blob: 4fa6c4f8e3be33821bd7363c9aead2f03d8847e4 [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
William Lallemandbc6ca7c2019-10-29 23:48:19 +0100358/* Uncommitted CKCH transaction */
359
360static struct {
361 struct ckch_store *new_ckchs;
362 struct ckch_store *old_ckchs;
363 char *path;
364} ckchs_transaction;
365
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +0100366/* This memory pool is used for capturing clienthello parameters. */
Thierry FOURNIER5bf77322017-02-25 12:45:22 +0100367struct ssl_capture {
Thierry FOURNIER5bf77322017-02-25 12:45:22 +0100368 unsigned long long int xxh64;
369 unsigned char ciphersuite_len;
370 char ciphersuite[0];
371};
Willy Tarreaubafbe012017-11-24 17:34:44 +0100372struct pool_head *pool_head_ssl_capture = NULL;
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +0100373static int ssl_capture_ptr_index = -1;
Thierry FOURNIER28962c92018-06-17 21:37:05 +0200374static int ssl_app_data_index = -1;
Willy Tarreauef934602016-12-22 23:12:01 +0100375
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200376#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
377struct list tlskeys_reference = LIST_HEAD_INIT(tlskeys_reference);
378#endif
379
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +0200380#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +0000381static unsigned int openssl_engines_initialized;
382struct list openssl_engines = LIST_HEAD_INIT(openssl_engines);
383struct ssl_engine_list {
384 struct list list;
385 ENGINE *e;
386};
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +0200387#endif
Grant Zhang872f9c22017-01-21 01:10:18 +0000388
Remi Gacogne8de54152014-07-15 11:36:40 +0200389#ifndef OPENSSL_NO_DH
Remi Gacogne4f902b82015-05-28 16:23:00 +0200390static int ssl_dh_ptr_index = -1;
Remi Gacogne47783ef2015-05-29 15:53:22 +0200391static DH *global_dh = NULL;
Remi Gacogne8de54152014-07-15 11:36:40 +0200392static DH *local_dh_1024 = NULL;
393static DH *local_dh_2048 = NULL;
394static DH *local_dh_4096 = NULL;
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +0100395static DH *ssl_get_tmp_dh(SSL *ssl, int export, int keylen);
Remi Gacogne8de54152014-07-15 11:36:40 +0200396#endif /* OPENSSL_NO_DH */
397
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100398#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Christopher Faulet31af49d2015-06-09 17:29:50 +0200399/* X509V3 Extensions that will be added on generated certificates */
400#define X509V3_EXT_SIZE 5
401static char *x509v3_ext_names[X509V3_EXT_SIZE] = {
402 "basicConstraints",
403 "nsComment",
404 "subjectKeyIdentifier",
405 "authorityKeyIdentifier",
406 "keyUsage",
407};
408static char *x509v3_ext_values[X509V3_EXT_SIZE] = {
409 "CA:FALSE",
410 "\"OpenSSL Generated Certificate\"",
411 "hash",
412 "keyid,issuer:always",
413 "nonRepudiation,digitalSignature,keyEncipherment"
414};
Christopher Faulet31af49d2015-06-09 17:29:50 +0200415/* LRU cache to store generated certificate */
416static struct lru64_head *ssl_ctx_lru_tree = NULL;
417static unsigned int ssl_ctx_lru_seed = 0;
Emeric Brun821bb9b2017-06-15 16:37:39 +0200418static unsigned int ssl_ctx_serial;
Willy Tarreau86abe442018-11-25 20:12:18 +0100419__decl_rwlock(ssl_ctx_lru_rwlock);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200420
Willy Tarreauc8ad3be2015-06-17 15:48:26 +0200421#endif // SSL_CTRL_SET_TLSEXT_HOSTNAME
422
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100423static struct ssl_bind_kw ssl_bind_kws[];
424
Willy Tarreau9a1ab082019-05-09 13:26:41 +0200425#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
yanbzhube2774d2015-12-10 15:07:30 -0500426/* The order here matters for picking a default context,
427 * keep the most common keytype at the bottom of the list
428 */
429const char *SSL_SOCK_KEYTYPE_NAMES[] = {
430 "dsa",
431 "ecdsa",
432 "rsa"
433};
434#define SSL_SOCK_NUM_KEYTYPES 3
Willy Tarreau30da7ad2015-12-14 11:28:33 +0100435#else
436#define SSL_SOCK_NUM_KEYTYPES 1
yanbzhube2774d2015-12-10 15:07:30 -0500437#endif
438
William Lallemandc3cd35f2017-11-28 11:04:43 +0100439static struct shared_context *ssl_shctx = NULL; /* ssl shared session cache */
William Lallemand4f45bb92017-10-30 20:08:51 +0100440static struct eb_root *sh_ssl_sess_tree; /* ssl shared session tree */
441
442#define sh_ssl_sess_tree_delete(s) ebmb_delete(&(s)->key);
443
444#define sh_ssl_sess_tree_insert(s) (struct sh_ssl_sess_hdr *)ebmb_insert(sh_ssl_sess_tree, \
445 &(s)->key, SSL_MAX_SSL_SESSION_ID_LENGTH);
446
447#define sh_ssl_sess_tree_lookup(k) (struct sh_ssl_sess_hdr *)ebmb_lookup(sh_ssl_sess_tree, \
448 (k), SSL_MAX_SSL_SESSION_ID_LENGTH);
William Lallemand3f85c9a2017-10-09 16:30:50 +0200449
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100450/*
451 * This function gives the detail of the SSL error. It is used only
452 * if the debug mode and the verbose mode are activated. It dump all
453 * the SSL error until the stack was empty.
454 */
455static forceinline void ssl_sock_dump_errors(struct connection *conn)
456{
457 unsigned long ret;
458
459 if (unlikely(global.mode & MODE_DEBUG)) {
460 while(1) {
461 ret = ERR_get_error();
462 if (ret == 0)
463 return;
464 fprintf(stderr, "fd[%04x] OpenSSL error[0x%lx] %s: %s\n",
Willy Tarreau585744b2017-08-24 14:31:19 +0200465 (unsigned short)conn->handle.fd, ret,
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100466 ERR_func_error_string(ret), ERR_reason_error_string(ret));
467 }
468 }
469}
470
yanbzhube2774d2015-12-10 15:07:30 -0500471
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +0200472#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +0000473static int ssl_init_single_engine(const char *engine_id, const char *def_algorithms)
474{
475 int err_code = ERR_ABORT;
476 ENGINE *engine;
477 struct ssl_engine_list *el;
478
479 /* grab the structural reference to the engine */
480 engine = ENGINE_by_id(engine_id);
481 if (engine == NULL) {
Christopher Faulet767a84b2017-11-24 16:50:31 +0100482 ha_alert("ssl-engine %s: failed to get structural reference\n", engine_id);
Grant Zhang872f9c22017-01-21 01:10:18 +0000483 goto fail_get;
484 }
485
486 if (!ENGINE_init(engine)) {
487 /* the engine couldn't initialise, release it */
Christopher Faulet767a84b2017-11-24 16:50:31 +0100488 ha_alert("ssl-engine %s: failed to initialize\n", engine_id);
Grant Zhang872f9c22017-01-21 01:10:18 +0000489 goto fail_init;
490 }
491
492 if (ENGINE_set_default_string(engine, def_algorithms) == 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +0100493 ha_alert("ssl-engine %s: failed on ENGINE_set_default_string\n", engine_id);
Grant Zhang872f9c22017-01-21 01:10:18 +0000494 goto fail_set_method;
495 }
496
497 el = calloc(1, sizeof(*el));
498 el->e = engine;
499 LIST_ADD(&openssl_engines, &el->list);
Emeric Brunece0c332017-12-06 13:51:49 +0100500 nb_engines++;
501 if (global_ssl.async)
502 global.ssl_used_async_engines = nb_engines;
Grant Zhang872f9c22017-01-21 01:10:18 +0000503 return 0;
504
505fail_set_method:
506 /* release the functional reference from ENGINE_init() */
507 ENGINE_finish(engine);
508
509fail_init:
510 /* release the structural reference from ENGINE_by_id() */
511 ENGINE_free(engine);
512
513fail_get:
514 return err_code;
515}
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +0200516#endif
Grant Zhang872f9c22017-01-21 01:10:18 +0000517
Willy Tarreau5db847a2019-05-09 14:13:35 +0200518#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brun3854e012017-05-17 20:42:48 +0200519/*
520 * openssl async fd handler
521 */
Emeric Brund0e095c2019-04-19 17:15:28 +0200522void ssl_async_fd_handler(int fd)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000523{
Olivier Houchardea8dd942019-05-20 14:02:16 +0200524 struct ssl_sock_ctx *ctx = fdtab[fd].owner;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000525
Emeric Brun3854e012017-05-17 20:42:48 +0200526 /* fd is an async enfine fd, we must stop
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000527 * to poll this fd until it is requested
528 */
Emeric Brunbbc16542017-06-02 15:54:06 +0000529 fd_stop_recv(fd);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000530 fd_cant_recv(fd);
531
532 /* crypto engine is available, let's notify the associated
533 * connection that it can pursue its processing.
534 */
Olivier Houchard03abf2d2019-05-28 10:12:02 +0200535 ssl_sock_io_cb(NULL, ctx, 0);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000536}
537
Emeric Brun3854e012017-05-17 20:42:48 +0200538/*
539 * openssl async delayed SSL_free handler
540 */
Emeric Brund0e095c2019-04-19 17:15:28 +0200541void ssl_async_fd_free(int fd)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000542{
543 SSL *ssl = fdtab[fd].owner;
Emeric Brun3854e012017-05-17 20:42:48 +0200544 OSSL_ASYNC_FD all_fd[32];
545 size_t num_all_fds = 0;
546 int i;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000547
Emeric Brun3854e012017-05-17 20:42:48 +0200548 /* We suppose that the async job for a same SSL *
549 * are serialized. So if we are awake it is
550 * because the running job has just finished
551 * and we can remove all async fds safely
552 */
553 SSL_get_all_async_fds(ssl, NULL, &num_all_fds);
554 if (num_all_fds > 32) {
555 send_log(NULL, LOG_EMERG, "haproxy: openssl returns too many async fds. It seems a bug. Process may crash\n");
556 return;
557 }
558
559 SSL_get_all_async_fds(ssl, all_fd, &num_all_fds);
560 for (i=0 ; i < num_all_fds ; i++)
561 fd_remove(all_fd[i]);
562
563 /* Now we can safely call SSL_free, no more pending job in engines */
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000564 SSL_free(ssl);
Olivier Houchard2be5a4c2019-03-08 18:54:43 +0100565 _HA_ATOMIC_SUB(&sslconns, 1);
566 _HA_ATOMIC_SUB(&jobs, 1);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000567}
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000568/*
Emeric Brun3854e012017-05-17 20:42:48 +0200569 * function used to manage a returned SSL_ERROR_WANT_ASYNC
570 * and enable/disable polling for async fds
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000571 */
Olivier Houchardea8dd942019-05-20 14:02:16 +0200572static inline void ssl_async_process_fds(struct ssl_sock_ctx *ctx)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000573{
Willy Tarreaua9786b62018-01-25 07:22:13 +0100574 OSSL_ASYNC_FD add_fd[32];
Emeric Brun3854e012017-05-17 20:42:48 +0200575 OSSL_ASYNC_FD del_fd[32];
Olivier Houchardea8dd942019-05-20 14:02:16 +0200576 SSL *ssl = ctx->ssl;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000577 size_t num_add_fds = 0;
578 size_t num_del_fds = 0;
Emeric Brun3854e012017-05-17 20:42:48 +0200579 int i;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000580
581 SSL_get_changed_async_fds(ssl, NULL, &num_add_fds, NULL,
582 &num_del_fds);
Emeric Brun3854e012017-05-17 20:42:48 +0200583 if (num_add_fds > 32 || num_del_fds > 32) {
584 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 +0000585 return;
586 }
587
Emeric Brun3854e012017-05-17 20:42:48 +0200588 SSL_get_changed_async_fds(ssl, add_fd, &num_add_fds, del_fd, &num_del_fds);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000589
Emeric Brun3854e012017-05-17 20:42:48 +0200590 /* We remove unused fds from the fdtab */
591 for (i=0 ; i < num_del_fds ; i++)
592 fd_remove(del_fd[i]);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000593
Emeric Brun3854e012017-05-17 20:42:48 +0200594 /* We add new fds to the fdtab */
595 for (i=0 ; i < num_add_fds ; i++) {
Olivier Houchardea8dd942019-05-20 14:02:16 +0200596 fd_insert(add_fd[i], ctx, ssl_async_fd_handler, tid_bit);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000597 }
598
Emeric Brun3854e012017-05-17 20:42:48 +0200599 num_add_fds = 0;
600 SSL_get_all_async_fds(ssl, NULL, &num_add_fds);
601 if (num_add_fds > 32) {
602 send_log(NULL, LOG_EMERG, "haproxy: openssl returns too many async fds. It seems a bug. Process may crash\n");
603 return;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000604 }
Emeric Brun3854e012017-05-17 20:42:48 +0200605
606 /* We activate the polling for all known async fds */
607 SSL_get_all_async_fds(ssl, add_fd, &num_add_fds);
Emeric Brunce9e01c2017-05-31 10:02:53 +0000608 for (i=0 ; i < num_add_fds ; i++) {
Emeric Brun3854e012017-05-17 20:42:48 +0200609 fd_want_recv(add_fd[i]);
Emeric Brunce9e01c2017-05-31 10:02:53 +0000610 /* To ensure that the fd cache won't be used
611 * We'll prefer to catch a real RD event
612 * because handling an EAGAIN on this fd will
613 * result in a context switch and also
614 * some engines uses a fd in blocking mode.
615 */
616 fd_cant_recv(add_fd[i]);
617 }
Emeric Brun3854e012017-05-17 20:42:48 +0200618
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000619}
620#endif
621
William Lallemand104a7a62019-10-14 14:14:59 +0200622#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
Emeric Brun4f3c87a2014-06-20 15:46:13 +0200623/*
624 * This function returns the number of seconds elapsed
625 * since the Epoch, 1970-01-01 00:00:00 +0000 (UTC) and the
626 * date presented un ASN1_GENERALIZEDTIME.
627 *
628 * In parsing error case, it returns -1.
629 */
630static long asn1_generalizedtime_to_epoch(ASN1_GENERALIZEDTIME *d)
631{
632 long epoch;
633 char *p, *end;
634 const unsigned short month_offset[12] = {
635 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
636 };
637 int year, month;
638
639 if (!d || (d->type != V_ASN1_GENERALIZEDTIME)) return -1;
640
641 p = (char *)d->data;
642 end = p + d->length;
643
644 if (end - p < 4) return -1;
645 year = 1000 * (p[0] - '0') + 100 * (p[1] - '0') + 10 * (p[2] - '0') + p[3] - '0';
646 p += 4;
647 if (end - p < 2) return -1;
648 month = 10 * (p[0] - '0') + p[1] - '0';
649 if (month < 1 || month > 12) return -1;
650 /* Compute the number of seconds since 1 jan 1970 and the beginning of current month
651 We consider leap years and the current month (<marsh or not) */
652 epoch = ( ((year - 1970) * 365)
653 + ((year - (month < 3)) / 4 - (year - (month < 3)) / 100 + (year - (month < 3)) / 400)
654 - ((1970 - 1) / 4 - (1970 - 1) / 100 + (1970 - 1) / 400)
655 + month_offset[month-1]
656 ) * 24 * 60 * 60;
657 p += 2;
658 if (end - p < 2) return -1;
659 /* Add the number of seconds of completed days of current month */
660 epoch += (10 * (p[0] - '0') + p[1] - '0' - 1) * 24 * 60 * 60;
661 p += 2;
662 if (end - p < 2) return -1;
663 /* Add the completed hours of the current day */
664 epoch += (10 * (p[0] - '0') + p[1] - '0') * 60 * 60;
665 p += 2;
666 if (end - p < 2) return -1;
667 /* Add the completed minutes of the current hour */
668 epoch += (10 * (p[0] - '0') + p[1] - '0') * 60;
669 p += 2;
670 if (p == end) return -1;
671 /* Test if there is available seconds */
672 if (p[0] < '0' || p[0] > '9')
673 goto nosec;
674 if (end - p < 2) return -1;
675 /* Add the seconds of the current minute */
676 epoch += 10 * (p[0] - '0') + p[1] - '0';
677 p += 2;
678 if (p == end) return -1;
679 /* Ignore seconds float part if present */
680 if (p[0] == '.') {
681 do {
682 if (++p == end) return -1;
683 } while (p[0] >= '0' && p[0] <= '9');
684 }
685
686nosec:
687 if (p[0] == 'Z') {
688 if (end - p != 1) return -1;
689 return epoch;
690 }
691 else if (p[0] == '+') {
692 if (end - p != 5) return -1;
693 /* Apply timezone offset */
Frederik Deweerdt953917a2017-10-16 07:37:31 -0700694 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 +0200695 }
696 else if (p[0] == '-') {
697 if (end - p != 5) return -1;
698 /* Apply timezone offset */
Frederik Deweerdt953917a2017-10-16 07:37:31 -0700699 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 +0200700 }
701
702 return -1;
703}
704
William Lallemand104a7a62019-10-14 14:14:59 +0200705/*
706 * struct alignment works here such that the key.key is the same as key_data
707 * Do not change the placement of key_data
708 */
709struct certificate_ocsp {
710 struct ebmb_node key;
711 unsigned char key_data[OCSP_MAX_CERTID_ASN1_LENGTH];
712 struct buffer response;
713 long expire;
714};
715
716struct ocsp_cbk_arg {
717 int is_single;
718 int single_kt;
719 union {
720 struct certificate_ocsp *s_ocsp;
721 /*
722 * m_ocsp will have multiple entries dependent on key type
723 * Entry 0 - DSA
724 * Entry 1 - ECDSA
725 * Entry 2 - RSA
726 */
727 struct certificate_ocsp *m_ocsp[SSL_SOCK_NUM_KEYTYPES];
728 };
729};
730
Emeric Brun1d3865b2014-06-20 15:37:32 +0200731static struct eb_root cert_ocsp_tree = EB_ROOT_UNIQUE;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200732
733/* This function starts to check if the OCSP response (in DER format) contained
734 * in chunk 'ocsp_response' is valid (else exits on error).
735 * If 'cid' is not NULL, it will be compared to the OCSP certificate ID
736 * contained in the OCSP Response and exits on error if no match.
737 * If it's a valid OCSP Response:
738 * If 'ocsp' is not NULL, the chunk is copied in the OCSP response's container
739 * pointed by 'ocsp'.
740 * If 'ocsp' is NULL, the function looks up into the OCSP response's
741 * containers tree (using as index the ASN1 form of the OCSP Certificate ID extracted
742 * from the response) and exits on error if not found. Finally, If an OCSP response is
743 * already present in the container, it will be overwritten.
744 *
745 * Note: OCSP response containing more than one OCSP Single response is not
746 * considered valid.
747 *
748 * Returns 0 on success, 1 in error case.
749 */
Willy Tarreau83061a82018-07-13 11:56:34 +0200750static int ssl_sock_load_ocsp_response(struct buffer *ocsp_response,
751 struct certificate_ocsp *ocsp,
752 OCSP_CERTID *cid, char **err)
Emeric Brun4147b2e2014-06-16 18:36:30 +0200753{
754 OCSP_RESPONSE *resp;
755 OCSP_BASICRESP *bs = NULL;
756 OCSP_SINGLERESP *sr;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200757 OCSP_CERTID *id;
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200758 unsigned char *p = (unsigned char *) ocsp_response->area;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200759 int rc , count_sr;
Emeric Brun13a6b482014-06-20 15:44:34 +0200760 ASN1_GENERALIZEDTIME *revtime, *thisupd, *nextupd = NULL;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200761 int reason;
762 int ret = 1;
763
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200764 resp = d2i_OCSP_RESPONSE(NULL, (const unsigned char **)&p,
765 ocsp_response->data);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200766 if (!resp) {
767 memprintf(err, "Unable to parse OCSP response");
768 goto out;
769 }
770
771 rc = OCSP_response_status(resp);
772 if (rc != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
773 memprintf(err, "OCSP response status not successful");
774 goto out;
775 }
776
777 bs = OCSP_response_get1_basic(resp);
778 if (!bs) {
779 memprintf(err, "Failed to get basic response from OCSP Response");
780 goto out;
781 }
782
783 count_sr = OCSP_resp_count(bs);
784 if (count_sr > 1) {
785 memprintf(err, "OCSP response ignored because contains multiple single responses (%d)", count_sr);
786 goto out;
787 }
788
789 sr = OCSP_resp_get0(bs, 0);
790 if (!sr) {
791 memprintf(err, "Failed to get OCSP single response");
792 goto out;
793 }
794
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200795 id = (OCSP_CERTID*)OCSP_SINGLERESP_get0_id(sr);
796
Emeric Brun4147b2e2014-06-16 18:36:30 +0200797 rc = OCSP_single_get0_status(sr, &reason, &revtime, &thisupd, &nextupd);
Emmanuel Hocdetef607052017-10-24 14:57:16 +0200798 if (rc != V_OCSP_CERTSTATUS_GOOD && rc != V_OCSP_CERTSTATUS_REVOKED) {
Emmanuel Hocdet872085c2017-10-10 15:18:52 +0200799 memprintf(err, "OCSP single response: certificate status is unknown");
Emeric Brun4147b2e2014-06-16 18:36:30 +0200800 goto out;
801 }
802
Emeric Brun13a6b482014-06-20 15:44:34 +0200803 if (!nextupd) {
804 memprintf(err, "OCSP single response: missing nextupdate");
805 goto out;
806 }
807
Emeric Brunc8b27b62014-06-19 14:16:17 +0200808 rc = OCSP_check_validity(thisupd, nextupd, OCSP_MAX_RESPONSE_TIME_SKEW, -1);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200809 if (!rc) {
810 memprintf(err, "OCSP single response: no longer valid.");
811 goto out;
812 }
813
814 if (cid) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200815 if (OCSP_id_cmp(id, cid)) {
Emeric Brun4147b2e2014-06-16 18:36:30 +0200816 memprintf(err, "OCSP single response: Certificate ID does not match certificate and issuer");
817 goto out;
818 }
819 }
820
821 if (!ocsp) {
822 unsigned char key[OCSP_MAX_CERTID_ASN1_LENGTH];
823 unsigned char *p;
824
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200825 rc = i2d_OCSP_CERTID(id, NULL);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200826 if (!rc) {
827 memprintf(err, "OCSP single response: Unable to encode Certificate ID");
828 goto out;
829 }
830
831 if (rc > OCSP_MAX_CERTID_ASN1_LENGTH) {
832 memprintf(err, "OCSP single response: Certificate ID too long");
833 goto out;
834 }
835
836 p = key;
837 memset(key, 0, OCSP_MAX_CERTID_ASN1_LENGTH);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200838 i2d_OCSP_CERTID(id, &p);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200839 ocsp = (struct certificate_ocsp *)ebmb_lookup(&cert_ocsp_tree, key, OCSP_MAX_CERTID_ASN1_LENGTH);
840 if (!ocsp) {
841 memprintf(err, "OCSP single response: Certificate ID does not match any certificate or issuer");
842 goto out;
843 }
844 }
845
846 /* According to comments on "chunk_dup", the
847 previous chunk buffer will be freed */
848 if (!chunk_dup(&ocsp->response, ocsp_response)) {
849 memprintf(err, "OCSP response: Memory allocation error");
850 goto out;
851 }
852
Emeric Brun4f3c87a2014-06-20 15:46:13 +0200853 ocsp->expire = asn1_generalizedtime_to_epoch(nextupd) - OCSP_MAX_RESPONSE_TIME_SKEW;
854
Emeric Brun4147b2e2014-06-16 18:36:30 +0200855 ret = 0;
856out:
Janusz Dziemidowicz8d710492017-03-08 16:59:41 +0100857 ERR_clear_error();
858
Emeric Brun4147b2e2014-06-16 18:36:30 +0200859 if (bs)
860 OCSP_BASICRESP_free(bs);
861
862 if (resp)
863 OCSP_RESPONSE_free(resp);
864
865 return ret;
866}
867/*
868 * External function use to update the OCSP response in the OCSP response's
869 * containers tree. The chunk 'ocsp_response' must contain the OCSP response
870 * to update in DER format.
871 *
872 * Returns 0 on success, 1 in error case.
873 */
Willy Tarreau83061a82018-07-13 11:56:34 +0200874int ssl_sock_update_ocsp_response(struct buffer *ocsp_response, char **err)
Emeric Brun4147b2e2014-06-16 18:36:30 +0200875{
876 return ssl_sock_load_ocsp_response(ocsp_response, NULL, NULL, err);
877}
878
William Lallemand4a660132019-10-14 14:51:41 +0200879#endif
880
881#if ((defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP) || defined OPENSSL_IS_BORINGSSL)
Emeric Brun4147b2e2014-06-16 18:36:30 +0200882/*
883 * This function load the OCSP Resonse in DER format contained in file at
William Lallemand3b5f3602019-10-16 18:05:05 +0200884 * path 'ocsp_path' or base64 in a buffer <buf>
Emeric Brun4147b2e2014-06-16 18:36:30 +0200885 *
886 * Returns 0 on success, 1 in error case.
887 */
William Lallemand3b5f3602019-10-16 18:05:05 +0200888static int ssl_sock_load_ocsp_response_from_file(const char *ocsp_path, char *buf, struct cert_key_and_chain *ckch, char **err)
Emeric Brun4147b2e2014-06-16 18:36:30 +0200889{
890 int fd = -1;
891 int r = 0;
892 int ret = 1;
William Lallemand3b5f3602019-10-16 18:05:05 +0200893 struct buffer *ocsp_response;
894 struct buffer *src = NULL;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200895
William Lallemand3b5f3602019-10-16 18:05:05 +0200896 if (buf) {
897 int i, j;
898 /* if it's from a buffer it will be base64 */
Emeric Brun4147b2e2014-06-16 18:36:30 +0200899
William Lallemand3b5f3602019-10-16 18:05:05 +0200900 /* remove \r and \n from the payload */
901 for (i = 0, j = 0; buf[i]; i++) {
902 if (buf[i] == '\r' || buf[i] == '\n')
Emeric Brun4147b2e2014-06-16 18:36:30 +0200903 continue;
William Lallemand3b5f3602019-10-16 18:05:05 +0200904 buf[j++] = buf[i];
905 }
906 buf[j] = 0;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200907
William Lallemand3b5f3602019-10-16 18:05:05 +0200908 ret = base64dec(buf, j, trash.area, trash.size);
909 if (ret < 0) {
910 memprintf(err, "Error reading OCSP response in base64 format");
Emeric Brun4147b2e2014-06-16 18:36:30 +0200911 goto end;
912 }
William Lallemand3b5f3602019-10-16 18:05:05 +0200913 trash.data = ret;
914 src = &trash;
915 } else {
916 fd = open(ocsp_path, O_RDONLY);
917 if (fd == -1) {
918 memprintf(err, "Error opening OCSP response file");
919 goto end;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200920 }
William Lallemand3b5f3602019-10-16 18:05:05 +0200921
922 trash.data = 0;
923 while (trash.data < trash.size) {
924 r = read(fd, trash.area + trash.data, trash.size - trash.data);
925 if (r < 0) {
926 if (errno == EINTR)
927 continue;
928
929 memprintf(err, "Error reading OCSP response from file");
930 goto end;
931 }
932 else if (r == 0) {
933 break;
934 }
935 trash.data += r;
936 }
937 close(fd);
938 fd = -1;
939 src = &trash;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200940 }
941
William Lallemand3b5f3602019-10-16 18:05:05 +0200942 ocsp_response = calloc(1, sizeof(*ocsp_response));
943 if (!chunk_dup(ocsp_response, src)) {
944 free(ocsp_response);
945 ocsp_response = NULL;
William Lallemand246c0242019-10-11 08:59:13 +0200946 goto end;
947 }
948
William Lallemand3b5f3602019-10-16 18:05:05 +0200949 ckch->ocsp_response = ocsp_response;
William Lallemande0f48ae2019-10-15 13:44:57 +0200950 ret = 0;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200951end:
952 if (fd != -1)
953 close(fd);
954
955 return ret;
956}
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100957#endif
Emeric Brun4147b2e2014-06-16 18:36:30 +0200958
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100959#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
960static 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)
961{
Christopher Faulet16f45c82018-02-16 11:23:49 +0100962 struct tls_keys_ref *ref;
Emeric Brun9e754772019-01-10 17:51:55 +0100963 union tls_sess_key *keys;
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100964 struct connection *conn;
965 int head;
966 int i;
Christopher Faulet16f45c82018-02-16 11:23:49 +0100967 int ret = -1; /* error by default */
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100968
Thierry FOURNIER28962c92018-06-17 21:37:05 +0200969 conn = SSL_get_ex_data(s, ssl_app_data_index);
Willy Tarreau07d94e42018-09-20 10:57:52 +0200970 ref = __objt_listener(conn->target)->bind_conf->keys_ref;
Christopher Faulet16f45c82018-02-16 11:23:49 +0100971 HA_RWLOCK_RDLOCK(TLSKEYS_REF_LOCK, &ref->lock);
972
973 keys = ref->tlskeys;
974 head = ref->tls_ticket_enc_index;
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100975
976 if (enc) {
977 memcpy(key_name, keys[head].name, 16);
978
979 if(!RAND_pseudo_bytes(iv, EVP_MAX_IV_LENGTH))
Christopher Faulet16f45c82018-02-16 11:23:49 +0100980 goto end;
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100981
Emeric Brun9e754772019-01-10 17:51:55 +0100982 if (ref->key_size_bits == 128) {
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100983
Emeric Brun9e754772019-01-10 17:51:55 +0100984 if(!EVP_EncryptInit_ex(ectx, EVP_aes_128_cbc(), NULL, keys[head].key_128.aes_key, iv))
985 goto end;
986
Willy Tarreau9356dac2019-05-10 09:22:53 +0200987 HMAC_Init_ex(hctx, keys[head].key_128.hmac_key, 16, TLS_TICKET_HASH_FUNCT(), NULL);
Emeric Brun9e754772019-01-10 17:51:55 +0100988 ret = 1;
989 }
990 else if (ref->key_size_bits == 256 ) {
991
992 if(!EVP_EncryptInit_ex(ectx, EVP_aes_256_cbc(), NULL, keys[head].key_256.aes_key, iv))
993 goto end;
994
Willy Tarreau9356dac2019-05-10 09:22:53 +0200995 HMAC_Init_ex(hctx, keys[head].key_256.hmac_key, 32, TLS_TICKET_HASH_FUNCT(), NULL);
Emeric Brun9e754772019-01-10 17:51:55 +0100996 ret = 1;
997 }
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100998 } else {
999 for (i = 0; i < TLS_TICKETS_NO; i++) {
1000 if (!memcmp(key_name, keys[(head + i) % TLS_TICKETS_NO].name, 16))
1001 goto found;
1002 }
Christopher Faulet16f45c82018-02-16 11:23:49 +01001003 ret = 0;
1004 goto end;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01001005
Christopher Faulet16f45c82018-02-16 11:23:49 +01001006 found:
Emeric Brun9e754772019-01-10 17:51:55 +01001007 if (ref->key_size_bits == 128) {
Willy Tarreau9356dac2019-05-10 09:22:53 +02001008 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 +01001009 if(!EVP_DecryptInit_ex(ectx, EVP_aes_128_cbc(), NULL, keys[(head + i) % TLS_TICKETS_NO].key_128.aes_key, iv))
1010 goto end;
1011 /* 2 for key renewal, 1 if current key is still valid */
1012 ret = i ? 2 : 1;
1013 }
1014 else if (ref->key_size_bits == 256) {
Willy Tarreau9356dac2019-05-10 09:22:53 +02001015 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 +01001016 if(!EVP_DecryptInit_ex(ectx, EVP_aes_256_cbc(), NULL, keys[(head + i) % TLS_TICKETS_NO].key_256.aes_key, iv))
1017 goto end;
1018 /* 2 for key renewal, 1 if current key is still valid */
1019 ret = i ? 2 : 1;
1020 }
Nenad Merdanovic05552d42015-02-27 19:56:49 +01001021 }
Emeric Brun9e754772019-01-10 17:51:55 +01001022
Christopher Faulet16f45c82018-02-16 11:23:49 +01001023 end:
1024 HA_RWLOCK_RDUNLOCK(TLSKEYS_REF_LOCK, &ref->lock);
1025 return ret;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02001026}
1027
1028struct tls_keys_ref *tlskeys_ref_lookup(const char *filename)
1029{
1030 struct tls_keys_ref *ref;
1031
1032 list_for_each_entry(ref, &tlskeys_reference, list)
1033 if (ref->filename && strcmp(filename, ref->filename) == 0)
1034 return ref;
1035 return NULL;
1036}
1037
1038struct tls_keys_ref *tlskeys_ref_lookupid(int unique_id)
1039{
1040 struct tls_keys_ref *ref;
1041
1042 list_for_each_entry(ref, &tlskeys_reference, list)
1043 if (ref->unique_id == unique_id)
1044 return ref;
1045 return NULL;
1046}
1047
Emeric Brun9e754772019-01-10 17:51:55 +01001048/* Update the key into ref: if keysize doesnt
1049 * match existing ones, this function returns -1
1050 * else it returns 0 on success.
1051 */
1052int ssl_sock_update_tlskey_ref(struct tls_keys_ref *ref,
Willy Tarreau83061a82018-07-13 11:56:34 +02001053 struct buffer *tlskey)
Christopher Faulet16f45c82018-02-16 11:23:49 +01001054{
Emeric Brun9e754772019-01-10 17:51:55 +01001055 if (ref->key_size_bits == 128) {
1056 if (tlskey->data != sizeof(struct tls_sess_key_128))
1057 return -1;
1058 }
1059 else if (ref->key_size_bits == 256) {
1060 if (tlskey->data != sizeof(struct tls_sess_key_256))
1061 return -1;
1062 }
1063 else
1064 return -1;
1065
Christopher Faulet16f45c82018-02-16 11:23:49 +01001066 HA_RWLOCK_WRLOCK(TLSKEYS_REF_LOCK, &ref->lock);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001067 memcpy((char *) (ref->tlskeys + ((ref->tls_ticket_enc_index + 2) % TLS_TICKETS_NO)),
1068 tlskey->area, tlskey->data);
Christopher Faulet16f45c82018-02-16 11:23:49 +01001069 ref->tls_ticket_enc_index = (ref->tls_ticket_enc_index + 1) % TLS_TICKETS_NO;
1070 HA_RWLOCK_WRUNLOCK(TLSKEYS_REF_LOCK, &ref->lock);
Emeric Brun9e754772019-01-10 17:51:55 +01001071
1072 return 0;
Christopher Faulet16f45c82018-02-16 11:23:49 +01001073}
1074
Willy Tarreau83061a82018-07-13 11:56:34 +02001075int ssl_sock_update_tlskey(char *filename, struct buffer *tlskey, char **err)
Christopher Faulet16f45c82018-02-16 11:23:49 +01001076{
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02001077 struct tls_keys_ref *ref = tlskeys_ref_lookup(filename);
1078
1079 if(!ref) {
1080 memprintf(err, "Unable to locate the referenced filename: %s", filename);
1081 return 1;
1082 }
Emeric Brun9e754772019-01-10 17:51:55 +01001083 if (ssl_sock_update_tlskey_ref(ref, tlskey) < 0) {
1084 memprintf(err, "Invalid key size");
1085 return 1;
1086 }
1087
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02001088 return 0;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01001089}
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02001090
1091/* This function finalize the configuration parsing. Its set all the
Willy Tarreaud1c57502016-12-22 22:46:15 +01001092 * automatic ids. It's called just after the basic checks. It returns
1093 * 0 on success otherwise ERR_*.
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02001094 */
Willy Tarreaud1c57502016-12-22 22:46:15 +01001095static int tlskeys_finalize_config(void)
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02001096{
1097 int i = 0;
1098 struct tls_keys_ref *ref, *ref2, *ref3;
1099 struct list tkr = LIST_HEAD_INIT(tkr);
1100
1101 list_for_each_entry(ref, &tlskeys_reference, list) {
1102 if (ref->unique_id == -1) {
1103 /* Look for the first free id. */
1104 while (1) {
1105 list_for_each_entry(ref2, &tlskeys_reference, list) {
1106 if (ref2->unique_id == i) {
1107 i++;
1108 break;
1109 }
1110 }
1111 if (&ref2->list == &tlskeys_reference)
1112 break;
1113 }
1114
1115 /* Uses the unique id and increment it for the next entry. */
1116 ref->unique_id = i;
1117 i++;
1118 }
1119 }
1120
1121 /* This sort the reference list by id. */
1122 list_for_each_entry_safe(ref, ref2, &tlskeys_reference, list) {
1123 LIST_DEL(&ref->list);
1124 list_for_each_entry(ref3, &tkr, list) {
1125 if (ref->unique_id < ref3->unique_id) {
1126 LIST_ADDQ(&ref3->list, &ref->list);
1127 break;
1128 }
1129 }
1130 if (&ref3->list == &tkr)
1131 LIST_ADDQ(&tkr, &ref->list);
1132 }
1133
1134 /* swap root */
1135 LIST_ADD(&tkr, &tlskeys_reference);
1136 LIST_DEL(&tkr);
Willy Tarreaud1c57502016-12-22 22:46:15 +01001137 return 0;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02001138}
Nenad Merdanovic05552d42015-02-27 19:56:49 +01001139#endif /* SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB */
1140
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01001141#ifndef OPENSSL_NO_OCSP
yanbzhube2774d2015-12-10 15:07:30 -05001142int ssl_sock_get_ocsp_arg_kt_index(int evp_keytype)
1143{
1144 switch (evp_keytype) {
1145 case EVP_PKEY_RSA:
1146 return 2;
1147 case EVP_PKEY_DSA:
1148 return 0;
1149 case EVP_PKEY_EC:
1150 return 1;
1151 }
1152
1153 return -1;
1154}
1155
Emeric Brun4147b2e2014-06-16 18:36:30 +02001156/*
1157 * Callback used to set OCSP status extension content in server hello.
1158 */
1159int ssl_sock_ocsp_stapling_cbk(SSL *ssl, void *arg)
1160{
yanbzhube2774d2015-12-10 15:07:30 -05001161 struct certificate_ocsp *ocsp;
1162 struct ocsp_cbk_arg *ocsp_arg;
1163 char *ssl_buf;
1164 EVP_PKEY *ssl_pkey;
1165 int key_type;
1166 int index;
1167
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02001168 ocsp_arg = arg;
yanbzhube2774d2015-12-10 15:07:30 -05001169
1170 ssl_pkey = SSL_get_privatekey(ssl);
1171 if (!ssl_pkey)
1172 return SSL_TLSEXT_ERR_NOACK;
1173
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001174 key_type = EVP_PKEY_base_id(ssl_pkey);
yanbzhube2774d2015-12-10 15:07:30 -05001175
1176 if (ocsp_arg->is_single && ocsp_arg->single_kt == key_type)
1177 ocsp = ocsp_arg->s_ocsp;
1178 else {
1179 /* For multiple certs per context, we have to find the correct OCSP response based on
1180 * the certificate type
1181 */
1182 index = ssl_sock_get_ocsp_arg_kt_index(key_type);
1183
1184 if (index < 0)
1185 return SSL_TLSEXT_ERR_NOACK;
1186
1187 ocsp = ocsp_arg->m_ocsp[index];
1188
1189 }
Emeric Brun4147b2e2014-06-16 18:36:30 +02001190
1191 if (!ocsp ||
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001192 !ocsp->response.area ||
1193 !ocsp->response.data ||
Emeric Brun4f3c87a2014-06-20 15:46:13 +02001194 (ocsp->expire < now.tv_sec))
Emeric Brun4147b2e2014-06-16 18:36:30 +02001195 return SSL_TLSEXT_ERR_NOACK;
1196
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001197 ssl_buf = OPENSSL_malloc(ocsp->response.data);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001198 if (!ssl_buf)
1199 return SSL_TLSEXT_ERR_NOACK;
1200
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001201 memcpy(ssl_buf, ocsp->response.area, ocsp->response.data);
1202 SSL_set_tlsext_status_ocsp_resp(ssl, ssl_buf, ocsp->response.data);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001203
1204 return SSL_TLSEXT_ERR_OK;
1205}
1206
William Lallemand4a660132019-10-14 14:51:41 +02001207#endif
1208
1209#if ((defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP) || defined OPENSSL_IS_BORINGSSL)
Emeric Brun4147b2e2014-06-16 18:36:30 +02001210/*
1211 * This function enables the handling of OCSP status extension on 'ctx' if a
William Lallemand246c0242019-10-11 08:59:13 +02001212 * ocsp_response buffer was found in the cert_key_and_chain. To enable OCSP
1213 * status extension, the issuer's certificate is mandatory. It should be
1214 * present in ckch->ocsp_issuer.
Emeric Brun4147b2e2014-06-16 18:36:30 +02001215 *
William Lallemand246c0242019-10-11 08:59:13 +02001216 * In addition, the ckch->ocsp_reponse buffer is loaded as a DER format of an
1217 * OCSP response. If file is empty or content is not a valid OCSP response,
1218 * OCSP status extension is enabled but OCSP response is ignored (a warning is
1219 * displayed).
Emeric Brun4147b2e2014-06-16 18:36:30 +02001220 *
1221 * Returns 1 if no ".ocsp" file found, 0 if OCSP status extension is
Joseph Herlant017b3da2018-11-15 09:07:59 -08001222 * successfully enabled, or -1 in other error case.
Emeric Brun4147b2e2014-06-16 18:36:30 +02001223 */
William Lallemand4a660132019-10-14 14:51:41 +02001224#ifndef OPENSSL_IS_BORINGSSL
William Lallemand246c0242019-10-11 08:59:13 +02001225static int ssl_sock_load_ocsp(SSL_CTX *ctx, const struct cert_key_and_chain *ckch)
Emeric Brun4147b2e2014-06-16 18:36:30 +02001226{
William Lallemand246c0242019-10-11 08:59:13 +02001227 X509 *x = NULL, *issuer = NULL;
Emeric Brun4147b2e2014-06-16 18:36:30 +02001228 OCSP_CERTID *cid = NULL;
Emeric Brun4147b2e2014-06-16 18:36:30 +02001229 int i, ret = -1;
Emeric Brun4147b2e2014-06-16 18:36:30 +02001230 struct certificate_ocsp *ocsp = NULL, *iocsp;
1231 char *warn = NULL;
1232 unsigned char *p;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001233 void (*callback) (void);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001234
Emeric Brun4147b2e2014-06-16 18:36:30 +02001235
William Lallemand246c0242019-10-11 08:59:13 +02001236 x = ckch->cert;
Emeric Brun4147b2e2014-06-16 18:36:30 +02001237 if (!x)
1238 goto out;
1239
William Lallemand246c0242019-10-11 08:59:13 +02001240 issuer = ckch->ocsp_issuer;
1241 if (!issuer)
1242 goto out;
Emeric Brun4147b2e2014-06-16 18:36:30 +02001243
1244 cid = OCSP_cert_to_id(0, x, issuer);
1245 if (!cid)
1246 goto out;
1247
1248 i = i2d_OCSP_CERTID(cid, NULL);
1249 if (!i || (i > OCSP_MAX_CERTID_ASN1_LENGTH))
1250 goto out;
1251
Vincent Bernat02779b62016-04-03 13:48:43 +02001252 ocsp = calloc(1, sizeof(*ocsp));
Emeric Brun4147b2e2014-06-16 18:36:30 +02001253 if (!ocsp)
1254 goto out;
1255
1256 p = ocsp->key_data;
1257 i2d_OCSP_CERTID(cid, &p);
1258
1259 iocsp = (struct certificate_ocsp *)ebmb_insert(&cert_ocsp_tree, &ocsp->key, OCSP_MAX_CERTID_ASN1_LENGTH);
1260 if (iocsp == ocsp)
1261 ocsp = NULL;
1262
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001263#ifndef SSL_CTX_get_tlsext_status_cb
1264# define SSL_CTX_get_tlsext_status_cb(ctx, cb) \
1265 *cb = (void (*) (void))ctx->tlsext_status_cb;
1266#endif
1267 SSL_CTX_get_tlsext_status_cb(ctx, &callback);
1268
1269 if (!callback) {
Vincent Bernat02779b62016-04-03 13:48:43 +02001270 struct ocsp_cbk_arg *cb_arg = calloc(1, sizeof(*cb_arg));
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001271 EVP_PKEY *pkey;
yanbzhube2774d2015-12-10 15:07:30 -05001272
1273 cb_arg->is_single = 1;
1274 cb_arg->s_ocsp = iocsp;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001275
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001276 pkey = X509_get_pubkey(x);
1277 cb_arg->single_kt = EVP_PKEY_base_id(pkey);
1278 EVP_PKEY_free(pkey);
yanbzhube2774d2015-12-10 15:07:30 -05001279
1280 SSL_CTX_set_tlsext_status_cb(ctx, ssl_sock_ocsp_stapling_cbk);
1281 SSL_CTX_set_tlsext_status_arg(ctx, cb_arg);
1282 } else {
1283 /*
1284 * If the ctx has a status CB, then we have previously set an OCSP staple for this ctx
1285 * Update that cb_arg with the new cert's staple
1286 */
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001287 struct ocsp_cbk_arg *cb_arg;
yanbzhube2774d2015-12-10 15:07:30 -05001288 struct certificate_ocsp *tmp_ocsp;
1289 int index;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001290 int key_type;
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001291 EVP_PKEY *pkey;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001292
1293#ifdef SSL_CTX_get_tlsext_status_arg
1294 SSL_CTX_ctrl(ctx, SSL_CTRL_GET_TLSEXT_STATUS_REQ_CB_ARG, 0, &cb_arg);
1295#else
1296 cb_arg = ctx->tlsext_status_arg;
1297#endif
yanbzhube2774d2015-12-10 15:07:30 -05001298
1299 /*
1300 * The following few lines will convert cb_arg from a single ocsp to multi ocsp
1301 * the order of operations below matter, take care when changing it
1302 */
1303 tmp_ocsp = cb_arg->s_ocsp;
1304 index = ssl_sock_get_ocsp_arg_kt_index(cb_arg->single_kt);
1305 cb_arg->s_ocsp = NULL;
1306 cb_arg->m_ocsp[index] = tmp_ocsp;
1307 cb_arg->is_single = 0;
1308 cb_arg->single_kt = 0;
1309
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001310 pkey = X509_get_pubkey(x);
1311 key_type = EVP_PKEY_base_id(pkey);
1312 EVP_PKEY_free(pkey);
1313
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001314 index = ssl_sock_get_ocsp_arg_kt_index(key_type);
yanbzhube2774d2015-12-10 15:07:30 -05001315 if (index >= 0 && !cb_arg->m_ocsp[index])
1316 cb_arg->m_ocsp[index] = iocsp;
1317
1318 }
Emeric Brun4147b2e2014-06-16 18:36:30 +02001319
1320 ret = 0;
1321
1322 warn = NULL;
William Lallemand246c0242019-10-11 08:59:13 +02001323 if (ssl_sock_load_ocsp_response(ckch->ocsp_response, ocsp, cid, &warn)) {
William Lallemand3b5f3602019-10-16 18:05:05 +02001324 memprintf(&warn, "Loading: %s. Content will be ignored", warn ? warn : "failure");
Christopher Faulet767a84b2017-11-24 16:50:31 +01001325 ha_warning("%s.\n", warn);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001326 }
1327
1328out:
Emeric Brun4147b2e2014-06-16 18:36:30 +02001329 if (cid)
1330 OCSP_CERTID_free(cid);
1331
1332 if (ocsp)
1333 free(ocsp);
1334
1335 if (warn)
1336 free(warn);
1337
Emeric Brun4147b2e2014-06-16 18:36:30 +02001338 return ret;
1339}
William Lallemand4a660132019-10-14 14:51:41 +02001340#else /* OPENSSL_IS_BORINGSSL */
1341static int ssl_sock_load_ocsp(SSL_CTX *ctx, const struct cert_key_and_chain *ckch)
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02001342{
William Lallemand4a660132019-10-14 14:51:41 +02001343 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 +02001344}
1345#endif
1346
William Lallemand4a660132019-10-14 14:51:41 +02001347#endif
1348
1349
Willy Tarreau5db847a2019-05-09 14:13:35 +02001350#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001351
1352#define CT_EXTENSION_TYPE 18
1353
1354static int sctl_ex_index = -1;
1355
1356/*
1357 * Try to parse Signed Certificate Timestamp List structure. This function
1358 * makes only basic test if the data seems like SCTL. No signature validation
1359 * is performed.
1360 */
Willy Tarreau83061a82018-07-13 11:56:34 +02001361static int ssl_sock_parse_sctl(struct buffer *sctl)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001362{
1363 int ret = 1;
1364 int len, pos, sct_len;
1365 unsigned char *data;
1366
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001367 if (sctl->data < 2)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001368 goto out;
1369
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001370 data = (unsigned char *) sctl->area;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001371 len = (data[0] << 8) | data[1];
1372
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001373 if (len + 2 != sctl->data)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001374 goto out;
1375
1376 data = data + 2;
1377 pos = 0;
1378 while (pos < len) {
1379 if (len - pos < 2)
1380 goto out;
1381
1382 sct_len = (data[pos] << 8) | data[pos + 1];
1383 if (pos + sct_len + 2 > len)
1384 goto out;
1385
1386 pos += sct_len + 2;
1387 }
1388
1389 ret = 0;
1390
1391out:
1392 return ret;
1393}
1394
William Lallemand0dfae6c2019-10-16 18:06:58 +02001395/* Try to load a sctl from a buffer <buf> if not NULL, or read the file <sctl_path>
1396 * It fills the ckch->sctl buffer
1397 * return 0 on success or != 0 on failure */
1398static int ssl_sock_load_sctl_from_file(const char *sctl_path, char *buf, struct cert_key_and_chain *ckch, char **err)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001399{
1400 int fd = -1;
1401 int r = 0;
1402 int ret = 1;
William Lallemand0dfae6c2019-10-16 18:06:58 +02001403 struct buffer tmp;
1404 struct buffer *src;
1405 struct buffer *sctl;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001406
William Lallemand0dfae6c2019-10-16 18:06:58 +02001407 if (buf) {
1408 tmp.area = buf;
1409 tmp.data = strlen(buf);
1410 tmp.size = tmp.data + 1;
1411 src = &tmp;
1412 } else {
1413 fd = open(sctl_path, O_RDONLY);
1414 if (fd == -1)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001415 goto end;
William Lallemand0dfae6c2019-10-16 18:06:58 +02001416
1417 trash.data = 0;
1418 while (trash.data < trash.size) {
1419 r = read(fd, trash.area + trash.data, trash.size - trash.data);
1420 if (r < 0) {
1421 if (errno == EINTR)
1422 continue;
1423 goto end;
1424 }
1425 else if (r == 0) {
1426 break;
1427 }
1428 trash.data += r;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001429 }
William Lallemand0dfae6c2019-10-16 18:06:58 +02001430 src = &trash;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001431 }
1432
William Lallemand0dfae6c2019-10-16 18:06:58 +02001433 ret = ssl_sock_parse_sctl(src);
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001434 if (ret)
1435 goto end;
1436
William Lallemand0dfae6c2019-10-16 18:06:58 +02001437 sctl = calloc(1, sizeof(*sctl));
1438 if (!chunk_dup(sctl, src)) {
1439 free(sctl);
1440 sctl = NULL;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001441 goto end;
1442 }
William Lallemand0dfae6c2019-10-16 18:06:58 +02001443 ret = 0;
1444 /* TODO: free the previous SCTL in the ckch */
1445 ckch->sctl = sctl;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001446
1447end:
1448 if (fd != -1)
1449 close(fd);
1450
1451 return ret;
1452}
1453
1454int ssl_sock_sctl_add_cbk(SSL *ssl, unsigned ext_type, const unsigned char **out, size_t *outlen, int *al, void *add_arg)
1455{
Willy Tarreau83061a82018-07-13 11:56:34 +02001456 struct buffer *sctl = add_arg;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001457
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001458 *out = (unsigned char *) sctl->area;
1459 *outlen = sctl->data;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001460
1461 return 1;
1462}
1463
1464int ssl_sock_sctl_parse_cbk(SSL *s, unsigned int ext_type, const unsigned char *in, size_t inlen, int *al, void *parse_arg)
1465{
1466 return 1;
1467}
1468
William Lallemanda17f4112019-10-10 15:16:44 +02001469static int ssl_sock_load_sctl(SSL_CTX *ctx, struct buffer *sctl)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001470{
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001471 int ret = -1;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001472
William Lallemanda17f4112019-10-10 15:16:44 +02001473 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 +01001474 goto out;
1475
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001476 SSL_CTX_set_ex_data(ctx, sctl_ex_index, sctl);
1477
1478 ret = 0;
1479
1480out:
1481 return ret;
1482}
1483
1484#endif
1485
Emeric Brune1f38db2012-09-03 20:36:47 +02001486void ssl_sock_infocbk(const SSL *ssl, int where, int ret)
1487{
Thierry FOURNIER28962c92018-06-17 21:37:05 +02001488 struct connection *conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001489 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
Emeric Brund8b2bb52014-01-28 15:43:53 +01001490 BIO *write_bio;
Willy Tarreau622317d2015-02-27 16:36:16 +01001491 (void)ret; /* shut gcc stupid warning */
Emeric Brune1f38db2012-09-03 20:36:47 +02001492
Dirkjan Bussink526894f2019-01-21 09:35:03 -08001493#ifndef SSL_OP_NO_RENEGOTIATION
1494 /* Please note that BoringSSL defines this macro to zero so don't
1495 * change this to #if and do not assign a default value to this macro!
1496 */
Emeric Brune1f38db2012-09-03 20:36:47 +02001497 if (where & SSL_CB_HANDSHAKE_START) {
1498 /* Disable renegotiation (CVE-2009-3555) */
Olivier Houchard90084a12017-11-23 18:21:29 +01001499 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 +02001500 conn->flags |= CO_FL_ERROR;
Willy Tarreau20879a02012-12-03 16:32:10 +01001501 conn->err_code = CO_ER_SSL_RENEG;
1502 }
Emeric Brune1f38db2012-09-03 20:36:47 +02001503 }
Dirkjan Bussink526894f2019-01-21 09:35:03 -08001504#endif
Emeric Brund8b2bb52014-01-28 15:43:53 +01001505
1506 if ((where & SSL_CB_ACCEPT_LOOP) == SSL_CB_ACCEPT_LOOP) {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001507 if (!(ctx->xprt_st & SSL_SOCK_ST_FL_16K_WBFSIZE)) {
Emeric Brund8b2bb52014-01-28 15:43:53 +01001508 /* Long certificate chains optimz
1509 If write and read bios are differents, we
1510 consider that the buffering was activated,
1511 so we rise the output buffer size from 4k
1512 to 16k */
1513 write_bio = SSL_get_wbio(ssl);
1514 if (write_bio != SSL_get_rbio(ssl)) {
1515 BIO_set_write_buffer_size(write_bio, 16384);
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001516 ctx->xprt_st |= SSL_SOCK_ST_FL_16K_WBFSIZE;
Emeric Brund8b2bb52014-01-28 15:43:53 +01001517 }
1518 }
1519 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02001520}
1521
Emeric Brune64aef12012-09-21 13:15:06 +02001522/* Callback is called for each certificate of the chain during a verify
1523 ok is set to 1 if preverify detect no error on current certificate.
1524 Returns 0 to break the handshake, 1 otherwise. */
Evan Broderbe554312013-06-27 00:05:25 -07001525int ssl_sock_bind_verifycbk(int ok, X509_STORE_CTX *x_store)
Emeric Brune64aef12012-09-21 13:15:06 +02001526{
1527 SSL *ssl;
1528 struct connection *conn;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001529 struct ssl_sock_ctx *ctx;
Emeric Brun81c00f02012-09-21 14:31:21 +02001530 int err, depth;
Emeric Brune64aef12012-09-21 13:15:06 +02001531
1532 ssl = X509_STORE_CTX_get_ex_data(x_store, SSL_get_ex_data_X509_STORE_CTX_idx());
Thierry FOURNIER28962c92018-06-17 21:37:05 +02001533 conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Emeric Brune64aef12012-09-21 13:15:06 +02001534
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001535 ctx = conn->xprt_ctx;
1536
1537 ctx->xprt_st |= SSL_SOCK_ST_FL_VERIFY_DONE;
Emeric Brune64aef12012-09-21 13:15:06 +02001538
Emeric Brun81c00f02012-09-21 14:31:21 +02001539 if (ok) /* no errors */
1540 return ok;
1541
1542 depth = X509_STORE_CTX_get_error_depth(x_store);
1543 err = X509_STORE_CTX_get_error(x_store);
1544
1545 /* check if CA error needs to be ignored */
1546 if (depth > 0) {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001547 if (!SSL_SOCK_ST_TO_CA_ERROR(ctx->xprt_st)) {
1548 ctx->xprt_st |= SSL_SOCK_CA_ERROR_TO_ST(err);
1549 ctx->xprt_st |= SSL_SOCK_CAEDEPTH_TO_ST(depth);
Emeric Brunf282a812012-09-21 15:27:54 +02001550 }
1551
Willy Tarreau07d94e42018-09-20 10:57:52 +02001552 if (__objt_listener(conn->target)->bind_conf->ca_ignerr & (1ULL << err)) {
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02001553 ssl_sock_dump_errors(conn);
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001554 ERR_clear_error();
Emeric Brun81c00f02012-09-21 14:31:21 +02001555 return 1;
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001556 }
Emeric Brun81c00f02012-09-21 14:31:21 +02001557
Willy Tarreau20879a02012-12-03 16:32:10 +01001558 conn->err_code = CO_ER_SSL_CA_FAIL;
Emeric Brun81c00f02012-09-21 14:31:21 +02001559 return 0;
1560 }
1561
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001562 if (!SSL_SOCK_ST_TO_CRTERROR(ctx->xprt_st))
1563 ctx->xprt_st |= SSL_SOCK_CRTERROR_TO_ST(err);
Emeric Brunf282a812012-09-21 15:27:54 +02001564
Emeric Brun81c00f02012-09-21 14:31:21 +02001565 /* check if certificate error needs to be ignored */
Willy Tarreau07d94e42018-09-20 10:57:52 +02001566 if (__objt_listener(conn->target)->bind_conf->crt_ignerr & (1ULL << err)) {
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02001567 ssl_sock_dump_errors(conn);
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001568 ERR_clear_error();
Emeric Brun81c00f02012-09-21 14:31:21 +02001569 return 1;
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001570 }
Emeric Brun81c00f02012-09-21 14:31:21 +02001571
Willy Tarreau20879a02012-12-03 16:32:10 +01001572 conn->err_code = CO_ER_SSL_CRT_FAIL;
Emeric Brun81c00f02012-09-21 14:31:21 +02001573 return 0;
Emeric Brune64aef12012-09-21 13:15:06 +02001574}
1575
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001576static inline
1577void ssl_sock_parse_clienthello(int write_p, int version, int content_type,
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001578 const void *buf, size_t len, SSL *ssl)
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001579{
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001580 struct ssl_capture *capture;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001581 unsigned char *msg;
1582 unsigned char *end;
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001583 size_t rec_len;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001584
1585 /* This function is called for "from client" and "to server"
1586 * connections. The combination of write_p == 0 and content_type == 22
Joseph Herlant017b3da2018-11-15 09:07:59 -08001587 * is only available during "from client" connection.
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001588 */
1589
1590 /* "write_p" is set to 0 is the bytes are received messages,
1591 * otherwise it is set to 1.
1592 */
1593 if (write_p != 0)
1594 return;
1595
1596 /* content_type contains the type of message received or sent
1597 * according with the SSL/TLS protocol spec. This message is
1598 * encoded with one byte. The value 256 (two bytes) is used
1599 * for designing the SSL/TLS record layer. According with the
1600 * rfc6101, the expected message (other than 256) are:
1601 * - change_cipher_spec(20)
1602 * - alert(21)
1603 * - handshake(22)
1604 * - application_data(23)
1605 * - (255)
1606 * We are interessed by the handshake and specially the client
1607 * hello.
1608 */
1609 if (content_type != 22)
1610 return;
1611
1612 /* The message length is at least 4 bytes, containing the
1613 * message type and the message length.
1614 */
1615 if (len < 4)
1616 return;
1617
1618 /* First byte of the handshake message id the type of
1619 * message. The konwn types are:
1620 * - hello_request(0)
1621 * - client_hello(1)
1622 * - server_hello(2)
1623 * - certificate(11)
1624 * - server_key_exchange (12)
1625 * - certificate_request(13)
1626 * - server_hello_done(14)
1627 * We are interested by the client hello.
1628 */
1629 msg = (unsigned char *)buf;
1630 if (msg[0] != 1)
1631 return;
1632
1633 /* Next three bytes are the length of the message. The total length
1634 * must be this decoded length + 4. If the length given as argument
1635 * is not the same, we abort the protocol dissector.
1636 */
1637 rec_len = (msg[1] << 16) + (msg[2] << 8) + msg[3];
1638 if (len < rec_len + 4)
1639 return;
1640 msg += 4;
1641 end = msg + rec_len;
1642 if (end < msg)
1643 return;
1644
1645 /* Expect 2 bytes for protocol version (1 byte for major and 1 byte
1646 * for minor, the random, composed by 4 bytes for the unix time and
Baptiste Assmann6be139f2018-11-28 15:20:25 +01001647 * 28 bytes for unix payload. So we jump 1 + 1 + 4 + 28.
1648 */
1649 msg += 1 + 1 + 4 + 28;
1650 if (msg > end)
1651 return;
1652
1653 /* Next, is session id:
1654 * if present, we have to jump by length + 1 for the size information
1655 * if not present, we have to jump by 1 only
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001656 */
Baptiste Assmann6be139f2018-11-28 15:20:25 +01001657 if (msg[0] > 0)
1658 msg += msg[0];
1659 msg += 1;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001660 if (msg > end)
1661 return;
1662
1663 /* Next two bytes are the ciphersuite length. */
1664 if (msg + 2 > end)
1665 return;
1666 rec_len = (msg[0] << 8) + msg[1];
1667 msg += 2;
1668 if (msg + rec_len > end || msg + rec_len < msg)
1669 return;
1670
Willy Tarreaubafbe012017-11-24 17:34:44 +01001671 capture = pool_alloc_dirty(pool_head_ssl_capture);
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001672 if (!capture)
1673 return;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001674 /* Compute the xxh64 of the ciphersuite. */
1675 capture->xxh64 = XXH64(msg, rec_len, 0);
1676
1677 /* Capture the ciphersuite. */
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001678 capture->ciphersuite_len = (global_ssl.capture_cipherlist < rec_len) ?
1679 global_ssl.capture_cipherlist : rec_len;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001680 memcpy(capture->ciphersuite, msg, capture->ciphersuite_len);
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001681
1682 SSL_set_ex_data(ssl, ssl_capture_ptr_index, capture);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001683}
1684
Emeric Brun29f037d2014-04-25 19:05:36 +02001685/* Callback is called for ssl protocol analyse */
1686void ssl_sock_msgcbk(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg)
1687{
Emeric Brun29f037d2014-04-25 19:05:36 +02001688#ifdef TLS1_RT_HEARTBEAT
1689 /* test heartbeat received (write_p is set to 0
1690 for a received record) */
Willy Tarreauf51c6982014-04-25 20:02:39 +02001691 if ((content_type == TLS1_RT_HEARTBEAT) && (write_p == 0)) {
Thierry FOURNIER28962c92018-06-17 21:37:05 +02001692 struct connection *conn = SSL_get_ex_data(ssl, ssl_app_data_index);
William Lallemand7e1770b2019-05-13 14:31:34 +02001693 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
Willy Tarreauf51c6982014-04-25 20:02:39 +02001694 const unsigned char *p = buf;
1695 unsigned int payload;
1696
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001697 ctx->xprt_st |= SSL_SOCK_RECV_HEARTBEAT;
Willy Tarreauf51c6982014-04-25 20:02:39 +02001698
1699 /* Check if this is a CVE-2014-0160 exploitation attempt. */
1700 if (*p != TLS1_HB_REQUEST)
1701 return;
1702
Willy Tarreauaeed6722014-04-25 23:59:58 +02001703 if (len < 1 + 2 + 16) /* 1 type + 2 size + 0 payload + 16 padding */
Willy Tarreauf51c6982014-04-25 20:02:39 +02001704 goto kill_it;
1705
1706 payload = (p[1] * 256) + p[2];
Willy Tarreau3b2fdb62014-04-25 23:44:22 +02001707 if (3 + payload + 16 <= len)
Willy Tarreauf51c6982014-04-25 20:02:39 +02001708 return; /* OK no problem */
Willy Tarreauaeed6722014-04-25 23:59:58 +02001709 kill_it:
Willy Tarreau3b2fdb62014-04-25 23:44:22 +02001710 /* We have a clear heartbleed attack (CVE-2014-0160), the
1711 * advertised payload is larger than the advertised packet
1712 * length, so we have garbage in the buffer between the
1713 * payload and the end of the buffer (p+len). We can't know
1714 * if the SSL stack is patched, and we don't know if we can
1715 * safely wipe out the area between p+3+len and payload.
1716 * So instead, we prevent the response from being sent by
1717 * setting the max_send_fragment to 0 and we report an SSL
1718 * error, which will kill this connection. It will be reported
1719 * above as SSL_ERROR_SSL while an other handshake failure with
Willy Tarreauf51c6982014-04-25 20:02:39 +02001720 * a heartbeat message will be reported as SSL_ERROR_SYSCALL.
1721 */
Willy Tarreau3b2fdb62014-04-25 23:44:22 +02001722 ssl->max_send_fragment = 0;
Willy Tarreauf51c6982014-04-25 20:02:39 +02001723 SSLerr(SSL_F_TLS1_HEARTBEAT, SSL_R_SSL_HANDSHAKE_FAILURE);
1724 return;
1725 }
Emeric Brun29f037d2014-04-25 19:05:36 +02001726#endif
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001727 if (global_ssl.capture_cipherlist > 0)
1728 ssl_sock_parse_clienthello(write_p, version, content_type, buf, len, ssl);
Emeric Brun29f037d2014-04-25 19:05:36 +02001729}
1730
Bernard Spil13c53f82018-02-15 13:34:58 +01001731#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Olivier Houchardc7566002018-11-20 23:33:50 +01001732static int ssl_sock_srv_select_protos(SSL *s, unsigned char **out, unsigned char *outlen,
1733 const unsigned char *in, unsigned int inlen,
1734 void *arg)
1735{
1736 struct server *srv = arg;
1737
1738 if (SSL_select_next_proto(out, outlen, in, inlen, (unsigned char *)srv->ssl_ctx.npn_str,
1739 srv->ssl_ctx.npn_len) == OPENSSL_NPN_NEGOTIATED)
1740 return SSL_TLSEXT_ERR_OK;
1741 return SSL_TLSEXT_ERR_NOACK;
1742}
1743#endif
1744
1745#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02001746/* This callback is used so that the server advertises the list of
1747 * negociable protocols for NPN.
1748 */
1749static int ssl_sock_advertise_npn_protos(SSL *s, const unsigned char **data,
1750 unsigned int *len, void *arg)
1751{
Emmanuel Hocdet98263292016-12-29 18:26:15 +01001752 struct ssl_bind_conf *conf = arg;
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02001753
1754 *data = (const unsigned char *)conf->npn_str;
1755 *len = conf->npn_len;
1756 return SSL_TLSEXT_ERR_OK;
1757}
1758#endif
1759
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01001760#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02001761/* This callback is used so that the server advertises the list of
1762 * negociable protocols for ALPN.
1763 */
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01001764static int ssl_sock_advertise_alpn_protos(SSL *s, const unsigned char **out,
1765 unsigned char *outlen,
1766 const unsigned char *server,
1767 unsigned int server_len, void *arg)
Willy Tarreauab861d32013-04-02 02:30:41 +02001768{
Emmanuel Hocdet98263292016-12-29 18:26:15 +01001769 struct ssl_bind_conf *conf = arg;
Willy Tarreauab861d32013-04-02 02:30:41 +02001770
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01001771 if (SSL_select_next_proto((unsigned char**) out, outlen, (const unsigned char *)conf->alpn_str,
1772 conf->alpn_len, server, server_len) != OPENSSL_NPN_NEGOTIATED) {
1773 return SSL_TLSEXT_ERR_NOACK;
1774 }
Willy Tarreauab861d32013-04-02 02:30:41 +02001775 return SSL_TLSEXT_ERR_OK;
1776}
1777#endif
1778
Willy Tarreauc8ad3be2015-06-17 15:48:26 +02001779#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01001780#ifndef SSL_NO_GENERATE_CERTIFICATES
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001781
Christopher Faulet30548802015-06-11 13:39:32 +02001782/* Create a X509 certificate with the specified servername and serial. This
1783 * function returns a SSL_CTX object or NULL if an error occurs. */
Christopher Faulet7969a332015-10-09 11:15:03 +02001784static SSL_CTX *
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001785ssl_sock_do_create_cert(const char *servername, struct bind_conf *bind_conf, SSL *ssl)
Christopher Faulet31af49d2015-06-09 17:29:50 +02001786{
Christopher Faulet7969a332015-10-09 11:15:03 +02001787 X509 *cacert = bind_conf->ca_sign_cert;
1788 EVP_PKEY *capkey = bind_conf->ca_sign_pkey;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001789 SSL_CTX *ssl_ctx = NULL;
1790 X509 *newcrt = NULL;
1791 EVP_PKEY *pkey = NULL;
Emmanuel Hocdet15969292017-08-11 10:56:00 +02001792 SSL *tmp_ssl = NULL;
Emmanuel Hocdeta9b84022018-10-01 18:41:36 +02001793 CONF *ctmp = NULL;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001794 X509_NAME *name;
1795 const EVP_MD *digest;
1796 X509V3_CTX ctx;
1797 unsigned int i;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001798 int key_type;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001799
Christopher Faulet48a83322017-07-28 16:56:09 +02001800 /* Get the private key of the default certificate and use it */
Willy Tarreau5db847a2019-05-09 14:13:35 +02001801#if (HA_OPENSSL_VERSION_NUMBER >= 0x10002000L)
Emmanuel Hocdet15969292017-08-11 10:56:00 +02001802 pkey = SSL_CTX_get0_privatekey(bind_conf->default_ctx);
1803#else
1804 tmp_ssl = SSL_new(bind_conf->default_ctx);
1805 if (tmp_ssl)
1806 pkey = SSL_get_privatekey(tmp_ssl);
1807#endif
1808 if (!pkey)
Christopher Faulet31af49d2015-06-09 17:29:50 +02001809 goto mkcert_error;
1810
1811 /* Create the certificate */
1812 if (!(newcrt = X509_new()))
1813 goto mkcert_error;
1814
1815 /* Set version number for the certificate (X509v3) and the serial
1816 * number */
1817 if (X509_set_version(newcrt, 2L) != 1)
1818 goto mkcert_error;
Olivier Houchard2be5a4c2019-03-08 18:54:43 +01001819 ASN1_INTEGER_set(X509_get_serialNumber(newcrt), _HA_ATOMIC_ADD(&ssl_ctx_serial, 1));
Christopher Faulet31af49d2015-06-09 17:29:50 +02001820
1821 /* Set duration for the certificate */
Rosen Penev68185952018-12-14 08:47:02 -08001822 if (!X509_gmtime_adj(X509_getm_notBefore(newcrt), (long)-60*60*24) ||
1823 !X509_gmtime_adj(X509_getm_notAfter(newcrt),(long)60*60*24*365))
Christopher Faulet31af49d2015-06-09 17:29:50 +02001824 goto mkcert_error;
1825
1826 /* set public key in the certificate */
1827 if (X509_set_pubkey(newcrt, pkey) != 1)
1828 goto mkcert_error;
1829
1830 /* Set issuer name from the CA */
1831 if (!(name = X509_get_subject_name(cacert)))
1832 goto mkcert_error;
1833 if (X509_set_issuer_name(newcrt, name) != 1)
1834 goto mkcert_error;
1835
1836 /* Set the subject name using the same, but the CN */
1837 name = X509_NAME_dup(name);
1838 if (X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC,
1839 (const unsigned char *)servername,
1840 -1, -1, 0) != 1) {
1841 X509_NAME_free(name);
1842 goto mkcert_error;
1843 }
1844 if (X509_set_subject_name(newcrt, name) != 1) {
1845 X509_NAME_free(name);
1846 goto mkcert_error;
1847 }
1848 X509_NAME_free(name);
1849
1850 /* Add x509v3 extensions as specified */
Emmanuel Hocdeta9b84022018-10-01 18:41:36 +02001851 ctmp = NCONF_new(NULL);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001852 X509V3_set_ctx(&ctx, cacert, newcrt, NULL, NULL, 0);
1853 for (i = 0; i < X509V3_EXT_SIZE; i++) {
1854 X509_EXTENSION *ext;
1855
Emmanuel Hocdeta9b84022018-10-01 18:41:36 +02001856 if (!(ext = X509V3_EXT_nconf(ctmp, &ctx, x509v3_ext_names[i], x509v3_ext_values[i])))
Christopher Faulet31af49d2015-06-09 17:29:50 +02001857 goto mkcert_error;
1858 if (!X509_add_ext(newcrt, ext, -1)) {
1859 X509_EXTENSION_free(ext);
1860 goto mkcert_error;
1861 }
1862 X509_EXTENSION_free(ext);
1863 }
1864
1865 /* Sign the certificate with the CA private key */
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001866
1867 key_type = EVP_PKEY_base_id(capkey);
1868
1869 if (key_type == EVP_PKEY_DSA)
1870 digest = EVP_sha1();
1871 else if (key_type == EVP_PKEY_RSA)
Christopher Faulet31af49d2015-06-09 17:29:50 +02001872 digest = EVP_sha256();
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001873 else if (key_type == EVP_PKEY_EC)
Christopher Faulet7969a332015-10-09 11:15:03 +02001874 digest = EVP_sha256();
1875 else {
Willy Tarreau9a1ab082019-05-09 13:26:41 +02001876#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000000fL) && !defined(OPENSSL_IS_BORINGSSL)
Christopher Faulet7969a332015-10-09 11:15:03 +02001877 int nid;
1878
1879 if (EVP_PKEY_get_default_digest_nid(capkey, &nid) <= 0)
1880 goto mkcert_error;
1881 if (!(digest = EVP_get_digestbynid(nid)))
1882 goto mkcert_error;
Christopher Faulete7db2162015-10-19 13:59:24 +02001883#else
1884 goto mkcert_error;
1885#endif
Christopher Faulet7969a332015-10-09 11:15:03 +02001886 }
1887
Christopher Faulet31af49d2015-06-09 17:29:50 +02001888 if (!(X509_sign(newcrt, capkey, digest)))
1889 goto mkcert_error;
1890
1891 /* Create and set the new SSL_CTX */
1892 if (!(ssl_ctx = SSL_CTX_new(SSLv23_server_method())))
1893 goto mkcert_error;
1894 if (!SSL_CTX_use_PrivateKey(ssl_ctx, pkey))
1895 goto mkcert_error;
1896 if (!SSL_CTX_use_certificate(ssl_ctx, newcrt))
1897 goto mkcert_error;
1898 if (!SSL_CTX_check_private_key(ssl_ctx))
1899 goto mkcert_error;
1900
1901 if (newcrt) X509_free(newcrt);
Christopher Faulet7969a332015-10-09 11:15:03 +02001902
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01001903#ifndef OPENSSL_NO_DH
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001904 SSL_CTX_set_tmp_dh_callback(ssl_ctx, ssl_get_tmp_dh);
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01001905#endif
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001906#if defined(SSL_CTX_set_tmp_ecdh) && !defined(OPENSSL_NO_ECDH)
1907 {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01001908 const char *ecdhe = (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe : ECDHE_DEFAULT_CURVE);
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001909 EC_KEY *ecc;
1910 int nid;
1911
1912 if ((nid = OBJ_sn2nid(ecdhe)) == NID_undef)
1913 goto end;
1914 if (!(ecc = EC_KEY_new_by_curve_name(nid)))
1915 goto end;
1916 SSL_CTX_set_tmp_ecdh(ssl_ctx, ecc);
1917 EC_KEY_free(ecc);
1918 }
1919#endif
1920 end:
Christopher Faulet31af49d2015-06-09 17:29:50 +02001921 return ssl_ctx;
1922
1923 mkcert_error:
Emmanuel Hocdeta9b84022018-10-01 18:41:36 +02001924 if (ctmp) NCONF_free(ctmp);
Emmanuel Hocdet15969292017-08-11 10:56:00 +02001925 if (tmp_ssl) SSL_free(tmp_ssl);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001926 if (ssl_ctx) SSL_CTX_free(ssl_ctx);
1927 if (newcrt) X509_free(newcrt);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001928 return NULL;
1929}
1930
Christopher Faulet7969a332015-10-09 11:15:03 +02001931SSL_CTX *
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001932ssl_sock_create_cert(struct connection *conn, const char *servername, unsigned int key)
Christopher Faulet7969a332015-10-09 11:15:03 +02001933{
Willy Tarreau07d94e42018-09-20 10:57:52 +02001934 struct bind_conf *bind_conf = __objt_listener(conn->target)->bind_conf;
Olivier Houchard66ab4982019-02-26 18:37:15 +01001935 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001936
Olivier Houchard66ab4982019-02-26 18:37:15 +01001937 return ssl_sock_do_create_cert(servername, bind_conf, ctx->ssl);
Christopher Faulet7969a332015-10-09 11:15:03 +02001938}
1939
Christopher Faulet30548802015-06-11 13:39:32 +02001940/* Do a lookup for a certificate in the LRU cache used to store generated
Emeric Brun821bb9b2017-06-15 16:37:39 +02001941 * certificates and immediately assign it to the SSL session if not null. */
Christopher Faulet30548802015-06-11 13:39:32 +02001942SSL_CTX *
Emeric Brun821bb9b2017-06-15 16:37:39 +02001943ssl_sock_assign_generated_cert(unsigned int key, struct bind_conf *bind_conf, SSL *ssl)
Christopher Faulet30548802015-06-11 13:39:32 +02001944{
1945 struct lru64 *lru = NULL;
1946
1947 if (ssl_ctx_lru_tree) {
Willy Tarreau03f4ec42018-05-17 10:56:47 +02001948 HA_RWLOCK_WRLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001949 lru = lru64_lookup(key, ssl_ctx_lru_tree, bind_conf->ca_sign_cert, 0);
Emeric Brun821bb9b2017-06-15 16:37:39 +02001950 if (lru && lru->domain) {
1951 if (ssl)
1952 SSL_set_SSL_CTX(ssl, (SSL_CTX *)lru->data);
Willy Tarreau03f4ec42018-05-17 10:56:47 +02001953 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet30548802015-06-11 13:39:32 +02001954 return (SSL_CTX *)lru->data;
Emeric Brun821bb9b2017-06-15 16:37:39 +02001955 }
Willy Tarreau03f4ec42018-05-17 10:56:47 +02001956 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet30548802015-06-11 13:39:32 +02001957 }
1958 return NULL;
1959}
1960
Emeric Brun821bb9b2017-06-15 16:37:39 +02001961/* Same as <ssl_sock_assign_generated_cert> but without SSL session. This
1962 * function is not thread-safe, it should only be used to check if a certificate
1963 * exists in the lru cache (with no warranty it will not be removed by another
1964 * thread). It is kept for backward compatibility. */
1965SSL_CTX *
1966ssl_sock_get_generated_cert(unsigned int key, struct bind_conf *bind_conf)
1967{
1968 return ssl_sock_assign_generated_cert(key, bind_conf, NULL);
1969}
1970
Christopher Fauletd2cab922015-07-28 16:03:47 +02001971/* Set a certificate int the LRU cache used to store generated
1972 * certificate. Return 0 on success, otherwise -1 */
1973int
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001974ssl_sock_set_generated_cert(SSL_CTX *ssl_ctx, unsigned int key, struct bind_conf *bind_conf)
Christopher Faulet30548802015-06-11 13:39:32 +02001975{
1976 struct lru64 *lru = NULL;
1977
1978 if (ssl_ctx_lru_tree) {
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001979 HA_RWLOCK_WRLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001980 lru = lru64_get(key, ssl_ctx_lru_tree, bind_conf->ca_sign_cert, 0);
Emeric Brun821bb9b2017-06-15 16:37:39 +02001981 if (!lru) {
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001982 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Fauletd2cab922015-07-28 16:03:47 +02001983 return -1;
Emeric Brun821bb9b2017-06-15 16:37:39 +02001984 }
Christopher Faulet30548802015-06-11 13:39:32 +02001985 if (lru->domain && lru->data)
1986 lru->free((SSL_CTX *)lru->data);
Christopher Faulet7969a332015-10-09 11:15:03 +02001987 lru64_commit(lru, ssl_ctx, bind_conf->ca_sign_cert, 0, (void (*)(void *))SSL_CTX_free);
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001988 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Fauletd2cab922015-07-28 16:03:47 +02001989 return 0;
Christopher Faulet30548802015-06-11 13:39:32 +02001990 }
Christopher Fauletd2cab922015-07-28 16:03:47 +02001991 return -1;
Christopher Faulet30548802015-06-11 13:39:32 +02001992}
1993
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001994/* Compute the key of the certificate. */
Christopher Faulet30548802015-06-11 13:39:32 +02001995unsigned int
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001996ssl_sock_generated_cert_key(const void *data, size_t len)
Christopher Faulet30548802015-06-11 13:39:32 +02001997{
1998 return XXH32(data, len, ssl_ctx_lru_seed);
1999}
2000
Willy Tarreau2f63ef42015-10-20 15:16:01 +02002001/* Generate a cert and immediately assign it to the SSL session so that the cert's
2002 * refcount is maintained regardless of the cert's presence in the LRU cache.
2003 */
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002004static int
Christopher Faulet7969a332015-10-09 11:15:03 +02002005ssl_sock_generate_certificate(const char *servername, struct bind_conf *bind_conf, SSL *ssl)
Christopher Faulet31af49d2015-06-09 17:29:50 +02002006{
2007 X509 *cacert = bind_conf->ca_sign_cert;
Christopher Faulet31af49d2015-06-09 17:29:50 +02002008 SSL_CTX *ssl_ctx = NULL;
2009 struct lru64 *lru = NULL;
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002010 unsigned int key;
Christopher Faulet31af49d2015-06-09 17:29:50 +02002011
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002012 key = ssl_sock_generated_cert_key(servername, strlen(servername));
Christopher Faulet31af49d2015-06-09 17:29:50 +02002013 if (ssl_ctx_lru_tree) {
Christopher Faulet2a944ee2017-11-07 10:42:54 +01002014 HA_RWLOCK_WRLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002015 lru = lru64_get(key, ssl_ctx_lru_tree, cacert, 0);
Christopher Faulet31af49d2015-06-09 17:29:50 +02002016 if (lru && lru->domain)
2017 ssl_ctx = (SSL_CTX *)lru->data;
Christopher Fauletd2cab922015-07-28 16:03:47 +02002018 if (!ssl_ctx && lru) {
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002019 ssl_ctx = ssl_sock_do_create_cert(servername, bind_conf, ssl);
Christopher Faulet31af49d2015-06-09 17:29:50 +02002020 lru64_commit(lru, ssl_ctx, cacert, 0, (void (*)(void *))SSL_CTX_free);
Christopher Fauletd2cab922015-07-28 16:03:47 +02002021 }
Willy Tarreau2f63ef42015-10-20 15:16:01 +02002022 SSL_set_SSL_CTX(ssl, ssl_ctx);
Christopher Faulet2a944ee2017-11-07 10:42:54 +01002023 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002024 return 1;
Christopher Faulet31af49d2015-06-09 17:29:50 +02002025 }
Willy Tarreau2f63ef42015-10-20 15:16:01 +02002026 else {
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002027 ssl_ctx = ssl_sock_do_create_cert(servername, bind_conf, ssl);
Willy Tarreau2f63ef42015-10-20 15:16:01 +02002028 SSL_set_SSL_CTX(ssl, ssl_ctx);
2029 /* No LRU cache, this CTX will be released as soon as the session dies */
2030 SSL_CTX_free(ssl_ctx);
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002031 return 1;
Willy Tarreau2f63ef42015-10-20 15:16:01 +02002032 }
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002033 return 0;
2034}
2035static int
2036ssl_sock_generate_certificate_from_conn(struct bind_conf *bind_conf, SSL *ssl)
2037{
2038 unsigned int key;
Thierry FOURNIER28962c92018-06-17 21:37:05 +02002039 struct connection *conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002040
Willy Tarreauf5bdb642019-07-17 11:29:32 +02002041 if (conn_get_dst(conn)) {
Willy Tarreau085a1512019-07-17 14:47:35 +02002042 key = ssl_sock_generated_cert_key(conn->dst, get_addr_len(conn->dst));
Emeric Brun821bb9b2017-06-15 16:37:39 +02002043 if (ssl_sock_assign_generated_cert(key, bind_conf, ssl))
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002044 return 1;
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002045 }
2046 return 0;
Christopher Faulet31af49d2015-06-09 17:29:50 +02002047}
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002048#endif /* !defined SSL_NO_GENERATE_CERTIFICATES */
Christopher Faulet31af49d2015-06-09 17:29:50 +02002049
Willy Tarreau9a1ab082019-05-09 13:26:41 +02002050#if (HA_OPENSSL_VERSION_NUMBER < 0x1010000fL)
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002051typedef enum { SET_CLIENT, SET_SERVER } set_context_func;
2052
2053static void ctx_set_SSLv3_func(SSL_CTX *ctx, set_context_func c)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002054{
Emmanuel Hocdet23877ab2017-07-12 12:53:02 +02002055#if SSL_OP_NO_SSLv3
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002056 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, SSLv3_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002057 : SSL_CTX_set_ssl_version(ctx, SSLv3_client_method());
2058#endif
2059}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002060static void ctx_set_TLSv10_func(SSL_CTX *ctx, set_context_func c) {
2061 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, TLSv1_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002062 : SSL_CTX_set_ssl_version(ctx, TLSv1_client_method());
2063}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002064static void ctx_set_TLSv11_func(SSL_CTX *ctx, set_context_func c) {
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002065#if SSL_OP_NO_TLSv1_1
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002066 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, TLSv1_1_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002067 : SSL_CTX_set_ssl_version(ctx, TLSv1_1_client_method());
2068#endif
2069}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002070static void ctx_set_TLSv12_func(SSL_CTX *ctx, set_context_func c) {
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002071#if SSL_OP_NO_TLSv1_2
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002072 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, TLSv1_2_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002073 : SSL_CTX_set_ssl_version(ctx, TLSv1_2_client_method());
2074#endif
2075}
Bertrand Jacquina25282b2018-08-14 00:56:13 +01002076/* TLSv1.2 is the last supported version in this context. */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002077static void ctx_set_TLSv13_func(SSL_CTX *ctx, set_context_func c) {}
2078/* Unusable in this context. */
2079static void ssl_set_SSLv3_func(SSL *ssl, set_context_func c) {}
2080static void ssl_set_TLSv10_func(SSL *ssl, set_context_func c) {}
2081static void ssl_set_TLSv11_func(SSL *ssl, set_context_func c) {}
2082static void ssl_set_TLSv12_func(SSL *ssl, set_context_func c) {}
2083static void ssl_set_TLSv13_func(SSL *ssl, set_context_func c) {}
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002084#else /* openssl >= 1.1.0 */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002085typedef enum { SET_MIN, SET_MAX } set_context_func;
2086
2087static void ctx_set_SSLv3_func(SSL_CTX *ctx, set_context_func c) {
2088 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, SSL3_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002089 : SSL_CTX_set_min_proto_version(ctx, SSL3_VERSION);
2090}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002091static void ssl_set_SSLv3_func(SSL *ssl, set_context_func c) {
2092 c == SET_MAX ? SSL_set_max_proto_version(ssl, SSL3_VERSION)
2093 : SSL_set_min_proto_version(ssl, SSL3_VERSION);
2094}
2095static void ctx_set_TLSv10_func(SSL_CTX *ctx, set_context_func c) {
2096 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002097 : SSL_CTX_set_min_proto_version(ctx, TLS1_VERSION);
2098}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002099static void ssl_set_TLSv10_func(SSL *ssl, set_context_func c) {
2100 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_VERSION)
2101 : SSL_set_min_proto_version(ssl, TLS1_VERSION);
2102}
2103static void ctx_set_TLSv11_func(SSL_CTX *ctx, set_context_func c) {
2104 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_1_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002105 : SSL_CTX_set_min_proto_version(ctx, TLS1_1_VERSION);
2106}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002107static void ssl_set_TLSv11_func(SSL *ssl, set_context_func c) {
2108 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_1_VERSION)
2109 : SSL_set_min_proto_version(ssl, TLS1_1_VERSION);
2110}
2111static void ctx_set_TLSv12_func(SSL_CTX *ctx, set_context_func c) {
2112 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_2_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002113 : SSL_CTX_set_min_proto_version(ctx, TLS1_2_VERSION);
2114}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002115static void ssl_set_TLSv12_func(SSL *ssl, set_context_func c) {
2116 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_2_VERSION)
2117 : SSL_set_min_proto_version(ssl, TLS1_2_VERSION);
2118}
2119static void ctx_set_TLSv13_func(SSL_CTX *ctx, set_context_func c) {
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002120#if SSL_OP_NO_TLSv1_3
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002121 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_3_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002122 : SSL_CTX_set_min_proto_version(ctx, TLS1_3_VERSION);
2123#endif
2124}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002125static void ssl_set_TLSv13_func(SSL *ssl, set_context_func c) {
2126#if SSL_OP_NO_TLSv1_3
2127 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_3_VERSION)
2128 : SSL_set_min_proto_version(ssl, TLS1_3_VERSION);
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002129#endif
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002130}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002131#endif
2132static void ctx_set_None_func(SSL_CTX *ctx, set_context_func c) { }
2133static void ssl_set_None_func(SSL *ssl, set_context_func c) { }
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002134
2135static struct {
2136 int option;
2137 uint16_t flag;
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002138 void (*ctx_set_version)(SSL_CTX *, set_context_func);
2139 void (*ssl_set_version)(SSL *, set_context_func);
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002140 const char *name;
2141} methodVersions[] = {
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002142 {0, 0, ctx_set_None_func, ssl_set_None_func, "NONE"}, /* CONF_TLSV_NONE */
2143 {SSL_OP_NO_SSLv3, MC_SSL_O_NO_SSLV3, ctx_set_SSLv3_func, ssl_set_SSLv3_func, "SSLv3"}, /* CONF_SSLV3 */
2144 {SSL_OP_NO_TLSv1, MC_SSL_O_NO_TLSV10, ctx_set_TLSv10_func, ssl_set_TLSv10_func, "TLSv1.0"}, /* CONF_TLSV10 */
2145 {SSL_OP_NO_TLSv1_1, MC_SSL_O_NO_TLSV11, ctx_set_TLSv11_func, ssl_set_TLSv11_func, "TLSv1.1"}, /* CONF_TLSV11 */
2146 {SSL_OP_NO_TLSv1_2, MC_SSL_O_NO_TLSV12, ctx_set_TLSv12_func, ssl_set_TLSv12_func, "TLSv1.2"}, /* CONF_TLSV12 */
2147 {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 +02002148};
2149
Emmanuel Hocdet530141f2017-03-01 18:54:56 +01002150static void ssl_sock_switchctx_set(SSL *ssl, SSL_CTX *ctx)
2151{
2152 SSL_set_verify(ssl, SSL_CTX_get_verify_mode(ctx), ssl_sock_bind_verifycbk);
2153 SSL_set_client_CA_list(ssl, SSL_dup_CA_list(SSL_CTX_get_client_CA_list(ctx)));
2154 SSL_set_SSL_CTX(ssl, ctx);
2155}
2156
Willy Tarreau5db847a2019-05-09 14:13:35 +02002157#if ((HA_OPENSSL_VERSION_NUMBER >= 0x10101000L) || defined(OPENSSL_IS_BORINGSSL))
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002158
2159static int ssl_sock_switchctx_err_cbk(SSL *ssl, int *al, void *priv)
2160{
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002161 struct bind_conf *s = priv;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002162 (void)al; /* shut gcc stupid warning */
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002163
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002164 if (SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name) || s->generate_certs)
2165 return SSL_TLSEXT_ERR_OK;
2166 return SSL_TLSEXT_ERR_NOACK;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002167}
2168
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002169#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002170static int ssl_sock_switchctx_cbk(const struct ssl_early_callback_ctx *ctx)
2171{
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002172 SSL *ssl = ctx->ssl;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002173#else
2174static int ssl_sock_switchctx_cbk(SSL *ssl, int *al, void *arg)
2175{
2176#endif
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002177 struct connection *conn;
2178 struct bind_conf *s;
2179 const uint8_t *extension_data;
2180 size_t extension_len;
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002181 int has_rsa_sig = 0, has_ecdsa_sig = 0;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002182
2183 char *wildp = NULL;
2184 const uint8_t *servername;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002185 size_t servername_len;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002186 struct ebmb_node *node, *n, *node_ecdsa = NULL, *node_rsa = NULL, *node_anonymous = NULL;
Olivier Houchardc2aae742017-09-22 18:26:28 +02002187 int allow_early = 0;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002188 int i;
2189
Thierry FOURNIER28962c92018-06-17 21:37:05 +02002190 conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Willy Tarreaua8825522018-10-15 13:20:07 +02002191 s = __objt_listener(conn->target)->bind_conf;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002192
Olivier Houchard9679ac92017-10-27 14:58:08 +02002193 if (s->ssl_conf.early_data)
Olivier Houchardc2aae742017-09-22 18:26:28 +02002194 allow_early = 1;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002195#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002196 if (SSL_early_callback_ctx_extension_get(ctx, TLSEXT_TYPE_server_name,
2197 &extension_data, &extension_len)) {
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002198#else
2199 if (SSL_client_hello_get0_ext(ssl, TLSEXT_TYPE_server_name, &extension_data, &extension_len)) {
2200#endif
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002201 /*
2202 * The server_name extension was given too much extensibility when it
2203 * was written, so parsing the normal case is a bit complex.
2204 */
2205 size_t len;
2206 if (extension_len <= 2)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002207 goto abort;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002208 /* Extract the length of the supplied list of names. */
2209 len = (*extension_data++) << 8;
2210 len |= *extension_data++;
2211 if (len + 2 != extension_len)
2212 goto abort;
2213 /*
2214 * The list in practice only has a single element, so we only consider
2215 * the first one.
2216 */
2217 if (len == 0 || *extension_data++ != TLSEXT_NAMETYPE_host_name)
2218 goto abort;
2219 extension_len = len - 1;
2220 /* Now we can finally pull out the byte array with the actual hostname. */
2221 if (extension_len <= 2)
2222 goto abort;
2223 len = (*extension_data++) << 8;
2224 len |= *extension_data++;
2225 if (len == 0 || len + 2 > extension_len || len > TLSEXT_MAXLEN_host_name
2226 || memchr(extension_data, 0, len) != NULL)
2227 goto abort;
2228 servername = extension_data;
2229 servername_len = len;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002230 } else {
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002231#if (!defined SSL_NO_GENERATE_CERTIFICATES)
2232 if (s->generate_certs && ssl_sock_generate_certificate_from_conn(s, ssl)) {
Olivier Houchardc2aae742017-09-22 18:26:28 +02002233 goto allow_early;
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002234 }
2235#endif
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002236 /* without SNI extension, is the default_ctx (need SSL_TLSEXT_ERR_NOACK) */
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002237 if (!s->strict_sni) {
William Lallemand21724f02019-11-04 17:56:13 +01002238 HA_RWLOCK_RDLOCK(SNI_LOCK, &s->sni_lock);
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002239 ssl_sock_switchctx_set(ssl, s->default_ctx);
William Lallemand21724f02019-11-04 17:56:13 +01002240 HA_RWLOCK_RDUNLOCK(SNI_LOCK, &s->sni_lock);
Olivier Houchardc2aae742017-09-22 18:26:28 +02002241 goto allow_early;
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002242 }
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002243 goto abort;
2244 }
2245
2246 /* extract/check clientHello informations */
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002247#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002248 if (SSL_early_callback_ctx_extension_get(ctx, TLSEXT_TYPE_signature_algorithms, &extension_data, &extension_len)) {
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002249#else
2250 if (SSL_client_hello_get0_ext(ssl, TLSEXT_TYPE_signature_algorithms, &extension_data, &extension_len)) {
2251#endif
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002252 uint8_t sign;
2253 size_t len;
2254 if (extension_len < 2)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002255 goto abort;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002256 len = (*extension_data++) << 8;
2257 len |= *extension_data++;
2258 if (len + 2 != extension_len)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002259 goto abort;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002260 if (len % 2 != 0)
2261 goto abort;
2262 for (; len > 0; len -= 2) {
2263 extension_data++; /* hash */
2264 sign = *extension_data++;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002265 switch (sign) {
2266 case TLSEXT_signature_rsa:
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002267 has_rsa_sig = 1;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002268 break;
2269 case TLSEXT_signature_ecdsa:
2270 has_ecdsa_sig = 1;
2271 break;
2272 default:
2273 continue;
2274 }
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002275 if (has_ecdsa_sig && has_rsa_sig)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002276 break;
2277 }
2278 } else {
Bertrand Jacquina25282b2018-08-14 00:56:13 +01002279 /* without TLSEXT_TYPE_signature_algorithms extension (< TLSv1.2) */
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002280 has_rsa_sig = 1;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002281 }
2282 if (has_ecdsa_sig) { /* in very rare case: has ecdsa sign but not a ECDSA cipher */
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002283 const SSL_CIPHER *cipher;
2284 size_t len;
2285 const uint8_t *cipher_suites;
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002286 has_ecdsa_sig = 0;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002287#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002288 len = ctx->cipher_suites_len;
2289 cipher_suites = ctx->cipher_suites;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002290#else
2291 len = SSL_client_hello_get0_ciphers(ssl, &cipher_suites);
2292#endif
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002293 if (len % 2 != 0)
2294 goto abort;
2295 for (; len != 0; len -= 2, cipher_suites += 2) {
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002296#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002297 uint16_t cipher_suite = (cipher_suites[0] << 8) | cipher_suites[1];
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002298 cipher = SSL_get_cipher_by_value(cipher_suite);
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002299#else
2300 cipher = SSL_CIPHER_find(ssl, cipher_suites);
2301#endif
Emmanuel Hocdet019f9b12017-10-02 17:12:06 +02002302 if (cipher && SSL_CIPHER_get_auth_nid(cipher) == NID_auth_ecdsa) {
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002303 has_ecdsa_sig = 1;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002304 break;
2305 }
2306 }
2307 }
2308
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002309 for (i = 0; i < trash.size && i < servername_len; i++) {
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002310 trash.area[i] = tolower(servername[i]);
2311 if (!wildp && (trash.area[i] == '.'))
2312 wildp = &trash.area[i];
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002313 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002314 trash.area[i] = 0;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002315
William Lallemand150bfa82019-09-19 17:12:49 +02002316 HA_RWLOCK_RDLOCK(SNI_LOCK, &s->sni_lock);
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002317 /* lookup in full qualified names */
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002318 node = ebst_lookup(&s->sni_ctx, trash.area);
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002319
2320 /* lookup a not neg filter */
2321 for (n = node; n; n = ebmb_next_dup(n)) {
2322 if (!container_of(n, struct sni_ctx, name)->neg) {
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002323 switch(container_of(n, struct sni_ctx, name)->kinfo.sig) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002324 case TLSEXT_signature_ecdsa:
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002325 if (!node_ecdsa)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002326 node_ecdsa = n;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002327 break;
2328 case TLSEXT_signature_rsa:
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002329 if (!node_rsa)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002330 node_rsa = n;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002331 break;
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002332 default: /* TLSEXT_signature_anonymous|dsa */
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002333 if (!node_anonymous)
2334 node_anonymous = n;
2335 break;
2336 }
2337 }
2338 }
2339 if (wildp) {
2340 /* lookup in wildcards names */
2341 node = ebst_lookup(&s->sni_w_ctx, wildp);
2342 for (n = node; n; n = ebmb_next_dup(n)) {
2343 if (!container_of(n, struct sni_ctx, name)->neg) {
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002344 switch(container_of(n, struct sni_ctx, name)->kinfo.sig) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002345 case TLSEXT_signature_ecdsa:
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002346 if (!node_ecdsa)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002347 node_ecdsa = n;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002348 break;
2349 case TLSEXT_signature_rsa:
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002350 if (!node_rsa)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002351 node_rsa = n;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002352 break;
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002353 default: /* TLSEXT_signature_anonymous|dsa */
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002354 if (!node_anonymous)
2355 node_anonymous = n;
2356 break;
2357 }
2358 }
2359 }
2360 }
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002361 /* select by key_signature priority order */
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002362 node = (has_ecdsa_sig && node_ecdsa) ? node_ecdsa
2363 : ((has_rsa_sig && node_rsa) ? node_rsa
2364 : (node_anonymous ? node_anonymous
2365 : (node_ecdsa ? node_ecdsa /* no ecdsa signature case (< TLSv1.2) */
2366 : node_rsa /* no rsa signature case (far far away) */
2367 )));
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002368 if (node) {
2369 /* switch ctx */
Emmanuel Hocdet43664762017-08-09 18:26:20 +02002370 struct ssl_bind_conf *conf = container_of(node, struct sni_ctx, name)->conf;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002371 ssl_sock_switchctx_set(ssl, container_of(node, struct sni_ctx, name)->ctx);
Olivier Houchard35a63cc2017-11-02 19:04:38 +01002372 if (conf) {
2373 methodVersions[conf->ssl_methods.min].ssl_set_version(ssl, SET_MIN);
2374 methodVersions[conf->ssl_methods.max].ssl_set_version(ssl, SET_MAX);
2375 if (conf->early_data)
2376 allow_early = 1;
2377 }
William Lallemand02010472019-10-18 11:02:19 +02002378 HA_RWLOCK_RDUNLOCK(SNI_LOCK, &s->sni_lock);
Olivier Houchard35a63cc2017-11-02 19:04:38 +01002379 goto allow_early;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002380 }
William Lallemand150bfa82019-09-19 17:12:49 +02002381
William Lallemand02010472019-10-18 11:02:19 +02002382 HA_RWLOCK_RDUNLOCK(SNI_LOCK, &s->sni_lock);
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002383#if (!defined SSL_NO_GENERATE_CERTIFICATES)
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002384 if (s->generate_certs && ssl_sock_generate_certificate(trash.area, s, ssl)) {
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002385 /* switch ctx done in ssl_sock_generate_certificate */
Olivier Houchardc2aae742017-09-22 18:26:28 +02002386 goto allow_early;
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002387 }
2388#endif
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002389 if (!s->strict_sni) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002390 /* no certificate match, is the default_ctx */
William Lallemand21724f02019-11-04 17:56:13 +01002391 HA_RWLOCK_RDLOCK(SNI_LOCK, &s->sni_lock);
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002392 ssl_sock_switchctx_set(ssl, s->default_ctx);
William Lallemand21724f02019-11-04 17:56:13 +01002393 HA_RWLOCK_RDUNLOCK(SNI_LOCK, &s->sni_lock);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002394 }
Olivier Houchardc2aae742017-09-22 18:26:28 +02002395allow_early:
2396#ifdef OPENSSL_IS_BORINGSSL
2397 if (allow_early)
2398 SSL_set_early_data_enabled(ssl, 1);
2399#else
2400 if (!allow_early)
2401 SSL_set_max_early_data(ssl, 0);
2402#endif
2403 return 1;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002404 abort:
2405 /* abort handshake (was SSL_TLSEXT_ERR_ALERT_FATAL) */
2406 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002407#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002408 return ssl_select_cert_error;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002409#else
2410 *al = SSL_AD_UNRECOGNIZED_NAME;
2411 return 0;
2412#endif
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002413}
2414
2415#else /* OPENSSL_IS_BORINGSSL */
2416
Emeric Brunfc0421f2012-09-07 17:30:07 +02002417/* Sets the SSL ctx of <ssl> to match the advertised server name. Returns a
2418 * warning when no match is found, which implies the default (first) cert
2419 * will keep being used.
2420 */
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002421static int ssl_sock_switchctx_cbk(SSL *ssl, int *al, void *priv)
Emeric Brunfc0421f2012-09-07 17:30:07 +02002422{
2423 const char *servername;
2424 const char *wildp = NULL;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002425 struct ebmb_node *node, *n;
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002426 struct bind_conf *s = priv;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002427 int i;
2428 (void)al; /* shut gcc stupid warning */
2429
2430 servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
Emmanuel Hocdet65623372013-01-24 17:17:15 +01002431 if (!servername) {
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002432#if (!defined SSL_NO_GENERATE_CERTIFICATES)
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002433 if (s->generate_certs && ssl_sock_generate_certificate_from_conn(s, ssl))
2434 return SSL_TLSEXT_ERR_OK;
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002435#endif
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002436 if (s->strict_sni)
2437 return SSL_TLSEXT_ERR_ALERT_FATAL;
William Lallemand21724f02019-11-04 17:56:13 +01002438 HA_RWLOCK_RDLOCK(SNI_LOCK, &s->sni_lock);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002439 ssl_sock_switchctx_set(ssl, s->default_ctx);
William Lallemand21724f02019-11-04 17:56:13 +01002440 HA_RWLOCK_RDUNLOCK(SNI_LOCK, &s->sni_lock);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002441 return SSL_TLSEXT_ERR_NOACK;
Emmanuel Hocdet65623372013-01-24 17:17:15 +01002442 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02002443
Willy Tarreau19d14ef2012-10-29 16:51:55 +01002444 for (i = 0; i < trash.size; i++) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02002445 if (!servername[i])
2446 break;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002447 trash.area[i] = tolower(servername[i]);
2448 if (!wildp && (trash.area[i] == '.'))
2449 wildp = &trash.area[i];
Emeric Brunfc0421f2012-09-07 17:30:07 +02002450 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002451 trash.area[i] = 0;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002452
William Lallemand150bfa82019-09-19 17:12:49 +02002453 HA_RWLOCK_RDLOCK(SNI_LOCK, &s->sni_lock);
Emmanuel Hocdetc5fdf0f2019-11-04 15:49:46 +01002454 node = NULL;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002455 /* lookup in full qualified names */
Emmanuel Hocdetc5fdf0f2019-11-04 15:49:46 +01002456 for (n = ebst_lookup(&s->sni_ctx, trash.area); n; n = ebmb_next_dup(n)) {
2457 /* lookup a not neg filter */
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002458 if (!container_of(n, struct sni_ctx, name)->neg) {
2459 node = n;
2460 break;
Emmanuel Hocdet65623372013-01-24 17:17:15 +01002461 }
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002462 }
2463 if (!node && wildp) {
2464 /* lookup in wildcards names */
Emmanuel Hocdetc5fdf0f2019-11-04 15:49:46 +01002465 for (n = ebst_lookup(&s->sni_w_ctx, wildp); n; n = ebmb_next_dup(n)) {
2466 /* lookup a not neg filter */
2467 if (!container_of(n, struct sni_ctx, name)->neg) {
2468 node = n;
2469 break;
2470 }
2471 }
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002472 }
Emmanuel Hocdetc5fdf0f2019-11-04 15:49:46 +01002473 if (!node) {
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002474#if (!defined SSL_NO_GENERATE_CERTIFICATES)
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002475 if (s->generate_certs && ssl_sock_generate_certificate(servername, s, ssl)) {
2476 /* switch ctx done in ssl_sock_generate_certificate */
William Lallemand150bfa82019-09-19 17:12:49 +02002477 HA_RWLOCK_RDUNLOCK(SNI_LOCK, &s->sni_lock);
Christopher Faulet31af49d2015-06-09 17:29:50 +02002478 return SSL_TLSEXT_ERR_OK;
2479 }
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002480#endif
William Lallemand21724f02019-11-04 17:56:13 +01002481 if (s->strict_sni) {
2482 HA_RWLOCK_RDUNLOCK(SNI_LOCK, &s->sni_lock);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002483 return SSL_TLSEXT_ERR_ALERT_FATAL;
William Lallemand21724f02019-11-04 17:56:13 +01002484 }
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002485 ssl_sock_switchctx_set(ssl, s->default_ctx);
William Lallemand21724f02019-11-04 17:56:13 +01002486 HA_RWLOCK_RDUNLOCK(SNI_LOCK, &s->sni_lock);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002487 return SSL_TLSEXT_ERR_OK;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002488 }
2489
2490 /* switch ctx */
Emmanuel Hocdet530141f2017-03-01 18:54:56 +01002491 ssl_sock_switchctx_set(ssl, container_of(node, struct sni_ctx, name)->ctx);
William Lallemand150bfa82019-09-19 17:12:49 +02002492 HA_RWLOCK_RDUNLOCK(SNI_LOCK, &s->sni_lock);
Emeric Brunfc0421f2012-09-07 17:30:07 +02002493 return SSL_TLSEXT_ERR_OK;
2494}
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002495#endif /* (!) OPENSSL_IS_BORINGSSL */
Emeric Brunfc0421f2012-09-07 17:30:07 +02002496#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
2497
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002498#ifndef OPENSSL_NO_DH
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002499
2500static DH * ssl_get_dh_1024(void)
2501{
Remi Gacogned3a341a2015-05-29 16:26:17 +02002502 static unsigned char dh1024_p[]={
2503 0xFA,0xF9,0x2A,0x22,0x2A,0xA7,0x7F,0xE1,0x67,0x4E,0x53,0xF7,
2504 0x56,0x13,0xC3,0xB1,0xE3,0x29,0x6B,0x66,0x31,0x6A,0x7F,0xB3,
2505 0xC2,0x68,0x6B,0xCB,0x1D,0x57,0x39,0x1D,0x1F,0xFF,0x1C,0xC9,
2506 0xA6,0xA4,0x98,0x82,0x31,0x5D,0x25,0xFF,0x8A,0xE0,0x73,0x96,
2507 0x81,0xC8,0x83,0x79,0xC1,0x5A,0x04,0xF8,0x37,0x0D,0xA8,0x3D,
2508 0xAE,0x74,0xBC,0xDB,0xB6,0xA4,0x75,0xD9,0x71,0x8A,0xA0,0x17,
2509 0x9E,0x2D,0xC8,0xA8,0xDF,0x2C,0x5F,0x82,0x95,0xF8,0x92,0x9B,
2510 0xA7,0x33,0x5F,0x89,0x71,0xC8,0x2D,0x6B,0x18,0x86,0xC4,0x94,
2511 0x22,0xA5,0x52,0x8D,0xF6,0xF6,0xD2,0x37,0x92,0x0F,0xA5,0xCC,
2512 0xDB,0x7B,0x1D,0x3D,0xA1,0x31,0xB7,0x80,0x8F,0x0B,0x67,0x5E,
2513 0x36,0xA5,0x60,0x0C,0xF1,0x95,0x33,0x8B,
2514 };
2515 static unsigned char dh1024_g[]={
2516 0x02,
2517 };
2518
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002519 BIGNUM *p;
2520 BIGNUM *g;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002521 DH *dh = DH_new();
2522 if (dh) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002523 p = BN_bin2bn(dh1024_p, sizeof dh1024_p, NULL);
2524 g = BN_bin2bn(dh1024_g, sizeof dh1024_g, NULL);
Remi Gacogned3a341a2015-05-29 16:26:17 +02002525
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002526 if (!p || !g) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002527 DH_free(dh);
2528 dh = NULL;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002529 } else {
2530 DH_set0_pqg(dh, p, NULL, g);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002531 }
2532 }
2533 return dh;
2534}
2535
2536static DH *ssl_get_dh_2048(void)
2537{
Remi Gacogned3a341a2015-05-29 16:26:17 +02002538 static unsigned char dh2048_p[]={
2539 0xEC,0x86,0xF8,0x70,0xA0,0x33,0x16,0xEC,0x05,0x1A,0x73,0x59,
2540 0xCD,0x1F,0x8B,0xF8,0x29,0xE4,0xD2,0xCF,0x52,0xDD,0xC2,0x24,
2541 0x8D,0xB5,0x38,0x9A,0xFB,0x5C,0xA4,0xE4,0xB2,0xDA,0xCE,0x66,
2542 0x50,0x74,0xA6,0x85,0x4D,0x4B,0x1D,0x30,0xB8,0x2B,0xF3,0x10,
2543 0xE9,0xA7,0x2D,0x05,0x71,0xE7,0x81,0xDF,0x8B,0x59,0x52,0x3B,
2544 0x5F,0x43,0x0B,0x68,0xF1,0xDB,0x07,0xBE,0x08,0x6B,0x1B,0x23,
2545 0xEE,0x4D,0xCC,0x9E,0x0E,0x43,0xA0,0x1E,0xDF,0x43,0x8C,0xEC,
2546 0xBE,0xBE,0x90,0xB4,0x51,0x54,0xB9,0x2F,0x7B,0x64,0x76,0x4E,
2547 0x5D,0xD4,0x2E,0xAE,0xC2,0x9E,0xAE,0x51,0x43,0x59,0xC7,0x77,
2548 0x9C,0x50,0x3C,0x0E,0xED,0x73,0x04,0x5F,0xF1,0x4C,0x76,0x2A,
2549 0xD8,0xF8,0xCF,0xFC,0x34,0x40,0xD1,0xB4,0x42,0x61,0x84,0x66,
2550 0x42,0x39,0x04,0xF8,0x68,0xB2,0x62,0xD7,0x55,0xED,0x1B,0x74,
2551 0x75,0x91,0xE0,0xC5,0x69,0xC1,0x31,0x5C,0xDB,0x7B,0x44,0x2E,
2552 0xCE,0x84,0x58,0x0D,0x1E,0x66,0x0C,0xC8,0x44,0x9E,0xFD,0x40,
2553 0x08,0x67,0x5D,0xFB,0xA7,0x76,0x8F,0x00,0x11,0x87,0xE9,0x93,
2554 0xF9,0x7D,0xC4,0xBC,0x74,0x55,0x20,0xD4,0x4A,0x41,0x2F,0x43,
2555 0x42,0x1A,0xC1,0xF2,0x97,0x17,0x49,0x27,0x37,0x6B,0x2F,0x88,
2556 0x7E,0x1C,0xA0,0xA1,0x89,0x92,0x27,0xD9,0x56,0x5A,0x71,0xC1,
2557 0x56,0x37,0x7E,0x3A,0x9D,0x05,0xE7,0xEE,0x5D,0x8F,0x82,0x17,
2558 0xBC,0xE9,0xC2,0x93,0x30,0x82,0xF9,0xF4,0xC9,0xAE,0x49,0xDB,
2559 0xD0,0x54,0xB4,0xD9,0x75,0x4D,0xFA,0x06,0xB8,0xD6,0x38,0x41,
2560 0xB7,0x1F,0x77,0xF3,
2561 };
2562 static unsigned char dh2048_g[]={
2563 0x02,
2564 };
2565
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002566 BIGNUM *p;
2567 BIGNUM *g;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002568 DH *dh = DH_new();
2569 if (dh) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002570 p = BN_bin2bn(dh2048_p, sizeof dh2048_p, NULL);
2571 g = BN_bin2bn(dh2048_g, sizeof dh2048_g, NULL);
Remi Gacogned3a341a2015-05-29 16:26:17 +02002572
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002573 if (!p || !g) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002574 DH_free(dh);
2575 dh = NULL;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002576 } else {
2577 DH_set0_pqg(dh, p, NULL, g);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002578 }
2579 }
2580 return dh;
2581}
2582
2583static DH *ssl_get_dh_4096(void)
2584{
Remi Gacogned3a341a2015-05-29 16:26:17 +02002585 static unsigned char dh4096_p[]={
2586 0xDE,0x16,0x94,0xCD,0x99,0x58,0x07,0xF1,0xF7,0x32,0x96,0x11,
2587 0x04,0x82,0xD4,0x84,0x72,0x80,0x99,0x06,0xCA,0xF0,0xA3,0x68,
2588 0x07,0xCE,0x64,0x50,0xE7,0x74,0x45,0x20,0x80,0x5E,0x4D,0xAD,
2589 0xA5,0xB6,0xED,0xFA,0x80,0x6C,0x3B,0x35,0xC4,0x9A,0x14,0x6B,
2590 0x32,0xBB,0xFD,0x1F,0x17,0x8E,0xB7,0x1F,0xD6,0xFA,0x3F,0x7B,
2591 0xEE,0x16,0xA5,0x62,0x33,0x0D,0xED,0xBC,0x4E,0x58,0xE5,0x47,
2592 0x4D,0xE9,0xAB,0x8E,0x38,0xD3,0x6E,0x90,0x57,0xE3,0x22,0x15,
2593 0x33,0xBD,0xF6,0x43,0x45,0xB5,0x10,0x0A,0xBE,0x2C,0xB4,0x35,
2594 0xB8,0x53,0x8D,0xAD,0xFB,0xA7,0x1F,0x85,0x58,0x41,0x7A,0x79,
2595 0x20,0x68,0xB3,0xE1,0x3D,0x08,0x76,0xBF,0x86,0x0D,0x49,0xE3,
2596 0x82,0x71,0x8C,0xB4,0x8D,0x81,0x84,0xD4,0xE7,0xBE,0x91,0xDC,
2597 0x26,0x39,0x48,0x0F,0x35,0xC4,0xCA,0x65,0xE3,0x40,0x93,0x52,
2598 0x76,0x58,0x7D,0xDD,0x51,0x75,0xDC,0x69,0x61,0xBF,0x47,0x2C,
2599 0x16,0x68,0x2D,0xC9,0x29,0xD3,0xE6,0xC0,0x99,0x48,0xA0,0x9A,
2600 0xC8,0x78,0xC0,0x6D,0x81,0x67,0x12,0x61,0x3F,0x71,0xBA,0x41,
2601 0x1F,0x6C,0x89,0x44,0x03,0xBA,0x3B,0x39,0x60,0xAA,0x28,0x55,
2602 0x59,0xAE,0xB8,0xFA,0xCB,0x6F,0xA5,0x1A,0xF7,0x2B,0xDD,0x52,
2603 0x8A,0x8B,0xE2,0x71,0xA6,0x5E,0x7E,0xD8,0x2E,0x18,0xE0,0x66,
2604 0xDF,0xDD,0x22,0x21,0x99,0x52,0x73,0xA6,0x33,0x20,0x65,0x0E,
2605 0x53,0xE7,0x6B,0x9B,0xC5,0xA3,0x2F,0x97,0x65,0x76,0xD3,0x47,
2606 0x23,0x77,0x12,0xB6,0x11,0x7B,0x24,0xED,0xF1,0xEF,0xC0,0xE2,
2607 0xA3,0x7E,0x67,0x05,0x3E,0x96,0x4D,0x45,0xC2,0x18,0xD1,0x73,
2608 0x9E,0x07,0xF3,0x81,0x6E,0x52,0x63,0xF6,0x20,0x76,0xB9,0x13,
2609 0xD2,0x65,0x30,0x18,0x16,0x09,0x16,0x9E,0x8F,0xF1,0xD2,0x10,
2610 0x5A,0xD3,0xD4,0xAF,0x16,0x61,0xDA,0x55,0x2E,0x18,0x5E,0x14,
2611 0x08,0x54,0x2E,0x2A,0x25,0xA2,0x1A,0x9B,0x8B,0x32,0xA9,0xFD,
2612 0xC2,0x48,0x96,0xE1,0x80,0xCA,0xE9,0x22,0x17,0xBB,0xCE,0x3E,
2613 0x9E,0xED,0xC7,0xF1,0x1F,0xEC,0x17,0x21,0xDC,0x7B,0x82,0x48,
2614 0x8E,0xBB,0x4B,0x9D,0x5B,0x04,0x04,0xDA,0xDB,0x39,0xDF,0x01,
2615 0x40,0xC3,0xAA,0x26,0x23,0x89,0x75,0xC6,0x0B,0xD0,0xA2,0x60,
2616 0x6A,0xF1,0xCC,0x65,0x18,0x98,0x1B,0x52,0xD2,0x74,0x61,0xCC,
2617 0xBD,0x60,0xAE,0xA3,0xA0,0x66,0x6A,0x16,0x34,0x92,0x3F,0x41,
2618 0x40,0x31,0x29,0xC0,0x2C,0x63,0xB2,0x07,0x8D,0xEB,0x94,0xB8,
2619 0xE8,0x47,0x92,0x52,0x93,0x6A,0x1B,0x7E,0x1A,0x61,0xB3,0x1B,
2620 0xF0,0xD6,0x72,0x9B,0xF1,0xB0,0xAF,0xBF,0x3E,0x65,0xEF,0x23,
2621 0x1D,0x6F,0xFF,0x70,0xCD,0x8A,0x4C,0x8A,0xA0,0x72,0x9D,0xBE,
2622 0xD4,0xBB,0x24,0x47,0x4A,0x68,0xB5,0xF5,0xC6,0xD5,0x7A,0xCD,
2623 0xCA,0x06,0x41,0x07,0xAD,0xC2,0x1E,0xE6,0x54,0xA7,0xAD,0x03,
2624 0xD9,0x12,0xC1,0x9C,0x13,0xB1,0xC9,0x0A,0x43,0x8E,0x1E,0x08,
2625 0xCE,0x50,0x82,0x73,0x5F,0xA7,0x55,0x1D,0xD9,0x59,0xAC,0xB5,
2626 0xEA,0x02,0x7F,0x6C,0x5B,0x74,0x96,0x98,0x67,0x24,0xA3,0x0F,
2627 0x15,0xFC,0xA9,0x7D,0x3E,0x67,0xD1,0x70,0xF8,0x97,0xF3,0x67,
2628 0xC5,0x8C,0x88,0x44,0x08,0x02,0xC7,0x2B,
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002629 };
Remi Gacogned3a341a2015-05-29 16:26:17 +02002630 static unsigned char dh4096_g[]={
2631 0x02,
2632 };
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002633
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002634 BIGNUM *p;
2635 BIGNUM *g;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002636 DH *dh = DH_new();
2637 if (dh) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002638 p = BN_bin2bn(dh4096_p, sizeof dh4096_p, NULL);
2639 g = BN_bin2bn(dh4096_g, sizeof dh4096_g, NULL);
Remi Gacogned3a341a2015-05-29 16:26:17 +02002640
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002641 if (!p || !g) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002642 DH_free(dh);
2643 dh = NULL;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002644 } else {
2645 DH_set0_pqg(dh, p, NULL, g);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002646 }
2647 }
2648 return dh;
2649}
2650
2651/* Returns Diffie-Hellman parameters matching the private key length
Willy Tarreauef934602016-12-22 23:12:01 +01002652 but not exceeding global_ssl.default_dh_param */
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002653static DH *ssl_get_tmp_dh(SSL *ssl, int export, int keylen)
2654{
2655 DH *dh = NULL;
2656 EVP_PKEY *pkey = SSL_get_privatekey(ssl);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002657 int type;
2658
2659 type = pkey ? EVP_PKEY_base_id(pkey) : EVP_PKEY_NONE;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002660
2661 /* The keylen supplied by OpenSSL can only be 512 or 1024.
2662 See ssl3_send_server_key_exchange() in ssl/s3_srvr.c
2663 */
2664 if (type == EVP_PKEY_RSA || type == EVP_PKEY_DSA) {
2665 keylen = EVP_PKEY_bits(pkey);
2666 }
2667
Willy Tarreauef934602016-12-22 23:12:01 +01002668 if (keylen > global_ssl.default_dh_param) {
2669 keylen = global_ssl.default_dh_param;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002670 }
2671
Remi Gacogned3a341a2015-05-29 16:26:17 +02002672 if (keylen >= 4096) {
Remi Gacogne8de54152014-07-15 11:36:40 +02002673 dh = local_dh_4096;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002674 }
2675 else if (keylen >= 2048) {
Remi Gacogne8de54152014-07-15 11:36:40 +02002676 dh = local_dh_2048;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002677 }
2678 else {
Remi Gacogne8de54152014-07-15 11:36:40 +02002679 dh = local_dh_1024;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002680 }
2681
2682 return dh;
2683}
2684
Remi Gacogne47783ef2015-05-29 15:53:22 +02002685static DH * ssl_sock_get_dh_from_file(const char *filename)
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002686{
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002687 DH *dh = NULL;
Remi Gacogne47783ef2015-05-29 15:53:22 +02002688 BIO *in = BIO_new(BIO_s_file());
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002689
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002690 if (in == NULL)
2691 goto end;
2692
Remi Gacogne47783ef2015-05-29 15:53:22 +02002693 if (BIO_read_filename(in, filename) <= 0)
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002694 goto end;
2695
Remi Gacogne47783ef2015-05-29 15:53:22 +02002696 dh = PEM_read_bio_DHparams(in, NULL, NULL, NULL);
2697
2698end:
2699 if (in)
2700 BIO_free(in);
2701
Emeric Brune1b4ed42018-08-16 15:14:12 +02002702 ERR_clear_error();
2703
Remi Gacogne47783ef2015-05-29 15:53:22 +02002704 return dh;
2705}
2706
2707int ssl_sock_load_global_dh_param_from_file(const char *filename)
2708{
2709 global_dh = ssl_sock_get_dh_from_file(filename);
2710
2711 if (global_dh) {
2712 return 0;
2713 }
2714
2715 return -1;
2716}
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002717#endif
2718
William Lallemand9117de92019-10-04 00:29:42 +02002719/* Alloc and init a ckch_inst */
2720static struct ckch_inst *ckch_inst_new()
2721{
2722 struct ckch_inst *ckch_inst;
2723
2724 ckch_inst = calloc(1, sizeof *ckch_inst);
2725 if (ckch_inst)
2726 LIST_INIT(&ckch_inst->sni_ctx);
2727
2728 return ckch_inst;
2729}
2730
2731
2732/* This function allocates a sni_ctx and adds it to the ckch_inst */
William Lallemand1d29c742019-10-04 00:53:29 +02002733static int ckch_inst_add_cert_sni(SSL_CTX *ctx, struct ckch_inst *ckch_inst,
William Lallemand9117de92019-10-04 00:29:42 +02002734 struct bind_conf *s, struct ssl_bind_conf *conf,
2735 struct pkey_info kinfo, char *name, int order)
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002736{
2737 struct sni_ctx *sc;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002738 int wild = 0, neg = 0;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002739
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002740 if (*name == '!') {
2741 neg = 1;
2742 name++;
2743 }
2744 if (*name == '*') {
2745 wild = 1;
2746 name++;
2747 }
2748 /* !* filter is a nop */
2749 if (neg && wild)
2750 return order;
2751 if (*name) {
2752 int j, len;
2753 len = strlen(name);
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002754 for (j = 0; j < len && j < trash.size; j++)
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002755 trash.area[j] = tolower(name[j]);
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002756 if (j >= trash.size)
William Lallemandfe49bb32019-10-03 23:46:33 +02002757 return -1;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002758 trash.area[j] = 0;
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002759
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002760 sc = malloc(sizeof(struct sni_ctx) + len + 1);
Thierry FOURNIER / OZON.IO7a3bd3b2016-10-06 10:35:29 +02002761 if (!sc)
William Lallemandfe49bb32019-10-03 23:46:33 +02002762 return -1;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002763 memcpy(sc->name.key, trash.area, len + 1);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002764 sc->ctx = ctx;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01002765 sc->conf = conf;
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002766 sc->kinfo = kinfo;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002767 sc->order = order++;
2768 sc->neg = neg;
William Lallemand1d29c742019-10-04 00:53:29 +02002769 sc->wild = wild;
2770 sc->name.node.leaf_p = NULL;
William Lallemand1d29c742019-10-04 00:53:29 +02002771 LIST_ADDQ(&ckch_inst->sni_ctx, &sc->by_ckch_inst);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002772 }
2773 return order;
2774}
2775
William Lallemand6af03992019-07-23 15:00:54 +02002776/*
William Lallemand1d29c742019-10-04 00:53:29 +02002777 * Insert the sni_ctxs that are listed in the ckch_inst, in the bind_conf's sni_ctx tree
2778 * This function can't return an error.
2779 *
2780 * *CAUTION*: The caller must lock the sni tree if called in multithreading mode
2781 */
2782static void ssl_sock_load_cert_sni(struct ckch_inst *ckch_inst, struct bind_conf *bind_conf)
2783{
2784
2785 struct sni_ctx *sc0, *sc0b, *sc1;
2786 struct ebmb_node *node;
William Lallemand21724f02019-11-04 17:56:13 +01002787 int def = 0;
William Lallemand1d29c742019-10-04 00:53:29 +02002788
2789 list_for_each_entry_safe(sc0, sc0b, &ckch_inst->sni_ctx, by_ckch_inst) {
2790
2791 /* ignore if sc0 was already inserted in a tree */
2792 if (sc0->name.node.leaf_p)
2793 continue;
2794
2795 /* Check for duplicates. */
2796 if (sc0->wild)
2797 node = ebst_lookup(&bind_conf->sni_w_ctx, (char *)sc0->name.key);
2798 else
2799 node = ebst_lookup(&bind_conf->sni_ctx, (char *)sc0->name.key);
2800
2801 for (; node; node = ebmb_next_dup(node)) {
2802 sc1 = ebmb_entry(node, struct sni_ctx, name);
2803 if (sc1->ctx == sc0->ctx && sc1->conf == sc0->conf
2804 && sc1->neg == sc0->neg && sc1->wild == sc0->wild) {
2805 /* it's a duplicate, we should remove and free it */
2806 LIST_DEL(&sc0->by_ckch_inst);
2807 free(sc0);
2808 sc0 = NULL;
William Lallemande15029b2019-10-14 10:46:58 +02002809 break;
William Lallemand1d29c742019-10-04 00:53:29 +02002810 }
2811 }
2812
2813 /* if duplicate, ignore the insertion */
2814 if (!sc0)
2815 continue;
2816
2817 if (sc0->wild)
2818 ebst_insert(&bind_conf->sni_w_ctx, &sc0->name);
2819 else
2820 ebst_insert(&bind_conf->sni_ctx, &sc0->name);
William Lallemand21724f02019-11-04 17:56:13 +01002821
2822 /* replace the default_ctx if required with the first ctx */
2823 if (ckch_inst->is_default && !def) {
2824 /* we don't need to free the default_ctx because the refcount was not incremented */
2825 bind_conf->default_ctx = sc0->ctx;
2826 def = 1;
2827 }
William Lallemand1d29c742019-10-04 00:53:29 +02002828 }
2829}
2830
2831/*
William Lallemande3af8fb2019-10-08 11:36:53 +02002832 * tree used to store the ckchs ordered by filename/bundle name
William Lallemand6af03992019-07-23 15:00:54 +02002833 */
William Lallemande3af8fb2019-10-08 11:36:53 +02002834struct eb_root ckchs_tree = EB_ROOT_UNIQUE;
William Lallemand6af03992019-07-23 15:00:54 +02002835
William Lallemandfa892222019-07-23 16:06:08 +02002836
Emeric Brun7a883362019-10-17 13:27:40 +02002837/* Loads Diffie-Hellman parameter from a ckchs to an SSL_CTX.
2838 * If there is no DH paramater availaible in the ckchs, the global
2839 * DH parameter is loaded into the SSL_CTX and if there is no
2840 * DH parameter available in ckchs nor in global, the default
2841 * DH parameters are applied on the SSL_CTX.
2842 * Returns a bitfield containing the flags:
2843 * ERR_FATAL in any fatal error case
2844 * ERR_ALERT if a reason of the error is availabine in err
2845 * ERR_WARN if a warning is available into err
2846 * The value 0 means there is no error nor warning and
2847 * the operation succeed.
2848 */
William Lallemandfa892222019-07-23 16:06:08 +02002849#ifndef OPENSSL_NO_DH
Emeric Brun7a883362019-10-17 13:27:40 +02002850static int ssl_sock_load_dh_params(SSL_CTX *ctx, const struct cert_key_and_chain *ckch,
2851 const char *path, char **err)
William Lallemandfa892222019-07-23 16:06:08 +02002852{
Emeric Brun7a883362019-10-17 13:27:40 +02002853 int ret = 0;
William Lallemandfa892222019-07-23 16:06:08 +02002854 DH *dh = NULL;
2855
William Lallemanda8c73742019-07-31 18:31:34 +02002856 if (ckch && ckch->dh) {
William Lallemandfa892222019-07-23 16:06:08 +02002857 dh = ckch->dh;
Emeric Bruna9363eb2019-10-17 14:53:03 +02002858 if (!SSL_CTX_set_tmp_dh(ctx, dh)) {
2859 memprintf(err, "%sunable to load the DH parameter specified in '%s'",
2860 err && *err ? *err : "", path);
2861#if defined(SSL_CTX_set_dh_auto)
2862 SSL_CTX_set_dh_auto(ctx, 1);
2863 memprintf(err, "%s, SSL library will use an automatically generated DH parameter.\n",
2864 err && *err ? *err : "");
2865#else
2866 memprintf(err, "%s, DH ciphers won't be available.\n",
2867 err && *err ? *err : "");
2868#endif
2869 ret |= ERR_WARN;
2870 goto end;
2871 }
William Lallemandfa892222019-07-23 16:06:08 +02002872
2873 if (ssl_dh_ptr_index >= 0) {
2874 /* store a pointer to the DH params to avoid complaining about
2875 ssl-default-dh-param not being set for this SSL_CTX */
2876 SSL_CTX_set_ex_data(ctx, ssl_dh_ptr_index, dh);
2877 }
2878 }
2879 else if (global_dh) {
Emeric Bruna9363eb2019-10-17 14:53:03 +02002880 if (!SSL_CTX_set_tmp_dh(ctx, global_dh)) {
2881 memprintf(err, "%sunable to use the global DH parameter for certificate '%s'",
2882 err && *err ? *err : "", path);
2883#if defined(SSL_CTX_set_dh_auto)
2884 SSL_CTX_set_dh_auto(ctx, 1);
2885 memprintf(err, "%s, SSL library will use an automatically generated DH parameter.\n",
2886 err && *err ? *err : "");
2887#else
2888 memprintf(err, "%s, DH ciphers won't be available.\n",
2889 err && *err ? *err : "");
2890#endif
2891 ret |= ERR_WARN;
2892 goto end;
2893 }
William Lallemandfa892222019-07-23 16:06:08 +02002894 }
2895 else {
2896 /* Clear openssl global errors stack */
2897 ERR_clear_error();
2898
2899 if (global_ssl.default_dh_param <= 1024) {
2900 /* we are limited to DH parameter of 1024 bits anyway */
2901 if (local_dh_1024 == NULL)
2902 local_dh_1024 = ssl_get_dh_1024();
2903
Emeric Brun7a883362019-10-17 13:27:40 +02002904 if (local_dh_1024 == NULL) {
2905 memprintf(err, "%sunable to load default 1024 bits DH parameter for certificate '%s'.\n",
2906 err && *err ? *err : "", path);
2907 ret |= ERR_ALERT | ERR_FATAL;
William Lallemandfa892222019-07-23 16:06:08 +02002908 goto end;
Emeric Brun7a883362019-10-17 13:27:40 +02002909 }
William Lallemandfa892222019-07-23 16:06:08 +02002910
Emeric Bruna9363eb2019-10-17 14:53:03 +02002911 if (!SSL_CTX_set_tmp_dh(ctx, local_dh_1024)) {
2912 memprintf(err, "%sunable to load default 1024 bits DH parameter for certificate '%s'.\n",
2913 err && *err ? *err : "", path);
2914#if defined(SSL_CTX_set_dh_auto)
2915 SSL_CTX_set_dh_auto(ctx, 1);
2916 memprintf(err, "%s, SSL library will use an automatically generated DH parameter.\n",
2917 err && *err ? *err : "");
2918#else
2919 memprintf(err, "%s, DH ciphers won't be available.\n",
2920 err && *err ? *err : "");
2921#endif
2922 ret |= ERR_WARN;
2923 goto end;
2924 }
William Lallemandfa892222019-07-23 16:06:08 +02002925 }
2926 else {
2927 SSL_CTX_set_tmp_dh_callback(ctx, ssl_get_tmp_dh);
2928 }
William Lallemandfa892222019-07-23 16:06:08 +02002929 }
2930
2931end:
William Lallemandfa892222019-07-23 16:06:08 +02002932 return ret;
2933}
2934#endif
yanbzhu08ce6ab2015-12-02 13:01:29 -05002935
yanbzhu488a4d22015-12-01 15:16:07 -05002936/* Frees the contents of a cert_key_and_chain
2937 */
2938static void ssl_sock_free_cert_key_and_chain_contents(struct cert_key_and_chain *ckch)
2939{
yanbzhu488a4d22015-12-01 15:16:07 -05002940 if (!ckch)
2941 return;
2942
2943 /* Free the certificate and set pointer to NULL */
2944 if (ckch->cert)
2945 X509_free(ckch->cert);
2946 ckch->cert = NULL;
2947
2948 /* Free the key and set pointer to NULL */
2949 if (ckch->key)
2950 EVP_PKEY_free(ckch->key);
2951 ckch->key = NULL;
2952
2953 /* Free each certificate in the chain */
Emmanuel Hocdet9246f8b2018-11-30 16:00:21 +01002954 if (ckch->chain)
2955 sk_X509_pop_free(ckch->chain, X509_free);
2956 ckch->chain = NULL;
yanbzhu488a4d22015-12-01 15:16:07 -05002957
William Lallemand455af502019-10-17 18:04:45 +02002958 if (ckch->dh)
2959 DH_free(ckch->dh);
2960 ckch->dh = NULL;
2961
2962 if (ckch->sctl) {
2963 free(ckch->sctl->area);
2964 ckch->sctl->area = NULL;
2965 free(ckch->sctl);
2966 ckch->sctl = NULL;
2967 }
2968
2969 if (ckch->ocsp_response) {
2970 free(ckch->ocsp_response->area);
2971 ckch->ocsp_response->area = NULL;
2972 free(ckch->ocsp_response);
2973 ckch->ocsp_response = NULL;
2974 }
yanbzhu488a4d22015-12-01 15:16:07 -05002975}
2976
William Lallemand8d0f8932019-10-17 18:03:58 +02002977/*
2978 *
2979 * This function copy a cert_key_and_chain in memory
2980 *
2981 * It's used to try to apply changes on a ckch before committing them, because
2982 * most of the time it's not possible to revert those changes
2983 *
2984 * Return a the dst or NULL
2985 */
2986static struct cert_key_and_chain *ssl_sock_copy_cert_key_and_chain(struct cert_key_and_chain *src,
2987 struct cert_key_and_chain *dst)
2988{
2989 if (src->cert) {
2990 dst->cert = src->cert;
2991 X509_up_ref(src->cert);
2992 }
2993
2994 if (src->key) {
2995 dst->key = src->key;
2996 EVP_PKEY_up_ref(src->key);
2997 }
2998
2999 if (src->chain) {
3000 dst->chain = X509_chain_up_ref(src->chain);
3001 }
3002
3003 if (src->dh) {
3004 DH_up_ref(src->dh);
3005 dst->dh = src->dh;
3006 }
3007
3008 if (src->sctl) {
3009 struct buffer *sctl;
3010
3011 sctl = calloc(1, sizeof(*sctl));
3012 if (!chunk_dup(sctl, src->sctl)) {
3013 free(sctl);
3014 sctl = NULL;
3015 goto error;
3016 }
3017 dst->sctl = sctl;
3018 }
3019
3020 if (src->ocsp_response) {
3021 struct buffer *ocsp_response;
3022
3023 ocsp_response = calloc(1, sizeof(*ocsp_response));
3024 if (!chunk_dup(ocsp_response, src->ocsp_response)) {
3025 free(ocsp_response);
3026 ocsp_response = NULL;
3027 goto error;
3028 }
3029 dst->ocsp_response = ocsp_response;
3030 }
3031
3032 if (src->ocsp_issuer) {
3033 X509_up_ref(src->ocsp_issuer);
3034 dst->ocsp_issuer = src->ocsp_issuer;
3035 }
3036
3037 return dst;
3038
3039error:
3040
3041 /* free everything */
3042 ssl_sock_free_cert_key_and_chain_contents(dst);
3043
3044 return NULL;
3045}
3046
3047
yanbzhu488a4d22015-12-01 15:16:07 -05003048/* checks if a key and cert exists in the ckch
3049 */
William Lallemand1633e392019-09-30 12:58:13 +02003050#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
yanbzhu488a4d22015-12-01 15:16:07 -05003051static int ssl_sock_is_ckch_valid(struct cert_key_and_chain *ckch)
3052{
3053 return (ckch->cert != NULL && ckch->key != NULL);
3054}
William Lallemand1633e392019-09-30 12:58:13 +02003055#endif
yanbzhu488a4d22015-12-01 15:16:07 -05003056
William Lallemandf9568fc2019-10-16 18:27:58 +02003057/*
3058 * return 0 on success or != 0 on failure
3059 */
3060static int ssl_sock_load_issuer_file_into_ckch(const char *path, char *buf, struct cert_key_and_chain *ckch, char **err)
3061{
3062 int ret = 1;
3063 BIO *in = NULL;
3064 X509 *issuer;
3065
3066 if (buf) {
3067 /* reading from a buffer */
3068 in = BIO_new_mem_buf(buf, -1);
3069 if (in == NULL) {
3070 memprintf(err, "%sCan't allocate memory\n", err && *err ? *err : "");
3071 goto end;
3072 }
3073
3074 } else {
3075 /* reading from a file */
3076 in = BIO_new(BIO_s_file());
3077 if (in == NULL)
3078 goto end;
3079
3080 if (BIO_read_filename(in, path) <= 0)
3081 goto end;
3082 }
3083
3084 issuer = PEM_read_bio_X509_AUX(in, NULL, NULL, NULL);
3085 if (!issuer) {
3086 memprintf(err, "%s'%s' cannot be read or parsed'.\n",
3087 *err ? *err : "", path);
3088 goto end;
3089 }
3090 ret = 0;
3091 ckch->ocsp_issuer = issuer;
3092
3093end:
3094
3095 ERR_clear_error();
3096 if (in)
3097 BIO_free(in);
3098
3099 return ret;
3100}
3101
William Lallemand96a9c972019-10-17 11:56:17 +02003102
3103/*
3104 * Try to load a PEM file from a <path> or a buffer <buf>
3105 * The PEM must contain at least a Private Key and a Certificate,
3106 * It could contain a DH and a certificate chain.
yanbzhu488a4d22015-12-01 15:16:07 -05003107 *
William Lallemand96a9c972019-10-17 11:56:17 +02003108 * If it failed you should not attempt to use the ckch but free it.
3109 *
3110 * Return 0 on success or != 0 on failure
yanbzhu488a4d22015-12-01 15:16:07 -05003111 */
William Lallemand96a9c972019-10-17 11:56:17 +02003112static int ssl_sock_load_pem_into_ckch(const char *path, char *buf, struct cert_key_and_chain *ckch , char **err)
yanbzhu488a4d22015-12-01 15:16:07 -05003113{
William Lallemandf11365b2019-09-19 14:25:58 +02003114 BIO *in = NULL;
yanbzhu488a4d22015-12-01 15:16:07 -05003115 int ret = 1;
Emmanuel Hocdet83cbd3c2019-10-25 11:55:03 +02003116 X509 *ca;
William Lallemand96a9c972019-10-17 11:56:17 +02003117 X509 *cert = NULL;
3118 EVP_PKEY *key = NULL;
3119 DH *dh;
3120
3121 if (buf) {
3122 /* reading from a buffer */
3123 in = BIO_new_mem_buf(buf, -1);
3124 if (in == NULL) {
3125 memprintf(err, "%sCan't allocate memory\n", err && *err ? *err : "");
3126 goto end;
3127 }
yanbzhu488a4d22015-12-01 15:16:07 -05003128
William Lallemand96a9c972019-10-17 11:56:17 +02003129 } else {
3130 /* reading from a file */
William Lallemandf11365b2019-09-19 14:25:58 +02003131 in = BIO_new(BIO_s_file());
3132 if (in == NULL)
3133 goto end;
yanbzhu488a4d22015-12-01 15:16:07 -05003134
William Lallemandf11365b2019-09-19 14:25:58 +02003135 if (BIO_read_filename(in, path) <= 0)
3136 goto end;
William Lallemandf11365b2019-09-19 14:25:58 +02003137 }
yanbzhu488a4d22015-12-01 15:16:07 -05003138
yanbzhu488a4d22015-12-01 15:16:07 -05003139 /* Read Private Key */
William Lallemand96a9c972019-10-17 11:56:17 +02003140 key = PEM_read_bio_PrivateKey(in, NULL, NULL, NULL);
3141 if (key == NULL) {
yanbzhu488a4d22015-12-01 15:16:07 -05003142 memprintf(err, "%sunable to load private key from file '%s'.\n",
William Lallemand96a9c972019-10-17 11:56:17 +02003143 err && *err ? *err : "", path);
yanbzhu488a4d22015-12-01 15:16:07 -05003144 goto end;
3145 }
3146
Emmanuel Hocdet54227d82019-07-30 17:04:01 +02003147#ifndef OPENSSL_NO_DH
William Lallemandfa892222019-07-23 16:06:08 +02003148 /* Seek back to beginning of file */
3149 if (BIO_reset(in) == -1) {
3150 memprintf(err, "%san error occurred while reading the file '%s'.\n",
3151 err && *err ? *err : "", path);
3152 goto end;
3153 }
3154
William Lallemand96a9c972019-10-17 11:56:17 +02003155 dh = PEM_read_bio_DHparams(in, NULL, NULL, NULL);
3156 /* no need to return an error there, dh is not mandatory */
3157
3158 if (dh) {
3159 if (ckch->dh)
3160 DH_free(ckch->dh);
3161 ckch->dh = dh;
3162 }
3163
Emmanuel Hocdet54227d82019-07-30 17:04:01 +02003164#endif
William Lallemandfa892222019-07-23 16:06:08 +02003165
Willy Tarreaubb137a82016-04-06 19:02:38 +02003166 /* Seek back to beginning of file */
Thierry FOURNIER / OZON.IOd44ea3f2016-10-14 00:49:21 +02003167 if (BIO_reset(in) == -1) {
3168 memprintf(err, "%san error occurred while reading the file '%s'.\n",
3169 err && *err ? *err : "", path);
3170 goto end;
3171 }
Willy Tarreaubb137a82016-04-06 19:02:38 +02003172
3173 /* Read Certificate */
William Lallemand96a9c972019-10-17 11:56:17 +02003174 cert = PEM_read_bio_X509_AUX(in, NULL, NULL, NULL);
3175 if (cert == NULL) {
Willy Tarreaubb137a82016-04-06 19:02:38 +02003176 memprintf(err, "%sunable to load certificate from file '%s'.\n",
William Lallemand96a9c972019-10-17 11:56:17 +02003177 err && *err ? *err : "", path);
Willy Tarreaubb137a82016-04-06 19:02:38 +02003178 goto end;
3179 }
3180
William Lallemand96a9c972019-10-17 11:56:17 +02003181 if (!X509_check_private_key(cert, key)) {
Emmanuel Hocdet03e09f32019-07-30 14:21:25 +02003182 memprintf(err, "%sinconsistencies between private key and certificate loaded from PEM file '%s'.\n",
William Lallemand96a9c972019-10-17 11:56:17 +02003183 err && *err ? *err : "", path);
Emmanuel Hocdet03e09f32019-07-30 14:21:25 +02003184 goto end;
3185 }
3186
William Lallemand96a9c972019-10-17 11:56:17 +02003187 /* Key and Cert are good, we can use them in the ckch */
3188 if (ckch->key) /* free the previous key */
3189 EVP_PKEY_free(ckch->key);
3190 ckch->key = key;
Emmanuel Hocdet83cbd3c2019-10-25 11:55:03 +02003191 key = NULL;
William Lallemand96a9c972019-10-17 11:56:17 +02003192
3193 if (ckch->cert) /* free the previous cert */
3194 X509_free(ckch->cert);
3195 ckch->cert = cert;
Emmanuel Hocdet83cbd3c2019-10-25 11:55:03 +02003196 cert = NULL;
William Lallemand96a9c972019-10-17 11:56:17 +02003197
3198 /* Look for a Certificate Chain */
3199 ca = PEM_read_bio_X509(in, NULL, NULL, NULL);
3200 if (ca) {
3201 /* there is a chain a in the PEM, clean the previous one in the CKCH */
3202 if (ckch->chain) /* free the previous chain */
3203 sk_X509_pop_free(ckch->chain, X509_free);
3204 ckch->chain = sk_X509_new_null();
3205 if (!sk_X509_push(ckch->chain, ca)) {
3206 X509_free(ca);
3207 goto end;
3208 }
3209 }
3210 /* look for other crt in the chain */
Emmanuel Hocdet9246f8b2018-11-30 16:00:21 +01003211 while ((ca = PEM_read_bio_X509(in, NULL, NULL, NULL)))
3212 if (!sk_X509_push(ckch->chain, ca)) {
3213 X509_free(ca);
3214 goto end;
3215 }
yanbzhu488a4d22015-12-01 15:16:07 -05003216
Emmanuel Hocdeted17f472019-10-24 18:28:33 +02003217 /* no chain */
3218 if (ckch->chain == NULL) {
3219 ckch->chain = sk_X509_new_null();
3220 }
3221
yanbzhu488a4d22015-12-01 15:16:07 -05003222 ret = ERR_get_error();
3223 if (ret && (ERR_GET_LIB(ret) != ERR_LIB_PEM && ERR_GET_REASON(ret) != PEM_R_NO_START_LINE)) {
3224 memprintf(err, "%sunable to load certificate chain from file '%s'.\n",
William Lallemand96a9c972019-10-17 11:56:17 +02003225 err && *err ? *err : "", path);
yanbzhu488a4d22015-12-01 15:16:07 -05003226 goto end;
William Lallemand246c0242019-10-11 08:59:13 +02003227 }
3228
3229 ret = 0;
3230
William Lallemand96a9c972019-10-17 11:56:17 +02003231end:
William Lallemand246c0242019-10-11 08:59:13 +02003232
3233 ERR_clear_error();
William Lallemand96a9c972019-10-17 11:56:17 +02003234 if (in)
William Lallemand246c0242019-10-11 08:59:13 +02003235 BIO_free(in);
Emmanuel Hocdet83cbd3c2019-10-25 11:55:03 +02003236 if (key)
3237 EVP_PKEY_free(key);
3238 if (cert)
3239 X509_free(cert);
William Lallemanda17f4112019-10-10 15:16:44 +02003240
William Lallemand96a9c972019-10-17 11:56:17 +02003241 return ret;
3242}
3243
3244/*
3245 * Try to load in a ckch every files related to a ckch.
3246 * (PEM, sctl, ocsp, issuer etc.)
3247 *
3248 * This function is only used to load files during the configuration parsing,
3249 * it is not used with the CLI.
3250 *
3251 * This allows us to carry the contents of the file without having to read the
3252 * file multiple times. The caller must call
3253 * ssl_sock_free_cert_key_and_chain_contents.
3254 *
3255 * returns:
3256 * 0 on Success
3257 * 1 on SSL Failure
3258 */
3259static int ssl_sock_load_files_into_ckch(const char *path, struct cert_key_and_chain *ckch, char **err)
3260{
3261 int ret = 1;
3262
3263 /* try to load the PEM */
3264 if (ssl_sock_load_pem_into_ckch(path, NULL, ckch , err) != 0) {
3265 goto end;
3266 }
3267
William Lallemanda17f4112019-10-10 15:16:44 +02003268#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
3269 /* try to load the sctl file */
3270 {
3271 char fp[MAXPATHLEN+1];
3272 struct stat st;
3273
3274 snprintf(fp, MAXPATHLEN+1, "%s.sctl", path);
3275 if (stat(fp, &st) == 0) {
William Lallemand0dfae6c2019-10-16 18:06:58 +02003276 if (ssl_sock_load_sctl_from_file(fp, NULL, ckch, err)) {
William Lallemanda17f4112019-10-10 15:16:44 +02003277 memprintf(err, "%s '%s.sctl' is present but cannot be read or parsed'.\n",
3278 *err ? *err : "", fp);
3279 ret = 1;
3280 goto end;
3281 }
3282 }
3283 }
3284#endif
yanbzhu488a4d22015-12-01 15:16:07 -05003285
William Lallemand246c0242019-10-11 08:59:13 +02003286 /* try to load an ocsp response file */
3287 {
3288 char fp[MAXPATHLEN+1];
3289 struct stat st;
3290
3291 snprintf(fp, MAXPATHLEN+1, "%s.ocsp", path);
3292 if (stat(fp, &st) == 0) {
William Lallemand3b5f3602019-10-16 18:05:05 +02003293 if (ssl_sock_load_ocsp_response_from_file(fp, NULL, ckch, err)) {
William Lallemand246c0242019-10-11 08:59:13 +02003294 ret = 1;
3295 goto end;
3296 }
3297 }
3298 }
3299
Emmanuel Hocdeteaad5cc2019-10-25 12:19:00 +02003300#ifndef OPENSSL_IS_BORINGSSL /* Useless for BoringSSL */
William Lallemand246c0242019-10-11 08:59:13 +02003301 if (ckch->ocsp_response) {
3302 X509 *issuer;
3303 int i;
3304
3305 /* check if one of the certificate of the chain is the issuer */
3306 for (i = 0; i < sk_X509_num(ckch->chain); i++) {
3307 issuer = sk_X509_value(ckch->chain, i);
3308 if (X509_check_issued(issuer, ckch->cert) == X509_V_OK) {
3309 ckch->ocsp_issuer = issuer;
3310 break;
3311 } else
3312 issuer = NULL;
3313 }
3314
3315 /* if no issuer was found, try to load an issuer from the .issuer */
3316 if (!issuer) {
3317 struct stat st;
3318 char fp[MAXPATHLEN+1];
3319
3320 snprintf(fp, MAXPATHLEN+1, "%s.issuer", path);
3321 if (stat(fp, &st) == 0) {
William Lallemandf9568fc2019-10-16 18:27:58 +02003322 if (ssl_sock_load_issuer_file_into_ckch(fp, NULL, ckch, err)) {
William Lallemand246c0242019-10-11 08:59:13 +02003323 ret = 1;
3324 goto end;
3325 }
3326
3327 if (X509_check_issued(ckch->ocsp_issuer, ckch->cert) != X509_V_OK) {
William Lallemand786188f2019-10-15 10:05:37 +02003328 memprintf(err, "%s '%s' is not an issuer'.\n",
William Lallemand246c0242019-10-11 08:59:13 +02003329 *err ? *err : "", fp);
3330 ret = 1;
3331 goto end;
3332 }
3333 } else {
3334 memprintf(err, "%sNo issuer found, cannot use the OCSP response'.\n",
3335 *err ? *err : "");
3336 ret = 1;
3337 goto end;
3338 }
3339 }
3340 }
Emmanuel Hocdeteaad5cc2019-10-25 12:19:00 +02003341#endif
William Lallemand246c0242019-10-11 08:59:13 +02003342
yanbzhu488a4d22015-12-01 15:16:07 -05003343 ret = 0;
3344
3345end:
3346
3347 ERR_clear_error();
yanbzhu488a4d22015-12-01 15:16:07 -05003348
3349 /* Something went wrong in one of the reads */
3350 if (ret != 0)
3351 ssl_sock_free_cert_key_and_chain_contents(ckch);
3352
3353 return ret;
3354}
3355
3356/* Loads the info in ckch into ctx
Emeric Bruna96b5822019-10-17 13:25:14 +02003357 * Returns a bitfield containing the flags:
3358 * ERR_FATAL in any fatal error case
3359 * ERR_ALERT if the reason of the error is available in err
3360 * ERR_WARN if a warning is available into err
3361 * The value 0 means there is no error nor warning and
3362 * the operation succeed.
yanbzhu488a4d22015-12-01 15:16:07 -05003363 */
3364static int ssl_sock_put_ckch_into_ctx(const char *path, const struct cert_key_and_chain *ckch, SSL_CTX *ctx, char **err)
3365{
Emeric Bruna96b5822019-10-17 13:25:14 +02003366 int errcode = 0;
3367
yanbzhu488a4d22015-12-01 15:16:07 -05003368 if (SSL_CTX_use_PrivateKey(ctx, ckch->key) <= 0) {
3369 memprintf(err, "%sunable to load SSL private key into SSL Context '%s'.\n",
3370 err && *err ? *err : "", path);
Emeric Bruna96b5822019-10-17 13:25:14 +02003371 errcode |= ERR_ALERT | ERR_FATAL;
3372 return errcode;
yanbzhu488a4d22015-12-01 15:16:07 -05003373 }
3374
3375 if (!SSL_CTX_use_certificate(ctx, ckch->cert)) {
3376 memprintf(err, "%sunable to load SSL certificate into SSL Context '%s'.\n",
3377 err && *err ? *err : "", path);
Emeric Bruna96b5822019-10-17 13:25:14 +02003378 errcode |= ERR_ALERT | ERR_FATAL;
3379 goto end;
yanbzhu488a4d22015-12-01 15:16:07 -05003380 }
3381
yanbzhu488a4d22015-12-01 15:16:07 -05003382 /* Load all certs in the ckch into the ctx_chain for the ssl_ctx */
Emmanuel Hocdet1c65fdd2018-12-03 18:07:44 +01003383#ifdef SSL_CTX_set1_chain
Emmanuel Hocdet9246f8b2018-11-30 16:00:21 +01003384 if (!SSL_CTX_set1_chain(ctx, ckch->chain)) {
3385 memprintf(err, "%sunable to load chain certificate into SSL Context '%s'. Make sure you are linking against Openssl >= 1.0.2.\n",
3386 err && *err ? *err : "", path);
Emeric Bruna96b5822019-10-17 13:25:14 +02003387 errcode |= ERR_ALERT | ERR_FATAL;
3388 goto end;
yanbzhu488a4d22015-12-01 15:16:07 -05003389 }
Emmanuel Hocdet1c65fdd2018-12-03 18:07:44 +01003390#else
3391 { /* legacy compat (< openssl 1.0.2) */
3392 X509 *ca;
3393 while ((ca = sk_X509_shift(ckch->chain)))
3394 if (!SSL_CTX_add_extra_chain_cert(ctx, ca)) {
3395 memprintf(err, "%sunable to load chain certificate into SSL Context '%s'.\n",
3396 err && *err ? *err : "", path);
3397 X509_free(ca);
Emeric Bruna96b5822019-10-17 13:25:14 +02003398 errcode |= ERR_ALERT | ERR_FATAL;
3399 goto end;
Emmanuel Hocdet1c65fdd2018-12-03 18:07:44 +01003400 }
3401 }
3402#endif
yanbzhu488a4d22015-12-01 15:16:07 -05003403
William Lallemandfa892222019-07-23 16:06:08 +02003404#ifndef OPENSSL_NO_DH
3405 /* store a NULL pointer to indicate we have not yet loaded
3406 a custom DH param file */
3407 if (ssl_dh_ptr_index >= 0) {
3408 SSL_CTX_set_ex_data(ctx, ssl_dh_ptr_index, NULL);
3409 }
3410
Emeric Brun7a883362019-10-17 13:27:40 +02003411 errcode |= ssl_sock_load_dh_params(ctx, ckch, path, err);
3412 if (errcode & ERR_CODE) {
William Lallemandfa892222019-07-23 16:06:08 +02003413 memprintf(err, "%sunable to load DH parameters from file '%s'.\n",
3414 err && *err ? *err : "", path);
Emeric Bruna96b5822019-10-17 13:25:14 +02003415 goto end;
William Lallemandfa892222019-07-23 16:06:08 +02003416 }
3417#endif
3418
William Lallemanda17f4112019-10-10 15:16:44 +02003419#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
3420 if (sctl_ex_index >= 0 && ckch->sctl) {
3421 if (ssl_sock_load_sctl(ctx, ckch->sctl) < 0) {
3422 memprintf(err, "%s '%s.sctl' is present but cannot be read or parsed'.\n",
3423 *err ? *err : "", path);
Emeric Bruna96b5822019-10-17 13:25:14 +02003424 errcode |= ERR_ALERT | ERR_FATAL;
3425 goto end;
William Lallemanda17f4112019-10-10 15:16:44 +02003426 }
3427 }
3428#endif
3429
William Lallemand4a660132019-10-14 14:51:41 +02003430#if ((defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP) || defined OPENSSL_IS_BORINGSSL)
William Lallemand246c0242019-10-11 08:59:13 +02003431 /* Load OCSP Info into context */
3432 if (ckch->ocsp_response) {
3433 if (ssl_sock_load_ocsp(ctx, ckch) < 0) {
3434 if (err)
3435 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",
3436 *err ? *err : "", path);
Emeric Bruna96b5822019-10-17 13:25:14 +02003437 errcode |= ERR_ALERT | ERR_FATAL;
3438 goto end;
William Lallemand246c0242019-10-11 08:59:13 +02003439 }
3440 }
William Lallemand246c0242019-10-11 08:59:13 +02003441#endif
3442
Emeric Bruna96b5822019-10-17 13:25:14 +02003443 end:
3444 return errcode;
yanbzhu488a4d22015-12-01 15:16:07 -05003445}
3446
William Lallemandc4ecddf2019-07-31 16:50:08 +02003447#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
yanbzhu08ce6ab2015-12-02 13:01:29 -05003448
William Lallemand28a8fce2019-10-04 17:36:55 +02003449static int ssl_sock_populate_sni_keytypes_hplr(const char *str, struct eb_root *sni_keytypes, int key_index)
yanbzhu08ce6ab2015-12-02 13:01:29 -05003450{
3451 struct sni_keytype *s_kt = NULL;
3452 struct ebmb_node *node;
3453 int i;
3454
3455 for (i = 0; i < trash.size; i++) {
3456 if (!str[i])
3457 break;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02003458 trash.area[i] = tolower(str[i]);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003459 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +02003460 trash.area[i] = 0;
3461 node = ebst_lookup(sni_keytypes, trash.area);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003462 if (!node) {
3463 /* CN not found in tree */
3464 s_kt = malloc(sizeof(struct sni_keytype) + i + 1);
3465 /* Using memcpy here instead of strncpy.
3466 * strncpy will cause sig_abrt errors under certain versions of gcc with -O2
3467 * See: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=60792
3468 */
William Lallemand28a8fce2019-10-04 17:36:55 +02003469 if (!s_kt)
3470 return -1;
3471
Willy Tarreau843b7cb2018-07-13 10:54:26 +02003472 memcpy(s_kt->name.key, trash.area, i+1);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003473 s_kt->keytypes = 0;
3474 ebst_insert(sni_keytypes, &s_kt->name);
3475 } else {
3476 /* CN found in tree */
3477 s_kt = container_of(node, struct sni_keytype, name);
3478 }
3479
3480 /* Mark that this CN has the keytype of key_index via keytypes mask */
3481 s_kt->keytypes |= 1<<key_index;
3482
William Lallemand28a8fce2019-10-04 17:36:55 +02003483 return 0;
3484
yanbzhu08ce6ab2015-12-02 13:01:29 -05003485}
3486
William Lallemandc4ecddf2019-07-31 16:50:08 +02003487#endif
William Lallemand8c1cdde2019-10-18 10:58:14 +02003488/*
3489 * Free a ckch_store and its ckch(s)
3490 * The linked ckch_inst are not free'd
3491 */
3492void ckchs_free(struct ckch_store *ckchs)
3493{
3494 if (!ckchs)
3495 return;
3496
3497#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
3498 if (ckchs->multi) {
3499 int n;
3500
3501 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++)
3502 ssl_sock_free_cert_key_and_chain_contents(&ckchs->ckch[n]);
3503 } else
3504#endif
3505 {
3506 ssl_sock_free_cert_key_and_chain_contents(ckchs->ckch);
3507 ckchs->ckch = NULL;
3508 }
3509
3510 free(ckchs);
3511}
3512
3513/* allocate and duplicate a ckch_store
3514 * Return a new ckch_store or NULL */
3515static struct ckch_store *ckchs_dup(const struct ckch_store *src)
3516{
3517 struct ckch_store *dst;
3518 int pathlen;
3519
3520 pathlen = strlen(src->path);
3521 dst = calloc(1, sizeof(*dst) + pathlen + 1);
3522 if (!dst)
3523 return NULL;
3524 /* copy previous key */
3525 memcpy(dst->path, src->path, pathlen + 1);
3526 dst->multi = src->multi;
3527 LIST_INIT(&dst->ckch_inst);
3528
3529 dst->ckch = calloc((src->multi ? SSL_SOCK_NUM_KEYTYPES : 1), sizeof(*dst->ckch));
3530 if (!dst->ckch)
3531 goto error;
3532
3533#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
3534 if (src->multi) {
3535 int n;
3536
3537 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
3538 if (&src->ckch[n]) {
3539 if (!ssl_sock_copy_cert_key_and_chain(&src->ckch[n], &dst->ckch[n]))
3540 goto error;
3541 }
3542 }
3543 } else
3544#endif
3545 {
3546 if (!ssl_sock_copy_cert_key_and_chain(src->ckch, dst->ckch))
3547 goto error;
3548 }
3549
3550 return dst;
3551
3552error:
3553 ckchs_free(dst);
3554
3555 return NULL;
3556}
William Lallemandc4ecddf2019-07-31 16:50:08 +02003557
William Lallemand36b84632019-07-18 19:28:17 +02003558/*
William Lallemande3af8fb2019-10-08 11:36:53 +02003559 * lookup a path into the ckchs tree.
William Lallemand6af03992019-07-23 15:00:54 +02003560 */
William Lallemande3af8fb2019-10-08 11:36:53 +02003561static inline struct ckch_store *ckchs_lookup(char *path)
William Lallemand6af03992019-07-23 15:00:54 +02003562{
3563 struct ebmb_node *eb;
3564
William Lallemande3af8fb2019-10-08 11:36:53 +02003565 eb = ebst_lookup(&ckchs_tree, path);
William Lallemand6af03992019-07-23 15:00:54 +02003566 if (!eb)
3567 return NULL;
3568
William Lallemande3af8fb2019-10-08 11:36:53 +02003569 return ebmb_entry(eb, struct ckch_store, node);
William Lallemand6af03992019-07-23 15:00:54 +02003570}
3571
3572/*
William Lallemande3af8fb2019-10-08 11:36:53 +02003573 * This function allocate a ckch_store and populate it with certificates from files.
William Lallemand36b84632019-07-18 19:28:17 +02003574 */
William Lallemande3af8fb2019-10-08 11:36:53 +02003575static struct ckch_store *ckchs_load_cert_file(char *path, int multi, char **err)
William Lallemand36b84632019-07-18 19:28:17 +02003576{
William Lallemande3af8fb2019-10-08 11:36:53 +02003577 struct ckch_store *ckchs;
William Lallemand36b84632019-07-18 19:28:17 +02003578
William Lallemande3af8fb2019-10-08 11:36:53 +02003579 ckchs = calloc(1, sizeof(*ckchs) + strlen(path) + 1);
3580 if (!ckchs) {
William Lallemand36b84632019-07-18 19:28:17 +02003581 memprintf(err, "%sunable to allocate memory.\n", err && *err ? *err : "");
3582 goto end;
3583 }
William Lallemande3af8fb2019-10-08 11:36:53 +02003584 ckchs->ckch = calloc(1, sizeof(*ckchs->ckch) * (multi ? SSL_SOCK_NUM_KEYTYPES : 1));
William Lallemand36b84632019-07-18 19:28:17 +02003585
William Lallemande3af8fb2019-10-08 11:36:53 +02003586 if (!ckchs->ckch) {
William Lallemand36b84632019-07-18 19:28:17 +02003587 memprintf(err, "%sunable to allocate memory.\n", err && *err ? *err : "");
3588 goto end;
3589 }
3590
William Lallemand9117de92019-10-04 00:29:42 +02003591 LIST_INIT(&ckchs->ckch_inst);
3592
William Lallemand36b84632019-07-18 19:28:17 +02003593 if (!multi) {
3594
William Lallemand96a9c972019-10-17 11:56:17 +02003595 if (ssl_sock_load_files_into_ckch(path, ckchs->ckch, err) == 1)
William Lallemand36b84632019-07-18 19:28:17 +02003596 goto end;
3597
William Lallemande3af8fb2019-10-08 11:36:53 +02003598 /* insert into the ckchs tree */
3599 memcpy(ckchs->path, path, strlen(path) + 1);
3600 ebst_insert(&ckchs_tree, &ckchs->node);
William Lallemand36b84632019-07-18 19:28:17 +02003601 } else {
3602 int found = 0;
William Lallemandc4ecddf2019-07-31 16:50:08 +02003603#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
3604 char fp[MAXPATHLEN+1] = {0};
3605 int n = 0;
William Lallemand36b84632019-07-18 19:28:17 +02003606
3607 /* Load all possible certs and keys */
3608 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
3609 struct stat buf;
3610 snprintf(fp, sizeof(fp), "%s.%s", path, SSL_SOCK_KEYTYPE_NAMES[n]);
3611 if (stat(fp, &buf) == 0) {
William Lallemand96a9c972019-10-17 11:56:17 +02003612 if (ssl_sock_load_files_into_ckch(fp, &ckchs->ckch[n], err) == 1)
William Lallemand36b84632019-07-18 19:28:17 +02003613 goto end;
3614 found = 1;
William Lallemande3af8fb2019-10-08 11:36:53 +02003615 ckchs->multi = 1;
William Lallemand36b84632019-07-18 19:28:17 +02003616 }
3617 }
William Lallemandc4ecddf2019-07-31 16:50:08 +02003618#endif
William Lallemand36b84632019-07-18 19:28:17 +02003619
3620 if (!found) {
William Lallemand6e5f2ce2019-08-01 14:43:20 +02003621 memprintf(err, "%sDidn't find any certificate for bundle '%s'.\n", err && *err ? *err : "", path);
William Lallemand36b84632019-07-18 19:28:17 +02003622 goto end;
3623 }
William Lallemande3af8fb2019-10-08 11:36:53 +02003624 /* insert into the ckchs tree */
3625 memcpy(ckchs->path, path, strlen(path) + 1);
3626 ebst_insert(&ckchs_tree, &ckchs->node);
William Lallemand36b84632019-07-18 19:28:17 +02003627 }
William Lallemande3af8fb2019-10-08 11:36:53 +02003628 return ckchs;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003629
William Lallemand36b84632019-07-18 19:28:17 +02003630end:
William Lallemande3af8fb2019-10-08 11:36:53 +02003631 if (ckchs) {
3632 free(ckchs->ckch);
3633 ebmb_delete(&ckchs->node);
William Lallemand6af03992019-07-23 15:00:54 +02003634 }
3635
William Lallemande3af8fb2019-10-08 11:36:53 +02003636 free(ckchs);
William Lallemand36b84632019-07-18 19:28:17 +02003637
3638 return NULL;
3639}
3640
William Lallemandc4ecddf2019-07-31 16:50:08 +02003641#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
3642
William Lallemand36b84632019-07-18 19:28:17 +02003643/*
William Lallemande3af8fb2019-10-08 11:36:53 +02003644 * Take a ckch_store which contains a multi-certificate bundle.
William Lallemand36b84632019-07-18 19:28:17 +02003645 * Group these certificates into a set of SSL_CTX*
yanbzhu08ce6ab2015-12-02 13:01:29 -05003646 * based on shared and unique CN and SAN entries. Add these SSL_CTX* to the SNI tree.
3647 *
Joseph Herlant017b3da2018-11-15 09:07:59 -08003648 * This will allow the user to explicitly group multiple cert/keys for a single purpose
yanbzhu08ce6ab2015-12-02 13:01:29 -05003649 *
Emeric Brun054563d2019-10-17 13:16:58 +02003650 * Returns a bitfield containing the flags:
3651 * ERR_FATAL in any fatal error case
3652 * ERR_ALERT if the reason of the error is available in err
3653 * ERR_WARN if a warning is available into err
William Lallemand36b84632019-07-18 19:28:17 +02003654 *
yanbzhu08ce6ab2015-12-02 13:01:29 -05003655 */
Emeric Brun054563d2019-10-17 13:16:58 +02003656static int ckch_inst_new_load_multi_store(const char *path, struct ckch_store *ckchs,
3657 struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
3658 char **sni_filter, int fcount, struct ckch_inst **ckchi, char **err)
yanbzhu08ce6ab2015-12-02 13:01:29 -05003659{
William Lallemand36b84632019-07-18 19:28:17 +02003660 int i = 0, n = 0;
3661 struct cert_key_and_chain *certs_and_keys;
William Lallemand4b989f22019-10-04 18:36:55 +02003662 struct eb_root sni_keytypes_map = EB_ROOT;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003663 struct ebmb_node *node;
3664 struct ebmb_node *next;
3665 /* Array of SSL_CTX pointers corresponding to each possible combo
3666 * of keytypes
3667 */
3668 struct key_combo_ctx key_combos[SSL_SOCK_POSSIBLE_KT_COMBOS] = { {0} };
Emeric Brun054563d2019-10-17 13:16:58 +02003669 int errcode = 0;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003670 X509_NAME *xname = NULL;
3671 char *str = NULL;
3672#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
3673 STACK_OF(GENERAL_NAME) *names = NULL;
3674#endif
William Lallemand614ca0d2019-10-07 13:52:11 +02003675 struct ckch_inst *ckch_inst;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003676
Emeric Brun054563d2019-10-17 13:16:58 +02003677 *ckchi = NULL;
3678
William Lallemande3af8fb2019-10-08 11:36:53 +02003679 if (!ckchs || !ckchs->ckch || !ckchs->multi) {
William Lallemand36b84632019-07-18 19:28:17 +02003680 memprintf(err, "%sunable to load SSL certificate file '%s' file does not exist.\n",
3681 err && *err ? *err : "", path);
Emeric Brun054563d2019-10-17 13:16:58 +02003682 return ERR_ALERT | ERR_FATAL;
William Lallemand614ca0d2019-10-07 13:52:11 +02003683 }
3684
3685 ckch_inst = ckch_inst_new();
3686 if (!ckch_inst) {
3687 memprintf(err, "%sunable to allocate SSL context for cert '%s'.\n",
3688 err && *err ? *err : "", path);
Emeric Brun054563d2019-10-17 13:16:58 +02003689 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemand614ca0d2019-10-07 13:52:11 +02003690 goto end;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003691 }
3692
William Lallemande3af8fb2019-10-08 11:36:53 +02003693 certs_and_keys = ckchs->ckch;
William Lallemand36b84632019-07-18 19:28:17 +02003694
William Lallemand150bfa82019-09-19 17:12:49 +02003695 /* at least one of the instances is using filters during the config
3696 * parsing, that's ok to inherit this during loading on CLI */
3697 ckchs->filters = !!fcount;
3698
yanbzhu08ce6ab2015-12-02 13:01:29 -05003699 /* Process each ckch and update keytypes for each CN/SAN
3700 * for example, if CN/SAN www.a.com is associated with
3701 * certs with keytype 0 and 2, then at the end of the loop,
3702 * www.a.com will have:
3703 * keyindex = 0 | 1 | 4 = 5
3704 */
3705 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
William Lallemand28a8fce2019-10-04 17:36:55 +02003706 int ret;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003707
3708 if (!ssl_sock_is_ckch_valid(&certs_and_keys[n]))
3709 continue;
3710
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003711 if (fcount) {
William Lallemand28a8fce2019-10-04 17:36:55 +02003712 for (i = 0; i < fcount; i++) {
3713 ret = ssl_sock_populate_sni_keytypes_hplr(sni_filter[i], &sni_keytypes_map, n);
3714 if (ret < 0) {
3715 memprintf(err, "%sunable to allocate SSL context.\n",
3716 err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02003717 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemand28a8fce2019-10-04 17:36:55 +02003718 goto end;
3719 }
3720 }
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003721 } else {
3722 /* A lot of the following code is OpenSSL boilerplate for processing CN's and SAN's,
3723 * so the line that contains logic is marked via comments
3724 */
3725 xname = X509_get_subject_name(certs_and_keys[n].cert);
3726 i = -1;
3727 while ((i = X509_NAME_get_index_by_NID(xname, NID_commonName, i)) != -1) {
3728 X509_NAME_ENTRY *entry = X509_NAME_get_entry(xname, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003729 ASN1_STRING *value;
3730 value = X509_NAME_ENTRY_get_data(entry);
3731 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003732 /* Important line is here */
William Lallemand28a8fce2019-10-04 17:36:55 +02003733 ret = ssl_sock_populate_sni_keytypes_hplr(str, &sni_keytypes_map, n);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003734
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003735 OPENSSL_free(str);
3736 str = NULL;
William Lallemand28a8fce2019-10-04 17:36:55 +02003737 if (ret < 0) {
3738 memprintf(err, "%sunable to allocate SSL context.\n",
3739 err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02003740 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemand28a8fce2019-10-04 17:36:55 +02003741 goto end;
3742 }
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003743 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003744 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003745
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003746 /* Do the above logic for each SAN */
yanbzhu08ce6ab2015-12-02 13:01:29 -05003747#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003748 names = X509_get_ext_d2i(certs_and_keys[n].cert, NID_subject_alt_name, NULL, NULL);
3749 if (names) {
3750 for (i = 0; i < sk_GENERAL_NAME_num(names); i++) {
3751 GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003752
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003753 if (name->type == GEN_DNS) {
3754 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
3755 /* Important line is here */
William Lallemand28a8fce2019-10-04 17:36:55 +02003756 ret = ssl_sock_populate_sni_keytypes_hplr(str, &sni_keytypes_map, n);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003757
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003758 OPENSSL_free(str);
3759 str = NULL;
William Lallemand28a8fce2019-10-04 17:36:55 +02003760 if (ret < 0) {
3761 memprintf(err, "%sunable to allocate SSL context.\n",
3762 err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02003763 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemand28a8fce2019-10-04 17:36:55 +02003764 goto end;
3765 }
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003766 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003767 }
3768 }
3769 }
3770 }
3771#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
3772 }
3773
3774 /* If no files found, return error */
3775 if (eb_is_empty(&sni_keytypes_map)) {
3776 memprintf(err, "%sunable to load SSL certificate file '%s' file does not exist.\n",
3777 err && *err ? *err : "", path);
Emeric Brun054563d2019-10-17 13:16:58 +02003778 errcode |= ERR_ALERT | ERR_FATAL;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003779 goto end;
3780 }
3781
3782 /* We now have a map of CN/SAN to keytypes that are loaded in
3783 * Iterate through the map to create the SSL_CTX's (if needed)
3784 * and add each CTX to the SNI tree
3785 *
3786 * Some math here:
Joseph Herlant017b3da2018-11-15 09:07:59 -08003787 * There are 2^n - 1 possible combinations, each unique
yanbzhu08ce6ab2015-12-02 13:01:29 -05003788 * combination is denoted by the key in the map. Each key
3789 * has a value between 1 and 2^n - 1. Conveniently, the array
3790 * of SSL_CTX* is sized 2^n. So, we can simply use the i'th
3791 * entry in the array to correspond to the unique combo (key)
3792 * associated with i. This unique key combo (i) will be associated
3793 * with combos[i-1]
3794 */
3795
3796 node = ebmb_first(&sni_keytypes_map);
3797 while (node) {
3798 SSL_CTX *cur_ctx;
Bertrand Jacquin33423092016-11-13 16:37:13 +00003799 char cur_file[MAXPATHLEN+1];
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003800 const struct pkey_info kinfo = { .sig = TLSEXT_signature_anonymous, .bits = 0 };
yanbzhu08ce6ab2015-12-02 13:01:29 -05003801
3802 str = (char *)container_of(node, struct sni_keytype, name)->name.key;
3803 i = container_of(node, struct sni_keytype, name)->keytypes;
3804 cur_ctx = key_combos[i-1].ctx;
3805
3806 if (cur_ctx == NULL) {
3807 /* need to create SSL_CTX */
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003808 cur_ctx = SSL_CTX_new(SSLv23_server_method());
yanbzhu08ce6ab2015-12-02 13:01:29 -05003809 if (cur_ctx == NULL) {
3810 memprintf(err, "%sunable to allocate SSL context.\n",
3811 err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02003812 errcode |= ERR_ALERT | ERR_FATAL;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003813 goto end;
3814 }
3815
yanbzhube2774d2015-12-10 15:07:30 -05003816 /* Load all required certs/keys/chains/OCSPs info into SSL_CTX */
yanbzhu08ce6ab2015-12-02 13:01:29 -05003817 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
3818 if (i & (1<<n)) {
3819 /* Key combo contains ckch[n] */
Bertrand Jacquin33423092016-11-13 16:37:13 +00003820 snprintf(cur_file, MAXPATHLEN+1, "%s.%s", path, SSL_SOCK_KEYTYPE_NAMES[n]);
Emeric Bruna96b5822019-10-17 13:25:14 +02003821 errcode |= ssl_sock_put_ckch_into_ctx(cur_file, &certs_and_keys[n], cur_ctx, err);
3822 if (errcode & ERR_CODE)
yanbzhu08ce6ab2015-12-02 13:01:29 -05003823 goto end;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003824 }
3825 }
3826
yanbzhu08ce6ab2015-12-02 13:01:29 -05003827 /* Update key_combos */
3828 key_combos[i-1].ctx = cur_ctx;
3829 }
3830
3831 /* Update SNI Tree */
William Lallemand9117de92019-10-04 00:29:42 +02003832
William Lallemand1d29c742019-10-04 00:53:29 +02003833 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 +02003834 kinfo, str, key_combos[i-1].order);
3835 if (key_combos[i-1].order < 0) {
3836 memprintf(err, "%sunable to create a sni context.\n", err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02003837 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemandfe49bb32019-10-03 23:46:33 +02003838 goto end;
3839 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003840 node = ebmb_next(node);
3841 }
3842
3843
3844 /* Mark a default context if none exists, using the ctx that has the most shared keys */
3845 if (!bind_conf->default_ctx) {
3846 for (i = SSL_SOCK_POSSIBLE_KT_COMBOS - 1; i >= 0; i--) {
3847 if (key_combos[i].ctx) {
3848 bind_conf->default_ctx = key_combos[i].ctx;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003849 bind_conf->default_ssl_conf = ssl_conf;
William Lallemand21724f02019-11-04 17:56:13 +01003850 ckch_inst->is_default = 1;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003851 break;
3852 }
3853 }
3854 }
3855
William Lallemand614ca0d2019-10-07 13:52:11 +02003856 ckch_inst->bind_conf = bind_conf;
William Lallemand150bfa82019-09-19 17:12:49 +02003857 ckch_inst->ssl_conf = ssl_conf;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003858end:
3859
3860 if (names)
3861 sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
3862
yanbzhu08ce6ab2015-12-02 13:01:29 -05003863 node = ebmb_first(&sni_keytypes_map);
3864 while (node) {
3865 next = ebmb_next(node);
3866 ebmb_delete(node);
William Lallemand8ed5b962019-10-04 17:24:39 +02003867 free(ebmb_entry(node, struct sni_keytype, name));
yanbzhu08ce6ab2015-12-02 13:01:29 -05003868 node = next;
3869 }
3870
Emeric Brun054563d2019-10-17 13:16:58 +02003871 if (errcode & ERR_CODE && ckch_inst) {
William Lallemand0c6d12f2019-10-04 18:38:51 +02003872 struct sni_ctx *sc0, *sc0b;
3873
3874 /* free the SSL_CTX in case of error */
3875 for (i = 0; i < SSL_SOCK_POSSIBLE_KT_COMBOS; i++) {
3876 if (key_combos[i].ctx)
3877 SSL_CTX_free(key_combos[i].ctx);
3878 }
3879
3880 /* free the sni_ctx in case of error */
3881 list_for_each_entry_safe(sc0, sc0b, &ckch_inst->sni_ctx, by_ckch_inst) {
3882
3883 ebmb_delete(&sc0->name);
3884 LIST_DEL(&sc0->by_ckch_inst);
3885 free(sc0);
3886 }
William Lallemand614ca0d2019-10-07 13:52:11 +02003887 free(ckch_inst);
3888 ckch_inst = NULL;
William Lallemand0c6d12f2019-10-04 18:38:51 +02003889 }
3890
Emeric Brun054563d2019-10-17 13:16:58 +02003891 *ckchi = ckch_inst;
3892 return errcode;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003893}
3894#else
3895/* This is a dummy, that just logs an error and returns error */
Emeric Brun054563d2019-10-17 13:16:58 +02003896static int ckch_inst_new_load_multi_store(const char *path, struct ckch_store *ckchs,
3897 struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
3898 char **sni_filter, int fcount, struct ckch_inst **ckchi, char **err)
yanbzhu08ce6ab2015-12-02 13:01:29 -05003899{
3900 memprintf(err, "%sunable to stat SSL certificate from file '%s' : %s.\n",
3901 err && *err ? *err : "", path, strerror(errno));
Emeric Brun054563d2019-10-17 13:16:58 +02003902 return ERR_ALERT | ERR_FATAL;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003903}
3904
Willy Tarreau9a1ab082019-05-09 13:26:41 +02003905#endif /* #if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL: Support for loading multiple certs into a single SSL_CTX */
yanbzhu488a4d22015-12-01 15:16:07 -05003906
William Lallemand614ca0d2019-10-07 13:52:11 +02003907/*
3908 * This function allocate a ckch_inst and create its snis
Emeric Brun054563d2019-10-17 13:16:58 +02003909 *
3910 * Returns a bitfield containing the flags:
3911 * ERR_FATAL in any fatal error case
3912 * ERR_ALERT if the reason of the error is available in err
3913 * ERR_WARN if a warning is available into err
William Lallemand614ca0d2019-10-07 13:52:11 +02003914 */
Emeric Brun054563d2019-10-17 13:16:58 +02003915static int ckch_inst_new_load_store(const char *path, struct ckch_store *ckchs, struct bind_conf *bind_conf,
3916 struct ssl_bind_conf *ssl_conf, char **sni_filter, int fcount, struct ckch_inst **ckchi, char **err)
Emeric Brunfc0421f2012-09-07 17:30:07 +02003917{
William Lallemandc9402072019-05-15 15:33:54 +02003918 SSL_CTX *ctx;
William Lallemandc9402072019-05-15 15:33:54 +02003919 int i;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003920 int order = 0;
3921 X509_NAME *xname;
3922 char *str;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003923 EVP_PKEY *pkey;
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003924 struct pkey_info kinfo = { .sig = TLSEXT_signature_anonymous, .bits = 0 };
Emeric Brunfc0421f2012-09-07 17:30:07 +02003925#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
3926 STACK_OF(GENERAL_NAME) *names;
3927#endif
William Lallemand36b84632019-07-18 19:28:17 +02003928 struct cert_key_and_chain *ckch;
William Lallemand614ca0d2019-10-07 13:52:11 +02003929 struct ckch_inst *ckch_inst = NULL;
Emeric Brun054563d2019-10-17 13:16:58 +02003930 int errcode = 0;
3931
3932 *ckchi = NULL;
William Lallemanda59191b2019-05-15 16:08:56 +02003933
William Lallemande3af8fb2019-10-08 11:36:53 +02003934 if (!ckchs || !ckchs->ckch)
Emeric Brun054563d2019-10-17 13:16:58 +02003935 return ERR_FATAL;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003936
William Lallemande3af8fb2019-10-08 11:36:53 +02003937 ckch = ckchs->ckch;
William Lallemand36b84632019-07-18 19:28:17 +02003938
William Lallemand150bfa82019-09-19 17:12:49 +02003939 /* at least one of the instances is using filters during the config
3940 * parsing, that's ok to inherit this during loading on CLI */
3941 ckchs->filters = !!fcount;
3942
William Lallemandc9402072019-05-15 15:33:54 +02003943 ctx = SSL_CTX_new(SSLv23_server_method());
3944 if (!ctx) {
3945 memprintf(err, "%sunable to allocate SSL context for cert '%s'.\n",
3946 err && *err ? *err : "", path);
Emeric Brun054563d2019-10-17 13:16:58 +02003947 errcode |= ERR_ALERT | ERR_FATAL;
3948 goto error;
William Lallemandc9402072019-05-15 15:33:54 +02003949 }
3950
Emeric Bruna96b5822019-10-17 13:25:14 +02003951 errcode |= ssl_sock_put_ckch_into_ctx(path, ckch, ctx, err);
3952 if (errcode & ERR_CODE)
William Lallemand614ca0d2019-10-07 13:52:11 +02003953 goto error;
William Lallemand614ca0d2019-10-07 13:52:11 +02003954
3955 ckch_inst = ckch_inst_new();
3956 if (!ckch_inst) {
3957 memprintf(err, "%sunable to allocate SSL context for cert '%s'.\n",
3958 err && *err ? *err : "", path);
Emeric Brun054563d2019-10-17 13:16:58 +02003959 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemandd9199372019-10-04 15:37:05 +02003960 goto error;
William Lallemandc9402072019-05-15 15:33:54 +02003961 }
3962
William Lallemand36b84632019-07-18 19:28:17 +02003963 pkey = X509_get_pubkey(ckch->cert);
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003964 if (pkey) {
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003965 kinfo.bits = EVP_PKEY_bits(pkey);
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003966 switch(EVP_PKEY_base_id(pkey)) {
3967 case EVP_PKEY_RSA:
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003968 kinfo.sig = TLSEXT_signature_rsa;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003969 break;
3970 case EVP_PKEY_EC:
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003971 kinfo.sig = TLSEXT_signature_ecdsa;
3972 break;
3973 case EVP_PKEY_DSA:
3974 kinfo.sig = TLSEXT_signature_dsa;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003975 break;
3976 }
3977 EVP_PKEY_free(pkey);
3978 }
3979
Emeric Brun50bcecc2013-04-22 13:05:23 +02003980 if (fcount) {
William Lallemandfe49bb32019-10-03 23:46:33 +02003981 while (fcount--) {
William Lallemand1d29c742019-10-04 00:53:29 +02003982 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 +02003983 if (order < 0) {
3984 memprintf(err, "%sunable to create a sni context.\n", err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02003985 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemandd9199372019-10-04 15:37:05 +02003986 goto error;
William Lallemandfe49bb32019-10-03 23:46:33 +02003987 }
3988 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003989 }
3990 else {
Emeric Brunfc0421f2012-09-07 17:30:07 +02003991#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
William Lallemand36b84632019-07-18 19:28:17 +02003992 names = X509_get_ext_d2i(ckch->cert, NID_subject_alt_name, NULL, NULL);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003993 if (names) {
3994 for (i = 0; i < sk_GENERAL_NAME_num(names); i++) {
3995 GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i);
3996 if (name->type == GEN_DNS) {
3997 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
William Lallemand1d29c742019-10-04 00:53:29 +02003998 order = ckch_inst_add_cert_sni(ctx, ckch_inst, bind_conf, ssl_conf, kinfo, str, order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003999 OPENSSL_free(str);
William Lallemandfe49bb32019-10-03 23:46:33 +02004000 if (order < 0) {
4001 memprintf(err, "%sunable to create a sni context.\n", err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02004002 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemandd9199372019-10-04 15:37:05 +02004003 goto error;
William Lallemandfe49bb32019-10-03 23:46:33 +02004004 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004005 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004006 }
4007 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004008 sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004009 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004010#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
William Lallemand36b84632019-07-18 19:28:17 +02004011 xname = X509_get_subject_name(ckch->cert);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004012 i = -1;
4013 while ((i = X509_NAME_get_index_by_NID(xname, NID_commonName, i)) != -1) {
4014 X509_NAME_ENTRY *entry = X509_NAME_get_entry(xname, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02004015 ASN1_STRING *value;
4016
4017 value = X509_NAME_ENTRY_get_data(entry);
4018 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
William Lallemand1d29c742019-10-04 00:53:29 +02004019 order = ckch_inst_add_cert_sni(ctx, ckch_inst, bind_conf, ssl_conf, kinfo, str, order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004020 OPENSSL_free(str);
William Lallemandfe49bb32019-10-03 23:46:33 +02004021 if (order < 0) {
4022 memprintf(err, "%sunable to create a sni context.\n", err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02004023 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemandd9199372019-10-04 15:37:05 +02004024 goto error;
William Lallemandfe49bb32019-10-03 23:46:33 +02004025 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004026 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004027 }
4028 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004029 /* we must not free the SSL_CTX anymore below, since it's already in
4030 * the tree, so it will be discovered and cleaned in time.
4031 */
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02004032
Emeric Brunfc0421f2012-09-07 17:30:07 +02004033#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004034 if (bind_conf->default_ctx) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02004035 memprintf(err, "%sthis version of openssl cannot load multiple SSL certificates.\n",
4036 err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02004037 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemandd9199372019-10-04 15:37:05 +02004038 goto error;
Emeric Brunfc0421f2012-09-07 17:30:07 +02004039 }
4040#endif
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004041 if (!bind_conf->default_ctx) {
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004042 bind_conf->default_ctx = ctx;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004043 bind_conf->default_ssl_conf = ssl_conf;
William Lallemand21724f02019-11-04 17:56:13 +01004044 ckch_inst->is_default = 1;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004045 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004046
William Lallemand9117de92019-10-04 00:29:42 +02004047 /* everything succeed, the ckch instance can be used */
4048 ckch_inst->bind_conf = bind_conf;
William Lallemand150bfa82019-09-19 17:12:49 +02004049 ckch_inst->ssl_conf = ssl_conf;
William Lallemand9117de92019-10-04 00:29:42 +02004050
Emeric Brun054563d2019-10-17 13:16:58 +02004051 *ckchi = ckch_inst;
4052 return errcode;
William Lallemandd9199372019-10-04 15:37:05 +02004053
4054error:
4055 /* free the allocated sni_ctxs */
William Lallemand614ca0d2019-10-07 13:52:11 +02004056 if (ckch_inst) {
William Lallemandd9199372019-10-04 15:37:05 +02004057 struct sni_ctx *sc0, *sc0b;
4058
4059 list_for_each_entry_safe(sc0, sc0b, &ckch_inst->sni_ctx, by_ckch_inst) {
4060
4061 ebmb_delete(&sc0->name);
4062 LIST_DEL(&sc0->by_ckch_inst);
4063 free(sc0);
4064 }
William Lallemand614ca0d2019-10-07 13:52:11 +02004065 free(ckch_inst);
4066 ckch_inst = NULL;
William Lallemandd9199372019-10-04 15:37:05 +02004067 }
4068 /* We only created 1 SSL_CTX so we can free it there */
4069 SSL_CTX_free(ctx);
4070
Emeric Brun054563d2019-10-17 13:16:58 +02004071 return errcode;
Emeric Brunfc0421f2012-09-07 17:30:07 +02004072}
4073
Willy Tarreau8c5414a2019-10-16 17:06:25 +02004074/* Returns a set of ERR_* flags possibly with an error in <err>. */
William Lallemand614ca0d2019-10-07 13:52:11 +02004075static int ssl_sock_load_ckchs(const char *path, struct ckch_store *ckchs,
4076 struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
4077 char **sni_filter, int fcount, char **err)
4078{
4079 struct ckch_inst *ckch_inst = NULL;
Emeric Brun054563d2019-10-17 13:16:58 +02004080 int errcode = 0;
William Lallemand614ca0d2019-10-07 13:52:11 +02004081
4082 /* we found the ckchs in the tree, we can use it directly */
4083 if (ckchs->multi)
Emeric Brun054563d2019-10-17 13:16:58 +02004084 errcode |= ckch_inst_new_load_multi_store(path, ckchs, bind_conf, ssl_conf, sni_filter, fcount, &ckch_inst, err);
William Lallemand614ca0d2019-10-07 13:52:11 +02004085 else
Emeric Brun054563d2019-10-17 13:16:58 +02004086 errcode |= ckch_inst_new_load_store(path, ckchs, bind_conf, ssl_conf, sni_filter, fcount, &ckch_inst, err);
William Lallemand614ca0d2019-10-07 13:52:11 +02004087
Emeric Brun054563d2019-10-17 13:16:58 +02004088 if (errcode & ERR_CODE)
4089 return errcode;
William Lallemand614ca0d2019-10-07 13:52:11 +02004090
4091 ssl_sock_load_cert_sni(ckch_inst, bind_conf);
4092
4093 /* succeed, add the instance to the ckch_store's list of instance */
4094 LIST_ADDQ(&ckchs->ckch_inst, &ckch_inst->by_ckchs);
Emeric Brun054563d2019-10-17 13:16:58 +02004095 return errcode;
William Lallemand614ca0d2019-10-07 13:52:11 +02004096}
4097
4098
Willy Tarreaubbc91962019-10-16 16:42:19 +02004099/* Returns a set of ERR_* flags possibly with an error in <err>. */
Willy Tarreau03209342016-12-22 17:08:28 +01004100int ssl_sock_load_cert(char *path, struct bind_conf *bind_conf, char **err)
Emeric Brunfc0421f2012-09-07 17:30:07 +02004101{
Cyril Bonté3180f7b2015-01-25 00:16:08 +01004102 struct dirent **de_list;
4103 int i, n;
Emeric Brunfc0421f2012-09-07 17:30:07 +02004104 DIR *dir;
4105 struct stat buf;
Willy Tarreauee2663b2012-12-06 11:36:59 +01004106 char *end;
4107 char fp[MAXPATHLEN+1];
Emeric Brunfc0421f2012-09-07 17:30:07 +02004108 int cfgerr = 0;
William Lallemande3af8fb2019-10-08 11:36:53 +02004109 struct ckch_store *ckchs;
Willy Tarreau9a1ab082019-05-09 13:26:41 +02004110#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
yanbzhu63ea8462015-12-09 13:35:14 -05004111 int is_bundle;
4112 int j;
4113#endif
William Lallemande3af8fb2019-10-08 11:36:53 +02004114 if ((ckchs = ckchs_lookup(path))) {
William Lallemande3af8fb2019-10-08 11:36:53 +02004115 /* we found the ckchs in the tree, we can use it directly */
Willy Tarreau8c5414a2019-10-16 17:06:25 +02004116 return ssl_sock_load_ckchs(path, ckchs, bind_conf, NULL, NULL, 0, err);
William Lallemand6af03992019-07-23 15:00:54 +02004117 }
4118
yanbzhu08ce6ab2015-12-02 13:01:29 -05004119 if (stat(path, &buf) == 0) {
4120 dir = opendir(path);
William Lallemand36b84632019-07-18 19:28:17 +02004121 if (!dir) {
William Lallemande3af8fb2019-10-08 11:36:53 +02004122 ckchs = ckchs_load_cert_file(path, 0, err);
4123 if (!ckchs)
Willy Tarreaubbc91962019-10-16 16:42:19 +02004124 return ERR_ALERT | ERR_FATAL;
4125
Willy Tarreau8c5414a2019-10-16 17:06:25 +02004126 return ssl_sock_load_ckchs(path, ckchs, bind_conf, NULL, NULL, 0, err);
William Lallemand36b84632019-07-18 19:28:17 +02004127 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004128
yanbzhu08ce6ab2015-12-02 13:01:29 -05004129 /* strip trailing slashes, including first one */
4130 for (end = path + strlen(path) - 1; end >= path && *end == '/'; end--)
4131 *end = 0;
Emeric Brunfc0421f2012-09-07 17:30:07 +02004132
yanbzhu08ce6ab2015-12-02 13:01:29 -05004133 n = scandir(path, &de_list, 0, alphasort);
4134 if (n < 0) {
4135 memprintf(err, "%sunable to scan directory '%s' : %s.\n",
4136 err && *err ? *err : "", path, strerror(errno));
Willy Tarreaubbc91962019-10-16 16:42:19 +02004137 cfgerr |= ERR_ALERT | ERR_FATAL;
yanbzhu08ce6ab2015-12-02 13:01:29 -05004138 }
4139 else {
4140 for (i = 0; i < n; i++) {
4141 struct dirent *de = de_list[i];
Emeric Brun2aab7222014-06-18 18:15:09 +02004142
yanbzhu08ce6ab2015-12-02 13:01:29 -05004143 end = strrchr(de->d_name, '.');
4144 if (end && (!strcmp(end, ".issuer") || !strcmp(end, ".ocsp") || !strcmp(end, ".sctl")))
4145 goto ignore_entry;
Cyril Bonté3180f7b2015-01-25 00:16:08 +01004146
yanbzhu08ce6ab2015-12-02 13:01:29 -05004147 snprintf(fp, sizeof(fp), "%s/%s", path, de->d_name);
4148 if (stat(fp, &buf) != 0) {
4149 memprintf(err, "%sunable to stat SSL certificate from file '%s' : %s.\n",
4150 err && *err ? *err : "", fp, strerror(errno));
Willy Tarreaubbc91962019-10-16 16:42:19 +02004151 cfgerr |= ERR_ALERT | ERR_FATAL;
yanbzhu08ce6ab2015-12-02 13:01:29 -05004152 goto ignore_entry;
4153 }
4154 if (!S_ISREG(buf.st_mode))
4155 goto ignore_entry;
yanbzhu63ea8462015-12-09 13:35:14 -05004156
Willy Tarreau9a1ab082019-05-09 13:26:41 +02004157#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
yanbzhu63ea8462015-12-09 13:35:14 -05004158 is_bundle = 0;
4159 /* Check if current entry in directory is part of a multi-cert bundle */
4160
4161 if (end) {
4162 for (j = 0; j < SSL_SOCK_NUM_KEYTYPES; j++) {
4163 if (!strcmp(end + 1, SSL_SOCK_KEYTYPE_NAMES[j])) {
4164 is_bundle = 1;
4165 break;
4166 }
4167 }
4168
4169 if (is_bundle) {
yanbzhu63ea8462015-12-09 13:35:14 -05004170 int dp_len;
4171
4172 dp_len = end - de->d_name;
yanbzhu63ea8462015-12-09 13:35:14 -05004173
4174 /* increment i and free de until we get to a non-bundle cert
4175 * Note here that we look at de_list[i + 1] before freeing de
Willy Tarreau05800522019-10-29 10:48:50 +01004176 * this is important since ignore_entry will free de. This also
4177 * guarantees that de->d_name continues to hold the same prefix.
yanbzhu63ea8462015-12-09 13:35:14 -05004178 */
Willy Tarreau05800522019-10-29 10:48:50 +01004179 while (i + 1 < n && !strncmp(de_list[i + 1]->d_name, de->d_name, dp_len)) {
yanbzhu63ea8462015-12-09 13:35:14 -05004180 free(de);
4181 i++;
4182 de = de_list[i];
4183 }
4184
Willy Tarreau05800522019-10-29 10:48:50 +01004185 snprintf(fp, sizeof(fp), "%s/%.*s", path, dp_len, de->d_name);
William Lallemande3af8fb2019-10-08 11:36:53 +02004186 if ((ckchs = ckchs_lookup(fp)) == NULL)
4187 ckchs = ckchs_load_cert_file(fp, 1, err);
4188 if (!ckchs)
Willy Tarreaubbc91962019-10-16 16:42:19 +02004189 cfgerr |= ERR_ALERT | ERR_FATAL;
Willy Tarreau8c5414a2019-10-16 17:06:25 +02004190 else
4191 cfgerr |= ssl_sock_load_ckchs(path, ckchs, bind_conf, NULL, NULL, 0, err);
yanbzhu63ea8462015-12-09 13:35:14 -05004192 /* Successfully processed the bundle */
4193 goto ignore_entry;
4194 }
4195 }
4196
4197#endif
William Lallemande3af8fb2019-10-08 11:36:53 +02004198 if ((ckchs = ckchs_lookup(fp)) == NULL)
4199 ckchs = ckchs_load_cert_file(fp, 0, err);
4200 if (!ckchs)
Willy Tarreaubbc91962019-10-16 16:42:19 +02004201 cfgerr |= ERR_ALERT | ERR_FATAL;
William Lallemand614ca0d2019-10-07 13:52:11 +02004202 else
Willy Tarreau8c5414a2019-10-16 17:06:25 +02004203 cfgerr |= ssl_sock_load_ckchs(path, ckchs, bind_conf, NULL, NULL, 0, err);
William Lallemand36b84632019-07-18 19:28:17 +02004204
yanbzhu08ce6ab2015-12-02 13:01:29 -05004205ignore_entry:
4206 free(de);
Cyril Bonté3180f7b2015-01-25 00:16:08 +01004207 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05004208 free(de_list);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004209 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05004210 closedir(dir);
4211 return cfgerr;
Emeric Brunfc0421f2012-09-07 17:30:07 +02004212 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05004213
William Lallemande3af8fb2019-10-08 11:36:53 +02004214 ckchs = ckchs_load_cert_file(path, 1, err);
4215 if (!ckchs)
Willy Tarreaubbc91962019-10-16 16:42:19 +02004216 return ERR_ALERT | ERR_FATAL;
4217
Willy Tarreau8c5414a2019-10-16 17:06:25 +02004218 cfgerr |= ssl_sock_load_ckchs(path, ckchs, bind_conf, NULL, NULL, 0, err);
yanbzhu08ce6ab2015-12-02 13:01:29 -05004219
Emeric Brunfc0421f2012-09-07 17:30:07 +02004220 return cfgerr;
4221}
4222
Thierry Fournier383085f2013-01-24 14:15:43 +01004223/* Make sure openssl opens /dev/urandom before the chroot. The work is only
4224 * done once. Zero is returned if the operation fails. No error is returned
4225 * if the random is said as not implemented, because we expect that openssl
4226 * will use another method once needed.
4227 */
4228static int ssl_initialize_random()
4229{
4230 unsigned char random;
4231 static int random_initialized = 0;
4232
4233 if (!random_initialized && RAND_bytes(&random, 1) != 0)
4234 random_initialized = 1;
4235
4236 return random_initialized;
4237}
4238
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004239/* release ssl bind conf */
4240void ssl_sock_free_ssl_conf(struct ssl_bind_conf *conf)
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004241{
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004242 if (conf) {
Bernard Spil13c53f82018-02-15 13:34:58 +01004243#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004244 free(conf->npn_str);
4245 conf->npn_str = NULL;
4246#endif
4247#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
4248 free(conf->alpn_str);
4249 conf->alpn_str = NULL;
4250#endif
4251 free(conf->ca_file);
4252 conf->ca_file = NULL;
4253 free(conf->crl_file);
4254 conf->crl_file = NULL;
4255 free(conf->ciphers);
4256 conf->ciphers = NULL;
Emmanuel Hocdet839af572019-05-14 16:27:35 +02004257#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02004258 free(conf->ciphersuites);
4259 conf->ciphersuites = NULL;
4260#endif
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004261 free(conf->curves);
4262 conf->curves = NULL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004263 free(conf->ecdhe);
4264 conf->ecdhe = NULL;
4265 }
4266}
4267
Willy Tarreaubbc91962019-10-16 16:42:19 +02004268/* Returns a set of ERR_* flags possibly with an error in <err>. */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004269int ssl_sock_load_cert_list_file(char *file, struct bind_conf *bind_conf, struct proxy *curproxy, char **err)
4270{
4271 char thisline[CRT_LINESIZE];
4272 char path[MAXPATHLEN+1];
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004273 FILE *f;
yanbzhu1b04e5b2015-12-02 13:54:14 -05004274 struct stat buf;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004275 int linenum = 0;
4276 int cfgerr = 0;
William Lallemande3af8fb2019-10-08 11:36:53 +02004277 struct ckch_store *ckchs;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004278
Willy Tarreauad1731d2013-04-02 17:35:58 +02004279 if ((f = fopen(file, "r")) == NULL) {
4280 memprintf(err, "cannot open file '%s' : %s", file, strerror(errno));
Willy Tarreaubbc91962019-10-16 16:42:19 +02004281 return ERR_ALERT | ERR_FATAL;
Willy Tarreauad1731d2013-04-02 17:35:58 +02004282 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004283
4284 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004285 int arg, newarg, cur_arg, i, ssl_b = 0, ssl_e = 0;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004286 char *end;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004287 char *args[MAX_CRT_ARGS + 1];
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004288 char *line = thisline;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004289 char *crt_path;
4290 struct ssl_bind_conf *ssl_conf = NULL;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004291
4292 linenum++;
4293 end = line + strlen(line);
4294 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
4295 /* Check if we reached the limit and the last char is not \n.
4296 * Watch out for the last line without the terminating '\n'!
4297 */
Willy Tarreauad1731d2013-04-02 17:35:58 +02004298 memprintf(err, "line %d too long in file '%s', limit is %d characters",
4299 linenum, file, (int)sizeof(thisline)-1);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004300 cfgerr |= ERR_ALERT | ERR_FATAL;
Willy Tarreauad1731d2013-04-02 17:35:58 +02004301 break;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004302 }
4303
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004304 arg = 0;
Emeric Brun50bcecc2013-04-22 13:05:23 +02004305 newarg = 1;
4306 while (*line) {
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004307 if (*line == '#' || *line == '\n' || *line == '\r') {
4308 /* end of string, end of loop */
4309 *line = 0;
4310 break;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004311 } else if (isspace(*line)) {
Emeric Brun50bcecc2013-04-22 13:05:23 +02004312 newarg = 1;
4313 *line = 0;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004314 } else if (*line == '[') {
4315 if (ssl_b) {
4316 memprintf(err, "too many '[' on line %d in file '%s'.", linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004317 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004318 break;
4319 }
4320 if (!arg) {
4321 memprintf(err, "file must start with a cert on line %d in file '%s'", linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004322 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004323 break;
4324 }
4325 ssl_b = arg;
4326 newarg = 1;
4327 *line = 0;
4328 } else if (*line == ']') {
4329 if (ssl_e) {
4330 memprintf(err, "too many ']' on line %d in file '%s'.", linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004331 cfgerr |= ERR_ALERT | ERR_FATAL;
Emeric Brun50bcecc2013-04-22 13:05:23 +02004332 break;
4333 }
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004334 if (!ssl_b) {
4335 memprintf(err, "missing '[' in line %d in file '%s'.", linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004336 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004337 break;
4338 }
4339 ssl_e = arg;
4340 newarg = 1;
4341 *line = 0;
4342 } else if (newarg) {
4343 if (arg == MAX_CRT_ARGS) {
4344 memprintf(err, "too many args on line %d in file '%s'.", linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004345 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004346 break;
4347 }
Emeric Brun50bcecc2013-04-22 13:05:23 +02004348 newarg = 0;
4349 args[arg++] = line;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004350 }
Emeric Brun50bcecc2013-04-22 13:05:23 +02004351 line++;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004352 }
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02004353 if (cfgerr)
4354 break;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004355 args[arg++] = line;
Willy Tarreauad1731d2013-04-02 17:35:58 +02004356
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004357 /* empty line */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004358 if (!*args[0])
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004359 continue;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004360
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004361 crt_path = args[0];
4362 if (*crt_path != '/' && global_ssl.crt_base) {
4363 if ((strlen(global_ssl.crt_base) + 1 + strlen(crt_path)) > MAXPATHLEN) {
4364 memprintf(err, "'%s' : path too long on line %d in file '%s'",
4365 crt_path, linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004366 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004367 break;
4368 }
4369 snprintf(path, sizeof(path), "%s/%s", global_ssl.crt_base, crt_path);
4370 crt_path = path;
4371 }
4372
4373 ssl_conf = calloc(1, sizeof *ssl_conf);
4374 cur_arg = ssl_b ? ssl_b : 1;
4375 while (cur_arg < ssl_e) {
4376 newarg = 0;
4377 for (i = 0; ssl_bind_kws[i].kw != NULL; i++) {
4378 if (strcmp(ssl_bind_kws[i].kw, args[cur_arg]) == 0) {
4379 newarg = 1;
Willy Tarreaubbc91962019-10-16 16:42:19 +02004380 cfgerr |= ssl_bind_kws[i].parse(args, cur_arg, curproxy, ssl_conf, err);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004381 if (cur_arg + 1 + ssl_bind_kws[i].skip > ssl_e) {
4382 memprintf(err, "ssl args out of '[]' for %s on line %d in file '%s'",
4383 args[cur_arg], linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004384 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004385 }
4386 cur_arg += 1 + ssl_bind_kws[i].skip;
4387 break;
4388 }
4389 }
4390 if (!cfgerr && !newarg) {
4391 memprintf(err, "unknown ssl keyword %s on line %d in file '%s'.",
4392 args[cur_arg], linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004393 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004394 break;
4395 }
4396 }
Willy Tarreaubbc91962019-10-16 16:42:19 +02004397
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004398 if (cfgerr) {
4399 ssl_sock_free_ssl_conf(ssl_conf);
4400 free(ssl_conf);
4401 ssl_conf = NULL;
4402 break;
4403 }
4404
William Lallemande3af8fb2019-10-08 11:36:53 +02004405 if ((ckchs = ckchs_lookup(crt_path)) == NULL) {
William Lallemandeed4bf22019-10-10 11:38:13 +02004406 if (stat(crt_path, &buf) == 0)
William Lallemande3af8fb2019-10-08 11:36:53 +02004407 ckchs = ckchs_load_cert_file(crt_path, 0, err);
Emmanuel Hocdet1503e052019-07-31 18:30:33 +02004408 else
William Lallemande3af8fb2019-10-08 11:36:53 +02004409 ckchs = ckchs_load_cert_file(crt_path, 1, err);
yanbzhu1b04e5b2015-12-02 13:54:14 -05004410 }
4411
Willy Tarreau8c5414a2019-10-16 17:06:25 +02004412 if (!ckchs)
Willy Tarreaubbc91962019-10-16 16:42:19 +02004413 cfgerr |= ERR_ALERT | ERR_FATAL;
Willy Tarreau8c5414a2019-10-16 17:06:25 +02004414 else
4415 cfgerr |= ssl_sock_load_ckchs(crt_path, ckchs, bind_conf, ssl_conf, &args[cur_arg], arg - cur_arg - 1, err);
William Lallemandeed4bf22019-10-10 11:38:13 +02004416
Willy Tarreauad1731d2013-04-02 17:35:58 +02004417 if (cfgerr) {
4418 memprintf(err, "error processing line %d in file '%s' : %s", linenum, file, *err);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004419 break;
Willy Tarreauad1731d2013-04-02 17:35:58 +02004420 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004421 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004422 fclose(f);
4423 return cfgerr;
4424}
4425
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004426/* Create an initial CTX used to start the SSL connection before switchctx */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004427static int
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004428ssl_sock_initial_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02004429{
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004430 SSL_CTX *ctx = NULL;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004431 long options =
Emeric Brunfc0421f2012-09-07 17:30:07 +02004432 SSL_OP_ALL | /* all known workarounds for bugs */
4433 SSL_OP_NO_SSLv2 |
4434 SSL_OP_NO_COMPRESSION |
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02004435 SSL_OP_SINGLE_DH_USE |
Emeric Brun2b58d042012-09-20 17:10:03 +02004436 SSL_OP_SINGLE_ECDH_USE |
Emeric Brun3c4bc6e2012-10-04 18:44:19 +02004437 SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION |
Lukas Tribus926594f2018-05-18 17:55:57 +02004438 SSL_OP_PRIORITIZE_CHACHA |
Emeric Brun3c4bc6e2012-10-04 18:44:19 +02004439 SSL_OP_CIPHER_SERVER_PREFERENCE;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004440 long mode =
Emeric Brunfc0421f2012-09-07 17:30:07 +02004441 SSL_MODE_ENABLE_PARTIAL_WRITE |
4442 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
Willy Tarreau396a1862014-11-13 14:06:52 +01004443 SSL_MODE_RELEASE_BUFFERS |
4444 SSL_MODE_SMALL_BUFFERS;
Emmanuel Hocdet43664762017-08-09 18:26:20 +02004445 struct tls_version_filter *conf_ssl_methods = &bind_conf->ssl_conf.ssl_methods;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004446 int i, min, max, hole;
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004447 int flags = MC_SSL_O_ALL;
4448 int cfgerr = 0;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004449
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004450 ctx = SSL_CTX_new(SSLv23_server_method());
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004451 bind_conf->initial_ctx = ctx;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004452
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004453 if (conf_ssl_methods->flags && (conf_ssl_methods->min || conf_ssl_methods->max))
Christopher Faulet767a84b2017-11-24 16:50:31 +01004454 ha_warning("Proxy '%s': no-sslv3/no-tlsv1x are ignored for bind '%s' at [%s:%d]. "
4455 "Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
4456 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004457 else
4458 flags = conf_ssl_methods->flags;
4459
Emmanuel Hocdetbd695fe2017-05-15 15:53:41 +02004460 min = conf_ssl_methods->min;
4461 max = conf_ssl_methods->max;
4462 /* start with TLSv10 to remove SSLv3 per default */
4463 if (!min && (!max || max >= CONF_TLSV10))
4464 min = CONF_TLSV10;
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004465 /* Real min and max should be determinate with configuration and openssl's capabilities */
Emmanuel Hocdetbd695fe2017-05-15 15:53:41 +02004466 if (min)
4467 flags |= (methodVersions[min].flag - 1);
4468 if (max)
4469 flags |= ~((methodVersions[max].flag << 1) - 1);
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004470 /* find min, max and holes */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004471 min = max = CONF_TLSV_NONE;
4472 hole = 0;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004473 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004474 /* version is in openssl && version not disable in configuration */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004475 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004476 if (min) {
4477 if (hole) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004478 ha_warning("Proxy '%s': SSL/TLS versions range not contiguous for bind '%s' at [%s:%d]. "
4479 "Hole find for %s. Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
4480 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line,
4481 methodVersions[hole].name);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004482 hole = 0;
4483 }
4484 max = i;
4485 }
4486 else {
4487 min = max = i;
4488 }
4489 }
4490 else {
4491 if (min)
4492 hole = i;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004493 }
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004494 if (!min) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004495 ha_alert("Proxy '%s': all SSL/TLS versions are disabled for bind '%s' at [%s:%d].\n",
4496 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004497 cfgerr += 1;
4498 }
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02004499 /* save real min/max in bind_conf */
4500 conf_ssl_methods->min = min;
4501 conf_ssl_methods->max = max;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004502
Willy Tarreau9a1ab082019-05-09 13:26:41 +02004503#if (HA_OPENSSL_VERSION_NUMBER < 0x1010000fL)
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004504 /* Keep force-xxx implementation as it is in older haproxy. It's a
Joseph Herlant017b3da2018-11-15 09:07:59 -08004505 precautionary measure to avoid any surprise with older openssl version. */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004506 if (min == max)
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004507 methodVersions[min].ctx_set_version(ctx, SET_SERVER);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004508 else
4509 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
4510 if (flags & methodVersions[i].flag)
4511 options |= methodVersions[i].option;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004512#else /* openssl >= 1.1.0 */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004513 /* set the max_version is required to cap TLS version or activate new TLS (v1.3) */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004514 methodVersions[min].ctx_set_version(ctx, SET_MIN);
4515 methodVersions[max].ctx_set_version(ctx, SET_MAX);
Emeric Brunfa5c5c82017-04-28 16:19:51 +02004516#endif
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004517
4518 if (bind_conf->ssl_options & BC_SSL_O_NO_TLS_TICKETS)
4519 options |= SSL_OP_NO_TICKET;
4520 if (bind_conf->ssl_options & BC_SSL_O_PREF_CLIE_CIPH)
4521 options &= ~SSL_OP_CIPHER_SERVER_PREFERENCE;
Dirkjan Bussink526894f2019-01-21 09:35:03 -08004522
4523#ifdef SSL_OP_NO_RENEGOTIATION
4524 options |= SSL_OP_NO_RENEGOTIATION;
4525#endif
4526
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004527 SSL_CTX_set_options(ctx, options);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004528
Willy Tarreau5db847a2019-05-09 14:13:35 +02004529#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004530 if (global_ssl.async)
4531 mode |= SSL_MODE_ASYNC;
4532#endif
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004533 SSL_CTX_set_mode(ctx, mode);
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004534 if (global_ssl.life_time)
4535 SSL_CTX_set_timeout(ctx, global_ssl.life_time);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004536
4537#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
4538#ifdef OPENSSL_IS_BORINGSSL
4539 SSL_CTX_set_select_certificate_cb(ctx, ssl_sock_switchctx_cbk);
4540 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_err_cbk);
Willy Tarreau5db847a2019-05-09 14:13:35 +02004541#elif (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Olivier Houchard51088ce2019-01-02 18:46:41 +01004542 if (bind_conf->ssl_conf.early_data) {
4543 SSL_CTX_set_options(ctx, SSL_OP_NO_ANTI_REPLAY);
4544 SSL_CTX_set_max_early_data(ctx, global.tune.bufsize - global.tune.maxrewrite);
4545 }
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02004546 SSL_CTX_set_client_hello_cb(ctx, ssl_sock_switchctx_cbk, NULL);
4547 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_err_cbk);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004548#else
4549 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_cbk);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004550#endif
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02004551 SSL_CTX_set_tlsext_servername_arg(ctx, bind_conf);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004552#endif
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004553 return cfgerr;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004554}
4555
William Lallemand4f45bb92017-10-30 20:08:51 +01004556
4557static inline void sh_ssl_sess_free_blocks(struct shared_block *first, struct shared_block *block)
4558{
4559 if (first == block) {
4560 struct sh_ssl_sess_hdr *sh_ssl_sess = (struct sh_ssl_sess_hdr *)first->data;
4561 if (first->len > 0)
4562 sh_ssl_sess_tree_delete(sh_ssl_sess);
4563 }
4564}
4565
4566/* return first block from sh_ssl_sess */
4567static inline struct shared_block *sh_ssl_sess_first_block(struct sh_ssl_sess_hdr *sh_ssl_sess)
4568{
4569 return (struct shared_block *)((unsigned char *)sh_ssl_sess - ((struct shared_block *)NULL)->data);
4570
4571}
4572
4573/* store a session into the cache
4574 * s_id : session id padded with zero to SSL_MAX_SSL_SESSION_ID_LENGTH
4575 * data: asn1 encoded session
4576 * data_len: asn1 encoded session length
4577 * Returns 1 id session was stored (else 0)
4578 */
4579static int sh_ssl_sess_store(unsigned char *s_id, unsigned char *data, int data_len)
4580{
4581 struct shared_block *first;
4582 struct sh_ssl_sess_hdr *sh_ssl_sess, *oldsh_ssl_sess;
4583
Frédéric Lécaille0bec8072018-10-22 17:55:57 +02004584 first = shctx_row_reserve_hot(ssl_shctx, NULL, data_len + sizeof(struct sh_ssl_sess_hdr));
William Lallemand4f45bb92017-10-30 20:08:51 +01004585 if (!first) {
4586 /* Could not retrieve enough free blocks to store that session */
4587 return 0;
4588 }
4589
4590 /* STORE the key in the first elem */
4591 sh_ssl_sess = (struct sh_ssl_sess_hdr *)first->data;
4592 memcpy(sh_ssl_sess->key_data, s_id, SSL_MAX_SSL_SESSION_ID_LENGTH);
4593 first->len = sizeof(struct sh_ssl_sess_hdr);
4594
4595 /* it returns the already existing node
4596 or current node if none, never returns null */
4597 oldsh_ssl_sess = sh_ssl_sess_tree_insert(sh_ssl_sess);
4598 if (oldsh_ssl_sess != sh_ssl_sess) {
4599 /* NOTE: Row couldn't be in use because we lock read & write function */
4600 /* release the reserved row */
4601 shctx_row_dec_hot(ssl_shctx, first);
4602 /* replace the previous session already in the tree */
4603 sh_ssl_sess = oldsh_ssl_sess;
4604 /* ignore the previous session data, only use the header */
4605 first = sh_ssl_sess_first_block(sh_ssl_sess);
4606 shctx_row_inc_hot(ssl_shctx, first);
4607 first->len = sizeof(struct sh_ssl_sess_hdr);
4608 }
4609
Frédéric Lécaille0bec8072018-10-22 17:55:57 +02004610 if (shctx_row_data_append(ssl_shctx, first, NULL, data, data_len) < 0) {
William Lallemand99b90af2018-01-03 19:15:51 +01004611 shctx_row_dec_hot(ssl_shctx, first);
William Lallemand4f45bb92017-10-30 20:08:51 +01004612 return 0;
William Lallemand99b90af2018-01-03 19:15:51 +01004613 }
4614
4615 shctx_row_dec_hot(ssl_shctx, first);
William Lallemand4f45bb92017-10-30 20:08:51 +01004616
4617 return 1;
4618}
William Lallemanded0b5ad2017-10-30 19:36:36 +01004619
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004620/* SSL callback used when a new session is created while connecting to a server */
4621static int ssl_sess_new_srv_cb(SSL *ssl, SSL_SESSION *sess)
4622{
Thierry FOURNIER28962c92018-06-17 21:37:05 +02004623 struct connection *conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Olivier Houcharde6060c52017-11-16 17:42:52 +01004624 struct server *s;
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004625
Willy Tarreau07d94e42018-09-20 10:57:52 +02004626 s = __objt_server(conn->target);
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004627
Olivier Houcharde6060c52017-11-16 17:42:52 +01004628 if (!(s->ssl_ctx.options & SRV_SSL_O_NO_REUSE)) {
4629 int len;
4630 unsigned char *ptr;
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004631
Olivier Houcharde6060c52017-11-16 17:42:52 +01004632 len = i2d_SSL_SESSION(sess, NULL);
4633 if (s->ssl_ctx.reused_sess[tid].ptr && s->ssl_ctx.reused_sess[tid].allocated_size >= len) {
4634 ptr = s->ssl_ctx.reused_sess[tid].ptr;
4635 } else {
4636 free(s->ssl_ctx.reused_sess[tid].ptr);
4637 ptr = s->ssl_ctx.reused_sess[tid].ptr = malloc(len);
4638 s->ssl_ctx.reused_sess[tid].allocated_size = len;
4639 }
4640 if (s->ssl_ctx.reused_sess[tid].ptr) {
4641 s->ssl_ctx.reused_sess[tid].size = i2d_SSL_SESSION(sess,
4642 &ptr);
4643 }
4644 } else {
4645 free(s->ssl_ctx.reused_sess[tid].ptr);
4646 s->ssl_ctx.reused_sess[tid].ptr = NULL;
4647 }
4648
4649 return 0;
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004650}
4651
Olivier Houcharde6060c52017-11-16 17:42:52 +01004652
William Lallemanded0b5ad2017-10-30 19:36:36 +01004653/* SSL callback used on new session creation */
William Lallemand4f45bb92017-10-30 20:08:51 +01004654int sh_ssl_sess_new_cb(SSL *ssl, SSL_SESSION *sess)
William Lallemanded0b5ad2017-10-30 19:36:36 +01004655{
4656 unsigned char encsess[SHSESS_MAX_DATA_LEN]; /* encoded session */
4657 unsigned char encid[SSL_MAX_SSL_SESSION_ID_LENGTH]; /* encoded id */
4658 unsigned char *p;
4659 int data_len;
Emeric Bruneb469652019-10-08 18:27:37 +02004660 unsigned int sid_length;
William Lallemanded0b5ad2017-10-30 19:36:36 +01004661 const unsigned char *sid_data;
William Lallemanded0b5ad2017-10-30 19:36:36 +01004662
4663 /* Session id is already stored in to key and session id is known
4664 * so we dont store it to keep size.
Emeric Bruneb469652019-10-08 18:27:37 +02004665 * note: SSL_SESSION_set1_id is using
4666 * a memcpy so we need to use a different pointer
4667 * than sid_data or sid_ctx_data to avoid valgrind
4668 * complaining.
William Lallemanded0b5ad2017-10-30 19:36:36 +01004669 */
4670
4671 sid_data = SSL_SESSION_get_id(sess, &sid_length);
Emeric Bruneb469652019-10-08 18:27:37 +02004672
4673 /* copy value in an other buffer */
4674 memcpy(encid, sid_data, sid_length);
4675
4676 /* pad with 0 */
4677 if (sid_length < SSL_MAX_SSL_SESSION_ID_LENGTH)
4678 memset(encid + sid_length, 0, SSL_MAX_SSL_SESSION_ID_LENGTH-sid_length);
4679
4680 /* force length to zero to avoid ASN1 encoding */
4681 SSL_SESSION_set1_id(sess, encid, 0);
4682
4683 /* force length to zero to avoid ASN1 encoding */
4684 SSL_SESSION_set1_id_context(sess, (const unsigned char *)SHCTX_APPNAME, 0);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004685
4686 /* check if buffer is large enough for the ASN1 encoded session */
4687 data_len = i2d_SSL_SESSION(sess, NULL);
4688 if (data_len > SHSESS_MAX_DATA_LEN)
4689 goto err;
4690
4691 p = encsess;
4692
4693 /* process ASN1 session encoding before the lock */
4694 i2d_SSL_SESSION(sess, &p);
4695
William Lallemanded0b5ad2017-10-30 19:36:36 +01004696
William Lallemanda3c77cf2017-10-30 23:44:40 +01004697 shctx_lock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004698 /* store to cache */
William Lallemand4f45bb92017-10-30 20:08:51 +01004699 sh_ssl_sess_store(encid, encsess, data_len);
William Lallemanda3c77cf2017-10-30 23:44:40 +01004700 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004701err:
4702 /* reset original length values */
Emeric Bruneb469652019-10-08 18:27:37 +02004703 SSL_SESSION_set1_id(sess, encid, sid_length);
4704 SSL_SESSION_set1_id_context(sess, (const unsigned char *)SHCTX_APPNAME, strlen(SHCTX_APPNAME));
William Lallemanded0b5ad2017-10-30 19:36:36 +01004705
4706 return 0; /* do not increment session reference count */
4707}
4708
4709/* SSL callback used on lookup an existing session cause none found in internal cache */
William Lallemand4f45bb92017-10-30 20:08:51 +01004710SSL_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 +01004711{
William Lallemand4f45bb92017-10-30 20:08:51 +01004712 struct sh_ssl_sess_hdr *sh_ssl_sess;
William Lallemanded0b5ad2017-10-30 19:36:36 +01004713 unsigned char data[SHSESS_MAX_DATA_LEN], *p;
4714 unsigned char tmpkey[SSL_MAX_SSL_SESSION_ID_LENGTH];
William Lallemanded0b5ad2017-10-30 19:36:36 +01004715 SSL_SESSION *sess;
William Lallemand4f45bb92017-10-30 20:08:51 +01004716 struct shared_block *first;
William Lallemanded0b5ad2017-10-30 19:36:36 +01004717
4718 global.shctx_lookups++;
4719
4720 /* allow the session to be freed automatically by openssl */
4721 *do_copy = 0;
4722
4723 /* tree key is zeros padded sessionid */
4724 if (key_len < SSL_MAX_SSL_SESSION_ID_LENGTH) {
4725 memcpy(tmpkey, key, key_len);
4726 memset(tmpkey + key_len, 0, SSL_MAX_SSL_SESSION_ID_LENGTH - key_len);
4727 key = tmpkey;
4728 }
4729
4730 /* lock cache */
William Lallemanda3c77cf2017-10-30 23:44:40 +01004731 shctx_lock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004732
4733 /* lookup for session */
William Lallemand4f45bb92017-10-30 20:08:51 +01004734 sh_ssl_sess = sh_ssl_sess_tree_lookup(key);
4735 if (!sh_ssl_sess) {
William Lallemanded0b5ad2017-10-30 19:36:36 +01004736 /* no session found: unlock cache and exit */
William Lallemanda3c77cf2017-10-30 23:44:40 +01004737 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004738 global.shctx_misses++;
4739 return NULL;
4740 }
4741
William Lallemand4f45bb92017-10-30 20:08:51 +01004742 /* sh_ssl_sess (shared_block->data) is at the end of shared_block */
4743 first = sh_ssl_sess_first_block(sh_ssl_sess);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004744
William Lallemand4f45bb92017-10-30 20:08:51 +01004745 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 +01004746
William Lallemanda3c77cf2017-10-30 23:44:40 +01004747 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004748
4749 /* decode ASN1 session */
4750 p = data;
William Lallemand4f45bb92017-10-30 20:08:51 +01004751 sess = d2i_SSL_SESSION(NULL, (const unsigned char **)&p, first->len-sizeof(struct sh_ssl_sess_hdr));
William Lallemanded0b5ad2017-10-30 19:36:36 +01004752 /* Reset session id and session id contenxt */
4753 if (sess) {
4754 SSL_SESSION_set1_id(sess, key, key_len);
4755 SSL_SESSION_set1_id_context(sess, (const unsigned char *)SHCTX_APPNAME, strlen(SHCTX_APPNAME));
4756 }
4757
4758 return sess;
4759}
4760
William Lallemand4f45bb92017-10-30 20:08:51 +01004761
William Lallemanded0b5ad2017-10-30 19:36:36 +01004762/* SSL callback used to signal session is no more used in internal cache */
William Lallemand4f45bb92017-10-30 20:08:51 +01004763void sh_ssl_sess_remove_cb(SSL_CTX *ctx, SSL_SESSION *sess)
William Lallemanded0b5ad2017-10-30 19:36:36 +01004764{
William Lallemand4f45bb92017-10-30 20:08:51 +01004765 struct sh_ssl_sess_hdr *sh_ssl_sess;
William Lallemanded0b5ad2017-10-30 19:36:36 +01004766 unsigned char tmpkey[SSL_MAX_SSL_SESSION_ID_LENGTH];
4767 unsigned int sid_length;
4768 const unsigned char *sid_data;
4769 (void)ctx;
4770
4771 sid_data = SSL_SESSION_get_id(sess, &sid_length);
4772 /* tree key is zeros padded sessionid */
4773 if (sid_length < SSL_MAX_SSL_SESSION_ID_LENGTH) {
4774 memcpy(tmpkey, sid_data, sid_length);
4775 memset(tmpkey+sid_length, 0, SSL_MAX_SSL_SESSION_ID_LENGTH - sid_length);
4776 sid_data = tmpkey;
4777 }
4778
William Lallemanda3c77cf2017-10-30 23:44:40 +01004779 shctx_lock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004780
4781 /* lookup for session */
William Lallemand4f45bb92017-10-30 20:08:51 +01004782 sh_ssl_sess = sh_ssl_sess_tree_lookup(sid_data);
4783 if (sh_ssl_sess) {
William Lallemanded0b5ad2017-10-30 19:36:36 +01004784 /* free session */
William Lallemand4f45bb92017-10-30 20:08:51 +01004785 sh_ssl_sess_tree_delete(sh_ssl_sess);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004786 }
4787
4788 /* unlock cache */
William Lallemanda3c77cf2017-10-30 23:44:40 +01004789 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004790}
4791
4792/* Set session cache mode to server and disable openssl internal cache.
4793 * Set shared cache callbacks on an ssl context.
4794 * Shared context MUST be firstly initialized */
William Lallemand4f45bb92017-10-30 20:08:51 +01004795void ssl_set_shctx(SSL_CTX *ctx)
William Lallemanded0b5ad2017-10-30 19:36:36 +01004796{
4797 SSL_CTX_set_session_id_context(ctx, (const unsigned char *)SHCTX_APPNAME, strlen(SHCTX_APPNAME));
4798
4799 if (!ssl_shctx) {
4800 SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF);
4801 return;
4802 }
4803
4804 SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_SERVER |
4805 SSL_SESS_CACHE_NO_INTERNAL |
4806 SSL_SESS_CACHE_NO_AUTO_CLEAR);
4807
4808 /* Set callbacks */
William Lallemand4f45bb92017-10-30 20:08:51 +01004809 SSL_CTX_sess_set_new_cb(ctx, sh_ssl_sess_new_cb);
4810 SSL_CTX_sess_set_get_cb(ctx, sh_ssl_sess_get_cb);
4811 SSL_CTX_sess_set_remove_cb(ctx, sh_ssl_sess_remove_cb);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004812}
4813
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004814int ssl_sock_prepare_ctx(struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf, SSL_CTX *ctx)
4815{
4816 struct proxy *curproxy = bind_conf->frontend;
4817 int cfgerr = 0;
4818 int verify = SSL_VERIFY_NONE;
Willy Tarreau5d4cafb2018-01-04 18:55:19 +01004819 struct ssl_bind_conf __maybe_unused *ssl_conf_cur;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004820 const char *conf_ciphers;
Emmanuel Hocdet839af572019-05-14 16:27:35 +02004821#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02004822 const char *conf_ciphersuites;
4823#endif
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004824 const char *conf_curves = NULL;
Emeric Brunfc0421f2012-09-07 17:30:07 +02004825
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02004826 if (ssl_conf) {
4827 struct tls_version_filter *conf_ssl_methods = &ssl_conf->ssl_methods;
4828 int i, min, max;
4829 int flags = MC_SSL_O_ALL;
4830
4831 /* Real min and max should be determinate with configuration and openssl's capabilities */
Emmanuel Hocdet43664762017-08-09 18:26:20 +02004832 min = conf_ssl_methods->min ? conf_ssl_methods->min : bind_conf->ssl_conf.ssl_methods.min;
4833 max = conf_ssl_methods->max ? conf_ssl_methods->max : bind_conf->ssl_conf.ssl_methods.max;
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02004834 if (min)
4835 flags |= (methodVersions[min].flag - 1);
4836 if (max)
4837 flags |= ~((methodVersions[max].flag << 1) - 1);
4838 min = max = CONF_TLSV_NONE;
4839 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
4840 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
4841 if (min)
4842 max = i;
4843 else
4844 min = max = i;
4845 }
4846 /* save real min/max */
4847 conf_ssl_methods->min = min;
4848 conf_ssl_methods->max = max;
4849 if (!min) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004850 ha_alert("Proxy '%s': all SSL/TLS versions are disabled for bind '%s' at [%s:%d].\n",
4851 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02004852 cfgerr += 1;
4853 }
4854 }
4855
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004856 switch ((ssl_conf && ssl_conf->verify) ? ssl_conf->verify : bind_conf->ssl_conf.verify) {
Emeric Brun850efd52014-01-29 12:24:34 +01004857 case SSL_SOCK_VERIFY_NONE:
4858 verify = SSL_VERIFY_NONE;
4859 break;
4860 case SSL_SOCK_VERIFY_OPTIONAL:
4861 verify = SSL_VERIFY_PEER;
4862 break;
4863 case SSL_SOCK_VERIFY_REQUIRED:
4864 verify = SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
4865 break;
4866 }
4867 SSL_CTX_set_verify(ctx, verify, ssl_sock_bind_verifycbk);
4868 if (verify & SSL_VERIFY_PEER) {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004869 char *ca_file = (ssl_conf && ssl_conf->ca_file) ? ssl_conf->ca_file : bind_conf->ssl_conf.ca_file;
4870 char *crl_file = (ssl_conf && ssl_conf->crl_file) ? ssl_conf->crl_file : bind_conf->ssl_conf.crl_file;
4871 if (ca_file) {
Emeric Brund94b3fe2012-09-20 18:23:56 +02004872 /* load CAfile to verify */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004873 if (!SSL_CTX_load_verify_locations(ctx, ca_file, NULL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004874 ha_alert("Proxy '%s': unable to load CA file '%s' for bind '%s' at [%s:%d].\n",
4875 curproxy->id, ca_file, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brund94b3fe2012-09-20 18:23:56 +02004876 cfgerr++;
4877 }
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02004878 if (!((ssl_conf && ssl_conf->no_ca_names) || bind_conf->ssl_conf.no_ca_names)) {
4879 /* set CA names for client cert request, function returns void */
4880 SSL_CTX_set_client_CA_list(ctx, SSL_load_client_CA_file(ca_file));
4881 }
Emeric Brund94b3fe2012-09-20 18:23:56 +02004882 }
Emeric Brun850efd52014-01-29 12:24:34 +01004883 else {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004884 ha_alert("Proxy '%s': verify is enabled but no CA file specified for bind '%s' at [%s:%d].\n",
4885 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brun850efd52014-01-29 12:24:34 +01004886 cfgerr++;
4887 }
Emeric Brun051cdab2012-10-02 19:25:50 +02004888#ifdef X509_V_FLAG_CRL_CHECK
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004889 if (crl_file) {
Emeric Brund94b3fe2012-09-20 18:23:56 +02004890 X509_STORE *store = SSL_CTX_get_cert_store(ctx);
4891
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004892 if (!store || !X509_STORE_load_locations(store, crl_file, NULL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004893 ha_alert("Proxy '%s': unable to configure CRL file '%s' for bind '%s' at [%s:%d].\n",
4894 curproxy->id, crl_file, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brund94b3fe2012-09-20 18:23:56 +02004895 cfgerr++;
4896 }
Emeric Brun561e5742012-10-02 15:20:55 +02004897 else {
4898 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
4899 }
Emeric Brund94b3fe2012-09-20 18:23:56 +02004900 }
Emeric Brun051cdab2012-10-02 19:25:50 +02004901#endif
Emeric Brun644cde02012-12-14 11:21:13 +01004902 ERR_clear_error();
Emeric Brund94b3fe2012-09-20 18:23:56 +02004903 }
Nenad Merdanovic05552d42015-02-27 19:56:49 +01004904#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
Nenad Merdanovic146defa2015-05-09 08:46:00 +02004905 if(bind_conf->keys_ref) {
Nenad Merdanovic05552d42015-02-27 19:56:49 +01004906 if (!SSL_CTX_set_tlsext_ticket_key_cb(ctx, ssl_tlsext_ticket_key_cb)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004907 ha_alert("Proxy '%s': unable to set callback for TLS ticket validation for bind '%s' at [%s:%d].\n",
4908 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Nenad Merdanovic05552d42015-02-27 19:56:49 +01004909 cfgerr++;
4910 }
4911 }
4912#endif
4913
William Lallemand4f45bb92017-10-30 20:08:51 +01004914 ssl_set_shctx(ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004915 conf_ciphers = (ssl_conf && ssl_conf->ciphers) ? ssl_conf->ciphers : bind_conf->ssl_conf.ciphers;
4916 if (conf_ciphers &&
4917 !SSL_CTX_set_cipher_list(ctx, conf_ciphers)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004918 ha_alert("Proxy '%s': unable to set SSL cipher list to '%s' for bind '%s' at [%s:%d].\n",
4919 curproxy->id, conf_ciphers, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004920 cfgerr++;
4921 }
4922
Emmanuel Hocdet839af572019-05-14 16:27:35 +02004923#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02004924 conf_ciphersuites = (ssl_conf && ssl_conf->ciphersuites) ? ssl_conf->ciphersuites : bind_conf->ssl_conf.ciphersuites;
4925 if (conf_ciphersuites &&
4926 !SSL_CTX_set_ciphersuites(ctx, conf_ciphersuites)) {
4927 ha_alert("Proxy '%s': unable to set TLS 1.3 cipher suites to '%s' for bind '%s' at [%s:%d].\n",
4928 curproxy->id, conf_ciphersuites, bind_conf->arg, bind_conf->file, bind_conf->line);
4929 cfgerr++;
4930 }
4931#endif
4932
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01004933#ifndef OPENSSL_NO_DH
Remi Gacogne47783ef2015-05-29 15:53:22 +02004934 /* If tune.ssl.default-dh-param has not been set,
4935 neither has ssl-default-dh-file and no static DH
4936 params were in the certificate file. */
Willy Tarreauef934602016-12-22 23:12:01 +01004937 if (global_ssl.default_dh_param == 0 &&
Remi Gacogne47783ef2015-05-29 15:53:22 +02004938 global_dh == NULL &&
Remi Gacogne4f902b82015-05-28 16:23:00 +02004939 (ssl_dh_ptr_index == -1 ||
4940 SSL_CTX_get_ex_data(ctx, ssl_dh_ptr_index) == NULL)) {
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01004941 STACK_OF(SSL_CIPHER) * ciphers = NULL;
4942 const SSL_CIPHER * cipher = NULL;
4943 char cipher_description[128];
4944 /* The description of ciphers using an Ephemeral Diffie Hellman key exchange
4945 contains " Kx=DH " or " Kx=DH(". Beware of " Kx=DH/",
4946 which is not ephemeral DH. */
4947 const char dhe_description[] = " Kx=DH ";
4948 const char dhe_export_description[] = " Kx=DH(";
4949 int idx = 0;
4950 int dhe_found = 0;
4951 SSL *ssl = NULL;
Lukas Tribus90132722014-08-18 00:56:33 +02004952
Remi Gacogne23d5d372014-10-10 17:04:26 +02004953 ssl = SSL_new(ctx);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004954
Remi Gacogne23d5d372014-10-10 17:04:26 +02004955 if (ssl) {
4956 ciphers = SSL_get_ciphers(ssl);
4957
4958 if (ciphers) {
4959 for (idx = 0; idx < sk_SSL_CIPHER_num(ciphers); idx++) {
4960 cipher = sk_SSL_CIPHER_value(ciphers, idx);
4961 if (SSL_CIPHER_description(cipher, cipher_description, sizeof (cipher_description)) == cipher_description) {
4962 if (strstr(cipher_description, dhe_description) != NULL ||
4963 strstr(cipher_description, dhe_export_description) != NULL) {
4964 dhe_found = 1;
4965 break;
4966 }
Remi Gacognec1eab8c2014-06-12 18:20:11 +02004967 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004968 }
4969 }
Remi Gacogne23d5d372014-10-10 17:04:26 +02004970 SSL_free(ssl);
4971 ssl = NULL;
Lukas Tribus90132722014-08-18 00:56:33 +02004972 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004973
Lukas Tribus90132722014-08-18 00:56:33 +02004974 if (dhe_found) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004975 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 +02004976 }
4977
Willy Tarreauef934602016-12-22 23:12:01 +01004978 global_ssl.default_dh_param = 1024;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004979 }
Remi Gacogne8de54152014-07-15 11:36:40 +02004980
Willy Tarreauef934602016-12-22 23:12:01 +01004981 if (global_ssl.default_dh_param >= 1024) {
Remi Gacogne8de54152014-07-15 11:36:40 +02004982 if (local_dh_1024 == NULL) {
4983 local_dh_1024 = ssl_get_dh_1024();
4984 }
Willy Tarreauef934602016-12-22 23:12:01 +01004985 if (global_ssl.default_dh_param >= 2048) {
Remi Gacogne8de54152014-07-15 11:36:40 +02004986 if (local_dh_2048 == NULL) {
4987 local_dh_2048 = ssl_get_dh_2048();
4988 }
Willy Tarreauef934602016-12-22 23:12:01 +01004989 if (global_ssl.default_dh_param >= 4096) {
Remi Gacogne8de54152014-07-15 11:36:40 +02004990 if (local_dh_4096 == NULL) {
4991 local_dh_4096 = ssl_get_dh_4096();
4992 }
Remi Gacogne8de54152014-07-15 11:36:40 +02004993 }
4994 }
4995 }
4996#endif /* OPENSSL_NO_DH */
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004997
Emeric Brunfc0421f2012-09-07 17:30:07 +02004998 SSL_CTX_set_info_callback(ctx, ssl_sock_infocbk);
Willy Tarreau9a1ab082019-05-09 13:26:41 +02004999#if HA_OPENSSL_VERSION_NUMBER >= 0x00907000L
Emeric Brun29f037d2014-04-25 19:05:36 +02005000 SSL_CTX_set_msg_callback(ctx, ssl_sock_msgcbk);
Willy Tarreau5cbe4ef2014-05-08 22:45:11 +02005001#endif
Emeric Brun29f037d2014-04-25 19:05:36 +02005002
Bernard Spil13c53f82018-02-15 13:34:58 +01005003#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005004 ssl_conf_cur = NULL;
5005 if (ssl_conf && ssl_conf->npn_str)
5006 ssl_conf_cur = ssl_conf;
5007 else if (bind_conf->ssl_conf.npn_str)
5008 ssl_conf_cur = &bind_conf->ssl_conf;
5009 if (ssl_conf_cur)
5010 SSL_CTX_set_next_protos_advertised_cb(ctx, ssl_sock_advertise_npn_protos, ssl_conf_cur);
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02005011#endif
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01005012#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005013 ssl_conf_cur = NULL;
5014 if (ssl_conf && ssl_conf->alpn_str)
5015 ssl_conf_cur = ssl_conf;
5016 else if (bind_conf->ssl_conf.alpn_str)
5017 ssl_conf_cur = &bind_conf->ssl_conf;
5018 if (ssl_conf_cur)
5019 SSL_CTX_set_alpn_select_cb(ctx, ssl_sock_advertise_alpn_protos, ssl_conf_cur);
Willy Tarreauab861d32013-04-02 02:30:41 +02005020#endif
Willy Tarreau9a1ab082019-05-09 13:26:41 +02005021#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01005022 conf_curves = (ssl_conf && ssl_conf->curves) ? ssl_conf->curves : bind_conf->ssl_conf.curves;
5023 if (conf_curves) {
5024 if (!SSL_CTX_set1_curves_list(ctx, conf_curves)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005025 ha_alert("Proxy '%s': unable to set SSL curves list to '%s' for bind '%s' at [%s:%d].\n",
5026 curproxy->id, conf_curves, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01005027 cfgerr++;
5028 }
Emmanuel Hocdeta52bb152017-03-20 11:11:49 +01005029#if defined(SSL_CTX_set_ecdh_auto)
5030 (void)SSL_CTX_set_ecdh_auto(ctx, 1);
5031#endif
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01005032 }
5033#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02005034#if defined(SSL_CTX_set_tmp_ecdh) && !defined(OPENSSL_NO_ECDH)
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01005035 if (!conf_curves) {
Emeric Brun2b58d042012-09-20 17:10:03 +02005036 int i;
5037 EC_KEY *ecdh;
Willy Tarreau9a1ab082019-05-09 13:26:41 +02005038#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005039 const char *ecdhe = (ssl_conf && ssl_conf->ecdhe) ? ssl_conf->ecdhe :
Olivier Houchardc2aae742017-09-22 18:26:28 +02005040 (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe :
5041 NULL);
5042
5043 if (ecdhe == NULL) {
Eric Salama3c8bde82019-11-20 11:33:40 +01005044 (void)SSL_CTX_set_ecdh_auto(ctx, 1);
Olivier Houchardc2aae742017-09-22 18:26:28 +02005045 return cfgerr;
5046 }
5047#else
5048 const char *ecdhe = (ssl_conf && ssl_conf->ecdhe) ? ssl_conf->ecdhe :
5049 (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe :
5050 ECDHE_DEFAULT_CURVE);
5051#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02005052
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005053 i = OBJ_sn2nid(ecdhe);
Emeric Brun2b58d042012-09-20 17:10:03 +02005054 if (!i || ((ecdh = EC_KEY_new_by_curve_name(i)) == NULL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005055 ha_alert("Proxy '%s': unable to set elliptic named curve to '%s' for bind '%s' at [%s:%d].\n",
5056 curproxy->id, ecdhe, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brun2b58d042012-09-20 17:10:03 +02005057 cfgerr++;
5058 }
5059 else {
5060 SSL_CTX_set_tmp_ecdh(ctx, ecdh);
5061 EC_KEY_free(ecdh);
5062 }
5063 }
5064#endif
5065
Emeric Brunfc0421f2012-09-07 17:30:07 +02005066 return cfgerr;
5067}
5068
Evan Broderbe554312013-06-27 00:05:25 -07005069static int ssl_sock_srv_hostcheck(const char *pattern, const char *hostname)
5070{
5071 const char *pattern_wildcard, *pattern_left_label_end, *hostname_left_label_end;
5072 size_t prefixlen, suffixlen;
5073
5074 /* Trivial case */
5075 if (strcmp(pattern, hostname) == 0)
5076 return 1;
5077
Evan Broderbe554312013-06-27 00:05:25 -07005078 /* The rest of this logic is based on RFC 6125, section 6.4.3
5079 * (http://tools.ietf.org/html/rfc6125#section-6.4.3) */
5080
Emeric Bruna848dae2013-10-08 11:27:28 +02005081 pattern_wildcard = NULL;
5082 pattern_left_label_end = pattern;
5083 while (*pattern_left_label_end != '.') {
5084 switch (*pattern_left_label_end) {
5085 case 0:
5086 /* End of label not found */
5087 return 0;
5088 case '*':
5089 /* If there is more than one wildcards */
5090 if (pattern_wildcard)
5091 return 0;
5092 pattern_wildcard = pattern_left_label_end;
5093 break;
5094 }
5095 pattern_left_label_end++;
5096 }
5097
5098 /* If it's not trivial and there is no wildcard, it can't
5099 * match */
5100 if (!pattern_wildcard)
Evan Broderbe554312013-06-27 00:05:25 -07005101 return 0;
5102
5103 /* Make sure all labels match except the leftmost */
5104 hostname_left_label_end = strchr(hostname, '.');
5105 if (!hostname_left_label_end
5106 || strcmp(pattern_left_label_end, hostname_left_label_end) != 0)
5107 return 0;
5108
5109 /* Make sure the leftmost label of the hostname is long enough
5110 * that the wildcard can match */
Emeric Brun369da852013-10-08 11:39:35 +02005111 if (hostname_left_label_end - hostname < (pattern_left_label_end - pattern) - 1)
Evan Broderbe554312013-06-27 00:05:25 -07005112 return 0;
5113
5114 /* Finally compare the string on either side of the
5115 * wildcard */
5116 prefixlen = pattern_wildcard - pattern;
5117 suffixlen = pattern_left_label_end - (pattern_wildcard + 1);
Emeric Bruna848dae2013-10-08 11:27:28 +02005118 if ((prefixlen && (memcmp(pattern, hostname, prefixlen) != 0))
5119 || (suffixlen && (memcmp(pattern_wildcard + 1, hostname_left_label_end - suffixlen, suffixlen) != 0)))
Evan Broderbe554312013-06-27 00:05:25 -07005120 return 0;
5121
5122 return 1;
5123}
5124
5125static int ssl_sock_srv_verifycbk(int ok, X509_STORE_CTX *ctx)
5126{
5127 SSL *ssl;
5128 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01005129 struct ssl_sock_ctx *ssl_ctx;
Willy Tarreau2ab88672017-07-05 18:23:03 +02005130 const char *servername;
Willy Tarreau71d058c2017-07-26 20:09:56 +02005131 const char *sni;
Evan Broderbe554312013-06-27 00:05:25 -07005132
5133 int depth;
5134 X509 *cert;
5135 STACK_OF(GENERAL_NAME) *alt_names;
5136 int i;
5137 X509_NAME *cert_subject;
5138 char *str;
5139
5140 if (ok == 0)
5141 return ok;
5142
5143 ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
Thierry FOURNIER28962c92018-06-17 21:37:05 +02005144 conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Olivier Houchard66ab4982019-02-26 18:37:15 +01005145 ssl_ctx = conn->xprt_ctx;
Evan Broderbe554312013-06-27 00:05:25 -07005146
Willy Tarreauad92a9a2017-07-28 11:38:41 +02005147 /* We're checking if the provided hostnames match the desired one. The
5148 * desired hostname comes from the SNI we presented if any, or if not
5149 * provided then it may have been explicitly stated using a "verifyhost"
5150 * directive. If neither is set, we don't care about the name so the
5151 * verification is OK.
Willy Tarreau2ab88672017-07-05 18:23:03 +02005152 */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005153 servername = SSL_get_servername(ssl_ctx->ssl, TLSEXT_NAMETYPE_host_name);
Willy Tarreau71d058c2017-07-26 20:09:56 +02005154 sni = servername;
Willy Tarreau2ab88672017-07-05 18:23:03 +02005155 if (!servername) {
Willy Tarreau07d94e42018-09-20 10:57:52 +02005156 servername = __objt_server(conn->target)->ssl_ctx.verify_host;
Willy Tarreau2ab88672017-07-05 18:23:03 +02005157 if (!servername)
5158 return ok;
5159 }
Evan Broderbe554312013-06-27 00:05:25 -07005160
5161 /* We only need to verify the CN on the actual server cert,
5162 * not the indirect CAs */
5163 depth = X509_STORE_CTX_get_error_depth(ctx);
5164 if (depth != 0)
5165 return ok;
5166
5167 /* At this point, the cert is *not* OK unless we can find a
5168 * hostname match */
5169 ok = 0;
5170
5171 cert = X509_STORE_CTX_get_current_cert(ctx);
5172 /* It seems like this might happen if verify peer isn't set */
5173 if (!cert)
5174 return ok;
5175
5176 alt_names = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
5177 if (alt_names) {
5178 for (i = 0; !ok && i < sk_GENERAL_NAME_num(alt_names); i++) {
5179 GENERAL_NAME *name = sk_GENERAL_NAME_value(alt_names, i);
5180 if (name->type == GEN_DNS) {
Willy Tarreau9a1ab082019-05-09 13:26:41 +02005181#if HA_OPENSSL_VERSION_NUMBER < 0x00907000L
Emeric Bruna33410c2013-09-17 15:47:48 +02005182 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.ia5) >= 0) {
5183#else
Evan Broderbe554312013-06-27 00:05:25 -07005184 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
Emeric Bruna33410c2013-09-17 15:47:48 +02005185#endif
Evan Broderbe554312013-06-27 00:05:25 -07005186 ok = ssl_sock_srv_hostcheck(str, servername);
5187 OPENSSL_free(str);
5188 }
5189 }
5190 }
Emeric Brun4ad50a42013-09-17 15:19:54 +02005191 sk_GENERAL_NAME_pop_free(alt_names, GENERAL_NAME_free);
Evan Broderbe554312013-06-27 00:05:25 -07005192 }
5193
5194 cert_subject = X509_get_subject_name(cert);
5195 i = -1;
5196 while (!ok && (i = X509_NAME_get_index_by_NID(cert_subject, NID_commonName, i)) != -1) {
5197 X509_NAME_ENTRY *entry = X509_NAME_get_entry(cert_subject, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005198 ASN1_STRING *value;
5199 value = X509_NAME_ENTRY_get_data(entry);
5200 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
Evan Broderbe554312013-06-27 00:05:25 -07005201 ok = ssl_sock_srv_hostcheck(str, servername);
5202 OPENSSL_free(str);
5203 }
5204 }
5205
Willy Tarreau71d058c2017-07-26 20:09:56 +02005206 /* report the mismatch and indicate if SNI was used or not */
5207 if (!ok && !conn->err_code)
5208 conn->err_code = sni ? CO_ER_SSL_MISMATCH_SNI : CO_ER_SSL_MISMATCH;
Evan Broderbe554312013-06-27 00:05:25 -07005209 return ok;
5210}
5211
Emeric Brun94324a42012-10-11 14:00:19 +02005212/* prepare ssl context from servers options. Returns an error count */
Willy Tarreau03209342016-12-22 17:08:28 +01005213int ssl_sock_prepare_srv_ctx(struct server *srv)
Emeric Brun94324a42012-10-11 14:00:19 +02005214{
Willy Tarreau03209342016-12-22 17:08:28 +01005215 struct proxy *curproxy = srv->proxy;
Emeric Brun94324a42012-10-11 14:00:19 +02005216 int cfgerr = 0;
Remi Gacogneaf5c3da2014-05-19 10:29:58 +02005217 long options =
Emeric Brun94324a42012-10-11 14:00:19 +02005218 SSL_OP_ALL | /* all known workarounds for bugs */
5219 SSL_OP_NO_SSLv2 |
5220 SSL_OP_NO_COMPRESSION;
Remi Gacogneaf5c3da2014-05-19 10:29:58 +02005221 long mode =
Emeric Brun94324a42012-10-11 14:00:19 +02005222 SSL_MODE_ENABLE_PARTIAL_WRITE |
5223 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
Willy Tarreau396a1862014-11-13 14:06:52 +01005224 SSL_MODE_RELEASE_BUFFERS |
5225 SSL_MODE_SMALL_BUFFERS;
Emeric Brun850efd52014-01-29 12:24:34 +01005226 int verify = SSL_VERIFY_NONE;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01005227 SSL_CTX *ctx = NULL;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005228 struct tls_version_filter *conf_ssl_methods = &srv->ssl_ctx.methods;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005229 int i, min, max, hole;
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005230 int flags = MC_SSL_O_ALL;
Emeric Brun94324a42012-10-11 14:00:19 +02005231
Thierry Fournier383085f2013-01-24 14:15:43 +01005232 /* Make sure openssl opens /dev/urandom before the chroot */
5233 if (!ssl_initialize_random()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005234 ha_alert("OpenSSL random data generator initialization failed.\n");
Thierry Fournier383085f2013-01-24 14:15:43 +01005235 cfgerr++;
5236 }
5237
Willy Tarreaufce03112015-01-15 21:32:40 +01005238 /* Automatic memory computations need to know we use SSL there */
5239 global.ssl_used_backend = 1;
5240
5241 /* Initiate SSL context for current server */
Emeric Brun821bb9b2017-06-15 16:37:39 +02005242 if (!srv->ssl_ctx.reused_sess) {
Olivier Houcharde6060c52017-11-16 17:42:52 +01005243 if ((srv->ssl_ctx.reused_sess = calloc(1, global.nbthread*sizeof(*srv->ssl_ctx.reused_sess))) == NULL) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005244 ha_alert("Proxy '%s', server '%s' [%s:%d] out of memory.\n",
5245 curproxy->id, srv->id,
5246 srv->conf.file, srv->conf.line);
Emeric Brun821bb9b2017-06-15 16:37:39 +02005247 cfgerr++;
5248 return cfgerr;
5249 }
5250 }
Emeric Brun94324a42012-10-11 14:00:19 +02005251 if (srv->use_ssl)
5252 srv->xprt = &ssl_sock;
5253 if (srv->check.use_ssl)
Cyril Bonté9ce13112014-11-15 22:41:27 +01005254 srv->check.xprt = &ssl_sock;
Emeric Brun94324a42012-10-11 14:00:19 +02005255
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005256 ctx = SSL_CTX_new(SSLv23_client_method());
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01005257 if (!ctx) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005258 ha_alert("config : %s '%s', server '%s': unable to allocate ssl context.\n",
5259 proxy_type_str(curproxy), curproxy->id,
5260 srv->id);
Emeric Brun94324a42012-10-11 14:00:19 +02005261 cfgerr++;
5262 return cfgerr;
5263 }
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005264
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005265 if (conf_ssl_methods->flags && (conf_ssl_methods->min || conf_ssl_methods->max))
Christopher Faulet767a84b2017-11-24 16:50:31 +01005266 ha_warning("config : %s '%s': no-sslv3/no-tlsv1x are ignored for server '%s'. "
5267 "Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
5268 proxy_type_str(curproxy), curproxy->id, srv->id);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005269 else
5270 flags = conf_ssl_methods->flags;
5271
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005272 /* Real min and max should be determinate with configuration and openssl's capabilities */
5273 if (conf_ssl_methods->min)
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005274 flags |= (methodVersions[conf_ssl_methods->min].flag - 1);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005275 if (conf_ssl_methods->max)
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005276 flags |= ~((methodVersions[conf_ssl_methods->max].flag << 1) - 1);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005277
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02005278 /* find min, max and holes */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005279 min = max = CONF_TLSV_NONE;
5280 hole = 0;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005281 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005282 /* version is in openssl && version not disable in configuration */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005283 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005284 if (min) {
5285 if (hole) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005286 ha_warning("config : %s '%s': SSL/TLS versions range not contiguous for server '%s'. "
5287 "Hole find for %s. Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
5288 proxy_type_str(curproxy), curproxy->id, srv->id,
5289 methodVersions[hole].name);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005290 hole = 0;
5291 }
5292 max = i;
5293 }
5294 else {
5295 min = max = i;
5296 }
5297 }
5298 else {
5299 if (min)
5300 hole = i;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005301 }
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005302 if (!min) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005303 ha_alert("config : %s '%s': all SSL/TLS versions are disabled for server '%s'.\n",
5304 proxy_type_str(curproxy), curproxy->id, srv->id);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005305 cfgerr += 1;
5306 }
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005307
Willy Tarreau9a1ab082019-05-09 13:26:41 +02005308#if (HA_OPENSSL_VERSION_NUMBER < 0x1010000fL)
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005309 /* Keep force-xxx implementation as it is in older haproxy. It's a
Joseph Herlant017b3da2018-11-15 09:07:59 -08005310 precautionary measure to avoid any surprise with older openssl version. */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005311 if (min == max)
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02005312 methodVersions[min].ctx_set_version(ctx, SET_CLIENT);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005313 else
5314 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
5315 if (flags & methodVersions[i].flag)
5316 options |= methodVersions[i].option;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005317#else /* openssl >= 1.1.0 */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005318 /* set the max_version is required to cap TLS version or activate new TLS (v1.3) */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02005319 methodVersions[min].ctx_set_version(ctx, SET_MIN);
5320 methodVersions[max].ctx_set_version(ctx, SET_MAX);
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005321#endif
5322
5323 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLS_TICKETS)
5324 options |= SSL_OP_NO_TICKET;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01005325 SSL_CTX_set_options(ctx, options);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005326
Willy Tarreau5db847a2019-05-09 14:13:35 +02005327#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005328 if (global_ssl.async)
5329 mode |= SSL_MODE_ASYNC;
5330#endif
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01005331 SSL_CTX_set_mode(ctx, mode);
5332 srv->ssl_ctx.ctx = ctx;
5333
Emeric Bruna7aa3092012-10-26 12:58:00 +02005334 if (srv->ssl_ctx.client_crt) {
5335 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 +01005336 ha_alert("config : %s '%s', server '%s': unable to load SSL private key from PEM file '%s'.\n",
5337 proxy_type_str(curproxy), curproxy->id,
5338 srv->id, srv->ssl_ctx.client_crt);
Emeric Bruna7aa3092012-10-26 12:58:00 +02005339 cfgerr++;
5340 }
5341 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 +01005342 ha_alert("config : %s '%s', server '%s': unable to load ssl certificate from PEM file '%s'.\n",
5343 proxy_type_str(curproxy), curproxy->id,
5344 srv->id, srv->ssl_ctx.client_crt);
Emeric Bruna7aa3092012-10-26 12:58:00 +02005345 cfgerr++;
5346 }
5347 else if (SSL_CTX_check_private_key(srv->ssl_ctx.ctx) <= 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005348 ha_alert("config : %s '%s', server '%s': inconsistencies between private key and certificate loaded from PEM file '%s'.\n",
5349 proxy_type_str(curproxy), curproxy->id,
5350 srv->id, srv->ssl_ctx.client_crt);
Emeric Bruna7aa3092012-10-26 12:58:00 +02005351 cfgerr++;
5352 }
5353 }
Emeric Brun94324a42012-10-11 14:00:19 +02005354
Emeric Brun850efd52014-01-29 12:24:34 +01005355 if (global.ssl_server_verify == SSL_SERVER_VERIFY_REQUIRED)
5356 verify = SSL_VERIFY_PEER;
Emeric Brun850efd52014-01-29 12:24:34 +01005357 switch (srv->ssl_ctx.verify) {
5358 case SSL_SOCK_VERIFY_NONE:
5359 verify = SSL_VERIFY_NONE;
5360 break;
5361 case SSL_SOCK_VERIFY_REQUIRED:
5362 verify = SSL_VERIFY_PEER;
5363 break;
5364 }
Evan Broderbe554312013-06-27 00:05:25 -07005365 SSL_CTX_set_verify(srv->ssl_ctx.ctx,
Emeric Brun850efd52014-01-29 12:24:34 +01005366 verify,
Willy Tarreau2ab88672017-07-05 18:23:03 +02005367 (srv->ssl_ctx.verify_host || (verify & SSL_VERIFY_PEER)) ? ssl_sock_srv_verifycbk : NULL);
Emeric Brun850efd52014-01-29 12:24:34 +01005368 if (verify & SSL_VERIFY_PEER) {
Emeric Brunef42d922012-10-11 16:11:36 +02005369 if (srv->ssl_ctx.ca_file) {
5370 /* load CAfile to verify */
5371 if (!SSL_CTX_load_verify_locations(srv->ssl_ctx.ctx, srv->ssl_ctx.ca_file, NULL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005372 ha_alert("Proxy '%s', server '%s' [%s:%d] unable to load CA file '%s'.\n",
5373 curproxy->id, srv->id,
5374 srv->conf.file, srv->conf.line, srv->ssl_ctx.ca_file);
Emeric Brunef42d922012-10-11 16:11:36 +02005375 cfgerr++;
5376 }
5377 }
Emeric Brun850efd52014-01-29 12:24:34 +01005378 else {
5379 if (global.ssl_server_verify == SSL_SERVER_VERIFY_REQUIRED)
Christopher Faulet767a84b2017-11-24 16:50:31 +01005380 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",
5381 curproxy->id, srv->id,
5382 srv->conf.file, srv->conf.line);
Emeric Brun850efd52014-01-29 12:24:34 +01005383 else
Christopher Faulet767a84b2017-11-24 16:50:31 +01005384 ha_alert("Proxy '%s', server '%s' [%s:%d] verify is enabled but no CA file specified.\n",
5385 curproxy->id, srv->id,
5386 srv->conf.file, srv->conf.line);
Emeric Brun850efd52014-01-29 12:24:34 +01005387 cfgerr++;
5388 }
Emeric Brunef42d922012-10-11 16:11:36 +02005389#ifdef X509_V_FLAG_CRL_CHECK
5390 if (srv->ssl_ctx.crl_file) {
5391 X509_STORE *store = SSL_CTX_get_cert_store(srv->ssl_ctx.ctx);
5392
5393 if (!store || !X509_STORE_load_locations(store, srv->ssl_ctx.crl_file, NULL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005394 ha_alert("Proxy '%s', server '%s' [%s:%d] unable to configure CRL file '%s'.\n",
5395 curproxy->id, srv->id,
5396 srv->conf.file, srv->conf.line, srv->ssl_ctx.crl_file);
Emeric Brunef42d922012-10-11 16:11:36 +02005397 cfgerr++;
5398 }
5399 else {
5400 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
5401 }
5402 }
5403#endif
5404 }
5405
Olivier Houchardbd84ac82017-11-03 13:43:35 +01005406 SSL_CTX_set_session_cache_mode(srv->ssl_ctx.ctx, SSL_SESS_CACHE_CLIENT |
5407 SSL_SESS_CACHE_NO_INTERNAL_STORE);
5408 SSL_CTX_sess_set_new_cb(srv->ssl_ctx.ctx, ssl_sess_new_srv_cb);
Emeric Brun94324a42012-10-11 14:00:19 +02005409 if (srv->ssl_ctx.ciphers &&
5410 !SSL_CTX_set_cipher_list(srv->ssl_ctx.ctx, srv->ssl_ctx.ciphers)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005411 ha_alert("Proxy '%s', server '%s' [%s:%d] : unable to set SSL cipher list to '%s'.\n",
5412 curproxy->id, srv->id,
5413 srv->conf.file, srv->conf.line, srv->ssl_ctx.ciphers);
Emeric Brun94324a42012-10-11 14:00:19 +02005414 cfgerr++;
5415 }
Dirkjan Bussink415150f2018-09-14 11:14:21 +02005416
Emmanuel Hocdet839af572019-05-14 16:27:35 +02005417#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02005418 if (srv->ssl_ctx.ciphersuites &&
Pierre Cheynierbc34cd12019-03-21 16:15:47 +00005419 !SSL_CTX_set_ciphersuites(srv->ssl_ctx.ctx, srv->ssl_ctx.ciphersuites)) {
Dirkjan Bussink415150f2018-09-14 11:14:21 +02005420 ha_alert("Proxy '%s', server '%s' [%s:%d] : unable to set TLS 1.3 cipher suites to '%s'.\n",
5421 curproxy->id, srv->id,
5422 srv->conf.file, srv->conf.line, srv->ssl_ctx.ciphersuites);
5423 cfgerr++;
5424 }
5425#endif
Olivier Houchardc7566002018-11-20 23:33:50 +01005426#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
5427 if (srv->ssl_ctx.npn_str)
5428 SSL_CTX_set_next_proto_select_cb(ctx, ssl_sock_srv_select_protos, srv);
5429#endif
5430#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
5431 if (srv->ssl_ctx.alpn_str)
5432 SSL_CTX_set_alpn_protos(ctx, (unsigned char *)srv->ssl_ctx.alpn_str, srv->ssl_ctx.alpn_len);
5433#endif
5434
Emeric Brun94324a42012-10-11 14:00:19 +02005435
5436 return cfgerr;
5437}
5438
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005439/* Walks down the two trees in bind_conf and prepares all certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +02005440 * be NULL, in which case nothing is done. Returns the number of errors
5441 * encountered.
5442 */
Willy Tarreau03209342016-12-22 17:08:28 +01005443int ssl_sock_prepare_all_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02005444{
5445 struct ebmb_node *node;
5446 struct sni_ctx *sni;
5447 int err = 0;
5448
Willy Tarreaufce03112015-01-15 21:32:40 +01005449 /* Automatic memory computations need to know we use SSL there */
5450 global.ssl_used_frontend = 1;
5451
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01005452 /* Make sure openssl opens /dev/urandom before the chroot */
5453 if (!ssl_initialize_random()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005454 ha_alert("OpenSSL random data generator initialization failed.\n");
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01005455 err++;
5456 }
5457 /* Create initial_ctx used to start the ssl connection before do switchctx */
5458 if (!bind_conf->initial_ctx) {
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005459 err += ssl_sock_initial_ctx(bind_conf);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01005460 /* It should not be necessary to call this function, but it's
5461 necessary first to check and move all initialisation related
5462 to initial_ctx in ssl_sock_initial_ctx. */
5463 err += ssl_sock_prepare_ctx(bind_conf, NULL, bind_conf->initial_ctx);
5464 }
Emeric Brun0bed9942014-10-30 19:25:24 +01005465 if (bind_conf->default_ctx)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005466 err += ssl_sock_prepare_ctx(bind_conf, bind_conf->default_ssl_conf, bind_conf->default_ctx);
Emeric Brun0bed9942014-10-30 19:25:24 +01005467
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005468 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02005469 while (node) {
5470 sni = ebmb_entry(node, struct sni_ctx, name);
Emeric Brun0bed9942014-10-30 19:25:24 +01005471 if (!sni->order && sni->ctx != bind_conf->default_ctx)
5472 /* only initialize the CTX on its first occurrence and
5473 if it is not the default_ctx */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005474 err += ssl_sock_prepare_ctx(bind_conf, sni->conf, sni->ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02005475 node = ebmb_next(node);
5476 }
5477
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005478 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02005479 while (node) {
5480 sni = ebmb_entry(node, struct sni_ctx, name);
Emeric Brun0bed9942014-10-30 19:25:24 +01005481 if (!sni->order && sni->ctx != bind_conf->default_ctx)
5482 /* only initialize the CTX on its first occurrence and
5483 if it is not the default_ctx */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005484 err += ssl_sock_prepare_ctx(bind_conf, sni->conf, sni->ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02005485 node = ebmb_next(node);
5486 }
5487 return err;
5488}
5489
Willy Tarreau55d37912016-12-21 23:38:39 +01005490/* Prepares all the contexts for a bind_conf and allocates the shared SSL
5491 * context if needed. Returns < 0 on error, 0 on success. The warnings and
5492 * alerts are directly emitted since the rest of the stack does it below.
5493 */
5494int ssl_sock_prepare_bind_conf(struct bind_conf *bind_conf)
5495{
5496 struct proxy *px = bind_conf->frontend;
5497 int alloc_ctx;
5498 int err;
5499
5500 if (!bind_conf->is_ssl) {
5501 if (bind_conf->default_ctx) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005502 ha_warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
5503 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreau55d37912016-12-21 23:38:39 +01005504 }
5505 return 0;
5506 }
5507 if (!bind_conf->default_ctx) {
Emmanuel Hocdetaa0d6372017-08-09 11:24:25 +02005508 if (bind_conf->strict_sni && !bind_conf->generate_certs) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005509 ha_warning("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d], ssl connections will fail (use 'crt').\n",
5510 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetaa0d6372017-08-09 11:24:25 +02005511 }
5512 else {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005513 ha_alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
5514 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetaa0d6372017-08-09 11:24:25 +02005515 return -1;
5516 }
Willy Tarreau55d37912016-12-21 23:38:39 +01005517 }
William Lallemandc61c0b32017-12-04 18:46:39 +01005518 if (!ssl_shctx && global.tune.sslcachesize) {
William Lallemandc3cd35f2017-11-28 11:04:43 +01005519 alloc_ctx = shctx_init(&ssl_shctx, global.tune.sslcachesize,
Frédéric Lécailleb7838af2018-10-22 16:21:39 +02005520 sizeof(struct sh_ssl_sess_hdr) + SHSESS_BLOCK_MIN_SIZE, -1,
William Lallemandc3cd35f2017-11-28 11:04:43 +01005521 sizeof(*sh_ssl_sess_tree),
5522 ((global.nbthread > 1) || (!global_ssl.private_cache && (global.nbproc > 1))) ? 1 : 0);
Frédéric Lécaille4c8aa112018-10-25 20:22:46 +02005523 if (alloc_ctx <= 0) {
William Lallemandc3cd35f2017-11-28 11:04:43 +01005524 if (alloc_ctx == SHCTX_E_INIT_LOCK)
5525 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");
5526 else
5527 ha_alert("Unable to allocate SSL session cache.\n");
5528 return -1;
5529 }
5530 /* free block callback */
5531 ssl_shctx->free_block = sh_ssl_sess_free_blocks;
5532 /* init the root tree within the extra space */
5533 sh_ssl_sess_tree = (void *)ssl_shctx + sizeof(struct shared_context);
5534 *sh_ssl_sess_tree = EB_ROOT_UNIQUE;
Willy Tarreau55d37912016-12-21 23:38:39 +01005535 }
Willy Tarreau55d37912016-12-21 23:38:39 +01005536 err = 0;
5537 /* initialize all certificate contexts */
5538 err += ssl_sock_prepare_all_ctx(bind_conf);
5539
5540 /* initialize CA variables if the certificates generation is enabled */
5541 err += ssl_sock_load_ca(bind_conf);
5542
5543 return -err;
5544}
Christopher Faulet77fe80c2015-07-29 13:02:40 +02005545
5546/* release ssl context allocated for servers. */
5547void ssl_sock_free_srv_ctx(struct server *srv)
5548{
Olivier Houchardc7566002018-11-20 23:33:50 +01005549#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
5550 if (srv->ssl_ctx.alpn_str)
5551 free(srv->ssl_ctx.alpn_str);
5552#endif
Lukas Tribusda95fd92018-11-25 13:21:27 +01005553#ifdef OPENSSL_NPN_NEGOTIATED
Olivier Houchardc7566002018-11-20 23:33:50 +01005554 if (srv->ssl_ctx.npn_str)
5555 free(srv->ssl_ctx.npn_str);
Lukas Tribus7706b852018-11-26 22:57:17 +01005556#endif
Christopher Faulet77fe80c2015-07-29 13:02:40 +02005557 if (srv->ssl_ctx.ctx)
5558 SSL_CTX_free(srv->ssl_ctx.ctx);
5559}
5560
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005561/* Walks down the two trees in bind_conf and frees all the certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +02005562 * be NULL, in which case nothing is done. The default_ctx is nullified too.
5563 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005564void ssl_sock_free_all_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02005565{
5566 struct ebmb_node *node, *back;
5567 struct sni_ctx *sni;
5568
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005569 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02005570 while (node) {
5571 sni = ebmb_entry(node, struct sni_ctx, name);
5572 back = ebmb_next(node);
5573 ebmb_delete(node);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005574 if (!sni->order) { /* only free the CTX on its first occurrence */
Emeric Brunfc0421f2012-09-07 17:30:07 +02005575 SSL_CTX_free(sni->ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005576 ssl_sock_free_ssl_conf(sni->conf);
5577 free(sni->conf);
5578 sni->conf = NULL;
5579 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02005580 free(sni);
5581 node = back;
5582 }
5583
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005584 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02005585 while (node) {
5586 sni = ebmb_entry(node, struct sni_ctx, name);
5587 back = ebmb_next(node);
5588 ebmb_delete(node);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005589 if (!sni->order) { /* only free the CTX on its first occurrence */
Emeric Brunfc0421f2012-09-07 17:30:07 +02005590 SSL_CTX_free(sni->ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005591 ssl_sock_free_ssl_conf(sni->conf);
5592 free(sni->conf);
5593 sni->conf = NULL;
5594 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02005595 free(sni);
5596 node = back;
5597 }
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01005598 SSL_CTX_free(bind_conf->initial_ctx);
5599 bind_conf->initial_ctx = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005600 bind_conf->default_ctx = NULL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005601 bind_conf->default_ssl_conf = NULL;
Emeric Brune1f38db2012-09-03 20:36:47 +02005602}
5603
Willy Tarreau795cdab2016-12-22 17:30:54 +01005604/* Destroys all the contexts for a bind_conf. This is used during deinit(). */
5605void ssl_sock_destroy_bind_conf(struct bind_conf *bind_conf)
5606{
5607 ssl_sock_free_ca(bind_conf);
5608 ssl_sock_free_all_ctx(bind_conf);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005609 ssl_sock_free_ssl_conf(&bind_conf->ssl_conf);
Willy Tarreau795cdab2016-12-22 17:30:54 +01005610 free(bind_conf->ca_sign_file);
5611 free(bind_conf->ca_sign_pass);
Willy Tarreau17b4aa12018-07-17 10:05:32 +02005612 if (bind_conf->keys_ref && !--bind_conf->keys_ref->refcount) {
Willy Tarreau795cdab2016-12-22 17:30:54 +01005613 free(bind_conf->keys_ref->filename);
5614 free(bind_conf->keys_ref->tlskeys);
5615 LIST_DEL(&bind_conf->keys_ref->list);
5616 free(bind_conf->keys_ref);
5617 }
5618 bind_conf->keys_ref = NULL;
Willy Tarreau795cdab2016-12-22 17:30:54 +01005619 bind_conf->ca_sign_pass = NULL;
5620 bind_conf->ca_sign_file = NULL;
Willy Tarreau795cdab2016-12-22 17:30:54 +01005621}
5622
Christopher Faulet31af49d2015-06-09 17:29:50 +02005623/* Load CA cert file and private key used to generate certificates */
5624int
Willy Tarreau03209342016-12-22 17:08:28 +01005625ssl_sock_load_ca(struct bind_conf *bind_conf)
Christopher Faulet31af49d2015-06-09 17:29:50 +02005626{
Willy Tarreau03209342016-12-22 17:08:28 +01005627 struct proxy *px = bind_conf->frontend;
Christopher Faulet31af49d2015-06-09 17:29:50 +02005628 FILE *fp;
5629 X509 *cacert = NULL;
5630 EVP_PKEY *capkey = NULL;
5631 int err = 0;
5632
Christopher Fauletf8bb0ce2017-09-15 09:52:49 +02005633 if (!bind_conf->generate_certs)
Christopher Faulet31af49d2015-06-09 17:29:50 +02005634 return err;
5635
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005636#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Emeric Brun821bb9b2017-06-15 16:37:39 +02005637 if (global_ssl.ctx_cache) {
Willy Tarreauef934602016-12-22 23:12:01 +01005638 ssl_ctx_lru_tree = lru64_new(global_ssl.ctx_cache);
Emeric Brun821bb9b2017-06-15 16:37:39 +02005639 }
Christopher Fauletd2cab922015-07-28 16:03:47 +02005640 ssl_ctx_lru_seed = (unsigned int)time(NULL);
Emeric Brun821bb9b2017-06-15 16:37:39 +02005641 ssl_ctx_serial = now_ms;
Willy Tarreaua84c2672015-10-09 12:10:13 +02005642#endif
Christopher Fauletd2cab922015-07-28 16:03:47 +02005643
Christopher Faulet31af49d2015-06-09 17:29:50 +02005644 if (!bind_conf->ca_sign_file) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005645 ha_alert("Proxy '%s': cannot enable certificate generation, "
5646 "no CA certificate File configured at [%s:%d].\n",
5647 px->id, bind_conf->file, bind_conf->line);
Christopher Faulet31af49d2015-06-09 17:29:50 +02005648 goto load_error;
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005649 }
Christopher Faulet31af49d2015-06-09 17:29:50 +02005650
5651 /* read in the CA certificate */
5652 if (!(fp = fopen(bind_conf->ca_sign_file, "r"))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005653 ha_alert("Proxy '%s': Failed to read CA certificate file '%s' at [%s:%d].\n",
5654 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Faulet31af49d2015-06-09 17:29:50 +02005655 goto load_error;
5656 }
5657 if (!(cacert = PEM_read_X509(fp, NULL, NULL, NULL))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005658 ha_alert("Proxy '%s': Failed to read CA certificate file '%s' at [%s:%d].\n",
5659 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005660 goto read_error;
Christopher Faulet31af49d2015-06-09 17:29:50 +02005661 }
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005662 rewind(fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02005663 if (!(capkey = PEM_read_PrivateKey(fp, NULL, NULL, bind_conf->ca_sign_pass))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005664 ha_alert("Proxy '%s': Failed to read CA private key file '%s' at [%s:%d].\n",
5665 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005666 goto read_error;
Christopher Faulet31af49d2015-06-09 17:29:50 +02005667 }
Christopher Faulet31af49d2015-06-09 17:29:50 +02005668
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005669 fclose (fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02005670 bind_conf->ca_sign_cert = cacert;
5671 bind_conf->ca_sign_pkey = capkey;
5672 return err;
5673
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005674 read_error:
5675 fclose (fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02005676 if (capkey) EVP_PKEY_free(capkey);
5677 if (cacert) X509_free(cacert);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005678 load_error:
5679 bind_conf->generate_certs = 0;
5680 err++;
Christopher Faulet31af49d2015-06-09 17:29:50 +02005681 return err;
5682}
5683
5684/* Release CA cert and private key used to generate certificated */
5685void
5686ssl_sock_free_ca(struct bind_conf *bind_conf)
5687{
Christopher Faulet31af49d2015-06-09 17:29:50 +02005688 if (bind_conf->ca_sign_pkey)
5689 EVP_PKEY_free(bind_conf->ca_sign_pkey);
5690 if (bind_conf->ca_sign_cert)
5691 X509_free(bind_conf->ca_sign_cert);
Willy Tarreau94ff03a2016-12-22 17:57:46 +01005692 bind_conf->ca_sign_pkey = NULL;
5693 bind_conf->ca_sign_cert = NULL;
Christopher Faulet31af49d2015-06-09 17:29:50 +02005694}
5695
Emeric Brun46591952012-05-18 15:47:34 +02005696/*
5697 * This function is called if SSL * context is not yet allocated. The function
5698 * is designed to be called before any other data-layer operation and sets the
5699 * handshake flag on the connection. It is safe to call it multiple times.
5700 * It returns 0 on success and -1 in error case.
5701 */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005702static int ssl_sock_init(struct connection *conn, void **xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02005703{
Olivier Houchard66ab4982019-02-26 18:37:15 +01005704 struct ssl_sock_ctx *ctx;
Emeric Brun46591952012-05-18 15:47:34 +02005705 /* already initialized */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005706 if (*xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02005707 return 0;
5708
Willy Tarreau3c728722014-01-23 13:50:42 +01005709 if (!conn_ctrl_ready(conn))
Willy Tarreauf79c8172013-10-21 16:30:56 +02005710 return 0;
5711
Olivier Houchard66ab4982019-02-26 18:37:15 +01005712 ctx = pool_alloc(ssl_sock_ctx_pool);
5713 if (!ctx) {
5714 conn->err_code = CO_ER_SSL_NO_MEM;
5715 return -1;
5716 }
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02005717 ctx->wait_event.tasklet = tasklet_new();
5718 if (!ctx->wait_event.tasklet) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02005719 conn->err_code = CO_ER_SSL_NO_MEM;
5720 pool_free(ssl_sock_ctx_pool, ctx);
5721 return -1;
5722 }
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02005723 ctx->wait_event.tasklet->process = ssl_sock_io_cb;
5724 ctx->wait_event.tasklet->context = ctx;
Olivier Houchardea8dd942019-05-20 14:02:16 +02005725 ctx->wait_event.events = 0;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01005726 ctx->sent_early_data = 0;
5727 ctx->tmp_early_data = -1;
Olivier Houcharda8955d52019-04-07 22:00:38 +02005728 ctx->conn = conn;
Olivier Houchard81284e62019-06-06 13:21:23 +02005729 ctx->send_wait = NULL;
5730 ctx->recv_wait = NULL;
Emeric Brun5762a0d2019-09-06 15:36:02 +02005731 ctx->xprt_st = 0;
5732 ctx->xprt_ctx = NULL;
Olivier Houcharda8955d52019-04-07 22:00:38 +02005733
5734 /* Only work with sockets for now, this should be adapted when we'll
5735 * add QUIC support.
5736 */
5737 ctx->xprt = xprt_get(XPRT_RAW);
Olivier Houchard19afb272019-05-23 18:24:07 +02005738 if (ctx->xprt->init) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02005739 if (ctx->xprt->init(conn, &ctx->xprt_ctx) != 0)
5740 goto err;
Olivier Houchard19afb272019-05-23 18:24:07 +02005741 }
Olivier Houchard66ab4982019-02-26 18:37:15 +01005742
Willy Tarreau20879a02012-12-03 16:32:10 +01005743 if (global.maxsslconn && sslconns >= global.maxsslconn) {
5744 conn->err_code = CO_ER_SSL_TOO_MANY;
Olivier Houchardea8dd942019-05-20 14:02:16 +02005745 goto err;
Willy Tarreau20879a02012-12-03 16:32:10 +01005746 }
Willy Tarreau403edff2012-09-06 11:58:37 +02005747
Emeric Brun46591952012-05-18 15:47:34 +02005748 /* If it is in client mode initiate SSL session
5749 in connect state otherwise accept state */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01005750 if (objt_server(conn->target)) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005751 int may_retry = 1;
5752
5753 retry_connect:
Emeric Brun46591952012-05-18 15:47:34 +02005754 /* Alloc a new SSL session ctx */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005755 ctx->ssl = SSL_new(__objt_server(conn->target)->ssl_ctx.ctx);
5756 if (!ctx->ssl) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005757 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005758 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005759 goto retry_connect;
5760 }
Willy Tarreau20879a02012-12-03 16:32:10 +01005761 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01005762 goto err;
Willy Tarreau20879a02012-12-03 16:32:10 +01005763 }
Olivier Houcharda8955d52019-04-07 22:00:38 +02005764 ctx->bio = BIO_new(ha_meth);
5765 if (!ctx->bio) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005766 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005767 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005768 goto retry_connect;
5769 }
Emeric Brun55476152014-11-12 17:35:37 +01005770 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01005771 goto err;
Emeric Brun55476152014-11-12 17:35:37 +01005772 }
Olivier Houcharda8955d52019-04-07 22:00:38 +02005773 BIO_set_data(ctx->bio, ctx);
Olivier Houcharda8955d52019-04-07 22:00:38 +02005774 SSL_set_bio(ctx->ssl, ctx->bio, ctx->bio);
Emeric Brun46591952012-05-18 15:47:34 +02005775
Evan Broderbe554312013-06-27 00:05:25 -07005776 /* set connection pointer */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005777 if (!SSL_set_ex_data(ctx->ssl, ssl_app_data_index, conn)) {
5778 SSL_free(ctx->ssl);
5779 ctx->ssl = NULL;
Emeric Brun55476152014-11-12 17:35:37 +01005780 conn->xprt_ctx = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005781 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005782 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005783 goto retry_connect;
5784 }
Emeric Brun55476152014-11-12 17:35:37 +01005785 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01005786 goto err;
Emeric Brun55476152014-11-12 17:35:37 +01005787 }
5788
Olivier Houchard66ab4982019-02-26 18:37:15 +01005789 SSL_set_connect_state(ctx->ssl);
Willy Tarreau07d94e42018-09-20 10:57:52 +02005790 if (__objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr) {
5791 const unsigned char *ptr = __objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr;
5792 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 +01005793 if (sess && !SSL_set_session(ctx->ssl, sess)) {
Olivier Houcharde6060c52017-11-16 17:42:52 +01005794 SSL_SESSION_free(sess);
Willy Tarreau07d94e42018-09-20 10:57:52 +02005795 free(__objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr);
5796 __objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr = NULL;
Olivier Houcharde6060c52017-11-16 17:42:52 +01005797 } else if (sess) {
5798 SSL_SESSION_free(sess);
Emeric Brun55476152014-11-12 17:35:37 +01005799 }
5800 }
Evan Broderbe554312013-06-27 00:05:25 -07005801
Emeric Brun46591952012-05-18 15:47:34 +02005802 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +02005803 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Willy Tarreau403edff2012-09-06 11:58:37 +02005804
Olivier Houchard2be5a4c2019-03-08 18:54:43 +01005805 _HA_ATOMIC_ADD(&sslconns, 1);
5806 _HA_ATOMIC_ADD(&totalsslconns, 1);
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005807 *xprt_ctx = ctx;
Olivier Houchardea8dd942019-05-20 14:02:16 +02005808 /* Start the handshake */
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02005809 tasklet_wakeup(ctx->wait_event.tasklet);
Olivier Houchardea8dd942019-05-20 14:02:16 +02005810 if (conn->flags & CO_FL_ERROR)
5811 goto err;
Emeric Brun46591952012-05-18 15:47:34 +02005812 return 0;
5813 }
Willy Tarreau3fdb3662012-11-12 00:42:33 +01005814 else if (objt_listener(conn->target)) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005815 int may_retry = 1;
5816
5817 retry_accept:
Emeric Brun46591952012-05-18 15:47:34 +02005818 /* Alloc a new SSL session ctx */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005819 ctx->ssl = SSL_new(__objt_listener(conn->target)->bind_conf->initial_ctx);
5820 if (!ctx->ssl) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005821 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005822 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005823 goto retry_accept;
5824 }
Willy Tarreau20879a02012-12-03 16:32:10 +01005825 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01005826 goto err;
Willy Tarreau20879a02012-12-03 16:32:10 +01005827 }
Emeric Brun46591952012-05-18 15:47:34 +02005828
Olivier Houcharda8955d52019-04-07 22:00:38 +02005829 ctx->bio = BIO_new(ha_meth);
5830 if (!ctx->bio) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005831 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005832 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005833 goto retry_accept;
5834 }
Emeric Brun55476152014-11-12 17:35:37 +01005835 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01005836 goto err;
Emeric Brun55476152014-11-12 17:35:37 +01005837 }
Olivier Houcharda8955d52019-04-07 22:00:38 +02005838 BIO_set_data(ctx->bio, ctx);
Olivier Houcharda8955d52019-04-07 22:00:38 +02005839 SSL_set_bio(ctx->ssl, ctx->bio, ctx->bio);
Emeric Brun46591952012-05-18 15:47:34 +02005840
Emeric Brune1f38db2012-09-03 20:36:47 +02005841 /* set connection pointer */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005842 if (!SSL_set_ex_data(ctx->ssl, ssl_app_data_index, conn)) {
5843 SSL_free(ctx->ssl);
5844 ctx->ssl = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005845 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005846 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005847 goto retry_accept;
5848 }
Emeric Brun55476152014-11-12 17:35:37 +01005849 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01005850 goto err;
Emeric Brun55476152014-11-12 17:35:37 +01005851 }
5852
Olivier Houchard66ab4982019-02-26 18:37:15 +01005853 SSL_set_accept_state(ctx->ssl);
Emeric Brune1f38db2012-09-03 20:36:47 +02005854
Emeric Brun46591952012-05-18 15:47:34 +02005855 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +02005856 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Emmanuel Hocdetf967c312019-08-05 18:04:16 +02005857#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Olivier Houchardc2aae742017-09-22 18:26:28 +02005858 conn->flags |= CO_FL_EARLY_SSL_HS;
5859#endif
Willy Tarreau403edff2012-09-06 11:58:37 +02005860
Olivier Houchard2be5a4c2019-03-08 18:54:43 +01005861 _HA_ATOMIC_ADD(&sslconns, 1);
5862 _HA_ATOMIC_ADD(&totalsslconns, 1);
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005863 *xprt_ctx = ctx;
Olivier Houchardea8dd942019-05-20 14:02:16 +02005864 /* Start the handshake */
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02005865 tasklet_wakeup(ctx->wait_event.tasklet);
Olivier Houchardea8dd942019-05-20 14:02:16 +02005866 if (conn->flags & CO_FL_ERROR)
5867 goto err;
Emeric Brun46591952012-05-18 15:47:34 +02005868 return 0;
5869 }
5870 /* don't know how to handle such a target */
Willy Tarreau20879a02012-12-03 16:32:10 +01005871 conn->err_code = CO_ER_SSL_NO_TARGET;
Olivier Houchard66ab4982019-02-26 18:37:15 +01005872err:
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02005873 if (ctx && ctx->wait_event.tasklet)
5874 tasklet_free(ctx->wait_event.tasklet);
Olivier Houchard66ab4982019-02-26 18:37:15 +01005875 pool_free(ssl_sock_ctx_pool, ctx);
Emeric Brun46591952012-05-18 15:47:34 +02005876 return -1;
5877}
5878
5879
5880/* This is the callback which is used when an SSL handshake is pending. It
5881 * updates the FD status if it wants some polling before being called again.
5882 * It returns 0 if it fails in a fatal way or needs to poll to go further,
5883 * otherwise it returns non-zero and removes itself from the connection's
5884 * flags (the bit is provided in <flag> by the caller).
5885 */
Olivier Houchard000694c2019-05-23 14:45:12 +02005886static int ssl_sock_handshake(struct connection *conn, unsigned int flag)
Emeric Brun46591952012-05-18 15:47:34 +02005887{
Olivier Houchard66ab4982019-02-26 18:37:15 +01005888 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
Emeric Brun46591952012-05-18 15:47:34 +02005889 int ret;
5890
Willy Tarreau3c728722014-01-23 13:50:42 +01005891 if (!conn_ctrl_ready(conn))
Willy Tarreauf79c8172013-10-21 16:30:56 +02005892 return 0;
5893
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005894 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02005895 goto out_error;
5896
Willy Tarreau5db847a2019-05-09 14:13:35 +02005897#if HA_OPENSSL_VERSION_NUMBER >= 0x10101000L
Olivier Houchardc2aae742017-09-22 18:26:28 +02005898 /*
5899 * Check if we have early data. If we do, we have to read them
5900 * before SSL_do_handshake() is called, And there's no way to
5901 * detect early data, except to try to read them
5902 */
5903 if (conn->flags & CO_FL_EARLY_SSL_HS) {
5904 size_t read_data;
5905
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01005906 ret = SSL_read_early_data(ctx->ssl, &ctx->tmp_early_data,
Olivier Houchardc2aae742017-09-22 18:26:28 +02005907 1, &read_data);
5908 if (ret == SSL_READ_EARLY_DATA_ERROR)
5909 goto check_error;
5910 if (ret == SSL_READ_EARLY_DATA_SUCCESS) {
5911 conn->flags &= ~(CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN);
5912 return 1;
5913 } else
5914 conn->flags &= ~CO_FL_EARLY_SSL_HS;
5915 }
5916#endif
Emeric Brun674b7432012-11-08 19:21:55 +01005917 /* If we use SSL_do_handshake to process a reneg initiated by
5918 * the remote peer, it sometimes returns SSL_ERROR_SSL.
5919 * Usually SSL_write and SSL_read are used and process implicitly
5920 * the reneg handshake.
5921 * Here we use SSL_peek as a workaround for reneg.
5922 */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005923 if ((conn->flags & CO_FL_CONNECTED) && SSL_renegotiate_pending(ctx->ssl)) {
Emeric Brun674b7432012-11-08 19:21:55 +01005924 char c;
5925
Olivier Houchard66ab4982019-02-26 18:37:15 +01005926 ret = SSL_peek(ctx->ssl, &c, 1);
Emeric Brun674b7432012-11-08 19:21:55 +01005927 if (ret <= 0) {
5928 /* handshake may have not been completed, let's find why */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005929 ret = SSL_get_error(ctx->ssl, ret);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005930
Emeric Brun674b7432012-11-08 19:21:55 +01005931 if (ret == SSL_ERROR_WANT_WRITE) {
5932 /* SSL handshake needs to write, L4 connection may not be ready */
Olivier Houchard03abf2d2019-05-28 10:12:02 +02005933 if (!(ctx->wait_event.events & SUB_RETRY_SEND))
Olivier Houchardea8dd942019-05-20 14:02:16 +02005934 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_SEND, &ctx->wait_event);
Emeric Brun674b7432012-11-08 19:21:55 +01005935 return 0;
5936 }
5937 else if (ret == SSL_ERROR_WANT_READ) {
5938 /* handshake may have been completed but we have
5939 * no more data to read.
5940 */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005941 if (!SSL_renegotiate_pending(ctx->ssl)) {
Emeric Brun674b7432012-11-08 19:21:55 +01005942 ret = 1;
5943 goto reneg_ok;
5944 }
5945 /* SSL handshake needs to read, L4 connection is ready */
Olivier Houchard03abf2d2019-05-28 10:12:02 +02005946 if (!(ctx->wait_event.events & SUB_RETRY_RECV))
Olivier Houchardea8dd942019-05-20 14:02:16 +02005947 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_RECV, &ctx->wait_event);
Emeric Brun674b7432012-11-08 19:21:55 +01005948 return 0;
5949 }
Willy Tarreau5db847a2019-05-09 14:13:35 +02005950#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005951 else if (ret == SSL_ERROR_WANT_ASYNC) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02005952 ssl_async_process_fds(ctx);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005953 return 0;
5954 }
5955#endif
Emeric Brun674b7432012-11-08 19:21:55 +01005956 else if (ret == SSL_ERROR_SYSCALL) {
5957 /* if errno is null, then connection was successfully established */
5958 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
5959 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Willy Tarreau20879a02012-12-03 16:32:10 +01005960 if (!conn->err_code) {
Lukas Tribus49799162019-07-08 14:29:15 +02005961#if defined(OPENSSL_IS_BORINGSSL) || defined(LIBRESSL_VERSION_NUMBER)
5962 /* do not handle empty handshakes in BoringSSL or LibreSSL */
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005963 conn->err_code = CO_ER_SSL_HANDSHAKE;
5964#else
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005965 int empty_handshake;
Willy Tarreau5db847a2019-05-09 14:13:35 +02005966#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL)
Lukas Tribus49799162019-07-08 14:29:15 +02005967 /* use SSL_get_state() in OpenSSL >= 1.1.0; SSL_state() is broken */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005968 OSSL_HANDSHAKE_STATE state = SSL_get_state((SSL *)ctx->ssl);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005969 empty_handshake = state == TLS_ST_BEFORE;
5970#else
Lukas Tribus49799162019-07-08 14:29:15 +02005971 /* access packet_length directly in OpenSSL <= 1.0.2; SSL_state() is broken */
5972 empty_handshake = !ctx->ssl->packet_length;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005973#endif
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005974 if (empty_handshake) {
Emeric Brun29f037d2014-04-25 19:05:36 +02005975 if (!errno) {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01005976 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emeric Brun29f037d2014-04-25 19:05:36 +02005977 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5978 else
5979 conn->err_code = CO_ER_SSL_EMPTY;
5980 }
5981 else {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01005982 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emeric Brun29f037d2014-04-25 19:05:36 +02005983 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5984 else
5985 conn->err_code = CO_ER_SSL_ABORT;
5986 }
5987 }
5988 else {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01005989 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emeric Brun29f037d2014-04-25 19:05:36 +02005990 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
Willy Tarreau20879a02012-12-03 16:32:10 +01005991 else
Emeric Brun29f037d2014-04-25 19:05:36 +02005992 conn->err_code = CO_ER_SSL_HANDSHAKE;
5993 }
Lukas Tribus49799162019-07-08 14:29:15 +02005994#endif /* BoringSSL or LibreSSL */
Willy Tarreau20879a02012-12-03 16:32:10 +01005995 }
Emeric Brun674b7432012-11-08 19:21:55 +01005996 goto out_error;
5997 }
5998 else {
5999 /* Fail on all other handshake errors */
6000 /* Note: OpenSSL may leave unread bytes in the socket's
6001 * buffer, causing an RST to be emitted upon close() on
6002 * TCP sockets. We first try to drain possibly pending
6003 * data to avoid this as much as possible.
6004 */
Willy Tarreaud85c4852015-03-13 00:40:28 +01006005 conn_sock_drain(conn);
Willy Tarreau20879a02012-12-03 16:32:10 +01006006 if (!conn->err_code)
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006007 conn->err_code = (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT) ?
Willy Tarreauf51c6982014-04-25 20:02:39 +02006008 CO_ER_SSL_KILLED_HB : CO_ER_SSL_HANDSHAKE;
Emeric Brun674b7432012-11-08 19:21:55 +01006009 goto out_error;
6010 }
6011 }
6012 /* read some data: consider handshake completed */
6013 goto reneg_ok;
6014 }
Olivier Houchard66ab4982019-02-26 18:37:15 +01006015 ret = SSL_do_handshake(ctx->ssl);
Olivier Houchardc2aae742017-09-22 18:26:28 +02006016check_error:
Emeric Brun46591952012-05-18 15:47:34 +02006017 if (ret != 1) {
6018 /* handshake did not complete, let's find why */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006019 ret = SSL_get_error(ctx->ssl, ret);
Emeric Brun46591952012-05-18 15:47:34 +02006020
6021 if (ret == SSL_ERROR_WANT_WRITE) {
6022 /* SSL handshake needs to write, L4 connection may not be ready */
Olivier Houchard03abf2d2019-05-28 10:12:02 +02006023 if (!(ctx->wait_event.events & SUB_RETRY_SEND))
Olivier Houchardea8dd942019-05-20 14:02:16 +02006024 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_SEND, &ctx->wait_event);
Emeric Brun46591952012-05-18 15:47:34 +02006025 return 0;
6026 }
6027 else if (ret == SSL_ERROR_WANT_READ) {
6028 /* SSL handshake needs to read, L4 connection is ready */
Olivier Houchardea8dd942019-05-20 14:02:16 +02006029 if (!(ctx->wait_event.events & SUB_RETRY_RECV))
Olivier Houchardea8dd942019-05-20 14:02:16 +02006030 ctx->xprt->subscribe(conn, ctx->xprt_ctx,
6031 SUB_RETRY_RECV, &ctx->wait_event);
Emeric Brun46591952012-05-18 15:47:34 +02006032 return 0;
6033 }
Willy Tarreau5db847a2019-05-09 14:13:35 +02006034#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006035 else if (ret == SSL_ERROR_WANT_ASYNC) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02006036 ssl_async_process_fds(ctx);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006037 return 0;
6038 }
6039#endif
Willy Tarreau89230192012-09-28 20:22:13 +02006040 else if (ret == SSL_ERROR_SYSCALL) {
6041 /* if errno is null, then connection was successfully established */
6042 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
6043 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01006044 if (!conn->err_code) {
Lukas Tribus49799162019-07-08 14:29:15 +02006045#if defined(OPENSSL_IS_BORINGSSL) || defined(LIBRESSL_VERSION_NUMBER)
6046 /* do not handle empty handshakes in BoringSSL or LibreSSL */
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01006047 conn->err_code = CO_ER_SSL_HANDSHAKE;
6048#else
6049 int empty_handshake;
Willy Tarreau5db847a2019-05-09 14:13:35 +02006050#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL)
Lukas Tribus49799162019-07-08 14:29:15 +02006051 /* use SSL_get_state() in OpenSSL >= 1.1.0; SSL_state() is broken */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006052 OSSL_HANDSHAKE_STATE state = SSL_get_state(ctx->ssl);
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01006053 empty_handshake = state == TLS_ST_BEFORE;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006054#else
Lukas Tribus49799162019-07-08 14:29:15 +02006055 /* access packet_length directly in OpenSSL <= 1.0.2; SSL_state() is broken */
6056 empty_handshake = !ctx->ssl->packet_length;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006057#endif
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01006058 if (empty_handshake) {
6059 if (!errno) {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006060 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01006061 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
6062 else
6063 conn->err_code = CO_ER_SSL_EMPTY;
6064 }
6065 else {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006066 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01006067 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
6068 else
6069 conn->err_code = CO_ER_SSL_ABORT;
6070 }
Emeric Brun29f037d2014-04-25 19:05:36 +02006071 }
6072 else {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006073 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emeric Brun29f037d2014-04-25 19:05:36 +02006074 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
6075 else
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01006076 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun29f037d2014-04-25 19:05:36 +02006077 }
Lukas Tribus49799162019-07-08 14:29:15 +02006078#endif /* BoringSSL or LibreSSL */
Emeric Brun29f037d2014-04-25 19:05:36 +02006079 }
Willy Tarreau89230192012-09-28 20:22:13 +02006080 goto out_error;
6081 }
Emeric Brun46591952012-05-18 15:47:34 +02006082 else {
6083 /* Fail on all other handshake errors */
Willy Tarreau566dc552012-10-19 20:52:18 +02006084 /* Note: OpenSSL may leave unread bytes in the socket's
6085 * buffer, causing an RST to be emitted upon close() on
6086 * TCP sockets. We first try to drain possibly pending
6087 * data to avoid this as much as possible.
6088 */
Willy Tarreaud85c4852015-03-13 00:40:28 +01006089 conn_sock_drain(conn);
Willy Tarreau20879a02012-12-03 16:32:10 +01006090 if (!conn->err_code)
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006091 conn->err_code = (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT) ?
Willy Tarreauf51c6982014-04-25 20:02:39 +02006092 CO_ER_SSL_KILLED_HB : CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02006093 goto out_error;
6094 }
6095 }
Willy Tarreau5db847a2019-05-09 14:13:35 +02006096#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Olivier Houchard522eea72017-11-03 16:27:47 +01006097 else {
6098 /*
6099 * If the server refused the early data, we have to send a
6100 * 425 to the client, as we no longer have the data to sent
6101 * them again.
6102 */
6103 if ((conn->flags & CO_FL_EARLY_DATA) && (objt_server(conn->target))) {
Olivier Houchard66ab4982019-02-26 18:37:15 +01006104 if (SSL_get_early_data_status(ctx->ssl) == SSL_EARLY_DATA_REJECTED) {
Olivier Houchard522eea72017-11-03 16:27:47 +01006105 conn->err_code = CO_ER_SSL_EARLY_FAILED;
6106 goto out_error;
6107 }
6108 }
6109 }
6110#endif
6111
Emeric Brun46591952012-05-18 15:47:34 +02006112
Emeric Brun674b7432012-11-08 19:21:55 +01006113reneg_ok:
Emeric Brunb5e42a82017-06-06 12:35:14 +00006114
Willy Tarreau5db847a2019-05-09 14:13:35 +02006115#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00006116 /* ASYNC engine API doesn't support moving read/write
6117 * buffers. So we disable ASYNC mode right after
6118 * the handshake to avoid buffer oveflows.
6119 */
6120 if (global_ssl.async)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006121 SSL_clear_mode(ctx->ssl, SSL_MODE_ASYNC);
Emeric Brunb5e42a82017-06-06 12:35:14 +00006122#endif
Emeric Brun46591952012-05-18 15:47:34 +02006123 /* Handshake succeeded */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006124 if (!SSL_session_reused(ctx->ssl)) {
Willy Tarreau0c9c2722014-05-28 12:28:58 +02006125 if (objt_server(conn->target)) {
6126 update_freq_ctr(&global.ssl_be_keys_per_sec, 1);
6127 if (global.ssl_be_keys_per_sec.curr_ctr > global.ssl_be_keys_max)
6128 global.ssl_be_keys_max = global.ssl_be_keys_per_sec.curr_ctr;
Emeric Brun46591952012-05-18 15:47:34 +02006129 }
Willy Tarreau0c9c2722014-05-28 12:28:58 +02006130 else {
6131 update_freq_ctr(&global.ssl_fe_keys_per_sec, 1);
6132 if (global.ssl_fe_keys_per_sec.curr_ctr > global.ssl_fe_keys_max)
6133 global.ssl_fe_keys_max = global.ssl_fe_keys_per_sec.curr_ctr;
6134 }
Emeric Brun46591952012-05-18 15:47:34 +02006135 }
6136
6137 /* The connection is now established at both layers, it's time to leave */
6138 conn->flags &= ~(flag | CO_FL_WAIT_L4_CONN | CO_FL_WAIT_L6_CONN);
6139 return 1;
6140
6141 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01006142 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02006143 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01006144 ERR_clear_error();
6145
Emeric Brun9fa89732012-10-04 17:09:56 +02006146 /* free resumed session if exists */
Willy Tarreau07d94e42018-09-20 10:57:52 +02006147 if (objt_server(conn->target) && __objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr) {
6148 free(__objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr);
6149 __objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr = NULL;
Emeric Brun9fa89732012-10-04 17:09:56 +02006150 }
6151
Emeric Brun46591952012-05-18 15:47:34 +02006152 /* Fail on all other handshake errors */
6153 conn->flags |= CO_FL_ERROR;
Willy Tarreau20879a02012-12-03 16:32:10 +01006154 if (!conn->err_code)
6155 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02006156 return 0;
6157}
6158
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006159static int ssl_subscribe(struct connection *conn, void *xprt_ctx, int event_type, void *param)
Olivier Houcharddf357842019-03-21 16:30:07 +01006160{
Olivier Houchardea8dd942019-05-20 14:02:16 +02006161 struct wait_event *sw;
6162 struct ssl_sock_ctx *ctx = xprt_ctx;
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006163
Olivier Houchard0ff28652019-06-24 18:57:39 +02006164 if (!ctx)
6165 return -1;
6166
Olivier Houchardea8dd942019-05-20 14:02:16 +02006167 if (event_type & SUB_RETRY_RECV) {
6168 sw = param;
6169 BUG_ON(ctx->recv_wait != NULL || (sw->events & SUB_RETRY_RECV));
6170 sw->events |= SUB_RETRY_RECV;
6171 ctx->recv_wait = sw;
6172 if (!(conn->flags & CO_FL_SSL_WAIT_HS) &&
6173 !(ctx->wait_event.events & SUB_RETRY_RECV))
6174 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_RECV, &ctx->wait_event);
6175 event_type &= ~SUB_RETRY_RECV;
6176 }
6177 if (event_type & SUB_RETRY_SEND) {
6178sw = param;
6179 BUG_ON(ctx->send_wait != NULL || (sw->events & SUB_RETRY_SEND));
6180 sw->events |= SUB_RETRY_SEND;
6181 ctx->send_wait = sw;
6182 if (!(conn->flags & CO_FL_SSL_WAIT_HS) &&
6183 !(ctx->wait_event.events & SUB_RETRY_SEND))
6184 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_SEND, &ctx->wait_event);
6185 event_type &= ~SUB_RETRY_SEND;
6186
6187 }
6188 if (event_type != 0)
6189 return -1;
6190 return 0;
Olivier Houcharddf357842019-03-21 16:30:07 +01006191}
6192
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006193static int ssl_unsubscribe(struct connection *conn, void *xprt_ctx, int event_type, void *param)
Olivier Houcharddf357842019-03-21 16:30:07 +01006194{
Olivier Houchardea8dd942019-05-20 14:02:16 +02006195 struct wait_event *sw;
6196 struct ssl_sock_ctx *ctx = xprt_ctx;
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006197
Olivier Houchardea8dd942019-05-20 14:02:16 +02006198 if (event_type & SUB_RETRY_RECV) {
6199 sw = param;
6200 BUG_ON(ctx->recv_wait != sw);
6201 ctx->recv_wait = NULL;
6202 sw->events &= ~SUB_RETRY_RECV;
6203 /* If we subscribed, and we're not doing the handshake,
6204 * then we subscribed because the upper layer asked for it,
6205 * as the upper layer is no longer interested, we can
6206 * unsubscribe too.
6207 */
6208 if (!(ctx->conn->flags & CO_FL_SSL_WAIT_HS) &&
6209 (ctx->wait_event.events & SUB_RETRY_RECV))
6210 conn_unsubscribe(conn, ctx->xprt_ctx, SUB_RETRY_RECV,
6211 &ctx->wait_event);
6212 }
6213 if (event_type & SUB_RETRY_SEND) {
6214 sw = param;
6215 BUG_ON(ctx->send_wait != sw);
6216 ctx->send_wait = NULL;
6217 sw->events &= ~SUB_RETRY_SEND;
6218 if (!(ctx->conn->flags & CO_FL_SSL_WAIT_HS) &&
6219 (ctx->wait_event.events & SUB_RETRY_SEND))
6220 conn_unsubscribe(conn, ctx->xprt_ctx, SUB_RETRY_SEND,
6221 &ctx->wait_event);
6222
6223 }
6224
6225 return 0;
Olivier Houcharddf357842019-03-21 16:30:07 +01006226}
6227
Olivier Houchard2e055482019-05-27 19:50:12 +02006228/* Use the provided XPRT as an underlying XPRT, and provide the old one.
6229 * Returns 0 on success, and non-zero on failure.
6230 */
6231static 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)
6232{
6233 struct ssl_sock_ctx *ctx = xprt_ctx;
6234
6235 if (oldxprt_ops != NULL)
6236 *oldxprt_ops = ctx->xprt;
6237 if (oldxprt_ctx != NULL)
6238 *oldxprt_ctx = ctx->xprt_ctx;
6239 ctx->xprt = toadd_ops;
6240 ctx->xprt_ctx = toadd_ctx;
6241 return 0;
6242}
6243
Olivier Houchard5149b592019-05-23 17:47:36 +02006244/* Remove the specified xprt. If if it our underlying XPRT, remove it and
6245 * return 0, otherwise just call the remove_xprt method from the underlying
6246 * XPRT.
6247 */
6248static int ssl_remove_xprt(struct connection *conn, void *xprt_ctx, void *toremove_ctx, const struct xprt_ops *newops, void *newctx)
6249{
6250 struct ssl_sock_ctx *ctx = xprt_ctx;
6251
6252 if (ctx->xprt_ctx == toremove_ctx) {
6253 ctx->xprt_ctx = newctx;
6254 ctx->xprt = newops;
6255 return 0;
6256 }
6257 return (ctx->xprt->remove_xprt(conn, ctx->xprt_ctx, toremove_ctx, newops, newctx));
6258}
6259
Olivier Houchardea8dd942019-05-20 14:02:16 +02006260static struct task *ssl_sock_io_cb(struct task *t, void *context, unsigned short state)
6261{
6262 struct ssl_sock_ctx *ctx = context;
6263
6264 /* First if we're doing an handshake, try that */
6265 if (ctx->conn->flags & CO_FL_SSL_WAIT_HS)
6266 ssl_sock_handshake(ctx->conn, CO_FL_SSL_WAIT_HS);
6267 /* If we had an error, or the handshake is done and I/O is available,
6268 * let the upper layer know.
6269 * If no mux was set up yet, and nobody subscribed, then call
6270 * xprt_done_cb() ourself if it's set, or destroy the connection,
6271 * we can't be sure conn_fd_handler() will be called again.
6272 */
6273 if ((ctx->conn->flags & CO_FL_ERROR) ||
6274 !(ctx->conn->flags & CO_FL_SSL_WAIT_HS)) {
6275 int ret = 0;
6276 int woke = 0;
6277
6278 /* On error, wake any waiter */
6279 if (ctx->recv_wait) {
6280 ctx->recv_wait->events &= ~SUB_RETRY_RECV;
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02006281 tasklet_wakeup(ctx->recv_wait->tasklet);
Olivier Houchardea8dd942019-05-20 14:02:16 +02006282 ctx->recv_wait = NULL;
6283 woke = 1;
6284 }
6285 if (ctx->send_wait) {
6286 ctx->send_wait->events &= ~SUB_RETRY_SEND;
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02006287 tasklet_wakeup(ctx->send_wait->tasklet);
Olivier Houchardea8dd942019-05-20 14:02:16 +02006288 ctx->send_wait = NULL;
6289 woke = 1;
6290 }
6291 /* If we're the first xprt for the connection, let the
6292 * upper layers know. If xprt_done_cb() is set, call it,
6293 * otherwise, we should have a mux, so call its wake
6294 * method if we didn't woke a tasklet already.
6295 */
6296 if (ctx->conn->xprt_ctx == ctx) {
6297 if (ctx->conn->xprt_done_cb)
6298 ret = ctx->conn->xprt_done_cb(ctx->conn);
6299 if (ret >= 0 && !woke && ctx->conn->mux && ctx->conn->mux->wake)
6300 ctx->conn->mux->wake(ctx->conn);
6301 return NULL;
6302 }
6303 }
6304 return NULL;
6305}
6306
Emeric Brun46591952012-05-18 15:47:34 +02006307/* Receive up to <count> bytes from connection <conn>'s socket and store them
Willy Tarreauabf08d92014-01-14 11:31:27 +01006308 * into buffer <buf>. Only one call to recv() is performed, unless the
Emeric Brun46591952012-05-18 15:47:34 +02006309 * buffer wraps, in which case a second call may be performed. The connection's
6310 * flags are updated with whatever special event is detected (error, read0,
6311 * empty). The caller is responsible for taking care of those events and
6312 * avoiding the call if inappropriate. The function does not call the
6313 * connection's polling update function, so the caller is responsible for this.
6314 */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006315static 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 +02006316{
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006317 struct ssl_sock_ctx *ctx = xprt_ctx;
Willy Tarreaubfc4d772018-07-18 11:22:03 +02006318 ssize_t ret;
6319 size_t try, done = 0;
Emeric Brun46591952012-05-18 15:47:34 +02006320
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02006321 conn_refresh_polling_flags(conn);
6322
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006323 if (!ctx)
Emeric Brun46591952012-05-18 15:47:34 +02006324 goto out_error;
6325
6326 if (conn->flags & CO_FL_HANDSHAKE)
6327 /* a handshake was requested */
6328 return 0;
6329
Emeric Brun46591952012-05-18 15:47:34 +02006330 /* read the largest possible block. For this, we perform only one call
6331 * to recv() unless the buffer wraps and we exactly fill the first hunk,
6332 * in which case we accept to do it once again. A new attempt is made on
6333 * EINTR too.
6334 */
Willy Tarreau00b0fb92014-01-17 11:09:40 +01006335 while (count > 0) {
Olivier Houchardc2aae742017-09-22 18:26:28 +02006336 int need_out = 0;
6337
Willy Tarreau591d4452018-06-15 17:21:00 +02006338 try = b_contig_space(buf);
6339 if (!try)
6340 break;
6341
Willy Tarreauabf08d92014-01-14 11:31:27 +01006342 if (try > count)
6343 try = count;
Willy Tarreau591d4452018-06-15 17:21:00 +02006344
Olivier Houchardc2aae742017-09-22 18:26:28 +02006345 if (((conn->flags & (CO_FL_EARLY_SSL_HS | CO_FL_EARLY_DATA)) == CO_FL_EARLY_SSL_HS) &&
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006346 ctx->tmp_early_data != -1) {
6347 *b_tail(buf) = ctx->tmp_early_data;
Olivier Houchardc2aae742017-09-22 18:26:28 +02006348 done++;
6349 try--;
6350 count--;
Olivier Houchardacd14032018-06-28 18:17:23 +02006351 b_add(buf, 1);
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006352 ctx->tmp_early_data = -1;
Olivier Houchardc2aae742017-09-22 18:26:28 +02006353 continue;
6354 }
Willy Tarreauabf08d92014-01-14 11:31:27 +01006355
Willy Tarreau5db847a2019-05-09 14:13:35 +02006356#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Olivier Houchardc2aae742017-09-22 18:26:28 +02006357 if (conn->flags & CO_FL_EARLY_SSL_HS) {
6358 size_t read_length;
6359
Olivier Houchard66ab4982019-02-26 18:37:15 +01006360 ret = SSL_read_early_data(ctx->ssl,
Willy Tarreau8f9c72d2018-06-07 18:46:28 +02006361 b_tail(buf), try, &read_length);
Olivier Houchard522eea72017-11-03 16:27:47 +01006362 if (ret == SSL_READ_EARLY_DATA_SUCCESS &&
6363 read_length > 0)
Olivier Houchardc2aae742017-09-22 18:26:28 +02006364 conn->flags |= CO_FL_EARLY_DATA;
6365 if (ret == SSL_READ_EARLY_DATA_SUCCESS ||
6366 ret == SSL_READ_EARLY_DATA_FINISH) {
6367 if (ret == SSL_READ_EARLY_DATA_FINISH) {
6368 /*
6369 * We're done reading the early data,
6370 * let's make the handshake
6371 */
6372 conn->flags &= ~CO_FL_EARLY_SSL_HS;
6373 conn->flags |= CO_FL_SSL_WAIT_HS;
6374 need_out = 1;
Olivier Houchard965e84e2019-06-15 20:59:30 +02006375 /* Now initiate the handshake */
6376 tasklet_wakeup(ctx->wait_event.tasklet);
Olivier Houchardc2aae742017-09-22 18:26:28 +02006377 if (read_length == 0)
6378 break;
6379 }
6380 ret = read_length;
6381 }
6382 } else
6383#endif
Olivier Houchard66ab4982019-02-26 18:37:15 +01006384 ret = SSL_read(ctx->ssl, b_tail(buf), try);
Emmanuel Hocdetf967c312019-08-05 18:04:16 +02006385
Emeric Brune1f38db2012-09-03 20:36:47 +02006386 if (conn->flags & CO_FL_ERROR) {
6387 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01006388 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02006389 }
Emeric Brun46591952012-05-18 15:47:34 +02006390 if (ret > 0) {
Olivier Houchardacd14032018-06-28 18:17:23 +02006391 b_add(buf, ret);
Emeric Brun46591952012-05-18 15:47:34 +02006392 done += ret;
Emeric Brun46591952012-05-18 15:47:34 +02006393 count -= ret;
Emeric Brun46591952012-05-18 15:47:34 +02006394 }
Emeric Brun46591952012-05-18 15:47:34 +02006395 else {
Olivier Houchard66ab4982019-02-26 18:37:15 +01006396 ret = SSL_get_error(ctx->ssl, ret);
Emeric Brun46591952012-05-18 15:47:34 +02006397 if (ret == SSL_ERROR_WANT_WRITE) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01006398 /* handshake is running, and it needs to enable write */
Emeric Brun46591952012-05-18 15:47:34 +02006399 conn->flags |= CO_FL_SSL_WAIT_HS;
Olivier Houchardea8dd942019-05-20 14:02:16 +02006400 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_SEND, &ctx->wait_event);
Willy Tarreau5db847a2019-05-09 14:13:35 +02006401#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00006402 /* Async mode can be re-enabled, because we're leaving data state.*/
6403 if (global_ssl.async)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006404 SSL_set_mode(ctx->ssl, SSL_MODE_ASYNC);
Emeric Brunb5e42a82017-06-06 12:35:14 +00006405#endif
Emeric Brun46591952012-05-18 15:47:34 +02006406 break;
6407 }
6408 else if (ret == SSL_ERROR_WANT_READ) {
Olivier Houchard66ab4982019-02-26 18:37:15 +01006409 if (SSL_renegotiate_pending(ctx->ssl)) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02006410 ctx->xprt->subscribe(conn, ctx->xprt_ctx,
6411 SUB_RETRY_RECV,
6412 &ctx->wait_event);
Emeric Brun282a76a2012-11-08 18:02:56 +01006413 /* handshake is running, and it may need to re-enable read */
6414 conn->flags |= CO_FL_SSL_WAIT_HS;
Willy Tarreau5db847a2019-05-09 14:13:35 +02006415#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00006416 /* Async mode can be re-enabled, because we're leaving data state.*/
6417 if (global_ssl.async)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006418 SSL_set_mode(ctx->ssl, SSL_MODE_ASYNC);
Emeric Brunb5e42a82017-06-06 12:35:14 +00006419#endif
Emeric Brun282a76a2012-11-08 18:02:56 +01006420 break;
6421 }
Emeric Brun46591952012-05-18 15:47:34 +02006422 break;
Olivier Houchardc2aae742017-09-22 18:26:28 +02006423 } else if (ret == SSL_ERROR_ZERO_RETURN)
6424 goto read0;
Christopher Faulet4ac77a92018-02-19 14:25:15 +01006425 /* For SSL_ERROR_SYSCALL, make sure to clear the error
6426 * stack before shutting down the connection for
6427 * reading. */
Olivier Houchard7e2e5052018-02-13 15:17:23 +01006428 if (ret == SSL_ERROR_SYSCALL && (!errno || errno == EAGAIN))
6429 goto clear_ssl_error;
Emeric Brun46591952012-05-18 15:47:34 +02006430 /* otherwise it's a real error */
6431 goto out_error;
6432 }
Olivier Houchardc2aae742017-09-22 18:26:28 +02006433 if (need_out)
6434 break;
Emeric Brun46591952012-05-18 15:47:34 +02006435 }
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02006436 leave:
Emeric Brun46591952012-05-18 15:47:34 +02006437 return done;
6438
Christopher Faulet4ac77a92018-02-19 14:25:15 +01006439 clear_ssl_error:
6440 /* Clear openssl global errors stack */
6441 ssl_sock_dump_errors(conn);
6442 ERR_clear_error();
Emeric Brun46591952012-05-18 15:47:34 +02006443 read0:
6444 conn_sock_read0(conn);
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02006445 goto leave;
Christopher Faulet4ac77a92018-02-19 14:25:15 +01006446
Emeric Brun46591952012-05-18 15:47:34 +02006447 out_error:
Olivier Houchard7e2e5052018-02-13 15:17:23 +01006448 conn->flags |= CO_FL_ERROR;
Emeric Brun644cde02012-12-14 11:21:13 +01006449 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02006450 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01006451 ERR_clear_error();
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02006452 goto leave;
Emeric Brun46591952012-05-18 15:47:34 +02006453}
6454
6455
Willy Tarreau787db9a2018-06-14 18:31:46 +02006456/* Send up to <count> pending bytes from buffer <buf> to connection <conn>'s
6457 * socket. <flags> may contain some CO_SFL_* flags to hint the system about
6458 * other pending data for example, but this flag is ignored at the moment.
Emeric Brun46591952012-05-18 15:47:34 +02006459 * Only one call to send() is performed, unless the buffer wraps, in which case
6460 * a second call may be performed. The connection's flags are updated with
6461 * whatever special event is detected (error, empty). The caller is responsible
6462 * for taking care of those events and avoiding the call if inappropriate. The
6463 * function does not call the connection's polling update function, so the caller
Willy Tarreau787db9a2018-06-14 18:31:46 +02006464 * is responsible for this. The buffer's output is not adjusted, it's up to the
6465 * caller to take care of this. It's up to the caller to update the buffer's
6466 * contents based on the return value.
Emeric Brun46591952012-05-18 15:47:34 +02006467 */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006468static 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 +02006469{
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006470 struct ssl_sock_ctx *ctx = xprt_ctx;
Willy Tarreau787db9a2018-06-14 18:31:46 +02006471 ssize_t ret;
6472 size_t try, done;
Emeric Brun46591952012-05-18 15:47:34 +02006473
6474 done = 0;
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02006475 conn_refresh_polling_flags(conn);
Emeric Brun46591952012-05-18 15:47:34 +02006476
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006477 if (!ctx)
Emeric Brun46591952012-05-18 15:47:34 +02006478 goto out_error;
6479
Olivier Houchard010941f2019-05-03 20:56:19 +02006480 if (conn->flags & (CO_FL_HANDSHAKE | CO_FL_EARLY_SSL_HS))
Emeric Brun46591952012-05-18 15:47:34 +02006481 /* a handshake was requested */
6482 return 0;
6483
6484 /* send the largest possible block. For this we perform only one call
6485 * to send() unless the buffer wraps and we exactly fill the first hunk,
6486 * in which case we accept to do it once again.
6487 */
Willy Tarreau787db9a2018-06-14 18:31:46 +02006488 while (count) {
Willy Tarreau5db847a2019-05-09 14:13:35 +02006489#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Olivier Houchardc2aae742017-09-22 18:26:28 +02006490 size_t written_data;
6491#endif
6492
Willy Tarreau787db9a2018-06-14 18:31:46 +02006493 try = b_contig_data(buf, done);
6494 if (try > count)
6495 try = count;
Willy Tarreaubfd59462013-02-21 07:46:09 +01006496
Willy Tarreau7bed9452014-02-02 02:00:24 +01006497 if (!(flags & CO_SFL_STREAMER) &&
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006498 !(ctx->xprt_st & SSL_SOCK_SEND_UNLIMITED) &&
Willy Tarreauef934602016-12-22 23:12:01 +01006499 global_ssl.max_record && try > global_ssl.max_record) {
6500 try = global_ssl.max_record;
Willy Tarreau518cedd2014-02-17 15:43:01 +01006501 }
6502 else {
6503 /* we need to keep the information about the fact that
6504 * we're not limiting the upcoming send(), because if it
6505 * fails, we'll have to retry with at least as many data.
6506 */
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006507 ctx->xprt_st |= SSL_SOCK_SEND_UNLIMITED;
Willy Tarreau518cedd2014-02-17 15:43:01 +01006508 }
Willy Tarreaubfd59462013-02-21 07:46:09 +01006509
Willy Tarreau5db847a2019-05-09 14:13:35 +02006510#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Olivier Houchard010941f2019-05-03 20:56:19 +02006511 if (!SSL_is_init_finished(ctx->ssl) && conn_is_back(conn)) {
Olivier Houchardc2aae742017-09-22 18:26:28 +02006512 unsigned int max_early;
6513
Olivier Houchard522eea72017-11-03 16:27:47 +01006514 if (objt_listener(conn->target))
Olivier Houchard66ab4982019-02-26 18:37:15 +01006515 max_early = SSL_get_max_early_data(ctx->ssl);
Olivier Houchard522eea72017-11-03 16:27:47 +01006516 else {
Olivier Houchard66ab4982019-02-26 18:37:15 +01006517 if (SSL_get0_session(ctx->ssl))
6518 max_early = SSL_SESSION_get_max_early_data(SSL_get0_session(ctx->ssl));
Olivier Houchard522eea72017-11-03 16:27:47 +01006519 else
6520 max_early = 0;
6521 }
6522
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006523 if (try + ctx->sent_early_data > max_early) {
6524 try -= (try + ctx->sent_early_data) - max_early;
Olivier Houchard522eea72017-11-03 16:27:47 +01006525 if (try <= 0) {
Olivier Houchard010941f2019-05-03 20:56:19 +02006526 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Olivier Houchard965e84e2019-06-15 20:59:30 +02006527 tasklet_wakeup(ctx->wait_event.tasklet);
Olivier Houchardc2aae742017-09-22 18:26:28 +02006528 break;
Olivier Houchard522eea72017-11-03 16:27:47 +01006529 }
Olivier Houchardc2aae742017-09-22 18:26:28 +02006530 }
Olivier Houchard66ab4982019-02-26 18:37:15 +01006531 ret = SSL_write_early_data(ctx->ssl, b_peek(buf, done), try, &written_data);
Olivier Houchardc2aae742017-09-22 18:26:28 +02006532 if (ret == 1) {
6533 ret = written_data;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006534 ctx->sent_early_data += ret;
Olivier Houchard965e84e2019-06-15 20:59:30 +02006535 if (objt_server(conn->target)) {
Olivier Houchard522eea72017-11-03 16:27:47 +01006536 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN | CO_FL_EARLY_DATA;
Olivier Houchard965e84e2019-06-15 20:59:30 +02006537 /* Initiate the handshake, now */
6538 tasklet_wakeup(ctx->wait_event.tasklet);
6539 }
Olivier Houchard522eea72017-11-03 16:27:47 +01006540
Olivier Houchardc2aae742017-09-22 18:26:28 +02006541 }
6542
6543 } else
6544#endif
Olivier Houchard66ab4982019-02-26 18:37:15 +01006545 ret = SSL_write(ctx->ssl, b_peek(buf, done), try);
Willy Tarreau518cedd2014-02-17 15:43:01 +01006546
Emeric Brune1f38db2012-09-03 20:36:47 +02006547 if (conn->flags & CO_FL_ERROR) {
6548 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01006549 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02006550 }
Emeric Brun46591952012-05-18 15:47:34 +02006551 if (ret > 0) {
Olivier Houchardf24502b2019-01-17 19:09:11 +01006552 /* A send succeeded, so we can consier ourself connected */
6553 conn->flags |= CO_FL_CONNECTED;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006554 ctx->xprt_st &= ~SSL_SOCK_SEND_UNLIMITED;
Willy Tarreau787db9a2018-06-14 18:31:46 +02006555 count -= ret;
Emeric Brun46591952012-05-18 15:47:34 +02006556 done += ret;
Emeric Brun46591952012-05-18 15:47:34 +02006557 }
6558 else {
Olivier Houchard66ab4982019-02-26 18:37:15 +01006559 ret = SSL_get_error(ctx->ssl, ret);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006560
Emeric Brun46591952012-05-18 15:47:34 +02006561 if (ret == SSL_ERROR_WANT_WRITE) {
Olivier Houchard66ab4982019-02-26 18:37:15 +01006562 if (SSL_renegotiate_pending(ctx->ssl)) {
Emeric Brun282a76a2012-11-08 18:02:56 +01006563 /* handshake is running, and it may need to re-enable write */
6564 conn->flags |= CO_FL_SSL_WAIT_HS;
Olivier Houchardea8dd942019-05-20 14:02:16 +02006565 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_SEND, &ctx->wait_event);
Willy Tarreau5db847a2019-05-09 14:13:35 +02006566#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00006567 /* Async mode can be re-enabled, because we're leaving data state.*/
6568 if (global_ssl.async)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006569 SSL_set_mode(ctx->ssl, SSL_MODE_ASYNC);
Emeric Brunb5e42a82017-06-06 12:35:14 +00006570#endif
Emeric Brun282a76a2012-11-08 18:02:56 +01006571 break;
6572 }
Olivier Houchardea8dd942019-05-20 14:02:16 +02006573
Emeric Brun46591952012-05-18 15:47:34 +02006574 break;
6575 }
6576 else if (ret == SSL_ERROR_WANT_READ) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01006577 /* handshake is running, and it needs to enable read */
Emeric Brun46591952012-05-18 15:47:34 +02006578 conn->flags |= CO_FL_SSL_WAIT_HS;
Olivier Houchardea8dd942019-05-20 14:02:16 +02006579 ctx->xprt->subscribe(conn, ctx->xprt_ctx,
6580 SUB_RETRY_RECV,
6581 &ctx->wait_event);
Willy Tarreau5db847a2019-05-09 14:13:35 +02006582#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00006583 /* Async mode can be re-enabled, because we're leaving data state.*/
6584 if (global_ssl.async)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006585 SSL_set_mode(ctx->ssl, SSL_MODE_ASYNC);
Emeric Brunb5e42a82017-06-06 12:35:14 +00006586#endif
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006587 break;
6588 }
Emeric Brun46591952012-05-18 15:47:34 +02006589 goto out_error;
6590 }
6591 }
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02006592 leave:
Emeric Brun46591952012-05-18 15:47:34 +02006593 return done;
6594
6595 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01006596 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02006597 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01006598 ERR_clear_error();
6599
Emeric Brun46591952012-05-18 15:47:34 +02006600 conn->flags |= CO_FL_ERROR;
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02006601 goto leave;
Emeric Brun46591952012-05-18 15:47:34 +02006602}
6603
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006604static void ssl_sock_close(struct connection *conn, void *xprt_ctx) {
Emeric Brun46591952012-05-18 15:47:34 +02006605
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006606 struct ssl_sock_ctx *ctx = xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006607
Olivier Houchardea8dd942019-05-20 14:02:16 +02006608
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006609 if (ctx) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02006610 if (ctx->wait_event.events != 0)
6611 ctx->xprt->unsubscribe(ctx->conn, ctx->xprt_ctx,
6612 ctx->wait_event.events,
6613 &ctx->wait_event);
6614 if (ctx->send_wait) {
6615 ctx->send_wait->events &= ~SUB_RETRY_SEND;
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02006616 tasklet_wakeup(ctx->send_wait->tasklet);
Olivier Houchardea8dd942019-05-20 14:02:16 +02006617 }
6618 if (ctx->recv_wait) {
6619 ctx->recv_wait->events &= ~SUB_RETRY_RECV;
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02006620 tasklet_wakeup(ctx->recv_wait->tasklet);
Olivier Houchardea8dd942019-05-20 14:02:16 +02006621 }
Olivier Houchard692c1d02019-05-23 18:41:47 +02006622 if (ctx->xprt->close)
6623 ctx->xprt->close(conn, ctx->xprt_ctx);
Willy Tarreau5db847a2019-05-09 14:13:35 +02006624#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brun3854e012017-05-17 20:42:48 +02006625 if (global_ssl.async) {
6626 OSSL_ASYNC_FD all_fd[32], afd;
6627 size_t num_all_fds = 0;
6628 int i;
6629
Olivier Houchard66ab4982019-02-26 18:37:15 +01006630 SSL_get_all_async_fds(ctx->ssl, NULL, &num_all_fds);
Emeric Brun3854e012017-05-17 20:42:48 +02006631 if (num_all_fds > 32) {
6632 send_log(NULL, LOG_EMERG, "haproxy: openssl returns too many async fds. It seems a bug. Process may crash\n");
6633 return;
6634 }
6635
Olivier Houchard66ab4982019-02-26 18:37:15 +01006636 SSL_get_all_async_fds(ctx->ssl, all_fd, &num_all_fds);
Emeric Brun3854e012017-05-17 20:42:48 +02006637
6638 /* If an async job is pending, we must try to
6639 to catch the end using polling before calling
6640 SSL_free */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006641 if (num_all_fds && SSL_waiting_for_async(ctx->ssl)) {
Emeric Brun3854e012017-05-17 20:42:48 +02006642 for (i=0 ; i < num_all_fds ; i++) {
6643 /* switch on an handler designed to
6644 * handle the SSL_free
6645 */
6646 afd = all_fd[i];
6647 fdtab[afd].iocb = ssl_async_fd_free;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006648 fdtab[afd].owner = ctx->ssl;
Emeric Brun3854e012017-05-17 20:42:48 +02006649 fd_want_recv(afd);
Emeric Brunce9e01c2017-05-31 10:02:53 +00006650 /* To ensure that the fd cache won't be used
6651 * and we'll catch a real RD event.
6652 */
6653 fd_cant_recv(afd);
Emeric Brun3854e012017-05-17 20:42:48 +02006654 }
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02006655 tasklet_free(ctx->wait_event.tasklet);
Olivier Houchard66ab4982019-02-26 18:37:15 +01006656 pool_free(ssl_sock_ctx_pool, ctx);
Olivier Houchard2be5a4c2019-03-08 18:54:43 +01006657 _HA_ATOMIC_ADD(&jobs, 1);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006658 return;
6659 }
Emeric Brun3854e012017-05-17 20:42:48 +02006660 /* Else we can remove the fds from the fdtab
6661 * and call SSL_free.
6662 * note: we do a fd_remove and not a delete
6663 * because the fd is owned by the engine.
6664 * the engine is responsible to close
6665 */
6666 for (i=0 ; i < num_all_fds ; i++)
6667 fd_remove(all_fd[i]);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006668 }
6669#endif
Olivier Houchard66ab4982019-02-26 18:37:15 +01006670 SSL_free(ctx->ssl);
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02006671 tasklet_free(ctx->wait_event.tasklet);
Olivier Houchard66ab4982019-02-26 18:37:15 +01006672 pool_free(ssl_sock_ctx_pool, ctx);
Olivier Houchard2be5a4c2019-03-08 18:54:43 +01006673 _HA_ATOMIC_SUB(&sslconns, 1);
Emeric Brun46591952012-05-18 15:47:34 +02006674 }
Emeric Brun46591952012-05-18 15:47:34 +02006675}
6676
6677/* This function tries to perform a clean shutdown on an SSL connection, and in
6678 * any case, flags the connection as reusable if no handshake was in progress.
6679 */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006680static void ssl_sock_shutw(struct connection *conn, void *xprt_ctx, int clean)
Emeric Brun46591952012-05-18 15:47:34 +02006681{
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006682 struct ssl_sock_ctx *ctx = xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006683
Emeric Brun46591952012-05-18 15:47:34 +02006684 if (conn->flags & CO_FL_HANDSHAKE)
6685 return;
Emmanuel Hocdet405ff312017-01-08 14:07:39 +01006686 if (!clean)
6687 /* don't sent notify on SSL_shutdown */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006688 SSL_set_quiet_shutdown(ctx->ssl, 1);
Emeric Brun46591952012-05-18 15:47:34 +02006689 /* no handshake was in progress, try a clean ssl shutdown */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006690 if (SSL_shutdown(ctx->ssl) <= 0) {
Emeric Brun644cde02012-12-14 11:21:13 +01006691 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02006692 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01006693 ERR_clear_error();
6694 }
Emeric Brun46591952012-05-18 15:47:34 +02006695}
6696
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01006697/* used for ppv2 pkey alog (can be used for logging) */
Willy Tarreau83061a82018-07-13 11:56:34 +02006698int ssl_sock_get_pkey_algo(struct connection *conn, struct buffer *out)
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01006699{
Christopher Faulet82004142019-09-10 10:12:03 +02006700 struct ssl_sock_ctx *ctx;
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01006701 int bits = 0;
6702 int sig = TLSEXT_signature_anonymous;
6703 int len = -1;
Emmanuel Hocdetc3775d22019-11-04 18:19:32 +01006704 X509 *crt;
6705 EVP_PKEY *pkey;
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01006706
6707 if (!ssl_sock_is_ssl(conn))
6708 return 0;
Christopher Faulet82004142019-09-10 10:12:03 +02006709 ctx = conn->xprt_ctx;
Emmanuel Hocdetc3775d22019-11-04 18:19:32 +01006710
6711 crt = SSL_get_certificate(ctx->ssl);
6712 if (!crt)
6713 return 0;
6714 pkey = X509_get_pubkey(crt);
6715 if (pkey) {
6716 bits = EVP_PKEY_bits(pkey);
6717 switch(EVP_PKEY_base_id(pkey)) {
6718 case EVP_PKEY_RSA:
6719 sig = TLSEXT_signature_rsa;
6720 break;
6721 case EVP_PKEY_EC:
6722 sig = TLSEXT_signature_ecdsa;
6723 break;
6724 case EVP_PKEY_DSA:
6725 sig = TLSEXT_signature_dsa;
6726 break;
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01006727 }
Emmanuel Hocdetc3775d22019-11-04 18:19:32 +01006728 EVP_PKEY_free(pkey);
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01006729 }
6730
6731 switch(sig) {
6732 case TLSEXT_signature_rsa:
6733 len = chunk_printf(out, "RSA%d", bits);
6734 break;
6735 case TLSEXT_signature_ecdsa:
6736 len = chunk_printf(out, "EC%d", bits);
6737 break;
6738 case TLSEXT_signature_dsa:
6739 len = chunk_printf(out, "DSA%d", bits);
6740 break;
6741 default:
6742 return 0;
6743 }
6744 if (len < 0)
6745 return 0;
6746 return 1;
6747}
6748
Emmanuel Hocdet283e0042017-11-02 14:05:23 +01006749/* used for ppv2 cert signature (can be used for logging) */
6750const char *ssl_sock_get_cert_sig(struct connection *conn)
6751{
Christopher Faulet82004142019-09-10 10:12:03 +02006752 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006753
Emmanuel Hocdet283e0042017-11-02 14:05:23 +01006754 __OPENSSL_110_CONST__ ASN1_OBJECT *algorithm;
6755 X509 *crt;
6756
6757 if (!ssl_sock_is_ssl(conn))
6758 return NULL;
Christopher Faulet82004142019-09-10 10:12:03 +02006759 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006760 crt = SSL_get_certificate(ctx->ssl);
Emmanuel Hocdet283e0042017-11-02 14:05:23 +01006761 if (!crt)
6762 return NULL;
6763 X509_ALGOR_get0(&algorithm, NULL, NULL, X509_get0_tbs_sigalg(crt));
6764 return OBJ_nid2sn(OBJ_obj2nid(algorithm));
6765}
6766
Emmanuel Hocdet253c3b72018-02-01 18:29:59 +01006767/* used for ppv2 authority */
6768const char *ssl_sock_get_sni(struct connection *conn)
6769{
6770#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Christopher Faulet82004142019-09-10 10:12:03 +02006771 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006772
Emmanuel Hocdet253c3b72018-02-01 18:29:59 +01006773 if (!ssl_sock_is_ssl(conn))
6774 return NULL;
Christopher Faulet82004142019-09-10 10:12:03 +02006775 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006776 return SSL_get_servername(ctx->ssl, TLSEXT_NAMETYPE_host_name);
Emmanuel Hocdet253c3b72018-02-01 18:29:59 +01006777#else
Olivier Houchard66ab4982019-02-26 18:37:15 +01006778 return NULL;
Emmanuel Hocdet253c3b72018-02-01 18:29:59 +01006779#endif
6780}
6781
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02006782/* used for logging/ppv2, may be changed for a sample fetch later */
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02006783const char *ssl_sock_get_cipher_name(struct connection *conn)
6784{
Christopher Faulet82004142019-09-10 10:12:03 +02006785 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006786
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02006787 if (!ssl_sock_is_ssl(conn))
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02006788 return NULL;
Christopher Faulet82004142019-09-10 10:12:03 +02006789 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006790 return SSL_get_cipher_name(ctx->ssl);
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02006791}
6792
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02006793/* used for logging/ppv2, may be changed for a sample fetch later */
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02006794const char *ssl_sock_get_proto_version(struct connection *conn)
6795{
Christopher Faulet82004142019-09-10 10:12:03 +02006796 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006797
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02006798 if (!ssl_sock_is_ssl(conn))
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02006799 return NULL;
Christopher Faulet82004142019-09-10 10:12:03 +02006800 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006801 return SSL_get_version(ctx->ssl);
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02006802}
6803
Willy Tarreau8d598402012-10-22 17:58:39 +02006804/* Extract a serial from a cert, and copy it to a chunk.
6805 * Returns 1 if serial is found and copied, 0 if no serial found and
6806 * -1 if output is not large enough.
6807 */
6808static int
Willy Tarreau83061a82018-07-13 11:56:34 +02006809ssl_sock_get_serial(X509 *crt, struct buffer *out)
Willy Tarreau8d598402012-10-22 17:58:39 +02006810{
6811 ASN1_INTEGER *serial;
6812
6813 serial = X509_get_serialNumber(crt);
6814 if (!serial)
6815 return 0;
6816
6817 if (out->size < serial->length)
6818 return -1;
6819
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006820 memcpy(out->area, serial->data, serial->length);
6821 out->data = serial->length;
Willy Tarreau8d598402012-10-22 17:58:39 +02006822 return 1;
6823}
6824
Emeric Brun43e79582014-10-29 19:03:26 +01006825/* Extract a cert to der, and copy it to a chunk.
Joseph Herlant017b3da2018-11-15 09:07:59 -08006826 * Returns 1 if the cert is found and copied, 0 on der conversion failure
6827 * and -1 if the output is not large enough.
Emeric Brun43e79582014-10-29 19:03:26 +01006828 */
6829static int
Willy Tarreau83061a82018-07-13 11:56:34 +02006830ssl_sock_crt2der(X509 *crt, struct buffer *out)
Emeric Brun43e79582014-10-29 19:03:26 +01006831{
6832 int len;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006833 unsigned char *p = (unsigned char *) out->area;;
Emeric Brun43e79582014-10-29 19:03:26 +01006834
6835 len =i2d_X509(crt, NULL);
6836 if (len <= 0)
6837 return 1;
6838
6839 if (out->size < len)
6840 return -1;
6841
6842 i2d_X509(crt,&p);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006843 out->data = len;
Emeric Brun43e79582014-10-29 19:03:26 +01006844 return 1;
6845}
6846
Emeric Brunce5ad802012-10-22 14:11:22 +02006847
Willy Tarreau83061a82018-07-13 11:56:34 +02006848/* Copy Date in ASN1_UTCTIME format in struct buffer out.
Emeric Brunce5ad802012-10-22 14:11:22 +02006849 * Returns 1 if serial is found and copied, 0 if no valid time found
6850 * and -1 if output is not large enough.
6851 */
6852static int
Willy Tarreau83061a82018-07-13 11:56:34 +02006853ssl_sock_get_time(ASN1_TIME *tm, struct buffer *out)
Emeric Brunce5ad802012-10-22 14:11:22 +02006854{
6855 if (tm->type == V_ASN1_GENERALIZEDTIME) {
6856 ASN1_GENERALIZEDTIME *gentm = (ASN1_GENERALIZEDTIME *)tm;
6857
6858 if (gentm->length < 12)
6859 return 0;
6860 if (gentm->data[0] != 0x32 || gentm->data[1] != 0x30)
6861 return 0;
6862 if (out->size < gentm->length-2)
6863 return -1;
6864
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006865 memcpy(out->area, gentm->data+2, gentm->length-2);
6866 out->data = gentm->length-2;
Emeric Brunce5ad802012-10-22 14:11:22 +02006867 return 1;
6868 }
6869 else if (tm->type == V_ASN1_UTCTIME) {
6870 ASN1_UTCTIME *utctm = (ASN1_UTCTIME *)tm;
6871
6872 if (utctm->length < 10)
6873 return 0;
6874 if (utctm->data[0] >= 0x35)
6875 return 0;
6876 if (out->size < utctm->length)
6877 return -1;
6878
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006879 memcpy(out->area, utctm->data, utctm->length);
6880 out->data = utctm->length;
Emeric Brunce5ad802012-10-22 14:11:22 +02006881 return 1;
6882 }
6883
6884 return 0;
6885}
6886
Emeric Brun87855892012-10-17 17:39:35 +02006887/* Extract an entry from a X509_NAME and copy its value to an output chunk.
6888 * Returns 1 if entry found, 0 if entry not found, or -1 if output not large enough.
6889 */
6890static int
Willy Tarreau83061a82018-07-13 11:56:34 +02006891ssl_sock_get_dn_entry(X509_NAME *a, const struct buffer *entry, int pos,
6892 struct buffer *out)
Emeric Brun87855892012-10-17 17:39:35 +02006893{
6894 X509_NAME_ENTRY *ne;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006895 ASN1_OBJECT *obj;
6896 ASN1_STRING *data;
6897 const unsigned char *data_ptr;
6898 int data_len;
Emeric Brun87855892012-10-17 17:39:35 +02006899 int i, j, n;
6900 int cur = 0;
6901 const char *s;
6902 char tmp[128];
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006903 int name_count;
6904
6905 name_count = X509_NAME_entry_count(a);
Emeric Brun87855892012-10-17 17:39:35 +02006906
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006907 out->data = 0;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006908 for (i = 0; i < name_count; i++) {
Emeric Brun87855892012-10-17 17:39:35 +02006909 if (pos < 0)
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006910 j = (name_count-1) - i;
Emeric Brun87855892012-10-17 17:39:35 +02006911 else
6912 j = i;
6913
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006914 ne = X509_NAME_get_entry(a, j);
6915 obj = X509_NAME_ENTRY_get_object(ne);
6916 data = X509_NAME_ENTRY_get_data(ne);
6917 data_ptr = ASN1_STRING_get0_data(data);
6918 data_len = ASN1_STRING_length(data);
6919 n = OBJ_obj2nid(obj);
Emeric Brun87855892012-10-17 17:39:35 +02006920 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006921 i2t_ASN1_OBJECT(tmp, sizeof(tmp), obj);
Emeric Brun87855892012-10-17 17:39:35 +02006922 s = tmp;
6923 }
6924
6925 if (chunk_strcasecmp(entry, s) != 0)
6926 continue;
6927
6928 if (pos < 0)
6929 cur--;
6930 else
6931 cur++;
6932
6933 if (cur != pos)
6934 continue;
6935
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006936 if (data_len > out->size)
Emeric Brun87855892012-10-17 17:39:35 +02006937 return -1;
6938
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006939 memcpy(out->area, data_ptr, data_len);
6940 out->data = data_len;
Emeric Brun87855892012-10-17 17:39:35 +02006941 return 1;
6942 }
6943
6944 return 0;
6945
6946}
6947
6948/* Extract and format full DN from a X509_NAME and copy result into a chunk
6949 * Returns 1 if dn entries exits, 0 if no dn entry found or -1 if output is not large enough.
6950 */
6951static int
Willy Tarreau83061a82018-07-13 11:56:34 +02006952ssl_sock_get_dn_oneline(X509_NAME *a, struct buffer *out)
Emeric Brun87855892012-10-17 17:39:35 +02006953{
6954 X509_NAME_ENTRY *ne;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006955 ASN1_OBJECT *obj;
6956 ASN1_STRING *data;
6957 const unsigned char *data_ptr;
6958 int data_len;
Emeric Brun87855892012-10-17 17:39:35 +02006959 int i, n, ln;
6960 int l = 0;
6961 const char *s;
6962 char *p;
6963 char tmp[128];
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006964 int name_count;
6965
6966
6967 name_count = X509_NAME_entry_count(a);
Emeric Brun87855892012-10-17 17:39:35 +02006968
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006969 out->data = 0;
6970 p = out->area;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006971 for (i = 0; i < name_count; i++) {
6972 ne = X509_NAME_get_entry(a, i);
6973 obj = X509_NAME_ENTRY_get_object(ne);
6974 data = X509_NAME_ENTRY_get_data(ne);
6975 data_ptr = ASN1_STRING_get0_data(data);
6976 data_len = ASN1_STRING_length(data);
6977 n = OBJ_obj2nid(obj);
Emeric Brun87855892012-10-17 17:39:35 +02006978 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006979 i2t_ASN1_OBJECT(tmp, sizeof(tmp), obj);
Emeric Brun87855892012-10-17 17:39:35 +02006980 s = tmp;
6981 }
6982 ln = strlen(s);
6983
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006984 l += 1 + ln + 1 + data_len;
Emeric Brun87855892012-10-17 17:39:35 +02006985 if (l > out->size)
6986 return -1;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006987 out->data = l;
Emeric Brun87855892012-10-17 17:39:35 +02006988
6989 *(p++)='/';
6990 memcpy(p, s, ln);
6991 p += ln;
6992 *(p++)='=';
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006993 memcpy(p, data_ptr, data_len);
6994 p += data_len;
Emeric Brun87855892012-10-17 17:39:35 +02006995 }
6996
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006997 if (!out->data)
Emeric Brun87855892012-10-17 17:39:35 +02006998 return 0;
6999
7000 return 1;
7001}
7002
Olivier Houchardab28a322018-12-21 19:45:40 +01007003void ssl_sock_set_alpn(struct connection *conn, const unsigned char *alpn, int len)
7004{
7005#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Christopher Faulet82004142019-09-10 10:12:03 +02007006 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007007
Olivier Houcharde488ea82019-06-28 14:10:33 +02007008 if (!ssl_sock_is_ssl(conn))
7009 return;
Christopher Faulet82004142019-09-10 10:12:03 +02007010 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007011 SSL_set_alpn_protos(ctx->ssl, alpn, len);
Olivier Houchardab28a322018-12-21 19:45:40 +01007012#endif
7013}
7014
Willy Tarreau119a4082016-12-22 21:58:38 +01007015/* Sets advertised SNI for outgoing connections. Please set <hostname> to NULL
7016 * to disable SNI.
7017 */
Willy Tarreau63076412015-07-10 11:33:32 +02007018void ssl_sock_set_servername(struct connection *conn, const char *hostname)
7019{
7020#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Christopher Faulet82004142019-09-10 10:12:03 +02007021 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007022
Willy Tarreau119a4082016-12-22 21:58:38 +01007023 char *prev_name;
7024
Willy Tarreau63076412015-07-10 11:33:32 +02007025 if (!ssl_sock_is_ssl(conn))
7026 return;
Christopher Faulet82004142019-09-10 10:12:03 +02007027 ctx = conn->xprt_ctx;
Willy Tarreau63076412015-07-10 11:33:32 +02007028
Willy Tarreau119a4082016-12-22 21:58:38 +01007029 /* if the SNI changes, we must destroy the reusable context so that a
7030 * new connection will present a new SNI. As an optimization we could
7031 * later imagine having a small cache of ssl_ctx to hold a few SNI per
7032 * server.
7033 */
Olivier Houchard66ab4982019-02-26 18:37:15 +01007034 prev_name = (char *)SSL_get_servername(ctx->ssl, TLSEXT_NAMETYPE_host_name);
Willy Tarreau119a4082016-12-22 21:58:38 +01007035 if ((!prev_name && hostname) ||
7036 (prev_name && (!hostname || strcmp(hostname, prev_name) != 0)))
Olivier Houchard66ab4982019-02-26 18:37:15 +01007037 SSL_set_session(ctx->ssl, NULL);
Willy Tarreau119a4082016-12-22 21:58:38 +01007038
Olivier Houchard66ab4982019-02-26 18:37:15 +01007039 SSL_set_tlsext_host_name(ctx->ssl, hostname);
Willy Tarreau63076412015-07-10 11:33:32 +02007040#endif
7041}
7042
Emeric Brun0abf8362014-06-24 18:26:41 +02007043/* Extract peer certificate's common name into the chunk dest
7044 * Returns
7045 * the len of the extracted common name
7046 * or 0 if no CN found in DN
7047 * or -1 on error case (i.e. no peer certificate)
7048 */
Willy Tarreau83061a82018-07-13 11:56:34 +02007049int ssl_sock_get_remote_common_name(struct connection *conn,
7050 struct buffer *dest)
David Safb76832014-05-08 23:42:08 -04007051{
Christopher Faulet82004142019-09-10 10:12:03 +02007052 struct ssl_sock_ctx *ctx;
David Safb76832014-05-08 23:42:08 -04007053 X509 *crt = NULL;
7054 X509_NAME *name;
David Safb76832014-05-08 23:42:08 -04007055 const char find_cn[] = "CN";
Willy Tarreau83061a82018-07-13 11:56:34 +02007056 const struct buffer find_cn_chunk = {
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007057 .area = (char *)&find_cn,
7058 .data = sizeof(find_cn)-1
David Safb76832014-05-08 23:42:08 -04007059 };
Emeric Brun0abf8362014-06-24 18:26:41 +02007060 int result = -1;
David Safb76832014-05-08 23:42:08 -04007061
7062 if (!ssl_sock_is_ssl(conn))
Emeric Brun0abf8362014-06-24 18:26:41 +02007063 goto out;
Christopher Faulet82004142019-09-10 10:12:03 +02007064 ctx = conn->xprt_ctx;
David Safb76832014-05-08 23:42:08 -04007065
7066 /* SSL_get_peer_certificate, it increase X509 * ref count */
Olivier Houchard66ab4982019-02-26 18:37:15 +01007067 crt = SSL_get_peer_certificate(ctx->ssl);
David Safb76832014-05-08 23:42:08 -04007068 if (!crt)
7069 goto out;
7070
7071 name = X509_get_subject_name(crt);
7072 if (!name)
7073 goto out;
David Safb76832014-05-08 23:42:08 -04007074
Emeric Brun0abf8362014-06-24 18:26:41 +02007075 result = ssl_sock_get_dn_entry(name, &find_cn_chunk, 1, dest);
7076out:
David Safb76832014-05-08 23:42:08 -04007077 if (crt)
7078 X509_free(crt);
7079
7080 return result;
7081}
7082
Dave McCowan328fb582014-07-30 10:39:13 -04007083/* returns 1 if client passed a certificate for this session, 0 if not */
7084int ssl_sock_get_cert_used_sess(struct connection *conn)
7085{
Christopher Faulet82004142019-09-10 10:12:03 +02007086 struct ssl_sock_ctx *ctx;
Dave McCowan328fb582014-07-30 10:39:13 -04007087 X509 *crt = NULL;
7088
7089 if (!ssl_sock_is_ssl(conn))
7090 return 0;
Christopher Faulet82004142019-09-10 10:12:03 +02007091 ctx = conn->xprt_ctx;
Dave McCowan328fb582014-07-30 10:39:13 -04007092
7093 /* SSL_get_peer_certificate, it increase X509 * ref count */
Olivier Houchard66ab4982019-02-26 18:37:15 +01007094 crt = SSL_get_peer_certificate(ctx->ssl);
Dave McCowan328fb582014-07-30 10:39:13 -04007095 if (!crt)
7096 return 0;
7097
7098 X509_free(crt);
7099 return 1;
7100}
7101
7102/* returns 1 if client passed a certificate for this connection, 0 if not */
7103int ssl_sock_get_cert_used_conn(struct connection *conn)
David Safb76832014-05-08 23:42:08 -04007104{
Christopher Faulet82004142019-09-10 10:12:03 +02007105 struct ssl_sock_ctx *ctx;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007106
David Safb76832014-05-08 23:42:08 -04007107 if (!ssl_sock_is_ssl(conn))
7108 return 0;
Christopher Faulet82004142019-09-10 10:12:03 +02007109 ctx = conn->xprt_ctx;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007110 return SSL_SOCK_ST_FL_VERIFY_DONE & ctx->xprt_st ? 1 : 0;
David Safb76832014-05-08 23:42:08 -04007111}
7112
7113/* returns result from SSL verify */
7114unsigned int ssl_sock_get_verify_result(struct connection *conn)
7115{
Christopher Faulet82004142019-09-10 10:12:03 +02007116 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007117
David Safb76832014-05-08 23:42:08 -04007118 if (!ssl_sock_is_ssl(conn))
7119 return (unsigned int)X509_V_ERR_APPLICATION_VERIFICATION;
Christopher Faulet82004142019-09-10 10:12:03 +02007120 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007121 return (unsigned int)SSL_get_verify_result(ctx->ssl);
David Safb76832014-05-08 23:42:08 -04007122}
7123
Willy Tarreau8743f7e2016-12-04 18:44:29 +01007124/* Returns the application layer protocol name in <str> and <len> when known.
7125 * Zero is returned if the protocol name was not found, otherwise non-zero is
7126 * returned. The string is allocated in the SSL context and doesn't have to be
7127 * freed by the caller. NPN is also checked if available since older versions
7128 * of openssl (1.0.1) which are more common in field only support this one.
7129 */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01007130static int ssl_sock_get_alpn(const struct connection *conn, void *xprt_ctx, const char **str, int *len)
Willy Tarreau8743f7e2016-12-04 18:44:29 +01007131{
Olivier Houchard66ab4982019-02-26 18:37:15 +01007132#if defined(TLSEXT_TYPE_application_layer_protocol_negotiation) || \
7133 defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Olivier Houcharde179d0e2019-03-21 18:27:17 +01007134 struct ssl_sock_ctx *ctx = xprt_ctx;
7135 if (!ctx)
Willy Tarreau8743f7e2016-12-04 18:44:29 +01007136 return 0;
7137
7138 *str = NULL;
7139
7140#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Olivier Houchard66ab4982019-02-26 18:37:15 +01007141 SSL_get0_alpn_selected(ctx->ssl, (const unsigned char **)str, (unsigned *)len);
Willy Tarreau8743f7e2016-12-04 18:44:29 +01007142 if (*str)
7143 return 1;
7144#endif
Bernard Spil13c53f82018-02-15 13:34:58 +01007145#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007146 SSL_get0_next_proto_negotiated(ctx->ssl, (const unsigned char **)str, (unsigned *)len);
Willy Tarreau8743f7e2016-12-04 18:44:29 +01007147 if (*str)
7148 return 1;
7149#endif
Olivier Houcharde179d0e2019-03-21 18:27:17 +01007150#endif
Willy Tarreau8743f7e2016-12-04 18:44:29 +01007151 return 0;
7152}
7153
Willy Tarreau7875d092012-09-10 08:20:03 +02007154/***** Below are some sample fetching functions for ACL/patterns *****/
7155
Olivier Houchardccaa7de2017-10-02 11:51:03 +02007156static int
7157smp_fetch_ssl_fc_has_early(const struct arg *args, struct sample *smp, const char *kw, void *private)
7158{
7159 struct connection *conn;
7160
7161 conn = objt_conn(smp->sess->origin);
7162 if (!conn || conn->xprt != &ssl_sock)
7163 return 0;
7164
7165 smp->flags = 0;
7166 smp->data.type = SMP_T_BOOL;
Emmanuel Hocdetc9858012019-08-07 14:44:49 +02007167#ifdef OPENSSL_IS_BORINGSSL
7168 {
7169 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
7170 smp->data.u.sint = (SSL_in_early_data(ctx->ssl) &&
7171 SSL_early_data_accepted(ctx->ssl));
7172 }
7173#else
Olivier Houchard25ae45a2017-11-29 19:51:19 +01007174 smp->data.u.sint = ((conn->flags & CO_FL_EARLY_DATA) &&
7175 (conn->flags & (CO_FL_EARLY_SSL_HS | CO_FL_HANDSHAKE))) ? 1 : 0;
Emmanuel Hocdetc9858012019-08-07 14:44:49 +02007176#endif
Olivier Houchardccaa7de2017-10-02 11:51:03 +02007177 return 1;
7178}
7179
Emeric Brune64aef12012-09-21 13:15:06 +02007180/* boolean, returns true if client cert was present */
7181static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007182smp_fetch_ssl_fc_has_crt(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brune64aef12012-09-21 13:15:06 +02007183{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007184 struct connection *conn;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007185 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007186
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007187 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007188 if (!conn || conn->xprt != &ssl_sock)
Emeric Brune64aef12012-09-21 13:15:06 +02007189 return 0;
7190
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007191 ctx = conn->xprt_ctx;
7192
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007193 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brune64aef12012-09-21 13:15:06 +02007194 smp->flags |= SMP_F_MAY_CHANGE;
7195 return 0;
7196 }
7197
7198 smp->flags = 0;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007199 smp->data.type = SMP_T_BOOL;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007200 smp->data.u.sint = SSL_SOCK_ST_FL_VERIFY_DONE & ctx->xprt_st ? 1 : 0;
Emeric Brune64aef12012-09-21 13:15:06 +02007201
7202 return 1;
7203}
7204
Emeric Brun43e79582014-10-29 19:03:26 +01007205/* binary, returns a certificate in a binary chunk (der/raw).
7206 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7207 * should be use.
7208 */
7209static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007210smp_fetch_ssl_x_der(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun43e79582014-10-29 19:03:26 +01007211{
7212 int cert_peer = (kw[4] == 'c') ? 1 : 0;
7213 X509 *crt = NULL;
7214 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02007215 struct buffer *smp_trash;
Emeric Brun43e79582014-10-29 19:03:26 +01007216 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007217 struct ssl_sock_ctx *ctx;
Emeric Brun43e79582014-10-29 19:03:26 +01007218
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007219 conn = objt_conn(smp->sess->origin);
Emeric Brun43e79582014-10-29 19:03:26 +01007220 if (!conn || conn->xprt != &ssl_sock)
7221 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007222 ctx = conn->xprt_ctx;
Emeric Brun43e79582014-10-29 19:03:26 +01007223
7224 if (!(conn->flags & CO_FL_CONNECTED)) {
7225 smp->flags |= SMP_F_MAY_CHANGE;
7226 return 0;
7227 }
7228
7229 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007230 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brun43e79582014-10-29 19:03:26 +01007231 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007232 crt = SSL_get_certificate(ctx->ssl);
Emeric Brun43e79582014-10-29 19:03:26 +01007233
7234 if (!crt)
7235 goto out;
7236
7237 smp_trash = get_trash_chunk();
7238 if (ssl_sock_crt2der(crt, smp_trash) <= 0)
7239 goto out;
7240
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007241 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007242 smp->data.type = SMP_T_BIN;
Emeric Brun43e79582014-10-29 19:03:26 +01007243 ret = 1;
7244out:
7245 /* SSL_get_peer_certificate, it increase X509 * ref count */
7246 if (cert_peer && crt)
7247 X509_free(crt);
7248 return ret;
7249}
7250
Emeric Brunba841a12014-04-30 17:05:08 +02007251/* binary, returns serial of certificate in a binary chunk.
7252 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7253 * should be use.
7254 */
Willy Tarreau8d598402012-10-22 17:58:39 +02007255static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007256smp_fetch_ssl_x_serial(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau8d598402012-10-22 17:58:39 +02007257{
Emeric Brunba841a12014-04-30 17:05:08 +02007258 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Willy Tarreau8d598402012-10-22 17:58:39 +02007259 X509 *crt = NULL;
7260 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02007261 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007262 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007263 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007264
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007265 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007266 if (!conn || conn->xprt != &ssl_sock)
Willy Tarreau8d598402012-10-22 17:58:39 +02007267 return 0;
7268
Olivier Houchard66ab4982019-02-26 18:37:15 +01007269 ctx = conn->xprt_ctx;
7270
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007271 if (!(conn->flags & CO_FL_CONNECTED)) {
Willy Tarreau8d598402012-10-22 17:58:39 +02007272 smp->flags |= SMP_F_MAY_CHANGE;
7273 return 0;
7274 }
7275
Emeric Brunba841a12014-04-30 17:05:08 +02007276 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007277 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007278 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007279 crt = SSL_get_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007280
Willy Tarreau8d598402012-10-22 17:58:39 +02007281 if (!crt)
7282 goto out;
7283
Willy Tarreau47ca5452012-12-23 20:22:19 +01007284 smp_trash = get_trash_chunk();
Willy Tarreau8d598402012-10-22 17:58:39 +02007285 if (ssl_sock_get_serial(crt, smp_trash) <= 0)
7286 goto out;
7287
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007288 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007289 smp->data.type = SMP_T_BIN;
Willy Tarreau8d598402012-10-22 17:58:39 +02007290 ret = 1;
7291out:
Emeric Brunba841a12014-04-30 17:05:08 +02007292 /* SSL_get_peer_certificate, it increase X509 * ref count */
7293 if (cert_peer && crt)
Willy Tarreau8d598402012-10-22 17:58:39 +02007294 X509_free(crt);
7295 return ret;
7296}
Emeric Brune64aef12012-09-21 13:15:06 +02007297
Emeric Brunba841a12014-04-30 17:05:08 +02007298/* binary, returns the client certificate's SHA-1 fingerprint (SHA-1 hash of DER-encoded certificate) in a binary chunk.
7299 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7300 * should be use.
7301 */
James Votha051b4a2013-05-14 20:37:59 +02007302static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007303smp_fetch_ssl_x_sha1(const struct arg *args, struct sample *smp, const char *kw, void *private)
James Votha051b4a2013-05-14 20:37:59 +02007304{
Emeric Brunba841a12014-04-30 17:05:08 +02007305 int cert_peer = (kw[4] == 'c') ? 1 : 0;
James Votha051b4a2013-05-14 20:37:59 +02007306 X509 *crt = NULL;
7307 const EVP_MD *digest;
7308 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02007309 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007310 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007311 struct ssl_sock_ctx *ctx;
James Votha051b4a2013-05-14 20:37:59 +02007312
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007313 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007314 if (!conn || conn->xprt != &ssl_sock)
7315 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007316 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007317
7318 if (!(conn->flags & CO_FL_CONNECTED)) {
James Votha051b4a2013-05-14 20:37:59 +02007319 smp->flags |= SMP_F_MAY_CHANGE;
7320 return 0;
7321 }
7322
Emeric Brunba841a12014-04-30 17:05:08 +02007323 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007324 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007325 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007326 crt = SSL_get_certificate(ctx->ssl);
James Votha051b4a2013-05-14 20:37:59 +02007327 if (!crt)
7328 goto out;
7329
7330 smp_trash = get_trash_chunk();
7331 digest = EVP_sha1();
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007332 X509_digest(crt, digest, (unsigned char *) smp_trash->area,
7333 (unsigned int *)&smp_trash->data);
James Votha051b4a2013-05-14 20:37:59 +02007334
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007335 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007336 smp->data.type = SMP_T_BIN;
James Votha051b4a2013-05-14 20:37:59 +02007337 ret = 1;
7338out:
Emeric Brunba841a12014-04-30 17:05:08 +02007339 /* SSL_get_peer_certificate, it increase X509 * ref count */
7340 if (cert_peer && crt)
James Votha051b4a2013-05-14 20:37:59 +02007341 X509_free(crt);
7342 return ret;
7343}
7344
Emeric Brunba841a12014-04-30 17:05:08 +02007345/* string, returns certificate's notafter date in ASN1_UTCTIME format.
7346 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7347 * should be use.
7348 */
Emeric Brunce5ad802012-10-22 14:11:22 +02007349static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007350smp_fetch_ssl_x_notafter(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunce5ad802012-10-22 14:11:22 +02007351{
Emeric Brunba841a12014-04-30 17:05:08 +02007352 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brunce5ad802012-10-22 14:11:22 +02007353 X509 *crt = NULL;
7354 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02007355 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007356 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007357 struct ssl_sock_ctx *ctx;
Emeric Brunce5ad802012-10-22 14:11:22 +02007358
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007359 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007360 if (!conn || conn->xprt != &ssl_sock)
7361 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007362 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007363
7364 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02007365 smp->flags |= SMP_F_MAY_CHANGE;
7366 return 0;
7367 }
7368
Emeric Brunba841a12014-04-30 17:05:08 +02007369 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007370 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007371 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007372 crt = SSL_get_certificate(ctx->ssl);
Emeric Brunce5ad802012-10-22 14:11:22 +02007373 if (!crt)
7374 goto out;
7375
Willy Tarreau47ca5452012-12-23 20:22:19 +01007376 smp_trash = get_trash_chunk();
Rosen Penev68185952018-12-14 08:47:02 -08007377 if (ssl_sock_get_time(X509_getm_notAfter(crt), smp_trash) <= 0)
Emeric Brunce5ad802012-10-22 14:11:22 +02007378 goto out;
7379
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007380 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007381 smp->data.type = SMP_T_STR;
Emeric Brunce5ad802012-10-22 14:11:22 +02007382 ret = 1;
7383out:
Emeric Brunba841a12014-04-30 17:05:08 +02007384 /* SSL_get_peer_certificate, it increase X509 * ref count */
7385 if (cert_peer && crt)
Emeric Brunce5ad802012-10-22 14:11:22 +02007386 X509_free(crt);
7387 return ret;
7388}
7389
Emeric Brunba841a12014-04-30 17:05:08 +02007390/* string, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. of certificate's issuer
7391 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7392 * should be use.
7393 */
Emeric Brun87855892012-10-17 17:39:35 +02007394static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007395smp_fetch_ssl_x_i_dn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun87855892012-10-17 17:39:35 +02007396{
Emeric Brunba841a12014-04-30 17:05:08 +02007397 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun87855892012-10-17 17:39:35 +02007398 X509 *crt = NULL;
7399 X509_NAME *name;
7400 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02007401 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007402 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007403 struct ssl_sock_ctx *ctx;
Emeric Brun87855892012-10-17 17:39:35 +02007404
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007405 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007406 if (!conn || conn->xprt != &ssl_sock)
7407 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007408 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007409
7410 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02007411 smp->flags |= SMP_F_MAY_CHANGE;
7412 return 0;
7413 }
7414
Emeric Brunba841a12014-04-30 17:05:08 +02007415 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007416 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007417 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007418 crt = SSL_get_certificate(ctx->ssl);
Emeric Brun87855892012-10-17 17:39:35 +02007419 if (!crt)
7420 goto out;
7421
7422 name = X509_get_issuer_name(crt);
7423 if (!name)
7424 goto out;
7425
Willy Tarreau47ca5452012-12-23 20:22:19 +01007426 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02007427 if (args && args[0].type == ARGT_STR) {
7428 int pos = 1;
7429
7430 if (args[1].type == ARGT_SINT)
7431 pos = args[1].data.sint;
Emeric Brun87855892012-10-17 17:39:35 +02007432
7433 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
7434 goto out;
7435 }
7436 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
7437 goto out;
7438
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007439 smp->data.type = SMP_T_STR;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007440 smp->data.u.str = *smp_trash;
Emeric Brun87855892012-10-17 17:39:35 +02007441 ret = 1;
7442out:
Emeric Brunba841a12014-04-30 17:05:08 +02007443 /* SSL_get_peer_certificate, it increase X509 * ref count */
7444 if (cert_peer && crt)
Emeric Brun87855892012-10-17 17:39:35 +02007445 X509_free(crt);
7446 return ret;
7447}
7448
Emeric Brunba841a12014-04-30 17:05:08 +02007449/* string, returns notbefore date in ASN1_UTCTIME format.
7450 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7451 * should be use.
7452 */
Emeric Brunce5ad802012-10-22 14:11:22 +02007453static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007454smp_fetch_ssl_x_notbefore(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunce5ad802012-10-22 14:11:22 +02007455{
Emeric Brunba841a12014-04-30 17:05:08 +02007456 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brunce5ad802012-10-22 14:11:22 +02007457 X509 *crt = NULL;
7458 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02007459 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007460 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007461 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007462
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007463 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007464 if (!conn || conn->xprt != &ssl_sock)
Emeric Brunce5ad802012-10-22 14:11:22 +02007465 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007466 ctx = conn->xprt_ctx;
Emeric Brunce5ad802012-10-22 14:11:22 +02007467
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007468 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02007469 smp->flags |= SMP_F_MAY_CHANGE;
7470 return 0;
7471 }
7472
Emeric Brunba841a12014-04-30 17:05:08 +02007473 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007474 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007475 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007476 crt = SSL_get_certificate(ctx->ssl);
Emeric Brunce5ad802012-10-22 14:11:22 +02007477 if (!crt)
7478 goto out;
7479
Willy Tarreau47ca5452012-12-23 20:22:19 +01007480 smp_trash = get_trash_chunk();
Rosen Penev68185952018-12-14 08:47:02 -08007481 if (ssl_sock_get_time(X509_getm_notBefore(crt), smp_trash) <= 0)
Emeric Brunce5ad802012-10-22 14:11:22 +02007482 goto out;
7483
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007484 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007485 smp->data.type = SMP_T_STR;
Emeric Brunce5ad802012-10-22 14:11:22 +02007486 ret = 1;
7487out:
Emeric Brunba841a12014-04-30 17:05:08 +02007488 /* SSL_get_peer_certificate, it increase X509 * ref count */
7489 if (cert_peer && crt)
Emeric Brunce5ad802012-10-22 14:11:22 +02007490 X509_free(crt);
7491 return ret;
7492}
7493
Emeric Brunba841a12014-04-30 17:05:08 +02007494/* string, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. of certificate's subject
7495 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7496 * should be use.
7497 */
Emeric Brun87855892012-10-17 17:39:35 +02007498static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007499smp_fetch_ssl_x_s_dn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun87855892012-10-17 17:39:35 +02007500{
Emeric Brunba841a12014-04-30 17:05:08 +02007501 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun87855892012-10-17 17:39:35 +02007502 X509 *crt = NULL;
7503 X509_NAME *name;
7504 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02007505 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007506 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007507 struct ssl_sock_ctx *ctx;
Emeric Brun87855892012-10-17 17:39:35 +02007508
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007509 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007510 if (!conn || conn->xprt != &ssl_sock)
7511 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007512 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007513
7514 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02007515 smp->flags |= SMP_F_MAY_CHANGE;
7516 return 0;
7517 }
7518
Emeric Brunba841a12014-04-30 17:05:08 +02007519 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007520 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007521 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007522 crt = SSL_get_certificate(ctx->ssl);
Emeric Brun87855892012-10-17 17:39:35 +02007523 if (!crt)
7524 goto out;
7525
7526 name = X509_get_subject_name(crt);
7527 if (!name)
7528 goto out;
7529
Willy Tarreau47ca5452012-12-23 20:22:19 +01007530 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02007531 if (args && args[0].type == ARGT_STR) {
7532 int pos = 1;
7533
7534 if (args[1].type == ARGT_SINT)
7535 pos = args[1].data.sint;
Emeric Brun87855892012-10-17 17:39:35 +02007536
7537 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
7538 goto out;
7539 }
7540 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
7541 goto out;
7542
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007543 smp->data.type = SMP_T_STR;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007544 smp->data.u.str = *smp_trash;
Emeric Brun87855892012-10-17 17:39:35 +02007545 ret = 1;
7546out:
Emeric Brunba841a12014-04-30 17:05:08 +02007547 /* SSL_get_peer_certificate, it increase X509 * ref count */
7548 if (cert_peer && crt)
Emeric Brun87855892012-10-17 17:39:35 +02007549 X509_free(crt);
7550 return ret;
7551}
Emeric Brun9143d372012-12-20 15:44:16 +01007552
7553/* integer, returns true if current session use a client certificate */
7554static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007555smp_fetch_ssl_c_used(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun9143d372012-12-20 15:44:16 +01007556{
7557 X509 *crt;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007558 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007559 struct ssl_sock_ctx *ctx;
Emeric Brun9143d372012-12-20 15:44:16 +01007560
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007561 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007562 if (!conn || conn->xprt != &ssl_sock)
7563 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007564 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007565
7566 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun9143d372012-12-20 15:44:16 +01007567 smp->flags |= SMP_F_MAY_CHANGE;
7568 return 0;
7569 }
7570
7571 /* SSL_get_peer_certificate returns a ptr on allocated X509 struct */
Olivier Houchard66ab4982019-02-26 18:37:15 +01007572 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brun9143d372012-12-20 15:44:16 +01007573 if (crt) {
7574 X509_free(crt);
7575 }
7576
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007577 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007578 smp->data.u.sint = (crt != NULL);
Emeric Brun9143d372012-12-20 15:44:16 +01007579 return 1;
7580}
7581
Emeric Brunba841a12014-04-30 17:05:08 +02007582/* integer, returns the certificate version
7583 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7584 * should be use.
7585 */
Emeric Bruna7359fd2012-10-17 15:03:11 +02007586static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007587smp_fetch_ssl_x_version(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Bruna7359fd2012-10-17 15:03:11 +02007588{
Emeric Brunba841a12014-04-30 17:05:08 +02007589 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Bruna7359fd2012-10-17 15:03:11 +02007590 X509 *crt;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007591 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007592 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007593
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007594 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007595 if (!conn || conn->xprt != &ssl_sock)
Emeric Bruna7359fd2012-10-17 15:03:11 +02007596 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007597 ctx = conn->xprt_ctx;
Emeric Bruna7359fd2012-10-17 15:03:11 +02007598
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007599 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Bruna7359fd2012-10-17 15:03:11 +02007600 smp->flags |= SMP_F_MAY_CHANGE;
7601 return 0;
7602 }
7603
Emeric Brunba841a12014-04-30 17:05:08 +02007604 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007605 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007606 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007607 crt = SSL_get_certificate(ctx->ssl);
Emeric Bruna7359fd2012-10-17 15:03:11 +02007608 if (!crt)
7609 return 0;
7610
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007611 smp->data.u.sint = (unsigned int)(1 + X509_get_version(crt));
Emeric Brunba841a12014-04-30 17:05:08 +02007612 /* SSL_get_peer_certificate increase X509 * ref count */
7613 if (cert_peer)
7614 X509_free(crt);
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007615 smp->data.type = SMP_T_SINT;
Emeric Bruna7359fd2012-10-17 15:03:11 +02007616
7617 return 1;
7618}
7619
Emeric Brunba841a12014-04-30 17:05:08 +02007620/* string, returns the certificate's signature algorithm.
7621 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7622 * should be use.
7623 */
Emeric Brun7f56e742012-10-19 18:15:40 +02007624static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007625smp_fetch_ssl_x_sig_alg(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun7f56e742012-10-19 18:15:40 +02007626{
Emeric Brunba841a12014-04-30 17:05:08 +02007627 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun7f56e742012-10-19 18:15:40 +02007628 X509 *crt;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007629 __OPENSSL_110_CONST__ ASN1_OBJECT *algorithm;
Emeric Brun7f56e742012-10-19 18:15:40 +02007630 int nid;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007631 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007632 struct ssl_sock_ctx *ctx;
Emeric Brun7f56e742012-10-19 18:15:40 +02007633
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007634 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007635 if (!conn || conn->xprt != &ssl_sock)
7636 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007637 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007638
7639 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun7f56e742012-10-19 18:15:40 +02007640 smp->flags |= SMP_F_MAY_CHANGE;
7641 return 0;
7642 }
7643
Emeric Brunba841a12014-04-30 17:05:08 +02007644 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007645 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007646 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007647 crt = SSL_get_certificate(ctx->ssl);
Emeric Brun7f56e742012-10-19 18:15:40 +02007648 if (!crt)
7649 return 0;
7650
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007651 X509_ALGOR_get0(&algorithm, NULL, NULL, X509_get0_tbs_sigalg(crt));
7652 nid = OBJ_obj2nid(algorithm);
Emeric Brun7f56e742012-10-19 18:15:40 +02007653
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007654 smp->data.u.str.area = (char *)OBJ_nid2sn(nid);
7655 if (!smp->data.u.str.area) {
Emeric Brunba841a12014-04-30 17:05:08 +02007656 /* SSL_get_peer_certificate increase X509 * ref count */
7657 if (cert_peer)
7658 X509_free(crt);
Emeric Brun7f56e742012-10-19 18:15:40 +02007659 return 0;
Emeric Brun9bf3ba22013-10-07 14:31:44 +02007660 }
Emeric Brun7f56e742012-10-19 18:15:40 +02007661
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007662 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01007663 smp->flags |= SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007664 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brunba841a12014-04-30 17:05:08 +02007665 /* SSL_get_peer_certificate increase X509 * ref count */
7666 if (cert_peer)
7667 X509_free(crt);
Emeric Brun7f56e742012-10-19 18:15:40 +02007668
7669 return 1;
7670}
7671
Emeric Brunba841a12014-04-30 17:05:08 +02007672/* string, returns the certificate's key algorithm.
7673 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7674 * should be use.
7675 */
Emeric Brun521a0112012-10-22 12:22:55 +02007676static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007677smp_fetch_ssl_x_key_alg(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun521a0112012-10-22 12:22:55 +02007678{
Emeric Brunba841a12014-04-30 17:05:08 +02007679 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun521a0112012-10-22 12:22:55 +02007680 X509 *crt;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007681 ASN1_OBJECT *algorithm;
Emeric Brun521a0112012-10-22 12:22:55 +02007682 int nid;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007683 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007684 struct ssl_sock_ctx *ctx;
Emeric Brun521a0112012-10-22 12:22:55 +02007685
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007686 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007687 if (!conn || conn->xprt != &ssl_sock)
7688 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007689 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007690
7691 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun521a0112012-10-22 12:22:55 +02007692 smp->flags |= SMP_F_MAY_CHANGE;
7693 return 0;
7694 }
7695
Emeric Brunba841a12014-04-30 17:05:08 +02007696 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007697 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007698 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007699 crt = SSL_get_certificate(ctx->ssl);
Emeric Brun521a0112012-10-22 12:22:55 +02007700 if (!crt)
7701 return 0;
7702
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007703 X509_PUBKEY_get0_param(&algorithm, NULL, NULL, NULL, X509_get_X509_PUBKEY(crt));
7704 nid = OBJ_obj2nid(algorithm);
Emeric Brun521a0112012-10-22 12:22:55 +02007705
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007706 smp->data.u.str.area = (char *)OBJ_nid2sn(nid);
7707 if (!smp->data.u.str.area) {
Emeric Brunba841a12014-04-30 17:05:08 +02007708 /* SSL_get_peer_certificate increase X509 * ref count */
7709 if (cert_peer)
7710 X509_free(crt);
Emeric Brun521a0112012-10-22 12:22:55 +02007711 return 0;
Emeric Brun9bf3ba22013-10-07 14:31:44 +02007712 }
Emeric Brun521a0112012-10-22 12:22:55 +02007713
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007714 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01007715 smp->flags |= SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007716 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brunba841a12014-04-30 17:05:08 +02007717 if (cert_peer)
7718 X509_free(crt);
Emeric Brun521a0112012-10-22 12:22:55 +02007719
7720 return 1;
7721}
7722
Emeric Brun645ae792014-04-30 14:21:06 +02007723/* boolean, returns true if front conn. transport layer is SSL.
7724 * This function is also usable on backend conn if the fetch keyword 5th
7725 * char is 'b'.
7726 */
Willy Tarreau7875d092012-09-10 08:20:03 +02007727static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007728smp_fetch_ssl_fc(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02007729{
Emeric Bruneb8def92018-02-19 15:59:48 +01007730 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7731 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007732
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007733 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007734 smp->data.u.sint = (conn && conn->xprt == &ssl_sock);
Willy Tarreau7875d092012-09-10 08:20:03 +02007735 return 1;
7736}
7737
Emeric Brun2525b6b2012-10-18 15:59:43 +02007738/* boolean, returns true if client present a SNI */
Willy Tarreau7875d092012-09-10 08:20:03 +02007739static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007740smp_fetch_ssl_fc_has_sni(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02007741{
7742#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007743 struct connection *conn = objt_conn(smp->sess->origin);
Olivier Houchard66ab4982019-02-26 18:37:15 +01007744 struct ssl_sock_ctx *ctx = conn ? conn->xprt_ctx : NULL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007745
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007746 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007747 smp->data.u.sint = (conn && conn->xprt == &ssl_sock) &&
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007748 conn->xprt_ctx &&
Olivier Houchard66ab4982019-02-26 18:37:15 +01007749 SSL_get_servername(ctx->ssl, TLSEXT_NAMETYPE_host_name) != NULL;
Willy Tarreau7875d092012-09-10 08:20:03 +02007750 return 1;
7751#else
7752 return 0;
7753#endif
7754}
7755
Emeric Brun74f7ffa2018-02-19 16:14:12 +01007756/* boolean, returns true if client session has been resumed.
7757 * This function is also usable on backend conn if the fetch keyword 5th
7758 * char is 'b'.
7759 */
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02007760static int
7761smp_fetch_ssl_fc_is_resumed(const struct arg *args, struct sample *smp, const char *kw, void *private)
7762{
Emeric Brun74f7ffa2018-02-19 16:14:12 +01007763 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7764 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007765 struct ssl_sock_ctx *ctx = conn ? conn->xprt_ctx : NULL;
Emeric Brun74f7ffa2018-02-19 16:14:12 +01007766
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02007767
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007768 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007769 smp->data.u.sint = (conn && conn->xprt == &ssl_sock) &&
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02007770 conn->xprt_ctx &&
Olivier Houchard66ab4982019-02-26 18:37:15 +01007771 SSL_session_reused(ctx->ssl);
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02007772 return 1;
7773}
7774
Emeric Brun645ae792014-04-30 14:21:06 +02007775/* string, returns the used cipher if front conn. transport layer is SSL.
7776 * This function is also usable on backend conn if the fetch keyword 5th
7777 * char is 'b'.
7778 */
Emeric Brun589fcad2012-10-16 14:13:26 +02007779static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007780smp_fetch_ssl_fc_cipher(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02007781{
Emeric Bruneb8def92018-02-19 15:59:48 +01007782 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7783 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007784 struct ssl_sock_ctx *ctx;
Emeric Brun589fcad2012-10-16 14:13:26 +02007785
Willy Tarreaube508f12016-03-10 11:47:01 +01007786 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007787 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02007788 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007789 ctx = conn->xprt_ctx;
Emeric Brun589fcad2012-10-16 14:13:26 +02007790
Olivier Houchard66ab4982019-02-26 18:37:15 +01007791 smp->data.u.str.area = (char *)SSL_get_cipher_name(ctx->ssl);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007792 if (!smp->data.u.str.area)
Emeric Brun589fcad2012-10-16 14:13:26 +02007793 return 0;
7794
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007795 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01007796 smp->flags |= SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007797 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brun589fcad2012-10-16 14:13:26 +02007798
7799 return 1;
7800}
7801
Emeric Brun645ae792014-04-30 14:21:06 +02007802/* integer, returns the algoritm's keysize if front conn. transport layer
7803 * is SSL.
7804 * This function is also usable on backend conn if the fetch keyword 5th
7805 * char is 'b'.
7806 */
Emeric Brun589fcad2012-10-16 14:13:26 +02007807static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007808smp_fetch_ssl_fc_alg_keysize(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02007809{
Emeric Bruneb8def92018-02-19 15:59:48 +01007810 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7811 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007812 struct ssl_sock_ctx *ctx;
Willy Tarreaue237fe12016-03-10 17:05:28 +01007813 int sint;
Willy Tarreaube508f12016-03-10 11:47:01 +01007814
Emeric Brun589fcad2012-10-16 14:13:26 +02007815 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007816 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02007817 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007818 ctx = conn->xprt_ctx;
Emeric Brun589fcad2012-10-16 14:13:26 +02007819
Olivier Houchard66ab4982019-02-26 18:37:15 +01007820 if (!SSL_get_cipher_bits(ctx->ssl, &sint))
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007821 return 0;
7822
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007823 smp->data.u.sint = sint;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007824 smp->data.type = SMP_T_SINT;
Emeric Brun589fcad2012-10-16 14:13:26 +02007825
7826 return 1;
7827}
7828
Emeric Brun645ae792014-04-30 14:21:06 +02007829/* integer, returns the used keysize if front conn. transport layer is SSL.
7830 * This function is also usable on backend conn if the fetch keyword 5th
7831 * char is 'b'.
7832 */
Emeric Brun589fcad2012-10-16 14:13:26 +02007833static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007834smp_fetch_ssl_fc_use_keysize(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02007835{
Emeric Bruneb8def92018-02-19 15:59:48 +01007836 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7837 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007838 struct ssl_sock_ctx *ctx;
Willy Tarreaube508f12016-03-10 11:47:01 +01007839
Emeric Brun589fcad2012-10-16 14:13:26 +02007840 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007841 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7842 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007843 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007844
Olivier Houchard66ab4982019-02-26 18:37:15 +01007845 smp->data.u.sint = (unsigned int)SSL_get_cipher_bits(ctx->ssl, NULL);
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007846 if (!smp->data.u.sint)
Emeric Brun589fcad2012-10-16 14:13:26 +02007847 return 0;
7848
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007849 smp->data.type = SMP_T_SINT;
Emeric Brun589fcad2012-10-16 14:13:26 +02007850
7851 return 1;
7852}
7853
Bernard Spil13c53f82018-02-15 13:34:58 +01007854#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Willy Tarreau7875d092012-09-10 08:20:03 +02007855static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007856smp_fetch_ssl_fc_npn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreaua33c6542012-10-15 13:19:06 +02007857{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007858 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007859 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007860
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01007861 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007862 smp->data.type = SMP_T_STR;
Willy Tarreaua33c6542012-10-15 13:19:06 +02007863
Olivier Houchard6b77f492018-11-22 18:18:29 +01007864 conn = (kw[4] != 'b' ) ? objt_conn(smp->sess->origin) :
7865 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007866 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7867 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007868 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007869
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007870 smp->data.u.str.area = NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007871 SSL_get0_next_proto_negotiated(ctx->ssl,
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007872 (const unsigned char **)&smp->data.u.str.area,
7873 (unsigned *)&smp->data.u.str.data);
Willy Tarreaua33c6542012-10-15 13:19:06 +02007874
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007875 if (!smp->data.u.str.area)
Willy Tarreaua33c6542012-10-15 13:19:06 +02007876 return 0;
7877
7878 return 1;
Willy Tarreaua33c6542012-10-15 13:19:06 +02007879}
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02007880#endif
Willy Tarreaua33c6542012-10-15 13:19:06 +02007881
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01007882#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02007883static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007884smp_fetch_ssl_fc_alpn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreauab861d32013-04-02 02:30:41 +02007885{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007886 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007887 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007888
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01007889 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007890 smp->data.type = SMP_T_STR;
Willy Tarreauab861d32013-04-02 02:30:41 +02007891
Olivier Houchard6b77f492018-11-22 18:18:29 +01007892 conn = (kw[4] != 'b' ) ? objt_conn(smp->sess->origin) :
7893 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
7894
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007895 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Willy Tarreauab861d32013-04-02 02:30:41 +02007896 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007897 ctx = conn->xprt_ctx;
Willy Tarreauab861d32013-04-02 02:30:41 +02007898
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007899 smp->data.u.str.area = NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007900 SSL_get0_alpn_selected(ctx->ssl,
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007901 (const unsigned char **)&smp->data.u.str.area,
7902 (unsigned *)&smp->data.u.str.data);
Willy Tarreauab861d32013-04-02 02:30:41 +02007903
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007904 if (!smp->data.u.str.area)
Willy Tarreauab861d32013-04-02 02:30:41 +02007905 return 0;
7906
7907 return 1;
7908}
7909#endif
7910
Emeric Brun645ae792014-04-30 14:21:06 +02007911/* string, returns the used protocol if front conn. transport layer is SSL.
7912 * This function is also usable on backend conn if the fetch keyword 5th
7913 * char is 'b'.
7914 */
Willy Tarreaua33c6542012-10-15 13:19:06 +02007915static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007916smp_fetch_ssl_fc_protocol(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02007917{
Emeric Bruneb8def92018-02-19 15:59:48 +01007918 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7919 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007920 struct ssl_sock_ctx *ctx;
Willy Tarreaube508f12016-03-10 11:47:01 +01007921
Emeric Brun589fcad2012-10-16 14:13:26 +02007922 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007923 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7924 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007925 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007926
Olivier Houchard66ab4982019-02-26 18:37:15 +01007927 smp->data.u.str.area = (char *)SSL_get_version(ctx->ssl);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007928 if (!smp->data.u.str.area)
Emeric Brun589fcad2012-10-16 14:13:26 +02007929 return 0;
7930
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007931 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01007932 smp->flags = SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007933 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brun589fcad2012-10-16 14:13:26 +02007934
7935 return 1;
7936}
7937
Willy Tarreau87b09662015-04-03 00:22:06 +02007938/* binary, returns the SSL stream id if front conn. transport layer is SSL.
Emeric Brun645ae792014-04-30 14:21:06 +02007939 * This function is also usable on backend conn if the fetch keyword 5th
7940 * char is 'b'.
7941 */
Willy Tarreau9a1ab082019-05-09 13:26:41 +02007942#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
Emeric Brun589fcad2012-10-16 14:13:26 +02007943static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007944smp_fetch_ssl_fc_session_id(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunfe68f682012-10-16 14:59:28 +02007945{
Emeric Bruneb8def92018-02-19 15:59:48 +01007946 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7947 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaue237fe12016-03-10 17:05:28 +01007948 SSL_SESSION *ssl_sess;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007949 struct ssl_sock_ctx *ctx;
Willy Tarreaube508f12016-03-10 11:47:01 +01007950
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01007951 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007952 smp->data.type = SMP_T_BIN;
Emeric Brunfe68f682012-10-16 14:59:28 +02007953
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007954 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7955 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007956 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007957
Olivier Houchard66ab4982019-02-26 18:37:15 +01007958 ssl_sess = SSL_get_session(ctx->ssl);
Willy Tarreau192252e2015-04-04 01:47:55 +02007959 if (!ssl_sess)
Emeric Brunfe68f682012-10-16 14:59:28 +02007960 return 0;
7961
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007962 smp->data.u.str.area = (char *)SSL_SESSION_get_id(ssl_sess,
7963 (unsigned int *)&smp->data.u.str.data);
7964 if (!smp->data.u.str.area || !smp->data.u.str.data)
Emeric Brunfe68f682012-10-16 14:59:28 +02007965 return 0;
7966
7967 return 1;
Emeric Brunfe68f682012-10-16 14:59:28 +02007968}
Patrick Hemmer41966772018-04-28 19:15:48 -04007969#endif
7970
Emeric Brunfe68f682012-10-16 14:59:28 +02007971
Emmanuel Hocdet839af572019-05-14 16:27:35 +02007972#if HA_OPENSSL_VERSION_NUMBER >= 0x10100000L
Patrick Hemmere0275472018-04-28 19:15:51 -04007973static int
Patrick Hemmer65674662019-06-04 08:13:03 -04007974smp_fetch_ssl_fc_random(const struct arg *args, struct sample *smp, const char *kw, void *private)
7975{
7976 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7977 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
7978 struct buffer *data;
7979 struct ssl_sock_ctx *ctx;
7980
7981 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7982 return 0;
7983 ctx = conn->xprt_ctx;
7984
7985 data = get_trash_chunk();
7986 if (kw[7] == 'c')
7987 data->data = SSL_get_client_random(ctx->ssl,
7988 (unsigned char *) data->area,
7989 data->size);
7990 else
7991 data->data = SSL_get_server_random(ctx->ssl,
7992 (unsigned char *) data->area,
7993 data->size);
7994 if (!data->data)
7995 return 0;
7996
7997 smp->flags = 0;
7998 smp->data.type = SMP_T_BIN;
7999 smp->data.u.str = *data;
8000
8001 return 1;
8002}
8003
8004static int
Patrick Hemmere0275472018-04-28 19:15:51 -04008005smp_fetch_ssl_fc_session_key(const struct arg *args, struct sample *smp, const char *kw, void *private)
8006{
8007 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
8008 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
8009 SSL_SESSION *ssl_sess;
Willy Tarreau83061a82018-07-13 11:56:34 +02008010 struct buffer *data;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008011 struct ssl_sock_ctx *ctx;
Patrick Hemmere0275472018-04-28 19:15:51 -04008012
8013 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8014 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008015 ctx = conn->xprt_ctx;
Patrick Hemmere0275472018-04-28 19:15:51 -04008016
Olivier Houchard66ab4982019-02-26 18:37:15 +01008017 ssl_sess = SSL_get_session(ctx->ssl);
Patrick Hemmere0275472018-04-28 19:15:51 -04008018 if (!ssl_sess)
8019 return 0;
8020
8021 data = get_trash_chunk();
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008022 data->data = SSL_SESSION_get_master_key(ssl_sess,
8023 (unsigned char *) data->area,
8024 data->size);
8025 if (!data->data)
Patrick Hemmere0275472018-04-28 19:15:51 -04008026 return 0;
8027
8028 smp->flags = 0;
8029 smp->data.type = SMP_T_BIN;
8030 smp->data.u.str = *data;
8031
8032 return 1;
8033}
8034#endif
8035
Patrick Hemmer41966772018-04-28 19:15:48 -04008036#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emeric Brunfe68f682012-10-16 14:59:28 +02008037static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008038smp_fetch_ssl_fc_sni(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02008039{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008040 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008041 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008042
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008043 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008044 smp->data.type = SMP_T_STR;
Willy Tarreau7875d092012-09-10 08:20:03 +02008045
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02008046 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008047 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8048 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008049 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008050
Olivier Houchard66ab4982019-02-26 18:37:15 +01008051 smp->data.u.str.area = (char *)SSL_get_servername(ctx->ssl, TLSEXT_NAMETYPE_host_name);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008052 if (!smp->data.u.str.area)
Willy Tarreau3e394c92012-09-14 23:56:58 +02008053 return 0;
8054
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008055 smp->data.u.str.data = strlen(smp->data.u.str.area);
Willy Tarreau7875d092012-09-10 08:20:03 +02008056 return 1;
Willy Tarreau7875d092012-09-10 08:20:03 +02008057}
Patrick Hemmer41966772018-04-28 19:15:48 -04008058#endif
Willy Tarreau7875d092012-09-10 08:20:03 +02008059
David Sc1ad52e2014-04-08 18:48:47 -04008060static int
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008061smp_fetch_ssl_fc_cl_bin(const struct arg *args, struct sample *smp, const char *kw, void *private)
8062{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008063 struct connection *conn;
8064 struct ssl_capture *capture;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008065 struct ssl_sock_ctx *ctx;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008066
8067 conn = objt_conn(smp->sess->origin);
8068 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8069 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008070 ctx = conn->xprt_ctx;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008071
Olivier Houchard66ab4982019-02-26 18:37:15 +01008072 capture = SSL_get_ex_data(ctx->ssl, ssl_capture_ptr_index);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008073 if (!capture)
8074 return 0;
8075
8076 smp->flags = SMP_F_CONST;
8077 smp->data.type = SMP_T_BIN;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008078 smp->data.u.str.area = capture->ciphersuite;
8079 smp->data.u.str.data = capture->ciphersuite_len;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008080 return 1;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008081}
8082
8083static int
8084smp_fetch_ssl_fc_cl_hex(const struct arg *args, struct sample *smp, const char *kw, void *private)
8085{
Willy Tarreau83061a82018-07-13 11:56:34 +02008086 struct buffer *data;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008087
8088 if (!smp_fetch_ssl_fc_cl_bin(args, smp, kw, private))
8089 return 0;
8090
8091 data = get_trash_chunk();
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008092 dump_binary(data, smp->data.u.str.area, smp->data.u.str.data);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008093 smp->data.type = SMP_T_BIN;
8094 smp->data.u.str = *data;
8095 return 1;
8096}
8097
8098static int
8099smp_fetch_ssl_fc_cl_xxh64(const struct arg *args, struct sample *smp, const char *kw, void *private)
8100{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008101 struct connection *conn;
8102 struct ssl_capture *capture;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008103 struct ssl_sock_ctx *ctx;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008104
8105 conn = objt_conn(smp->sess->origin);
8106 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8107 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008108 ctx = conn->xprt_ctx;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008109
Olivier Houchard66ab4982019-02-26 18:37:15 +01008110 capture = SSL_get_ex_data(ctx->ssl, ssl_capture_ptr_index);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008111 if (!capture)
8112 return 0;
8113
8114 smp->data.type = SMP_T_SINT;
8115 smp->data.u.sint = capture->xxh64;
8116 return 1;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008117}
8118
8119static int
8120smp_fetch_ssl_fc_cl_str(const struct arg *args, struct sample *smp, const char *kw, void *private)
8121{
Willy Tarreau5db847a2019-05-09 14:13:35 +02008122#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL)
Willy Tarreau83061a82018-07-13 11:56:34 +02008123 struct buffer *data;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008124 int i;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008125
8126 if (!smp_fetch_ssl_fc_cl_bin(args, smp, kw, private))
8127 return 0;
8128
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008129 data = get_trash_chunk();
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008130 for (i = 0; i + 1 < smp->data.u.str.data; i += 2) {
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02008131 const char *str;
8132 const SSL_CIPHER *cipher;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008133 const unsigned char *bin = (const unsigned char *) smp->data.u.str.area + i;
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02008134 uint16_t id = (bin[0] << 8) | bin[1];
8135#if defined(OPENSSL_IS_BORINGSSL)
8136 cipher = SSL_get_cipher_by_value(id);
8137#else
Willy Tarreaub7290772018-10-15 11:01:59 +02008138 struct connection *conn = __objt_conn(smp->sess->origin);
Olivier Houchard66ab4982019-02-26 18:37:15 +01008139 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
8140 cipher = SSL_CIPHER_find(ctx->ssl, bin);
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02008141#endif
8142 str = SSL_CIPHER_get_name(cipher);
8143 if (!str || strcmp(str, "(NONE)") == 0)
8144 chunk_appendf(data, "%sUNKNOWN(%04x)", i == 0 ? "" : ",", id);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008145 else
8146 chunk_appendf(data, "%s%s", i == 0 ? "" : ",", str);
8147 }
8148 smp->data.type = SMP_T_STR;
8149 smp->data.u.str = *data;
8150 return 1;
8151#else
8152 return smp_fetch_ssl_fc_cl_xxh64(args, smp, kw, private);
8153#endif
8154}
8155
Willy Tarreau9a1ab082019-05-09 13:26:41 +02008156#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008157static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008158smp_fetch_ssl_fc_unique_id(const struct arg *args, struct sample *smp, const char *kw, void *private)
David Sc1ad52e2014-04-08 18:48:47 -04008159{
Emeric Bruneb8def92018-02-19 15:59:48 +01008160 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
8161 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
David Sc1ad52e2014-04-08 18:48:47 -04008162 int finished_len;
Willy Tarreau83061a82018-07-13 11:56:34 +02008163 struct buffer *finished_trash;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008164 struct ssl_sock_ctx *ctx;
David Sc1ad52e2014-04-08 18:48:47 -04008165
8166 smp->flags = 0;
David Sc1ad52e2014-04-08 18:48:47 -04008167 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8168 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008169 ctx = conn->xprt_ctx;
David Sc1ad52e2014-04-08 18:48:47 -04008170
8171 if (!(conn->flags & CO_FL_CONNECTED)) {
8172 smp->flags |= SMP_F_MAY_CHANGE;
8173 return 0;
8174 }
8175
8176 finished_trash = get_trash_chunk();
Olivier Houchard66ab4982019-02-26 18:37:15 +01008177 if (!SSL_session_reused(ctx->ssl))
8178 finished_len = SSL_get_peer_finished(ctx->ssl,
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008179 finished_trash->area,
8180 finished_trash->size);
David Sc1ad52e2014-04-08 18:48:47 -04008181 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01008182 finished_len = SSL_get_finished(ctx->ssl,
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008183 finished_trash->area,
8184 finished_trash->size);
David Sc1ad52e2014-04-08 18:48:47 -04008185
8186 if (!finished_len)
8187 return 0;
8188
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008189 finished_trash->data = finished_len;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02008190 smp->data.u.str = *finished_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008191 smp->data.type = SMP_T_BIN;
David Sc1ad52e2014-04-08 18:48:47 -04008192
8193 return 1;
David Sc1ad52e2014-04-08 18:48:47 -04008194}
Patrick Hemmer41966772018-04-28 19:15:48 -04008195#endif
David Sc1ad52e2014-04-08 18:48:47 -04008196
Emeric Brun2525b6b2012-10-18 15:59:43 +02008197/* integer, returns the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02008198static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008199smp_fetch_ssl_c_ca_err(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunf282a812012-09-21 15:27:54 +02008200{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008201 struct connection *conn;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008202 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008203
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02008204 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008205 if (!conn || conn->xprt != &ssl_sock)
8206 return 0;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008207 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008208
8209 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02008210 smp->flags = SMP_F_MAY_CHANGE;
8211 return 0;
8212 }
8213
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008214 smp->data.type = SMP_T_SINT;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008215 smp->data.u.sint = (unsigned long long int)SSL_SOCK_ST_TO_CA_ERROR(ctx->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02008216 smp->flags = 0;
8217
8218 return 1;
8219}
8220
Emeric Brun2525b6b2012-10-18 15:59:43 +02008221/* integer, returns the depth of the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02008222static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008223smp_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 +02008224{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008225 struct connection *conn;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008226 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008227
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02008228 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008229 if (!conn || conn->xprt != &ssl_sock)
Emeric Brunf282a812012-09-21 15:27:54 +02008230 return 0;
8231
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008232 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02008233 smp->flags = SMP_F_MAY_CHANGE;
8234 return 0;
8235 }
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008236 ctx = conn->xprt_ctx;
Emeric Brunf282a812012-09-21 15:27:54 +02008237
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008238 smp->data.type = SMP_T_SINT;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008239 smp->data.u.sint = (long long int)SSL_SOCK_ST_TO_CAEDEPTH(ctx->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02008240 smp->flags = 0;
8241
8242 return 1;
8243}
8244
Emeric Brun2525b6b2012-10-18 15:59:43 +02008245/* integer, returns the first verify error on client certificate */
Emeric Brunf282a812012-09-21 15:27:54 +02008246static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008247smp_fetch_ssl_c_err(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunf282a812012-09-21 15:27:54 +02008248{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008249 struct connection *conn;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008250 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008251
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02008252 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008253 if (!conn || conn->xprt != &ssl_sock)
8254 return 0;
8255
8256 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02008257 smp->flags = SMP_F_MAY_CHANGE;
8258 return 0;
8259 }
8260
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008261 ctx = conn->xprt_ctx;
8262
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008263 smp->data.type = SMP_T_SINT;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008264 smp->data.u.sint = (long long int)SSL_SOCK_ST_TO_CRTERROR(ctx->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02008265 smp->flags = 0;
8266
8267 return 1;
8268}
8269
Emeric Brun2525b6b2012-10-18 15:59:43 +02008270/* integer, returns the verify result on client cert */
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02008271static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008272smp_fetch_ssl_c_verify(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02008273{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008274 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008275 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008276
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02008277 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008278 if (!conn || conn->xprt != &ssl_sock)
8279 return 0;
8280
8281 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02008282 smp->flags = SMP_F_MAY_CHANGE;
8283 return 0;
8284 }
8285
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008286 if (!conn->xprt_ctx)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02008287 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008288 ctx = conn->xprt_ctx;
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02008289
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008290 smp->data.type = SMP_T_SINT;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008291 smp->data.u.sint = (long long int)SSL_get_verify_result(ctx->ssl);
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02008292 smp->flags = 0;
8293
8294 return 1;
8295}
8296
Emeric Brunfb510ea2012-10-05 12:00:26 +02008297/* parse the "ca-file" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008298static 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 +02008299{
8300 if (!*args[cur_arg + 1]) {
8301 if (err)
8302 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
8303 return ERR_ALERT | ERR_FATAL;
8304 }
8305
Willy Tarreauef934602016-12-22 23:12:01 +01008306 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
8307 memprintf(&conf->ca_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02008308 else
8309 memprintf(&conf->ca_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02008310
Emeric Brund94b3fe2012-09-20 18:23:56 +02008311 return 0;
8312}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008313static int bind_parse_ca_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8314{
8315 return ssl_bind_parse_ca_file(args, cur_arg, px, &conf->ssl_conf, err);
8316}
Emeric Brund94b3fe2012-09-20 18:23:56 +02008317
Christopher Faulet31af49d2015-06-09 17:29:50 +02008318/* parse the "ca-sign-file" bind keyword */
8319static int bind_parse_ca_sign_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8320{
8321 if (!*args[cur_arg + 1]) {
8322 if (err)
8323 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
8324 return ERR_ALERT | ERR_FATAL;
8325 }
8326
Willy Tarreauef934602016-12-22 23:12:01 +01008327 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
8328 memprintf(&conf->ca_sign_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Christopher Faulet31af49d2015-06-09 17:29:50 +02008329 else
8330 memprintf(&conf->ca_sign_file, "%s", args[cur_arg + 1]);
8331
8332 return 0;
8333}
8334
Bertrand Jacquinff13c062016-11-13 16:37:11 +00008335/* parse the "ca-sign-pass" bind keyword */
Christopher Faulet31af49d2015-06-09 17:29:50 +02008336static int bind_parse_ca_sign_pass(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8337{
8338 if (!*args[cur_arg + 1]) {
8339 if (err)
8340 memprintf(err, "'%s' : missing CAkey password", args[cur_arg]);
8341 return ERR_ALERT | ERR_FATAL;
8342 }
8343 memprintf(&conf->ca_sign_pass, "%s", args[cur_arg + 1]);
8344 return 0;
8345}
8346
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008347/* parse the "ciphers" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008348static 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 +02008349{
8350 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02008351 memprintf(err, "'%s' : missing cipher suite", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008352 return ERR_ALERT | ERR_FATAL;
8353 }
8354
Emeric Brun76d88952012-10-05 15:47:31 +02008355 free(conf->ciphers);
Willy Tarreau4348fad2012-09-20 16:48:07 +02008356 conf->ciphers = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008357 return 0;
8358}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008359static int bind_parse_ciphers(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8360{
8361 return ssl_bind_parse_ciphers(args, cur_arg, px, &conf->ssl_conf, err);
8362}
Dirkjan Bussink415150f2018-09-14 11:14:21 +02008363
Emmanuel Hocdet839af572019-05-14 16:27:35 +02008364#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02008365/* parse the "ciphersuites" bind keyword */
8366static int ssl_bind_parse_ciphersuites(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
8367{
8368 if (!*args[cur_arg + 1]) {
8369 memprintf(err, "'%s' : missing cipher suite", args[cur_arg]);
8370 return ERR_ALERT | ERR_FATAL;
8371 }
8372
8373 free(conf->ciphersuites);
8374 conf->ciphersuites = strdup(args[cur_arg + 1]);
8375 return 0;
8376}
8377static int bind_parse_ciphersuites(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8378{
8379 return ssl_bind_parse_ciphersuites(args, cur_arg, px, &conf->ssl_conf, err);
8380}
8381#endif
8382
Willy Tarreaubbc91962019-10-16 16:42:19 +02008383/* parse the "crt" bind keyword. Returns a set of ERR_* flags possibly with an error in <err>. */
Willy Tarreau4348fad2012-09-20 16:48:07 +02008384static 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 +02008385{
Willy Tarreau38011032013-08-13 16:59:39 +02008386 char path[MAXPATHLEN];
Willy Tarreaub75d6922014-04-14 18:05:41 +02008387
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008388 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02008389 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008390 return ERR_ALERT | ERR_FATAL;
8391 }
8392
Willy Tarreauef934602016-12-22 23:12:01 +01008393 if ((*args[cur_arg + 1] != '/' ) && global_ssl.crt_base) {
8394 if ((strlen(global_ssl.crt_base) + 1 + strlen(args[cur_arg + 1]) + 1) > MAXPATHLEN) {
Emeric Brunc8e8d122012-10-02 18:42:10 +02008395 memprintf(err, "'%s' : path too long", args[cur_arg]);
8396 return ERR_ALERT | ERR_FATAL;
8397 }
Willy Tarreauef934602016-12-22 23:12:01 +01008398 snprintf(path, sizeof(path), "%s/%s", global_ssl.crt_base, args[cur_arg + 1]);
Willy Tarreaubbc91962019-10-16 16:42:19 +02008399 return ssl_sock_load_cert(path, conf, err);
Emeric Brunc8e8d122012-10-02 18:42:10 +02008400 }
8401
Willy Tarreaubbc91962019-10-16 16:42:19 +02008402 return ssl_sock_load_cert(args[cur_arg + 1], conf, err);
Emeric Brund94b3fe2012-09-20 18:23:56 +02008403}
8404
Willy Tarreaubbc91962019-10-16 16:42:19 +02008405/* parse the "crt-list" bind keyword. Returns a set of ERR_* flags possibly with an error in <err>. */
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01008406static int bind_parse_crt_list(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8407{
Willy Tarreaubbc91962019-10-16 16:42:19 +02008408 int err_code;
8409
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01008410 if (!*args[cur_arg + 1]) {
8411 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
8412 return ERR_ALERT | ERR_FATAL;
8413 }
8414
Willy Tarreaubbc91962019-10-16 16:42:19 +02008415 err_code = ssl_sock_load_cert_list_file(args[cur_arg + 1], conf, px, err);
8416 if (err_code)
Willy Tarreauad1731d2013-04-02 17:35:58 +02008417 memprintf(err, "'%s' : %s", args[cur_arg], *err);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01008418
Willy Tarreaubbc91962019-10-16 16:42:19 +02008419 return err_code;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01008420}
8421
Emeric Brunfb510ea2012-10-05 12:00:26 +02008422/* parse the "crl-file" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008423static 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 +02008424{
Emeric Brun051cdab2012-10-02 19:25:50 +02008425#ifndef X509_V_FLAG_CRL_CHECK
8426 if (err)
8427 memprintf(err, "'%s' : library does not support CRL verify", args[cur_arg]);
8428 return ERR_ALERT | ERR_FATAL;
8429#else
Emeric Brund94b3fe2012-09-20 18:23:56 +02008430 if (!*args[cur_arg + 1]) {
8431 if (err)
8432 memprintf(err, "'%s' : missing CRLfile path", args[cur_arg]);
8433 return ERR_ALERT | ERR_FATAL;
8434 }
Emeric Brun2b58d042012-09-20 17:10:03 +02008435
Willy Tarreauef934602016-12-22 23:12:01 +01008436 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
8437 memprintf(&conf->crl_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02008438 else
8439 memprintf(&conf->crl_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02008440
Emeric Brun2b58d042012-09-20 17:10:03 +02008441 return 0;
Emeric Brun051cdab2012-10-02 19:25:50 +02008442#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02008443}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008444static int bind_parse_crl_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8445{
8446 return ssl_bind_parse_crl_file(args, cur_arg, px, &conf->ssl_conf, err);
8447}
Emeric Brun2b58d042012-09-20 17:10:03 +02008448
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01008449/* parse the "curves" bind keyword keyword */
8450static int ssl_bind_parse_curves(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
8451{
Willy Tarreau9a1ab082019-05-09 13:26:41 +02008452#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01008453 if (!*args[cur_arg + 1]) {
8454 if (err)
8455 memprintf(err, "'%s' : missing curve suite", args[cur_arg]);
8456 return ERR_ALERT | ERR_FATAL;
8457 }
8458 conf->curves = strdup(args[cur_arg + 1]);
8459 return 0;
8460#else
8461 if (err)
8462 memprintf(err, "'%s' : library does not support curve suite", args[cur_arg]);
8463 return ERR_ALERT | ERR_FATAL;
8464#endif
8465}
8466static int bind_parse_curves(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8467{
8468 return ssl_bind_parse_curves(args, cur_arg, px, &conf->ssl_conf, err);
8469}
8470
Bertrand Jacquinff13c062016-11-13 16:37:11 +00008471/* parse the "ecdhe" bind keyword keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008472static 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 +02008473{
Willy Tarreau9a1ab082019-05-09 13:26:41 +02008474#if HA_OPENSSL_VERSION_NUMBER < 0x0090800fL
Emeric Brun2b58d042012-09-20 17:10:03 +02008475 if (err)
8476 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (too old)", args[cur_arg]);
8477 return ERR_ALERT | ERR_FATAL;
8478#elif defined(OPENSSL_NO_ECDH)
8479 if (err)
8480 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (disabled via OPENSSL_NO_ECDH)", args[cur_arg]);
8481 return ERR_ALERT | ERR_FATAL;
8482#else
8483 if (!*args[cur_arg + 1]) {
8484 if (err)
8485 memprintf(err, "'%s' : missing named curve", args[cur_arg]);
8486 return ERR_ALERT | ERR_FATAL;
8487 }
8488
8489 conf->ecdhe = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008490
8491 return 0;
Emeric Brun2b58d042012-09-20 17:10:03 +02008492#endif
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008493}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008494static int bind_parse_ecdhe(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8495{
8496 return ssl_bind_parse_ecdhe(args, cur_arg, px, &conf->ssl_conf, err);
8497}
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008498
Bertrand Jacquinff13c062016-11-13 16:37:11 +00008499/* parse the "crt-ignore-err" and "ca-ignore-err" bind keywords */
Emeric Brun81c00f02012-09-21 14:31:21 +02008500static int bind_parse_ignore_err(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8501{
8502 int code;
8503 char *p = args[cur_arg + 1];
8504 unsigned long long *ignerr = &conf->crt_ignerr;
8505
8506 if (!*p) {
8507 if (err)
8508 memprintf(err, "'%s' : missing error IDs list", args[cur_arg]);
8509 return ERR_ALERT | ERR_FATAL;
8510 }
8511
8512 if (strcmp(args[cur_arg], "ca-ignore-err") == 0)
8513 ignerr = &conf->ca_ignerr;
8514
8515 if (strcmp(p, "all") == 0) {
8516 *ignerr = ~0ULL;
8517 return 0;
8518 }
8519
8520 while (p) {
8521 code = atoi(p);
8522 if ((code <= 0) || (code > 63)) {
8523 if (err)
8524 memprintf(err, "'%s' : ID '%d' out of range (1..63) in error IDs list '%s'",
8525 args[cur_arg], code, args[cur_arg + 1]);
8526 return ERR_ALERT | ERR_FATAL;
8527 }
8528 *ignerr |= 1ULL << code;
8529 p = strchr(p, ',');
8530 if (p)
8531 p++;
8532 }
8533
Emeric Brun2cb7ae52012-10-05 14:14:21 +02008534 return 0;
8535}
8536
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008537/* parse tls_method_options "no-xxx" and "force-xxx" */
8538static int parse_tls_method_options(char *arg, struct tls_version_filter *methods, char **err)
Emeric Brun2cb7ae52012-10-05 14:14:21 +02008539{
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008540 uint16_t v;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008541 char *p;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008542 p = strchr(arg, '-');
8543 if (!p)
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008544 goto fail;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008545 p++;
8546 if (!strcmp(p, "sslv3"))
8547 v = CONF_SSLV3;
8548 else if (!strcmp(p, "tlsv10"))
8549 v = CONF_TLSV10;
8550 else if (!strcmp(p, "tlsv11"))
8551 v = CONF_TLSV11;
8552 else if (!strcmp(p, "tlsv12"))
8553 v = CONF_TLSV12;
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +02008554 else if (!strcmp(p, "tlsv13"))
8555 v = CONF_TLSV13;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008556 else
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008557 goto fail;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008558 if (!strncmp(arg, "no-", 3))
8559 methods->flags |= methodVersions[v].flag;
8560 else if (!strncmp(arg, "force-", 6))
8561 methods->min = methods->max = v;
8562 else
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008563 goto fail;
Emeric Brun2d0c4822012-10-02 13:45:20 +02008564 return 0;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008565 fail:
8566 if (err)
8567 memprintf(err, "'%s' : option not implemented", arg);
8568 return ERR_ALERT | ERR_FATAL;
Emeric Brun2d0c4822012-10-02 13:45:20 +02008569}
8570
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008571static 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 +02008572{
Emmanuel Hocdet43664762017-08-09 18:26:20 +02008573 return parse_tls_method_options(args[cur_arg], &conf->ssl_conf.ssl_methods, err);
Emeric Brun2cb7ae52012-10-05 14:14:21 +02008574}
8575
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008576static 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 +02008577{
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008578 return parse_tls_method_options(args[*cur_arg], &newsrv->ssl_ctx.methods, err);
8579}
8580
8581/* parse tls_method min/max: "ssl-min-ver" and "ssl-max-ver" */
8582static int parse_tls_method_minmax(char **args, int cur_arg, struct tls_version_filter *methods, char **err)
8583{
8584 uint16_t i, v = 0;
8585 char *argv = args[cur_arg + 1];
8586 if (!*argv) {
8587 if (err)
8588 memprintf(err, "'%s' : missing the ssl/tls version", args[cur_arg]);
8589 return ERR_ALERT | ERR_FATAL;
8590 }
8591 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
8592 if (!strcmp(argv, methodVersions[i].name))
8593 v = i;
8594 if (!v) {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008595 if (err)
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008596 memprintf(err, "'%s' : unknown ssl/tls version", args[cur_arg + 1]);
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008597 return ERR_ALERT | ERR_FATAL;
8598 }
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008599 if (!strcmp("ssl-min-ver", args[cur_arg]))
8600 methods->min = v;
8601 else if (!strcmp("ssl-max-ver", args[cur_arg]))
8602 methods->max = v;
8603 else {
8604 if (err)
8605 memprintf(err, "'%s' : option not implemented", args[cur_arg]);
8606 return ERR_ALERT | ERR_FATAL;
8607 }
Emeric Brun2cb7ae52012-10-05 14:14:21 +02008608 return 0;
Emeric Brun2cb7ae52012-10-05 14:14:21 +02008609}
Emeric Brun2cb7ae52012-10-05 14:14:21 +02008610
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02008611static int ssl_bind_parse_tls_method_minmax(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
8612{
Willy Tarreau9a1ab082019-05-09 13:26:41 +02008613#if (HA_OPENSSL_VERSION_NUMBER < 0x10101000L) && !defined(OPENSSL_IS_BORINGSSL)
Christopher Faulet767a84b2017-11-24 16:50:31 +01008614 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 +02008615#endif
8616 return parse_tls_method_minmax(args, cur_arg, &conf->ssl_methods, err);
8617}
8618
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008619static int bind_parse_tls_method_minmax(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8620{
Emmanuel Hocdet43664762017-08-09 18:26:20 +02008621 return parse_tls_method_minmax(args, cur_arg, &conf->ssl_conf.ssl_methods, err);
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008622}
8623
8624static int srv_parse_tls_method_minmax(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8625{
8626 return parse_tls_method_minmax(args, *cur_arg, &newsrv->ssl_ctx.methods, err);
8627}
8628
Emeric Brun2d0c4822012-10-02 13:45:20 +02008629/* parse the "no-tls-tickets" bind keyword */
Emmanuel Hocdet4608ed92017-01-20 13:06:27 +01008630static 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 +02008631{
Emeric Brun89675492012-10-05 13:48:26 +02008632 conf->ssl_options |= BC_SSL_O_NO_TLS_TICKETS;
Emeric Brun81c00f02012-09-21 14:31:21 +02008633 return 0;
8634}
Emeric Brun2d0c4822012-10-02 13:45:20 +02008635
Olivier Houchardc2aae742017-09-22 18:26:28 +02008636/* parse the "allow-0rtt" bind keyword */
8637static int ssl_bind_parse_allow_0rtt(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
8638{
8639 conf->early_data = 1;
8640 return 0;
8641}
8642
8643static int bind_parse_allow_0rtt(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8644{
Olivier Houchard9679ac92017-10-27 14:58:08 +02008645 conf->ssl_conf.early_data = 1;
Olivier Houchardc2aae742017-09-22 18:26:28 +02008646 return 0;
8647}
8648
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02008649/* parse the "npn" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008650static 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 +02008651{
Bernard Spil13c53f82018-02-15 13:34:58 +01008652#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02008653 char *p1, *p2;
8654
8655 if (!*args[cur_arg + 1]) {
8656 memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[cur_arg]);
8657 return ERR_ALERT | ERR_FATAL;
8658 }
8659
8660 free(conf->npn_str);
8661
Willy Tarreau3724da12016-02-12 17:11:12 +01008662 /* the NPN string is built as a suite of (<len> <name>)*,
8663 * so we reuse each comma to store the next <len> and need
8664 * one more for the end of the string.
8665 */
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02008666 conf->npn_len = strlen(args[cur_arg + 1]) + 1;
Willy Tarreau3724da12016-02-12 17:11:12 +01008667 conf->npn_str = calloc(1, conf->npn_len + 1);
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02008668 memcpy(conf->npn_str + 1, args[cur_arg + 1], conf->npn_len);
8669
8670 /* replace commas with the name length */
8671 p1 = conf->npn_str;
8672 p2 = p1 + 1;
8673 while (1) {
8674 p2 = memchr(p1 + 1, ',', conf->npn_str + conf->npn_len - (p1 + 1));
8675 if (!p2)
8676 p2 = p1 + 1 + strlen(p1 + 1);
8677
8678 if (p2 - (p1 + 1) > 255) {
8679 *p2 = '\0';
8680 memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
8681 return ERR_ALERT | ERR_FATAL;
8682 }
8683
8684 *p1 = p2 - (p1 + 1);
8685 p1 = p2;
8686
8687 if (!*p2)
8688 break;
8689
8690 *(p2++) = '\0';
8691 }
8692 return 0;
8693#else
8694 if (err)
8695 memprintf(err, "'%s' : library does not support TLS NPN extension", args[cur_arg]);
8696 return ERR_ALERT | ERR_FATAL;
8697#endif
8698}
8699
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008700static int bind_parse_npn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8701{
8702 return ssl_bind_parse_npn(args, cur_arg, px, &conf->ssl_conf, err);
8703}
8704
Willy Tarreauab861d32013-04-02 02:30:41 +02008705/* parse the "alpn" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008706static 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 +02008707{
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01008708#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02008709 char *p1, *p2;
8710
8711 if (!*args[cur_arg + 1]) {
8712 memprintf(err, "'%s' : missing the comma-delimited ALPN protocol suite", args[cur_arg]);
8713 return ERR_ALERT | ERR_FATAL;
8714 }
8715
8716 free(conf->alpn_str);
8717
Marcoen Hirschbergbef60912016-02-12 17:05:24 +01008718 /* the ALPN string is built as a suite of (<len> <name>)*,
8719 * so we reuse each comma to store the next <len> and need
8720 * one more for the end of the string.
8721 */
Willy Tarreauab861d32013-04-02 02:30:41 +02008722 conf->alpn_len = strlen(args[cur_arg + 1]) + 1;
Marcoen Hirschbergbef60912016-02-12 17:05:24 +01008723 conf->alpn_str = calloc(1, conf->alpn_len + 1);
Willy Tarreauab861d32013-04-02 02:30:41 +02008724 memcpy(conf->alpn_str + 1, args[cur_arg + 1], conf->alpn_len);
8725
8726 /* replace commas with the name length */
8727 p1 = conf->alpn_str;
8728 p2 = p1 + 1;
8729 while (1) {
8730 p2 = memchr(p1 + 1, ',', conf->alpn_str + conf->alpn_len - (p1 + 1));
8731 if (!p2)
8732 p2 = p1 + 1 + strlen(p1 + 1);
8733
8734 if (p2 - (p1 + 1) > 255) {
8735 *p2 = '\0';
8736 memprintf(err, "'%s' : ALPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
8737 return ERR_ALERT | ERR_FATAL;
8738 }
8739
8740 *p1 = p2 - (p1 + 1);
8741 p1 = p2;
8742
8743 if (!*p2)
8744 break;
8745
8746 *(p2++) = '\0';
8747 }
8748 return 0;
8749#else
8750 if (err)
8751 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[cur_arg]);
8752 return ERR_ALERT | ERR_FATAL;
8753#endif
8754}
8755
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008756static int bind_parse_alpn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8757{
8758 return ssl_bind_parse_alpn(args, cur_arg, px, &conf->ssl_conf, err);
8759}
8760
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008761/* parse the "ssl" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02008762static 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 +02008763{
Willy Tarreau71a8c7c2016-12-21 22:04:54 +01008764 conf->xprt = &ssl_sock;
Willy Tarreau4348fad2012-09-20 16:48:07 +02008765 conf->is_ssl = 1;
Emeric Brun76d88952012-10-05 15:47:31 +02008766
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008767 if (global_ssl.listen_default_ciphers && !conf->ssl_conf.ciphers)
8768 conf->ssl_conf.ciphers = strdup(global_ssl.listen_default_ciphers);
Emmanuel Hocdet839af572019-05-14 16:27:35 +02008769#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02008770 if (global_ssl.listen_default_ciphersuites && !conf->ssl_conf.ciphersuites)
8771 conf->ssl_conf.ciphersuites = strdup(global_ssl.listen_default_ciphersuites);
8772#endif
Emmanuel Hocdet4608ed92017-01-20 13:06:27 +01008773 conf->ssl_options |= global_ssl.listen_default_ssloptions;
Emmanuel Hocdet43664762017-08-09 18:26:20 +02008774 conf->ssl_conf.ssl_methods.flags |= global_ssl.listen_default_sslmethods.flags;
8775 if (!conf->ssl_conf.ssl_methods.min)
8776 conf->ssl_conf.ssl_methods.min = global_ssl.listen_default_sslmethods.min;
8777 if (!conf->ssl_conf.ssl_methods.max)
8778 conf->ssl_conf.ssl_methods.max = global_ssl.listen_default_sslmethods.max;
Emeric Brun76d88952012-10-05 15:47:31 +02008779
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008780 return 0;
8781}
8782
Lukas Tribus53ae85c2017-05-04 15:45:40 +00008783/* parse the "prefer-client-ciphers" bind keyword */
8784static int bind_parse_pcc(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8785{
8786 conf->ssl_options |= BC_SSL_O_PREF_CLIE_CIPH;
8787 return 0;
8788}
8789
Christopher Faulet31af49d2015-06-09 17:29:50 +02008790/* parse the "generate-certificates" bind keyword */
8791static int bind_parse_generate_certs(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8792{
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01008793#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Christopher Faulet31af49d2015-06-09 17:29:50 +02008794 conf->generate_certs = 1;
8795#else
8796 memprintf(err, "%sthis version of openssl cannot generate SSL certificates.\n",
8797 err && *err ? *err : "");
8798#endif
8799 return 0;
8800}
8801
Emmanuel Hocdet65623372013-01-24 17:17:15 +01008802/* parse the "strict-sni" bind keyword */
8803static int bind_parse_strict_sni(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8804{
8805 conf->strict_sni = 1;
8806 return 0;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008807}
8808
8809/* parse the "tls-ticket-keys" bind keyword */
8810static int bind_parse_tls_ticket_keys(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8811{
8812#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
Christopher Faulete566f3d2019-10-21 09:55:49 +02008813 FILE *f = NULL;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008814 int i = 0;
8815 char thisline[LINESIZE];
Christopher Faulete566f3d2019-10-21 09:55:49 +02008816 struct tls_keys_ref *keys_ref = NULL;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008817
8818 if (!*args[cur_arg + 1]) {
8819 if (err)
8820 memprintf(err, "'%s' : missing TLS ticket keys file path", args[cur_arg]);
Christopher Faulete566f3d2019-10-21 09:55:49 +02008821 goto fail;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008822 }
8823
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02008824 keys_ref = tlskeys_ref_lookup(args[cur_arg + 1]);
Willy Tarreau17b4aa12018-07-17 10:05:32 +02008825 if (keys_ref) {
8826 keys_ref->refcount++;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02008827 conf->keys_ref = keys_ref;
8828 return 0;
8829 }
8830
Christopher Faulete566f3d2019-10-21 09:55:49 +02008831 keys_ref = calloc(1, sizeof(*keys_ref));
Emeric Brun09852f72019-01-10 10:51:13 +01008832 if (!keys_ref) {
8833 if (err)
8834 memprintf(err, "'%s' : allocation error", args[cur_arg+1]);
Christopher Faulete566f3d2019-10-21 09:55:49 +02008835 goto fail;
Emeric Brun09852f72019-01-10 10:51:13 +01008836 }
8837
Emeric Brun9e754772019-01-10 17:51:55 +01008838 keys_ref->tlskeys = malloc(TLS_TICKETS_NO * sizeof(union tls_sess_key));
Emeric Brun09852f72019-01-10 10:51:13 +01008839 if (!keys_ref->tlskeys) {
Emeric Brun09852f72019-01-10 10:51:13 +01008840 if (err)
8841 memprintf(err, "'%s' : allocation error", args[cur_arg+1]);
Christopher Faulete566f3d2019-10-21 09:55:49 +02008842 goto fail;
Emeric Brun09852f72019-01-10 10:51:13 +01008843 }
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008844
8845 if ((f = fopen(args[cur_arg + 1], "r")) == NULL) {
8846 if (err)
8847 memprintf(err, "'%s' : unable to load ssl tickets keys file", args[cur_arg+1]);
Christopher Faulete566f3d2019-10-21 09:55:49 +02008848 goto fail;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008849 }
8850
Nenad Merdanovic146defa2015-05-09 08:46:00 +02008851 keys_ref->filename = strdup(args[cur_arg + 1]);
Emeric Brun09852f72019-01-10 10:51:13 +01008852 if (!keys_ref->filename) {
Emeric Brun09852f72019-01-10 10:51:13 +01008853 if (err)
8854 memprintf(err, "'%s' : allocation error", args[cur_arg+1]);
Christopher Faulete566f3d2019-10-21 09:55:49 +02008855 goto fail;
Emeric Brun09852f72019-01-10 10:51:13 +01008856 }
Nenad Merdanovic146defa2015-05-09 08:46:00 +02008857
Emeric Brun9e754772019-01-10 17:51:55 +01008858 keys_ref->key_size_bits = 0;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008859 while (fgets(thisline, sizeof(thisline), f) != NULL) {
8860 int len = strlen(thisline);
Emeric Brun9e754772019-01-10 17:51:55 +01008861 int dec_size;
8862
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008863 /* Strip newline characters from the end */
8864 if(thisline[len - 1] == '\n')
8865 thisline[--len] = 0;
8866
8867 if(thisline[len - 1] == '\r')
8868 thisline[--len] = 0;
8869
Emeric Brun9e754772019-01-10 17:51:55 +01008870 dec_size = base64dec(thisline, len, (char *) (keys_ref->tlskeys + i % TLS_TICKETS_NO), sizeof(union tls_sess_key));
8871 if (dec_size < 0) {
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008872 if (err)
8873 memprintf(err, "'%s' : unable to decode base64 key on line %d", args[cur_arg+1], i + 1);
Christopher Faulete566f3d2019-10-21 09:55:49 +02008874 goto fail;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008875 }
Emeric Brun9e754772019-01-10 17:51:55 +01008876 else if (!keys_ref->key_size_bits && (dec_size == sizeof(struct tls_sess_key_128))) {
8877 keys_ref->key_size_bits = 128;
8878 }
8879 else if (!keys_ref->key_size_bits && (dec_size == sizeof(struct tls_sess_key_256))) {
8880 keys_ref->key_size_bits = 256;
8881 }
8882 else if (((dec_size != sizeof(struct tls_sess_key_128)) && (dec_size != sizeof(struct tls_sess_key_256)))
8883 || ((dec_size == sizeof(struct tls_sess_key_128) && (keys_ref->key_size_bits != 128)))
8884 || ((dec_size == sizeof(struct tls_sess_key_256) && (keys_ref->key_size_bits != 256)))) {
Emeric Brun9e754772019-01-10 17:51:55 +01008885 if (err)
8886 memprintf(err, "'%s' : wrong sized key on line %d", args[cur_arg+1], i + 1);
Christopher Faulete566f3d2019-10-21 09:55:49 +02008887 goto fail;
Emeric Brun9e754772019-01-10 17:51:55 +01008888 }
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008889 i++;
8890 }
8891
8892 if (i < TLS_TICKETS_NO) {
8893 if (err)
8894 memprintf(err, "'%s' : please supply at least %d keys in the tls-tickets-file", args[cur_arg+1], TLS_TICKETS_NO);
Christopher Faulete566f3d2019-10-21 09:55:49 +02008895 goto fail;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008896 }
8897
8898 fclose(f);
8899
8900 /* Use penultimate key for encryption, handle when TLS_TICKETS_NO = 1 */
Nenad Merdanovic17891152016-03-25 22:16:57 +01008901 i -= 2;
8902 keys_ref->tls_ticket_enc_index = i < 0 ? 0 : i % TLS_TICKETS_NO;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02008903 keys_ref->unique_id = -1;
Willy Tarreau17b4aa12018-07-17 10:05:32 +02008904 keys_ref->refcount = 1;
Christopher Faulet16f45c82018-02-16 11:23:49 +01008905 HA_RWLOCK_INIT(&keys_ref->lock);
Nenad Merdanovic146defa2015-05-09 08:46:00 +02008906 conf->keys_ref = keys_ref;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008907
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02008908 LIST_ADD(&tlskeys_reference, &keys_ref->list);
8909
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008910 return 0;
Christopher Faulete566f3d2019-10-21 09:55:49 +02008911
8912 fail:
8913 if (f)
8914 fclose(f);
8915 if (keys_ref) {
8916 free(keys_ref->filename);
8917 free(keys_ref->tlskeys);
8918 free(keys_ref);
8919 }
8920 return ERR_ALERT | ERR_FATAL;
8921
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008922#else
8923 if (err)
8924 memprintf(err, "'%s' : TLS ticket callback extension not supported", args[cur_arg]);
8925 return ERR_ALERT | ERR_FATAL;
8926#endif /* SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB */
Emmanuel Hocdet65623372013-01-24 17:17:15 +01008927}
8928
Emeric Brund94b3fe2012-09-20 18:23:56 +02008929/* parse the "verify" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008930static 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 +02008931{
8932 if (!*args[cur_arg + 1]) {
8933 if (err)
8934 memprintf(err, "'%s' : missing verify method", args[cur_arg]);
8935 return ERR_ALERT | ERR_FATAL;
8936 }
8937
8938 if (strcmp(args[cur_arg + 1], "none") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01008939 conf->verify = SSL_SOCK_VERIFY_NONE;
Emeric Brund94b3fe2012-09-20 18:23:56 +02008940 else if (strcmp(args[cur_arg + 1], "optional") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01008941 conf->verify = SSL_SOCK_VERIFY_OPTIONAL;
Emeric Brund94b3fe2012-09-20 18:23:56 +02008942 else if (strcmp(args[cur_arg + 1], "required") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01008943 conf->verify = SSL_SOCK_VERIFY_REQUIRED;
Emeric Brund94b3fe2012-09-20 18:23:56 +02008944 else {
8945 if (err)
8946 memprintf(err, "'%s' : unknown verify method '%s', only 'none', 'optional', and 'required' are supported\n",
8947 args[cur_arg], args[cur_arg + 1]);
8948 return ERR_ALERT | ERR_FATAL;
8949 }
8950
8951 return 0;
8952}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008953static int bind_parse_verify(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8954{
8955 return ssl_bind_parse_verify(args, cur_arg, px, &conf->ssl_conf, err);
8956}
Emeric Brund94b3fe2012-09-20 18:23:56 +02008957
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02008958/* parse the "no-ca-names" bind keyword */
8959static int ssl_bind_parse_no_ca_names(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
8960{
8961 conf->no_ca_names = 1;
8962 return 0;
8963}
8964static int bind_parse_no_ca_names(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8965{
8966 return ssl_bind_parse_no_ca_names(args, cur_arg, px, &conf->ssl_conf, err);
8967}
8968
Willy Tarreau92faadf2012-10-10 23:04:25 +02008969/************** "server" keywords ****************/
8970
Olivier Houchardc7566002018-11-20 23:33:50 +01008971/* parse the "npn" bind keyword */
8972static int srv_parse_npn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8973{
8974#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
8975 char *p1, *p2;
8976
8977 if (!*args[*cur_arg + 1]) {
8978 memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[*cur_arg]);
8979 return ERR_ALERT | ERR_FATAL;
8980 }
8981
8982 free(newsrv->ssl_ctx.npn_str);
8983
8984 /* the NPN string is built as a suite of (<len> <name>)*,
8985 * so we reuse each comma to store the next <len> and need
8986 * one more for the end of the string.
8987 */
8988 newsrv->ssl_ctx.npn_len = strlen(args[*cur_arg + 1]) + 1;
8989 newsrv->ssl_ctx.npn_str = calloc(1, newsrv->ssl_ctx.npn_len + 1);
8990 memcpy(newsrv->ssl_ctx.npn_str + 1, args[*cur_arg + 1],
8991 newsrv->ssl_ctx.npn_len);
8992
8993 /* replace commas with the name length */
8994 p1 = newsrv->ssl_ctx.npn_str;
8995 p2 = p1 + 1;
8996 while (1) {
8997 p2 = memchr(p1 + 1, ',', newsrv->ssl_ctx.npn_str +
8998 newsrv->ssl_ctx.npn_len - (p1 + 1));
8999 if (!p2)
9000 p2 = p1 + 1 + strlen(p1 + 1);
9001
9002 if (p2 - (p1 + 1) > 255) {
9003 *p2 = '\0';
9004 memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[*cur_arg], p1 + 1);
9005 return ERR_ALERT | ERR_FATAL;
9006 }
9007
9008 *p1 = p2 - (p1 + 1);
9009 p1 = p2;
9010
9011 if (!*p2)
9012 break;
9013
9014 *(p2++) = '\0';
9015 }
9016 return 0;
9017#else
9018 if (err)
9019 memprintf(err, "'%s' : library does not support TLS NPN extension", args[*cur_arg]);
9020 return ERR_ALERT | ERR_FATAL;
9021#endif
9022}
9023
Olivier Houchard92150142018-12-21 19:47:01 +01009024/* parse the "alpn" or the "check-alpn" server keyword */
Olivier Houchardc7566002018-11-20 23:33:50 +01009025static int srv_parse_alpn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9026{
9027#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
9028 char *p1, *p2;
Olivier Houchard92150142018-12-21 19:47:01 +01009029 char **alpn_str;
9030 int *alpn_len;
Olivier Houchardc7566002018-11-20 23:33:50 +01009031
Olivier Houchard92150142018-12-21 19:47:01 +01009032 if (*args[*cur_arg] == 'c') {
9033 alpn_str = &newsrv->check.alpn_str;
9034 alpn_len = &newsrv->check.alpn_len;
9035 } else {
9036 alpn_str = &newsrv->ssl_ctx.alpn_str;
9037 alpn_len = &newsrv->ssl_ctx.alpn_len;
9038
9039 }
Olivier Houchardc7566002018-11-20 23:33:50 +01009040 if (!*args[*cur_arg + 1]) {
9041 memprintf(err, "'%s' : missing the comma-delimited ALPN protocol suite", args[*cur_arg]);
9042 return ERR_ALERT | ERR_FATAL;
9043 }
9044
Olivier Houchard92150142018-12-21 19:47:01 +01009045 free(*alpn_str);
Olivier Houchardc7566002018-11-20 23:33:50 +01009046
9047 /* the ALPN string is built as a suite of (<len> <name>)*,
9048 * so we reuse each comma to store the next <len> and need
9049 * one more for the end of the string.
9050 */
Olivier Houchard92150142018-12-21 19:47:01 +01009051 *alpn_len = strlen(args[*cur_arg + 1]) + 1;
9052 *alpn_str = calloc(1, *alpn_len + 1);
9053 memcpy(*alpn_str + 1, args[*cur_arg + 1], *alpn_len);
Olivier Houchardc7566002018-11-20 23:33:50 +01009054
9055 /* replace commas with the name length */
Olivier Houchard92150142018-12-21 19:47:01 +01009056 p1 = *alpn_str;
Olivier Houchardc7566002018-11-20 23:33:50 +01009057 p2 = p1 + 1;
9058 while (1) {
Olivier Houchard92150142018-12-21 19:47:01 +01009059 p2 = memchr(p1 + 1, ',', *alpn_str + *alpn_len - (p1 + 1));
Olivier Houchardc7566002018-11-20 23:33:50 +01009060 if (!p2)
9061 p2 = p1 + 1 + strlen(p1 + 1);
9062
9063 if (p2 - (p1 + 1) > 255) {
9064 *p2 = '\0';
9065 memprintf(err, "'%s' : ALPN protocol name too long : '%s'", args[*cur_arg], p1 + 1);
9066 return ERR_ALERT | ERR_FATAL;
9067 }
9068
9069 *p1 = p2 - (p1 + 1);
9070 p1 = p2;
9071
9072 if (!*p2)
9073 break;
9074
9075 *(p2++) = '\0';
9076 }
9077 return 0;
9078#else
9079 if (err)
9080 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[*cur_arg]);
9081 return ERR_ALERT | ERR_FATAL;
9082#endif
9083}
9084
Emeric Brunef42d922012-10-11 16:11:36 +02009085/* parse the "ca-file" server keyword */
9086static int srv_parse_ca_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9087{
9088 if (!*args[*cur_arg + 1]) {
9089 if (err)
9090 memprintf(err, "'%s' : missing CAfile path", args[*cur_arg]);
9091 return ERR_ALERT | ERR_FATAL;
9092 }
9093
Willy Tarreauef934602016-12-22 23:12:01 +01009094 if ((*args[*cur_arg + 1] != '/') && global_ssl.ca_base)
9095 memprintf(&newsrv->ssl_ctx.ca_file, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02009096 else
9097 memprintf(&newsrv->ssl_ctx.ca_file, "%s", args[*cur_arg + 1]);
9098
9099 return 0;
9100}
9101
Olivier Houchard9130a962017-10-17 17:33:43 +02009102/* parse the "check-sni" server keyword */
9103static int srv_parse_check_sni(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9104{
9105 if (!*args[*cur_arg + 1]) {
9106 if (err)
9107 memprintf(err, "'%s' : missing SNI", args[*cur_arg]);
9108 return ERR_ALERT | ERR_FATAL;
9109 }
9110
9111 newsrv->check.sni = strdup(args[*cur_arg + 1]);
9112 if (!newsrv->check.sni) {
9113 memprintf(err, "'%s' : failed to allocate memory", args[*cur_arg]);
9114 return ERR_ALERT | ERR_FATAL;
9115 }
9116 return 0;
9117
9118}
9119
Willy Tarreau92faadf2012-10-10 23:04:25 +02009120/* parse the "check-ssl" server keyword */
9121static int srv_parse_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9122{
9123 newsrv->check.use_ssl = 1;
Willy Tarreauef934602016-12-22 23:12:01 +01009124 if (global_ssl.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
9125 newsrv->ssl_ctx.ciphers = strdup(global_ssl.connect_default_ciphers);
Emmanuel Hocdet839af572019-05-14 16:27:35 +02009126#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009127 if (global_ssl.connect_default_ciphersuites && !newsrv->ssl_ctx.ciphersuites)
9128 newsrv->ssl_ctx.ciphersuites = strdup(global_ssl.connect_default_ciphersuites);
9129#endif
Willy Tarreauef934602016-12-22 23:12:01 +01009130 newsrv->ssl_ctx.options |= global_ssl.connect_default_ssloptions;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02009131 newsrv->ssl_ctx.methods.flags |= global_ssl.connect_default_sslmethods.flags;
9132 if (!newsrv->ssl_ctx.methods.min)
9133 newsrv->ssl_ctx.methods.min = global_ssl.connect_default_sslmethods.min;
9134 if (!newsrv->ssl_ctx.methods.max)
9135 newsrv->ssl_ctx.methods.max = global_ssl.connect_default_sslmethods.max;
9136
Willy Tarreau92faadf2012-10-10 23:04:25 +02009137 return 0;
9138}
9139
9140/* parse the "ciphers" server keyword */
9141static int srv_parse_ciphers(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9142{
9143 if (!*args[*cur_arg + 1]) {
9144 memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
9145 return ERR_ALERT | ERR_FATAL;
9146 }
9147
9148 free(newsrv->ssl_ctx.ciphers);
9149 newsrv->ssl_ctx.ciphers = strdup(args[*cur_arg + 1]);
9150 return 0;
9151}
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009152
Emmanuel Hocdet839af572019-05-14 16:27:35 +02009153#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009154/* parse the "ciphersuites" server keyword */
9155static int srv_parse_ciphersuites(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9156{
9157 if (!*args[*cur_arg + 1]) {
9158 memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
9159 return ERR_ALERT | ERR_FATAL;
9160 }
9161
9162 free(newsrv->ssl_ctx.ciphersuites);
9163 newsrv->ssl_ctx.ciphersuites = strdup(args[*cur_arg + 1]);
9164 return 0;
9165}
9166#endif
Willy Tarreau92faadf2012-10-10 23:04:25 +02009167
Emeric Brunef42d922012-10-11 16:11:36 +02009168/* parse the "crl-file" server keyword */
9169static int srv_parse_crl_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9170{
9171#ifndef X509_V_FLAG_CRL_CHECK
9172 if (err)
9173 memprintf(err, "'%s' : library does not support CRL verify", args[*cur_arg]);
9174 return ERR_ALERT | ERR_FATAL;
9175#else
9176 if (!*args[*cur_arg + 1]) {
9177 if (err)
9178 memprintf(err, "'%s' : missing CRLfile path", args[*cur_arg]);
9179 return ERR_ALERT | ERR_FATAL;
9180 }
9181
Willy Tarreauef934602016-12-22 23:12:01 +01009182 if ((*args[*cur_arg + 1] != '/') && global_ssl.ca_base)
9183 memprintf(&newsrv->ssl_ctx.crl_file, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02009184 else
9185 memprintf(&newsrv->ssl_ctx.crl_file, "%s", args[*cur_arg + 1]);
9186
9187 return 0;
9188#endif
9189}
9190
Emeric Bruna7aa3092012-10-26 12:58:00 +02009191/* parse the "crt" server keyword */
9192static int srv_parse_crt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9193{
9194 if (!*args[*cur_arg + 1]) {
9195 if (err)
9196 memprintf(err, "'%s' : missing certificate file path", args[*cur_arg]);
9197 return ERR_ALERT | ERR_FATAL;
9198 }
9199
Willy Tarreauef934602016-12-22 23:12:01 +01009200 if ((*args[*cur_arg + 1] != '/') && global_ssl.crt_base)
Christopher Fauletff3a41e2017-11-23 09:13:32 +01009201 memprintf(&newsrv->ssl_ctx.client_crt, "%s/%s", global_ssl.crt_base, args[*cur_arg + 1]);
Emeric Bruna7aa3092012-10-26 12:58:00 +02009202 else
9203 memprintf(&newsrv->ssl_ctx.client_crt, "%s", args[*cur_arg + 1]);
9204
9205 return 0;
9206}
Emeric Brunef42d922012-10-11 16:11:36 +02009207
Frédéric Lécaille340ae602017-03-13 10:38:04 +01009208/* parse the "no-check-ssl" server keyword */
9209static int srv_parse_no_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9210{
9211 newsrv->check.use_ssl = 0;
9212 free(newsrv->ssl_ctx.ciphers);
9213 newsrv->ssl_ctx.ciphers = NULL;
9214 newsrv->ssl_ctx.options &= ~global_ssl.connect_default_ssloptions;
9215 return 0;
9216}
9217
Frédéric Lécaillee892c4c2017-03-13 12:08:01 +01009218/* parse the "no-send-proxy-v2-ssl" server keyword */
9219static int srv_parse_no_send_proxy_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9220{
9221 newsrv->pp_opts &= ~SRV_PP_V2;
9222 newsrv->pp_opts &= ~SRV_PP_V2_SSL;
9223 return 0;
9224}
9225
9226/* parse the "no-send-proxy-v2-ssl-cn" server keyword */
9227static int srv_parse_no_send_proxy_cn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9228{
9229 newsrv->pp_opts &= ~SRV_PP_V2;
9230 newsrv->pp_opts &= ~SRV_PP_V2_SSL;
9231 newsrv->pp_opts &= ~SRV_PP_V2_SSL_CN;
9232 return 0;
9233}
9234
Frédéric Lécaillee381d762017-03-13 11:54:17 +01009235/* parse the "no-ssl" server keyword */
9236static int srv_parse_no_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9237{
9238 newsrv->use_ssl = 0;
9239 free(newsrv->ssl_ctx.ciphers);
9240 newsrv->ssl_ctx.ciphers = NULL;
9241 return 0;
9242}
9243
Olivier Houchard522eea72017-11-03 16:27:47 +01009244/* parse the "allow-0rtt" server keyword */
9245static int srv_parse_allow_0rtt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9246{
9247 newsrv->ssl_ctx.options |= SRV_SSL_O_EARLY_DATA;
9248 return 0;
9249}
9250
Willy Tarreau2a3fb1c2015-02-05 16:47:07 +01009251/* parse the "no-ssl-reuse" server keyword */
9252static int srv_parse_no_ssl_reuse(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9253{
9254 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_REUSE;
9255 return 0;
9256}
9257
Emeric Brunf9c5c472012-10-11 15:28:34 +02009258/* parse the "no-tls-tickets" server keyword */
9259static int srv_parse_no_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9260{
9261 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLS_TICKETS;
9262 return 0;
9263}
David Safb76832014-05-08 23:42:08 -04009264/* parse the "send-proxy-v2-ssl" server keyword */
9265static int srv_parse_send_proxy_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9266{
9267 newsrv->pp_opts |= SRV_PP_V2;
9268 newsrv->pp_opts |= SRV_PP_V2_SSL;
9269 return 0;
9270}
9271
9272/* parse the "send-proxy-v2-ssl-cn" server keyword */
9273static int srv_parse_send_proxy_cn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9274{
9275 newsrv->pp_opts |= SRV_PP_V2;
9276 newsrv->pp_opts |= SRV_PP_V2_SSL;
9277 newsrv->pp_opts |= SRV_PP_V2_SSL_CN;
9278 return 0;
9279}
Emeric Brunf9c5c472012-10-11 15:28:34 +02009280
Willy Tarreau732eac42015-07-09 11:40:25 +02009281/* parse the "sni" server keyword */
9282static int srv_parse_sni(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9283{
9284#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
9285 memprintf(err, "'%s' : the current SSL library doesn't support the SNI TLS extension", args[*cur_arg]);
9286 return ERR_ALERT | ERR_FATAL;
9287#else
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01009288 char *arg;
Willy Tarreau732eac42015-07-09 11:40:25 +02009289
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01009290 arg = args[*cur_arg + 1];
9291 if (!*arg) {
Willy Tarreau732eac42015-07-09 11:40:25 +02009292 memprintf(err, "'%s' : missing sni expression", args[*cur_arg]);
9293 return ERR_ALERT | ERR_FATAL;
9294 }
9295
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01009296 free(newsrv->sni_expr);
9297 newsrv->sni_expr = strdup(arg);
Willy Tarreau732eac42015-07-09 11:40:25 +02009298
Willy Tarreau732eac42015-07-09 11:40:25 +02009299 return 0;
9300#endif
9301}
9302
Willy Tarreau92faadf2012-10-10 23:04:25 +02009303/* parse the "ssl" server keyword */
9304static int srv_parse_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9305{
9306 newsrv->use_ssl = 1;
Willy Tarreauef934602016-12-22 23:12:01 +01009307 if (global_ssl.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
9308 newsrv->ssl_ctx.ciphers = strdup(global_ssl.connect_default_ciphers);
Emmanuel Hocdet839af572019-05-14 16:27:35 +02009309#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009310 if (global_ssl.connect_default_ciphersuites && !newsrv->ssl_ctx.ciphersuites)
9311 newsrv->ssl_ctx.ciphersuites = strdup(global_ssl.connect_default_ciphersuites);
9312#endif
Willy Tarreau92faadf2012-10-10 23:04:25 +02009313 return 0;
9314}
9315
Frédéric Lécaille2cfcdbe2017-03-13 11:32:20 +01009316/* parse the "ssl-reuse" server keyword */
9317static int srv_parse_ssl_reuse(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9318{
9319 newsrv->ssl_ctx.options &= ~SRV_SSL_O_NO_REUSE;
9320 return 0;
9321}
9322
Frédéric Lécaille2cfcdbe2017-03-13 11:32:20 +01009323/* parse the "tls-tickets" server keyword */
9324static int srv_parse_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9325{
9326 newsrv->ssl_ctx.options &= ~SRV_SSL_O_NO_TLS_TICKETS;
9327 return 0;
9328}
9329
Emeric Brunef42d922012-10-11 16:11:36 +02009330/* parse the "verify" server keyword */
9331static int srv_parse_verify(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9332{
9333 if (!*args[*cur_arg + 1]) {
9334 if (err)
9335 memprintf(err, "'%s' : missing verify method", args[*cur_arg]);
9336 return ERR_ALERT | ERR_FATAL;
9337 }
9338
9339 if (strcmp(args[*cur_arg + 1], "none") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01009340 newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_NONE;
Emeric Brunef42d922012-10-11 16:11:36 +02009341 else if (strcmp(args[*cur_arg + 1], "required") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01009342 newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_REQUIRED;
Emeric Brunef42d922012-10-11 16:11:36 +02009343 else {
9344 if (err)
9345 memprintf(err, "'%s' : unknown verify method '%s', only 'none' and 'required' are supported\n",
9346 args[*cur_arg], args[*cur_arg + 1]);
9347 return ERR_ALERT | ERR_FATAL;
9348 }
9349
Evan Broderbe554312013-06-27 00:05:25 -07009350 return 0;
9351}
9352
9353/* parse the "verifyhost" server keyword */
9354static int srv_parse_verifyhost(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9355{
9356 if (!*args[*cur_arg + 1]) {
9357 if (err)
9358 memprintf(err, "'%s' : missing hostname to verify against", args[*cur_arg]);
9359 return ERR_ALERT | ERR_FATAL;
9360 }
9361
Frédéric Lécaille273f3212017-03-13 15:52:01 +01009362 free(newsrv->ssl_ctx.verify_host);
Evan Broderbe554312013-06-27 00:05:25 -07009363 newsrv->ssl_ctx.verify_host = strdup(args[*cur_arg + 1]);
9364
Emeric Brunef42d922012-10-11 16:11:36 +02009365 return 0;
9366}
9367
Emeric Brun2c86cbf2014-10-30 15:56:50 +01009368/* parse the "ssl-default-bind-options" keyword in global section */
9369static int ssl_parse_default_bind_options(char **args, int section_type, struct proxy *curpx,
9370 struct proxy *defpx, const char *file, int line,
9371 char **err) {
9372 int i = 1;
9373
9374 if (*(args[i]) == 0) {
9375 memprintf(err, "global statement '%s' expects an option as an argument.", args[0]);
9376 return -1;
9377 }
9378 while (*(args[i])) {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02009379 if (!strcmp(args[i], "no-tls-tickets"))
Willy Tarreauef934602016-12-22 23:12:01 +01009380 global_ssl.listen_default_ssloptions |= BC_SSL_O_NO_TLS_TICKETS;
Lukas Tribus53ae85c2017-05-04 15:45:40 +00009381 else if (!strcmp(args[i], "prefer-client-ciphers"))
9382 global_ssl.listen_default_ssloptions |= BC_SSL_O_PREF_CLIE_CIPH;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02009383 else if (!strcmp(args[i], "ssl-min-ver") || !strcmp(args[i], "ssl-max-ver")) {
9384 if (!parse_tls_method_minmax(args, i, &global_ssl.listen_default_sslmethods, err))
9385 i++;
9386 else {
9387 memprintf(err, "%s on global statement '%s'.", *err, args[0]);
9388 return -1;
9389 }
9390 }
9391 else if (parse_tls_method_options(args[i], &global_ssl.listen_default_sslmethods, err)) {
Emeric Brun2c86cbf2014-10-30 15:56:50 +01009392 memprintf(err, "unknown option '%s' on global statement '%s'.", args[i], args[0]);
9393 return -1;
9394 }
9395 i++;
9396 }
9397 return 0;
9398}
9399
9400/* parse the "ssl-default-server-options" keyword in global section */
9401static int ssl_parse_default_server_options(char **args, int section_type, struct proxy *curpx,
9402 struct proxy *defpx, const char *file, int line,
9403 char **err) {
9404 int i = 1;
9405
9406 if (*(args[i]) == 0) {
9407 memprintf(err, "global statement '%s' expects an option as an argument.", args[0]);
9408 return -1;
9409 }
9410 while (*(args[i])) {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02009411 if (!strcmp(args[i], "no-tls-tickets"))
Willy Tarreauef934602016-12-22 23:12:01 +01009412 global_ssl.connect_default_ssloptions |= SRV_SSL_O_NO_TLS_TICKETS;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02009413 else if (!strcmp(args[i], "ssl-min-ver") || !strcmp(args[i], "ssl-max-ver")) {
9414 if (!parse_tls_method_minmax(args, i, &global_ssl.connect_default_sslmethods, err))
9415 i++;
9416 else {
9417 memprintf(err, "%s on global statement '%s'.", *err, args[0]);
9418 return -1;
9419 }
9420 }
9421 else if (parse_tls_method_options(args[i], &global_ssl.connect_default_sslmethods, err)) {
Emeric Brun2c86cbf2014-10-30 15:56:50 +01009422 memprintf(err, "unknown option '%s' on global statement '%s'.", args[i], args[0]);
9423 return -1;
9424 }
9425 i++;
9426 }
9427 return 0;
9428}
9429
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01009430/* parse the "ca-base" / "crt-base" keywords in global section.
9431 * Returns <0 on alert, >0 on warning, 0 on success.
9432 */
9433static int ssl_parse_global_ca_crt_base(char **args, int section_type, struct proxy *curpx,
9434 struct proxy *defpx, const char *file, int line,
9435 char **err)
9436{
9437 char **target;
9438
Willy Tarreauef934602016-12-22 23:12:01 +01009439 target = (args[0][1] == 'a') ? &global_ssl.ca_base : &global_ssl.crt_base;
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01009440
9441 if (too_many_args(1, args, err, NULL))
9442 return -1;
9443
9444 if (*target) {
9445 memprintf(err, "'%s' already specified.", args[0]);
9446 return -1;
9447 }
9448
9449 if (*(args[1]) == 0) {
9450 memprintf(err, "global statement '%s' expects a directory path as an argument.", args[0]);
9451 return -1;
9452 }
9453 *target = strdup(args[1]);
9454 return 0;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00009455}
9456
9457/* parse the "ssl-mode-async" keyword in global section.
9458 * Returns <0 on alert, >0 on warning, 0 on success.
9459 */
9460static int ssl_parse_global_ssl_async(char **args, int section_type, struct proxy *curpx,
9461 struct proxy *defpx, const char *file, int line,
9462 char **err)
9463{
Willy Tarreau5db847a2019-05-09 14:13:35 +02009464#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00009465 global_ssl.async = 1;
Emeric Brunece0c332017-12-06 13:51:49 +01009466 global.ssl_used_async_engines = nb_engines;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00009467 return 0;
9468#else
9469 memprintf(err, "'%s': openssl library does not support async mode", args[0]);
9470 return -1;
9471#endif
9472}
9473
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02009474#ifndef OPENSSL_NO_ENGINE
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00009475static int ssl_check_async_engine_count(void) {
9476 int err_code = 0;
9477
Emeric Brun3854e012017-05-17 20:42:48 +02009478 if (global_ssl.async && (openssl_engines_initialized > 32)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01009479 ha_alert("ssl-mode-async only supports a maximum of 32 engines.\n");
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00009480 err_code = ERR_ABORT;
9481 }
9482 return err_code;
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01009483}
9484
Grant Zhang872f9c22017-01-21 01:10:18 +00009485/* parse the "ssl-engine" keyword in global section.
9486 * Returns <0 on alert, >0 on warning, 0 on success.
9487 */
9488static int ssl_parse_global_ssl_engine(char **args, int section_type, struct proxy *curpx,
9489 struct proxy *defpx, const char *file, int line,
9490 char **err)
9491{
9492 char *algo;
9493 int ret = -1;
9494
9495 if (*(args[1]) == 0) {
9496 memprintf(err, "global statement '%s' expects a valid engine name as an argument.", args[0]);
9497 return ret;
9498 }
9499
9500 if (*(args[2]) == 0) {
9501 /* if no list of algorithms is given, it defaults to ALL */
9502 algo = strdup("ALL");
9503 goto add_engine;
9504 }
9505
9506 /* otherwise the expected format is ssl-engine <engine_name> algo <list of algo> */
9507 if (strcmp(args[2], "algo") != 0) {
9508 memprintf(err, "global statement '%s' expects to have algo keyword.", args[0]);
9509 return ret;
9510 }
9511
9512 if (*(args[3]) == 0) {
9513 memprintf(err, "global statement '%s' expects algorithm names as an argument.", args[0]);
9514 return ret;
9515 }
9516 algo = strdup(args[3]);
9517
9518add_engine:
9519 if (ssl_init_single_engine(args[1], algo)==0) {
9520 openssl_engines_initialized++;
9521 ret = 0;
9522 }
9523 free(algo);
9524 return ret;
9525}
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02009526#endif
Grant Zhang872f9c22017-01-21 01:10:18 +00009527
Willy Tarreauf22e9682016-12-21 23:23:19 +01009528/* parse the "ssl-default-bind-ciphers" / "ssl-default-server-ciphers" keywords
9529 * in global section. Returns <0 on alert, >0 on warning, 0 on success.
9530 */
9531static int ssl_parse_global_ciphers(char **args, int section_type, struct proxy *curpx,
9532 struct proxy *defpx, const char *file, int line,
9533 char **err)
9534{
9535 char **target;
9536
Willy Tarreauef934602016-12-22 23:12:01 +01009537 target = (args[0][12] == 'b') ? &global_ssl.listen_default_ciphers : &global_ssl.connect_default_ciphers;
Willy Tarreauf22e9682016-12-21 23:23:19 +01009538
9539 if (too_many_args(1, args, err, NULL))
9540 return -1;
9541
9542 if (*(args[1]) == 0) {
9543 memprintf(err, "global statement '%s' expects a cipher suite as an argument.", args[0]);
9544 return -1;
9545 }
9546
9547 free(*target);
9548 *target = strdup(args[1]);
9549 return 0;
9550}
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009551
Emmanuel Hocdet839af572019-05-14 16:27:35 +02009552#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009553/* parse the "ssl-default-bind-ciphersuites" / "ssl-default-server-ciphersuites" keywords
9554 * in global section. Returns <0 on alert, >0 on warning, 0 on success.
9555 */
9556static int ssl_parse_global_ciphersuites(char **args, int section_type, struct proxy *curpx,
9557 struct proxy *defpx, const char *file, int line,
9558 char **err)
9559{
9560 char **target;
9561
9562 target = (args[0][12] == 'b') ? &global_ssl.listen_default_ciphersuites : &global_ssl.connect_default_ciphersuites;
9563
9564 if (too_many_args(1, args, err, NULL))
9565 return -1;
9566
9567 if (*(args[1]) == 0) {
9568 memprintf(err, "global statement '%s' expects a cipher suite as an argument.", args[0]);
9569 return -1;
9570 }
9571
9572 free(*target);
9573 *target = strdup(args[1]);
9574 return 0;
9575}
9576#endif
Willy Tarreauf22e9682016-12-21 23:23:19 +01009577
Willy Tarreau9ceda382016-12-21 23:13:03 +01009578/* parse various global tune.ssl settings consisting in positive integers.
9579 * Returns <0 on alert, >0 on warning, 0 on success.
9580 */
9581static int ssl_parse_global_int(char **args, int section_type, struct proxy *curpx,
9582 struct proxy *defpx, const char *file, int line,
9583 char **err)
9584{
9585 int *target;
9586
9587 if (strcmp(args[0], "tune.ssl.cachesize") == 0)
9588 target = &global.tune.sslcachesize;
9589 else if (strcmp(args[0], "tune.ssl.maxrecord") == 0)
Willy Tarreauef934602016-12-22 23:12:01 +01009590 target = (int *)&global_ssl.max_record;
Willy Tarreau9ceda382016-12-21 23:13:03 +01009591 else if (strcmp(args[0], "tune.ssl.ssl-ctx-cache-size") == 0)
Willy Tarreauef934602016-12-22 23:12:01 +01009592 target = &global_ssl.ctx_cache;
Willy Tarreau0bea58d2016-12-21 23:17:25 +01009593 else if (strcmp(args[0], "maxsslconn") == 0)
9594 target = &global.maxsslconn;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01009595 else if (strcmp(args[0], "tune.ssl.capture-cipherlist-size") == 0)
9596 target = &global_ssl.capture_cipherlist;
Willy Tarreau9ceda382016-12-21 23:13:03 +01009597 else {
9598 memprintf(err, "'%s' keyword not unhandled (please report this bug).", args[0]);
9599 return -1;
9600 }
9601
9602 if (too_many_args(1, args, err, NULL))
9603 return -1;
9604
9605 if (*(args[1]) == 0) {
9606 memprintf(err, "'%s' expects an integer argument.", args[0]);
9607 return -1;
9608 }
9609
9610 *target = atoi(args[1]);
9611 if (*target < 0) {
9612 memprintf(err, "'%s' expects a positive numeric value.", args[0]);
9613 return -1;
9614 }
9615 return 0;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01009616}
9617
9618static int ssl_parse_global_capture_cipherlist(char **args, int section_type, struct proxy *curpx,
9619 struct proxy *defpx, const char *file, int line,
9620 char **err)
9621{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01009622 int ret;
9623
9624 ret = ssl_parse_global_int(args, section_type, curpx, defpx, file, line, err);
9625 if (ret != 0)
9626 return ret;
9627
Willy Tarreaubafbe012017-11-24 17:34:44 +01009628 if (pool_head_ssl_capture) {
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01009629 memprintf(err, "'%s' is already configured.", args[0]);
9630 return -1;
9631 }
9632
Willy Tarreaubafbe012017-11-24 17:34:44 +01009633 pool_head_ssl_capture = create_pool("ssl-capture", sizeof(struct ssl_capture) + global_ssl.capture_cipherlist, MEM_F_SHARED);
9634 if (!pool_head_ssl_capture) {
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01009635 memprintf(err, "Out of memory error.");
9636 return -1;
9637 }
9638 return 0;
Willy Tarreau9ceda382016-12-21 23:13:03 +01009639}
9640
9641/* parse "ssl.force-private-cache".
9642 * Returns <0 on alert, >0 on warning, 0 on success.
9643 */
9644static int ssl_parse_global_private_cache(char **args, int section_type, struct proxy *curpx,
9645 struct proxy *defpx, const char *file, int line,
9646 char **err)
9647{
9648 if (too_many_args(0, args, err, NULL))
9649 return -1;
9650
Willy Tarreauef934602016-12-22 23:12:01 +01009651 global_ssl.private_cache = 1;
Willy Tarreau9ceda382016-12-21 23:13:03 +01009652 return 0;
9653}
9654
9655/* parse "ssl.lifetime".
9656 * Returns <0 on alert, >0 on warning, 0 on success.
9657 */
9658static int ssl_parse_global_lifetime(char **args, int section_type, struct proxy *curpx,
9659 struct proxy *defpx, const char *file, int line,
9660 char **err)
9661{
9662 const char *res;
9663
9664 if (too_many_args(1, args, err, NULL))
9665 return -1;
9666
9667 if (*(args[1]) == 0) {
9668 memprintf(err, "'%s' expects ssl sessions <lifetime> in seconds as argument.", args[0]);
9669 return -1;
9670 }
9671
Willy Tarreauef934602016-12-22 23:12:01 +01009672 res = parse_time_err(args[1], &global_ssl.life_time, TIME_UNIT_S);
Willy Tarreau9faebe32019-06-07 19:00:37 +02009673 if (res == PARSE_TIME_OVER) {
9674 memprintf(err, "timer overflow in argument '%s' to <%s> (maximum value is 2147483647 s or ~68 years).",
9675 args[1], args[0]);
9676 return -1;
9677 }
9678 else if (res == PARSE_TIME_UNDER) {
9679 memprintf(err, "timer underflow in argument '%s' to <%s> (minimum non-null value is 1 s).",
9680 args[1], args[0]);
9681 return -1;
9682 }
9683 else if (res) {
Willy Tarreau9ceda382016-12-21 23:13:03 +01009684 memprintf(err, "unexpected character '%c' in argument to <%s>.", *res, args[0]);
9685 return -1;
9686 }
9687 return 0;
9688}
9689
9690#ifndef OPENSSL_NO_DH
Willy Tarreau14e36a12016-12-21 23:28:13 +01009691/* parse "ssl-dh-param-file".
9692 * Returns <0 on alert, >0 on warning, 0 on success.
9693 */
9694static int ssl_parse_global_dh_param_file(char **args, int section_type, struct proxy *curpx,
9695 struct proxy *defpx, const char *file, int line,
9696 char **err)
9697{
9698 if (too_many_args(1, args, err, NULL))
9699 return -1;
9700
9701 if (*(args[1]) == 0) {
9702 memprintf(err, "'%s' expects a file path as an argument.", args[0]);
9703 return -1;
9704 }
9705
9706 if (ssl_sock_load_global_dh_param_from_file(args[1])) {
9707 memprintf(err, "'%s': unable to load DH parameters from file <%s>.", args[0], args[1]);
9708 return -1;
9709 }
9710 return 0;
9711}
9712
Willy Tarreau9ceda382016-12-21 23:13:03 +01009713/* parse "ssl.default-dh-param".
9714 * Returns <0 on alert, >0 on warning, 0 on success.
9715 */
9716static int ssl_parse_global_default_dh(char **args, int section_type, struct proxy *curpx,
9717 struct proxy *defpx, const char *file, int line,
9718 char **err)
9719{
9720 if (too_many_args(1, args, err, NULL))
9721 return -1;
9722
9723 if (*(args[1]) == 0) {
9724 memprintf(err, "'%s' expects an integer argument.", args[0]);
9725 return -1;
9726 }
9727
Willy Tarreauef934602016-12-22 23:12:01 +01009728 global_ssl.default_dh_param = atoi(args[1]);
9729 if (global_ssl.default_dh_param < 1024) {
Willy Tarreau9ceda382016-12-21 23:13:03 +01009730 memprintf(err, "'%s' expects a value >= 1024.", args[0]);
9731 return -1;
9732 }
9733 return 0;
9734}
9735#endif
9736
9737
William Lallemand32af2032016-10-29 18:09:35 +02009738/* This function is used with TLS ticket keys management. It permits to browse
9739 * each reference. The variable <getnext> must contain the current node,
9740 * <end> point to the root node.
9741 */
9742#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
9743static inline
9744struct tls_keys_ref *tlskeys_list_get_next(struct tls_keys_ref *getnext, struct list *end)
9745{
9746 struct tls_keys_ref *ref = getnext;
9747
9748 while (1) {
9749
9750 /* Get next list entry. */
9751 ref = LIST_NEXT(&ref->list, struct tls_keys_ref *, list);
9752
9753 /* If the entry is the last of the list, return NULL. */
9754 if (&ref->list == end)
9755 return NULL;
9756
9757 return ref;
9758 }
9759}
9760
9761static inline
9762struct tls_keys_ref *tlskeys_ref_lookup_ref(const char *reference)
9763{
9764 int id;
9765 char *error;
9766
9767 /* If the reference starts by a '#', this is numeric id. */
9768 if (reference[0] == '#') {
9769 /* Try to convert the numeric id. If the conversion fails, the lookup fails. */
9770 id = strtol(reference + 1, &error, 10);
9771 if (*error != '\0')
9772 return NULL;
9773
9774 /* Perform the unique id lookup. */
9775 return tlskeys_ref_lookupid(id);
9776 }
9777
9778 /* Perform the string lookup. */
9779 return tlskeys_ref_lookup(reference);
9780}
9781#endif
9782
9783
9784#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
9785
9786static int cli_io_handler_tlskeys_files(struct appctx *appctx);
9787
9788static inline int cli_io_handler_tlskeys_entries(struct appctx *appctx) {
9789 return cli_io_handler_tlskeys_files(appctx);
9790}
9791
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009792/* dumps all tls keys. Relies on cli.i0 (non-null = only list file names), cli.i1
9793 * (next index to be dumped), and cli.p0 (next key reference).
9794 */
William Lallemand32af2032016-10-29 18:09:35 +02009795static int cli_io_handler_tlskeys_files(struct appctx *appctx) {
9796
9797 struct stream_interface *si = appctx->owner;
9798
9799 switch (appctx->st2) {
9800 case STAT_ST_INIT:
9801 /* Display the column headers. If the message cannot be sent,
Joseph Herlant017b3da2018-11-15 09:07:59 -08009802 * quit the function with returning 0. The function is called
William Lallemand32af2032016-10-29 18:09:35 +02009803 * later and restart at the state "STAT_ST_INIT".
9804 */
9805 chunk_reset(&trash);
9806
9807 if (appctx->io_handler == cli_io_handler_tlskeys_entries)
9808 chunk_appendf(&trash, "# id secret\n");
9809 else
9810 chunk_appendf(&trash, "# id (file)\n");
9811
Willy Tarreau06d80a92017-10-19 14:32:15 +02009812 if (ci_putchk(si_ic(si), &trash) == -1) {
Willy Tarreaudb398432018-11-15 11:08:52 +01009813 si_rx_room_blk(si);
William Lallemand32af2032016-10-29 18:09:35 +02009814 return 0;
9815 }
9816
William Lallemand32af2032016-10-29 18:09:35 +02009817 /* Now, we start the browsing of the references lists.
9818 * Note that the following call to LIST_ELEM return bad pointer. The only
9819 * available field of this pointer is <list>. It is used with the function
9820 * tlskeys_list_get_next() for retruning the first available entry
9821 */
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009822 if (appctx->ctx.cli.p0 == NULL) {
9823 appctx->ctx.cli.p0 = LIST_ELEM(&tlskeys_reference, struct tls_keys_ref *, list);
9824 appctx->ctx.cli.p0 = tlskeys_list_get_next(appctx->ctx.cli.p0, &tlskeys_reference);
William Lallemand32af2032016-10-29 18:09:35 +02009825 }
9826
9827 appctx->st2 = STAT_ST_LIST;
9828 /* fall through */
9829
9830 case STAT_ST_LIST:
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009831 while (appctx->ctx.cli.p0) {
9832 struct tls_keys_ref *ref = appctx->ctx.cli.p0;
William Lallemand32af2032016-10-29 18:09:35 +02009833
9834 chunk_reset(&trash);
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009835 if (appctx->io_handler == cli_io_handler_tlskeys_entries && appctx->ctx.cli.i1 == 0)
William Lallemand32af2032016-10-29 18:09:35 +02009836 chunk_appendf(&trash, "# ");
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009837
9838 if (appctx->ctx.cli.i1 == 0)
9839 chunk_appendf(&trash, "%d (%s)\n", ref->unique_id, ref->filename);
9840
William Lallemand32af2032016-10-29 18:09:35 +02009841 if (appctx->io_handler == cli_io_handler_tlskeys_entries) {
Christopher Faulet16f45c82018-02-16 11:23:49 +01009842 int head;
9843
9844 HA_RWLOCK_RDLOCK(TLSKEYS_REF_LOCK, &ref->lock);
9845 head = ref->tls_ticket_enc_index;
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009846 while (appctx->ctx.cli.i1 < TLS_TICKETS_NO) {
Willy Tarreau83061a82018-07-13 11:56:34 +02009847 struct buffer *t2 = get_trash_chunk();
William Lallemand32af2032016-10-29 18:09:35 +02009848
9849 chunk_reset(t2);
9850 /* should never fail here because we dump only a key in the t2 buffer */
Emeric Brun9e754772019-01-10 17:51:55 +01009851 if (ref->key_size_bits == 128) {
9852 t2->data = a2base64((char *)(ref->tlskeys + (head + 2 + appctx->ctx.cli.i1) % TLS_TICKETS_NO),
9853 sizeof(struct tls_sess_key_128),
9854 t2->area, t2->size);
9855 chunk_appendf(&trash, "%d.%d %s\n", ref->unique_id, appctx->ctx.cli.i1,
9856 t2->area);
9857 }
9858 else if (ref->key_size_bits == 256) {
9859 t2->data = a2base64((char *)(ref->tlskeys + (head + 2 + appctx->ctx.cli.i1) % TLS_TICKETS_NO),
9860 sizeof(struct tls_sess_key_256),
9861 t2->area, t2->size);
9862 chunk_appendf(&trash, "%d.%d %s\n", ref->unique_id, appctx->ctx.cli.i1,
9863 t2->area);
9864 }
9865 else {
9866 /* This case should never happen */
9867 chunk_appendf(&trash, "%d.%d <unknown>\n", ref->unique_id, appctx->ctx.cli.i1);
9868 }
William Lallemand32af2032016-10-29 18:09:35 +02009869
Willy Tarreau06d80a92017-10-19 14:32:15 +02009870 if (ci_putchk(si_ic(si), &trash) == -1) {
William Lallemand32af2032016-10-29 18:09:35 +02009871 /* let's try again later from this stream. We add ourselves into
9872 * this stream's users so that it can remove us upon termination.
9873 */
Christopher Faulet16f45c82018-02-16 11:23:49 +01009874 HA_RWLOCK_RDUNLOCK(TLSKEYS_REF_LOCK, &ref->lock);
Willy Tarreaudb398432018-11-15 11:08:52 +01009875 si_rx_room_blk(si);
William Lallemand32af2032016-10-29 18:09:35 +02009876 return 0;
9877 }
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009878 appctx->ctx.cli.i1++;
William Lallemand32af2032016-10-29 18:09:35 +02009879 }
Christopher Faulet16f45c82018-02-16 11:23:49 +01009880 HA_RWLOCK_RDUNLOCK(TLSKEYS_REF_LOCK, &ref->lock);
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009881 appctx->ctx.cli.i1 = 0;
William Lallemand32af2032016-10-29 18:09:35 +02009882 }
Willy Tarreau06d80a92017-10-19 14:32:15 +02009883 if (ci_putchk(si_ic(si), &trash) == -1) {
William Lallemand32af2032016-10-29 18:09:35 +02009884 /* let's try again later from this stream. We add ourselves into
9885 * this stream's users so that it can remove us upon termination.
9886 */
Willy Tarreaudb398432018-11-15 11:08:52 +01009887 si_rx_room_blk(si);
William Lallemand32af2032016-10-29 18:09:35 +02009888 return 0;
9889 }
9890
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009891 if (appctx->ctx.cli.i0 == 0) /* don't display everything if not necessary */
William Lallemand32af2032016-10-29 18:09:35 +02009892 break;
9893
9894 /* get next list entry and check the end of the list */
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009895 appctx->ctx.cli.p0 = tlskeys_list_get_next(appctx->ctx.cli.p0, &tlskeys_reference);
William Lallemand32af2032016-10-29 18:09:35 +02009896 }
9897
9898 appctx->st2 = STAT_ST_FIN;
9899 /* fall through */
9900
9901 default:
9902 appctx->st2 = STAT_ST_FIN;
9903 return 1;
9904 }
9905 return 0;
9906}
9907
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009908/* sets cli.i0 to non-zero if only file lists should be dumped */
Aurélien Nephtaliabbf6072018-04-18 13:26:46 +02009909static int cli_parse_show_tlskeys(char **args, char *payload, struct appctx *appctx, void *private)
William Lallemand32af2032016-10-29 18:09:35 +02009910{
William Lallemand32af2032016-10-29 18:09:35 +02009911 /* no parameter, shows only file list */
9912 if (!*args[2]) {
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009913 appctx->ctx.cli.i0 = 1;
William Lallemand32af2032016-10-29 18:09:35 +02009914 appctx->io_handler = cli_io_handler_tlskeys_files;
Willy Tarreau3067bfa2016-12-05 14:50:15 +01009915 return 0;
William Lallemand32af2032016-10-29 18:09:35 +02009916 }
9917
9918 if (args[2][0] == '*') {
9919 /* list every TLS ticket keys */
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009920 appctx->ctx.cli.i0 = 1;
William Lallemand32af2032016-10-29 18:09:35 +02009921 } else {
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009922 appctx->ctx.cli.p0 = tlskeys_ref_lookup_ref(args[2]);
Willy Tarreau9d008692019-08-09 11:21:01 +02009923 if (!appctx->ctx.cli.p0)
9924 return cli_err(appctx, "'show tls-keys' unable to locate referenced filename\n");
William Lallemand32af2032016-10-29 18:09:35 +02009925 }
William Lallemand32af2032016-10-29 18:09:35 +02009926 appctx->io_handler = cli_io_handler_tlskeys_entries;
Willy Tarreau3067bfa2016-12-05 14:50:15 +01009927 return 0;
William Lallemand32af2032016-10-29 18:09:35 +02009928}
9929
Aurélien Nephtaliabbf6072018-04-18 13:26:46 +02009930static int cli_parse_set_tlskeys(char **args, char *payload, struct appctx *appctx, void *private)
William Lallemand32af2032016-10-29 18:09:35 +02009931{
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009932 struct tls_keys_ref *ref;
Willy Tarreau1c913e42018-08-22 05:26:57 +02009933 int ret;
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009934
William Lallemand32af2032016-10-29 18:09:35 +02009935 /* Expect two parameters: the filename and the new new TLS key in encoding */
Willy Tarreau9d008692019-08-09 11:21:01 +02009936 if (!*args[3] || !*args[4])
9937 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 +02009938
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009939 ref = tlskeys_ref_lookup_ref(args[3]);
Willy Tarreau9d008692019-08-09 11:21:01 +02009940 if (!ref)
9941 return cli_err(appctx, "'set ssl tls-key' unable to locate referenced filename\n");
William Lallemand32af2032016-10-29 18:09:35 +02009942
Willy Tarreau1c913e42018-08-22 05:26:57 +02009943 ret = base64dec(args[4], strlen(args[4]), trash.area, trash.size);
Willy Tarreau9d008692019-08-09 11:21:01 +02009944 if (ret < 0)
9945 return cli_err(appctx, "'set ssl tls-key' received invalid base64 encoded TLS key.\n");
Emeric Brun9e754772019-01-10 17:51:55 +01009946
Willy Tarreau1c913e42018-08-22 05:26:57 +02009947 trash.data = ret;
Willy Tarreau9d008692019-08-09 11:21:01 +02009948 if (ssl_sock_update_tlskey_ref(ref, &trash) < 0)
9949 return cli_err(appctx, "'set ssl tls-key' received a key of wrong size.\n");
William Lallemand32af2032016-10-29 18:09:35 +02009950
Willy Tarreau9d008692019-08-09 11:21:01 +02009951 return cli_msg(appctx, LOG_INFO, "TLS ticket key updated!\n");
William Lallemand32af2032016-10-29 18:09:35 +02009952}
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01009953#endif
William Lallemand32af2032016-10-29 18:09:35 +02009954
William Lallemand44b35322019-10-17 16:28:40 +02009955
9956/* Type of SSL payloads that can be updated over the CLI */
9957
9958enum {
9959 CERT_TYPE_PEM = 0,
Emmanuel Hocdetf6ac4fa2019-10-30 17:41:27 +01009960#if ((defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP) || defined OPENSSL_IS_BORINGSSL)
William Lallemand44b35322019-10-17 16:28:40 +02009961 CERT_TYPE_OCSP,
Emmanuel Hocdetf6ac4fa2019-10-30 17:41:27 +01009962#endif
William Lallemand44b35322019-10-17 16:28:40 +02009963 CERT_TYPE_ISSUER,
Emmanuel Hocdetf6ac4fa2019-10-30 17:41:27 +01009964#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
William Lallemand44b35322019-10-17 16:28:40 +02009965 CERT_TYPE_SCTL,
Emmanuel Hocdetf6ac4fa2019-10-30 17:41:27 +01009966#endif
William Lallemand44b35322019-10-17 16:28:40 +02009967 CERT_TYPE_MAX,
9968};
9969
9970struct {
9971 const char *ext;
9972 int type;
9973 int (*load)(const char *path, char *payload, struct cert_key_and_chain *ckch, char **err);
9974 /* add a parsing callback */
William Lallemandf29cdef2019-10-23 15:00:52 +02009975} cert_exts[CERT_TYPE_MAX+1] = {
William Lallemand44b35322019-10-17 16:28:40 +02009976 [CERT_TYPE_PEM] = { "", CERT_TYPE_PEM, &ssl_sock_load_pem_into_ckch }, /* default mode, no extensions */
William Lallemand541a5342019-10-23 14:11:54 +02009977#if ((defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP) || defined OPENSSL_IS_BORINGSSL)
William Lallemand44b35322019-10-17 16:28:40 +02009978 [CERT_TYPE_OCSP] = { "ocsp", CERT_TYPE_OCSP, &ssl_sock_load_ocsp_response_from_file },
William Lallemand541a5342019-10-23 14:11:54 +02009979#endif
9980#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
William Lallemand44b35322019-10-17 16:28:40 +02009981 [CERT_TYPE_SCTL] = { "sctl", CERT_TYPE_SCTL, &ssl_sock_load_sctl_from_file },
William Lallemand541a5342019-10-23 14:11:54 +02009982#endif
William Lallemand44b35322019-10-17 16:28:40 +02009983 [CERT_TYPE_ISSUER] = { "issuer", CERT_TYPE_ISSUER, &ssl_sock_load_issuer_file_into_ckch },
William Lallemandf29cdef2019-10-23 15:00:52 +02009984 [CERT_TYPE_MAX] = { NULL, CERT_TYPE_MAX, NULL },
William Lallemand44b35322019-10-17 16:28:40 +02009985};
9986
William Lallemand430413e2019-10-28 14:30:47 +01009987/* states of the CLI IO handler for 'set ssl cert' */
9988enum {
9989 SETCERT_ST_INIT = 0,
9990 SETCERT_ST_GEN,
9991 SETCERT_ST_INSERT,
9992 SETCERT_ST_FIN,
9993};
William Lallemand8f840d72019-10-23 10:53:05 +02009994
William Lallemand430413e2019-10-28 14:30:47 +01009995/* release function of the `set ssl cert' command, free things and unlock the spinlock */
William Lallemandbc6ca7c2019-10-29 23:48:19 +01009996static void cli_release_commit_cert(struct appctx *appctx)
William Lallemand8f840d72019-10-23 10:53:05 +02009997{
9998 struct ckch_store *new_ckchs;
9999 struct ckch_inst *ckchi, *ckchis;
William Lallemand8f840d72019-10-23 10:53:05 +020010000
William Lallemand430413e2019-10-28 14:30:47 +010010001 HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
William Lallemand8f840d72019-10-23 10:53:05 +020010002
William Lallemand430413e2019-10-28 14:30:47 +010010003 if (appctx->st2 != SETCERT_ST_FIN) {
William Lallemand8f840d72019-10-23 10:53:05 +020010004 /* free every new sni_ctx and the new store, which are not in the trees so no spinlock there */
William Lallemandbeea2a42019-10-30 17:45:33 +010010005 new_ckchs = appctx->ctx.ssl.new_ckchs;
William Lallemand8f840d72019-10-23 10:53:05 +020010006
William Lallemandbeea2a42019-10-30 17:45:33 +010010007 if (!new_ckchs)
10008 return;
William Lallemand8f840d72019-10-23 10:53:05 +020010009
William Lallemandbeea2a42019-10-30 17:45:33 +010010010 /* if the allocation failed, we need to free everything from the temporary list */
10011 list_for_each_entry_safe(ckchi, ckchis, &new_ckchs->ckch_inst, by_ckchs) {
10012 struct sni_ctx *sc0, *sc0s;
William Lallemand8f840d72019-10-23 10:53:05 +020010013
William Lallemandbeea2a42019-10-30 17:45:33 +010010014 list_for_each_entry_safe(sc0, sc0s, &ckchi->sni_ctx, by_ckch_inst) {
10015 if (sc0->order == 0) /* we only free if it's the first inserted */
10016 SSL_CTX_free(sc0->ctx);
10017 LIST_DEL(&sc0->by_ckch_inst);
10018 free(sc0);
William Lallemand8f840d72019-10-23 10:53:05 +020010019 }
William Lallemandbeea2a42019-10-30 17:45:33 +010010020 LIST_DEL(&ckchi->by_ckchs);
10021 free(ckchi);
William Lallemand8f840d72019-10-23 10:53:05 +020010022 }
William Lallemandbeea2a42019-10-30 17:45:33 +010010023 ckchs_free(new_ckchs);
William Lallemand8f840d72019-10-23 10:53:05 +020010024 }
10025}
10026
10027
10028/*
10029 * This function tries to create the new ckch_inst and their SNIs
10030 */
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010031static int cli_io_handler_commit_cert(struct appctx *appctx)
William Lallemand8f840d72019-10-23 10:53:05 +020010032{
10033 struct stream_interface *si = appctx->owner;
10034 int y = 0;
10035 char *err = NULL;
10036 int errcode = 0;
10037 struct ckch_store *old_ckchs, *new_ckchs = NULL;
10038 struct ckch_inst *ckchi, *ckchis;
William Lallemand8f840d72019-10-23 10:53:05 +020010039 struct buffer *trash = alloc_trash_chunk();
10040
William Lallemand33cc76f2019-10-31 11:43:45 +010010041 if (trash == NULL)
10042 goto error;
10043
William Lallemand8f840d72019-10-23 10:53:05 +020010044 if (unlikely(si_ic(si)->flags & (CF_WRITE_ERROR|CF_SHUTW)))
10045 goto error;
10046
William Lallemand430413e2019-10-28 14:30:47 +010010047 while (1) {
10048 switch (appctx->st2) {
10049 case SETCERT_ST_INIT:
10050 /* This state just print the update message */
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010051 chunk_printf(trash, "Committing %s", ckchs_transaction.path);
William Lallemand430413e2019-10-28 14:30:47 +010010052 if (ci_putchk(si_ic(si), trash) == -1) {
10053 si_rx_room_blk(si);
William Lallemand8f840d72019-10-23 10:53:05 +020010054 goto yield;
William Lallemand430413e2019-10-28 14:30:47 +010010055 }
10056 appctx->st2 = SETCERT_ST_GEN;
10057 /* fallthrough */
10058 case SETCERT_ST_GEN:
10059 /*
10060 * This state generates the ckch instances with their
10061 * sni_ctxs and SSL_CTX.
10062 *
William Lallemand430413e2019-10-28 14:30:47 +010010063 * Since the SSL_CTX generation can be CPU consumer, we
10064 * yield every 10 instances.
10065 */
William Lallemand8f840d72019-10-23 10:53:05 +020010066
William Lallemandbeea2a42019-10-30 17:45:33 +010010067 old_ckchs = appctx->ctx.ssl.old_ckchs;
10068 new_ckchs = appctx->ctx.ssl.new_ckchs;
William Lallemand8f840d72019-10-23 10:53:05 +020010069
William Lallemandbeea2a42019-10-30 17:45:33 +010010070 if (!new_ckchs)
10071 continue;
William Lallemand8f840d72019-10-23 10:53:05 +020010072
William Lallemandbeea2a42019-10-30 17:45:33 +010010073 /* get the next ckchi to regenerate */
10074 ckchi = appctx->ctx.ssl.next_ckchi;
10075 /* we didn't start yet, set it to the first elem */
10076 if (ckchi == NULL)
10077 ckchi = LIST_ELEM(old_ckchs->ckch_inst.n, typeof(ckchi), by_ckchs);
William Lallemand8f840d72019-10-23 10:53:05 +020010078
William Lallemandbeea2a42019-10-30 17:45:33 +010010079 /* walk through the old ckch_inst and creates new ckch_inst using the updated ckchs */
10080 list_for_each_entry_from(ckchi, &old_ckchs->ckch_inst, by_ckchs) {
10081 struct ckch_inst *new_inst;
William Lallemand8f840d72019-10-23 10:53:05 +020010082
William Lallemandbeea2a42019-10-30 17:45:33 +010010083 /* it takes a lot of CPU to creates SSL_CTXs, so we yield every 10 CKCH instances */
10084 if (y >= 10) {
10085 /* save the next ckchi to compute */
10086 appctx->ctx.ssl.next_ckchi = ckchi;
10087 goto yield;
10088 }
William Lallemand8f840d72019-10-23 10:53:05 +020010089
William Lallemandbeea2a42019-10-30 17:45:33 +010010090 if (new_ckchs->multi)
10091 errcode |= ckch_inst_new_load_multi_store(new_ckchs->path, new_ckchs, ckchi->bind_conf, ckchi->ssl_conf, NULL, 0, &new_inst, &err);
10092 else
10093 errcode |= ckch_inst_new_load_store(new_ckchs->path, new_ckchs, ckchi->bind_conf, ckchi->ssl_conf, NULL, 0, &new_inst, &err);
William Lallemand8f840d72019-10-23 10:53:05 +020010094
William Lallemandbeea2a42019-10-30 17:45:33 +010010095 if (errcode & ERR_CODE)
10096 goto error;
William Lallemand8f840d72019-10-23 10:53:05 +020010097
William Lallemand21724f02019-11-04 17:56:13 +010010098 /* if the previous ckchi was used as the default */
10099 if (ckchi->is_default)
10100 new_inst->is_default = 1;
10101
William Lallemandbeea2a42019-10-30 17:45:33 +010010102 /* display one dot per new instance */
10103 chunk_appendf(trash, ".");
10104 /* link the new ckch_inst to the duplicate */
10105 LIST_ADDQ(&new_ckchs->ckch_inst, &new_inst->by_ckchs);
10106 y++;
10107 }
William Lallemand430413e2019-10-28 14:30:47 +010010108 appctx->st2 = SETCERT_ST_INSERT;
10109 /* fallthrough */
10110 case SETCERT_ST_INSERT:
10111 /* The generation is finished, we can insert everything */
William Lallemand8f840d72019-10-23 10:53:05 +020010112
William Lallemandbeea2a42019-10-30 17:45:33 +010010113 old_ckchs = appctx->ctx.ssl.old_ckchs;
10114 new_ckchs = appctx->ctx.ssl.new_ckchs;
William Lallemand8f840d72019-10-23 10:53:05 +020010115
William Lallemandbeea2a42019-10-30 17:45:33 +010010116 if (!new_ckchs)
10117 continue;
William Lallemand430413e2019-10-28 14:30:47 +010010118
William Lallemand21724f02019-11-04 17:56:13 +010010119 /* First, we insert every new SNIs in the trees, also replace the default_ctx */
William Lallemandbeea2a42019-10-30 17:45:33 +010010120 list_for_each_entry_safe(ckchi, ckchis, &new_ckchs->ckch_inst, by_ckchs) {
10121 HA_RWLOCK_WRLOCK(SNI_LOCK, &ckchi->bind_conf->sni_lock);
10122 ssl_sock_load_cert_sni(ckchi, ckchi->bind_conf);
10123 HA_RWLOCK_WRUNLOCK(SNI_LOCK, &ckchi->bind_conf->sni_lock);
10124 }
William Lallemand8f840d72019-10-23 10:53:05 +020010125
William Lallemandbeea2a42019-10-30 17:45:33 +010010126 /* delete the old sni_ctx, the old ckch_insts and the ckch_store */
10127 list_for_each_entry_safe(ckchi, ckchis, &old_ckchs->ckch_inst, by_ckchs) {
10128 struct sni_ctx *sc0, *sc0s;
William Lallemand430413e2019-10-28 14:30:47 +010010129
William Lallemandbeea2a42019-10-30 17:45:33 +010010130 HA_RWLOCK_WRLOCK(SNI_LOCK, &ckchi->bind_conf->sni_lock);
10131 list_for_each_entry_safe(sc0, sc0s, &ckchi->sni_ctx, by_ckch_inst) {
10132 ebmb_delete(&sc0->name);
10133 LIST_DEL(&sc0->by_ckch_inst);
10134 free(sc0);
William Lallemand430413e2019-10-28 14:30:47 +010010135 }
William Lallemandbeea2a42019-10-30 17:45:33 +010010136 HA_RWLOCK_WRUNLOCK(SNI_LOCK, &ckchi->bind_conf->sni_lock);
10137 LIST_DEL(&ckchi->by_ckchs);
10138 free(ckchi);
10139 }
William Lallemand8f840d72019-10-23 10:53:05 +020010140
William Lallemandbeea2a42019-10-30 17:45:33 +010010141 /* Replace the old ckchs by the new one */
10142 ebmb_delete(&old_ckchs->node);
10143 ckchs_free(old_ckchs);
10144 ebst_insert(&ckchs_tree, &new_ckchs->node);
William Lallemand430413e2019-10-28 14:30:47 +010010145 appctx->st2 = SETCERT_ST_FIN;
10146 /* fallthrough */
10147 case SETCERT_ST_FIN:
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010148 /* we achieved the transaction, we can set everything to NULL */
10149 free(ckchs_transaction.path);
10150 ckchs_transaction.path = NULL;
10151 ckchs_transaction.new_ckchs = NULL;
10152 ckchs_transaction.old_ckchs = NULL;
William Lallemand430413e2019-10-28 14:30:47 +010010153 goto end;
10154 }
William Lallemand8f840d72019-10-23 10:53:05 +020010155 }
William Lallemand430413e2019-10-28 14:30:47 +010010156end:
William Lallemand8f840d72019-10-23 10:53:05 +020010157
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010158 chunk_appendf(trash, "\nSuccess!\n");
William Lallemand430413e2019-10-28 14:30:47 +010010159 if (ci_putchk(si_ic(si), trash) == -1)
10160 si_rx_room_blk(si);
10161 free_trash_chunk(trash);
10162 /* success: call the release function and don't come back */
10163 return 1;
William Lallemand8f840d72019-10-23 10:53:05 +020010164yield:
10165 /* store the state */
10166 if (ci_putchk(si_ic(si), trash) == -1)
10167 si_rx_room_blk(si);
10168 free_trash_chunk(trash);
10169 si_rx_endp_more(si); /* let's come back later */
William Lallemand8f840d72019-10-23 10:53:05 +020010170 return 0; /* should come back */
10171
10172error:
10173 /* spin unlock and free are done in the release function */
William Lallemand33cc76f2019-10-31 11:43:45 +010010174 if (trash) {
10175 chunk_appendf(trash, "\n%sFailed!\n", err);
10176 if (ci_putchk(si_ic(si), trash) == -1)
10177 si_rx_room_blk(si);
10178 free_trash_chunk(trash);
10179 }
William Lallemand430413e2019-10-28 14:30:47 +010010180 /* error: call the release function and don't come back */
10181 return 1;
William Lallemand8f840d72019-10-23 10:53:05 +020010182}
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010183
10184/*
10185 * Parsing function of 'commit ssl cert'
10186 */
10187static int cli_parse_commit_cert(char **args, char *payload, struct appctx *appctx, void *private)
10188{
10189 char *err = NULL;
10190
10191 if (!*args[3])
10192 return cli_err(appctx, "'commit ssl cert expects a filename\n");
10193
10194 /* The operations on the CKCH architecture are locked so we can
10195 * manipulate ckch_store and ckch_inst */
10196 if (HA_SPIN_TRYLOCK(CKCH_LOCK, &ckch_lock))
10197 return cli_err(appctx, "Can't commit the certificate!\nOperations on certificates are currently locked!\n");
10198
10199 if (!ckchs_transaction.path) {
10200 memprintf(&err, "No ongoing transaction! !\n");
10201 goto error;
10202 }
10203
10204 if (strcmp(ckchs_transaction.path, args[3]) != 0) {
10205 memprintf(&err, "The ongoing transaction is about '%s' but you are trying to set '%s'\n", ckchs_transaction.path, args[3]);
10206 goto error;
10207 }
10208
10209 /* init the appctx structure */
10210 appctx->st2 = SETCERT_ST_INIT;
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010211 appctx->ctx.ssl.next_ckchi = NULL;
10212 appctx->ctx.ssl.new_ckchs = ckchs_transaction.new_ckchs;
10213 appctx->ctx.ssl.old_ckchs = ckchs_transaction.old_ckchs;
10214
10215 /* we don't unlock there, it will be unlock after the IO handler, in the release handler */
10216 return 0;
10217
10218error:
10219
10220 HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
10221 err = memprintf(&err, "%sCan't commit %s!\n", err ? err : "", args[3]);
10222
10223 return cli_dynerr(appctx, err);
10224}
10225
10226
William Lallemand8f840d72019-10-23 10:53:05 +020010227/*
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010228 * Parsing function of `set ssl cert`, it updates or creates a temporary ckch.
William Lallemand8f840d72019-10-23 10:53:05 +020010229 */
William Lallemand150bfa82019-09-19 17:12:49 +020010230static int cli_parse_set_cert(char **args, char *payload, struct appctx *appctx, void *private)
10231{
William Lallemand0c3b7d92019-10-18 11:27:07 +020010232 struct ckch_store *new_ckchs = NULL;
William Lallemand8f840d72019-10-23 10:53:05 +020010233 struct ckch_store *old_ckchs = NULL;
William Lallemand150bfa82019-09-19 17:12:49 +020010234 char *err = NULL;
William Lallemand963b2e72019-10-14 11:38:36 +020010235 int i;
William Lallemand849eed62019-10-17 16:23:50 +020010236 int bundle = -1; /* TRUE if >= 0 (ckch index) */
Emeric Brunf69ed1d2019-10-17 11:56:56 +020010237 int errcode = 0;
William Lallemand44b35322019-10-17 16:28:40 +020010238 char *end;
10239 int type = CERT_TYPE_PEM;
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010240 struct cert_key_and_chain *ckch;
10241 struct buffer *buf;
William Lallemand8f840d72019-10-23 10:53:05 +020010242
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010243 if ((buf = alloc_trash_chunk()) == NULL)
10244 return cli_err(appctx, "Can't allocate memory\n");
William Lallemand150bfa82019-09-19 17:12:49 +020010245
10246 if (!*args[3] || !payload)
10247 return cli_err(appctx, "'set ssl cert expects a filename and a certificat as a payload\n");
10248
10249 /* The operations on the CKCH architecture are locked so we can
10250 * manipulate ckch_store and ckch_inst */
10251 if (HA_SPIN_TRYLOCK(CKCH_LOCK, &ckch_lock))
10252 return cli_err(appctx, "Can't update the certificate!\nOperations on certificates are currently locked!\n");
10253
William Lallemand8f840d72019-10-23 10:53:05 +020010254 if (!chunk_strcpy(buf, args[3])) {
10255 memprintf(&err, "%sCan't allocate memory\n", err ? err : "");
10256 errcode |= ERR_ALERT | ERR_FATAL;
10257 goto end;
10258 }
10259
William Lallemand44b35322019-10-17 16:28:40 +020010260 /* check which type of file we want to update */
William Lallemandf29cdef2019-10-23 15:00:52 +020010261 for (i = 0; cert_exts[i].type < CERT_TYPE_MAX; i++) {
William Lallemand8f840d72019-10-23 10:53:05 +020010262 end = strrchr(buf->area, '.');
William Lallemand44b35322019-10-17 16:28:40 +020010263 if (end && *cert_exts[i].ext && (!strcmp(end + 1, cert_exts[i].ext))) {
10264 *end = '\0';
10265 type = cert_exts[i].type;
10266 break;
10267 }
10268 }
10269
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010270 appctx->ctx.ssl.old_ckchs = NULL;
10271 appctx->ctx.ssl.new_ckchs = NULL;
William Lallemand849eed62019-10-17 16:23:50 +020010272
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010273 /* if there is an ongoing transaction */
10274 if (ckchs_transaction.path) {
10275 /* if the ongoing transaction is a bundle, we need to find which part of the bundle need to be updated */
William Lallemand963b2e72019-10-14 11:38:36 +020010276#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010277 if (ckchs_transaction.new_ckchs->multi) {
Emmanuel Hocdet40f2f1e2019-10-30 17:31:28 +010010278 char *end;
William Lallemand963b2e72019-10-14 11:38:36 +020010279 int j;
William Lallemand150bfa82019-09-19 17:12:49 +020010280
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010281 /* check if it was used in a bundle by removing the
William Lallemand963b2e72019-10-14 11:38:36 +020010282 * .dsa/.rsa/.ecdsa at the end of the filename */
William Lallemand8f840d72019-10-23 10:53:05 +020010283 end = strrchr(buf->area, '.');
Emmanuel Hocdet40f2f1e2019-10-30 17:31:28 +010010284 for (j = 0; end && j < SSL_SOCK_NUM_KEYTYPES; j++) {
William Lallemand963b2e72019-10-14 11:38:36 +020010285 if (!strcmp(end + 1, SSL_SOCK_KEYTYPE_NAMES[j])) {
10286 bundle = j; /* keep the type of certificate so we insert it at the right place */
10287 *end = '\0'; /* it's a bundle let's end the string*/
10288 break;
10289 }
William Lallemand150bfa82019-09-19 17:12:49 +020010290 }
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010291 if (bundle < 0) {
10292 memprintf(&err, "The ongoing transaction is the '%s' bundle. You need to specify which part of the bundle you want to update ('%s.{rsa,ecdsa,dsa}')\n", ckchs_transaction.path, buf->area);
10293 errcode |= ERR_ALERT | ERR_FATAL;
10294 goto end;
10295 }
10296 }
10297#endif
10298
10299 /* if there is an ongoing transaction, check if this is the same file */
10300 if (strcmp(ckchs_transaction.path, buf->area) != 0) {
10301 memprintf(&err, "The ongoing transaction is about '%s' but you are trying to set '%s'\n", ckchs_transaction.path, buf->area);
10302 errcode |= ERR_ALERT | ERR_FATAL;
10303 goto end;
William Lallemand150bfa82019-09-19 17:12:49 +020010304 }
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010305
10306 appctx->ctx.ssl.old_ckchs = ckchs_transaction.new_ckchs;
10307
10308 } else {
10309 struct ckch_store *find_ckchs[2] = { NULL, NULL };
10310
10311 /* lookup for the certificate in the tree:
10312 * check if this is used as a bundle AND as a unique certificate */
10313 for (i = 0; i < 2; i++) {
10314
10315 if ((find_ckchs[i] = ckchs_lookup(buf->area)) != NULL) {
10316 /* only the bundle name is in the tree and you should
10317 * never update a bundle name, only a filename */
10318 if (bundle < 0 && find_ckchs[i]->multi) {
10319 /* we tried to look for a non-bundle and we found a bundle */
10320 memprintf(&err, "%s%s is a multi-cert bundle. Try updating %s.{dsa,rsa,ecdsa}\n",
10321 err ? err : "", args[3], args[3]);
10322 errcode |= ERR_ALERT | ERR_FATAL;
10323 goto end;
10324 }
William Lallemand3246d942019-11-04 14:02:11 +010010325 /* If we want a bundle but this is not a bundle
10326 * example: When you try to update <file>.rsa, but
10327 * <file> is a regular file */
10328 if (bundle >= 0 && find_ckchs[i]->multi == 0) {
10329 find_ckchs[i] = NULL;
10330 break;
10331 }
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010332 }
10333#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
10334 {
Emmanuel Hocdet40f2f1e2019-10-30 17:31:28 +010010335 char *end;
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010336 int j;
10337
10338 /* check if it was used in a bundle by removing the
10339 * .dsa/.rsa/.ecdsa at the end of the filename */
10340 end = strrchr(buf->area, '.');
Emmanuel Hocdet40f2f1e2019-10-30 17:31:28 +010010341 for (j = 0; end && j < SSL_SOCK_NUM_KEYTYPES; j++) {
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010342 if (!strcmp(end + 1, SSL_SOCK_KEYTYPE_NAMES[j])) {
10343 bundle = j; /* keep the type of certificate so we insert it at the right place */
10344 *end = '\0'; /* it's a bundle let's end the string*/
10345 break;
10346 }
10347 }
William Lallemand37031b82019-11-04 13:38:53 +010010348 if (bundle < 0) /* we didn't find a bundle extension */
10349 break;
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010350 }
William Lallemand963b2e72019-10-14 11:38:36 +020010351#else
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010352 /* bundles are not supported here, so we don't need to lookup again */
10353 break;
William Lallemand963b2e72019-10-14 11:38:36 +020010354#endif
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010355 }
10356
10357 if (find_ckchs[0] && find_ckchs[1]) {
10358 memprintf(&err, "%sUpdating a certificate which is used in the HAProxy configuration as a bundle and as a unique certificate is not supported. ('%s' and '%s')\n",
10359 err ? err : "", find_ckchs[0]->path, find_ckchs[1]->path);
10360 errcode |= ERR_ALERT | ERR_FATAL;
10361 goto end;
10362 }
10363
10364 appctx->ctx.ssl.old_ckchs = find_ckchs[0] ? find_ckchs[0] : find_ckchs[1];
William Lallemand150bfa82019-09-19 17:12:49 +020010365 }
10366
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010367 if (!appctx->ctx.ssl.old_ckchs) {
10368 memprintf(&err, "%sCan't replace a certificate which is not referenced by the configuration!\n",
William Lallemand150bfa82019-09-19 17:12:49 +020010369 err ? err : "");
Emeric Brunf69ed1d2019-10-17 11:56:56 +020010370 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemand8f840d72019-10-23 10:53:05 +020010371 goto end;
William Lallemand150bfa82019-09-19 17:12:49 +020010372 }
10373
William Lallemand8a7fdf02019-11-04 10:59:32 +010010374 if (!appctx->ctx.ssl.path) {
10375 /* this is a new transaction, set the path of the transaction */
10376 appctx->ctx.ssl.path = strdup(appctx->ctx.ssl.old_ckchs->path);
10377 if (!appctx->ctx.ssl.path) {
10378 memprintf(&err, "%sCan't allocate memory\n", err ? err : "");
10379 errcode |= ERR_ALERT | ERR_FATAL;
10380 goto end;
10381 }
10382 }
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010383
10384 old_ckchs = appctx->ctx.ssl.old_ckchs;
10385
10386 /* TODO: handle filters */
10387 if (old_ckchs->filters) {
10388 memprintf(&err, "%sCertificates used in crt-list with filters are not supported!\n",
10389 err ? err : "");
10390 errcode |= ERR_ALERT | ERR_FATAL;
10391 goto end;
10392 }
10393
10394 /* duplicate the ckch store */
10395 new_ckchs = ckchs_dup(old_ckchs);
10396 if (!new_ckchs) {
10397 memprintf(&err, "%sCannot allocate memory!\n",
10398 err ? err : "");
10399 errcode |= ERR_ALERT | ERR_FATAL;
10400 goto end;
10401 }
10402
10403 if (!new_ckchs->multi)
10404 ckch = new_ckchs->ckch;
10405 else
10406 ckch = &new_ckchs->ckch[bundle];
10407
10408 /* appply the change on the duplicate */
10409 if (cert_exts[type].load(buf->area, payload, ckch, &err) != 0) {
10410 memprintf(&err, "%sCan't load the payload\n", err ? err : "");
10411 errcode |= ERR_ALERT | ERR_FATAL;
10412 goto end;
10413 }
10414
10415 appctx->ctx.ssl.new_ckchs = new_ckchs;
10416
10417 /* we succeed, we can save the ckchs in the transaction */
10418
10419 /* if there wasn't a transaction, update the old ckchs */
10420 if (!ckchs_transaction.old_ckchs && !ckchs_transaction.old_ckchs) {
10421 ckchs_transaction.old_ckchs = appctx->ctx.ssl.old_ckchs;
10422 ckchs_transaction.path = appctx->ctx.ssl.path;
10423 err = memprintf(&err, "Transaction created for certificate %s!\n", ckchs_transaction.path);
10424 } else {
10425 err = memprintf(&err, "Transaction updated for certificate %s!\n", ckchs_transaction.path);
10426
10427 }
10428
10429 /* free the previous ckchs if there was a transaction */
10430 ckchs_free(ckchs_transaction.new_ckchs);
10431
10432 ckchs_transaction.new_ckchs = appctx->ctx.ssl.new_ckchs;
10433
10434
William Lallemand8f840d72019-10-23 10:53:05 +020010435 /* creates the SNI ctxs later in the IO handler */
William Lallemand150bfa82019-09-19 17:12:49 +020010436
William Lallemand8f840d72019-10-23 10:53:05 +020010437end:
10438 free_trash_chunk(buf);
William Lallemand150bfa82019-09-19 17:12:49 +020010439
Emeric Brunf69ed1d2019-10-17 11:56:56 +020010440 if (errcode & ERR_CODE) {
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010441
10442 ckchs_free(appctx->ctx.ssl.new_ckchs);
10443 appctx->ctx.ssl.new_ckchs = NULL;
10444
10445 appctx->ctx.ssl.old_ckchs = NULL;
10446
10447 free(appctx->ctx.ssl.path);
10448 appctx->ctx.ssl.path = NULL;
10449
10450 HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
William Lallemand44b35322019-10-17 16:28:40 +020010451 return cli_dynerr(appctx, memprintf(&err, "%sCan't update %s!\n", err ? err : "", args[3]));
William Lallemand430413e2019-10-28 14:30:47 +010010452 } else {
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010453
10454 HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
10455 return cli_dynmsg(appctx, LOG_NOTICE, err);
William Lallemand430413e2019-10-28 14:30:47 +010010456 }
William Lallemand8f840d72019-10-23 10:53:05 +020010457 /* TODO: handle the ERR_WARN which are not handled because of the io_handler */
William Lallemand150bfa82019-09-19 17:12:49 +020010458}
10459
William Lallemand0bc9c8a2019-11-19 15:51:51 +010010460/* parsing function of 'abort ssl cert' */
10461static int cli_parse_abort_cert(char **args, char *payload, struct appctx *appctx, void *private)
10462{
10463 char *err = NULL;
10464
10465 if (!*args[3])
10466 return cli_err(appctx, "'abort ssl cert' expects a filename\n");
10467
10468 /* The operations on the CKCH architecture are locked so we can
10469 * manipulate ckch_store and ckch_inst */
10470 if (HA_SPIN_TRYLOCK(CKCH_LOCK, &ckch_lock))
10471 return cli_err(appctx, "Can't abort!\nOperations on certificates are currently locked!\n");
10472
10473 if (!ckchs_transaction.path) {
10474 memprintf(&err, "No ongoing transaction!\n");
10475 goto error;
10476 }
10477
10478 if (strcmp(ckchs_transaction.path, args[3]) != 0) {
10479 memprintf(&err, "The ongoing transaction is about '%s' but you are trying to abort a transaction for '%s'\n", ckchs_transaction.path, args[3]);
10480 goto error;
10481 }
10482
10483 /* Only free the ckchs there, because the SNI and instances were not generated yet */
10484 ckchs_free(ckchs_transaction.new_ckchs);
10485 ckchs_transaction.new_ckchs = NULL;
10486 ckchs_free(ckchs_transaction.old_ckchs);
10487 ckchs_transaction.old_ckchs = NULL;
10488 free(ckchs_transaction.path);
10489 ckchs_transaction.path = NULL;
10490
10491 HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
10492
10493 err = memprintf(&err, "Transaction aborted for certificate '%s'!\n", args[3]);
10494 return cli_dynmsg(appctx, LOG_NOTICE, err);
10495
10496error:
10497 HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
10498
10499 return cli_dynerr(appctx, err);
10500}
10501
Aurélien Nephtaliabbf6072018-04-18 13:26:46 +020010502static int cli_parse_set_ocspresponse(char **args, char *payload, struct appctx *appctx, void *private)
William Lallemand32af2032016-10-29 18:09:35 +020010503{
10504#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
10505 char *err = NULL;
Willy Tarreau1c913e42018-08-22 05:26:57 +020010506 int i, j, ret;
Aurélien Nephtali1e0867c2018-04-18 14:04:58 +020010507
10508 if (!payload)
10509 payload = args[3];
William Lallemand32af2032016-10-29 18:09:35 +020010510
10511 /* Expect one parameter: the new response in base64 encoding */
Willy Tarreau9d008692019-08-09 11:21:01 +020010512 if (!*payload)
10513 return cli_err(appctx, "'set ssl ocsp-response' expects response in base64 encoding.\n");
Aurélien Nephtali1e0867c2018-04-18 14:04:58 +020010514
10515 /* remove \r and \n from the payload */
10516 for (i = 0, j = 0; payload[i]; i++) {
10517 if (payload[i] == '\r' || payload[i] == '\n')
10518 continue;
10519 payload[j++] = payload[i];
10520 }
10521 payload[j] = 0;
William Lallemand32af2032016-10-29 18:09:35 +020010522
Willy Tarreau1c913e42018-08-22 05:26:57 +020010523 ret = base64dec(payload, j, trash.area, trash.size);
Willy Tarreau9d008692019-08-09 11:21:01 +020010524 if (ret < 0)
10525 return cli_err(appctx, "'set ssl ocsp-response' received invalid base64 encoded response.\n");
William Lallemand32af2032016-10-29 18:09:35 +020010526
Willy Tarreau1c913e42018-08-22 05:26:57 +020010527 trash.data = ret;
William Lallemand32af2032016-10-29 18:09:35 +020010528 if (ssl_sock_update_ocsp_response(&trash, &err)) {
Willy Tarreau9d008692019-08-09 11:21:01 +020010529 if (err)
10530 return cli_dynerr(appctx, memprintf(&err, "%s.\n", err));
10531 else
10532 return cli_err(appctx, "Failed to update OCSP response.\n");
William Lallemand32af2032016-10-29 18:09:35 +020010533 }
Willy Tarreau9d008692019-08-09 11:21:01 +020010534
10535 return cli_msg(appctx, LOG_INFO, "OCSP Response updated!\n");
William Lallemand32af2032016-10-29 18:09:35 +020010536#else
Willy Tarreau9d008692019-08-09 11:21:01 +020010537 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 +020010538#endif
10539
Nenad Merdanovicc31499d2019-03-23 11:00:32 +010010540}
10541
Willy Tarreau86a394e2019-05-09 14:15:32 +020010542#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000100fL)
Nenad Merdanovicc31499d2019-03-23 11:00:32 +010010543static inline int sample_conv_var2smp_str(const struct arg *arg, struct sample *smp)
10544{
10545 switch (arg->type) {
10546 case ARGT_STR:
10547 smp->data.type = SMP_T_STR;
10548 smp->data.u.str = arg->data.str;
10549 return 1;
10550 case ARGT_VAR:
10551 if (!vars_get_by_desc(&arg->data.var, smp))
10552 return 0;
10553 if (!sample_casts[smp->data.type][SMP_T_STR])
10554 return 0;
10555 if (!sample_casts[smp->data.type][SMP_T_STR](smp))
10556 return 0;
10557 return 1;
10558 default:
10559 return 0;
10560 }
10561}
10562
10563static int check_aes_gcm(struct arg *args, struct sample_conv *conv,
10564 const char *file, int line, char **err)
10565{
10566 switch(args[0].data.sint) {
10567 case 128:
10568 case 192:
10569 case 256:
10570 break;
10571 default:
10572 memprintf(err, "key size must be 128, 192 or 256 (bits).");
10573 return 0;
10574 }
10575 /* Try to decode a variable. */
10576 vars_check_arg(&args[1], NULL);
10577 vars_check_arg(&args[2], NULL);
10578 vars_check_arg(&args[3], NULL);
10579 return 1;
10580}
10581
10582/* Arguements: AES size in bits, nonce, key, tag. The last three arguments are base64 encoded */
10583static int sample_conv_aes_gcm_dec(const struct arg *arg_p, struct sample *smp, void *private)
10584{
10585 struct sample nonce, key, aead_tag;
10586 struct buffer *smp_trash, *smp_trash_alloc;
10587 EVP_CIPHER_CTX *ctx;
10588 int dec_size, ret;
10589
10590 smp_set_owner(&nonce, smp->px, smp->sess, smp->strm, smp->opt);
10591 if (!sample_conv_var2smp_str(&arg_p[1], &nonce))
10592 return 0;
10593
10594 smp_set_owner(&key, smp->px, smp->sess, smp->strm, smp->opt);
10595 if (!sample_conv_var2smp_str(&arg_p[2], &key))
10596 return 0;
10597
10598 smp_set_owner(&aead_tag, smp->px, smp->sess, smp->strm, smp->opt);
10599 if (!sample_conv_var2smp_str(&arg_p[3], &aead_tag))
10600 return 0;
10601
10602 smp_trash = get_trash_chunk();
10603 smp_trash_alloc = alloc_trash_chunk();
10604 if (!smp_trash_alloc)
10605 return 0;
10606
10607 ctx = EVP_CIPHER_CTX_new();
10608
10609 if (!ctx)
10610 goto err;
10611
10612 dec_size = base64dec(nonce.data.u.str.area, nonce.data.u.str.data, smp_trash->area, smp_trash->size);
10613 if (dec_size < 0)
10614 goto err;
10615 smp_trash->data = dec_size;
10616
10617 /* Set cipher type and mode */
10618 switch(arg_p[0].data.sint) {
10619 case 128:
10620 EVP_DecryptInit_ex(ctx, EVP_aes_128_gcm(), NULL, NULL, NULL);
10621 break;
10622 case 192:
10623 EVP_DecryptInit_ex(ctx, EVP_aes_192_gcm(), NULL, NULL, NULL);
10624 break;
10625 case 256:
10626 EVP_DecryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL);
10627 break;
10628 }
10629
10630 EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, smp_trash->data, NULL);
10631
10632 /* Initialise IV */
10633 if(!EVP_DecryptInit_ex(ctx, NULL, NULL, NULL, (unsigned char *) smp_trash->area))
10634 goto err;
10635
10636 dec_size = base64dec(key.data.u.str.area, key.data.u.str.data, smp_trash->area, smp_trash->size);
10637 if (dec_size < 0)
10638 goto err;
10639 smp_trash->data = dec_size;
10640
10641 /* Initialise key */
10642 if (!EVP_DecryptInit_ex(ctx, NULL, NULL, (unsigned char *) smp_trash->area, NULL))
10643 goto err;
10644
10645 if (!EVP_DecryptUpdate(ctx, (unsigned char *) smp_trash->area, (int *) &smp_trash->data,
10646 (unsigned char *) smp->data.u.str.area, (int) smp->data.u.str.data))
10647 goto err;
10648
10649 dec_size = base64dec(aead_tag.data.u.str.area, aead_tag.data.u.str.data, smp_trash_alloc->area, smp_trash_alloc->size);
10650 if (dec_size < 0)
10651 goto err;
10652 smp_trash_alloc->data = dec_size;
10653 dec_size = smp_trash->data;
10654
10655 EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, smp_trash_alloc->data, (void *) smp_trash_alloc->area);
10656 ret = EVP_DecryptFinal_ex(ctx, (unsigned char *) smp_trash->area + smp_trash->data, (int *) &smp_trash->data);
10657
10658 if (ret <= 0)
10659 goto err;
10660
10661 smp->data.u.str.data = dec_size + smp_trash->data;
10662 smp->data.u.str.area = smp_trash->area;
10663 smp->data.type = SMP_T_BIN;
10664 smp->flags &= ~SMP_F_CONST;
10665 free_trash_chunk(smp_trash_alloc);
10666 return 1;
10667
10668err:
10669 free_trash_chunk(smp_trash_alloc);
10670 return 0;
William Lallemand32af2032016-10-29 18:09:35 +020010671}
Nenad Merdanovicc31499d2019-03-23 11:00:32 +010010672# endif
William Lallemand32af2032016-10-29 18:09:35 +020010673
10674/* register cli keywords */
10675static struct cli_kw_list cli_kws = {{ },{
10676#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
10677 { { "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 +020010678 { { "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 +020010679#endif
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +010010680 { { "set", "ssl", "ocsp-response", NULL }, NULL, cli_parse_set_ocspresponse, NULL },
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010681 { { "set", "ssl", "cert", NULL }, "set ssl cert <certfile> <payload> : replace a certificate file", cli_parse_set_cert, NULL, NULL },
10682 { { "commit", "ssl", "cert", NULL }, "commit ssl cert <certfile> : commit a certificate file", cli_parse_commit_cert, cli_io_handler_commit_cert, cli_release_commit_cert },
William Lallemand0bc9c8a2019-11-19 15:51:51 +010010683 { { "abort", "ssl", "cert", NULL }, "abort ssl cert <certfile> : abort a transaction for a certificate file", cli_parse_abort_cert, NULL, NULL },
William Lallemand32af2032016-10-29 18:09:35 +020010684 { { NULL }, NULL, NULL, NULL }
10685}};
10686
Willy Tarreau0108d902018-11-25 19:14:37 +010010687INITCALL1(STG_REGISTER, cli_register_kw, &cli_kws);
William Lallemand32af2032016-10-29 18:09:35 +020010688
Willy Tarreau7875d092012-09-10 08:20:03 +020010689/* Note: must not be declared <const> as its list will be overwritten.
10690 * Please take care of keeping this list alphabetically sorted.
10691 */
Willy Tarreaudc13c112013-06-21 23:16:39 +020010692static struct sample_fetch_kw_list sample_fetch_keywords = {ILH, {
Emeric Brun645ae792014-04-30 14:21:06 +020010693 { "ssl_bc", smp_fetch_ssl_fc, 0, NULL, SMP_T_BOOL, SMP_USE_L5SRV },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +020010694 { "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 +010010695#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Jérôme Magnine064a802018-12-03 22:21:04 +010010696 { "ssl_bc_alpn", smp_fetch_ssl_fc_alpn, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
Olivier Houchard6b77f492018-11-22 18:18:29 +010010697#endif
Emeric Brun645ae792014-04-30 14:21:06 +020010698 { "ssl_bc_cipher", smp_fetch_ssl_fc_cipher, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
Olivier Houchard6b77f492018-11-22 18:18:29 +010010699#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
10700 { "ssl_bc_npn", smp_fetch_ssl_fc_npn, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
10701#endif
Emeric Brun74f7ffa2018-02-19 16:14:12 +010010702 { "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 +020010703 { "ssl_bc_protocol", smp_fetch_ssl_fc_protocol, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
Emeric Brunb73a9b02014-04-30 18:49:19 +020010704 { "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 +020010705 { "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 +020010706#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
Emeric Brun645ae792014-04-30 14:21:06 +020010707 { "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 -040010708#endif
Emmanuel Hocdet839af572019-05-14 16:27:35 +020010709#if HA_OPENSSL_VERSION_NUMBER >= 0x10100000L
Patrick Hemmer65674662019-06-04 08:13:03 -040010710 { "ssl_bc_client_random", smp_fetch_ssl_fc_random, 0, NULL, SMP_T_BIN, SMP_USE_L5SRV },
10711 { "ssl_bc_server_random", smp_fetch_ssl_fc_random, 0, NULL, SMP_T_BIN, SMP_USE_L5SRV },
Patrick Hemmere0275472018-04-28 19:15:51 -040010712 { "ssl_bc_session_key", smp_fetch_ssl_fc_session_key, 0, NULL, SMP_T_BIN, SMP_USE_L5SRV },
10713#endif
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +020010714 { "ssl_c_ca_err", smp_fetch_ssl_c_ca_err, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
10715 { "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 +010010716 { "ssl_c_der", smp_fetch_ssl_x_der, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +020010717 { "ssl_c_err", smp_fetch_ssl_c_err, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Emeric Brunba841a12014-04-30 17:05:08 +020010718 { "ssl_c_i_dn", smp_fetch_ssl_x_i_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
10719 { "ssl_c_key_alg", smp_fetch_ssl_x_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
10720 { "ssl_c_notafter", smp_fetch_ssl_x_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
10721 { "ssl_c_notbefore", smp_fetch_ssl_x_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
10722 { "ssl_c_sig_alg", smp_fetch_ssl_x_sig_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
10723 { "ssl_c_s_dn", smp_fetch_ssl_x_s_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
10724 { "ssl_c_serial", smp_fetch_ssl_x_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
10725 { "ssl_c_sha1", smp_fetch_ssl_x_sha1, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +010010726 { "ssl_c_used", smp_fetch_ssl_c_used, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +020010727 { "ssl_c_verify", smp_fetch_ssl_c_verify, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
10728 { "ssl_c_version", smp_fetch_ssl_x_version, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Emeric Brun43e79582014-10-29 19:03:26 +010010729 { "ssl_f_der", smp_fetch_ssl_x_der, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Emeric Brunba841a12014-04-30 17:05:08 +020010730 { "ssl_f_i_dn", smp_fetch_ssl_x_i_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
10731 { "ssl_f_key_alg", smp_fetch_ssl_x_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
10732 { "ssl_f_notafter", smp_fetch_ssl_x_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
10733 { "ssl_f_notbefore", smp_fetch_ssl_x_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
10734 { "ssl_f_sig_alg", smp_fetch_ssl_x_sig_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
10735 { "ssl_f_s_dn", smp_fetch_ssl_x_s_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
10736 { "ssl_f_serial", smp_fetch_ssl_x_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Emeric Brun55f4fa82014-04-30 17:11:25 +020010737 { "ssl_f_sha1", smp_fetch_ssl_x_sha1, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +020010738 { "ssl_f_version", smp_fetch_ssl_x_version, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +010010739 { "ssl_fc", smp_fetch_ssl_fc, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +020010740 { "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 +010010741 { "ssl_fc_cipher", smp_fetch_ssl_fc_cipher, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +010010742 { "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 +020010743 { "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 +010010744 { "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 +020010745 { "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 +010010746#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +010010747 { "ssl_fc_npn", smp_fetch_ssl_fc_npn, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreaua33c6542012-10-15 13:19:06 +020010748#endif
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +010010749#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +010010750 { "ssl_fc_alpn", smp_fetch_ssl_fc_alpn, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreauab861d32013-04-02 02:30:41 +020010751#endif
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +010010752 { "ssl_fc_protocol", smp_fetch_ssl_fc_protocol, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreau9a1ab082019-05-09 13:26:41 +020010753#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
Emeric Brunb73a9b02014-04-30 18:49:19 +020010754 { "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 -040010755#endif
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +020010756 { "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 +020010757#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +010010758 { "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 -040010759#endif
Emmanuel Hocdet839af572019-05-14 16:27:35 +020010760#if HA_OPENSSL_VERSION_NUMBER >= 0x10100000L
Patrick Hemmer65674662019-06-04 08:13:03 -040010761 { "ssl_fc_client_random", smp_fetch_ssl_fc_random, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
10762 { "ssl_fc_server_random", smp_fetch_ssl_fc_random, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Patrick Hemmere0275472018-04-28 19:15:51 -040010763 { "ssl_fc_session_key", smp_fetch_ssl_fc_session_key, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
10764#endif
Patrick Hemmer41966772018-04-28 19:15:48 -040010765#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +010010766 { "ssl_fc_sni", smp_fetch_ssl_fc_sni, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Patrick Hemmer41966772018-04-28 19:15:48 -040010767#endif
Thierry FOURNIER5bf77322017-02-25 12:45:22 +010010768 { "ssl_fc_cipherlist_bin", smp_fetch_ssl_fc_cl_bin, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
10769 { "ssl_fc_cipherlist_hex", smp_fetch_ssl_fc_cl_hex, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
10770 { "ssl_fc_cipherlist_str", smp_fetch_ssl_fc_cl_str, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
10771 { "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 +020010772 { NULL, NULL, 0, 0, 0 },
10773}};
10774
Willy Tarreau0108d902018-11-25 19:14:37 +010010775INITCALL1(STG_REGISTER, sample_register_fetches, &sample_fetch_keywords);
10776
Willy Tarreau7875d092012-09-10 08:20:03 +020010777/* Note: must not be declared <const> as its list will be overwritten.
10778 * Please take care of keeping this list alphabetically sorted.
10779 */
Willy Tarreaudc13c112013-06-21 23:16:39 +020010780static struct acl_kw_list acl_kws = {ILH, {
Thierry FOURNIERc5a4e982014-03-05 16:07:08 +010010781 { "ssl_fc_sni_end", "ssl_fc_sni", PAT_MATCH_END },
10782 { "ssl_fc_sni_reg", "ssl_fc_sni", PAT_MATCH_REG },
Willy Tarreau8ed669b2013-01-11 15:49:37 +010010783 { /* END */ },
Willy Tarreau7875d092012-09-10 08:20:03 +020010784}};
10785
Willy Tarreau0108d902018-11-25 19:14:37 +010010786INITCALL1(STG_REGISTER, acl_register_keywords, &acl_kws);
10787
Willy Tarreau79eeafa2012-09-14 07:53:05 +020010788/* Note: must not be declared <const> as its list will be overwritten.
10789 * Please take care of keeping this list alphabetically sorted, doing so helps
10790 * all code contributors.
10791 * Optional keywords are also declared with a NULL ->parse() function so that
10792 * the config parser can report an appropriate error when a known keyword was
10793 * not enabled.
10794 */
Emmanuel Hocdet98263292016-12-29 18:26:15 +010010795static struct ssl_bind_kw ssl_bind_kws[] = {
Olivier Houchardc2aae742017-09-22 18:26:28 +020010796 { "allow-0rtt", ssl_bind_parse_allow_0rtt, 0 }, /* allow 0-RTT */
Emmanuel Hocdet98263292016-12-29 18:26:15 +010010797 { "alpn", ssl_bind_parse_alpn, 1 }, /* set ALPN supported protocols */
10798 { "ca-file", ssl_bind_parse_ca_file, 1 }, /* set CAfile to process verify on client cert */
10799 { "ciphers", ssl_bind_parse_ciphers, 1 }, /* set SSL cipher suite */
Emmanuel Hocdet839af572019-05-14 16:27:35 +020010800#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +020010801 { "ciphersuites", ssl_bind_parse_ciphersuites, 1 }, /* set TLS 1.3 cipher suite */
10802#endif
Emmanuel Hocdet98263292016-12-29 18:26:15 +010010803 { "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 +010010804 { "curves", ssl_bind_parse_curves, 1 }, /* set SSL curve suite */
Emmanuel Hocdet98263292016-12-29 18:26:15 +010010805 { "ecdhe", ssl_bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +020010806 { "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 +010010807 { "npn", ssl_bind_parse_npn, 1 }, /* set NPN supported protocols */
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +020010808 { "ssl-min-ver", ssl_bind_parse_tls_method_minmax,1 }, /* minimum version */
10809 { "ssl-max-ver", ssl_bind_parse_tls_method_minmax,1 }, /* maximum version */
Emmanuel Hocdet98263292016-12-29 18:26:15 +010010810 { "verify", ssl_bind_parse_verify, 1 }, /* set SSL verify method */
10811 { NULL, NULL, 0 },
10812};
10813
Willy Tarreau0108d902018-11-25 19:14:37 +010010814/* no initcall for ssl_bind_kws, these ones are parsed in the parser loop */
10815
Willy Tarreau51fb7652012-09-18 18:24:39 +020010816static struct bind_kw_list bind_kws = { "SSL", { }, {
Olivier Houchardc2aae742017-09-22 18:26:28 +020010817 { "allow-0rtt", bind_parse_allow_0rtt, 0 }, /* Allow 0RTT */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +020010818 { "alpn", bind_parse_alpn, 1 }, /* set ALPN supported protocols */
10819 { "ca-file", bind_parse_ca_file, 1 }, /* set CAfile to process verify on client cert */
10820 { "ca-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ignore on verify depth > 0 */
10821 { "ca-sign-file", bind_parse_ca_sign_file, 1 }, /* set CAFile used to generate and sign server certs */
10822 { "ca-sign-pass", bind_parse_ca_sign_pass, 1 }, /* set CAKey passphrase */
10823 { "ciphers", bind_parse_ciphers, 1 }, /* set SSL cipher suite */
Emmanuel Hocdet839af572019-05-14 16:27:35 +020010824#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +020010825 { "ciphersuites", bind_parse_ciphersuites, 1 }, /* set TLS 1.3 cipher suite */
10826#endif
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +020010827 { "crl-file", bind_parse_crl_file, 1 }, /* set certificat revocation list file use on client cert verify */
10828 { "crt", bind_parse_crt, 1 }, /* load SSL certificates from this location */
10829 { "crt-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ingore on verify depth == 0 */
10830 { "crt-list", bind_parse_crt_list, 1 }, /* load a list of crt from this location */
10831 { "curves", bind_parse_curves, 1 }, /* set SSL curve suite */
10832 { "ecdhe", bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
10833 { "force-sslv3", bind_parse_tls_method_options, 0 }, /* force SSLv3 */
10834 { "force-tlsv10", bind_parse_tls_method_options, 0 }, /* force TLSv10 */
10835 { "force-tlsv11", bind_parse_tls_method_options, 0 }, /* force TLSv11 */
10836 { "force-tlsv12", bind_parse_tls_method_options, 0 }, /* force TLSv12 */
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +020010837 { "force-tlsv13", bind_parse_tls_method_options, 0 }, /* force TLSv13 */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +020010838 { "generate-certificates", bind_parse_generate_certs, 0 }, /* enable the server certificates generation */
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +020010839 { "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 +020010840 { "no-sslv3", bind_parse_tls_method_options, 0 }, /* disable SSLv3 */
10841 { "no-tlsv10", bind_parse_tls_method_options, 0 }, /* disable TLSv10 */
10842 { "no-tlsv11", bind_parse_tls_method_options, 0 }, /* disable TLSv11 */
10843 { "no-tlsv12", bind_parse_tls_method_options, 0 }, /* disable TLSv12 */
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +020010844 { "no-tlsv13", bind_parse_tls_method_options, 0 }, /* disable TLSv13 */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +020010845 { "no-tls-tickets", bind_parse_no_tls_tickets, 0 }, /* disable session resumption tickets */
10846 { "ssl", bind_parse_ssl, 0 }, /* enable SSL processing */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +020010847 { "ssl-min-ver", bind_parse_tls_method_minmax, 1 }, /* minimum version */
10848 { "ssl-max-ver", bind_parse_tls_method_minmax, 1 }, /* maximum version */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +020010849 { "strict-sni", bind_parse_strict_sni, 0 }, /* refuse negotiation if sni doesn't match a certificate */
10850 { "tls-ticket-keys", bind_parse_tls_ticket_keys, 1 }, /* set file to load TLS ticket keys from */
10851 { "verify", bind_parse_verify, 1 }, /* set SSL verify method */
10852 { "npn", bind_parse_npn, 1 }, /* set NPN supported protocols */
10853 { "prefer-client-ciphers", bind_parse_pcc, 0 }, /* prefer client ciphers */
Willy Tarreau79eeafa2012-09-14 07:53:05 +020010854 { NULL, NULL, 0 },
10855}};
Emeric Brun46591952012-05-18 15:47:34 +020010856
Willy Tarreau0108d902018-11-25 19:14:37 +010010857INITCALL1(STG_REGISTER, bind_register_keywords, &bind_kws);
10858
Willy Tarreau92faadf2012-10-10 23:04:25 +020010859/* Note: must not be declared <const> as its list will be overwritten.
10860 * Please take care of keeping this list alphabetically sorted, doing so helps
10861 * all code contributors.
10862 * Optional keywords are also declared with a NULL ->parse() function so that
10863 * the config parser can report an appropriate error when a known keyword was
10864 * not enabled.
10865 */
10866static struct srv_kw_list srv_kws = { "SSL", { }, {
Olivier Houchard522eea72017-11-03 16:27:47 +010010867 { "allow-0rtt", srv_parse_allow_0rtt, 0, 1 }, /* Allow using early data on this server */
Olivier Houchardc7566002018-11-20 23:33:50 +010010868 { "alpn", srv_parse_alpn, 1, 1 }, /* Set ALPN supported protocols */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +020010869 { "ca-file", srv_parse_ca_file, 1, 1 }, /* set CAfile to process verify server cert */
Olivier Houchard92150142018-12-21 19:47:01 +010010870 { "check-alpn", srv_parse_alpn, 1, 1 }, /* Set ALPN used for checks */
Olivier Houchard9130a962017-10-17 17:33:43 +020010871 { "check-sni", srv_parse_check_sni, 1, 1 }, /* set SNI */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +020010872 { "check-ssl", srv_parse_check_ssl, 0, 1 }, /* enable SSL for health checks */
10873 { "ciphers", srv_parse_ciphers, 1, 1 }, /* select the cipher suite */
Emmanuel Hocdet839af572019-05-14 16:27:35 +020010874#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +020010875 { "ciphersuites", srv_parse_ciphersuites, 1, 1 }, /* select the cipher suite */
10876#endif
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +020010877 { "crl-file", srv_parse_crl_file, 1, 1 }, /* set certificate revocation list file use on server cert verify */
10878 { "crt", srv_parse_crt, 1, 1 }, /* set client certificate */
10879 { "force-sslv3", srv_parse_tls_method_options, 0, 1 }, /* force SSLv3 */
10880 { "force-tlsv10", srv_parse_tls_method_options, 0, 1 }, /* force TLSv10 */
10881 { "force-tlsv11", srv_parse_tls_method_options, 0, 1 }, /* force TLSv11 */
10882 { "force-tlsv12", srv_parse_tls_method_options, 0, 1 }, /* force TLSv12 */
10883 { "force-tlsv13", srv_parse_tls_method_options, 0, 1 }, /* force TLSv13 */
10884 { "no-check-ssl", srv_parse_no_check_ssl, 0, 1 }, /* disable SSL for health checks */
10885 { "no-send-proxy-v2-ssl", srv_parse_no_send_proxy_ssl, 0, 1 }, /* do not send PROXY protocol header v2 with SSL info */
10886 { "no-send-proxy-v2-ssl-cn", srv_parse_no_send_proxy_cn, 0, 1 }, /* do not send PROXY protocol header v2 with CN */
10887 { "no-ssl", srv_parse_no_ssl, 0, 1 }, /* disable SSL processing */
10888 { "no-ssl-reuse", srv_parse_no_ssl_reuse, 0, 1 }, /* disable session reuse */
10889 { "no-sslv3", srv_parse_tls_method_options, 0, 0 }, /* disable SSLv3 */
10890 { "no-tlsv10", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv10 */
10891 { "no-tlsv11", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv11 */
10892 { "no-tlsv12", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv12 */
10893 { "no-tlsv13", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv13 */
10894 { "no-tls-tickets", srv_parse_no_tls_tickets, 0, 1 }, /* disable session resumption tickets */
Olivier Houchardc7566002018-11-20 23:33:50 +010010895 { "npn", srv_parse_npn, 1, 1 }, /* Set NPN supported protocols */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +020010896 { "send-proxy-v2-ssl", srv_parse_send_proxy_ssl, 0, 1 }, /* send PROXY protocol header v2 with SSL info */
10897 { "send-proxy-v2-ssl-cn", srv_parse_send_proxy_cn, 0, 1 }, /* send PROXY protocol header v2 with CN */
10898 { "sni", srv_parse_sni, 1, 1 }, /* send SNI extension */
10899 { "ssl", srv_parse_ssl, 0, 1 }, /* enable SSL processing */
10900 { "ssl-min-ver", srv_parse_tls_method_minmax, 1, 1 }, /* minimum version */
10901 { "ssl-max-ver", srv_parse_tls_method_minmax, 1, 1 }, /* maximum version */
10902 { "ssl-reuse", srv_parse_ssl_reuse, 0, 1 }, /* enable session reuse */
10903 { "tls-tickets", srv_parse_tls_tickets, 0, 1 }, /* enable session resumption tickets */
10904 { "verify", srv_parse_verify, 1, 1 }, /* set SSL verify method */
10905 { "verifyhost", srv_parse_verifyhost, 1, 1 }, /* require that SSL cert verifies for hostname */
Willy Tarreau92faadf2012-10-10 23:04:25 +020010906 { NULL, NULL, 0, 0 },
10907}};
10908
Willy Tarreau0108d902018-11-25 19:14:37 +010010909INITCALL1(STG_REGISTER, srv_register_keywords, &srv_kws);
10910
Emeric Brun2c86cbf2014-10-30 15:56:50 +010010911static struct cfg_kw_list cfg_kws = {ILH, {
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +010010912 { CFG_GLOBAL, "ca-base", ssl_parse_global_ca_crt_base },
10913 { CFG_GLOBAL, "crt-base", ssl_parse_global_ca_crt_base },
Willy Tarreau0bea58d2016-12-21 23:17:25 +010010914 { CFG_GLOBAL, "maxsslconn", ssl_parse_global_int },
Emeric Brun2c86cbf2014-10-30 15:56:50 +010010915 { CFG_GLOBAL, "ssl-default-bind-options", ssl_parse_default_bind_options },
10916 { CFG_GLOBAL, "ssl-default-server-options", ssl_parse_default_server_options },
Willy Tarreau14e36a12016-12-21 23:28:13 +010010917#ifndef OPENSSL_NO_DH
10918 { CFG_GLOBAL, "ssl-dh-param-file", ssl_parse_global_dh_param_file },
10919#endif
Grant Zhangfa6c7ee2017-01-14 01:42:15 +000010920 { CFG_GLOBAL, "ssl-mode-async", ssl_parse_global_ssl_async },
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020010921#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +000010922 { CFG_GLOBAL, "ssl-engine", ssl_parse_global_ssl_engine },
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020010923#endif
Willy Tarreau9ceda382016-12-21 23:13:03 +010010924 { CFG_GLOBAL, "tune.ssl.cachesize", ssl_parse_global_int },
10925#ifndef OPENSSL_NO_DH
10926 { CFG_GLOBAL, "tune.ssl.default-dh-param", ssl_parse_global_default_dh },
10927#endif
10928 { CFG_GLOBAL, "tune.ssl.force-private-cache", ssl_parse_global_private_cache },
10929 { CFG_GLOBAL, "tune.ssl.lifetime", ssl_parse_global_lifetime },
10930 { CFG_GLOBAL, "tune.ssl.maxrecord", ssl_parse_global_int },
10931 { CFG_GLOBAL, "tune.ssl.ssl-ctx-cache-size", ssl_parse_global_int },
Thierry FOURNIER5bf77322017-02-25 12:45:22 +010010932 { CFG_GLOBAL, "tune.ssl.capture-cipherlist-size", ssl_parse_global_capture_cipherlist },
Willy Tarreauf22e9682016-12-21 23:23:19 +010010933 { CFG_GLOBAL, "ssl-default-bind-ciphers", ssl_parse_global_ciphers },
10934 { CFG_GLOBAL, "ssl-default-server-ciphers", ssl_parse_global_ciphers },
Emmanuel Hocdet839af572019-05-14 16:27:35 +020010935#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +020010936 { CFG_GLOBAL, "ssl-default-bind-ciphersuites", ssl_parse_global_ciphersuites },
10937 { CFG_GLOBAL, "ssl-default-server-ciphersuites", ssl_parse_global_ciphersuites },
10938#endif
Emeric Brun2c86cbf2014-10-30 15:56:50 +010010939 { 0, NULL, NULL },
10940}};
10941
Willy Tarreau0108d902018-11-25 19:14:37 +010010942INITCALL1(STG_REGISTER, cfg_register_keywords, &cfg_kws);
10943
Nenad Merdanovicc31499d2019-03-23 11:00:32 +010010944/* Note: must not be declared <const> as its list will be overwritten */
10945static struct sample_conv_kw_list conv_kws = {ILH, {
Willy Tarreau86a394e2019-05-09 14:15:32 +020010946#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000100fL)
Nenad Merdanovicc31499d2019-03-23 11:00:32 +010010947 { "aes_gcm_dec", sample_conv_aes_gcm_dec, ARG4(4,SINT,STR,STR,STR), check_aes_gcm, SMP_T_BIN, SMP_T_BIN },
10948#endif
10949 { NULL, NULL, 0, 0, 0 },
10950}};
10951
10952INITCALL1(STG_REGISTER, sample_register_convs, &conv_kws);
10953
Willy Tarreauf7bc57c2012-10-03 00:19:48 +020010954/* transport-layer operations for SSL sockets */
Willy Tarreaud9f5cca2016-12-22 21:08:52 +010010955static struct xprt_ops ssl_sock = {
Emeric Brun46591952012-05-18 15:47:34 +020010956 .snd_buf = ssl_sock_from_buf,
10957 .rcv_buf = ssl_sock_to_buf,
Olivier Houcharddf357842019-03-21 16:30:07 +010010958 .subscribe = ssl_subscribe,
10959 .unsubscribe = ssl_unsubscribe,
Olivier Houchard5149b592019-05-23 17:47:36 +020010960 .remove_xprt = ssl_remove_xprt,
Olivier Houchard2e055482019-05-27 19:50:12 +020010961 .add_xprt = ssl_add_xprt,
Emeric Brun46591952012-05-18 15:47:34 +020010962 .rcv_pipe = NULL,
10963 .snd_pipe = NULL,
10964 .shutr = NULL,
10965 .shutw = ssl_sock_shutw,
10966 .close = ssl_sock_close,
10967 .init = ssl_sock_init,
Willy Tarreau55d37912016-12-21 23:38:39 +010010968 .prepare_bind_conf = ssl_sock_prepare_bind_conf,
Willy Tarreau795cdab2016-12-22 17:30:54 +010010969 .destroy_bind_conf = ssl_sock_destroy_bind_conf,
Willy Tarreau17d45382016-12-22 21:16:08 +010010970 .prepare_srv = ssl_sock_prepare_srv_ctx,
10971 .destroy_srv = ssl_sock_free_srv_ctx,
Willy Tarreau8743f7e2016-12-04 18:44:29 +010010972 .get_alpn = ssl_sock_get_alpn,
Willy Tarreau8e0bb0a2016-11-24 16:58:12 +010010973 .name = "SSL",
Emeric Brun46591952012-05-18 15:47:34 +020010974};
10975
Olivier Houchardccaa7de2017-10-02 11:51:03 +020010976enum act_return ssl_action_wait_for_hs(struct act_rule *rule, struct proxy *px,
10977 struct session *sess, struct stream *s, int flags)
10978{
10979 struct connection *conn;
Olivier Houchard6fa63d92017-11-27 18:41:32 +010010980 struct conn_stream *cs;
Olivier Houchardccaa7de2017-10-02 11:51:03 +020010981
10982 conn = objt_conn(sess->origin);
Olivier Houchard6fa63d92017-11-27 18:41:32 +010010983 cs = objt_cs(s->si[0].end);
Olivier Houchardccaa7de2017-10-02 11:51:03 +020010984
Olivier Houchard6fa63d92017-11-27 18:41:32 +010010985 if (conn && cs) {
Olivier Houchardccaa7de2017-10-02 11:51:03 +020010986 if (conn->flags & (CO_FL_EARLY_SSL_HS | CO_FL_SSL_WAIT_HS)) {
Olivier Houchard6fa63d92017-11-27 18:41:32 +010010987 cs->flags |= CS_FL_WAIT_FOR_HS;
Olivier Houchardccaa7de2017-10-02 11:51:03 +020010988 s->req.flags |= CF_READ_NULL;
10989 return ACT_RET_YIELD;
10990 }
10991 }
10992 return (ACT_RET_CONT);
10993}
10994
10995static enum act_parse_ret ssl_parse_wait_for_hs(const char **args, int *orig_arg, struct proxy *px, struct act_rule *rule, char **err)
10996{
10997 rule->action_ptr = ssl_action_wait_for_hs;
10998
10999 return ACT_RET_PRS_OK;
11000}
11001
11002static struct action_kw_list http_req_actions = {ILH, {
11003 { "wait-for-handshake", ssl_parse_wait_for_hs },
11004 { /* END */ }
11005}};
11006
Willy Tarreau0108d902018-11-25 19:14:37 +010011007INITCALL1(STG_REGISTER, http_req_keywords_register, &http_req_actions);
11008
Willy Tarreau5db847a2019-05-09 14:13:35 +020011009#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +010011010
11011static void ssl_sock_sctl_free_func(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, long argl, void *argp)
11012{
11013 if (ptr) {
11014 chunk_destroy(ptr);
11015 free(ptr);
11016 }
11017}
11018
11019#endif
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +010011020static void ssl_sock_capture_free_func(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, long argl, void *argp)
11021{
Willy Tarreaubafbe012017-11-24 17:34:44 +010011022 pool_free(pool_head_ssl_capture, ptr);
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +010011023}
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +010011024
Emeric Brun46591952012-05-18 15:47:34 +020011025__attribute__((constructor))
Willy Tarreau92faadf2012-10-10 23:04:25 +020011026static void __ssl_sock_init(void)
11027{
Ilya Shipitsin0590f442019-05-25 19:30:50 +050011028#if (!defined(OPENSSL_NO_COMP) && !defined(SSL_OP_NO_COMPRESSION))
Emeric Brun46591952012-05-18 15:47:34 +020011029 STACK_OF(SSL_COMP)* cm;
Ilya Shipitsine242f3d2019-05-25 03:38:14 +050011030 int n;
Ilya Shipitsin0590f442019-05-25 19:30:50 +050011031#endif
Emeric Brun46591952012-05-18 15:47:34 +020011032
Willy Tarreauef934602016-12-22 23:12:01 +010011033 if (global_ssl.listen_default_ciphers)
11034 global_ssl.listen_default_ciphers = strdup(global_ssl.listen_default_ciphers);
11035 if (global_ssl.connect_default_ciphers)
11036 global_ssl.connect_default_ciphers = strdup(global_ssl.connect_default_ciphers);
Emmanuel Hocdet839af572019-05-14 16:27:35 +020011037#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +020011038 if (global_ssl.listen_default_ciphersuites)
11039 global_ssl.listen_default_ciphersuites = strdup(global_ssl.listen_default_ciphersuites);
11040 if (global_ssl.connect_default_ciphersuites)
11041 global_ssl.connect_default_ciphersuites = strdup(global_ssl.connect_default_ciphersuites);
11042#endif
Willy Tarreau610f04b2014-02-13 11:36:41 +010011043
Willy Tarreau13e14102016-12-22 20:25:26 +010011044 xprt_register(XPRT_SSL, &ssl_sock);
Willy Tarreau9a1ab082019-05-09 13:26:41 +020011045#if HA_OPENSSL_VERSION_NUMBER < 0x10100000L
Emeric Brun46591952012-05-18 15:47:34 +020011046 SSL_library_init();
Rosen Penev68185952018-12-14 08:47:02 -080011047#endif
Ilya Shipitsin0590f442019-05-25 19:30:50 +050011048#if (!defined(OPENSSL_NO_COMP) && !defined(SSL_OP_NO_COMPRESSION))
Emeric Brun46591952012-05-18 15:47:34 +020011049 cm = SSL_COMP_get_compression_methods();
Ilya Shipitsine242f3d2019-05-25 03:38:14 +050011050 n = sk_SSL_COMP_num(cm);
11051 while (n--) {
11052 (void) sk_SSL_COMP_pop(cm);
11053 }
Ilya Shipitsin0590f442019-05-25 19:30:50 +050011054#endif
Ilya Shipitsine242f3d2019-05-25 03:38:14 +050011055
Willy Tarreau5db847a2019-05-09 14:13:35 +020011056#if defined(USE_THREAD) && (HA_OPENSSL_VERSION_NUMBER < 0x10100000L)
Emeric Brun821bb9b2017-06-15 16:37:39 +020011057 ssl_locking_init();
11058#endif
Willy Tarreau5db847a2019-05-09 14:13:35 +020011059#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +010011060 sctl_ex_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, ssl_sock_sctl_free_func);
11061#endif
Thierry FOURNIER28962c92018-06-17 21:37:05 +020011062 ssl_app_data_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL);
Thierry FOURNIER16ff0502018-06-17 21:33:01 +020011063 ssl_capture_ptr_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, ssl_sock_capture_free_func);
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020011064#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +000011065 ENGINE_load_builtin_engines();
Grant Zhangfa6c7ee2017-01-14 01:42:15 +000011066 hap_register_post_check(ssl_check_async_engine_count);
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020011067#endif
Willy Tarreaud1c57502016-12-22 22:46:15 +010011068#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
11069 hap_register_post_check(tlskeys_finalize_config);
11070#endif
Willy Tarreau80713382018-11-26 10:19:54 +010011071
11072 global.ssl_session_max_cost = SSL_SESSION_MAX_COST;
11073 global.ssl_handshake_max_cost = SSL_HANDSHAKE_MAX_COST;
11074
11075#ifndef OPENSSL_NO_DH
11076 ssl_dh_ptr_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, NULL);
11077 hap_register_post_deinit(ssl_free_dh);
11078#endif
11079#ifndef OPENSSL_NO_ENGINE
11080 hap_register_post_deinit(ssl_free_engines);
11081#endif
11082 /* Load SSL string for the verbose & debug mode. */
11083 ERR_load_SSL_strings();
Olivier Houcharda8955d52019-04-07 22:00:38 +020011084 ha_meth = BIO_meth_new(0x666, "ha methods");
11085 BIO_meth_set_write(ha_meth, ha_ssl_write);
11086 BIO_meth_set_read(ha_meth, ha_ssl_read);
11087 BIO_meth_set_ctrl(ha_meth, ha_ssl_ctrl);
11088 BIO_meth_set_create(ha_meth, ha_ssl_new);
11089 BIO_meth_set_destroy(ha_meth, ha_ssl_free);
11090 BIO_meth_set_puts(ha_meth, ha_ssl_puts);
11091 BIO_meth_set_gets(ha_meth, ha_ssl_gets);
William Lallemand150bfa82019-09-19 17:12:49 +020011092
11093 HA_SPIN_INIT(&ckch_lock);
Willy Tarreau80713382018-11-26 10:19:54 +010011094}
Willy Tarreaud92aa5c2015-01-15 21:34:39 +010011095
Willy Tarreau80713382018-11-26 10:19:54 +010011096/* Compute and register the version string */
11097static void ssl_register_build_options()
11098{
11099 char *ptr = NULL;
11100 int i;
11101
Willy Tarreauc2c0b612016-12-21 19:23:20 +010011102 memprintf(&ptr, "Built with OpenSSL version : "
11103#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet50e25e12017-03-24 15:20:03 +010011104 "BoringSSL");
Willy Tarreauc2c0b612016-12-21 19:23:20 +010011105#else /* OPENSSL_IS_BORINGSSL */
11106 OPENSSL_VERSION_TEXT
11107 "\nRunning on OpenSSL version : %s%s",
Rosen Penev68185952018-12-14 08:47:02 -080011108 OpenSSL_version(OPENSSL_VERSION),
Willy Tarreau1d158ab2019-05-09 13:41:45 +020011109 ((OPENSSL_VERSION_NUMBER ^ OpenSSL_version_num()) >> 8) ? " (VERSIONS DIFFER!)" : "");
Willy Tarreauc2c0b612016-12-21 19:23:20 +010011110#endif
11111 memprintf(&ptr, "%s\nOpenSSL library supports TLS extensions : "
Willy Tarreau9a1ab082019-05-09 13:26:41 +020011112#if HA_OPENSSL_VERSION_NUMBER < 0x00907000L
Willy Tarreauc2c0b612016-12-21 19:23:20 +010011113 "no (library version too old)"
11114#elif defined(OPENSSL_NO_TLSEXT)
11115 "no (disabled via OPENSSL_NO_TLSEXT)"
11116#else
11117 "yes"
11118#endif
11119 "", ptr);
11120
11121 memprintf(&ptr, "%s\nOpenSSL library supports SNI : "
11122#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
11123 "yes"
11124#else
11125#ifdef OPENSSL_NO_TLSEXT
11126 "no (because of OPENSSL_NO_TLSEXT)"
11127#else
11128 "no (version might be too old, 0.9.8f min needed)"
11129#endif
11130#endif
11131 "", ptr);
11132
Emmanuel Hocdetf80bc242017-07-12 14:25:38 +020011133 memprintf(&ptr, "%s\nOpenSSL library supports :", ptr);
11134 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
11135 if (methodVersions[i].option)
11136 memprintf(&ptr, "%s %s", ptr, methodVersions[i].name);
Emmanuel Hocdet50e25e12017-03-24 15:20:03 +010011137
Willy Tarreauc2c0b612016-12-21 19:23:20 +010011138 hap_register_build_opts(ptr, 1);
Willy Tarreau80713382018-11-26 10:19:54 +010011139}
Willy Tarreauc2c0b612016-12-21 19:23:20 +010011140
Willy Tarreau80713382018-11-26 10:19:54 +010011141INITCALL0(STG_REGISTER, ssl_register_build_options);
Remi Gacogne4f902b82015-05-28 16:23:00 +020011142
Emeric Brun46591952012-05-18 15:47:34 +020011143
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020011144#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +000011145void ssl_free_engines(void) {
11146 struct ssl_engine_list *wl, *wlb;
11147 /* free up engine list */
11148 list_for_each_entry_safe(wl, wlb, &openssl_engines, list) {
11149 ENGINE_finish(wl->e);
11150 ENGINE_free(wl->e);
11151 LIST_DEL(&wl->list);
11152 free(wl);
11153 }
11154}
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020011155#endif
Christopher Faulet31af49d2015-06-09 17:29:50 +020011156
Remi Gacogned3a23c32015-05-28 16:39:47 +020011157#ifndef OPENSSL_NO_DH
Grant Zhang872f9c22017-01-21 01:10:18 +000011158void ssl_free_dh(void) {
11159 if (local_dh_1024) {
11160 DH_free(local_dh_1024);
11161 local_dh_1024 = NULL;
11162 }
11163 if (local_dh_2048) {
11164 DH_free(local_dh_2048);
11165 local_dh_2048 = NULL;
11166 }
11167 if (local_dh_4096) {
11168 DH_free(local_dh_4096);
11169 local_dh_4096 = NULL;
11170 }
Remi Gacogne47783ef2015-05-29 15:53:22 +020011171 if (global_dh) {
11172 DH_free(global_dh);
11173 global_dh = NULL;
11174 }
Grant Zhang872f9c22017-01-21 01:10:18 +000011175}
11176#endif
11177
11178__attribute__((destructor))
11179static void __ssl_sock_deinit(void)
11180{
11181#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Emeric Brun821bb9b2017-06-15 16:37:39 +020011182 if (ssl_ctx_lru_tree) {
11183 lru64_destroy(ssl_ctx_lru_tree);
Christopher Faulet2a944ee2017-11-07 10:42:54 +010011184 HA_RWLOCK_DESTROY(&ssl_ctx_lru_rwlock);
Emeric Brun821bb9b2017-06-15 16:37:39 +020011185 }
Remi Gacogned3a23c32015-05-28 16:39:47 +020011186#endif
11187
Willy Tarreau5db847a2019-05-09 14:13:35 +020011188#if (HA_OPENSSL_VERSION_NUMBER < 0x10100000L)
Remi Gacogned3a23c32015-05-28 16:39:47 +020011189 ERR_remove_state(0);
11190 ERR_free_strings();
11191
11192 EVP_cleanup();
Rosen Penev68185952018-12-14 08:47:02 -080011193#endif
Remi Gacogned3a23c32015-05-28 16:39:47 +020011194
Willy Tarreau5db847a2019-05-09 14:13:35 +020011195#if (HA_OPENSSL_VERSION_NUMBER >= 0x00907000L) && (HA_OPENSSL_VERSION_NUMBER < 0x10100000L)
Remi Gacogned3a23c32015-05-28 16:39:47 +020011196 CRYPTO_cleanup_all_ex_data();
11197#endif
Olivier Houcharda8955d52019-04-07 22:00:38 +020011198 BIO_meth_free(ha_meth);
Remi Gacogned3a23c32015-05-28 16:39:47 +020011199}
11200
11201
Emeric Brun46591952012-05-18 15:47:34 +020011202/*
11203 * Local variables:
11204 * c-indent-level: 8
11205 * c-basic-offset: 8
11206 * End:
11207 */