blob: 9c0962ca4ee2dcc669b5f5df6dc67c24f3a9f18d [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
William Lallemand8b453912019-11-21 15:48:10 +01004814/*
4815 * This function applies the SSL configuration on a SSL_CTX
4816 * It returns an error code and fills the <err> buffer
4817 */
4818int ssl_sock_prepare_ctx(struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf, SSL_CTX *ctx, char **err)
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004819{
4820 struct proxy *curproxy = bind_conf->frontend;
4821 int cfgerr = 0;
4822 int verify = SSL_VERIFY_NONE;
Willy Tarreau5d4cafb2018-01-04 18:55:19 +01004823 struct ssl_bind_conf __maybe_unused *ssl_conf_cur;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004824 const char *conf_ciphers;
Emmanuel Hocdet839af572019-05-14 16:27:35 +02004825#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02004826 const char *conf_ciphersuites;
4827#endif
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004828 const char *conf_curves = NULL;
Emeric Brunfc0421f2012-09-07 17:30:07 +02004829
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02004830 if (ssl_conf) {
4831 struct tls_version_filter *conf_ssl_methods = &ssl_conf->ssl_methods;
4832 int i, min, max;
4833 int flags = MC_SSL_O_ALL;
4834
4835 /* Real min and max should be determinate with configuration and openssl's capabilities */
Emmanuel Hocdet43664762017-08-09 18:26:20 +02004836 min = conf_ssl_methods->min ? conf_ssl_methods->min : bind_conf->ssl_conf.ssl_methods.min;
4837 max = conf_ssl_methods->max ? conf_ssl_methods->max : bind_conf->ssl_conf.ssl_methods.max;
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02004838 if (min)
4839 flags |= (methodVersions[min].flag - 1);
4840 if (max)
4841 flags |= ~((methodVersions[max].flag << 1) - 1);
4842 min = max = CONF_TLSV_NONE;
4843 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
4844 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
4845 if (min)
4846 max = i;
4847 else
4848 min = max = i;
4849 }
4850 /* save real min/max */
4851 conf_ssl_methods->min = min;
4852 conf_ssl_methods->max = max;
4853 if (!min) {
William Lallemand8b453912019-11-21 15:48:10 +01004854 if (err)
4855 memprintf(err, "%sProxy '%s': all SSL/TLS versions are disabled for bind '%s' at [%s:%d].\n",
4856 *err ? *err : "", bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
4857 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02004858 }
4859 }
4860
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004861 switch ((ssl_conf && ssl_conf->verify) ? ssl_conf->verify : bind_conf->ssl_conf.verify) {
Emeric Brun850efd52014-01-29 12:24:34 +01004862 case SSL_SOCK_VERIFY_NONE:
4863 verify = SSL_VERIFY_NONE;
4864 break;
4865 case SSL_SOCK_VERIFY_OPTIONAL:
4866 verify = SSL_VERIFY_PEER;
4867 break;
4868 case SSL_SOCK_VERIFY_REQUIRED:
4869 verify = SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
4870 break;
4871 }
4872 SSL_CTX_set_verify(ctx, verify, ssl_sock_bind_verifycbk);
4873 if (verify & SSL_VERIFY_PEER) {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004874 char *ca_file = (ssl_conf && ssl_conf->ca_file) ? ssl_conf->ca_file : bind_conf->ssl_conf.ca_file;
4875 char *crl_file = (ssl_conf && ssl_conf->crl_file) ? ssl_conf->crl_file : bind_conf->ssl_conf.crl_file;
4876 if (ca_file) {
Emeric Brund94b3fe2012-09-20 18:23:56 +02004877 /* load CAfile to verify */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004878 if (!SSL_CTX_load_verify_locations(ctx, ca_file, NULL)) {
William Lallemand8b453912019-11-21 15:48:10 +01004879 if (err)
4880 memprintf(err, "%sProxy '%s': unable to load CA file '%s' for bind '%s' at [%s:%d].\n",
4881 *err ? *err : "", curproxy->id, ca_file, bind_conf->arg, bind_conf->file, bind_conf->line);
4882 cfgerr |= ERR_ALERT | ERR_FATAL;
Emeric Brund94b3fe2012-09-20 18:23:56 +02004883 }
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02004884 if (!((ssl_conf && ssl_conf->no_ca_names) || bind_conf->ssl_conf.no_ca_names)) {
4885 /* set CA names for client cert request, function returns void */
4886 SSL_CTX_set_client_CA_list(ctx, SSL_load_client_CA_file(ca_file));
4887 }
Emeric Brund94b3fe2012-09-20 18:23:56 +02004888 }
Emeric Brun850efd52014-01-29 12:24:34 +01004889 else {
William Lallemand8b453912019-11-21 15:48:10 +01004890 if (err)
4891 memprintf(err, "%sProxy '%s': verify is enabled but no CA file specified for bind '%s' at [%s:%d].\n",
4892 *err ? *err : "", curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
4893 cfgerr |= ERR_ALERT | ERR_FATAL;
Emeric Brun850efd52014-01-29 12:24:34 +01004894 }
Emeric Brun051cdab2012-10-02 19:25:50 +02004895#ifdef X509_V_FLAG_CRL_CHECK
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004896 if (crl_file) {
Emeric Brund94b3fe2012-09-20 18:23:56 +02004897 X509_STORE *store = SSL_CTX_get_cert_store(ctx);
4898
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004899 if (!store || !X509_STORE_load_locations(store, crl_file, NULL)) {
William Lallemand8b453912019-11-21 15:48:10 +01004900 if (err)
4901 memprintf(err, "%sProxy '%s': unable to configure CRL file '%s' for bind '%s' at [%s:%d].\n",
4902 *err ? *err : "", curproxy->id, crl_file, bind_conf->arg, bind_conf->file, bind_conf->line);
4903 cfgerr |= ERR_ALERT | ERR_FATAL;
Emeric Brund94b3fe2012-09-20 18:23:56 +02004904 }
Emeric Brun561e5742012-10-02 15:20:55 +02004905 else {
4906 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
4907 }
Emeric Brund94b3fe2012-09-20 18:23:56 +02004908 }
Emeric Brun051cdab2012-10-02 19:25:50 +02004909#endif
Emeric Brun644cde02012-12-14 11:21:13 +01004910 ERR_clear_error();
Emeric Brund94b3fe2012-09-20 18:23:56 +02004911 }
Nenad Merdanovic05552d42015-02-27 19:56:49 +01004912#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
Nenad Merdanovic146defa2015-05-09 08:46:00 +02004913 if(bind_conf->keys_ref) {
Nenad Merdanovic05552d42015-02-27 19:56:49 +01004914 if (!SSL_CTX_set_tlsext_ticket_key_cb(ctx, ssl_tlsext_ticket_key_cb)) {
William Lallemand8b453912019-11-21 15:48:10 +01004915 if (err)
4916 memprintf(err, "%sProxy '%s': unable to set callback for TLS ticket validation for bind '%s' at [%s:%d].\n",
4917 *err ? *err : "", curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
4918 cfgerr |= ERR_ALERT | ERR_FATAL;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01004919 }
4920 }
4921#endif
4922
William Lallemand4f45bb92017-10-30 20:08:51 +01004923 ssl_set_shctx(ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004924 conf_ciphers = (ssl_conf && ssl_conf->ciphers) ? ssl_conf->ciphers : bind_conf->ssl_conf.ciphers;
4925 if (conf_ciphers &&
4926 !SSL_CTX_set_cipher_list(ctx, conf_ciphers)) {
William Lallemand8b453912019-11-21 15:48:10 +01004927 if (err)
4928 memprintf(err, "%sProxy '%s': unable to set SSL cipher list to '%s' for bind '%s' at [%s:%d].\n",
4929 *err ? *err : "", curproxy->id, conf_ciphers, bind_conf->arg, bind_conf->file, bind_conf->line);
4930 cfgerr |= ERR_ALERT | ERR_FATAL;
Emeric Brunfc0421f2012-09-07 17:30:07 +02004931 }
4932
Emmanuel Hocdet839af572019-05-14 16:27:35 +02004933#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02004934 conf_ciphersuites = (ssl_conf && ssl_conf->ciphersuites) ? ssl_conf->ciphersuites : bind_conf->ssl_conf.ciphersuites;
4935 if (conf_ciphersuites &&
4936 !SSL_CTX_set_ciphersuites(ctx, conf_ciphersuites)) {
William Lallemand8b453912019-11-21 15:48:10 +01004937 memprintf(err, "%sProxy '%s': unable to set TLS 1.3 cipher suites to '%s' for bind '%s' at [%s:%d].\n",
4938 *err ? *err : "", curproxy->id, conf_ciphersuites, bind_conf->arg, bind_conf->file, bind_conf->line);
4939 cfgerr |= ERR_ALERT | ERR_FATAL;
Dirkjan Bussink415150f2018-09-14 11:14:21 +02004940 }
4941#endif
4942
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01004943#ifndef OPENSSL_NO_DH
Remi Gacogne47783ef2015-05-29 15:53:22 +02004944 /* If tune.ssl.default-dh-param has not been set,
4945 neither has ssl-default-dh-file and no static DH
4946 params were in the certificate file. */
Willy Tarreauef934602016-12-22 23:12:01 +01004947 if (global_ssl.default_dh_param == 0 &&
Remi Gacogne47783ef2015-05-29 15:53:22 +02004948 global_dh == NULL &&
Remi Gacogne4f902b82015-05-28 16:23:00 +02004949 (ssl_dh_ptr_index == -1 ||
4950 SSL_CTX_get_ex_data(ctx, ssl_dh_ptr_index) == NULL)) {
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01004951 STACK_OF(SSL_CIPHER) * ciphers = NULL;
4952 const SSL_CIPHER * cipher = NULL;
4953 char cipher_description[128];
4954 /* The description of ciphers using an Ephemeral Diffie Hellman key exchange
4955 contains " Kx=DH " or " Kx=DH(". Beware of " Kx=DH/",
4956 which is not ephemeral DH. */
4957 const char dhe_description[] = " Kx=DH ";
4958 const char dhe_export_description[] = " Kx=DH(";
4959 int idx = 0;
4960 int dhe_found = 0;
4961 SSL *ssl = NULL;
Lukas Tribus90132722014-08-18 00:56:33 +02004962
Remi Gacogne23d5d372014-10-10 17:04:26 +02004963 ssl = SSL_new(ctx);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004964
Remi Gacogne23d5d372014-10-10 17:04:26 +02004965 if (ssl) {
4966 ciphers = SSL_get_ciphers(ssl);
4967
4968 if (ciphers) {
4969 for (idx = 0; idx < sk_SSL_CIPHER_num(ciphers); idx++) {
4970 cipher = sk_SSL_CIPHER_value(ciphers, idx);
4971 if (SSL_CIPHER_description(cipher, cipher_description, sizeof (cipher_description)) == cipher_description) {
4972 if (strstr(cipher_description, dhe_description) != NULL ||
4973 strstr(cipher_description, dhe_export_description) != NULL) {
4974 dhe_found = 1;
4975 break;
4976 }
Remi Gacognec1eab8c2014-06-12 18:20:11 +02004977 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004978 }
4979 }
Remi Gacogne23d5d372014-10-10 17:04:26 +02004980 SSL_free(ssl);
4981 ssl = NULL;
Lukas Tribus90132722014-08-18 00:56:33 +02004982 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004983
Lukas Tribus90132722014-08-18 00:56:33 +02004984 if (dhe_found) {
William Lallemand8b453912019-11-21 15:48:10 +01004985 if (err)
4986 memprintf(err, "%sSetting 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", *err ? *err : "");
4987 cfgerr |= ERR_WARN;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004988 }
4989
Willy Tarreauef934602016-12-22 23:12:01 +01004990 global_ssl.default_dh_param = 1024;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004991 }
Remi Gacogne8de54152014-07-15 11:36:40 +02004992
Willy Tarreauef934602016-12-22 23:12:01 +01004993 if (global_ssl.default_dh_param >= 1024) {
Remi Gacogne8de54152014-07-15 11:36:40 +02004994 if (local_dh_1024 == NULL) {
4995 local_dh_1024 = ssl_get_dh_1024();
4996 }
Willy Tarreauef934602016-12-22 23:12:01 +01004997 if (global_ssl.default_dh_param >= 2048) {
Remi Gacogne8de54152014-07-15 11:36:40 +02004998 if (local_dh_2048 == NULL) {
4999 local_dh_2048 = ssl_get_dh_2048();
5000 }
Willy Tarreauef934602016-12-22 23:12:01 +01005001 if (global_ssl.default_dh_param >= 4096) {
Remi Gacogne8de54152014-07-15 11:36:40 +02005002 if (local_dh_4096 == NULL) {
5003 local_dh_4096 = ssl_get_dh_4096();
5004 }
Remi Gacogne8de54152014-07-15 11:36:40 +02005005 }
5006 }
5007 }
5008#endif /* OPENSSL_NO_DH */
Remi Gacognef46cd6e2014-06-12 14:58:40 +02005009
Emeric Brunfc0421f2012-09-07 17:30:07 +02005010 SSL_CTX_set_info_callback(ctx, ssl_sock_infocbk);
Willy Tarreau9a1ab082019-05-09 13:26:41 +02005011#if HA_OPENSSL_VERSION_NUMBER >= 0x00907000L
Emeric Brun29f037d2014-04-25 19:05:36 +02005012 SSL_CTX_set_msg_callback(ctx, ssl_sock_msgcbk);
Willy Tarreau5cbe4ef2014-05-08 22:45:11 +02005013#endif
Emeric Brun29f037d2014-04-25 19:05:36 +02005014
Bernard Spil13c53f82018-02-15 13:34:58 +01005015#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005016 ssl_conf_cur = NULL;
5017 if (ssl_conf && ssl_conf->npn_str)
5018 ssl_conf_cur = ssl_conf;
5019 else if (bind_conf->ssl_conf.npn_str)
5020 ssl_conf_cur = &bind_conf->ssl_conf;
5021 if (ssl_conf_cur)
5022 SSL_CTX_set_next_protos_advertised_cb(ctx, ssl_sock_advertise_npn_protos, ssl_conf_cur);
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02005023#endif
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01005024#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005025 ssl_conf_cur = NULL;
5026 if (ssl_conf && ssl_conf->alpn_str)
5027 ssl_conf_cur = ssl_conf;
5028 else if (bind_conf->ssl_conf.alpn_str)
5029 ssl_conf_cur = &bind_conf->ssl_conf;
5030 if (ssl_conf_cur)
5031 SSL_CTX_set_alpn_select_cb(ctx, ssl_sock_advertise_alpn_protos, ssl_conf_cur);
Willy Tarreauab861d32013-04-02 02:30:41 +02005032#endif
Willy Tarreau9a1ab082019-05-09 13:26:41 +02005033#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01005034 conf_curves = (ssl_conf && ssl_conf->curves) ? ssl_conf->curves : bind_conf->ssl_conf.curves;
5035 if (conf_curves) {
5036 if (!SSL_CTX_set1_curves_list(ctx, conf_curves)) {
William Lallemand8b453912019-11-21 15:48:10 +01005037 memprintf(err, "%sProxy '%s': unable to set SSL curves list to '%s' for bind '%s' at [%s:%d].\n",
5038 *err ? *err : "", curproxy->id, conf_curves, bind_conf->arg, bind_conf->file, bind_conf->line);
5039 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01005040 }
Emmanuel Hocdeta52bb152017-03-20 11:11:49 +01005041#if defined(SSL_CTX_set_ecdh_auto)
5042 (void)SSL_CTX_set_ecdh_auto(ctx, 1);
5043#endif
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01005044 }
5045#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02005046#if defined(SSL_CTX_set_tmp_ecdh) && !defined(OPENSSL_NO_ECDH)
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01005047 if (!conf_curves) {
Emeric Brun2b58d042012-09-20 17:10:03 +02005048 int i;
5049 EC_KEY *ecdh;
Willy Tarreau9a1ab082019-05-09 13:26:41 +02005050#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005051 const char *ecdhe = (ssl_conf && ssl_conf->ecdhe) ? ssl_conf->ecdhe :
Olivier Houchardc2aae742017-09-22 18:26:28 +02005052 (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe :
5053 NULL);
5054
5055 if (ecdhe == NULL) {
Eric Salama3c8bde82019-11-20 11:33:40 +01005056 (void)SSL_CTX_set_ecdh_auto(ctx, 1);
Olivier Houchardc2aae742017-09-22 18:26:28 +02005057 return cfgerr;
5058 }
5059#else
5060 const char *ecdhe = (ssl_conf && ssl_conf->ecdhe) ? ssl_conf->ecdhe :
5061 (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe :
5062 ECDHE_DEFAULT_CURVE);
5063#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02005064
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005065 i = OBJ_sn2nid(ecdhe);
Emeric Brun2b58d042012-09-20 17:10:03 +02005066 if (!i || ((ecdh = EC_KEY_new_by_curve_name(i)) == NULL)) {
William Lallemand8b453912019-11-21 15:48:10 +01005067 memprintf(err, "%sProxy '%s': unable to set elliptic named curve to '%s' for bind '%s' at [%s:%d].\n",
5068 *err ? *err : "", curproxy->id, ecdhe, bind_conf->arg, bind_conf->file, bind_conf->line);
5069 cfgerr |= ERR_ALERT | ERR_FATAL;
Emeric Brun2b58d042012-09-20 17:10:03 +02005070 }
5071 else {
5072 SSL_CTX_set_tmp_ecdh(ctx, ecdh);
5073 EC_KEY_free(ecdh);
5074 }
5075 }
5076#endif
5077
Emeric Brunfc0421f2012-09-07 17:30:07 +02005078 return cfgerr;
5079}
5080
Evan Broderbe554312013-06-27 00:05:25 -07005081static int ssl_sock_srv_hostcheck(const char *pattern, const char *hostname)
5082{
5083 const char *pattern_wildcard, *pattern_left_label_end, *hostname_left_label_end;
5084 size_t prefixlen, suffixlen;
5085
5086 /* Trivial case */
5087 if (strcmp(pattern, hostname) == 0)
5088 return 1;
5089
Evan Broderbe554312013-06-27 00:05:25 -07005090 /* The rest of this logic is based on RFC 6125, section 6.4.3
5091 * (http://tools.ietf.org/html/rfc6125#section-6.4.3) */
5092
Emeric Bruna848dae2013-10-08 11:27:28 +02005093 pattern_wildcard = NULL;
5094 pattern_left_label_end = pattern;
5095 while (*pattern_left_label_end != '.') {
5096 switch (*pattern_left_label_end) {
5097 case 0:
5098 /* End of label not found */
5099 return 0;
5100 case '*':
5101 /* If there is more than one wildcards */
5102 if (pattern_wildcard)
5103 return 0;
5104 pattern_wildcard = pattern_left_label_end;
5105 break;
5106 }
5107 pattern_left_label_end++;
5108 }
5109
5110 /* If it's not trivial and there is no wildcard, it can't
5111 * match */
5112 if (!pattern_wildcard)
Evan Broderbe554312013-06-27 00:05:25 -07005113 return 0;
5114
5115 /* Make sure all labels match except the leftmost */
5116 hostname_left_label_end = strchr(hostname, '.');
5117 if (!hostname_left_label_end
5118 || strcmp(pattern_left_label_end, hostname_left_label_end) != 0)
5119 return 0;
5120
5121 /* Make sure the leftmost label of the hostname is long enough
5122 * that the wildcard can match */
Emeric Brun369da852013-10-08 11:39:35 +02005123 if (hostname_left_label_end - hostname < (pattern_left_label_end - pattern) - 1)
Evan Broderbe554312013-06-27 00:05:25 -07005124 return 0;
5125
5126 /* Finally compare the string on either side of the
5127 * wildcard */
5128 prefixlen = pattern_wildcard - pattern;
5129 suffixlen = pattern_left_label_end - (pattern_wildcard + 1);
Emeric Bruna848dae2013-10-08 11:27:28 +02005130 if ((prefixlen && (memcmp(pattern, hostname, prefixlen) != 0))
5131 || (suffixlen && (memcmp(pattern_wildcard + 1, hostname_left_label_end - suffixlen, suffixlen) != 0)))
Evan Broderbe554312013-06-27 00:05:25 -07005132 return 0;
5133
5134 return 1;
5135}
5136
5137static int ssl_sock_srv_verifycbk(int ok, X509_STORE_CTX *ctx)
5138{
5139 SSL *ssl;
5140 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01005141 struct ssl_sock_ctx *ssl_ctx;
Willy Tarreau2ab88672017-07-05 18:23:03 +02005142 const char *servername;
Willy Tarreau71d058c2017-07-26 20:09:56 +02005143 const char *sni;
Evan Broderbe554312013-06-27 00:05:25 -07005144
5145 int depth;
5146 X509 *cert;
5147 STACK_OF(GENERAL_NAME) *alt_names;
5148 int i;
5149 X509_NAME *cert_subject;
5150 char *str;
5151
5152 if (ok == 0)
5153 return ok;
5154
5155 ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
Thierry FOURNIER28962c92018-06-17 21:37:05 +02005156 conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Olivier Houchard66ab4982019-02-26 18:37:15 +01005157 ssl_ctx = conn->xprt_ctx;
Evan Broderbe554312013-06-27 00:05:25 -07005158
Willy Tarreauad92a9a2017-07-28 11:38:41 +02005159 /* We're checking if the provided hostnames match the desired one. The
5160 * desired hostname comes from the SNI we presented if any, or if not
5161 * provided then it may have been explicitly stated using a "verifyhost"
5162 * directive. If neither is set, we don't care about the name so the
5163 * verification is OK.
Willy Tarreau2ab88672017-07-05 18:23:03 +02005164 */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005165 servername = SSL_get_servername(ssl_ctx->ssl, TLSEXT_NAMETYPE_host_name);
Willy Tarreau71d058c2017-07-26 20:09:56 +02005166 sni = servername;
Willy Tarreau2ab88672017-07-05 18:23:03 +02005167 if (!servername) {
Willy Tarreau07d94e42018-09-20 10:57:52 +02005168 servername = __objt_server(conn->target)->ssl_ctx.verify_host;
Willy Tarreau2ab88672017-07-05 18:23:03 +02005169 if (!servername)
5170 return ok;
5171 }
Evan Broderbe554312013-06-27 00:05:25 -07005172
5173 /* We only need to verify the CN on the actual server cert,
5174 * not the indirect CAs */
5175 depth = X509_STORE_CTX_get_error_depth(ctx);
5176 if (depth != 0)
5177 return ok;
5178
5179 /* At this point, the cert is *not* OK unless we can find a
5180 * hostname match */
5181 ok = 0;
5182
5183 cert = X509_STORE_CTX_get_current_cert(ctx);
5184 /* It seems like this might happen if verify peer isn't set */
5185 if (!cert)
5186 return ok;
5187
5188 alt_names = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
5189 if (alt_names) {
5190 for (i = 0; !ok && i < sk_GENERAL_NAME_num(alt_names); i++) {
5191 GENERAL_NAME *name = sk_GENERAL_NAME_value(alt_names, i);
5192 if (name->type == GEN_DNS) {
Willy Tarreau9a1ab082019-05-09 13:26:41 +02005193#if HA_OPENSSL_VERSION_NUMBER < 0x00907000L
Emeric Bruna33410c2013-09-17 15:47:48 +02005194 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.ia5) >= 0) {
5195#else
Evan Broderbe554312013-06-27 00:05:25 -07005196 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
Emeric Bruna33410c2013-09-17 15:47:48 +02005197#endif
Evan Broderbe554312013-06-27 00:05:25 -07005198 ok = ssl_sock_srv_hostcheck(str, servername);
5199 OPENSSL_free(str);
5200 }
5201 }
5202 }
Emeric Brun4ad50a42013-09-17 15:19:54 +02005203 sk_GENERAL_NAME_pop_free(alt_names, GENERAL_NAME_free);
Evan Broderbe554312013-06-27 00:05:25 -07005204 }
5205
5206 cert_subject = X509_get_subject_name(cert);
5207 i = -1;
5208 while (!ok && (i = X509_NAME_get_index_by_NID(cert_subject, NID_commonName, i)) != -1) {
5209 X509_NAME_ENTRY *entry = X509_NAME_get_entry(cert_subject, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005210 ASN1_STRING *value;
5211 value = X509_NAME_ENTRY_get_data(entry);
5212 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
Evan Broderbe554312013-06-27 00:05:25 -07005213 ok = ssl_sock_srv_hostcheck(str, servername);
5214 OPENSSL_free(str);
5215 }
5216 }
5217
Willy Tarreau71d058c2017-07-26 20:09:56 +02005218 /* report the mismatch and indicate if SNI was used or not */
5219 if (!ok && !conn->err_code)
5220 conn->err_code = sni ? CO_ER_SSL_MISMATCH_SNI : CO_ER_SSL_MISMATCH;
Evan Broderbe554312013-06-27 00:05:25 -07005221 return ok;
5222}
5223
Emeric Brun94324a42012-10-11 14:00:19 +02005224/* prepare ssl context from servers options. Returns an error count */
Willy Tarreau03209342016-12-22 17:08:28 +01005225int ssl_sock_prepare_srv_ctx(struct server *srv)
Emeric Brun94324a42012-10-11 14:00:19 +02005226{
Willy Tarreau03209342016-12-22 17:08:28 +01005227 struct proxy *curproxy = srv->proxy;
Emeric Brun94324a42012-10-11 14:00:19 +02005228 int cfgerr = 0;
Remi Gacogneaf5c3da2014-05-19 10:29:58 +02005229 long options =
Emeric Brun94324a42012-10-11 14:00:19 +02005230 SSL_OP_ALL | /* all known workarounds for bugs */
5231 SSL_OP_NO_SSLv2 |
5232 SSL_OP_NO_COMPRESSION;
Remi Gacogneaf5c3da2014-05-19 10:29:58 +02005233 long mode =
Emeric Brun94324a42012-10-11 14:00:19 +02005234 SSL_MODE_ENABLE_PARTIAL_WRITE |
5235 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
Willy Tarreau396a1862014-11-13 14:06:52 +01005236 SSL_MODE_RELEASE_BUFFERS |
5237 SSL_MODE_SMALL_BUFFERS;
Emeric Brun850efd52014-01-29 12:24:34 +01005238 int verify = SSL_VERIFY_NONE;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01005239 SSL_CTX *ctx = NULL;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005240 struct tls_version_filter *conf_ssl_methods = &srv->ssl_ctx.methods;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005241 int i, min, max, hole;
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005242 int flags = MC_SSL_O_ALL;
Emeric Brun94324a42012-10-11 14:00:19 +02005243
Thierry Fournier383085f2013-01-24 14:15:43 +01005244 /* Make sure openssl opens /dev/urandom before the chroot */
5245 if (!ssl_initialize_random()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005246 ha_alert("OpenSSL random data generator initialization failed.\n");
Thierry Fournier383085f2013-01-24 14:15:43 +01005247 cfgerr++;
5248 }
5249
Willy Tarreaufce03112015-01-15 21:32:40 +01005250 /* Automatic memory computations need to know we use SSL there */
5251 global.ssl_used_backend = 1;
5252
5253 /* Initiate SSL context for current server */
Emeric Brun821bb9b2017-06-15 16:37:39 +02005254 if (!srv->ssl_ctx.reused_sess) {
Olivier Houcharde6060c52017-11-16 17:42:52 +01005255 if ((srv->ssl_ctx.reused_sess = calloc(1, global.nbthread*sizeof(*srv->ssl_ctx.reused_sess))) == NULL) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005256 ha_alert("Proxy '%s', server '%s' [%s:%d] out of memory.\n",
5257 curproxy->id, srv->id,
5258 srv->conf.file, srv->conf.line);
Emeric Brun821bb9b2017-06-15 16:37:39 +02005259 cfgerr++;
5260 return cfgerr;
5261 }
5262 }
Emeric Brun94324a42012-10-11 14:00:19 +02005263 if (srv->use_ssl)
5264 srv->xprt = &ssl_sock;
5265 if (srv->check.use_ssl)
Cyril Bonté9ce13112014-11-15 22:41:27 +01005266 srv->check.xprt = &ssl_sock;
Emeric Brun94324a42012-10-11 14:00:19 +02005267
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005268 ctx = SSL_CTX_new(SSLv23_client_method());
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01005269 if (!ctx) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005270 ha_alert("config : %s '%s', server '%s': unable to allocate ssl context.\n",
5271 proxy_type_str(curproxy), curproxy->id,
5272 srv->id);
Emeric Brun94324a42012-10-11 14:00:19 +02005273 cfgerr++;
5274 return cfgerr;
5275 }
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005276
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005277 if (conf_ssl_methods->flags && (conf_ssl_methods->min || conf_ssl_methods->max))
Christopher Faulet767a84b2017-11-24 16:50:31 +01005278 ha_warning("config : %s '%s': no-sslv3/no-tlsv1x are ignored for server '%s'. "
5279 "Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
5280 proxy_type_str(curproxy), curproxy->id, srv->id);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005281 else
5282 flags = conf_ssl_methods->flags;
5283
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005284 /* Real min and max should be determinate with configuration and openssl's capabilities */
5285 if (conf_ssl_methods->min)
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005286 flags |= (methodVersions[conf_ssl_methods->min].flag - 1);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005287 if (conf_ssl_methods->max)
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005288 flags |= ~((methodVersions[conf_ssl_methods->max].flag << 1) - 1);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005289
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02005290 /* find min, max and holes */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005291 min = max = CONF_TLSV_NONE;
5292 hole = 0;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005293 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005294 /* version is in openssl && version not disable in configuration */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005295 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005296 if (min) {
5297 if (hole) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005298 ha_warning("config : %s '%s': SSL/TLS versions range not contiguous for server '%s'. "
5299 "Hole find for %s. Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
5300 proxy_type_str(curproxy), curproxy->id, srv->id,
5301 methodVersions[hole].name);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005302 hole = 0;
5303 }
5304 max = i;
5305 }
5306 else {
5307 min = max = i;
5308 }
5309 }
5310 else {
5311 if (min)
5312 hole = i;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005313 }
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005314 if (!min) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005315 ha_alert("config : %s '%s': all SSL/TLS versions are disabled for server '%s'.\n",
5316 proxy_type_str(curproxy), curproxy->id, srv->id);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005317 cfgerr += 1;
5318 }
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005319
Willy Tarreau9a1ab082019-05-09 13:26:41 +02005320#if (HA_OPENSSL_VERSION_NUMBER < 0x1010000fL)
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005321 /* Keep force-xxx implementation as it is in older haproxy. It's a
Joseph Herlant017b3da2018-11-15 09:07:59 -08005322 precautionary measure to avoid any surprise with older openssl version. */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005323 if (min == max)
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02005324 methodVersions[min].ctx_set_version(ctx, SET_CLIENT);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005325 else
5326 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
5327 if (flags & methodVersions[i].flag)
5328 options |= methodVersions[i].option;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005329#else /* openssl >= 1.1.0 */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005330 /* set the max_version is required to cap TLS version or activate new TLS (v1.3) */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02005331 methodVersions[min].ctx_set_version(ctx, SET_MIN);
5332 methodVersions[max].ctx_set_version(ctx, SET_MAX);
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005333#endif
5334
5335 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLS_TICKETS)
5336 options |= SSL_OP_NO_TICKET;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01005337 SSL_CTX_set_options(ctx, options);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005338
Willy Tarreau5db847a2019-05-09 14:13:35 +02005339#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005340 if (global_ssl.async)
5341 mode |= SSL_MODE_ASYNC;
5342#endif
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01005343 SSL_CTX_set_mode(ctx, mode);
5344 srv->ssl_ctx.ctx = ctx;
5345
Emeric Bruna7aa3092012-10-26 12:58:00 +02005346 if (srv->ssl_ctx.client_crt) {
5347 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 +01005348 ha_alert("config : %s '%s', server '%s': unable to load SSL private key 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 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 +01005354 ha_alert("config : %s '%s', server '%s': unable to load ssl certificate from PEM file '%s'.\n",
5355 proxy_type_str(curproxy), curproxy->id,
5356 srv->id, srv->ssl_ctx.client_crt);
Emeric Bruna7aa3092012-10-26 12:58:00 +02005357 cfgerr++;
5358 }
5359 else if (SSL_CTX_check_private_key(srv->ssl_ctx.ctx) <= 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005360 ha_alert("config : %s '%s', server '%s': inconsistencies between private key and certificate loaded from PEM file '%s'.\n",
5361 proxy_type_str(curproxy), curproxy->id,
5362 srv->id, srv->ssl_ctx.client_crt);
Emeric Bruna7aa3092012-10-26 12:58:00 +02005363 cfgerr++;
5364 }
5365 }
Emeric Brun94324a42012-10-11 14:00:19 +02005366
Emeric Brun850efd52014-01-29 12:24:34 +01005367 if (global.ssl_server_verify == SSL_SERVER_VERIFY_REQUIRED)
5368 verify = SSL_VERIFY_PEER;
Emeric Brun850efd52014-01-29 12:24:34 +01005369 switch (srv->ssl_ctx.verify) {
5370 case SSL_SOCK_VERIFY_NONE:
5371 verify = SSL_VERIFY_NONE;
5372 break;
5373 case SSL_SOCK_VERIFY_REQUIRED:
5374 verify = SSL_VERIFY_PEER;
5375 break;
5376 }
Evan Broderbe554312013-06-27 00:05:25 -07005377 SSL_CTX_set_verify(srv->ssl_ctx.ctx,
Emeric Brun850efd52014-01-29 12:24:34 +01005378 verify,
Willy Tarreau2ab88672017-07-05 18:23:03 +02005379 (srv->ssl_ctx.verify_host || (verify & SSL_VERIFY_PEER)) ? ssl_sock_srv_verifycbk : NULL);
Emeric Brun850efd52014-01-29 12:24:34 +01005380 if (verify & SSL_VERIFY_PEER) {
Emeric Brunef42d922012-10-11 16:11:36 +02005381 if (srv->ssl_ctx.ca_file) {
5382 /* load CAfile to verify */
5383 if (!SSL_CTX_load_verify_locations(srv->ssl_ctx.ctx, srv->ssl_ctx.ca_file, NULL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005384 ha_alert("Proxy '%s', server '%s' [%s:%d] unable to load CA file '%s'.\n",
5385 curproxy->id, srv->id,
5386 srv->conf.file, srv->conf.line, srv->ssl_ctx.ca_file);
Emeric Brunef42d922012-10-11 16:11:36 +02005387 cfgerr++;
5388 }
5389 }
Emeric Brun850efd52014-01-29 12:24:34 +01005390 else {
5391 if (global.ssl_server_verify == SSL_SERVER_VERIFY_REQUIRED)
Christopher Faulet767a84b2017-11-24 16:50:31 +01005392 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",
5393 curproxy->id, srv->id,
5394 srv->conf.file, srv->conf.line);
Emeric Brun850efd52014-01-29 12:24:34 +01005395 else
Christopher Faulet767a84b2017-11-24 16:50:31 +01005396 ha_alert("Proxy '%s', server '%s' [%s:%d] verify is enabled but no CA file specified.\n",
5397 curproxy->id, srv->id,
5398 srv->conf.file, srv->conf.line);
Emeric Brun850efd52014-01-29 12:24:34 +01005399 cfgerr++;
5400 }
Emeric Brunef42d922012-10-11 16:11:36 +02005401#ifdef X509_V_FLAG_CRL_CHECK
5402 if (srv->ssl_ctx.crl_file) {
5403 X509_STORE *store = SSL_CTX_get_cert_store(srv->ssl_ctx.ctx);
5404
5405 if (!store || !X509_STORE_load_locations(store, srv->ssl_ctx.crl_file, NULL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005406 ha_alert("Proxy '%s', server '%s' [%s:%d] unable to configure CRL file '%s'.\n",
5407 curproxy->id, srv->id,
5408 srv->conf.file, srv->conf.line, srv->ssl_ctx.crl_file);
Emeric Brunef42d922012-10-11 16:11:36 +02005409 cfgerr++;
5410 }
5411 else {
5412 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
5413 }
5414 }
5415#endif
5416 }
5417
Olivier Houchardbd84ac82017-11-03 13:43:35 +01005418 SSL_CTX_set_session_cache_mode(srv->ssl_ctx.ctx, SSL_SESS_CACHE_CLIENT |
5419 SSL_SESS_CACHE_NO_INTERNAL_STORE);
5420 SSL_CTX_sess_set_new_cb(srv->ssl_ctx.ctx, ssl_sess_new_srv_cb);
Emeric Brun94324a42012-10-11 14:00:19 +02005421 if (srv->ssl_ctx.ciphers &&
5422 !SSL_CTX_set_cipher_list(srv->ssl_ctx.ctx, srv->ssl_ctx.ciphers)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005423 ha_alert("Proxy '%s', server '%s' [%s:%d] : unable to set SSL cipher list to '%s'.\n",
5424 curproxy->id, srv->id,
5425 srv->conf.file, srv->conf.line, srv->ssl_ctx.ciphers);
Emeric Brun94324a42012-10-11 14:00:19 +02005426 cfgerr++;
5427 }
Dirkjan Bussink415150f2018-09-14 11:14:21 +02005428
Emmanuel Hocdet839af572019-05-14 16:27:35 +02005429#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02005430 if (srv->ssl_ctx.ciphersuites &&
Pierre Cheynierbc34cd12019-03-21 16:15:47 +00005431 !SSL_CTX_set_ciphersuites(srv->ssl_ctx.ctx, srv->ssl_ctx.ciphersuites)) {
Dirkjan Bussink415150f2018-09-14 11:14:21 +02005432 ha_alert("Proxy '%s', server '%s' [%s:%d] : unable to set TLS 1.3 cipher suites to '%s'.\n",
5433 curproxy->id, srv->id,
5434 srv->conf.file, srv->conf.line, srv->ssl_ctx.ciphersuites);
5435 cfgerr++;
5436 }
5437#endif
Olivier Houchardc7566002018-11-20 23:33:50 +01005438#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
5439 if (srv->ssl_ctx.npn_str)
5440 SSL_CTX_set_next_proto_select_cb(ctx, ssl_sock_srv_select_protos, srv);
5441#endif
5442#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
5443 if (srv->ssl_ctx.alpn_str)
5444 SSL_CTX_set_alpn_protos(ctx, (unsigned char *)srv->ssl_ctx.alpn_str, srv->ssl_ctx.alpn_len);
5445#endif
5446
Emeric Brun94324a42012-10-11 14:00:19 +02005447
5448 return cfgerr;
5449}
5450
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005451/* Walks down the two trees in bind_conf and prepares all certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +02005452 * be NULL, in which case nothing is done. Returns the number of errors
5453 * encountered.
5454 */
Willy Tarreau03209342016-12-22 17:08:28 +01005455int ssl_sock_prepare_all_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02005456{
5457 struct ebmb_node *node;
5458 struct sni_ctx *sni;
5459 int err = 0;
William Lallemand8b453912019-11-21 15:48:10 +01005460 int errcode = 0;
5461 char *errmsg = NULL;
Emeric Brunfc0421f2012-09-07 17:30:07 +02005462
Willy Tarreaufce03112015-01-15 21:32:40 +01005463 /* Automatic memory computations need to know we use SSL there */
5464 global.ssl_used_frontend = 1;
5465
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01005466 /* Make sure openssl opens /dev/urandom before the chroot */
5467 if (!ssl_initialize_random()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005468 ha_alert("OpenSSL random data generator initialization failed.\n");
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01005469 err++;
5470 }
5471 /* Create initial_ctx used to start the ssl connection before do switchctx */
5472 if (!bind_conf->initial_ctx) {
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005473 err += ssl_sock_initial_ctx(bind_conf);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01005474 /* It should not be necessary to call this function, but it's
5475 necessary first to check and move all initialisation related
5476 to initial_ctx in ssl_sock_initial_ctx. */
William Lallemand8b453912019-11-21 15:48:10 +01005477 errcode |= ssl_sock_prepare_ctx(bind_conf, NULL, bind_conf->initial_ctx, &errmsg);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01005478 }
Emeric Brun0bed9942014-10-30 19:25:24 +01005479 if (bind_conf->default_ctx)
William Lallemand8b453912019-11-21 15:48:10 +01005480 errcode |= ssl_sock_prepare_ctx(bind_conf, bind_conf->default_ssl_conf, bind_conf->default_ctx, &errmsg);
Emeric Brun0bed9942014-10-30 19:25:24 +01005481
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005482 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02005483 while (node) {
5484 sni = ebmb_entry(node, struct sni_ctx, name);
Emeric Brun0bed9942014-10-30 19:25:24 +01005485 if (!sni->order && sni->ctx != bind_conf->default_ctx)
5486 /* only initialize the CTX on its first occurrence and
5487 if it is not the default_ctx */
William Lallemand8b453912019-11-21 15:48:10 +01005488 errcode |= ssl_sock_prepare_ctx(bind_conf, sni->conf, sni->ctx, &errmsg);
Emeric Brunfc0421f2012-09-07 17:30:07 +02005489 node = ebmb_next(node);
5490 }
5491
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005492 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02005493 while (node) {
5494 sni = ebmb_entry(node, struct sni_ctx, name);
William Lallemand8b453912019-11-21 15:48:10 +01005495 if (!sni->order && sni->ctx != bind_conf->default_ctx) {
Emeric Brun0bed9942014-10-30 19:25:24 +01005496 /* only initialize the CTX on its first occurrence and
5497 if it is not the default_ctx */
William Lallemand8b453912019-11-21 15:48:10 +01005498 errcode |= ssl_sock_prepare_ctx(bind_conf, sni->conf, sni->ctx, &errmsg);
5499 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02005500 node = ebmb_next(node);
5501 }
William Lallemand8b453912019-11-21 15:48:10 +01005502
5503 if (errcode & ERR_WARN) {
5504 ha_warning(errmsg);
5505 } else if (errcode & ERR_CODE) {
5506 ha_alert(errmsg);
5507 err++;
5508 }
5509
5510 free(errmsg);
Emeric Brunfc0421f2012-09-07 17:30:07 +02005511 return err;
5512}
5513
Willy Tarreau55d37912016-12-21 23:38:39 +01005514/* Prepares all the contexts for a bind_conf and allocates the shared SSL
5515 * context if needed. Returns < 0 on error, 0 on success. The warnings and
5516 * alerts are directly emitted since the rest of the stack does it below.
5517 */
5518int ssl_sock_prepare_bind_conf(struct bind_conf *bind_conf)
5519{
5520 struct proxy *px = bind_conf->frontend;
5521 int alloc_ctx;
5522 int err;
5523
5524 if (!bind_conf->is_ssl) {
5525 if (bind_conf->default_ctx) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005526 ha_warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
5527 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreau55d37912016-12-21 23:38:39 +01005528 }
5529 return 0;
5530 }
5531 if (!bind_conf->default_ctx) {
Emmanuel Hocdetaa0d6372017-08-09 11:24:25 +02005532 if (bind_conf->strict_sni && !bind_conf->generate_certs) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005533 ha_warning("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d], ssl connections will fail (use 'crt').\n",
5534 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetaa0d6372017-08-09 11:24:25 +02005535 }
5536 else {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005537 ha_alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
5538 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetaa0d6372017-08-09 11:24:25 +02005539 return -1;
5540 }
Willy Tarreau55d37912016-12-21 23:38:39 +01005541 }
William Lallemandc61c0b32017-12-04 18:46:39 +01005542 if (!ssl_shctx && global.tune.sslcachesize) {
William Lallemandc3cd35f2017-11-28 11:04:43 +01005543 alloc_ctx = shctx_init(&ssl_shctx, global.tune.sslcachesize,
Frédéric Lécailleb7838af2018-10-22 16:21:39 +02005544 sizeof(struct sh_ssl_sess_hdr) + SHSESS_BLOCK_MIN_SIZE, -1,
William Lallemandc3cd35f2017-11-28 11:04:43 +01005545 sizeof(*sh_ssl_sess_tree),
5546 ((global.nbthread > 1) || (!global_ssl.private_cache && (global.nbproc > 1))) ? 1 : 0);
Frédéric Lécaille4c8aa112018-10-25 20:22:46 +02005547 if (alloc_ctx <= 0) {
William Lallemandc3cd35f2017-11-28 11:04:43 +01005548 if (alloc_ctx == SHCTX_E_INIT_LOCK)
5549 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");
5550 else
5551 ha_alert("Unable to allocate SSL session cache.\n");
5552 return -1;
5553 }
5554 /* free block callback */
5555 ssl_shctx->free_block = sh_ssl_sess_free_blocks;
5556 /* init the root tree within the extra space */
5557 sh_ssl_sess_tree = (void *)ssl_shctx + sizeof(struct shared_context);
5558 *sh_ssl_sess_tree = EB_ROOT_UNIQUE;
Willy Tarreau55d37912016-12-21 23:38:39 +01005559 }
Willy Tarreau55d37912016-12-21 23:38:39 +01005560 err = 0;
5561 /* initialize all certificate contexts */
5562 err += ssl_sock_prepare_all_ctx(bind_conf);
5563
5564 /* initialize CA variables if the certificates generation is enabled */
5565 err += ssl_sock_load_ca(bind_conf);
5566
5567 return -err;
5568}
Christopher Faulet77fe80c2015-07-29 13:02:40 +02005569
5570/* release ssl context allocated for servers. */
5571void ssl_sock_free_srv_ctx(struct server *srv)
5572{
Olivier Houchardc7566002018-11-20 23:33:50 +01005573#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
5574 if (srv->ssl_ctx.alpn_str)
5575 free(srv->ssl_ctx.alpn_str);
5576#endif
Lukas Tribusda95fd92018-11-25 13:21:27 +01005577#ifdef OPENSSL_NPN_NEGOTIATED
Olivier Houchardc7566002018-11-20 23:33:50 +01005578 if (srv->ssl_ctx.npn_str)
5579 free(srv->ssl_ctx.npn_str);
Lukas Tribus7706b852018-11-26 22:57:17 +01005580#endif
Christopher Faulet77fe80c2015-07-29 13:02:40 +02005581 if (srv->ssl_ctx.ctx)
5582 SSL_CTX_free(srv->ssl_ctx.ctx);
5583}
5584
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005585/* Walks down the two trees in bind_conf and frees all the certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +02005586 * be NULL, in which case nothing is done. The default_ctx is nullified too.
5587 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005588void ssl_sock_free_all_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02005589{
5590 struct ebmb_node *node, *back;
5591 struct sni_ctx *sni;
5592
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005593 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02005594 while (node) {
5595 sni = ebmb_entry(node, struct sni_ctx, name);
5596 back = ebmb_next(node);
5597 ebmb_delete(node);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005598 if (!sni->order) { /* only free the CTX on its first occurrence */
Emeric Brunfc0421f2012-09-07 17:30:07 +02005599 SSL_CTX_free(sni->ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005600 ssl_sock_free_ssl_conf(sni->conf);
5601 free(sni->conf);
5602 sni->conf = NULL;
5603 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02005604 free(sni);
5605 node = back;
5606 }
5607
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005608 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02005609 while (node) {
5610 sni = ebmb_entry(node, struct sni_ctx, name);
5611 back = ebmb_next(node);
5612 ebmb_delete(node);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005613 if (!sni->order) { /* only free the CTX on its first occurrence */
Emeric Brunfc0421f2012-09-07 17:30:07 +02005614 SSL_CTX_free(sni->ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005615 ssl_sock_free_ssl_conf(sni->conf);
5616 free(sni->conf);
5617 sni->conf = NULL;
5618 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02005619 free(sni);
5620 node = back;
5621 }
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01005622 SSL_CTX_free(bind_conf->initial_ctx);
5623 bind_conf->initial_ctx = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005624 bind_conf->default_ctx = NULL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005625 bind_conf->default_ssl_conf = NULL;
Emeric Brune1f38db2012-09-03 20:36:47 +02005626}
5627
Willy Tarreau795cdab2016-12-22 17:30:54 +01005628/* Destroys all the contexts for a bind_conf. This is used during deinit(). */
5629void ssl_sock_destroy_bind_conf(struct bind_conf *bind_conf)
5630{
5631 ssl_sock_free_ca(bind_conf);
5632 ssl_sock_free_all_ctx(bind_conf);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005633 ssl_sock_free_ssl_conf(&bind_conf->ssl_conf);
Willy Tarreau795cdab2016-12-22 17:30:54 +01005634 free(bind_conf->ca_sign_file);
5635 free(bind_conf->ca_sign_pass);
Willy Tarreau17b4aa12018-07-17 10:05:32 +02005636 if (bind_conf->keys_ref && !--bind_conf->keys_ref->refcount) {
Willy Tarreau795cdab2016-12-22 17:30:54 +01005637 free(bind_conf->keys_ref->filename);
5638 free(bind_conf->keys_ref->tlskeys);
5639 LIST_DEL(&bind_conf->keys_ref->list);
5640 free(bind_conf->keys_ref);
5641 }
5642 bind_conf->keys_ref = NULL;
Willy Tarreau795cdab2016-12-22 17:30:54 +01005643 bind_conf->ca_sign_pass = NULL;
5644 bind_conf->ca_sign_file = NULL;
Willy Tarreau795cdab2016-12-22 17:30:54 +01005645}
5646
Christopher Faulet31af49d2015-06-09 17:29:50 +02005647/* Load CA cert file and private key used to generate certificates */
5648int
Willy Tarreau03209342016-12-22 17:08:28 +01005649ssl_sock_load_ca(struct bind_conf *bind_conf)
Christopher Faulet31af49d2015-06-09 17:29:50 +02005650{
Willy Tarreau03209342016-12-22 17:08:28 +01005651 struct proxy *px = bind_conf->frontend;
Christopher Faulet31af49d2015-06-09 17:29:50 +02005652 FILE *fp;
5653 X509 *cacert = NULL;
5654 EVP_PKEY *capkey = NULL;
5655 int err = 0;
5656
Christopher Fauletf8bb0ce2017-09-15 09:52:49 +02005657 if (!bind_conf->generate_certs)
Christopher Faulet31af49d2015-06-09 17:29:50 +02005658 return err;
5659
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005660#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Emeric Brun821bb9b2017-06-15 16:37:39 +02005661 if (global_ssl.ctx_cache) {
Willy Tarreauef934602016-12-22 23:12:01 +01005662 ssl_ctx_lru_tree = lru64_new(global_ssl.ctx_cache);
Emeric Brun821bb9b2017-06-15 16:37:39 +02005663 }
Christopher Fauletd2cab922015-07-28 16:03:47 +02005664 ssl_ctx_lru_seed = (unsigned int)time(NULL);
Emeric Brun821bb9b2017-06-15 16:37:39 +02005665 ssl_ctx_serial = now_ms;
Willy Tarreaua84c2672015-10-09 12:10:13 +02005666#endif
Christopher Fauletd2cab922015-07-28 16:03:47 +02005667
Christopher Faulet31af49d2015-06-09 17:29:50 +02005668 if (!bind_conf->ca_sign_file) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005669 ha_alert("Proxy '%s': cannot enable certificate generation, "
5670 "no CA certificate File configured at [%s:%d].\n",
5671 px->id, bind_conf->file, bind_conf->line);
Christopher Faulet31af49d2015-06-09 17:29:50 +02005672 goto load_error;
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005673 }
Christopher Faulet31af49d2015-06-09 17:29:50 +02005674
5675 /* read in the CA certificate */
5676 if (!(fp = fopen(bind_conf->ca_sign_file, "r"))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005677 ha_alert("Proxy '%s': Failed to read CA certificate file '%s' at [%s:%d].\n",
5678 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Faulet31af49d2015-06-09 17:29:50 +02005679 goto load_error;
5680 }
5681 if (!(cacert = PEM_read_X509(fp, NULL, NULL, NULL))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005682 ha_alert("Proxy '%s': Failed to read CA certificate file '%s' at [%s:%d].\n",
5683 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005684 goto read_error;
Christopher Faulet31af49d2015-06-09 17:29:50 +02005685 }
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005686 rewind(fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02005687 if (!(capkey = PEM_read_PrivateKey(fp, NULL, NULL, bind_conf->ca_sign_pass))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005688 ha_alert("Proxy '%s': Failed to read CA private key file '%s' at [%s:%d].\n",
5689 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005690 goto read_error;
Christopher Faulet31af49d2015-06-09 17:29:50 +02005691 }
Christopher Faulet31af49d2015-06-09 17:29:50 +02005692
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005693 fclose (fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02005694 bind_conf->ca_sign_cert = cacert;
5695 bind_conf->ca_sign_pkey = capkey;
5696 return err;
5697
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005698 read_error:
5699 fclose (fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02005700 if (capkey) EVP_PKEY_free(capkey);
5701 if (cacert) X509_free(cacert);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005702 load_error:
5703 bind_conf->generate_certs = 0;
5704 err++;
Christopher Faulet31af49d2015-06-09 17:29:50 +02005705 return err;
5706}
5707
5708/* Release CA cert and private key used to generate certificated */
5709void
5710ssl_sock_free_ca(struct bind_conf *bind_conf)
5711{
Christopher Faulet31af49d2015-06-09 17:29:50 +02005712 if (bind_conf->ca_sign_pkey)
5713 EVP_PKEY_free(bind_conf->ca_sign_pkey);
5714 if (bind_conf->ca_sign_cert)
5715 X509_free(bind_conf->ca_sign_cert);
Willy Tarreau94ff03a2016-12-22 17:57:46 +01005716 bind_conf->ca_sign_pkey = NULL;
5717 bind_conf->ca_sign_cert = NULL;
Christopher Faulet31af49d2015-06-09 17:29:50 +02005718}
5719
Emeric Brun46591952012-05-18 15:47:34 +02005720/*
5721 * This function is called if SSL * context is not yet allocated. The function
5722 * is designed to be called before any other data-layer operation and sets the
5723 * handshake flag on the connection. It is safe to call it multiple times.
5724 * It returns 0 on success and -1 in error case.
5725 */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005726static int ssl_sock_init(struct connection *conn, void **xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02005727{
Olivier Houchard66ab4982019-02-26 18:37:15 +01005728 struct ssl_sock_ctx *ctx;
Emeric Brun46591952012-05-18 15:47:34 +02005729 /* already initialized */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005730 if (*xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02005731 return 0;
5732
Willy Tarreau3c728722014-01-23 13:50:42 +01005733 if (!conn_ctrl_ready(conn))
Willy Tarreauf79c8172013-10-21 16:30:56 +02005734 return 0;
5735
Olivier Houchard66ab4982019-02-26 18:37:15 +01005736 ctx = pool_alloc(ssl_sock_ctx_pool);
5737 if (!ctx) {
5738 conn->err_code = CO_ER_SSL_NO_MEM;
5739 return -1;
5740 }
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02005741 ctx->wait_event.tasklet = tasklet_new();
5742 if (!ctx->wait_event.tasklet) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02005743 conn->err_code = CO_ER_SSL_NO_MEM;
5744 pool_free(ssl_sock_ctx_pool, ctx);
5745 return -1;
5746 }
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02005747 ctx->wait_event.tasklet->process = ssl_sock_io_cb;
5748 ctx->wait_event.tasklet->context = ctx;
Olivier Houchardea8dd942019-05-20 14:02:16 +02005749 ctx->wait_event.events = 0;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01005750 ctx->sent_early_data = 0;
5751 ctx->tmp_early_data = -1;
Olivier Houcharda8955d52019-04-07 22:00:38 +02005752 ctx->conn = conn;
Olivier Houchard81284e62019-06-06 13:21:23 +02005753 ctx->send_wait = NULL;
5754 ctx->recv_wait = NULL;
Emeric Brun5762a0d2019-09-06 15:36:02 +02005755 ctx->xprt_st = 0;
5756 ctx->xprt_ctx = NULL;
Olivier Houcharda8955d52019-04-07 22:00:38 +02005757
5758 /* Only work with sockets for now, this should be adapted when we'll
5759 * add QUIC support.
5760 */
5761 ctx->xprt = xprt_get(XPRT_RAW);
Olivier Houchard19afb272019-05-23 18:24:07 +02005762 if (ctx->xprt->init) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02005763 if (ctx->xprt->init(conn, &ctx->xprt_ctx) != 0)
5764 goto err;
Olivier Houchard19afb272019-05-23 18:24:07 +02005765 }
Olivier Houchard66ab4982019-02-26 18:37:15 +01005766
Willy Tarreau20879a02012-12-03 16:32:10 +01005767 if (global.maxsslconn && sslconns >= global.maxsslconn) {
5768 conn->err_code = CO_ER_SSL_TOO_MANY;
Olivier Houchardea8dd942019-05-20 14:02:16 +02005769 goto err;
Willy Tarreau20879a02012-12-03 16:32:10 +01005770 }
Willy Tarreau403edff2012-09-06 11:58:37 +02005771
Emeric Brun46591952012-05-18 15:47:34 +02005772 /* If it is in client mode initiate SSL session
5773 in connect state otherwise accept state */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01005774 if (objt_server(conn->target)) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005775 int may_retry = 1;
5776
5777 retry_connect:
Emeric Brun46591952012-05-18 15:47:34 +02005778 /* Alloc a new SSL session ctx */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005779 ctx->ssl = SSL_new(__objt_server(conn->target)->ssl_ctx.ctx);
5780 if (!ctx->ssl) {
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 }
Willy Tarreau20879a02012-12-03 16:32:10 +01005785 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01005786 goto err;
Willy Tarreau20879a02012-12-03 16:32:10 +01005787 }
Olivier Houcharda8955d52019-04-07 22:00:38 +02005788 ctx->bio = BIO_new(ha_meth);
5789 if (!ctx->bio) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005790 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005791 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005792 goto retry_connect;
5793 }
Emeric Brun55476152014-11-12 17:35:37 +01005794 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01005795 goto err;
Emeric Brun55476152014-11-12 17:35:37 +01005796 }
Olivier Houcharda8955d52019-04-07 22:00:38 +02005797 BIO_set_data(ctx->bio, ctx);
Olivier Houcharda8955d52019-04-07 22:00:38 +02005798 SSL_set_bio(ctx->ssl, ctx->bio, ctx->bio);
Emeric Brun46591952012-05-18 15:47:34 +02005799
Evan Broderbe554312013-06-27 00:05:25 -07005800 /* set connection pointer */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005801 if (!SSL_set_ex_data(ctx->ssl, ssl_app_data_index, conn)) {
5802 SSL_free(ctx->ssl);
5803 ctx->ssl = NULL;
Emeric Brun55476152014-11-12 17:35:37 +01005804 conn->xprt_ctx = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005805 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005806 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005807 goto retry_connect;
5808 }
Emeric Brun55476152014-11-12 17:35:37 +01005809 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01005810 goto err;
Emeric Brun55476152014-11-12 17:35:37 +01005811 }
5812
Olivier Houchard66ab4982019-02-26 18:37:15 +01005813 SSL_set_connect_state(ctx->ssl);
Willy Tarreau07d94e42018-09-20 10:57:52 +02005814 if (__objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr) {
5815 const unsigned char *ptr = __objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr;
5816 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 +01005817 if (sess && !SSL_set_session(ctx->ssl, sess)) {
Olivier Houcharde6060c52017-11-16 17:42:52 +01005818 SSL_SESSION_free(sess);
Willy Tarreau07d94e42018-09-20 10:57:52 +02005819 free(__objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr);
5820 __objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr = NULL;
Olivier Houcharde6060c52017-11-16 17:42:52 +01005821 } else if (sess) {
5822 SSL_SESSION_free(sess);
Emeric Brun55476152014-11-12 17:35:37 +01005823 }
5824 }
Evan Broderbe554312013-06-27 00:05:25 -07005825
Emeric Brun46591952012-05-18 15:47:34 +02005826 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +02005827 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Willy Tarreau403edff2012-09-06 11:58:37 +02005828
Olivier Houchard2be5a4c2019-03-08 18:54:43 +01005829 _HA_ATOMIC_ADD(&sslconns, 1);
5830 _HA_ATOMIC_ADD(&totalsslconns, 1);
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005831 *xprt_ctx = ctx;
Olivier Houchardea8dd942019-05-20 14:02:16 +02005832 /* Start the handshake */
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02005833 tasklet_wakeup(ctx->wait_event.tasklet);
Olivier Houchardea8dd942019-05-20 14:02:16 +02005834 if (conn->flags & CO_FL_ERROR)
5835 goto err;
Emeric Brun46591952012-05-18 15:47:34 +02005836 return 0;
5837 }
Willy Tarreau3fdb3662012-11-12 00:42:33 +01005838 else if (objt_listener(conn->target)) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005839 int may_retry = 1;
5840
5841 retry_accept:
Emeric Brun46591952012-05-18 15:47:34 +02005842 /* Alloc a new SSL session ctx */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005843 ctx->ssl = SSL_new(__objt_listener(conn->target)->bind_conf->initial_ctx);
5844 if (!ctx->ssl) {
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 }
Willy Tarreau20879a02012-12-03 16:32:10 +01005849 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01005850 goto err;
Willy Tarreau20879a02012-12-03 16:32:10 +01005851 }
Emeric Brun46591952012-05-18 15:47:34 +02005852
Olivier Houcharda8955d52019-04-07 22:00:38 +02005853 ctx->bio = BIO_new(ha_meth);
5854 if (!ctx->bio) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005855 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005856 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005857 goto retry_accept;
5858 }
Emeric Brun55476152014-11-12 17:35:37 +01005859 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01005860 goto err;
Emeric Brun55476152014-11-12 17:35:37 +01005861 }
Olivier Houcharda8955d52019-04-07 22:00:38 +02005862 BIO_set_data(ctx->bio, ctx);
Olivier Houcharda8955d52019-04-07 22:00:38 +02005863 SSL_set_bio(ctx->ssl, ctx->bio, ctx->bio);
Emeric Brun46591952012-05-18 15:47:34 +02005864
Emeric Brune1f38db2012-09-03 20:36:47 +02005865 /* set connection pointer */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005866 if (!SSL_set_ex_data(ctx->ssl, ssl_app_data_index, conn)) {
5867 SSL_free(ctx->ssl);
5868 ctx->ssl = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005869 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005870 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005871 goto retry_accept;
5872 }
Emeric Brun55476152014-11-12 17:35:37 +01005873 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01005874 goto err;
Emeric Brun55476152014-11-12 17:35:37 +01005875 }
5876
Olivier Houchard66ab4982019-02-26 18:37:15 +01005877 SSL_set_accept_state(ctx->ssl);
Emeric Brune1f38db2012-09-03 20:36:47 +02005878
Emeric Brun46591952012-05-18 15:47:34 +02005879 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +02005880 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Emmanuel Hocdetf967c312019-08-05 18:04:16 +02005881#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Olivier Houchardc2aae742017-09-22 18:26:28 +02005882 conn->flags |= CO_FL_EARLY_SSL_HS;
5883#endif
Willy Tarreau403edff2012-09-06 11:58:37 +02005884
Olivier Houchard2be5a4c2019-03-08 18:54:43 +01005885 _HA_ATOMIC_ADD(&sslconns, 1);
5886 _HA_ATOMIC_ADD(&totalsslconns, 1);
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005887 *xprt_ctx = ctx;
Olivier Houchardea8dd942019-05-20 14:02:16 +02005888 /* Start the handshake */
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02005889 tasklet_wakeup(ctx->wait_event.tasklet);
Olivier Houchardea8dd942019-05-20 14:02:16 +02005890 if (conn->flags & CO_FL_ERROR)
5891 goto err;
Emeric Brun46591952012-05-18 15:47:34 +02005892 return 0;
5893 }
5894 /* don't know how to handle such a target */
Willy Tarreau20879a02012-12-03 16:32:10 +01005895 conn->err_code = CO_ER_SSL_NO_TARGET;
Olivier Houchard66ab4982019-02-26 18:37:15 +01005896err:
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02005897 if (ctx && ctx->wait_event.tasklet)
5898 tasklet_free(ctx->wait_event.tasklet);
Olivier Houchard66ab4982019-02-26 18:37:15 +01005899 pool_free(ssl_sock_ctx_pool, ctx);
Emeric Brun46591952012-05-18 15:47:34 +02005900 return -1;
5901}
5902
5903
5904/* This is the callback which is used when an SSL handshake is pending. It
5905 * updates the FD status if it wants some polling before being called again.
5906 * It returns 0 if it fails in a fatal way or needs to poll to go further,
5907 * otherwise it returns non-zero and removes itself from the connection's
5908 * flags (the bit is provided in <flag> by the caller).
5909 */
Olivier Houchard000694c2019-05-23 14:45:12 +02005910static int ssl_sock_handshake(struct connection *conn, unsigned int flag)
Emeric Brun46591952012-05-18 15:47:34 +02005911{
Olivier Houchard66ab4982019-02-26 18:37:15 +01005912 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
Emeric Brun46591952012-05-18 15:47:34 +02005913 int ret;
5914
Willy Tarreau3c728722014-01-23 13:50:42 +01005915 if (!conn_ctrl_ready(conn))
Willy Tarreauf79c8172013-10-21 16:30:56 +02005916 return 0;
5917
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005918 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02005919 goto out_error;
5920
Willy Tarreau5db847a2019-05-09 14:13:35 +02005921#if HA_OPENSSL_VERSION_NUMBER >= 0x10101000L
Olivier Houchardc2aae742017-09-22 18:26:28 +02005922 /*
5923 * Check if we have early data. If we do, we have to read them
5924 * before SSL_do_handshake() is called, And there's no way to
5925 * detect early data, except to try to read them
5926 */
5927 if (conn->flags & CO_FL_EARLY_SSL_HS) {
5928 size_t read_data;
5929
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01005930 ret = SSL_read_early_data(ctx->ssl, &ctx->tmp_early_data,
Olivier Houchardc2aae742017-09-22 18:26:28 +02005931 1, &read_data);
5932 if (ret == SSL_READ_EARLY_DATA_ERROR)
5933 goto check_error;
5934 if (ret == SSL_READ_EARLY_DATA_SUCCESS) {
5935 conn->flags &= ~(CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN);
5936 return 1;
5937 } else
5938 conn->flags &= ~CO_FL_EARLY_SSL_HS;
5939 }
5940#endif
Emeric Brun674b7432012-11-08 19:21:55 +01005941 /* If we use SSL_do_handshake to process a reneg initiated by
5942 * the remote peer, it sometimes returns SSL_ERROR_SSL.
5943 * Usually SSL_write and SSL_read are used and process implicitly
5944 * the reneg handshake.
5945 * Here we use SSL_peek as a workaround for reneg.
5946 */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005947 if ((conn->flags & CO_FL_CONNECTED) && SSL_renegotiate_pending(ctx->ssl)) {
Emeric Brun674b7432012-11-08 19:21:55 +01005948 char c;
5949
Olivier Houchard66ab4982019-02-26 18:37:15 +01005950 ret = SSL_peek(ctx->ssl, &c, 1);
Emeric Brun674b7432012-11-08 19:21:55 +01005951 if (ret <= 0) {
5952 /* handshake may have not been completed, let's find why */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005953 ret = SSL_get_error(ctx->ssl, ret);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005954
Emeric Brun674b7432012-11-08 19:21:55 +01005955 if (ret == SSL_ERROR_WANT_WRITE) {
5956 /* SSL handshake needs to write, L4 connection may not be ready */
Olivier Houchard03abf2d2019-05-28 10:12:02 +02005957 if (!(ctx->wait_event.events & SUB_RETRY_SEND))
Olivier Houchardea8dd942019-05-20 14:02:16 +02005958 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_SEND, &ctx->wait_event);
Emeric Brun674b7432012-11-08 19:21:55 +01005959 return 0;
5960 }
5961 else if (ret == SSL_ERROR_WANT_READ) {
5962 /* handshake may have been completed but we have
5963 * no more data to read.
5964 */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005965 if (!SSL_renegotiate_pending(ctx->ssl)) {
Emeric Brun674b7432012-11-08 19:21:55 +01005966 ret = 1;
5967 goto reneg_ok;
5968 }
5969 /* SSL handshake needs to read, L4 connection is ready */
Olivier Houchard03abf2d2019-05-28 10:12:02 +02005970 if (!(ctx->wait_event.events & SUB_RETRY_RECV))
Olivier Houchardea8dd942019-05-20 14:02:16 +02005971 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_RECV, &ctx->wait_event);
Emeric Brun674b7432012-11-08 19:21:55 +01005972 return 0;
5973 }
Willy Tarreau5db847a2019-05-09 14:13:35 +02005974#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005975 else if (ret == SSL_ERROR_WANT_ASYNC) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02005976 ssl_async_process_fds(ctx);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005977 return 0;
5978 }
5979#endif
Emeric Brun674b7432012-11-08 19:21:55 +01005980 else if (ret == SSL_ERROR_SYSCALL) {
5981 /* if errno is null, then connection was successfully established */
5982 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
5983 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Willy Tarreau20879a02012-12-03 16:32:10 +01005984 if (!conn->err_code) {
Lukas Tribus49799162019-07-08 14:29:15 +02005985#if defined(OPENSSL_IS_BORINGSSL) || defined(LIBRESSL_VERSION_NUMBER)
5986 /* do not handle empty handshakes in BoringSSL or LibreSSL */
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005987 conn->err_code = CO_ER_SSL_HANDSHAKE;
5988#else
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005989 int empty_handshake;
Willy Tarreau5db847a2019-05-09 14:13:35 +02005990#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL)
Lukas Tribus49799162019-07-08 14:29:15 +02005991 /* use SSL_get_state() in OpenSSL >= 1.1.0; SSL_state() is broken */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005992 OSSL_HANDSHAKE_STATE state = SSL_get_state((SSL *)ctx->ssl);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005993 empty_handshake = state == TLS_ST_BEFORE;
5994#else
Lukas Tribus49799162019-07-08 14:29:15 +02005995 /* access packet_length directly in OpenSSL <= 1.0.2; SSL_state() is broken */
5996 empty_handshake = !ctx->ssl->packet_length;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005997#endif
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005998 if (empty_handshake) {
Emeric Brun29f037d2014-04-25 19:05:36 +02005999 if (!errno) {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006000 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emeric Brun29f037d2014-04-25 19:05:36 +02006001 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
6002 else
6003 conn->err_code = CO_ER_SSL_EMPTY;
6004 }
6005 else {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006006 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emeric Brun29f037d2014-04-25 19:05:36 +02006007 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
6008 else
6009 conn->err_code = CO_ER_SSL_ABORT;
6010 }
6011 }
6012 else {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006013 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emeric Brun29f037d2014-04-25 19:05:36 +02006014 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
Willy Tarreau20879a02012-12-03 16:32:10 +01006015 else
Emeric Brun29f037d2014-04-25 19:05:36 +02006016 conn->err_code = CO_ER_SSL_HANDSHAKE;
6017 }
Lukas Tribus49799162019-07-08 14:29:15 +02006018#endif /* BoringSSL or LibreSSL */
Willy Tarreau20879a02012-12-03 16:32:10 +01006019 }
Emeric Brun674b7432012-11-08 19:21:55 +01006020 goto out_error;
6021 }
6022 else {
6023 /* Fail on all other handshake errors */
6024 /* Note: OpenSSL may leave unread bytes in the socket's
6025 * buffer, causing an RST to be emitted upon close() on
6026 * TCP sockets. We first try to drain possibly pending
6027 * data to avoid this as much as possible.
6028 */
Willy Tarreaud85c4852015-03-13 00:40:28 +01006029 conn_sock_drain(conn);
Willy Tarreau20879a02012-12-03 16:32:10 +01006030 if (!conn->err_code)
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006031 conn->err_code = (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT) ?
Willy Tarreauf51c6982014-04-25 20:02:39 +02006032 CO_ER_SSL_KILLED_HB : CO_ER_SSL_HANDSHAKE;
Emeric Brun674b7432012-11-08 19:21:55 +01006033 goto out_error;
6034 }
6035 }
6036 /* read some data: consider handshake completed */
6037 goto reneg_ok;
6038 }
Olivier Houchard66ab4982019-02-26 18:37:15 +01006039 ret = SSL_do_handshake(ctx->ssl);
Olivier Houchardc2aae742017-09-22 18:26:28 +02006040check_error:
Emeric Brun46591952012-05-18 15:47:34 +02006041 if (ret != 1) {
6042 /* handshake did not complete, let's find why */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006043 ret = SSL_get_error(ctx->ssl, ret);
Emeric Brun46591952012-05-18 15:47:34 +02006044
6045 if (ret == SSL_ERROR_WANT_WRITE) {
6046 /* SSL handshake needs to write, L4 connection may not be ready */
Olivier Houchard03abf2d2019-05-28 10:12:02 +02006047 if (!(ctx->wait_event.events & SUB_RETRY_SEND))
Olivier Houchardea8dd942019-05-20 14:02:16 +02006048 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_SEND, &ctx->wait_event);
Emeric Brun46591952012-05-18 15:47:34 +02006049 return 0;
6050 }
6051 else if (ret == SSL_ERROR_WANT_READ) {
6052 /* SSL handshake needs to read, L4 connection is ready */
Olivier Houchardea8dd942019-05-20 14:02:16 +02006053 if (!(ctx->wait_event.events & SUB_RETRY_RECV))
Olivier Houchardea8dd942019-05-20 14:02:16 +02006054 ctx->xprt->subscribe(conn, ctx->xprt_ctx,
6055 SUB_RETRY_RECV, &ctx->wait_event);
Emeric Brun46591952012-05-18 15:47:34 +02006056 return 0;
6057 }
Willy Tarreau5db847a2019-05-09 14:13:35 +02006058#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006059 else if (ret == SSL_ERROR_WANT_ASYNC) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02006060 ssl_async_process_fds(ctx);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006061 return 0;
6062 }
6063#endif
Willy Tarreau89230192012-09-28 20:22:13 +02006064 else if (ret == SSL_ERROR_SYSCALL) {
6065 /* if errno is null, then connection was successfully established */
6066 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
6067 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01006068 if (!conn->err_code) {
Lukas Tribus49799162019-07-08 14:29:15 +02006069#if defined(OPENSSL_IS_BORINGSSL) || defined(LIBRESSL_VERSION_NUMBER)
6070 /* do not handle empty handshakes in BoringSSL or LibreSSL */
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01006071 conn->err_code = CO_ER_SSL_HANDSHAKE;
6072#else
6073 int empty_handshake;
Willy Tarreau5db847a2019-05-09 14:13:35 +02006074#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL)
Lukas Tribus49799162019-07-08 14:29:15 +02006075 /* use SSL_get_state() in OpenSSL >= 1.1.0; SSL_state() is broken */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006076 OSSL_HANDSHAKE_STATE state = SSL_get_state(ctx->ssl);
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01006077 empty_handshake = state == TLS_ST_BEFORE;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006078#else
Lukas Tribus49799162019-07-08 14:29:15 +02006079 /* access packet_length directly in OpenSSL <= 1.0.2; SSL_state() is broken */
6080 empty_handshake = !ctx->ssl->packet_length;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006081#endif
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01006082 if (empty_handshake) {
6083 if (!errno) {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006084 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01006085 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
6086 else
6087 conn->err_code = CO_ER_SSL_EMPTY;
6088 }
6089 else {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006090 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01006091 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
6092 else
6093 conn->err_code = CO_ER_SSL_ABORT;
6094 }
Emeric Brun29f037d2014-04-25 19:05:36 +02006095 }
6096 else {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006097 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emeric Brun29f037d2014-04-25 19:05:36 +02006098 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
6099 else
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01006100 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun29f037d2014-04-25 19:05:36 +02006101 }
Lukas Tribus49799162019-07-08 14:29:15 +02006102#endif /* BoringSSL or LibreSSL */
Emeric Brun29f037d2014-04-25 19:05:36 +02006103 }
Willy Tarreau89230192012-09-28 20:22:13 +02006104 goto out_error;
6105 }
Emeric Brun46591952012-05-18 15:47:34 +02006106 else {
6107 /* Fail on all other handshake errors */
Willy Tarreau566dc552012-10-19 20:52:18 +02006108 /* Note: OpenSSL may leave unread bytes in the socket's
6109 * buffer, causing an RST to be emitted upon close() on
6110 * TCP sockets. We first try to drain possibly pending
6111 * data to avoid this as much as possible.
6112 */
Willy Tarreaud85c4852015-03-13 00:40:28 +01006113 conn_sock_drain(conn);
Willy Tarreau20879a02012-12-03 16:32:10 +01006114 if (!conn->err_code)
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006115 conn->err_code = (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT) ?
Willy Tarreauf51c6982014-04-25 20:02:39 +02006116 CO_ER_SSL_KILLED_HB : CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02006117 goto out_error;
6118 }
6119 }
Willy Tarreau5db847a2019-05-09 14:13:35 +02006120#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Olivier Houchard522eea72017-11-03 16:27:47 +01006121 else {
6122 /*
6123 * If the server refused the early data, we have to send a
6124 * 425 to the client, as we no longer have the data to sent
6125 * them again.
6126 */
6127 if ((conn->flags & CO_FL_EARLY_DATA) && (objt_server(conn->target))) {
Olivier Houchard66ab4982019-02-26 18:37:15 +01006128 if (SSL_get_early_data_status(ctx->ssl) == SSL_EARLY_DATA_REJECTED) {
Olivier Houchard522eea72017-11-03 16:27:47 +01006129 conn->err_code = CO_ER_SSL_EARLY_FAILED;
6130 goto out_error;
6131 }
6132 }
6133 }
6134#endif
6135
Emeric Brun46591952012-05-18 15:47:34 +02006136
Emeric Brun674b7432012-11-08 19:21:55 +01006137reneg_ok:
Emeric Brunb5e42a82017-06-06 12:35:14 +00006138
Willy Tarreau5db847a2019-05-09 14:13:35 +02006139#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00006140 /* ASYNC engine API doesn't support moving read/write
6141 * buffers. So we disable ASYNC mode right after
6142 * the handshake to avoid buffer oveflows.
6143 */
6144 if (global_ssl.async)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006145 SSL_clear_mode(ctx->ssl, SSL_MODE_ASYNC);
Emeric Brunb5e42a82017-06-06 12:35:14 +00006146#endif
Emeric Brun46591952012-05-18 15:47:34 +02006147 /* Handshake succeeded */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006148 if (!SSL_session_reused(ctx->ssl)) {
Willy Tarreau0c9c2722014-05-28 12:28:58 +02006149 if (objt_server(conn->target)) {
6150 update_freq_ctr(&global.ssl_be_keys_per_sec, 1);
6151 if (global.ssl_be_keys_per_sec.curr_ctr > global.ssl_be_keys_max)
6152 global.ssl_be_keys_max = global.ssl_be_keys_per_sec.curr_ctr;
Emeric Brun46591952012-05-18 15:47:34 +02006153 }
Willy Tarreau0c9c2722014-05-28 12:28:58 +02006154 else {
6155 update_freq_ctr(&global.ssl_fe_keys_per_sec, 1);
6156 if (global.ssl_fe_keys_per_sec.curr_ctr > global.ssl_fe_keys_max)
6157 global.ssl_fe_keys_max = global.ssl_fe_keys_per_sec.curr_ctr;
6158 }
Emeric Brun46591952012-05-18 15:47:34 +02006159 }
6160
6161 /* The connection is now established at both layers, it's time to leave */
6162 conn->flags &= ~(flag | CO_FL_WAIT_L4_CONN | CO_FL_WAIT_L6_CONN);
6163 return 1;
6164
6165 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01006166 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02006167 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01006168 ERR_clear_error();
6169
Emeric Brun9fa89732012-10-04 17:09:56 +02006170 /* free resumed session if exists */
Willy Tarreau07d94e42018-09-20 10:57:52 +02006171 if (objt_server(conn->target) && __objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr) {
6172 free(__objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr);
6173 __objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr = NULL;
Emeric Brun9fa89732012-10-04 17:09:56 +02006174 }
6175
Emeric Brun46591952012-05-18 15:47:34 +02006176 /* Fail on all other handshake errors */
6177 conn->flags |= CO_FL_ERROR;
Willy Tarreau20879a02012-12-03 16:32:10 +01006178 if (!conn->err_code)
6179 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02006180 return 0;
6181}
6182
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006183static int ssl_subscribe(struct connection *conn, void *xprt_ctx, int event_type, void *param)
Olivier Houcharddf357842019-03-21 16:30:07 +01006184{
Olivier Houchardea8dd942019-05-20 14:02:16 +02006185 struct wait_event *sw;
6186 struct ssl_sock_ctx *ctx = xprt_ctx;
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006187
Olivier Houchard0ff28652019-06-24 18:57:39 +02006188 if (!ctx)
6189 return -1;
6190
Olivier Houchardea8dd942019-05-20 14:02:16 +02006191 if (event_type & SUB_RETRY_RECV) {
6192 sw = param;
6193 BUG_ON(ctx->recv_wait != NULL || (sw->events & SUB_RETRY_RECV));
6194 sw->events |= SUB_RETRY_RECV;
6195 ctx->recv_wait = sw;
6196 if (!(conn->flags & CO_FL_SSL_WAIT_HS) &&
6197 !(ctx->wait_event.events & SUB_RETRY_RECV))
6198 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_RECV, &ctx->wait_event);
6199 event_type &= ~SUB_RETRY_RECV;
6200 }
6201 if (event_type & SUB_RETRY_SEND) {
6202sw = param;
6203 BUG_ON(ctx->send_wait != NULL || (sw->events & SUB_RETRY_SEND));
6204 sw->events |= SUB_RETRY_SEND;
6205 ctx->send_wait = sw;
6206 if (!(conn->flags & CO_FL_SSL_WAIT_HS) &&
6207 !(ctx->wait_event.events & SUB_RETRY_SEND))
6208 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_SEND, &ctx->wait_event);
6209 event_type &= ~SUB_RETRY_SEND;
6210
6211 }
6212 if (event_type != 0)
6213 return -1;
6214 return 0;
Olivier Houcharddf357842019-03-21 16:30:07 +01006215}
6216
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006217static int ssl_unsubscribe(struct connection *conn, void *xprt_ctx, int event_type, void *param)
Olivier Houcharddf357842019-03-21 16:30:07 +01006218{
Olivier Houchardea8dd942019-05-20 14:02:16 +02006219 struct wait_event *sw;
6220 struct ssl_sock_ctx *ctx = xprt_ctx;
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006221
Olivier Houchardea8dd942019-05-20 14:02:16 +02006222 if (event_type & SUB_RETRY_RECV) {
6223 sw = param;
6224 BUG_ON(ctx->recv_wait != sw);
6225 ctx->recv_wait = NULL;
6226 sw->events &= ~SUB_RETRY_RECV;
6227 /* If we subscribed, and we're not doing the handshake,
6228 * then we subscribed because the upper layer asked for it,
6229 * as the upper layer is no longer interested, we can
6230 * unsubscribe too.
6231 */
6232 if (!(ctx->conn->flags & CO_FL_SSL_WAIT_HS) &&
6233 (ctx->wait_event.events & SUB_RETRY_RECV))
6234 conn_unsubscribe(conn, ctx->xprt_ctx, SUB_RETRY_RECV,
6235 &ctx->wait_event);
6236 }
6237 if (event_type & SUB_RETRY_SEND) {
6238 sw = param;
6239 BUG_ON(ctx->send_wait != sw);
6240 ctx->send_wait = NULL;
6241 sw->events &= ~SUB_RETRY_SEND;
6242 if (!(ctx->conn->flags & CO_FL_SSL_WAIT_HS) &&
6243 (ctx->wait_event.events & SUB_RETRY_SEND))
6244 conn_unsubscribe(conn, ctx->xprt_ctx, SUB_RETRY_SEND,
6245 &ctx->wait_event);
6246
6247 }
6248
6249 return 0;
Olivier Houcharddf357842019-03-21 16:30:07 +01006250}
6251
Olivier Houchard2e055482019-05-27 19:50:12 +02006252/* Use the provided XPRT as an underlying XPRT, and provide the old one.
6253 * Returns 0 on success, and non-zero on failure.
6254 */
6255static 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)
6256{
6257 struct ssl_sock_ctx *ctx = xprt_ctx;
6258
6259 if (oldxprt_ops != NULL)
6260 *oldxprt_ops = ctx->xprt;
6261 if (oldxprt_ctx != NULL)
6262 *oldxprt_ctx = ctx->xprt_ctx;
6263 ctx->xprt = toadd_ops;
6264 ctx->xprt_ctx = toadd_ctx;
6265 return 0;
6266}
6267
Olivier Houchard5149b592019-05-23 17:47:36 +02006268/* Remove the specified xprt. If if it our underlying XPRT, remove it and
6269 * return 0, otherwise just call the remove_xprt method from the underlying
6270 * XPRT.
6271 */
6272static int ssl_remove_xprt(struct connection *conn, void *xprt_ctx, void *toremove_ctx, const struct xprt_ops *newops, void *newctx)
6273{
6274 struct ssl_sock_ctx *ctx = xprt_ctx;
6275
6276 if (ctx->xprt_ctx == toremove_ctx) {
6277 ctx->xprt_ctx = newctx;
6278 ctx->xprt = newops;
6279 return 0;
6280 }
6281 return (ctx->xprt->remove_xprt(conn, ctx->xprt_ctx, toremove_ctx, newops, newctx));
6282}
6283
Olivier Houchardea8dd942019-05-20 14:02:16 +02006284static struct task *ssl_sock_io_cb(struct task *t, void *context, unsigned short state)
6285{
6286 struct ssl_sock_ctx *ctx = context;
6287
6288 /* First if we're doing an handshake, try that */
6289 if (ctx->conn->flags & CO_FL_SSL_WAIT_HS)
6290 ssl_sock_handshake(ctx->conn, CO_FL_SSL_WAIT_HS);
6291 /* If we had an error, or the handshake is done and I/O is available,
6292 * let the upper layer know.
6293 * If no mux was set up yet, and nobody subscribed, then call
6294 * xprt_done_cb() ourself if it's set, or destroy the connection,
6295 * we can't be sure conn_fd_handler() will be called again.
6296 */
6297 if ((ctx->conn->flags & CO_FL_ERROR) ||
6298 !(ctx->conn->flags & CO_FL_SSL_WAIT_HS)) {
6299 int ret = 0;
6300 int woke = 0;
6301
6302 /* On error, wake any waiter */
6303 if (ctx->recv_wait) {
6304 ctx->recv_wait->events &= ~SUB_RETRY_RECV;
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02006305 tasklet_wakeup(ctx->recv_wait->tasklet);
Olivier Houchardea8dd942019-05-20 14:02:16 +02006306 ctx->recv_wait = NULL;
6307 woke = 1;
6308 }
6309 if (ctx->send_wait) {
6310 ctx->send_wait->events &= ~SUB_RETRY_SEND;
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02006311 tasklet_wakeup(ctx->send_wait->tasklet);
Olivier Houchardea8dd942019-05-20 14:02:16 +02006312 ctx->send_wait = NULL;
6313 woke = 1;
6314 }
6315 /* If we're the first xprt for the connection, let the
6316 * upper layers know. If xprt_done_cb() is set, call it,
6317 * otherwise, we should have a mux, so call its wake
6318 * method if we didn't woke a tasklet already.
6319 */
6320 if (ctx->conn->xprt_ctx == ctx) {
6321 if (ctx->conn->xprt_done_cb)
6322 ret = ctx->conn->xprt_done_cb(ctx->conn);
6323 if (ret >= 0 && !woke && ctx->conn->mux && ctx->conn->mux->wake)
6324 ctx->conn->mux->wake(ctx->conn);
6325 return NULL;
6326 }
6327 }
6328 return NULL;
6329}
6330
Emeric Brun46591952012-05-18 15:47:34 +02006331/* Receive up to <count> bytes from connection <conn>'s socket and store them
Willy Tarreauabf08d92014-01-14 11:31:27 +01006332 * into buffer <buf>. Only one call to recv() is performed, unless the
Emeric Brun46591952012-05-18 15:47:34 +02006333 * buffer wraps, in which case a second call may be performed. The connection's
6334 * flags are updated with whatever special event is detected (error, read0,
6335 * empty). The caller is responsible for taking care of those events and
6336 * avoiding the call if inappropriate. The function does not call the
6337 * connection's polling update function, so the caller is responsible for this.
6338 */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006339static 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 +02006340{
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006341 struct ssl_sock_ctx *ctx = xprt_ctx;
Willy Tarreaubfc4d772018-07-18 11:22:03 +02006342 ssize_t ret;
6343 size_t try, done = 0;
Emeric Brun46591952012-05-18 15:47:34 +02006344
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02006345 conn_refresh_polling_flags(conn);
6346
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006347 if (!ctx)
Emeric Brun46591952012-05-18 15:47:34 +02006348 goto out_error;
6349
6350 if (conn->flags & CO_FL_HANDSHAKE)
6351 /* a handshake was requested */
6352 return 0;
6353
Emeric Brun46591952012-05-18 15:47:34 +02006354 /* read the largest possible block. For this, we perform only one call
6355 * to recv() unless the buffer wraps and we exactly fill the first hunk,
6356 * in which case we accept to do it once again. A new attempt is made on
6357 * EINTR too.
6358 */
Willy Tarreau00b0fb92014-01-17 11:09:40 +01006359 while (count > 0) {
Olivier Houchardc2aae742017-09-22 18:26:28 +02006360 int need_out = 0;
6361
Willy Tarreau591d4452018-06-15 17:21:00 +02006362 try = b_contig_space(buf);
6363 if (!try)
6364 break;
6365
Willy Tarreauabf08d92014-01-14 11:31:27 +01006366 if (try > count)
6367 try = count;
Willy Tarreau591d4452018-06-15 17:21:00 +02006368
Olivier Houchardc2aae742017-09-22 18:26:28 +02006369 if (((conn->flags & (CO_FL_EARLY_SSL_HS | CO_FL_EARLY_DATA)) == CO_FL_EARLY_SSL_HS) &&
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006370 ctx->tmp_early_data != -1) {
6371 *b_tail(buf) = ctx->tmp_early_data;
Olivier Houchardc2aae742017-09-22 18:26:28 +02006372 done++;
6373 try--;
6374 count--;
Olivier Houchardacd14032018-06-28 18:17:23 +02006375 b_add(buf, 1);
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006376 ctx->tmp_early_data = -1;
Olivier Houchardc2aae742017-09-22 18:26:28 +02006377 continue;
6378 }
Willy Tarreauabf08d92014-01-14 11:31:27 +01006379
Willy Tarreau5db847a2019-05-09 14:13:35 +02006380#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Olivier Houchardc2aae742017-09-22 18:26:28 +02006381 if (conn->flags & CO_FL_EARLY_SSL_HS) {
6382 size_t read_length;
6383
Olivier Houchard66ab4982019-02-26 18:37:15 +01006384 ret = SSL_read_early_data(ctx->ssl,
Willy Tarreau8f9c72d2018-06-07 18:46:28 +02006385 b_tail(buf), try, &read_length);
Olivier Houchard522eea72017-11-03 16:27:47 +01006386 if (ret == SSL_READ_EARLY_DATA_SUCCESS &&
6387 read_length > 0)
Olivier Houchardc2aae742017-09-22 18:26:28 +02006388 conn->flags |= CO_FL_EARLY_DATA;
6389 if (ret == SSL_READ_EARLY_DATA_SUCCESS ||
6390 ret == SSL_READ_EARLY_DATA_FINISH) {
6391 if (ret == SSL_READ_EARLY_DATA_FINISH) {
6392 /*
6393 * We're done reading the early data,
6394 * let's make the handshake
6395 */
6396 conn->flags &= ~CO_FL_EARLY_SSL_HS;
6397 conn->flags |= CO_FL_SSL_WAIT_HS;
6398 need_out = 1;
Olivier Houchard965e84e2019-06-15 20:59:30 +02006399 /* Now initiate the handshake */
6400 tasklet_wakeup(ctx->wait_event.tasklet);
Olivier Houchardc2aae742017-09-22 18:26:28 +02006401 if (read_length == 0)
6402 break;
6403 }
6404 ret = read_length;
6405 }
6406 } else
6407#endif
Olivier Houchard66ab4982019-02-26 18:37:15 +01006408 ret = SSL_read(ctx->ssl, b_tail(buf), try);
Emmanuel Hocdetf967c312019-08-05 18:04:16 +02006409
Emeric Brune1f38db2012-09-03 20:36:47 +02006410 if (conn->flags & CO_FL_ERROR) {
6411 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01006412 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02006413 }
Emeric Brun46591952012-05-18 15:47:34 +02006414 if (ret > 0) {
Olivier Houchardacd14032018-06-28 18:17:23 +02006415 b_add(buf, ret);
Emeric Brun46591952012-05-18 15:47:34 +02006416 done += ret;
Emeric Brun46591952012-05-18 15:47:34 +02006417 count -= ret;
Emeric Brun46591952012-05-18 15:47:34 +02006418 }
Emeric Brun46591952012-05-18 15:47:34 +02006419 else {
Olivier Houchard66ab4982019-02-26 18:37:15 +01006420 ret = SSL_get_error(ctx->ssl, ret);
Emeric Brun46591952012-05-18 15:47:34 +02006421 if (ret == SSL_ERROR_WANT_WRITE) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01006422 /* handshake is running, and it needs to enable write */
Emeric Brun46591952012-05-18 15:47:34 +02006423 conn->flags |= CO_FL_SSL_WAIT_HS;
Olivier Houchardea8dd942019-05-20 14:02:16 +02006424 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_SEND, &ctx->wait_event);
Willy Tarreau5db847a2019-05-09 14:13:35 +02006425#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00006426 /* Async mode can be re-enabled, because we're leaving data state.*/
6427 if (global_ssl.async)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006428 SSL_set_mode(ctx->ssl, SSL_MODE_ASYNC);
Emeric Brunb5e42a82017-06-06 12:35:14 +00006429#endif
Emeric Brun46591952012-05-18 15:47:34 +02006430 break;
6431 }
6432 else if (ret == SSL_ERROR_WANT_READ) {
Olivier Houchard66ab4982019-02-26 18:37:15 +01006433 if (SSL_renegotiate_pending(ctx->ssl)) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02006434 ctx->xprt->subscribe(conn, ctx->xprt_ctx,
6435 SUB_RETRY_RECV,
6436 &ctx->wait_event);
Emeric Brun282a76a2012-11-08 18:02:56 +01006437 /* handshake is running, and it may need to re-enable read */
6438 conn->flags |= CO_FL_SSL_WAIT_HS;
Willy Tarreau5db847a2019-05-09 14:13:35 +02006439#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00006440 /* Async mode can be re-enabled, because we're leaving data state.*/
6441 if (global_ssl.async)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006442 SSL_set_mode(ctx->ssl, SSL_MODE_ASYNC);
Emeric Brunb5e42a82017-06-06 12:35:14 +00006443#endif
Emeric Brun282a76a2012-11-08 18:02:56 +01006444 break;
6445 }
Emeric Brun46591952012-05-18 15:47:34 +02006446 break;
Olivier Houchardc2aae742017-09-22 18:26:28 +02006447 } else if (ret == SSL_ERROR_ZERO_RETURN)
6448 goto read0;
Christopher Faulet4ac77a92018-02-19 14:25:15 +01006449 /* For SSL_ERROR_SYSCALL, make sure to clear the error
6450 * stack before shutting down the connection for
6451 * reading. */
Olivier Houchard7e2e5052018-02-13 15:17:23 +01006452 if (ret == SSL_ERROR_SYSCALL && (!errno || errno == EAGAIN))
6453 goto clear_ssl_error;
Emeric Brun46591952012-05-18 15:47:34 +02006454 /* otherwise it's a real error */
6455 goto out_error;
6456 }
Olivier Houchardc2aae742017-09-22 18:26:28 +02006457 if (need_out)
6458 break;
Emeric Brun46591952012-05-18 15:47:34 +02006459 }
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02006460 leave:
Emeric Brun46591952012-05-18 15:47:34 +02006461 return done;
6462
Christopher Faulet4ac77a92018-02-19 14:25:15 +01006463 clear_ssl_error:
6464 /* Clear openssl global errors stack */
6465 ssl_sock_dump_errors(conn);
6466 ERR_clear_error();
Emeric Brun46591952012-05-18 15:47:34 +02006467 read0:
6468 conn_sock_read0(conn);
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02006469 goto leave;
Christopher Faulet4ac77a92018-02-19 14:25:15 +01006470
Emeric Brun46591952012-05-18 15:47:34 +02006471 out_error:
Olivier Houchard7e2e5052018-02-13 15:17:23 +01006472 conn->flags |= CO_FL_ERROR;
Emeric Brun644cde02012-12-14 11:21:13 +01006473 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02006474 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01006475 ERR_clear_error();
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02006476 goto leave;
Emeric Brun46591952012-05-18 15:47:34 +02006477}
6478
6479
Willy Tarreau787db9a2018-06-14 18:31:46 +02006480/* Send up to <count> pending bytes from buffer <buf> to connection <conn>'s
6481 * socket. <flags> may contain some CO_SFL_* flags to hint the system about
6482 * other pending data for example, but this flag is ignored at the moment.
Emeric Brun46591952012-05-18 15:47:34 +02006483 * Only one call to send() is performed, unless the buffer wraps, in which case
6484 * a second call may be performed. The connection's flags are updated with
6485 * whatever special event is detected (error, empty). The caller is responsible
6486 * for taking care of those events and avoiding the call if inappropriate. The
6487 * function does not call the connection's polling update function, so the caller
Willy Tarreau787db9a2018-06-14 18:31:46 +02006488 * is responsible for this. The buffer's output is not adjusted, it's up to the
6489 * caller to take care of this. It's up to the caller to update the buffer's
6490 * contents based on the return value.
Emeric Brun46591952012-05-18 15:47:34 +02006491 */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006492static 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 +02006493{
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006494 struct ssl_sock_ctx *ctx = xprt_ctx;
Willy Tarreau787db9a2018-06-14 18:31:46 +02006495 ssize_t ret;
6496 size_t try, done;
Emeric Brun46591952012-05-18 15:47:34 +02006497
6498 done = 0;
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02006499 conn_refresh_polling_flags(conn);
Emeric Brun46591952012-05-18 15:47:34 +02006500
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006501 if (!ctx)
Emeric Brun46591952012-05-18 15:47:34 +02006502 goto out_error;
6503
Olivier Houchard010941f2019-05-03 20:56:19 +02006504 if (conn->flags & (CO_FL_HANDSHAKE | CO_FL_EARLY_SSL_HS))
Emeric Brun46591952012-05-18 15:47:34 +02006505 /* a handshake was requested */
6506 return 0;
6507
6508 /* send the largest possible block. For this we perform only one call
6509 * to send() unless the buffer wraps and we exactly fill the first hunk,
6510 * in which case we accept to do it once again.
6511 */
Willy Tarreau787db9a2018-06-14 18:31:46 +02006512 while (count) {
Willy Tarreau5db847a2019-05-09 14:13:35 +02006513#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Olivier Houchardc2aae742017-09-22 18:26:28 +02006514 size_t written_data;
6515#endif
6516
Willy Tarreau787db9a2018-06-14 18:31:46 +02006517 try = b_contig_data(buf, done);
6518 if (try > count)
6519 try = count;
Willy Tarreaubfd59462013-02-21 07:46:09 +01006520
Willy Tarreau7bed9452014-02-02 02:00:24 +01006521 if (!(flags & CO_SFL_STREAMER) &&
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006522 !(ctx->xprt_st & SSL_SOCK_SEND_UNLIMITED) &&
Willy Tarreauef934602016-12-22 23:12:01 +01006523 global_ssl.max_record && try > global_ssl.max_record) {
6524 try = global_ssl.max_record;
Willy Tarreau518cedd2014-02-17 15:43:01 +01006525 }
6526 else {
6527 /* we need to keep the information about the fact that
6528 * we're not limiting the upcoming send(), because if it
6529 * fails, we'll have to retry with at least as many data.
6530 */
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006531 ctx->xprt_st |= SSL_SOCK_SEND_UNLIMITED;
Willy Tarreau518cedd2014-02-17 15:43:01 +01006532 }
Willy Tarreaubfd59462013-02-21 07:46:09 +01006533
Willy Tarreau5db847a2019-05-09 14:13:35 +02006534#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Olivier Houchard010941f2019-05-03 20:56:19 +02006535 if (!SSL_is_init_finished(ctx->ssl) && conn_is_back(conn)) {
Olivier Houchardc2aae742017-09-22 18:26:28 +02006536 unsigned int max_early;
6537
Olivier Houchard522eea72017-11-03 16:27:47 +01006538 if (objt_listener(conn->target))
Olivier Houchard66ab4982019-02-26 18:37:15 +01006539 max_early = SSL_get_max_early_data(ctx->ssl);
Olivier Houchard522eea72017-11-03 16:27:47 +01006540 else {
Olivier Houchard66ab4982019-02-26 18:37:15 +01006541 if (SSL_get0_session(ctx->ssl))
6542 max_early = SSL_SESSION_get_max_early_data(SSL_get0_session(ctx->ssl));
Olivier Houchard522eea72017-11-03 16:27:47 +01006543 else
6544 max_early = 0;
6545 }
6546
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006547 if (try + ctx->sent_early_data > max_early) {
6548 try -= (try + ctx->sent_early_data) - max_early;
Olivier Houchard522eea72017-11-03 16:27:47 +01006549 if (try <= 0) {
Olivier Houchard010941f2019-05-03 20:56:19 +02006550 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Olivier Houchard965e84e2019-06-15 20:59:30 +02006551 tasklet_wakeup(ctx->wait_event.tasklet);
Olivier Houchardc2aae742017-09-22 18:26:28 +02006552 break;
Olivier Houchard522eea72017-11-03 16:27:47 +01006553 }
Olivier Houchardc2aae742017-09-22 18:26:28 +02006554 }
Olivier Houchard66ab4982019-02-26 18:37:15 +01006555 ret = SSL_write_early_data(ctx->ssl, b_peek(buf, done), try, &written_data);
Olivier Houchardc2aae742017-09-22 18:26:28 +02006556 if (ret == 1) {
6557 ret = written_data;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006558 ctx->sent_early_data += ret;
Olivier Houchard965e84e2019-06-15 20:59:30 +02006559 if (objt_server(conn->target)) {
Olivier Houchard522eea72017-11-03 16:27:47 +01006560 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN | CO_FL_EARLY_DATA;
Olivier Houchard965e84e2019-06-15 20:59:30 +02006561 /* Initiate the handshake, now */
6562 tasklet_wakeup(ctx->wait_event.tasklet);
6563 }
Olivier Houchard522eea72017-11-03 16:27:47 +01006564
Olivier Houchardc2aae742017-09-22 18:26:28 +02006565 }
6566
6567 } else
6568#endif
Olivier Houchard66ab4982019-02-26 18:37:15 +01006569 ret = SSL_write(ctx->ssl, b_peek(buf, done), try);
Willy Tarreau518cedd2014-02-17 15:43:01 +01006570
Emeric Brune1f38db2012-09-03 20:36:47 +02006571 if (conn->flags & CO_FL_ERROR) {
6572 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01006573 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02006574 }
Emeric Brun46591952012-05-18 15:47:34 +02006575 if (ret > 0) {
Olivier Houchardf24502b2019-01-17 19:09:11 +01006576 /* A send succeeded, so we can consier ourself connected */
6577 conn->flags |= CO_FL_CONNECTED;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006578 ctx->xprt_st &= ~SSL_SOCK_SEND_UNLIMITED;
Willy Tarreau787db9a2018-06-14 18:31:46 +02006579 count -= ret;
Emeric Brun46591952012-05-18 15:47:34 +02006580 done += ret;
Emeric Brun46591952012-05-18 15:47:34 +02006581 }
6582 else {
Olivier Houchard66ab4982019-02-26 18:37:15 +01006583 ret = SSL_get_error(ctx->ssl, ret);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006584
Emeric Brun46591952012-05-18 15:47:34 +02006585 if (ret == SSL_ERROR_WANT_WRITE) {
Olivier Houchard66ab4982019-02-26 18:37:15 +01006586 if (SSL_renegotiate_pending(ctx->ssl)) {
Emeric Brun282a76a2012-11-08 18:02:56 +01006587 /* handshake is running, and it may need to re-enable write */
6588 conn->flags |= CO_FL_SSL_WAIT_HS;
Olivier Houchardea8dd942019-05-20 14:02:16 +02006589 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_SEND, &ctx->wait_event);
Willy Tarreau5db847a2019-05-09 14:13:35 +02006590#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00006591 /* Async mode can be re-enabled, because we're leaving data state.*/
6592 if (global_ssl.async)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006593 SSL_set_mode(ctx->ssl, SSL_MODE_ASYNC);
Emeric Brunb5e42a82017-06-06 12:35:14 +00006594#endif
Emeric Brun282a76a2012-11-08 18:02:56 +01006595 break;
6596 }
Olivier Houchardea8dd942019-05-20 14:02:16 +02006597
Emeric Brun46591952012-05-18 15:47:34 +02006598 break;
6599 }
6600 else if (ret == SSL_ERROR_WANT_READ) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01006601 /* handshake is running, and it needs to enable read */
Emeric Brun46591952012-05-18 15:47:34 +02006602 conn->flags |= CO_FL_SSL_WAIT_HS;
Olivier Houchardea8dd942019-05-20 14:02:16 +02006603 ctx->xprt->subscribe(conn, ctx->xprt_ctx,
6604 SUB_RETRY_RECV,
6605 &ctx->wait_event);
Willy Tarreau5db847a2019-05-09 14:13:35 +02006606#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00006607 /* Async mode can be re-enabled, because we're leaving data state.*/
6608 if (global_ssl.async)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006609 SSL_set_mode(ctx->ssl, SSL_MODE_ASYNC);
Emeric Brunb5e42a82017-06-06 12:35:14 +00006610#endif
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006611 break;
6612 }
Emeric Brun46591952012-05-18 15:47:34 +02006613 goto out_error;
6614 }
6615 }
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02006616 leave:
Emeric Brun46591952012-05-18 15:47:34 +02006617 return done;
6618
6619 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01006620 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02006621 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01006622 ERR_clear_error();
6623
Emeric Brun46591952012-05-18 15:47:34 +02006624 conn->flags |= CO_FL_ERROR;
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02006625 goto leave;
Emeric Brun46591952012-05-18 15:47:34 +02006626}
6627
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006628static void ssl_sock_close(struct connection *conn, void *xprt_ctx) {
Emeric Brun46591952012-05-18 15:47:34 +02006629
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006630 struct ssl_sock_ctx *ctx = xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006631
Olivier Houchardea8dd942019-05-20 14:02:16 +02006632
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006633 if (ctx) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02006634 if (ctx->wait_event.events != 0)
6635 ctx->xprt->unsubscribe(ctx->conn, ctx->xprt_ctx,
6636 ctx->wait_event.events,
6637 &ctx->wait_event);
6638 if (ctx->send_wait) {
6639 ctx->send_wait->events &= ~SUB_RETRY_SEND;
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02006640 tasklet_wakeup(ctx->send_wait->tasklet);
Olivier Houchardea8dd942019-05-20 14:02:16 +02006641 }
6642 if (ctx->recv_wait) {
6643 ctx->recv_wait->events &= ~SUB_RETRY_RECV;
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02006644 tasklet_wakeup(ctx->recv_wait->tasklet);
Olivier Houchardea8dd942019-05-20 14:02:16 +02006645 }
Olivier Houchard692c1d02019-05-23 18:41:47 +02006646 if (ctx->xprt->close)
6647 ctx->xprt->close(conn, ctx->xprt_ctx);
Willy Tarreau5db847a2019-05-09 14:13:35 +02006648#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brun3854e012017-05-17 20:42:48 +02006649 if (global_ssl.async) {
6650 OSSL_ASYNC_FD all_fd[32], afd;
6651 size_t num_all_fds = 0;
6652 int i;
6653
Olivier Houchard66ab4982019-02-26 18:37:15 +01006654 SSL_get_all_async_fds(ctx->ssl, NULL, &num_all_fds);
Emeric Brun3854e012017-05-17 20:42:48 +02006655 if (num_all_fds > 32) {
6656 send_log(NULL, LOG_EMERG, "haproxy: openssl returns too many async fds. It seems a bug. Process may crash\n");
6657 return;
6658 }
6659
Olivier Houchard66ab4982019-02-26 18:37:15 +01006660 SSL_get_all_async_fds(ctx->ssl, all_fd, &num_all_fds);
Emeric Brun3854e012017-05-17 20:42:48 +02006661
6662 /* If an async job is pending, we must try to
6663 to catch the end using polling before calling
6664 SSL_free */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006665 if (num_all_fds && SSL_waiting_for_async(ctx->ssl)) {
Emeric Brun3854e012017-05-17 20:42:48 +02006666 for (i=0 ; i < num_all_fds ; i++) {
6667 /* switch on an handler designed to
6668 * handle the SSL_free
6669 */
6670 afd = all_fd[i];
6671 fdtab[afd].iocb = ssl_async_fd_free;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006672 fdtab[afd].owner = ctx->ssl;
Emeric Brun3854e012017-05-17 20:42:48 +02006673 fd_want_recv(afd);
Emeric Brunce9e01c2017-05-31 10:02:53 +00006674 /* To ensure that the fd cache won't be used
6675 * and we'll catch a real RD event.
6676 */
6677 fd_cant_recv(afd);
Emeric Brun3854e012017-05-17 20:42:48 +02006678 }
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02006679 tasklet_free(ctx->wait_event.tasklet);
Olivier Houchard66ab4982019-02-26 18:37:15 +01006680 pool_free(ssl_sock_ctx_pool, ctx);
Olivier Houchard2be5a4c2019-03-08 18:54:43 +01006681 _HA_ATOMIC_ADD(&jobs, 1);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006682 return;
6683 }
Emeric Brun3854e012017-05-17 20:42:48 +02006684 /* Else we can remove the fds from the fdtab
6685 * and call SSL_free.
6686 * note: we do a fd_remove and not a delete
6687 * because the fd is owned by the engine.
6688 * the engine is responsible to close
6689 */
6690 for (i=0 ; i < num_all_fds ; i++)
6691 fd_remove(all_fd[i]);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006692 }
6693#endif
Olivier Houchard66ab4982019-02-26 18:37:15 +01006694 SSL_free(ctx->ssl);
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02006695 tasklet_free(ctx->wait_event.tasklet);
Olivier Houchard66ab4982019-02-26 18:37:15 +01006696 pool_free(ssl_sock_ctx_pool, ctx);
Olivier Houchard2be5a4c2019-03-08 18:54:43 +01006697 _HA_ATOMIC_SUB(&sslconns, 1);
Emeric Brun46591952012-05-18 15:47:34 +02006698 }
Emeric Brun46591952012-05-18 15:47:34 +02006699}
6700
6701/* This function tries to perform a clean shutdown on an SSL connection, and in
6702 * any case, flags the connection as reusable if no handshake was in progress.
6703 */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006704static void ssl_sock_shutw(struct connection *conn, void *xprt_ctx, int clean)
Emeric Brun46591952012-05-18 15:47:34 +02006705{
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006706 struct ssl_sock_ctx *ctx = xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006707
Emeric Brun46591952012-05-18 15:47:34 +02006708 if (conn->flags & CO_FL_HANDSHAKE)
6709 return;
Emmanuel Hocdet405ff312017-01-08 14:07:39 +01006710 if (!clean)
6711 /* don't sent notify on SSL_shutdown */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006712 SSL_set_quiet_shutdown(ctx->ssl, 1);
Emeric Brun46591952012-05-18 15:47:34 +02006713 /* no handshake was in progress, try a clean ssl shutdown */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006714 if (SSL_shutdown(ctx->ssl) <= 0) {
Emeric Brun644cde02012-12-14 11:21:13 +01006715 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02006716 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01006717 ERR_clear_error();
6718 }
Emeric Brun46591952012-05-18 15:47:34 +02006719}
6720
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01006721/* used for ppv2 pkey alog (can be used for logging) */
Willy Tarreau83061a82018-07-13 11:56:34 +02006722int ssl_sock_get_pkey_algo(struct connection *conn, struct buffer *out)
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01006723{
Christopher Faulet82004142019-09-10 10:12:03 +02006724 struct ssl_sock_ctx *ctx;
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01006725 int bits = 0;
6726 int sig = TLSEXT_signature_anonymous;
6727 int len = -1;
Emmanuel Hocdetc3775d22019-11-04 18:19:32 +01006728 X509 *crt;
6729 EVP_PKEY *pkey;
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01006730
6731 if (!ssl_sock_is_ssl(conn))
6732 return 0;
Christopher Faulet82004142019-09-10 10:12:03 +02006733 ctx = conn->xprt_ctx;
Emmanuel Hocdetc3775d22019-11-04 18:19:32 +01006734
6735 crt = SSL_get_certificate(ctx->ssl);
6736 if (!crt)
6737 return 0;
6738 pkey = X509_get_pubkey(crt);
6739 if (pkey) {
6740 bits = EVP_PKEY_bits(pkey);
6741 switch(EVP_PKEY_base_id(pkey)) {
6742 case EVP_PKEY_RSA:
6743 sig = TLSEXT_signature_rsa;
6744 break;
6745 case EVP_PKEY_EC:
6746 sig = TLSEXT_signature_ecdsa;
6747 break;
6748 case EVP_PKEY_DSA:
6749 sig = TLSEXT_signature_dsa;
6750 break;
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01006751 }
Emmanuel Hocdetc3775d22019-11-04 18:19:32 +01006752 EVP_PKEY_free(pkey);
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01006753 }
6754
6755 switch(sig) {
6756 case TLSEXT_signature_rsa:
6757 len = chunk_printf(out, "RSA%d", bits);
6758 break;
6759 case TLSEXT_signature_ecdsa:
6760 len = chunk_printf(out, "EC%d", bits);
6761 break;
6762 case TLSEXT_signature_dsa:
6763 len = chunk_printf(out, "DSA%d", bits);
6764 break;
6765 default:
6766 return 0;
6767 }
6768 if (len < 0)
6769 return 0;
6770 return 1;
6771}
6772
Emmanuel Hocdet283e0042017-11-02 14:05:23 +01006773/* used for ppv2 cert signature (can be used for logging) */
6774const char *ssl_sock_get_cert_sig(struct connection *conn)
6775{
Christopher Faulet82004142019-09-10 10:12:03 +02006776 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006777
Emmanuel Hocdet283e0042017-11-02 14:05:23 +01006778 __OPENSSL_110_CONST__ ASN1_OBJECT *algorithm;
6779 X509 *crt;
6780
6781 if (!ssl_sock_is_ssl(conn))
6782 return NULL;
Christopher Faulet82004142019-09-10 10:12:03 +02006783 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006784 crt = SSL_get_certificate(ctx->ssl);
Emmanuel Hocdet283e0042017-11-02 14:05:23 +01006785 if (!crt)
6786 return NULL;
6787 X509_ALGOR_get0(&algorithm, NULL, NULL, X509_get0_tbs_sigalg(crt));
6788 return OBJ_nid2sn(OBJ_obj2nid(algorithm));
6789}
6790
Emmanuel Hocdet253c3b72018-02-01 18:29:59 +01006791/* used for ppv2 authority */
6792const char *ssl_sock_get_sni(struct connection *conn)
6793{
6794#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Christopher Faulet82004142019-09-10 10:12:03 +02006795 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006796
Emmanuel Hocdet253c3b72018-02-01 18:29:59 +01006797 if (!ssl_sock_is_ssl(conn))
6798 return NULL;
Christopher Faulet82004142019-09-10 10:12:03 +02006799 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006800 return SSL_get_servername(ctx->ssl, TLSEXT_NAMETYPE_host_name);
Emmanuel Hocdet253c3b72018-02-01 18:29:59 +01006801#else
Olivier Houchard66ab4982019-02-26 18:37:15 +01006802 return NULL;
Emmanuel Hocdet253c3b72018-02-01 18:29:59 +01006803#endif
6804}
6805
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02006806/* used for logging/ppv2, may be changed for a sample fetch later */
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02006807const char *ssl_sock_get_cipher_name(struct connection *conn)
6808{
Christopher Faulet82004142019-09-10 10:12:03 +02006809 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006810
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02006811 if (!ssl_sock_is_ssl(conn))
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02006812 return NULL;
Christopher Faulet82004142019-09-10 10:12:03 +02006813 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006814 return SSL_get_cipher_name(ctx->ssl);
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02006815}
6816
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02006817/* used for logging/ppv2, may be changed for a sample fetch later */
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02006818const char *ssl_sock_get_proto_version(struct connection *conn)
6819{
Christopher Faulet82004142019-09-10 10:12:03 +02006820 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006821
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02006822 if (!ssl_sock_is_ssl(conn))
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02006823 return NULL;
Christopher Faulet82004142019-09-10 10:12:03 +02006824 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006825 return SSL_get_version(ctx->ssl);
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02006826}
6827
Willy Tarreau8d598402012-10-22 17:58:39 +02006828/* Extract a serial from a cert, and copy it to a chunk.
6829 * Returns 1 if serial is found and copied, 0 if no serial found and
6830 * -1 if output is not large enough.
6831 */
6832static int
Willy Tarreau83061a82018-07-13 11:56:34 +02006833ssl_sock_get_serial(X509 *crt, struct buffer *out)
Willy Tarreau8d598402012-10-22 17:58:39 +02006834{
6835 ASN1_INTEGER *serial;
6836
6837 serial = X509_get_serialNumber(crt);
6838 if (!serial)
6839 return 0;
6840
6841 if (out->size < serial->length)
6842 return -1;
6843
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006844 memcpy(out->area, serial->data, serial->length);
6845 out->data = serial->length;
Willy Tarreau8d598402012-10-22 17:58:39 +02006846 return 1;
6847}
6848
Emeric Brun43e79582014-10-29 19:03:26 +01006849/* Extract a cert to der, and copy it to a chunk.
Joseph Herlant017b3da2018-11-15 09:07:59 -08006850 * Returns 1 if the cert is found and copied, 0 on der conversion failure
6851 * and -1 if the output is not large enough.
Emeric Brun43e79582014-10-29 19:03:26 +01006852 */
6853static int
Willy Tarreau83061a82018-07-13 11:56:34 +02006854ssl_sock_crt2der(X509 *crt, struct buffer *out)
Emeric Brun43e79582014-10-29 19:03:26 +01006855{
6856 int len;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006857 unsigned char *p = (unsigned char *) out->area;;
Emeric Brun43e79582014-10-29 19:03:26 +01006858
6859 len =i2d_X509(crt, NULL);
6860 if (len <= 0)
6861 return 1;
6862
6863 if (out->size < len)
6864 return -1;
6865
6866 i2d_X509(crt,&p);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006867 out->data = len;
Emeric Brun43e79582014-10-29 19:03:26 +01006868 return 1;
6869}
6870
Emeric Brunce5ad802012-10-22 14:11:22 +02006871
Willy Tarreau83061a82018-07-13 11:56:34 +02006872/* Copy Date in ASN1_UTCTIME format in struct buffer out.
Emeric Brunce5ad802012-10-22 14:11:22 +02006873 * Returns 1 if serial is found and copied, 0 if no valid time found
6874 * and -1 if output is not large enough.
6875 */
6876static int
Willy Tarreau83061a82018-07-13 11:56:34 +02006877ssl_sock_get_time(ASN1_TIME *tm, struct buffer *out)
Emeric Brunce5ad802012-10-22 14:11:22 +02006878{
6879 if (tm->type == V_ASN1_GENERALIZEDTIME) {
6880 ASN1_GENERALIZEDTIME *gentm = (ASN1_GENERALIZEDTIME *)tm;
6881
6882 if (gentm->length < 12)
6883 return 0;
6884 if (gentm->data[0] != 0x32 || gentm->data[1] != 0x30)
6885 return 0;
6886 if (out->size < gentm->length-2)
6887 return -1;
6888
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006889 memcpy(out->area, gentm->data+2, gentm->length-2);
6890 out->data = gentm->length-2;
Emeric Brunce5ad802012-10-22 14:11:22 +02006891 return 1;
6892 }
6893 else if (tm->type == V_ASN1_UTCTIME) {
6894 ASN1_UTCTIME *utctm = (ASN1_UTCTIME *)tm;
6895
6896 if (utctm->length < 10)
6897 return 0;
6898 if (utctm->data[0] >= 0x35)
6899 return 0;
6900 if (out->size < utctm->length)
6901 return -1;
6902
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006903 memcpy(out->area, utctm->data, utctm->length);
6904 out->data = utctm->length;
Emeric Brunce5ad802012-10-22 14:11:22 +02006905 return 1;
6906 }
6907
6908 return 0;
6909}
6910
Emeric Brun87855892012-10-17 17:39:35 +02006911/* Extract an entry from a X509_NAME and copy its value to an output chunk.
6912 * Returns 1 if entry found, 0 if entry not found, or -1 if output not large enough.
6913 */
6914static int
Willy Tarreau83061a82018-07-13 11:56:34 +02006915ssl_sock_get_dn_entry(X509_NAME *a, const struct buffer *entry, int pos,
6916 struct buffer *out)
Emeric Brun87855892012-10-17 17:39:35 +02006917{
6918 X509_NAME_ENTRY *ne;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006919 ASN1_OBJECT *obj;
6920 ASN1_STRING *data;
6921 const unsigned char *data_ptr;
6922 int data_len;
Emeric Brun87855892012-10-17 17:39:35 +02006923 int i, j, n;
6924 int cur = 0;
6925 const char *s;
6926 char tmp[128];
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006927 int name_count;
6928
6929 name_count = X509_NAME_entry_count(a);
Emeric Brun87855892012-10-17 17:39:35 +02006930
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006931 out->data = 0;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006932 for (i = 0; i < name_count; i++) {
Emeric Brun87855892012-10-17 17:39:35 +02006933 if (pos < 0)
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006934 j = (name_count-1) - i;
Emeric Brun87855892012-10-17 17:39:35 +02006935 else
6936 j = i;
6937
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006938 ne = X509_NAME_get_entry(a, j);
6939 obj = X509_NAME_ENTRY_get_object(ne);
6940 data = X509_NAME_ENTRY_get_data(ne);
6941 data_ptr = ASN1_STRING_get0_data(data);
6942 data_len = ASN1_STRING_length(data);
6943 n = OBJ_obj2nid(obj);
Emeric Brun87855892012-10-17 17:39:35 +02006944 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006945 i2t_ASN1_OBJECT(tmp, sizeof(tmp), obj);
Emeric Brun87855892012-10-17 17:39:35 +02006946 s = tmp;
6947 }
6948
6949 if (chunk_strcasecmp(entry, s) != 0)
6950 continue;
6951
6952 if (pos < 0)
6953 cur--;
6954 else
6955 cur++;
6956
6957 if (cur != pos)
6958 continue;
6959
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006960 if (data_len > out->size)
Emeric Brun87855892012-10-17 17:39:35 +02006961 return -1;
6962
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006963 memcpy(out->area, data_ptr, data_len);
6964 out->data = data_len;
Emeric Brun87855892012-10-17 17:39:35 +02006965 return 1;
6966 }
6967
6968 return 0;
6969
6970}
6971
6972/* Extract and format full DN from a X509_NAME and copy result into a chunk
6973 * Returns 1 if dn entries exits, 0 if no dn entry found or -1 if output is not large enough.
6974 */
6975static int
Willy Tarreau83061a82018-07-13 11:56:34 +02006976ssl_sock_get_dn_oneline(X509_NAME *a, struct buffer *out)
Emeric Brun87855892012-10-17 17:39:35 +02006977{
6978 X509_NAME_ENTRY *ne;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006979 ASN1_OBJECT *obj;
6980 ASN1_STRING *data;
6981 const unsigned char *data_ptr;
6982 int data_len;
Emeric Brun87855892012-10-17 17:39:35 +02006983 int i, n, ln;
6984 int l = 0;
6985 const char *s;
6986 char *p;
6987 char tmp[128];
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006988 int name_count;
6989
6990
6991 name_count = X509_NAME_entry_count(a);
Emeric Brun87855892012-10-17 17:39:35 +02006992
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006993 out->data = 0;
6994 p = out->area;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006995 for (i = 0; i < name_count; i++) {
6996 ne = X509_NAME_get_entry(a, i);
6997 obj = X509_NAME_ENTRY_get_object(ne);
6998 data = X509_NAME_ENTRY_get_data(ne);
6999 data_ptr = ASN1_STRING_get0_data(data);
7000 data_len = ASN1_STRING_length(data);
7001 n = OBJ_obj2nid(obj);
Emeric Brun87855892012-10-17 17:39:35 +02007002 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007003 i2t_ASN1_OBJECT(tmp, sizeof(tmp), obj);
Emeric Brun87855892012-10-17 17:39:35 +02007004 s = tmp;
7005 }
7006 ln = strlen(s);
7007
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007008 l += 1 + ln + 1 + data_len;
Emeric Brun87855892012-10-17 17:39:35 +02007009 if (l > out->size)
7010 return -1;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007011 out->data = l;
Emeric Brun87855892012-10-17 17:39:35 +02007012
7013 *(p++)='/';
7014 memcpy(p, s, ln);
7015 p += ln;
7016 *(p++)='=';
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007017 memcpy(p, data_ptr, data_len);
7018 p += data_len;
Emeric Brun87855892012-10-17 17:39:35 +02007019 }
7020
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007021 if (!out->data)
Emeric Brun87855892012-10-17 17:39:35 +02007022 return 0;
7023
7024 return 1;
7025}
7026
Olivier Houchardab28a322018-12-21 19:45:40 +01007027void ssl_sock_set_alpn(struct connection *conn, const unsigned char *alpn, int len)
7028{
7029#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Christopher Faulet82004142019-09-10 10:12:03 +02007030 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007031
Olivier Houcharde488ea82019-06-28 14:10:33 +02007032 if (!ssl_sock_is_ssl(conn))
7033 return;
Christopher Faulet82004142019-09-10 10:12:03 +02007034 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007035 SSL_set_alpn_protos(ctx->ssl, alpn, len);
Olivier Houchardab28a322018-12-21 19:45:40 +01007036#endif
7037}
7038
Willy Tarreau119a4082016-12-22 21:58:38 +01007039/* Sets advertised SNI for outgoing connections. Please set <hostname> to NULL
7040 * to disable SNI.
7041 */
Willy Tarreau63076412015-07-10 11:33:32 +02007042void ssl_sock_set_servername(struct connection *conn, const char *hostname)
7043{
7044#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Christopher Faulet82004142019-09-10 10:12:03 +02007045 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007046
Willy Tarreau119a4082016-12-22 21:58:38 +01007047 char *prev_name;
7048
Willy Tarreau63076412015-07-10 11:33:32 +02007049 if (!ssl_sock_is_ssl(conn))
7050 return;
Christopher Faulet82004142019-09-10 10:12:03 +02007051 ctx = conn->xprt_ctx;
Willy Tarreau63076412015-07-10 11:33:32 +02007052
Willy Tarreau119a4082016-12-22 21:58:38 +01007053 /* if the SNI changes, we must destroy the reusable context so that a
7054 * new connection will present a new SNI. As an optimization we could
7055 * later imagine having a small cache of ssl_ctx to hold a few SNI per
7056 * server.
7057 */
Olivier Houchard66ab4982019-02-26 18:37:15 +01007058 prev_name = (char *)SSL_get_servername(ctx->ssl, TLSEXT_NAMETYPE_host_name);
Willy Tarreau119a4082016-12-22 21:58:38 +01007059 if ((!prev_name && hostname) ||
7060 (prev_name && (!hostname || strcmp(hostname, prev_name) != 0)))
Olivier Houchard66ab4982019-02-26 18:37:15 +01007061 SSL_set_session(ctx->ssl, NULL);
Willy Tarreau119a4082016-12-22 21:58:38 +01007062
Olivier Houchard66ab4982019-02-26 18:37:15 +01007063 SSL_set_tlsext_host_name(ctx->ssl, hostname);
Willy Tarreau63076412015-07-10 11:33:32 +02007064#endif
7065}
7066
Emeric Brun0abf8362014-06-24 18:26:41 +02007067/* Extract peer certificate's common name into the chunk dest
7068 * Returns
7069 * the len of the extracted common name
7070 * or 0 if no CN found in DN
7071 * or -1 on error case (i.e. no peer certificate)
7072 */
Willy Tarreau83061a82018-07-13 11:56:34 +02007073int ssl_sock_get_remote_common_name(struct connection *conn,
7074 struct buffer *dest)
David Safb76832014-05-08 23:42:08 -04007075{
Christopher Faulet82004142019-09-10 10:12:03 +02007076 struct ssl_sock_ctx *ctx;
David Safb76832014-05-08 23:42:08 -04007077 X509 *crt = NULL;
7078 X509_NAME *name;
David Safb76832014-05-08 23:42:08 -04007079 const char find_cn[] = "CN";
Willy Tarreau83061a82018-07-13 11:56:34 +02007080 const struct buffer find_cn_chunk = {
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007081 .area = (char *)&find_cn,
7082 .data = sizeof(find_cn)-1
David Safb76832014-05-08 23:42:08 -04007083 };
Emeric Brun0abf8362014-06-24 18:26:41 +02007084 int result = -1;
David Safb76832014-05-08 23:42:08 -04007085
7086 if (!ssl_sock_is_ssl(conn))
Emeric Brun0abf8362014-06-24 18:26:41 +02007087 goto out;
Christopher Faulet82004142019-09-10 10:12:03 +02007088 ctx = conn->xprt_ctx;
David Safb76832014-05-08 23:42:08 -04007089
7090 /* SSL_get_peer_certificate, it increase X509 * ref count */
Olivier Houchard66ab4982019-02-26 18:37:15 +01007091 crt = SSL_get_peer_certificate(ctx->ssl);
David Safb76832014-05-08 23:42:08 -04007092 if (!crt)
7093 goto out;
7094
7095 name = X509_get_subject_name(crt);
7096 if (!name)
7097 goto out;
David Safb76832014-05-08 23:42:08 -04007098
Emeric Brun0abf8362014-06-24 18:26:41 +02007099 result = ssl_sock_get_dn_entry(name, &find_cn_chunk, 1, dest);
7100out:
David Safb76832014-05-08 23:42:08 -04007101 if (crt)
7102 X509_free(crt);
7103
7104 return result;
7105}
7106
Dave McCowan328fb582014-07-30 10:39:13 -04007107/* returns 1 if client passed a certificate for this session, 0 if not */
7108int ssl_sock_get_cert_used_sess(struct connection *conn)
7109{
Christopher Faulet82004142019-09-10 10:12:03 +02007110 struct ssl_sock_ctx *ctx;
Dave McCowan328fb582014-07-30 10:39:13 -04007111 X509 *crt = NULL;
7112
7113 if (!ssl_sock_is_ssl(conn))
7114 return 0;
Christopher Faulet82004142019-09-10 10:12:03 +02007115 ctx = conn->xprt_ctx;
Dave McCowan328fb582014-07-30 10:39:13 -04007116
7117 /* SSL_get_peer_certificate, it increase X509 * ref count */
Olivier Houchard66ab4982019-02-26 18:37:15 +01007118 crt = SSL_get_peer_certificate(ctx->ssl);
Dave McCowan328fb582014-07-30 10:39:13 -04007119 if (!crt)
7120 return 0;
7121
7122 X509_free(crt);
7123 return 1;
7124}
7125
7126/* returns 1 if client passed a certificate for this connection, 0 if not */
7127int ssl_sock_get_cert_used_conn(struct connection *conn)
David Safb76832014-05-08 23:42:08 -04007128{
Christopher Faulet82004142019-09-10 10:12:03 +02007129 struct ssl_sock_ctx *ctx;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007130
David Safb76832014-05-08 23:42:08 -04007131 if (!ssl_sock_is_ssl(conn))
7132 return 0;
Christopher Faulet82004142019-09-10 10:12:03 +02007133 ctx = conn->xprt_ctx;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007134 return SSL_SOCK_ST_FL_VERIFY_DONE & ctx->xprt_st ? 1 : 0;
David Safb76832014-05-08 23:42:08 -04007135}
7136
7137/* returns result from SSL verify */
7138unsigned int ssl_sock_get_verify_result(struct connection *conn)
7139{
Christopher Faulet82004142019-09-10 10:12:03 +02007140 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007141
David Safb76832014-05-08 23:42:08 -04007142 if (!ssl_sock_is_ssl(conn))
7143 return (unsigned int)X509_V_ERR_APPLICATION_VERIFICATION;
Christopher Faulet82004142019-09-10 10:12:03 +02007144 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007145 return (unsigned int)SSL_get_verify_result(ctx->ssl);
David Safb76832014-05-08 23:42:08 -04007146}
7147
Willy Tarreau8743f7e2016-12-04 18:44:29 +01007148/* Returns the application layer protocol name in <str> and <len> when known.
7149 * Zero is returned if the protocol name was not found, otherwise non-zero is
7150 * returned. The string is allocated in the SSL context and doesn't have to be
7151 * freed by the caller. NPN is also checked if available since older versions
7152 * of openssl (1.0.1) which are more common in field only support this one.
7153 */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01007154static int ssl_sock_get_alpn(const struct connection *conn, void *xprt_ctx, const char **str, int *len)
Willy Tarreau8743f7e2016-12-04 18:44:29 +01007155{
Olivier Houchard66ab4982019-02-26 18:37:15 +01007156#if defined(TLSEXT_TYPE_application_layer_protocol_negotiation) || \
7157 defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Olivier Houcharde179d0e2019-03-21 18:27:17 +01007158 struct ssl_sock_ctx *ctx = xprt_ctx;
7159 if (!ctx)
Willy Tarreau8743f7e2016-12-04 18:44:29 +01007160 return 0;
7161
7162 *str = NULL;
7163
7164#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Olivier Houchard66ab4982019-02-26 18:37:15 +01007165 SSL_get0_alpn_selected(ctx->ssl, (const unsigned char **)str, (unsigned *)len);
Willy Tarreau8743f7e2016-12-04 18:44:29 +01007166 if (*str)
7167 return 1;
7168#endif
Bernard Spil13c53f82018-02-15 13:34:58 +01007169#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007170 SSL_get0_next_proto_negotiated(ctx->ssl, (const unsigned char **)str, (unsigned *)len);
Willy Tarreau8743f7e2016-12-04 18:44:29 +01007171 if (*str)
7172 return 1;
7173#endif
Olivier Houcharde179d0e2019-03-21 18:27:17 +01007174#endif
Willy Tarreau8743f7e2016-12-04 18:44:29 +01007175 return 0;
7176}
7177
Willy Tarreau7875d092012-09-10 08:20:03 +02007178/***** Below are some sample fetching functions for ACL/patterns *****/
7179
Olivier Houchardccaa7de2017-10-02 11:51:03 +02007180static int
7181smp_fetch_ssl_fc_has_early(const struct arg *args, struct sample *smp, const char *kw, void *private)
7182{
7183 struct connection *conn;
7184
7185 conn = objt_conn(smp->sess->origin);
7186 if (!conn || conn->xprt != &ssl_sock)
7187 return 0;
7188
7189 smp->flags = 0;
7190 smp->data.type = SMP_T_BOOL;
Emmanuel Hocdetc9858012019-08-07 14:44:49 +02007191#ifdef OPENSSL_IS_BORINGSSL
7192 {
7193 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
7194 smp->data.u.sint = (SSL_in_early_data(ctx->ssl) &&
7195 SSL_early_data_accepted(ctx->ssl));
7196 }
7197#else
Olivier Houchard25ae45a2017-11-29 19:51:19 +01007198 smp->data.u.sint = ((conn->flags & CO_FL_EARLY_DATA) &&
7199 (conn->flags & (CO_FL_EARLY_SSL_HS | CO_FL_HANDSHAKE))) ? 1 : 0;
Emmanuel Hocdetc9858012019-08-07 14:44:49 +02007200#endif
Olivier Houchardccaa7de2017-10-02 11:51:03 +02007201 return 1;
7202}
7203
Emeric Brune64aef12012-09-21 13:15:06 +02007204/* boolean, returns true if client cert was present */
7205static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007206smp_fetch_ssl_fc_has_crt(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brune64aef12012-09-21 13:15:06 +02007207{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007208 struct connection *conn;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007209 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007210
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007211 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007212 if (!conn || conn->xprt != &ssl_sock)
Emeric Brune64aef12012-09-21 13:15:06 +02007213 return 0;
7214
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007215 ctx = conn->xprt_ctx;
7216
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007217 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brune64aef12012-09-21 13:15:06 +02007218 smp->flags |= SMP_F_MAY_CHANGE;
7219 return 0;
7220 }
7221
7222 smp->flags = 0;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007223 smp->data.type = SMP_T_BOOL;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007224 smp->data.u.sint = SSL_SOCK_ST_FL_VERIFY_DONE & ctx->xprt_st ? 1 : 0;
Emeric Brune64aef12012-09-21 13:15:06 +02007225
7226 return 1;
7227}
7228
Emeric Brun43e79582014-10-29 19:03:26 +01007229/* binary, returns a certificate in a binary chunk (der/raw).
7230 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7231 * should be use.
7232 */
7233static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007234smp_fetch_ssl_x_der(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun43e79582014-10-29 19:03:26 +01007235{
7236 int cert_peer = (kw[4] == 'c') ? 1 : 0;
7237 X509 *crt = NULL;
7238 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02007239 struct buffer *smp_trash;
Emeric Brun43e79582014-10-29 19:03:26 +01007240 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007241 struct ssl_sock_ctx *ctx;
Emeric Brun43e79582014-10-29 19:03:26 +01007242
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007243 conn = objt_conn(smp->sess->origin);
Emeric Brun43e79582014-10-29 19:03:26 +01007244 if (!conn || conn->xprt != &ssl_sock)
7245 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007246 ctx = conn->xprt_ctx;
Emeric Brun43e79582014-10-29 19:03:26 +01007247
7248 if (!(conn->flags & CO_FL_CONNECTED)) {
7249 smp->flags |= SMP_F_MAY_CHANGE;
7250 return 0;
7251 }
7252
7253 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007254 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brun43e79582014-10-29 19:03:26 +01007255 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007256 crt = SSL_get_certificate(ctx->ssl);
Emeric Brun43e79582014-10-29 19:03:26 +01007257
7258 if (!crt)
7259 goto out;
7260
7261 smp_trash = get_trash_chunk();
7262 if (ssl_sock_crt2der(crt, smp_trash) <= 0)
7263 goto out;
7264
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007265 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007266 smp->data.type = SMP_T_BIN;
Emeric Brun43e79582014-10-29 19:03:26 +01007267 ret = 1;
7268out:
7269 /* SSL_get_peer_certificate, it increase X509 * ref count */
7270 if (cert_peer && crt)
7271 X509_free(crt);
7272 return ret;
7273}
7274
Emeric Brunba841a12014-04-30 17:05:08 +02007275/* binary, returns serial of certificate in a binary chunk.
7276 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7277 * should be use.
7278 */
Willy Tarreau8d598402012-10-22 17:58:39 +02007279static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007280smp_fetch_ssl_x_serial(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau8d598402012-10-22 17:58:39 +02007281{
Emeric Brunba841a12014-04-30 17:05:08 +02007282 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Willy Tarreau8d598402012-10-22 17:58:39 +02007283 X509 *crt = NULL;
7284 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02007285 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007286 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007287 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007288
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007289 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007290 if (!conn || conn->xprt != &ssl_sock)
Willy Tarreau8d598402012-10-22 17:58:39 +02007291 return 0;
7292
Olivier Houchard66ab4982019-02-26 18:37:15 +01007293 ctx = conn->xprt_ctx;
7294
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007295 if (!(conn->flags & CO_FL_CONNECTED)) {
Willy Tarreau8d598402012-10-22 17:58:39 +02007296 smp->flags |= SMP_F_MAY_CHANGE;
7297 return 0;
7298 }
7299
Emeric Brunba841a12014-04-30 17:05:08 +02007300 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007301 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007302 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007303 crt = SSL_get_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007304
Willy Tarreau8d598402012-10-22 17:58:39 +02007305 if (!crt)
7306 goto out;
7307
Willy Tarreau47ca5452012-12-23 20:22:19 +01007308 smp_trash = get_trash_chunk();
Willy Tarreau8d598402012-10-22 17:58:39 +02007309 if (ssl_sock_get_serial(crt, smp_trash) <= 0)
7310 goto out;
7311
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007312 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007313 smp->data.type = SMP_T_BIN;
Willy Tarreau8d598402012-10-22 17:58:39 +02007314 ret = 1;
7315out:
Emeric Brunba841a12014-04-30 17:05:08 +02007316 /* SSL_get_peer_certificate, it increase X509 * ref count */
7317 if (cert_peer && crt)
Willy Tarreau8d598402012-10-22 17:58:39 +02007318 X509_free(crt);
7319 return ret;
7320}
Emeric Brune64aef12012-09-21 13:15:06 +02007321
Emeric Brunba841a12014-04-30 17:05:08 +02007322/* binary, returns the client certificate's SHA-1 fingerprint (SHA-1 hash of DER-encoded certificate) in a binary chunk.
7323 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7324 * should be use.
7325 */
James Votha051b4a2013-05-14 20:37:59 +02007326static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007327smp_fetch_ssl_x_sha1(const struct arg *args, struct sample *smp, const char *kw, void *private)
James Votha051b4a2013-05-14 20:37:59 +02007328{
Emeric Brunba841a12014-04-30 17:05:08 +02007329 int cert_peer = (kw[4] == 'c') ? 1 : 0;
James Votha051b4a2013-05-14 20:37:59 +02007330 X509 *crt = NULL;
7331 const EVP_MD *digest;
7332 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02007333 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007334 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007335 struct ssl_sock_ctx *ctx;
James Votha051b4a2013-05-14 20:37:59 +02007336
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007337 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007338 if (!conn || conn->xprt != &ssl_sock)
7339 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007340 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007341
7342 if (!(conn->flags & CO_FL_CONNECTED)) {
James Votha051b4a2013-05-14 20:37:59 +02007343 smp->flags |= SMP_F_MAY_CHANGE;
7344 return 0;
7345 }
7346
Emeric Brunba841a12014-04-30 17:05:08 +02007347 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007348 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007349 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007350 crt = SSL_get_certificate(ctx->ssl);
James Votha051b4a2013-05-14 20:37:59 +02007351 if (!crt)
7352 goto out;
7353
7354 smp_trash = get_trash_chunk();
7355 digest = EVP_sha1();
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007356 X509_digest(crt, digest, (unsigned char *) smp_trash->area,
7357 (unsigned int *)&smp_trash->data);
James Votha051b4a2013-05-14 20:37:59 +02007358
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007359 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007360 smp->data.type = SMP_T_BIN;
James Votha051b4a2013-05-14 20:37:59 +02007361 ret = 1;
7362out:
Emeric Brunba841a12014-04-30 17:05:08 +02007363 /* SSL_get_peer_certificate, it increase X509 * ref count */
7364 if (cert_peer && crt)
James Votha051b4a2013-05-14 20:37:59 +02007365 X509_free(crt);
7366 return ret;
7367}
7368
Emeric Brunba841a12014-04-30 17:05:08 +02007369/* string, returns certificate's notafter date in ASN1_UTCTIME format.
7370 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7371 * should be use.
7372 */
Emeric Brunce5ad802012-10-22 14:11:22 +02007373static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007374smp_fetch_ssl_x_notafter(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunce5ad802012-10-22 14:11:22 +02007375{
Emeric Brunba841a12014-04-30 17:05:08 +02007376 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brunce5ad802012-10-22 14:11:22 +02007377 X509 *crt = NULL;
7378 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02007379 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007380 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007381 struct ssl_sock_ctx *ctx;
Emeric Brunce5ad802012-10-22 14:11:22 +02007382
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007383 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007384 if (!conn || conn->xprt != &ssl_sock)
7385 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007386 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007387
7388 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02007389 smp->flags |= SMP_F_MAY_CHANGE;
7390 return 0;
7391 }
7392
Emeric Brunba841a12014-04-30 17:05:08 +02007393 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007394 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007395 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007396 crt = SSL_get_certificate(ctx->ssl);
Emeric Brunce5ad802012-10-22 14:11:22 +02007397 if (!crt)
7398 goto out;
7399
Willy Tarreau47ca5452012-12-23 20:22:19 +01007400 smp_trash = get_trash_chunk();
Rosen Penev68185952018-12-14 08:47:02 -08007401 if (ssl_sock_get_time(X509_getm_notAfter(crt), smp_trash) <= 0)
Emeric Brunce5ad802012-10-22 14:11:22 +02007402 goto out;
7403
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007404 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007405 smp->data.type = SMP_T_STR;
Emeric Brunce5ad802012-10-22 14:11:22 +02007406 ret = 1;
7407out:
Emeric Brunba841a12014-04-30 17:05:08 +02007408 /* SSL_get_peer_certificate, it increase X509 * ref count */
7409 if (cert_peer && crt)
Emeric Brunce5ad802012-10-22 14:11:22 +02007410 X509_free(crt);
7411 return ret;
7412}
7413
Emeric Brunba841a12014-04-30 17:05:08 +02007414/* string, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. of certificate's issuer
7415 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7416 * should be use.
7417 */
Emeric Brun87855892012-10-17 17:39:35 +02007418static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007419smp_fetch_ssl_x_i_dn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun87855892012-10-17 17:39:35 +02007420{
Emeric Brunba841a12014-04-30 17:05:08 +02007421 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun87855892012-10-17 17:39:35 +02007422 X509 *crt = NULL;
7423 X509_NAME *name;
7424 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02007425 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007426 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007427 struct ssl_sock_ctx *ctx;
Emeric Brun87855892012-10-17 17:39:35 +02007428
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007429 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007430 if (!conn || conn->xprt != &ssl_sock)
7431 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007432 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007433
7434 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02007435 smp->flags |= SMP_F_MAY_CHANGE;
7436 return 0;
7437 }
7438
Emeric Brunba841a12014-04-30 17:05:08 +02007439 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007440 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007441 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007442 crt = SSL_get_certificate(ctx->ssl);
Emeric Brun87855892012-10-17 17:39:35 +02007443 if (!crt)
7444 goto out;
7445
7446 name = X509_get_issuer_name(crt);
7447 if (!name)
7448 goto out;
7449
Willy Tarreau47ca5452012-12-23 20:22:19 +01007450 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02007451 if (args && args[0].type == ARGT_STR) {
7452 int pos = 1;
7453
7454 if (args[1].type == ARGT_SINT)
7455 pos = args[1].data.sint;
Emeric Brun87855892012-10-17 17:39:35 +02007456
7457 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
7458 goto out;
7459 }
7460 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
7461 goto out;
7462
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007463 smp->data.type = SMP_T_STR;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007464 smp->data.u.str = *smp_trash;
Emeric Brun87855892012-10-17 17:39:35 +02007465 ret = 1;
7466out:
Emeric Brunba841a12014-04-30 17:05:08 +02007467 /* SSL_get_peer_certificate, it increase X509 * ref count */
7468 if (cert_peer && crt)
Emeric Brun87855892012-10-17 17:39:35 +02007469 X509_free(crt);
7470 return ret;
7471}
7472
Emeric Brunba841a12014-04-30 17:05:08 +02007473/* string, returns notbefore date in ASN1_UTCTIME format.
7474 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7475 * should be use.
7476 */
Emeric Brunce5ad802012-10-22 14:11:22 +02007477static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007478smp_fetch_ssl_x_notbefore(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunce5ad802012-10-22 14:11:22 +02007479{
Emeric Brunba841a12014-04-30 17:05:08 +02007480 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brunce5ad802012-10-22 14:11:22 +02007481 X509 *crt = NULL;
7482 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02007483 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007484 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007485 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007486
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007487 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007488 if (!conn || conn->xprt != &ssl_sock)
Emeric Brunce5ad802012-10-22 14:11:22 +02007489 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007490 ctx = conn->xprt_ctx;
Emeric Brunce5ad802012-10-22 14:11:22 +02007491
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007492 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02007493 smp->flags |= SMP_F_MAY_CHANGE;
7494 return 0;
7495 }
7496
Emeric Brunba841a12014-04-30 17:05:08 +02007497 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007498 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007499 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007500 crt = SSL_get_certificate(ctx->ssl);
Emeric Brunce5ad802012-10-22 14:11:22 +02007501 if (!crt)
7502 goto out;
7503
Willy Tarreau47ca5452012-12-23 20:22:19 +01007504 smp_trash = get_trash_chunk();
Rosen Penev68185952018-12-14 08:47:02 -08007505 if (ssl_sock_get_time(X509_getm_notBefore(crt), smp_trash) <= 0)
Emeric Brunce5ad802012-10-22 14:11:22 +02007506 goto out;
7507
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007508 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007509 smp->data.type = SMP_T_STR;
Emeric Brunce5ad802012-10-22 14:11:22 +02007510 ret = 1;
7511out:
Emeric Brunba841a12014-04-30 17:05:08 +02007512 /* SSL_get_peer_certificate, it increase X509 * ref count */
7513 if (cert_peer && crt)
Emeric Brunce5ad802012-10-22 14:11:22 +02007514 X509_free(crt);
7515 return ret;
7516}
7517
Emeric Brunba841a12014-04-30 17:05:08 +02007518/* string, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. of certificate's subject
7519 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7520 * should be use.
7521 */
Emeric Brun87855892012-10-17 17:39:35 +02007522static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007523smp_fetch_ssl_x_s_dn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun87855892012-10-17 17:39:35 +02007524{
Emeric Brunba841a12014-04-30 17:05:08 +02007525 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun87855892012-10-17 17:39:35 +02007526 X509 *crt = NULL;
7527 X509_NAME *name;
7528 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02007529 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007530 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007531 struct ssl_sock_ctx *ctx;
Emeric Brun87855892012-10-17 17:39:35 +02007532
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007533 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007534 if (!conn || conn->xprt != &ssl_sock)
7535 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007536 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007537
7538 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02007539 smp->flags |= SMP_F_MAY_CHANGE;
7540 return 0;
7541 }
7542
Emeric Brunba841a12014-04-30 17:05:08 +02007543 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007544 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007545 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007546 crt = SSL_get_certificate(ctx->ssl);
Emeric Brun87855892012-10-17 17:39:35 +02007547 if (!crt)
7548 goto out;
7549
7550 name = X509_get_subject_name(crt);
7551 if (!name)
7552 goto out;
7553
Willy Tarreau47ca5452012-12-23 20:22:19 +01007554 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02007555 if (args && args[0].type == ARGT_STR) {
7556 int pos = 1;
7557
7558 if (args[1].type == ARGT_SINT)
7559 pos = args[1].data.sint;
Emeric Brun87855892012-10-17 17:39:35 +02007560
7561 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
7562 goto out;
7563 }
7564 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
7565 goto out;
7566
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007567 smp->data.type = SMP_T_STR;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007568 smp->data.u.str = *smp_trash;
Emeric Brun87855892012-10-17 17:39:35 +02007569 ret = 1;
7570out:
Emeric Brunba841a12014-04-30 17:05:08 +02007571 /* SSL_get_peer_certificate, it increase X509 * ref count */
7572 if (cert_peer && crt)
Emeric Brun87855892012-10-17 17:39:35 +02007573 X509_free(crt);
7574 return ret;
7575}
Emeric Brun9143d372012-12-20 15:44:16 +01007576
7577/* integer, returns true if current session use a client certificate */
7578static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007579smp_fetch_ssl_c_used(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun9143d372012-12-20 15:44:16 +01007580{
7581 X509 *crt;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007582 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007583 struct ssl_sock_ctx *ctx;
Emeric Brun9143d372012-12-20 15:44:16 +01007584
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007585 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007586 if (!conn || conn->xprt != &ssl_sock)
7587 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007588 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007589
7590 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun9143d372012-12-20 15:44:16 +01007591 smp->flags |= SMP_F_MAY_CHANGE;
7592 return 0;
7593 }
7594
7595 /* SSL_get_peer_certificate returns a ptr on allocated X509 struct */
Olivier Houchard66ab4982019-02-26 18:37:15 +01007596 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brun9143d372012-12-20 15:44:16 +01007597 if (crt) {
7598 X509_free(crt);
7599 }
7600
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007601 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007602 smp->data.u.sint = (crt != NULL);
Emeric Brun9143d372012-12-20 15:44:16 +01007603 return 1;
7604}
7605
Emeric Brunba841a12014-04-30 17:05:08 +02007606/* integer, returns the certificate version
7607 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7608 * should be use.
7609 */
Emeric Bruna7359fd2012-10-17 15:03:11 +02007610static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007611smp_fetch_ssl_x_version(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Bruna7359fd2012-10-17 15:03:11 +02007612{
Emeric Brunba841a12014-04-30 17:05:08 +02007613 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Bruna7359fd2012-10-17 15:03:11 +02007614 X509 *crt;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007615 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007616 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007617
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007618 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007619 if (!conn || conn->xprt != &ssl_sock)
Emeric Bruna7359fd2012-10-17 15:03:11 +02007620 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007621 ctx = conn->xprt_ctx;
Emeric Bruna7359fd2012-10-17 15:03:11 +02007622
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007623 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Bruna7359fd2012-10-17 15:03:11 +02007624 smp->flags |= SMP_F_MAY_CHANGE;
7625 return 0;
7626 }
7627
Emeric Brunba841a12014-04-30 17:05:08 +02007628 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007629 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007630 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007631 crt = SSL_get_certificate(ctx->ssl);
Emeric Bruna7359fd2012-10-17 15:03:11 +02007632 if (!crt)
7633 return 0;
7634
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007635 smp->data.u.sint = (unsigned int)(1 + X509_get_version(crt));
Emeric Brunba841a12014-04-30 17:05:08 +02007636 /* SSL_get_peer_certificate increase X509 * ref count */
7637 if (cert_peer)
7638 X509_free(crt);
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007639 smp->data.type = SMP_T_SINT;
Emeric Bruna7359fd2012-10-17 15:03:11 +02007640
7641 return 1;
7642}
7643
Emeric Brunba841a12014-04-30 17:05:08 +02007644/* string, returns the certificate's signature algorithm.
7645 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7646 * should be use.
7647 */
Emeric Brun7f56e742012-10-19 18:15:40 +02007648static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007649smp_fetch_ssl_x_sig_alg(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun7f56e742012-10-19 18:15:40 +02007650{
Emeric Brunba841a12014-04-30 17:05:08 +02007651 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun7f56e742012-10-19 18:15:40 +02007652 X509 *crt;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007653 __OPENSSL_110_CONST__ ASN1_OBJECT *algorithm;
Emeric Brun7f56e742012-10-19 18:15:40 +02007654 int nid;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007655 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007656 struct ssl_sock_ctx *ctx;
Emeric Brun7f56e742012-10-19 18:15:40 +02007657
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007658 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007659 if (!conn || conn->xprt != &ssl_sock)
7660 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007661 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007662
7663 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun7f56e742012-10-19 18:15:40 +02007664 smp->flags |= SMP_F_MAY_CHANGE;
7665 return 0;
7666 }
7667
Emeric Brunba841a12014-04-30 17:05:08 +02007668 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007669 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007670 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007671 crt = SSL_get_certificate(ctx->ssl);
Emeric Brun7f56e742012-10-19 18:15:40 +02007672 if (!crt)
7673 return 0;
7674
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007675 X509_ALGOR_get0(&algorithm, NULL, NULL, X509_get0_tbs_sigalg(crt));
7676 nid = OBJ_obj2nid(algorithm);
Emeric Brun7f56e742012-10-19 18:15:40 +02007677
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007678 smp->data.u.str.area = (char *)OBJ_nid2sn(nid);
7679 if (!smp->data.u.str.area) {
Emeric Brunba841a12014-04-30 17:05:08 +02007680 /* SSL_get_peer_certificate increase X509 * ref count */
7681 if (cert_peer)
7682 X509_free(crt);
Emeric Brun7f56e742012-10-19 18:15:40 +02007683 return 0;
Emeric Brun9bf3ba22013-10-07 14:31:44 +02007684 }
Emeric Brun7f56e742012-10-19 18:15:40 +02007685
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007686 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01007687 smp->flags |= SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007688 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brunba841a12014-04-30 17:05:08 +02007689 /* SSL_get_peer_certificate increase X509 * ref count */
7690 if (cert_peer)
7691 X509_free(crt);
Emeric Brun7f56e742012-10-19 18:15:40 +02007692
7693 return 1;
7694}
7695
Emeric Brunba841a12014-04-30 17:05:08 +02007696/* string, returns the certificate's key algorithm.
7697 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7698 * should be use.
7699 */
Emeric Brun521a0112012-10-22 12:22:55 +02007700static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007701smp_fetch_ssl_x_key_alg(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun521a0112012-10-22 12:22:55 +02007702{
Emeric Brunba841a12014-04-30 17:05:08 +02007703 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun521a0112012-10-22 12:22:55 +02007704 X509 *crt;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007705 ASN1_OBJECT *algorithm;
Emeric Brun521a0112012-10-22 12:22:55 +02007706 int nid;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007707 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007708 struct ssl_sock_ctx *ctx;
Emeric Brun521a0112012-10-22 12:22:55 +02007709
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007710 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007711 if (!conn || conn->xprt != &ssl_sock)
7712 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007713 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007714
7715 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun521a0112012-10-22 12:22:55 +02007716 smp->flags |= SMP_F_MAY_CHANGE;
7717 return 0;
7718 }
7719
Emeric Brunba841a12014-04-30 17:05:08 +02007720 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007721 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007722 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007723 crt = SSL_get_certificate(ctx->ssl);
Emeric Brun521a0112012-10-22 12:22:55 +02007724 if (!crt)
7725 return 0;
7726
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007727 X509_PUBKEY_get0_param(&algorithm, NULL, NULL, NULL, X509_get_X509_PUBKEY(crt));
7728 nid = OBJ_obj2nid(algorithm);
Emeric Brun521a0112012-10-22 12:22:55 +02007729
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007730 smp->data.u.str.area = (char *)OBJ_nid2sn(nid);
7731 if (!smp->data.u.str.area) {
Emeric Brunba841a12014-04-30 17:05:08 +02007732 /* SSL_get_peer_certificate increase X509 * ref count */
7733 if (cert_peer)
7734 X509_free(crt);
Emeric Brun521a0112012-10-22 12:22:55 +02007735 return 0;
Emeric Brun9bf3ba22013-10-07 14:31:44 +02007736 }
Emeric Brun521a0112012-10-22 12:22:55 +02007737
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007738 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01007739 smp->flags |= SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007740 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brunba841a12014-04-30 17:05:08 +02007741 if (cert_peer)
7742 X509_free(crt);
Emeric Brun521a0112012-10-22 12:22:55 +02007743
7744 return 1;
7745}
7746
Emeric Brun645ae792014-04-30 14:21:06 +02007747/* boolean, returns true if front conn. transport layer is SSL.
7748 * This function is also usable on backend conn if the fetch keyword 5th
7749 * char is 'b'.
7750 */
Willy Tarreau7875d092012-09-10 08:20:03 +02007751static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007752smp_fetch_ssl_fc(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02007753{
Emeric Bruneb8def92018-02-19 15:59:48 +01007754 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7755 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007756
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007757 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007758 smp->data.u.sint = (conn && conn->xprt == &ssl_sock);
Willy Tarreau7875d092012-09-10 08:20:03 +02007759 return 1;
7760}
7761
Emeric Brun2525b6b2012-10-18 15:59:43 +02007762/* boolean, returns true if client present a SNI */
Willy Tarreau7875d092012-09-10 08:20:03 +02007763static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007764smp_fetch_ssl_fc_has_sni(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02007765{
7766#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007767 struct connection *conn = objt_conn(smp->sess->origin);
Olivier Houchard66ab4982019-02-26 18:37:15 +01007768 struct ssl_sock_ctx *ctx = conn ? conn->xprt_ctx : NULL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007769
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007770 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007771 smp->data.u.sint = (conn && conn->xprt == &ssl_sock) &&
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007772 conn->xprt_ctx &&
Olivier Houchard66ab4982019-02-26 18:37:15 +01007773 SSL_get_servername(ctx->ssl, TLSEXT_NAMETYPE_host_name) != NULL;
Willy Tarreau7875d092012-09-10 08:20:03 +02007774 return 1;
7775#else
7776 return 0;
7777#endif
7778}
7779
Emeric Brun74f7ffa2018-02-19 16:14:12 +01007780/* boolean, returns true if client session has been resumed.
7781 * This function is also usable on backend conn if the fetch keyword 5th
7782 * char is 'b'.
7783 */
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02007784static int
7785smp_fetch_ssl_fc_is_resumed(const struct arg *args, struct sample *smp, const char *kw, void *private)
7786{
Emeric Brun74f7ffa2018-02-19 16:14:12 +01007787 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7788 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007789 struct ssl_sock_ctx *ctx = conn ? conn->xprt_ctx : NULL;
Emeric Brun74f7ffa2018-02-19 16:14:12 +01007790
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02007791
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007792 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007793 smp->data.u.sint = (conn && conn->xprt == &ssl_sock) &&
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02007794 conn->xprt_ctx &&
Olivier Houchard66ab4982019-02-26 18:37:15 +01007795 SSL_session_reused(ctx->ssl);
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02007796 return 1;
7797}
7798
Emeric Brun645ae792014-04-30 14:21:06 +02007799/* string, returns the used cipher if front conn. transport layer is SSL.
7800 * This function is also usable on backend conn if the fetch keyword 5th
7801 * char is 'b'.
7802 */
Emeric Brun589fcad2012-10-16 14:13:26 +02007803static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007804smp_fetch_ssl_fc_cipher(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02007805{
Emeric Bruneb8def92018-02-19 15:59:48 +01007806 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7807 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007808 struct ssl_sock_ctx *ctx;
Emeric Brun589fcad2012-10-16 14:13:26 +02007809
Willy Tarreaube508f12016-03-10 11:47:01 +01007810 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007811 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02007812 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007813 ctx = conn->xprt_ctx;
Emeric Brun589fcad2012-10-16 14:13:26 +02007814
Olivier Houchard66ab4982019-02-26 18:37:15 +01007815 smp->data.u.str.area = (char *)SSL_get_cipher_name(ctx->ssl);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007816 if (!smp->data.u.str.area)
Emeric Brun589fcad2012-10-16 14:13:26 +02007817 return 0;
7818
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007819 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01007820 smp->flags |= SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007821 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brun589fcad2012-10-16 14:13:26 +02007822
7823 return 1;
7824}
7825
Emeric Brun645ae792014-04-30 14:21:06 +02007826/* integer, returns the algoritm's keysize if front conn. transport layer
7827 * is SSL.
7828 * This function is also usable on backend conn if the fetch keyword 5th
7829 * char is 'b'.
7830 */
Emeric Brun589fcad2012-10-16 14:13:26 +02007831static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007832smp_fetch_ssl_fc_alg_keysize(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02007833{
Emeric Bruneb8def92018-02-19 15:59:48 +01007834 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7835 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007836 struct ssl_sock_ctx *ctx;
Willy Tarreaue237fe12016-03-10 17:05:28 +01007837 int sint;
Willy Tarreaube508f12016-03-10 11:47:01 +01007838
Emeric Brun589fcad2012-10-16 14:13:26 +02007839 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007840 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02007841 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007842 ctx = conn->xprt_ctx;
Emeric Brun589fcad2012-10-16 14:13:26 +02007843
Olivier Houchard66ab4982019-02-26 18:37:15 +01007844 if (!SSL_get_cipher_bits(ctx->ssl, &sint))
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007845 return 0;
7846
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007847 smp->data.u.sint = sint;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007848 smp->data.type = SMP_T_SINT;
Emeric Brun589fcad2012-10-16 14:13:26 +02007849
7850 return 1;
7851}
7852
Emeric Brun645ae792014-04-30 14:21:06 +02007853/* integer, returns the used keysize if front conn. transport layer is SSL.
7854 * This function is also usable on backend conn if the fetch keyword 5th
7855 * char is 'b'.
7856 */
Emeric Brun589fcad2012-10-16 14:13:26 +02007857static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007858smp_fetch_ssl_fc_use_keysize(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02007859{
Emeric Bruneb8def92018-02-19 15:59:48 +01007860 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7861 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007862 struct ssl_sock_ctx *ctx;
Willy Tarreaube508f12016-03-10 11:47:01 +01007863
Emeric Brun589fcad2012-10-16 14:13:26 +02007864 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007865 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7866 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007867 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007868
Olivier Houchard66ab4982019-02-26 18:37:15 +01007869 smp->data.u.sint = (unsigned int)SSL_get_cipher_bits(ctx->ssl, NULL);
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007870 if (!smp->data.u.sint)
Emeric Brun589fcad2012-10-16 14:13:26 +02007871 return 0;
7872
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007873 smp->data.type = SMP_T_SINT;
Emeric Brun589fcad2012-10-16 14:13:26 +02007874
7875 return 1;
7876}
7877
Bernard Spil13c53f82018-02-15 13:34:58 +01007878#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Willy Tarreau7875d092012-09-10 08:20:03 +02007879static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007880smp_fetch_ssl_fc_npn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreaua33c6542012-10-15 13:19:06 +02007881{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007882 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007883 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007884
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01007885 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007886 smp->data.type = SMP_T_STR;
Willy Tarreaua33c6542012-10-15 13:19:06 +02007887
Olivier Houchard6b77f492018-11-22 18:18:29 +01007888 conn = (kw[4] != 'b' ) ? objt_conn(smp->sess->origin) :
7889 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007890 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7891 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007892 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007893
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007894 smp->data.u.str.area = NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007895 SSL_get0_next_proto_negotiated(ctx->ssl,
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007896 (const unsigned char **)&smp->data.u.str.area,
7897 (unsigned *)&smp->data.u.str.data);
Willy Tarreaua33c6542012-10-15 13:19:06 +02007898
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007899 if (!smp->data.u.str.area)
Willy Tarreaua33c6542012-10-15 13:19:06 +02007900 return 0;
7901
7902 return 1;
Willy Tarreaua33c6542012-10-15 13:19:06 +02007903}
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02007904#endif
Willy Tarreaua33c6542012-10-15 13:19:06 +02007905
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01007906#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02007907static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007908smp_fetch_ssl_fc_alpn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreauab861d32013-04-02 02:30:41 +02007909{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007910 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007911 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007912
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01007913 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007914 smp->data.type = SMP_T_STR;
Willy Tarreauab861d32013-04-02 02:30:41 +02007915
Olivier Houchard6b77f492018-11-22 18:18:29 +01007916 conn = (kw[4] != 'b' ) ? objt_conn(smp->sess->origin) :
7917 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
7918
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007919 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Willy Tarreauab861d32013-04-02 02:30:41 +02007920 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007921 ctx = conn->xprt_ctx;
Willy Tarreauab861d32013-04-02 02:30:41 +02007922
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007923 smp->data.u.str.area = NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007924 SSL_get0_alpn_selected(ctx->ssl,
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007925 (const unsigned char **)&smp->data.u.str.area,
7926 (unsigned *)&smp->data.u.str.data);
Willy Tarreauab861d32013-04-02 02:30:41 +02007927
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007928 if (!smp->data.u.str.area)
Willy Tarreauab861d32013-04-02 02:30:41 +02007929 return 0;
7930
7931 return 1;
7932}
7933#endif
7934
Emeric Brun645ae792014-04-30 14:21:06 +02007935/* string, returns the used protocol if front conn. transport layer is SSL.
7936 * This function is also usable on backend conn if the fetch keyword 5th
7937 * char is 'b'.
7938 */
Willy Tarreaua33c6542012-10-15 13:19:06 +02007939static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007940smp_fetch_ssl_fc_protocol(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02007941{
Emeric Bruneb8def92018-02-19 15:59:48 +01007942 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7943 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007944 struct ssl_sock_ctx *ctx;
Willy Tarreaube508f12016-03-10 11:47:01 +01007945
Emeric Brun589fcad2012-10-16 14:13:26 +02007946 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007947 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7948 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007949 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007950
Olivier Houchard66ab4982019-02-26 18:37:15 +01007951 smp->data.u.str.area = (char *)SSL_get_version(ctx->ssl);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007952 if (!smp->data.u.str.area)
Emeric Brun589fcad2012-10-16 14:13:26 +02007953 return 0;
7954
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007955 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01007956 smp->flags = SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007957 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brun589fcad2012-10-16 14:13:26 +02007958
7959 return 1;
7960}
7961
Willy Tarreau87b09662015-04-03 00:22:06 +02007962/* binary, returns the SSL stream id if front conn. transport layer is SSL.
Emeric Brun645ae792014-04-30 14:21:06 +02007963 * This function is also usable on backend conn if the fetch keyword 5th
7964 * char is 'b'.
7965 */
Willy Tarreau9a1ab082019-05-09 13:26:41 +02007966#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
Emeric Brun589fcad2012-10-16 14:13:26 +02007967static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007968smp_fetch_ssl_fc_session_id(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunfe68f682012-10-16 14:59:28 +02007969{
Emeric Bruneb8def92018-02-19 15:59:48 +01007970 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7971 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaue237fe12016-03-10 17:05:28 +01007972 SSL_SESSION *ssl_sess;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007973 struct ssl_sock_ctx *ctx;
Willy Tarreaube508f12016-03-10 11:47:01 +01007974
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01007975 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007976 smp->data.type = SMP_T_BIN;
Emeric Brunfe68f682012-10-16 14:59:28 +02007977
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007978 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7979 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007980 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007981
Olivier Houchard66ab4982019-02-26 18:37:15 +01007982 ssl_sess = SSL_get_session(ctx->ssl);
Willy Tarreau192252e2015-04-04 01:47:55 +02007983 if (!ssl_sess)
Emeric Brunfe68f682012-10-16 14:59:28 +02007984 return 0;
7985
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007986 smp->data.u.str.area = (char *)SSL_SESSION_get_id(ssl_sess,
7987 (unsigned int *)&smp->data.u.str.data);
7988 if (!smp->data.u.str.area || !smp->data.u.str.data)
Emeric Brunfe68f682012-10-16 14:59:28 +02007989 return 0;
7990
7991 return 1;
Emeric Brunfe68f682012-10-16 14:59:28 +02007992}
Patrick Hemmer41966772018-04-28 19:15:48 -04007993#endif
7994
Emeric Brunfe68f682012-10-16 14:59:28 +02007995
Emmanuel Hocdet839af572019-05-14 16:27:35 +02007996#if HA_OPENSSL_VERSION_NUMBER >= 0x10100000L
Patrick Hemmere0275472018-04-28 19:15:51 -04007997static int
Patrick Hemmer65674662019-06-04 08:13:03 -04007998smp_fetch_ssl_fc_random(const struct arg *args, struct sample *smp, const char *kw, void *private)
7999{
8000 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
8001 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
8002 struct buffer *data;
8003 struct ssl_sock_ctx *ctx;
8004
8005 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8006 return 0;
8007 ctx = conn->xprt_ctx;
8008
8009 data = get_trash_chunk();
8010 if (kw[7] == 'c')
8011 data->data = SSL_get_client_random(ctx->ssl,
8012 (unsigned char *) data->area,
8013 data->size);
8014 else
8015 data->data = SSL_get_server_random(ctx->ssl,
8016 (unsigned char *) data->area,
8017 data->size);
8018 if (!data->data)
8019 return 0;
8020
8021 smp->flags = 0;
8022 smp->data.type = SMP_T_BIN;
8023 smp->data.u.str = *data;
8024
8025 return 1;
8026}
8027
8028static int
Patrick Hemmere0275472018-04-28 19:15:51 -04008029smp_fetch_ssl_fc_session_key(const struct arg *args, struct sample *smp, const char *kw, void *private)
8030{
8031 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
8032 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
8033 SSL_SESSION *ssl_sess;
Willy Tarreau83061a82018-07-13 11:56:34 +02008034 struct buffer *data;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008035 struct ssl_sock_ctx *ctx;
Patrick Hemmere0275472018-04-28 19:15:51 -04008036
8037 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8038 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008039 ctx = conn->xprt_ctx;
Patrick Hemmere0275472018-04-28 19:15:51 -04008040
Olivier Houchard66ab4982019-02-26 18:37:15 +01008041 ssl_sess = SSL_get_session(ctx->ssl);
Patrick Hemmere0275472018-04-28 19:15:51 -04008042 if (!ssl_sess)
8043 return 0;
8044
8045 data = get_trash_chunk();
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008046 data->data = SSL_SESSION_get_master_key(ssl_sess,
8047 (unsigned char *) data->area,
8048 data->size);
8049 if (!data->data)
Patrick Hemmere0275472018-04-28 19:15:51 -04008050 return 0;
8051
8052 smp->flags = 0;
8053 smp->data.type = SMP_T_BIN;
8054 smp->data.u.str = *data;
8055
8056 return 1;
8057}
8058#endif
8059
Patrick Hemmer41966772018-04-28 19:15:48 -04008060#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emeric Brunfe68f682012-10-16 14:59:28 +02008061static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008062smp_fetch_ssl_fc_sni(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02008063{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008064 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008065 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008066
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008067 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008068 smp->data.type = SMP_T_STR;
Willy Tarreau7875d092012-09-10 08:20:03 +02008069
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02008070 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008071 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8072 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008073 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008074
Olivier Houchard66ab4982019-02-26 18:37:15 +01008075 smp->data.u.str.area = (char *)SSL_get_servername(ctx->ssl, TLSEXT_NAMETYPE_host_name);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008076 if (!smp->data.u.str.area)
Willy Tarreau3e394c92012-09-14 23:56:58 +02008077 return 0;
8078
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008079 smp->data.u.str.data = strlen(smp->data.u.str.area);
Willy Tarreau7875d092012-09-10 08:20:03 +02008080 return 1;
Willy Tarreau7875d092012-09-10 08:20:03 +02008081}
Patrick Hemmer41966772018-04-28 19:15:48 -04008082#endif
Willy Tarreau7875d092012-09-10 08:20:03 +02008083
David Sc1ad52e2014-04-08 18:48:47 -04008084static int
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008085smp_fetch_ssl_fc_cl_bin(const struct arg *args, struct sample *smp, const char *kw, void *private)
8086{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008087 struct connection *conn;
8088 struct ssl_capture *capture;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008089 struct ssl_sock_ctx *ctx;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008090
8091 conn = objt_conn(smp->sess->origin);
8092 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8093 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008094 ctx = conn->xprt_ctx;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008095
Olivier Houchard66ab4982019-02-26 18:37:15 +01008096 capture = SSL_get_ex_data(ctx->ssl, ssl_capture_ptr_index);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008097 if (!capture)
8098 return 0;
8099
8100 smp->flags = SMP_F_CONST;
8101 smp->data.type = SMP_T_BIN;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008102 smp->data.u.str.area = capture->ciphersuite;
8103 smp->data.u.str.data = capture->ciphersuite_len;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008104 return 1;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008105}
8106
8107static int
8108smp_fetch_ssl_fc_cl_hex(const struct arg *args, struct sample *smp, const char *kw, void *private)
8109{
Willy Tarreau83061a82018-07-13 11:56:34 +02008110 struct buffer *data;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008111
8112 if (!smp_fetch_ssl_fc_cl_bin(args, smp, kw, private))
8113 return 0;
8114
8115 data = get_trash_chunk();
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008116 dump_binary(data, smp->data.u.str.area, smp->data.u.str.data);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008117 smp->data.type = SMP_T_BIN;
8118 smp->data.u.str = *data;
8119 return 1;
8120}
8121
8122static int
8123smp_fetch_ssl_fc_cl_xxh64(const struct arg *args, struct sample *smp, const char *kw, void *private)
8124{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008125 struct connection *conn;
8126 struct ssl_capture *capture;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008127 struct ssl_sock_ctx *ctx;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008128
8129 conn = objt_conn(smp->sess->origin);
8130 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8131 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008132 ctx = conn->xprt_ctx;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008133
Olivier Houchard66ab4982019-02-26 18:37:15 +01008134 capture = SSL_get_ex_data(ctx->ssl, ssl_capture_ptr_index);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008135 if (!capture)
8136 return 0;
8137
8138 smp->data.type = SMP_T_SINT;
8139 smp->data.u.sint = capture->xxh64;
8140 return 1;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008141}
8142
8143static int
8144smp_fetch_ssl_fc_cl_str(const struct arg *args, struct sample *smp, const char *kw, void *private)
8145{
Willy Tarreau5db847a2019-05-09 14:13:35 +02008146#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL)
Willy Tarreau83061a82018-07-13 11:56:34 +02008147 struct buffer *data;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008148 int i;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008149
8150 if (!smp_fetch_ssl_fc_cl_bin(args, smp, kw, private))
8151 return 0;
8152
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008153 data = get_trash_chunk();
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008154 for (i = 0; i + 1 < smp->data.u.str.data; i += 2) {
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02008155 const char *str;
8156 const SSL_CIPHER *cipher;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008157 const unsigned char *bin = (const unsigned char *) smp->data.u.str.area + i;
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02008158 uint16_t id = (bin[0] << 8) | bin[1];
8159#if defined(OPENSSL_IS_BORINGSSL)
8160 cipher = SSL_get_cipher_by_value(id);
8161#else
Willy Tarreaub7290772018-10-15 11:01:59 +02008162 struct connection *conn = __objt_conn(smp->sess->origin);
Olivier Houchard66ab4982019-02-26 18:37:15 +01008163 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
8164 cipher = SSL_CIPHER_find(ctx->ssl, bin);
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02008165#endif
8166 str = SSL_CIPHER_get_name(cipher);
8167 if (!str || strcmp(str, "(NONE)") == 0)
8168 chunk_appendf(data, "%sUNKNOWN(%04x)", i == 0 ? "" : ",", id);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008169 else
8170 chunk_appendf(data, "%s%s", i == 0 ? "" : ",", str);
8171 }
8172 smp->data.type = SMP_T_STR;
8173 smp->data.u.str = *data;
8174 return 1;
8175#else
8176 return smp_fetch_ssl_fc_cl_xxh64(args, smp, kw, private);
8177#endif
8178}
8179
Willy Tarreau9a1ab082019-05-09 13:26:41 +02008180#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008181static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008182smp_fetch_ssl_fc_unique_id(const struct arg *args, struct sample *smp, const char *kw, void *private)
David Sc1ad52e2014-04-08 18:48:47 -04008183{
Emeric Bruneb8def92018-02-19 15:59:48 +01008184 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
8185 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
David Sc1ad52e2014-04-08 18:48:47 -04008186 int finished_len;
Willy Tarreau83061a82018-07-13 11:56:34 +02008187 struct buffer *finished_trash;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008188 struct ssl_sock_ctx *ctx;
David Sc1ad52e2014-04-08 18:48:47 -04008189
8190 smp->flags = 0;
David Sc1ad52e2014-04-08 18:48:47 -04008191 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8192 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008193 ctx = conn->xprt_ctx;
David Sc1ad52e2014-04-08 18:48:47 -04008194
8195 if (!(conn->flags & CO_FL_CONNECTED)) {
8196 smp->flags |= SMP_F_MAY_CHANGE;
8197 return 0;
8198 }
8199
8200 finished_trash = get_trash_chunk();
Olivier Houchard66ab4982019-02-26 18:37:15 +01008201 if (!SSL_session_reused(ctx->ssl))
8202 finished_len = SSL_get_peer_finished(ctx->ssl,
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008203 finished_trash->area,
8204 finished_trash->size);
David Sc1ad52e2014-04-08 18:48:47 -04008205 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01008206 finished_len = SSL_get_finished(ctx->ssl,
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008207 finished_trash->area,
8208 finished_trash->size);
David Sc1ad52e2014-04-08 18:48:47 -04008209
8210 if (!finished_len)
8211 return 0;
8212
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008213 finished_trash->data = finished_len;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02008214 smp->data.u.str = *finished_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008215 smp->data.type = SMP_T_BIN;
David Sc1ad52e2014-04-08 18:48:47 -04008216
8217 return 1;
David Sc1ad52e2014-04-08 18:48:47 -04008218}
Patrick Hemmer41966772018-04-28 19:15:48 -04008219#endif
David Sc1ad52e2014-04-08 18:48:47 -04008220
Emeric Brun2525b6b2012-10-18 15:59:43 +02008221/* integer, returns 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(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)
8230 return 0;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008231 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008232
8233 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02008234 smp->flags = SMP_F_MAY_CHANGE;
8235 return 0;
8236 }
8237
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 = (unsigned long long int)SSL_SOCK_ST_TO_CA_ERROR(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 depth of the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02008246static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008247smp_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 +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)
Emeric Brunf282a812012-09-21 15:27:54 +02008254 return 0;
8255
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008256 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02008257 smp->flags = SMP_F_MAY_CHANGE;
8258 return 0;
8259 }
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008260 ctx = conn->xprt_ctx;
Emeric Brunf282a812012-09-21 15:27:54 +02008261
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008262 smp->data.type = SMP_T_SINT;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008263 smp->data.u.sint = (long long int)SSL_SOCK_ST_TO_CAEDEPTH(ctx->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02008264 smp->flags = 0;
8265
8266 return 1;
8267}
8268
Emeric Brun2525b6b2012-10-18 15:59:43 +02008269/* integer, returns the first verify error on client certificate */
Emeric Brunf282a812012-09-21 15:27:54 +02008270static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008271smp_fetch_ssl_c_err(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunf282a812012-09-21 15:27:54 +02008272{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008273 struct connection *conn;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008274 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008275
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02008276 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008277 if (!conn || conn->xprt != &ssl_sock)
8278 return 0;
8279
8280 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02008281 smp->flags = SMP_F_MAY_CHANGE;
8282 return 0;
8283 }
8284
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008285 ctx = conn->xprt_ctx;
8286
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008287 smp->data.type = SMP_T_SINT;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008288 smp->data.u.sint = (long long int)SSL_SOCK_ST_TO_CRTERROR(ctx->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02008289 smp->flags = 0;
8290
8291 return 1;
8292}
8293
Emeric Brun2525b6b2012-10-18 15:59:43 +02008294/* integer, returns the verify result on client cert */
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02008295static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008296smp_fetch_ssl_c_verify(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02008297{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008298 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008299 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008300
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02008301 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008302 if (!conn || conn->xprt != &ssl_sock)
8303 return 0;
8304
8305 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02008306 smp->flags = SMP_F_MAY_CHANGE;
8307 return 0;
8308 }
8309
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008310 if (!conn->xprt_ctx)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02008311 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008312 ctx = conn->xprt_ctx;
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02008313
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008314 smp->data.type = SMP_T_SINT;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008315 smp->data.u.sint = (long long int)SSL_get_verify_result(ctx->ssl);
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02008316 smp->flags = 0;
8317
8318 return 1;
8319}
8320
Emeric Brunfb510ea2012-10-05 12:00:26 +02008321/* parse the "ca-file" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008322static 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 +02008323{
8324 if (!*args[cur_arg + 1]) {
8325 if (err)
8326 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
8327 return ERR_ALERT | ERR_FATAL;
8328 }
8329
Willy Tarreauef934602016-12-22 23:12:01 +01008330 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
8331 memprintf(&conf->ca_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02008332 else
8333 memprintf(&conf->ca_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02008334
Emeric Brund94b3fe2012-09-20 18:23:56 +02008335 return 0;
8336}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008337static int bind_parse_ca_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8338{
8339 return ssl_bind_parse_ca_file(args, cur_arg, px, &conf->ssl_conf, err);
8340}
Emeric Brund94b3fe2012-09-20 18:23:56 +02008341
Christopher Faulet31af49d2015-06-09 17:29:50 +02008342/* parse the "ca-sign-file" bind keyword */
8343static int bind_parse_ca_sign_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8344{
8345 if (!*args[cur_arg + 1]) {
8346 if (err)
8347 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
8348 return ERR_ALERT | ERR_FATAL;
8349 }
8350
Willy Tarreauef934602016-12-22 23:12:01 +01008351 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
8352 memprintf(&conf->ca_sign_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Christopher Faulet31af49d2015-06-09 17:29:50 +02008353 else
8354 memprintf(&conf->ca_sign_file, "%s", args[cur_arg + 1]);
8355
8356 return 0;
8357}
8358
Bertrand Jacquinff13c062016-11-13 16:37:11 +00008359/* parse the "ca-sign-pass" bind keyword */
Christopher Faulet31af49d2015-06-09 17:29:50 +02008360static int bind_parse_ca_sign_pass(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8361{
8362 if (!*args[cur_arg + 1]) {
8363 if (err)
8364 memprintf(err, "'%s' : missing CAkey password", args[cur_arg]);
8365 return ERR_ALERT | ERR_FATAL;
8366 }
8367 memprintf(&conf->ca_sign_pass, "%s", args[cur_arg + 1]);
8368 return 0;
8369}
8370
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008371/* parse the "ciphers" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008372static 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 +02008373{
8374 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02008375 memprintf(err, "'%s' : missing cipher suite", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008376 return ERR_ALERT | ERR_FATAL;
8377 }
8378
Emeric Brun76d88952012-10-05 15:47:31 +02008379 free(conf->ciphers);
Willy Tarreau4348fad2012-09-20 16:48:07 +02008380 conf->ciphers = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008381 return 0;
8382}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008383static int bind_parse_ciphers(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8384{
8385 return ssl_bind_parse_ciphers(args, cur_arg, px, &conf->ssl_conf, err);
8386}
Dirkjan Bussink415150f2018-09-14 11:14:21 +02008387
Emmanuel Hocdet839af572019-05-14 16:27:35 +02008388#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02008389/* parse the "ciphersuites" bind keyword */
8390static int ssl_bind_parse_ciphersuites(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
8391{
8392 if (!*args[cur_arg + 1]) {
8393 memprintf(err, "'%s' : missing cipher suite", args[cur_arg]);
8394 return ERR_ALERT | ERR_FATAL;
8395 }
8396
8397 free(conf->ciphersuites);
8398 conf->ciphersuites = strdup(args[cur_arg + 1]);
8399 return 0;
8400}
8401static int bind_parse_ciphersuites(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8402{
8403 return ssl_bind_parse_ciphersuites(args, cur_arg, px, &conf->ssl_conf, err);
8404}
8405#endif
8406
Willy Tarreaubbc91962019-10-16 16:42:19 +02008407/* parse the "crt" bind keyword. Returns a set of ERR_* flags possibly with an error in <err>. */
Willy Tarreau4348fad2012-09-20 16:48:07 +02008408static 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 +02008409{
Willy Tarreau38011032013-08-13 16:59:39 +02008410 char path[MAXPATHLEN];
Willy Tarreaub75d6922014-04-14 18:05:41 +02008411
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008412 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02008413 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008414 return ERR_ALERT | ERR_FATAL;
8415 }
8416
Willy Tarreauef934602016-12-22 23:12:01 +01008417 if ((*args[cur_arg + 1] != '/' ) && global_ssl.crt_base) {
8418 if ((strlen(global_ssl.crt_base) + 1 + strlen(args[cur_arg + 1]) + 1) > MAXPATHLEN) {
Emeric Brunc8e8d122012-10-02 18:42:10 +02008419 memprintf(err, "'%s' : path too long", args[cur_arg]);
8420 return ERR_ALERT | ERR_FATAL;
8421 }
Willy Tarreauef934602016-12-22 23:12:01 +01008422 snprintf(path, sizeof(path), "%s/%s", global_ssl.crt_base, args[cur_arg + 1]);
Willy Tarreaubbc91962019-10-16 16:42:19 +02008423 return ssl_sock_load_cert(path, conf, err);
Emeric Brunc8e8d122012-10-02 18:42:10 +02008424 }
8425
Willy Tarreaubbc91962019-10-16 16:42:19 +02008426 return ssl_sock_load_cert(args[cur_arg + 1], conf, err);
Emeric Brund94b3fe2012-09-20 18:23:56 +02008427}
8428
Willy Tarreaubbc91962019-10-16 16:42:19 +02008429/* 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 +01008430static int bind_parse_crt_list(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8431{
Willy Tarreaubbc91962019-10-16 16:42:19 +02008432 int err_code;
8433
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01008434 if (!*args[cur_arg + 1]) {
8435 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
8436 return ERR_ALERT | ERR_FATAL;
8437 }
8438
Willy Tarreaubbc91962019-10-16 16:42:19 +02008439 err_code = ssl_sock_load_cert_list_file(args[cur_arg + 1], conf, px, err);
8440 if (err_code)
Willy Tarreauad1731d2013-04-02 17:35:58 +02008441 memprintf(err, "'%s' : %s", args[cur_arg], *err);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01008442
Willy Tarreaubbc91962019-10-16 16:42:19 +02008443 return err_code;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01008444}
8445
Emeric Brunfb510ea2012-10-05 12:00:26 +02008446/* parse the "crl-file" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008447static 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 +02008448{
Emeric Brun051cdab2012-10-02 19:25:50 +02008449#ifndef X509_V_FLAG_CRL_CHECK
8450 if (err)
8451 memprintf(err, "'%s' : library does not support CRL verify", args[cur_arg]);
8452 return ERR_ALERT | ERR_FATAL;
8453#else
Emeric Brund94b3fe2012-09-20 18:23:56 +02008454 if (!*args[cur_arg + 1]) {
8455 if (err)
8456 memprintf(err, "'%s' : missing CRLfile path", args[cur_arg]);
8457 return ERR_ALERT | ERR_FATAL;
8458 }
Emeric Brun2b58d042012-09-20 17:10:03 +02008459
Willy Tarreauef934602016-12-22 23:12:01 +01008460 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
8461 memprintf(&conf->crl_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02008462 else
8463 memprintf(&conf->crl_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02008464
Emeric Brun2b58d042012-09-20 17:10:03 +02008465 return 0;
Emeric Brun051cdab2012-10-02 19:25:50 +02008466#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02008467}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008468static int bind_parse_crl_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8469{
8470 return ssl_bind_parse_crl_file(args, cur_arg, px, &conf->ssl_conf, err);
8471}
Emeric Brun2b58d042012-09-20 17:10:03 +02008472
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01008473/* parse the "curves" bind keyword keyword */
8474static int ssl_bind_parse_curves(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
8475{
Willy Tarreau9a1ab082019-05-09 13:26:41 +02008476#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01008477 if (!*args[cur_arg + 1]) {
8478 if (err)
8479 memprintf(err, "'%s' : missing curve suite", args[cur_arg]);
8480 return ERR_ALERT | ERR_FATAL;
8481 }
8482 conf->curves = strdup(args[cur_arg + 1]);
8483 return 0;
8484#else
8485 if (err)
8486 memprintf(err, "'%s' : library does not support curve suite", args[cur_arg]);
8487 return ERR_ALERT | ERR_FATAL;
8488#endif
8489}
8490static int bind_parse_curves(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8491{
8492 return ssl_bind_parse_curves(args, cur_arg, px, &conf->ssl_conf, err);
8493}
8494
Bertrand Jacquinff13c062016-11-13 16:37:11 +00008495/* parse the "ecdhe" bind keyword keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008496static 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 +02008497{
Willy Tarreau9a1ab082019-05-09 13:26:41 +02008498#if HA_OPENSSL_VERSION_NUMBER < 0x0090800fL
Emeric Brun2b58d042012-09-20 17:10:03 +02008499 if (err)
8500 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (too old)", args[cur_arg]);
8501 return ERR_ALERT | ERR_FATAL;
8502#elif defined(OPENSSL_NO_ECDH)
8503 if (err)
8504 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (disabled via OPENSSL_NO_ECDH)", args[cur_arg]);
8505 return ERR_ALERT | ERR_FATAL;
8506#else
8507 if (!*args[cur_arg + 1]) {
8508 if (err)
8509 memprintf(err, "'%s' : missing named curve", args[cur_arg]);
8510 return ERR_ALERT | ERR_FATAL;
8511 }
8512
8513 conf->ecdhe = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008514
8515 return 0;
Emeric Brun2b58d042012-09-20 17:10:03 +02008516#endif
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008517}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008518static int bind_parse_ecdhe(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8519{
8520 return ssl_bind_parse_ecdhe(args, cur_arg, px, &conf->ssl_conf, err);
8521}
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008522
Bertrand Jacquinff13c062016-11-13 16:37:11 +00008523/* parse the "crt-ignore-err" and "ca-ignore-err" bind keywords */
Emeric Brun81c00f02012-09-21 14:31:21 +02008524static int bind_parse_ignore_err(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8525{
8526 int code;
8527 char *p = args[cur_arg + 1];
8528 unsigned long long *ignerr = &conf->crt_ignerr;
8529
8530 if (!*p) {
8531 if (err)
8532 memprintf(err, "'%s' : missing error IDs list", args[cur_arg]);
8533 return ERR_ALERT | ERR_FATAL;
8534 }
8535
8536 if (strcmp(args[cur_arg], "ca-ignore-err") == 0)
8537 ignerr = &conf->ca_ignerr;
8538
8539 if (strcmp(p, "all") == 0) {
8540 *ignerr = ~0ULL;
8541 return 0;
8542 }
8543
8544 while (p) {
8545 code = atoi(p);
8546 if ((code <= 0) || (code > 63)) {
8547 if (err)
8548 memprintf(err, "'%s' : ID '%d' out of range (1..63) in error IDs list '%s'",
8549 args[cur_arg], code, args[cur_arg + 1]);
8550 return ERR_ALERT | ERR_FATAL;
8551 }
8552 *ignerr |= 1ULL << code;
8553 p = strchr(p, ',');
8554 if (p)
8555 p++;
8556 }
8557
Emeric Brun2cb7ae52012-10-05 14:14:21 +02008558 return 0;
8559}
8560
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008561/* parse tls_method_options "no-xxx" and "force-xxx" */
8562static int parse_tls_method_options(char *arg, struct tls_version_filter *methods, char **err)
Emeric Brun2cb7ae52012-10-05 14:14:21 +02008563{
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008564 uint16_t v;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008565 char *p;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008566 p = strchr(arg, '-');
8567 if (!p)
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008568 goto fail;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008569 p++;
8570 if (!strcmp(p, "sslv3"))
8571 v = CONF_SSLV3;
8572 else if (!strcmp(p, "tlsv10"))
8573 v = CONF_TLSV10;
8574 else if (!strcmp(p, "tlsv11"))
8575 v = CONF_TLSV11;
8576 else if (!strcmp(p, "tlsv12"))
8577 v = CONF_TLSV12;
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +02008578 else if (!strcmp(p, "tlsv13"))
8579 v = CONF_TLSV13;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008580 else
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008581 goto fail;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008582 if (!strncmp(arg, "no-", 3))
8583 methods->flags |= methodVersions[v].flag;
8584 else if (!strncmp(arg, "force-", 6))
8585 methods->min = methods->max = v;
8586 else
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008587 goto fail;
Emeric Brun2d0c4822012-10-02 13:45:20 +02008588 return 0;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008589 fail:
8590 if (err)
8591 memprintf(err, "'%s' : option not implemented", arg);
8592 return ERR_ALERT | ERR_FATAL;
Emeric Brun2d0c4822012-10-02 13:45:20 +02008593}
8594
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008595static 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 +02008596{
Emmanuel Hocdet43664762017-08-09 18:26:20 +02008597 return parse_tls_method_options(args[cur_arg], &conf->ssl_conf.ssl_methods, err);
Emeric Brun2cb7ae52012-10-05 14:14:21 +02008598}
8599
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008600static 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 +02008601{
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008602 return parse_tls_method_options(args[*cur_arg], &newsrv->ssl_ctx.methods, err);
8603}
8604
8605/* parse tls_method min/max: "ssl-min-ver" and "ssl-max-ver" */
8606static int parse_tls_method_minmax(char **args, int cur_arg, struct tls_version_filter *methods, char **err)
8607{
8608 uint16_t i, v = 0;
8609 char *argv = args[cur_arg + 1];
8610 if (!*argv) {
8611 if (err)
8612 memprintf(err, "'%s' : missing the ssl/tls version", args[cur_arg]);
8613 return ERR_ALERT | ERR_FATAL;
8614 }
8615 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
8616 if (!strcmp(argv, methodVersions[i].name))
8617 v = i;
8618 if (!v) {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008619 if (err)
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008620 memprintf(err, "'%s' : unknown ssl/tls version", args[cur_arg + 1]);
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008621 return ERR_ALERT | ERR_FATAL;
8622 }
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008623 if (!strcmp("ssl-min-ver", args[cur_arg]))
8624 methods->min = v;
8625 else if (!strcmp("ssl-max-ver", args[cur_arg]))
8626 methods->max = v;
8627 else {
8628 if (err)
8629 memprintf(err, "'%s' : option not implemented", args[cur_arg]);
8630 return ERR_ALERT | ERR_FATAL;
8631 }
Emeric Brun2cb7ae52012-10-05 14:14:21 +02008632 return 0;
Emeric Brun2cb7ae52012-10-05 14:14:21 +02008633}
Emeric Brun2cb7ae52012-10-05 14:14:21 +02008634
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02008635static int ssl_bind_parse_tls_method_minmax(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
8636{
Willy Tarreau9a1ab082019-05-09 13:26:41 +02008637#if (HA_OPENSSL_VERSION_NUMBER < 0x10101000L) && !defined(OPENSSL_IS_BORINGSSL)
Christopher Faulet767a84b2017-11-24 16:50:31 +01008638 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 +02008639#endif
8640 return parse_tls_method_minmax(args, cur_arg, &conf->ssl_methods, err);
8641}
8642
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008643static int bind_parse_tls_method_minmax(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8644{
Emmanuel Hocdet43664762017-08-09 18:26:20 +02008645 return parse_tls_method_minmax(args, cur_arg, &conf->ssl_conf.ssl_methods, err);
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008646}
8647
8648static int srv_parse_tls_method_minmax(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8649{
8650 return parse_tls_method_minmax(args, *cur_arg, &newsrv->ssl_ctx.methods, err);
8651}
8652
Emeric Brun2d0c4822012-10-02 13:45:20 +02008653/* parse the "no-tls-tickets" bind keyword */
Emmanuel Hocdet4608ed92017-01-20 13:06:27 +01008654static 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 +02008655{
Emeric Brun89675492012-10-05 13:48:26 +02008656 conf->ssl_options |= BC_SSL_O_NO_TLS_TICKETS;
Emeric Brun81c00f02012-09-21 14:31:21 +02008657 return 0;
8658}
Emeric Brun2d0c4822012-10-02 13:45:20 +02008659
Olivier Houchardc2aae742017-09-22 18:26:28 +02008660/* parse the "allow-0rtt" bind keyword */
8661static int ssl_bind_parse_allow_0rtt(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
8662{
8663 conf->early_data = 1;
8664 return 0;
8665}
8666
8667static int bind_parse_allow_0rtt(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8668{
Olivier Houchard9679ac92017-10-27 14:58:08 +02008669 conf->ssl_conf.early_data = 1;
Olivier Houchardc2aae742017-09-22 18:26:28 +02008670 return 0;
8671}
8672
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02008673/* parse the "npn" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008674static 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 +02008675{
Bernard Spil13c53f82018-02-15 13:34:58 +01008676#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02008677 char *p1, *p2;
8678
8679 if (!*args[cur_arg + 1]) {
8680 memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[cur_arg]);
8681 return ERR_ALERT | ERR_FATAL;
8682 }
8683
8684 free(conf->npn_str);
8685
Willy Tarreau3724da12016-02-12 17:11:12 +01008686 /* the NPN string is built as a suite of (<len> <name>)*,
8687 * so we reuse each comma to store the next <len> and need
8688 * one more for the end of the string.
8689 */
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02008690 conf->npn_len = strlen(args[cur_arg + 1]) + 1;
Willy Tarreau3724da12016-02-12 17:11:12 +01008691 conf->npn_str = calloc(1, conf->npn_len + 1);
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02008692 memcpy(conf->npn_str + 1, args[cur_arg + 1], conf->npn_len);
8693
8694 /* replace commas with the name length */
8695 p1 = conf->npn_str;
8696 p2 = p1 + 1;
8697 while (1) {
8698 p2 = memchr(p1 + 1, ',', conf->npn_str + conf->npn_len - (p1 + 1));
8699 if (!p2)
8700 p2 = p1 + 1 + strlen(p1 + 1);
8701
8702 if (p2 - (p1 + 1) > 255) {
8703 *p2 = '\0';
8704 memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
8705 return ERR_ALERT | ERR_FATAL;
8706 }
8707
8708 *p1 = p2 - (p1 + 1);
8709 p1 = p2;
8710
8711 if (!*p2)
8712 break;
8713
8714 *(p2++) = '\0';
8715 }
8716 return 0;
8717#else
8718 if (err)
8719 memprintf(err, "'%s' : library does not support TLS NPN extension", args[cur_arg]);
8720 return ERR_ALERT | ERR_FATAL;
8721#endif
8722}
8723
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008724static int bind_parse_npn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8725{
8726 return ssl_bind_parse_npn(args, cur_arg, px, &conf->ssl_conf, err);
8727}
8728
Willy Tarreauab861d32013-04-02 02:30:41 +02008729/* parse the "alpn" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008730static 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 +02008731{
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01008732#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02008733 char *p1, *p2;
8734
8735 if (!*args[cur_arg + 1]) {
8736 memprintf(err, "'%s' : missing the comma-delimited ALPN protocol suite", args[cur_arg]);
8737 return ERR_ALERT | ERR_FATAL;
8738 }
8739
8740 free(conf->alpn_str);
8741
Marcoen Hirschbergbef60912016-02-12 17:05:24 +01008742 /* the ALPN string is built as a suite of (<len> <name>)*,
8743 * so we reuse each comma to store the next <len> and need
8744 * one more for the end of the string.
8745 */
Willy Tarreauab861d32013-04-02 02:30:41 +02008746 conf->alpn_len = strlen(args[cur_arg + 1]) + 1;
Marcoen Hirschbergbef60912016-02-12 17:05:24 +01008747 conf->alpn_str = calloc(1, conf->alpn_len + 1);
Willy Tarreauab861d32013-04-02 02:30:41 +02008748 memcpy(conf->alpn_str + 1, args[cur_arg + 1], conf->alpn_len);
8749
8750 /* replace commas with the name length */
8751 p1 = conf->alpn_str;
8752 p2 = p1 + 1;
8753 while (1) {
8754 p2 = memchr(p1 + 1, ',', conf->alpn_str + conf->alpn_len - (p1 + 1));
8755 if (!p2)
8756 p2 = p1 + 1 + strlen(p1 + 1);
8757
8758 if (p2 - (p1 + 1) > 255) {
8759 *p2 = '\0';
8760 memprintf(err, "'%s' : ALPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
8761 return ERR_ALERT | ERR_FATAL;
8762 }
8763
8764 *p1 = p2 - (p1 + 1);
8765 p1 = p2;
8766
8767 if (!*p2)
8768 break;
8769
8770 *(p2++) = '\0';
8771 }
8772 return 0;
8773#else
8774 if (err)
8775 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[cur_arg]);
8776 return ERR_ALERT | ERR_FATAL;
8777#endif
8778}
8779
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008780static int bind_parse_alpn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8781{
8782 return ssl_bind_parse_alpn(args, cur_arg, px, &conf->ssl_conf, err);
8783}
8784
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008785/* parse the "ssl" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02008786static 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 +02008787{
Willy Tarreau71a8c7c2016-12-21 22:04:54 +01008788 conf->xprt = &ssl_sock;
Willy Tarreau4348fad2012-09-20 16:48:07 +02008789 conf->is_ssl = 1;
Emeric Brun76d88952012-10-05 15:47:31 +02008790
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008791 if (global_ssl.listen_default_ciphers && !conf->ssl_conf.ciphers)
8792 conf->ssl_conf.ciphers = strdup(global_ssl.listen_default_ciphers);
Emmanuel Hocdet839af572019-05-14 16:27:35 +02008793#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02008794 if (global_ssl.listen_default_ciphersuites && !conf->ssl_conf.ciphersuites)
8795 conf->ssl_conf.ciphersuites = strdup(global_ssl.listen_default_ciphersuites);
8796#endif
Emmanuel Hocdet4608ed92017-01-20 13:06:27 +01008797 conf->ssl_options |= global_ssl.listen_default_ssloptions;
Emmanuel Hocdet43664762017-08-09 18:26:20 +02008798 conf->ssl_conf.ssl_methods.flags |= global_ssl.listen_default_sslmethods.flags;
8799 if (!conf->ssl_conf.ssl_methods.min)
8800 conf->ssl_conf.ssl_methods.min = global_ssl.listen_default_sslmethods.min;
8801 if (!conf->ssl_conf.ssl_methods.max)
8802 conf->ssl_conf.ssl_methods.max = global_ssl.listen_default_sslmethods.max;
Emeric Brun76d88952012-10-05 15:47:31 +02008803
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008804 return 0;
8805}
8806
Lukas Tribus53ae85c2017-05-04 15:45:40 +00008807/* parse the "prefer-client-ciphers" bind keyword */
8808static int bind_parse_pcc(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8809{
8810 conf->ssl_options |= BC_SSL_O_PREF_CLIE_CIPH;
8811 return 0;
8812}
8813
Christopher Faulet31af49d2015-06-09 17:29:50 +02008814/* parse the "generate-certificates" bind keyword */
8815static int bind_parse_generate_certs(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8816{
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01008817#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Christopher Faulet31af49d2015-06-09 17:29:50 +02008818 conf->generate_certs = 1;
8819#else
8820 memprintf(err, "%sthis version of openssl cannot generate SSL certificates.\n",
8821 err && *err ? *err : "");
8822#endif
8823 return 0;
8824}
8825
Emmanuel Hocdet65623372013-01-24 17:17:15 +01008826/* parse the "strict-sni" bind keyword */
8827static int bind_parse_strict_sni(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8828{
8829 conf->strict_sni = 1;
8830 return 0;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008831}
8832
8833/* parse the "tls-ticket-keys" bind keyword */
8834static int bind_parse_tls_ticket_keys(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8835{
8836#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
Christopher Faulete566f3d2019-10-21 09:55:49 +02008837 FILE *f = NULL;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008838 int i = 0;
8839 char thisline[LINESIZE];
Christopher Faulete566f3d2019-10-21 09:55:49 +02008840 struct tls_keys_ref *keys_ref = NULL;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008841
8842 if (!*args[cur_arg + 1]) {
8843 if (err)
8844 memprintf(err, "'%s' : missing TLS ticket keys file path", args[cur_arg]);
Christopher Faulete566f3d2019-10-21 09:55:49 +02008845 goto fail;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008846 }
8847
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02008848 keys_ref = tlskeys_ref_lookup(args[cur_arg + 1]);
Willy Tarreau17b4aa12018-07-17 10:05:32 +02008849 if (keys_ref) {
8850 keys_ref->refcount++;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02008851 conf->keys_ref = keys_ref;
8852 return 0;
8853 }
8854
Christopher Faulete566f3d2019-10-21 09:55:49 +02008855 keys_ref = calloc(1, sizeof(*keys_ref));
Emeric Brun09852f72019-01-10 10:51:13 +01008856 if (!keys_ref) {
8857 if (err)
8858 memprintf(err, "'%s' : allocation error", args[cur_arg+1]);
Christopher Faulete566f3d2019-10-21 09:55:49 +02008859 goto fail;
Emeric Brun09852f72019-01-10 10:51:13 +01008860 }
8861
Emeric Brun9e754772019-01-10 17:51:55 +01008862 keys_ref->tlskeys = malloc(TLS_TICKETS_NO * sizeof(union tls_sess_key));
Emeric Brun09852f72019-01-10 10:51:13 +01008863 if (!keys_ref->tlskeys) {
Emeric Brun09852f72019-01-10 10:51:13 +01008864 if (err)
8865 memprintf(err, "'%s' : allocation error", args[cur_arg+1]);
Christopher Faulete566f3d2019-10-21 09:55:49 +02008866 goto fail;
Emeric Brun09852f72019-01-10 10:51:13 +01008867 }
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008868
8869 if ((f = fopen(args[cur_arg + 1], "r")) == NULL) {
8870 if (err)
8871 memprintf(err, "'%s' : unable to load ssl tickets keys file", args[cur_arg+1]);
Christopher Faulete566f3d2019-10-21 09:55:49 +02008872 goto fail;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008873 }
8874
Nenad Merdanovic146defa2015-05-09 08:46:00 +02008875 keys_ref->filename = strdup(args[cur_arg + 1]);
Emeric Brun09852f72019-01-10 10:51:13 +01008876 if (!keys_ref->filename) {
Emeric Brun09852f72019-01-10 10:51:13 +01008877 if (err)
8878 memprintf(err, "'%s' : allocation error", args[cur_arg+1]);
Christopher Faulete566f3d2019-10-21 09:55:49 +02008879 goto fail;
Emeric Brun09852f72019-01-10 10:51:13 +01008880 }
Nenad Merdanovic146defa2015-05-09 08:46:00 +02008881
Emeric Brun9e754772019-01-10 17:51:55 +01008882 keys_ref->key_size_bits = 0;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008883 while (fgets(thisline, sizeof(thisline), f) != NULL) {
8884 int len = strlen(thisline);
Emeric Brun9e754772019-01-10 17:51:55 +01008885 int dec_size;
8886
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008887 /* Strip newline characters from the end */
8888 if(thisline[len - 1] == '\n')
8889 thisline[--len] = 0;
8890
8891 if(thisline[len - 1] == '\r')
8892 thisline[--len] = 0;
8893
Emeric Brun9e754772019-01-10 17:51:55 +01008894 dec_size = base64dec(thisline, len, (char *) (keys_ref->tlskeys + i % TLS_TICKETS_NO), sizeof(union tls_sess_key));
8895 if (dec_size < 0) {
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008896 if (err)
8897 memprintf(err, "'%s' : unable to decode base64 key on line %d", args[cur_arg+1], i + 1);
Christopher Faulete566f3d2019-10-21 09:55:49 +02008898 goto fail;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008899 }
Emeric Brun9e754772019-01-10 17:51:55 +01008900 else if (!keys_ref->key_size_bits && (dec_size == sizeof(struct tls_sess_key_128))) {
8901 keys_ref->key_size_bits = 128;
8902 }
8903 else if (!keys_ref->key_size_bits && (dec_size == sizeof(struct tls_sess_key_256))) {
8904 keys_ref->key_size_bits = 256;
8905 }
8906 else if (((dec_size != sizeof(struct tls_sess_key_128)) && (dec_size != sizeof(struct tls_sess_key_256)))
8907 || ((dec_size == sizeof(struct tls_sess_key_128) && (keys_ref->key_size_bits != 128)))
8908 || ((dec_size == sizeof(struct tls_sess_key_256) && (keys_ref->key_size_bits != 256)))) {
Emeric Brun9e754772019-01-10 17:51:55 +01008909 if (err)
8910 memprintf(err, "'%s' : wrong sized key on line %d", args[cur_arg+1], i + 1);
Christopher Faulete566f3d2019-10-21 09:55:49 +02008911 goto fail;
Emeric Brun9e754772019-01-10 17:51:55 +01008912 }
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008913 i++;
8914 }
8915
8916 if (i < TLS_TICKETS_NO) {
8917 if (err)
8918 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 +02008919 goto fail;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008920 }
8921
8922 fclose(f);
8923
8924 /* Use penultimate key for encryption, handle when TLS_TICKETS_NO = 1 */
Nenad Merdanovic17891152016-03-25 22:16:57 +01008925 i -= 2;
8926 keys_ref->tls_ticket_enc_index = i < 0 ? 0 : i % TLS_TICKETS_NO;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02008927 keys_ref->unique_id = -1;
Willy Tarreau17b4aa12018-07-17 10:05:32 +02008928 keys_ref->refcount = 1;
Christopher Faulet16f45c82018-02-16 11:23:49 +01008929 HA_RWLOCK_INIT(&keys_ref->lock);
Nenad Merdanovic146defa2015-05-09 08:46:00 +02008930 conf->keys_ref = keys_ref;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008931
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02008932 LIST_ADD(&tlskeys_reference, &keys_ref->list);
8933
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008934 return 0;
Christopher Faulete566f3d2019-10-21 09:55:49 +02008935
8936 fail:
8937 if (f)
8938 fclose(f);
8939 if (keys_ref) {
8940 free(keys_ref->filename);
8941 free(keys_ref->tlskeys);
8942 free(keys_ref);
8943 }
8944 return ERR_ALERT | ERR_FATAL;
8945
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008946#else
8947 if (err)
8948 memprintf(err, "'%s' : TLS ticket callback extension not supported", args[cur_arg]);
8949 return ERR_ALERT | ERR_FATAL;
8950#endif /* SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB */
Emmanuel Hocdet65623372013-01-24 17:17:15 +01008951}
8952
Emeric Brund94b3fe2012-09-20 18:23:56 +02008953/* parse the "verify" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008954static 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 +02008955{
8956 if (!*args[cur_arg + 1]) {
8957 if (err)
8958 memprintf(err, "'%s' : missing verify method", args[cur_arg]);
8959 return ERR_ALERT | ERR_FATAL;
8960 }
8961
8962 if (strcmp(args[cur_arg + 1], "none") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01008963 conf->verify = SSL_SOCK_VERIFY_NONE;
Emeric Brund94b3fe2012-09-20 18:23:56 +02008964 else if (strcmp(args[cur_arg + 1], "optional") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01008965 conf->verify = SSL_SOCK_VERIFY_OPTIONAL;
Emeric Brund94b3fe2012-09-20 18:23:56 +02008966 else if (strcmp(args[cur_arg + 1], "required") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01008967 conf->verify = SSL_SOCK_VERIFY_REQUIRED;
Emeric Brund94b3fe2012-09-20 18:23:56 +02008968 else {
8969 if (err)
8970 memprintf(err, "'%s' : unknown verify method '%s', only 'none', 'optional', and 'required' are supported\n",
8971 args[cur_arg], args[cur_arg + 1]);
8972 return ERR_ALERT | ERR_FATAL;
8973 }
8974
8975 return 0;
8976}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008977static int bind_parse_verify(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8978{
8979 return ssl_bind_parse_verify(args, cur_arg, px, &conf->ssl_conf, err);
8980}
Emeric Brund94b3fe2012-09-20 18:23:56 +02008981
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02008982/* parse the "no-ca-names" bind keyword */
8983static int ssl_bind_parse_no_ca_names(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
8984{
8985 conf->no_ca_names = 1;
8986 return 0;
8987}
8988static int bind_parse_no_ca_names(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8989{
8990 return ssl_bind_parse_no_ca_names(args, cur_arg, px, &conf->ssl_conf, err);
8991}
8992
Willy Tarreau92faadf2012-10-10 23:04:25 +02008993/************** "server" keywords ****************/
8994
Olivier Houchardc7566002018-11-20 23:33:50 +01008995/* parse the "npn" bind keyword */
8996static int srv_parse_npn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8997{
8998#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
8999 char *p1, *p2;
9000
9001 if (!*args[*cur_arg + 1]) {
9002 memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[*cur_arg]);
9003 return ERR_ALERT | ERR_FATAL;
9004 }
9005
9006 free(newsrv->ssl_ctx.npn_str);
9007
9008 /* the NPN string is built as a suite of (<len> <name>)*,
9009 * so we reuse each comma to store the next <len> and need
9010 * one more for the end of the string.
9011 */
9012 newsrv->ssl_ctx.npn_len = strlen(args[*cur_arg + 1]) + 1;
9013 newsrv->ssl_ctx.npn_str = calloc(1, newsrv->ssl_ctx.npn_len + 1);
9014 memcpy(newsrv->ssl_ctx.npn_str + 1, args[*cur_arg + 1],
9015 newsrv->ssl_ctx.npn_len);
9016
9017 /* replace commas with the name length */
9018 p1 = newsrv->ssl_ctx.npn_str;
9019 p2 = p1 + 1;
9020 while (1) {
9021 p2 = memchr(p1 + 1, ',', newsrv->ssl_ctx.npn_str +
9022 newsrv->ssl_ctx.npn_len - (p1 + 1));
9023 if (!p2)
9024 p2 = p1 + 1 + strlen(p1 + 1);
9025
9026 if (p2 - (p1 + 1) > 255) {
9027 *p2 = '\0';
9028 memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[*cur_arg], p1 + 1);
9029 return ERR_ALERT | ERR_FATAL;
9030 }
9031
9032 *p1 = p2 - (p1 + 1);
9033 p1 = p2;
9034
9035 if (!*p2)
9036 break;
9037
9038 *(p2++) = '\0';
9039 }
9040 return 0;
9041#else
9042 if (err)
9043 memprintf(err, "'%s' : library does not support TLS NPN extension", args[*cur_arg]);
9044 return ERR_ALERT | ERR_FATAL;
9045#endif
9046}
9047
Olivier Houchard92150142018-12-21 19:47:01 +01009048/* parse the "alpn" or the "check-alpn" server keyword */
Olivier Houchardc7566002018-11-20 23:33:50 +01009049static int srv_parse_alpn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9050{
9051#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
9052 char *p1, *p2;
Olivier Houchard92150142018-12-21 19:47:01 +01009053 char **alpn_str;
9054 int *alpn_len;
Olivier Houchardc7566002018-11-20 23:33:50 +01009055
Olivier Houchard92150142018-12-21 19:47:01 +01009056 if (*args[*cur_arg] == 'c') {
9057 alpn_str = &newsrv->check.alpn_str;
9058 alpn_len = &newsrv->check.alpn_len;
9059 } else {
9060 alpn_str = &newsrv->ssl_ctx.alpn_str;
9061 alpn_len = &newsrv->ssl_ctx.alpn_len;
9062
9063 }
Olivier Houchardc7566002018-11-20 23:33:50 +01009064 if (!*args[*cur_arg + 1]) {
9065 memprintf(err, "'%s' : missing the comma-delimited ALPN protocol suite", args[*cur_arg]);
9066 return ERR_ALERT | ERR_FATAL;
9067 }
9068
Olivier Houchard92150142018-12-21 19:47:01 +01009069 free(*alpn_str);
Olivier Houchardc7566002018-11-20 23:33:50 +01009070
9071 /* the ALPN string is built as a suite of (<len> <name>)*,
9072 * so we reuse each comma to store the next <len> and need
9073 * one more for the end of the string.
9074 */
Olivier Houchard92150142018-12-21 19:47:01 +01009075 *alpn_len = strlen(args[*cur_arg + 1]) + 1;
9076 *alpn_str = calloc(1, *alpn_len + 1);
9077 memcpy(*alpn_str + 1, args[*cur_arg + 1], *alpn_len);
Olivier Houchardc7566002018-11-20 23:33:50 +01009078
9079 /* replace commas with the name length */
Olivier Houchard92150142018-12-21 19:47:01 +01009080 p1 = *alpn_str;
Olivier Houchardc7566002018-11-20 23:33:50 +01009081 p2 = p1 + 1;
9082 while (1) {
Olivier Houchard92150142018-12-21 19:47:01 +01009083 p2 = memchr(p1 + 1, ',', *alpn_str + *alpn_len - (p1 + 1));
Olivier Houchardc7566002018-11-20 23:33:50 +01009084 if (!p2)
9085 p2 = p1 + 1 + strlen(p1 + 1);
9086
9087 if (p2 - (p1 + 1) > 255) {
9088 *p2 = '\0';
9089 memprintf(err, "'%s' : ALPN protocol name too long : '%s'", args[*cur_arg], p1 + 1);
9090 return ERR_ALERT | ERR_FATAL;
9091 }
9092
9093 *p1 = p2 - (p1 + 1);
9094 p1 = p2;
9095
9096 if (!*p2)
9097 break;
9098
9099 *(p2++) = '\0';
9100 }
9101 return 0;
9102#else
9103 if (err)
9104 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[*cur_arg]);
9105 return ERR_ALERT | ERR_FATAL;
9106#endif
9107}
9108
Emeric Brunef42d922012-10-11 16:11:36 +02009109/* parse the "ca-file" server keyword */
9110static int srv_parse_ca_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9111{
9112 if (!*args[*cur_arg + 1]) {
9113 if (err)
9114 memprintf(err, "'%s' : missing CAfile path", args[*cur_arg]);
9115 return ERR_ALERT | ERR_FATAL;
9116 }
9117
Willy Tarreauef934602016-12-22 23:12:01 +01009118 if ((*args[*cur_arg + 1] != '/') && global_ssl.ca_base)
9119 memprintf(&newsrv->ssl_ctx.ca_file, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02009120 else
9121 memprintf(&newsrv->ssl_ctx.ca_file, "%s", args[*cur_arg + 1]);
9122
9123 return 0;
9124}
9125
Olivier Houchard9130a962017-10-17 17:33:43 +02009126/* parse the "check-sni" server keyword */
9127static int srv_parse_check_sni(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9128{
9129 if (!*args[*cur_arg + 1]) {
9130 if (err)
9131 memprintf(err, "'%s' : missing SNI", args[*cur_arg]);
9132 return ERR_ALERT | ERR_FATAL;
9133 }
9134
9135 newsrv->check.sni = strdup(args[*cur_arg + 1]);
9136 if (!newsrv->check.sni) {
9137 memprintf(err, "'%s' : failed to allocate memory", args[*cur_arg]);
9138 return ERR_ALERT | ERR_FATAL;
9139 }
9140 return 0;
9141
9142}
9143
Willy Tarreau92faadf2012-10-10 23:04:25 +02009144/* parse the "check-ssl" server keyword */
9145static int srv_parse_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9146{
9147 newsrv->check.use_ssl = 1;
Willy Tarreauef934602016-12-22 23:12:01 +01009148 if (global_ssl.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
9149 newsrv->ssl_ctx.ciphers = strdup(global_ssl.connect_default_ciphers);
Emmanuel Hocdet839af572019-05-14 16:27:35 +02009150#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009151 if (global_ssl.connect_default_ciphersuites && !newsrv->ssl_ctx.ciphersuites)
9152 newsrv->ssl_ctx.ciphersuites = strdup(global_ssl.connect_default_ciphersuites);
9153#endif
Willy Tarreauef934602016-12-22 23:12:01 +01009154 newsrv->ssl_ctx.options |= global_ssl.connect_default_ssloptions;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02009155 newsrv->ssl_ctx.methods.flags |= global_ssl.connect_default_sslmethods.flags;
9156 if (!newsrv->ssl_ctx.methods.min)
9157 newsrv->ssl_ctx.methods.min = global_ssl.connect_default_sslmethods.min;
9158 if (!newsrv->ssl_ctx.methods.max)
9159 newsrv->ssl_ctx.methods.max = global_ssl.connect_default_sslmethods.max;
9160
Willy Tarreau92faadf2012-10-10 23:04:25 +02009161 return 0;
9162}
9163
9164/* parse the "ciphers" server keyword */
9165static int srv_parse_ciphers(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9166{
9167 if (!*args[*cur_arg + 1]) {
9168 memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
9169 return ERR_ALERT | ERR_FATAL;
9170 }
9171
9172 free(newsrv->ssl_ctx.ciphers);
9173 newsrv->ssl_ctx.ciphers = strdup(args[*cur_arg + 1]);
9174 return 0;
9175}
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009176
Emmanuel Hocdet839af572019-05-14 16:27:35 +02009177#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009178/* parse the "ciphersuites" server keyword */
9179static int srv_parse_ciphersuites(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9180{
9181 if (!*args[*cur_arg + 1]) {
9182 memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
9183 return ERR_ALERT | ERR_FATAL;
9184 }
9185
9186 free(newsrv->ssl_ctx.ciphersuites);
9187 newsrv->ssl_ctx.ciphersuites = strdup(args[*cur_arg + 1]);
9188 return 0;
9189}
9190#endif
Willy Tarreau92faadf2012-10-10 23:04:25 +02009191
Emeric Brunef42d922012-10-11 16:11:36 +02009192/* parse the "crl-file" server keyword */
9193static int srv_parse_crl_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9194{
9195#ifndef X509_V_FLAG_CRL_CHECK
9196 if (err)
9197 memprintf(err, "'%s' : library does not support CRL verify", args[*cur_arg]);
9198 return ERR_ALERT | ERR_FATAL;
9199#else
9200 if (!*args[*cur_arg + 1]) {
9201 if (err)
9202 memprintf(err, "'%s' : missing CRLfile path", args[*cur_arg]);
9203 return ERR_ALERT | ERR_FATAL;
9204 }
9205
Willy Tarreauef934602016-12-22 23:12:01 +01009206 if ((*args[*cur_arg + 1] != '/') && global_ssl.ca_base)
9207 memprintf(&newsrv->ssl_ctx.crl_file, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02009208 else
9209 memprintf(&newsrv->ssl_ctx.crl_file, "%s", args[*cur_arg + 1]);
9210
9211 return 0;
9212#endif
9213}
9214
Emeric Bruna7aa3092012-10-26 12:58:00 +02009215/* parse the "crt" server keyword */
9216static int srv_parse_crt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9217{
9218 if (!*args[*cur_arg + 1]) {
9219 if (err)
9220 memprintf(err, "'%s' : missing certificate file path", args[*cur_arg]);
9221 return ERR_ALERT | ERR_FATAL;
9222 }
9223
Willy Tarreauef934602016-12-22 23:12:01 +01009224 if ((*args[*cur_arg + 1] != '/') && global_ssl.crt_base)
Christopher Fauletff3a41e2017-11-23 09:13:32 +01009225 memprintf(&newsrv->ssl_ctx.client_crt, "%s/%s", global_ssl.crt_base, args[*cur_arg + 1]);
Emeric Bruna7aa3092012-10-26 12:58:00 +02009226 else
9227 memprintf(&newsrv->ssl_ctx.client_crt, "%s", args[*cur_arg + 1]);
9228
9229 return 0;
9230}
Emeric Brunef42d922012-10-11 16:11:36 +02009231
Frédéric Lécaille340ae602017-03-13 10:38:04 +01009232/* parse the "no-check-ssl" server keyword */
9233static int srv_parse_no_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9234{
9235 newsrv->check.use_ssl = 0;
9236 free(newsrv->ssl_ctx.ciphers);
9237 newsrv->ssl_ctx.ciphers = NULL;
9238 newsrv->ssl_ctx.options &= ~global_ssl.connect_default_ssloptions;
9239 return 0;
9240}
9241
Frédéric Lécaillee892c4c2017-03-13 12:08:01 +01009242/* parse the "no-send-proxy-v2-ssl" server keyword */
9243static int srv_parse_no_send_proxy_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9244{
9245 newsrv->pp_opts &= ~SRV_PP_V2;
9246 newsrv->pp_opts &= ~SRV_PP_V2_SSL;
9247 return 0;
9248}
9249
9250/* parse the "no-send-proxy-v2-ssl-cn" server keyword */
9251static int srv_parse_no_send_proxy_cn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9252{
9253 newsrv->pp_opts &= ~SRV_PP_V2;
9254 newsrv->pp_opts &= ~SRV_PP_V2_SSL;
9255 newsrv->pp_opts &= ~SRV_PP_V2_SSL_CN;
9256 return 0;
9257}
9258
Frédéric Lécaillee381d762017-03-13 11:54:17 +01009259/* parse the "no-ssl" server keyword */
9260static int srv_parse_no_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9261{
9262 newsrv->use_ssl = 0;
9263 free(newsrv->ssl_ctx.ciphers);
9264 newsrv->ssl_ctx.ciphers = NULL;
9265 return 0;
9266}
9267
Olivier Houchard522eea72017-11-03 16:27:47 +01009268/* parse the "allow-0rtt" server keyword */
9269static int srv_parse_allow_0rtt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9270{
9271 newsrv->ssl_ctx.options |= SRV_SSL_O_EARLY_DATA;
9272 return 0;
9273}
9274
Willy Tarreau2a3fb1c2015-02-05 16:47:07 +01009275/* parse the "no-ssl-reuse" server keyword */
9276static int srv_parse_no_ssl_reuse(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9277{
9278 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_REUSE;
9279 return 0;
9280}
9281
Emeric Brunf9c5c472012-10-11 15:28:34 +02009282/* parse the "no-tls-tickets" server keyword */
9283static int srv_parse_no_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9284{
9285 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLS_TICKETS;
9286 return 0;
9287}
David Safb76832014-05-08 23:42:08 -04009288/* parse the "send-proxy-v2-ssl" server keyword */
9289static int srv_parse_send_proxy_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9290{
9291 newsrv->pp_opts |= SRV_PP_V2;
9292 newsrv->pp_opts |= SRV_PP_V2_SSL;
9293 return 0;
9294}
9295
9296/* parse the "send-proxy-v2-ssl-cn" server keyword */
9297static int srv_parse_send_proxy_cn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9298{
9299 newsrv->pp_opts |= SRV_PP_V2;
9300 newsrv->pp_opts |= SRV_PP_V2_SSL;
9301 newsrv->pp_opts |= SRV_PP_V2_SSL_CN;
9302 return 0;
9303}
Emeric Brunf9c5c472012-10-11 15:28:34 +02009304
Willy Tarreau732eac42015-07-09 11:40:25 +02009305/* parse the "sni" server keyword */
9306static int srv_parse_sni(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9307{
9308#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
9309 memprintf(err, "'%s' : the current SSL library doesn't support the SNI TLS extension", args[*cur_arg]);
9310 return ERR_ALERT | ERR_FATAL;
9311#else
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01009312 char *arg;
Willy Tarreau732eac42015-07-09 11:40:25 +02009313
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01009314 arg = args[*cur_arg + 1];
9315 if (!*arg) {
Willy Tarreau732eac42015-07-09 11:40:25 +02009316 memprintf(err, "'%s' : missing sni expression", args[*cur_arg]);
9317 return ERR_ALERT | ERR_FATAL;
9318 }
9319
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01009320 free(newsrv->sni_expr);
9321 newsrv->sni_expr = strdup(arg);
Willy Tarreau732eac42015-07-09 11:40:25 +02009322
Willy Tarreau732eac42015-07-09 11:40:25 +02009323 return 0;
9324#endif
9325}
9326
Willy Tarreau92faadf2012-10-10 23:04:25 +02009327/* parse the "ssl" server keyword */
9328static int srv_parse_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9329{
9330 newsrv->use_ssl = 1;
Willy Tarreauef934602016-12-22 23:12:01 +01009331 if (global_ssl.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
9332 newsrv->ssl_ctx.ciphers = strdup(global_ssl.connect_default_ciphers);
Emmanuel Hocdet839af572019-05-14 16:27:35 +02009333#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009334 if (global_ssl.connect_default_ciphersuites && !newsrv->ssl_ctx.ciphersuites)
9335 newsrv->ssl_ctx.ciphersuites = strdup(global_ssl.connect_default_ciphersuites);
9336#endif
Willy Tarreau92faadf2012-10-10 23:04:25 +02009337 return 0;
9338}
9339
Frédéric Lécaille2cfcdbe2017-03-13 11:32:20 +01009340/* parse the "ssl-reuse" server keyword */
9341static int srv_parse_ssl_reuse(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9342{
9343 newsrv->ssl_ctx.options &= ~SRV_SSL_O_NO_REUSE;
9344 return 0;
9345}
9346
Frédéric Lécaille2cfcdbe2017-03-13 11:32:20 +01009347/* parse the "tls-tickets" server keyword */
9348static int srv_parse_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9349{
9350 newsrv->ssl_ctx.options &= ~SRV_SSL_O_NO_TLS_TICKETS;
9351 return 0;
9352}
9353
Emeric Brunef42d922012-10-11 16:11:36 +02009354/* parse the "verify" server keyword */
9355static int srv_parse_verify(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9356{
9357 if (!*args[*cur_arg + 1]) {
9358 if (err)
9359 memprintf(err, "'%s' : missing verify method", args[*cur_arg]);
9360 return ERR_ALERT | ERR_FATAL;
9361 }
9362
9363 if (strcmp(args[*cur_arg + 1], "none") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01009364 newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_NONE;
Emeric Brunef42d922012-10-11 16:11:36 +02009365 else if (strcmp(args[*cur_arg + 1], "required") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01009366 newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_REQUIRED;
Emeric Brunef42d922012-10-11 16:11:36 +02009367 else {
9368 if (err)
9369 memprintf(err, "'%s' : unknown verify method '%s', only 'none' and 'required' are supported\n",
9370 args[*cur_arg], args[*cur_arg + 1]);
9371 return ERR_ALERT | ERR_FATAL;
9372 }
9373
Evan Broderbe554312013-06-27 00:05:25 -07009374 return 0;
9375}
9376
9377/* parse the "verifyhost" server keyword */
9378static int srv_parse_verifyhost(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9379{
9380 if (!*args[*cur_arg + 1]) {
9381 if (err)
9382 memprintf(err, "'%s' : missing hostname to verify against", args[*cur_arg]);
9383 return ERR_ALERT | ERR_FATAL;
9384 }
9385
Frédéric Lécaille273f3212017-03-13 15:52:01 +01009386 free(newsrv->ssl_ctx.verify_host);
Evan Broderbe554312013-06-27 00:05:25 -07009387 newsrv->ssl_ctx.verify_host = strdup(args[*cur_arg + 1]);
9388
Emeric Brunef42d922012-10-11 16:11:36 +02009389 return 0;
9390}
9391
Emeric Brun2c86cbf2014-10-30 15:56:50 +01009392/* parse the "ssl-default-bind-options" keyword in global section */
9393static int ssl_parse_default_bind_options(char **args, int section_type, struct proxy *curpx,
9394 struct proxy *defpx, const char *file, int line,
9395 char **err) {
9396 int i = 1;
9397
9398 if (*(args[i]) == 0) {
9399 memprintf(err, "global statement '%s' expects an option as an argument.", args[0]);
9400 return -1;
9401 }
9402 while (*(args[i])) {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02009403 if (!strcmp(args[i], "no-tls-tickets"))
Willy Tarreauef934602016-12-22 23:12:01 +01009404 global_ssl.listen_default_ssloptions |= BC_SSL_O_NO_TLS_TICKETS;
Lukas Tribus53ae85c2017-05-04 15:45:40 +00009405 else if (!strcmp(args[i], "prefer-client-ciphers"))
9406 global_ssl.listen_default_ssloptions |= BC_SSL_O_PREF_CLIE_CIPH;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02009407 else if (!strcmp(args[i], "ssl-min-ver") || !strcmp(args[i], "ssl-max-ver")) {
9408 if (!parse_tls_method_minmax(args, i, &global_ssl.listen_default_sslmethods, err))
9409 i++;
9410 else {
9411 memprintf(err, "%s on global statement '%s'.", *err, args[0]);
9412 return -1;
9413 }
9414 }
9415 else if (parse_tls_method_options(args[i], &global_ssl.listen_default_sslmethods, err)) {
Emeric Brun2c86cbf2014-10-30 15:56:50 +01009416 memprintf(err, "unknown option '%s' on global statement '%s'.", args[i], args[0]);
9417 return -1;
9418 }
9419 i++;
9420 }
9421 return 0;
9422}
9423
9424/* parse the "ssl-default-server-options" keyword in global section */
9425static int ssl_parse_default_server_options(char **args, int section_type, struct proxy *curpx,
9426 struct proxy *defpx, const char *file, int line,
9427 char **err) {
9428 int i = 1;
9429
9430 if (*(args[i]) == 0) {
9431 memprintf(err, "global statement '%s' expects an option as an argument.", args[0]);
9432 return -1;
9433 }
9434 while (*(args[i])) {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02009435 if (!strcmp(args[i], "no-tls-tickets"))
Willy Tarreauef934602016-12-22 23:12:01 +01009436 global_ssl.connect_default_ssloptions |= SRV_SSL_O_NO_TLS_TICKETS;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02009437 else if (!strcmp(args[i], "ssl-min-ver") || !strcmp(args[i], "ssl-max-ver")) {
9438 if (!parse_tls_method_minmax(args, i, &global_ssl.connect_default_sslmethods, err))
9439 i++;
9440 else {
9441 memprintf(err, "%s on global statement '%s'.", *err, args[0]);
9442 return -1;
9443 }
9444 }
9445 else if (parse_tls_method_options(args[i], &global_ssl.connect_default_sslmethods, err)) {
Emeric Brun2c86cbf2014-10-30 15:56:50 +01009446 memprintf(err, "unknown option '%s' on global statement '%s'.", args[i], args[0]);
9447 return -1;
9448 }
9449 i++;
9450 }
9451 return 0;
9452}
9453
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01009454/* parse the "ca-base" / "crt-base" keywords in global section.
9455 * Returns <0 on alert, >0 on warning, 0 on success.
9456 */
9457static int ssl_parse_global_ca_crt_base(char **args, int section_type, struct proxy *curpx,
9458 struct proxy *defpx, const char *file, int line,
9459 char **err)
9460{
9461 char **target;
9462
Willy Tarreauef934602016-12-22 23:12:01 +01009463 target = (args[0][1] == 'a') ? &global_ssl.ca_base : &global_ssl.crt_base;
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01009464
9465 if (too_many_args(1, args, err, NULL))
9466 return -1;
9467
9468 if (*target) {
9469 memprintf(err, "'%s' already specified.", args[0]);
9470 return -1;
9471 }
9472
9473 if (*(args[1]) == 0) {
9474 memprintf(err, "global statement '%s' expects a directory path as an argument.", args[0]);
9475 return -1;
9476 }
9477 *target = strdup(args[1]);
9478 return 0;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00009479}
9480
9481/* parse the "ssl-mode-async" keyword in global section.
9482 * Returns <0 on alert, >0 on warning, 0 on success.
9483 */
9484static int ssl_parse_global_ssl_async(char **args, int section_type, struct proxy *curpx,
9485 struct proxy *defpx, const char *file, int line,
9486 char **err)
9487{
Willy Tarreau5db847a2019-05-09 14:13:35 +02009488#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00009489 global_ssl.async = 1;
Emeric Brunece0c332017-12-06 13:51:49 +01009490 global.ssl_used_async_engines = nb_engines;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00009491 return 0;
9492#else
9493 memprintf(err, "'%s': openssl library does not support async mode", args[0]);
9494 return -1;
9495#endif
9496}
9497
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02009498#ifndef OPENSSL_NO_ENGINE
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00009499static int ssl_check_async_engine_count(void) {
9500 int err_code = 0;
9501
Emeric Brun3854e012017-05-17 20:42:48 +02009502 if (global_ssl.async && (openssl_engines_initialized > 32)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01009503 ha_alert("ssl-mode-async only supports a maximum of 32 engines.\n");
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00009504 err_code = ERR_ABORT;
9505 }
9506 return err_code;
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01009507}
9508
Grant Zhang872f9c22017-01-21 01:10:18 +00009509/* parse the "ssl-engine" keyword in global section.
9510 * Returns <0 on alert, >0 on warning, 0 on success.
9511 */
9512static int ssl_parse_global_ssl_engine(char **args, int section_type, struct proxy *curpx,
9513 struct proxy *defpx, const char *file, int line,
9514 char **err)
9515{
9516 char *algo;
9517 int ret = -1;
9518
9519 if (*(args[1]) == 0) {
9520 memprintf(err, "global statement '%s' expects a valid engine name as an argument.", args[0]);
9521 return ret;
9522 }
9523
9524 if (*(args[2]) == 0) {
9525 /* if no list of algorithms is given, it defaults to ALL */
9526 algo = strdup("ALL");
9527 goto add_engine;
9528 }
9529
9530 /* otherwise the expected format is ssl-engine <engine_name> algo <list of algo> */
9531 if (strcmp(args[2], "algo") != 0) {
9532 memprintf(err, "global statement '%s' expects to have algo keyword.", args[0]);
9533 return ret;
9534 }
9535
9536 if (*(args[3]) == 0) {
9537 memprintf(err, "global statement '%s' expects algorithm names as an argument.", args[0]);
9538 return ret;
9539 }
9540 algo = strdup(args[3]);
9541
9542add_engine:
9543 if (ssl_init_single_engine(args[1], algo)==0) {
9544 openssl_engines_initialized++;
9545 ret = 0;
9546 }
9547 free(algo);
9548 return ret;
9549}
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02009550#endif
Grant Zhang872f9c22017-01-21 01:10:18 +00009551
Willy Tarreauf22e9682016-12-21 23:23:19 +01009552/* parse the "ssl-default-bind-ciphers" / "ssl-default-server-ciphers" keywords
9553 * in global section. Returns <0 on alert, >0 on warning, 0 on success.
9554 */
9555static int ssl_parse_global_ciphers(char **args, int section_type, struct proxy *curpx,
9556 struct proxy *defpx, const char *file, int line,
9557 char **err)
9558{
9559 char **target;
9560
Willy Tarreauef934602016-12-22 23:12:01 +01009561 target = (args[0][12] == 'b') ? &global_ssl.listen_default_ciphers : &global_ssl.connect_default_ciphers;
Willy Tarreauf22e9682016-12-21 23:23:19 +01009562
9563 if (too_many_args(1, args, err, NULL))
9564 return -1;
9565
9566 if (*(args[1]) == 0) {
9567 memprintf(err, "global statement '%s' expects a cipher suite as an argument.", args[0]);
9568 return -1;
9569 }
9570
9571 free(*target);
9572 *target = strdup(args[1]);
9573 return 0;
9574}
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009575
Emmanuel Hocdet839af572019-05-14 16:27:35 +02009576#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009577/* parse the "ssl-default-bind-ciphersuites" / "ssl-default-server-ciphersuites" keywords
9578 * in global section. Returns <0 on alert, >0 on warning, 0 on success.
9579 */
9580static int ssl_parse_global_ciphersuites(char **args, int section_type, struct proxy *curpx,
9581 struct proxy *defpx, const char *file, int line,
9582 char **err)
9583{
9584 char **target;
9585
9586 target = (args[0][12] == 'b') ? &global_ssl.listen_default_ciphersuites : &global_ssl.connect_default_ciphersuites;
9587
9588 if (too_many_args(1, args, err, NULL))
9589 return -1;
9590
9591 if (*(args[1]) == 0) {
9592 memprintf(err, "global statement '%s' expects a cipher suite as an argument.", args[0]);
9593 return -1;
9594 }
9595
9596 free(*target);
9597 *target = strdup(args[1]);
9598 return 0;
9599}
9600#endif
Willy Tarreauf22e9682016-12-21 23:23:19 +01009601
Willy Tarreau9ceda382016-12-21 23:13:03 +01009602/* parse various global tune.ssl settings consisting in positive integers.
9603 * Returns <0 on alert, >0 on warning, 0 on success.
9604 */
9605static int ssl_parse_global_int(char **args, int section_type, struct proxy *curpx,
9606 struct proxy *defpx, const char *file, int line,
9607 char **err)
9608{
9609 int *target;
9610
9611 if (strcmp(args[0], "tune.ssl.cachesize") == 0)
9612 target = &global.tune.sslcachesize;
9613 else if (strcmp(args[0], "tune.ssl.maxrecord") == 0)
Willy Tarreauef934602016-12-22 23:12:01 +01009614 target = (int *)&global_ssl.max_record;
Willy Tarreau9ceda382016-12-21 23:13:03 +01009615 else if (strcmp(args[0], "tune.ssl.ssl-ctx-cache-size") == 0)
Willy Tarreauef934602016-12-22 23:12:01 +01009616 target = &global_ssl.ctx_cache;
Willy Tarreau0bea58d2016-12-21 23:17:25 +01009617 else if (strcmp(args[0], "maxsslconn") == 0)
9618 target = &global.maxsslconn;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01009619 else if (strcmp(args[0], "tune.ssl.capture-cipherlist-size") == 0)
9620 target = &global_ssl.capture_cipherlist;
Willy Tarreau9ceda382016-12-21 23:13:03 +01009621 else {
9622 memprintf(err, "'%s' keyword not unhandled (please report this bug).", args[0]);
9623 return -1;
9624 }
9625
9626 if (too_many_args(1, args, err, NULL))
9627 return -1;
9628
9629 if (*(args[1]) == 0) {
9630 memprintf(err, "'%s' expects an integer argument.", args[0]);
9631 return -1;
9632 }
9633
9634 *target = atoi(args[1]);
9635 if (*target < 0) {
9636 memprintf(err, "'%s' expects a positive numeric value.", args[0]);
9637 return -1;
9638 }
9639 return 0;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01009640}
9641
9642static int ssl_parse_global_capture_cipherlist(char **args, int section_type, struct proxy *curpx,
9643 struct proxy *defpx, const char *file, int line,
9644 char **err)
9645{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01009646 int ret;
9647
9648 ret = ssl_parse_global_int(args, section_type, curpx, defpx, file, line, err);
9649 if (ret != 0)
9650 return ret;
9651
Willy Tarreaubafbe012017-11-24 17:34:44 +01009652 if (pool_head_ssl_capture) {
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01009653 memprintf(err, "'%s' is already configured.", args[0]);
9654 return -1;
9655 }
9656
Willy Tarreaubafbe012017-11-24 17:34:44 +01009657 pool_head_ssl_capture = create_pool("ssl-capture", sizeof(struct ssl_capture) + global_ssl.capture_cipherlist, MEM_F_SHARED);
9658 if (!pool_head_ssl_capture) {
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01009659 memprintf(err, "Out of memory error.");
9660 return -1;
9661 }
9662 return 0;
Willy Tarreau9ceda382016-12-21 23:13:03 +01009663}
9664
9665/* parse "ssl.force-private-cache".
9666 * Returns <0 on alert, >0 on warning, 0 on success.
9667 */
9668static int ssl_parse_global_private_cache(char **args, int section_type, struct proxy *curpx,
9669 struct proxy *defpx, const char *file, int line,
9670 char **err)
9671{
9672 if (too_many_args(0, args, err, NULL))
9673 return -1;
9674
Willy Tarreauef934602016-12-22 23:12:01 +01009675 global_ssl.private_cache = 1;
Willy Tarreau9ceda382016-12-21 23:13:03 +01009676 return 0;
9677}
9678
9679/* parse "ssl.lifetime".
9680 * Returns <0 on alert, >0 on warning, 0 on success.
9681 */
9682static int ssl_parse_global_lifetime(char **args, int section_type, struct proxy *curpx,
9683 struct proxy *defpx, const char *file, int line,
9684 char **err)
9685{
9686 const char *res;
9687
9688 if (too_many_args(1, args, err, NULL))
9689 return -1;
9690
9691 if (*(args[1]) == 0) {
9692 memprintf(err, "'%s' expects ssl sessions <lifetime> in seconds as argument.", args[0]);
9693 return -1;
9694 }
9695
Willy Tarreauef934602016-12-22 23:12:01 +01009696 res = parse_time_err(args[1], &global_ssl.life_time, TIME_UNIT_S);
Willy Tarreau9faebe32019-06-07 19:00:37 +02009697 if (res == PARSE_TIME_OVER) {
9698 memprintf(err, "timer overflow in argument '%s' to <%s> (maximum value is 2147483647 s or ~68 years).",
9699 args[1], args[0]);
9700 return -1;
9701 }
9702 else if (res == PARSE_TIME_UNDER) {
9703 memprintf(err, "timer underflow in argument '%s' to <%s> (minimum non-null value is 1 s).",
9704 args[1], args[0]);
9705 return -1;
9706 }
9707 else if (res) {
Willy Tarreau9ceda382016-12-21 23:13:03 +01009708 memprintf(err, "unexpected character '%c' in argument to <%s>.", *res, args[0]);
9709 return -1;
9710 }
9711 return 0;
9712}
9713
9714#ifndef OPENSSL_NO_DH
Willy Tarreau14e36a12016-12-21 23:28:13 +01009715/* parse "ssl-dh-param-file".
9716 * Returns <0 on alert, >0 on warning, 0 on success.
9717 */
9718static int ssl_parse_global_dh_param_file(char **args, int section_type, struct proxy *curpx,
9719 struct proxy *defpx, const char *file, int line,
9720 char **err)
9721{
9722 if (too_many_args(1, args, err, NULL))
9723 return -1;
9724
9725 if (*(args[1]) == 0) {
9726 memprintf(err, "'%s' expects a file path as an argument.", args[0]);
9727 return -1;
9728 }
9729
9730 if (ssl_sock_load_global_dh_param_from_file(args[1])) {
9731 memprintf(err, "'%s': unable to load DH parameters from file <%s>.", args[0], args[1]);
9732 return -1;
9733 }
9734 return 0;
9735}
9736
Willy Tarreau9ceda382016-12-21 23:13:03 +01009737/* parse "ssl.default-dh-param".
9738 * Returns <0 on alert, >0 on warning, 0 on success.
9739 */
9740static int ssl_parse_global_default_dh(char **args, int section_type, struct proxy *curpx,
9741 struct proxy *defpx, const char *file, int line,
9742 char **err)
9743{
9744 if (too_many_args(1, args, err, NULL))
9745 return -1;
9746
9747 if (*(args[1]) == 0) {
9748 memprintf(err, "'%s' expects an integer argument.", args[0]);
9749 return -1;
9750 }
9751
Willy Tarreauef934602016-12-22 23:12:01 +01009752 global_ssl.default_dh_param = atoi(args[1]);
9753 if (global_ssl.default_dh_param < 1024) {
Willy Tarreau9ceda382016-12-21 23:13:03 +01009754 memprintf(err, "'%s' expects a value >= 1024.", args[0]);
9755 return -1;
9756 }
9757 return 0;
9758}
9759#endif
9760
9761
William Lallemand32af2032016-10-29 18:09:35 +02009762/* This function is used with TLS ticket keys management. It permits to browse
9763 * each reference. The variable <getnext> must contain the current node,
9764 * <end> point to the root node.
9765 */
9766#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
9767static inline
9768struct tls_keys_ref *tlskeys_list_get_next(struct tls_keys_ref *getnext, struct list *end)
9769{
9770 struct tls_keys_ref *ref = getnext;
9771
9772 while (1) {
9773
9774 /* Get next list entry. */
9775 ref = LIST_NEXT(&ref->list, struct tls_keys_ref *, list);
9776
9777 /* If the entry is the last of the list, return NULL. */
9778 if (&ref->list == end)
9779 return NULL;
9780
9781 return ref;
9782 }
9783}
9784
9785static inline
9786struct tls_keys_ref *tlskeys_ref_lookup_ref(const char *reference)
9787{
9788 int id;
9789 char *error;
9790
9791 /* If the reference starts by a '#', this is numeric id. */
9792 if (reference[0] == '#') {
9793 /* Try to convert the numeric id. If the conversion fails, the lookup fails. */
9794 id = strtol(reference + 1, &error, 10);
9795 if (*error != '\0')
9796 return NULL;
9797
9798 /* Perform the unique id lookup. */
9799 return tlskeys_ref_lookupid(id);
9800 }
9801
9802 /* Perform the string lookup. */
9803 return tlskeys_ref_lookup(reference);
9804}
9805#endif
9806
9807
9808#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
9809
9810static int cli_io_handler_tlskeys_files(struct appctx *appctx);
9811
9812static inline int cli_io_handler_tlskeys_entries(struct appctx *appctx) {
9813 return cli_io_handler_tlskeys_files(appctx);
9814}
9815
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009816/* dumps all tls keys. Relies on cli.i0 (non-null = only list file names), cli.i1
9817 * (next index to be dumped), and cli.p0 (next key reference).
9818 */
William Lallemand32af2032016-10-29 18:09:35 +02009819static int cli_io_handler_tlskeys_files(struct appctx *appctx) {
9820
9821 struct stream_interface *si = appctx->owner;
9822
9823 switch (appctx->st2) {
9824 case STAT_ST_INIT:
9825 /* Display the column headers. If the message cannot be sent,
Joseph Herlant017b3da2018-11-15 09:07:59 -08009826 * quit the function with returning 0. The function is called
William Lallemand32af2032016-10-29 18:09:35 +02009827 * later and restart at the state "STAT_ST_INIT".
9828 */
9829 chunk_reset(&trash);
9830
9831 if (appctx->io_handler == cli_io_handler_tlskeys_entries)
9832 chunk_appendf(&trash, "# id secret\n");
9833 else
9834 chunk_appendf(&trash, "# id (file)\n");
9835
Willy Tarreau06d80a92017-10-19 14:32:15 +02009836 if (ci_putchk(si_ic(si), &trash) == -1) {
Willy Tarreaudb398432018-11-15 11:08:52 +01009837 si_rx_room_blk(si);
William Lallemand32af2032016-10-29 18:09:35 +02009838 return 0;
9839 }
9840
William Lallemand32af2032016-10-29 18:09:35 +02009841 /* Now, we start the browsing of the references lists.
9842 * Note that the following call to LIST_ELEM return bad pointer. The only
9843 * available field of this pointer is <list>. It is used with the function
9844 * tlskeys_list_get_next() for retruning the first available entry
9845 */
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009846 if (appctx->ctx.cli.p0 == NULL) {
9847 appctx->ctx.cli.p0 = LIST_ELEM(&tlskeys_reference, struct tls_keys_ref *, list);
9848 appctx->ctx.cli.p0 = tlskeys_list_get_next(appctx->ctx.cli.p0, &tlskeys_reference);
William Lallemand32af2032016-10-29 18:09:35 +02009849 }
9850
9851 appctx->st2 = STAT_ST_LIST;
9852 /* fall through */
9853
9854 case STAT_ST_LIST:
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009855 while (appctx->ctx.cli.p0) {
9856 struct tls_keys_ref *ref = appctx->ctx.cli.p0;
William Lallemand32af2032016-10-29 18:09:35 +02009857
9858 chunk_reset(&trash);
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009859 if (appctx->io_handler == cli_io_handler_tlskeys_entries && appctx->ctx.cli.i1 == 0)
William Lallemand32af2032016-10-29 18:09:35 +02009860 chunk_appendf(&trash, "# ");
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009861
9862 if (appctx->ctx.cli.i1 == 0)
9863 chunk_appendf(&trash, "%d (%s)\n", ref->unique_id, ref->filename);
9864
William Lallemand32af2032016-10-29 18:09:35 +02009865 if (appctx->io_handler == cli_io_handler_tlskeys_entries) {
Christopher Faulet16f45c82018-02-16 11:23:49 +01009866 int head;
9867
9868 HA_RWLOCK_RDLOCK(TLSKEYS_REF_LOCK, &ref->lock);
9869 head = ref->tls_ticket_enc_index;
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009870 while (appctx->ctx.cli.i1 < TLS_TICKETS_NO) {
Willy Tarreau83061a82018-07-13 11:56:34 +02009871 struct buffer *t2 = get_trash_chunk();
William Lallemand32af2032016-10-29 18:09:35 +02009872
9873 chunk_reset(t2);
9874 /* should never fail here because we dump only a key in the t2 buffer */
Emeric Brun9e754772019-01-10 17:51:55 +01009875 if (ref->key_size_bits == 128) {
9876 t2->data = a2base64((char *)(ref->tlskeys + (head + 2 + appctx->ctx.cli.i1) % TLS_TICKETS_NO),
9877 sizeof(struct tls_sess_key_128),
9878 t2->area, t2->size);
9879 chunk_appendf(&trash, "%d.%d %s\n", ref->unique_id, appctx->ctx.cli.i1,
9880 t2->area);
9881 }
9882 else if (ref->key_size_bits == 256) {
9883 t2->data = a2base64((char *)(ref->tlskeys + (head + 2 + appctx->ctx.cli.i1) % TLS_TICKETS_NO),
9884 sizeof(struct tls_sess_key_256),
9885 t2->area, t2->size);
9886 chunk_appendf(&trash, "%d.%d %s\n", ref->unique_id, appctx->ctx.cli.i1,
9887 t2->area);
9888 }
9889 else {
9890 /* This case should never happen */
9891 chunk_appendf(&trash, "%d.%d <unknown>\n", ref->unique_id, appctx->ctx.cli.i1);
9892 }
William Lallemand32af2032016-10-29 18:09:35 +02009893
Willy Tarreau06d80a92017-10-19 14:32:15 +02009894 if (ci_putchk(si_ic(si), &trash) == -1) {
William Lallemand32af2032016-10-29 18:09:35 +02009895 /* let's try again later from this stream. We add ourselves into
9896 * this stream's users so that it can remove us upon termination.
9897 */
Christopher Faulet16f45c82018-02-16 11:23:49 +01009898 HA_RWLOCK_RDUNLOCK(TLSKEYS_REF_LOCK, &ref->lock);
Willy Tarreaudb398432018-11-15 11:08:52 +01009899 si_rx_room_blk(si);
William Lallemand32af2032016-10-29 18:09:35 +02009900 return 0;
9901 }
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009902 appctx->ctx.cli.i1++;
William Lallemand32af2032016-10-29 18:09:35 +02009903 }
Christopher Faulet16f45c82018-02-16 11:23:49 +01009904 HA_RWLOCK_RDUNLOCK(TLSKEYS_REF_LOCK, &ref->lock);
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009905 appctx->ctx.cli.i1 = 0;
William Lallemand32af2032016-10-29 18:09:35 +02009906 }
Willy Tarreau06d80a92017-10-19 14:32:15 +02009907 if (ci_putchk(si_ic(si), &trash) == -1) {
William Lallemand32af2032016-10-29 18:09:35 +02009908 /* let's try again later from this stream. We add ourselves into
9909 * this stream's users so that it can remove us upon termination.
9910 */
Willy Tarreaudb398432018-11-15 11:08:52 +01009911 si_rx_room_blk(si);
William Lallemand32af2032016-10-29 18:09:35 +02009912 return 0;
9913 }
9914
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009915 if (appctx->ctx.cli.i0 == 0) /* don't display everything if not necessary */
William Lallemand32af2032016-10-29 18:09:35 +02009916 break;
9917
9918 /* get next list entry and check the end of the list */
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009919 appctx->ctx.cli.p0 = tlskeys_list_get_next(appctx->ctx.cli.p0, &tlskeys_reference);
William Lallemand32af2032016-10-29 18:09:35 +02009920 }
9921
9922 appctx->st2 = STAT_ST_FIN;
9923 /* fall through */
9924
9925 default:
9926 appctx->st2 = STAT_ST_FIN;
9927 return 1;
9928 }
9929 return 0;
9930}
9931
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009932/* sets cli.i0 to non-zero if only file lists should be dumped */
Aurélien Nephtaliabbf6072018-04-18 13:26:46 +02009933static int cli_parse_show_tlskeys(char **args, char *payload, struct appctx *appctx, void *private)
William Lallemand32af2032016-10-29 18:09:35 +02009934{
William Lallemand32af2032016-10-29 18:09:35 +02009935 /* no parameter, shows only file list */
9936 if (!*args[2]) {
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009937 appctx->ctx.cli.i0 = 1;
William Lallemand32af2032016-10-29 18:09:35 +02009938 appctx->io_handler = cli_io_handler_tlskeys_files;
Willy Tarreau3067bfa2016-12-05 14:50:15 +01009939 return 0;
William Lallemand32af2032016-10-29 18:09:35 +02009940 }
9941
9942 if (args[2][0] == '*') {
9943 /* list every TLS ticket keys */
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009944 appctx->ctx.cli.i0 = 1;
William Lallemand32af2032016-10-29 18:09:35 +02009945 } else {
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009946 appctx->ctx.cli.p0 = tlskeys_ref_lookup_ref(args[2]);
Willy Tarreau9d008692019-08-09 11:21:01 +02009947 if (!appctx->ctx.cli.p0)
9948 return cli_err(appctx, "'show tls-keys' unable to locate referenced filename\n");
William Lallemand32af2032016-10-29 18:09:35 +02009949 }
William Lallemand32af2032016-10-29 18:09:35 +02009950 appctx->io_handler = cli_io_handler_tlskeys_entries;
Willy Tarreau3067bfa2016-12-05 14:50:15 +01009951 return 0;
William Lallemand32af2032016-10-29 18:09:35 +02009952}
9953
Aurélien Nephtaliabbf6072018-04-18 13:26:46 +02009954static int cli_parse_set_tlskeys(char **args, char *payload, struct appctx *appctx, void *private)
William Lallemand32af2032016-10-29 18:09:35 +02009955{
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009956 struct tls_keys_ref *ref;
Willy Tarreau1c913e42018-08-22 05:26:57 +02009957 int ret;
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009958
William Lallemand32af2032016-10-29 18:09:35 +02009959 /* Expect two parameters: the filename and the new new TLS key in encoding */
Willy Tarreau9d008692019-08-09 11:21:01 +02009960 if (!*args[3] || !*args[4])
9961 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 +02009962
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009963 ref = tlskeys_ref_lookup_ref(args[3]);
Willy Tarreau9d008692019-08-09 11:21:01 +02009964 if (!ref)
9965 return cli_err(appctx, "'set ssl tls-key' unable to locate referenced filename\n");
William Lallemand32af2032016-10-29 18:09:35 +02009966
Willy Tarreau1c913e42018-08-22 05:26:57 +02009967 ret = base64dec(args[4], strlen(args[4]), trash.area, trash.size);
Willy Tarreau9d008692019-08-09 11:21:01 +02009968 if (ret < 0)
9969 return cli_err(appctx, "'set ssl tls-key' received invalid base64 encoded TLS key.\n");
Emeric Brun9e754772019-01-10 17:51:55 +01009970
Willy Tarreau1c913e42018-08-22 05:26:57 +02009971 trash.data = ret;
Willy Tarreau9d008692019-08-09 11:21:01 +02009972 if (ssl_sock_update_tlskey_ref(ref, &trash) < 0)
9973 return cli_err(appctx, "'set ssl tls-key' received a key of wrong size.\n");
William Lallemand32af2032016-10-29 18:09:35 +02009974
Willy Tarreau9d008692019-08-09 11:21:01 +02009975 return cli_msg(appctx, LOG_INFO, "TLS ticket key updated!\n");
William Lallemand32af2032016-10-29 18:09:35 +02009976}
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01009977#endif
William Lallemand32af2032016-10-29 18:09:35 +02009978
William Lallemand44b35322019-10-17 16:28:40 +02009979
9980/* Type of SSL payloads that can be updated over the CLI */
9981
9982enum {
9983 CERT_TYPE_PEM = 0,
Emmanuel Hocdetf6ac4fa2019-10-30 17:41:27 +01009984#if ((defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP) || defined OPENSSL_IS_BORINGSSL)
William Lallemand44b35322019-10-17 16:28:40 +02009985 CERT_TYPE_OCSP,
Emmanuel Hocdetf6ac4fa2019-10-30 17:41:27 +01009986#endif
William Lallemand44b35322019-10-17 16:28:40 +02009987 CERT_TYPE_ISSUER,
Emmanuel Hocdetf6ac4fa2019-10-30 17:41:27 +01009988#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
William Lallemand44b35322019-10-17 16:28:40 +02009989 CERT_TYPE_SCTL,
Emmanuel Hocdetf6ac4fa2019-10-30 17:41:27 +01009990#endif
William Lallemand44b35322019-10-17 16:28:40 +02009991 CERT_TYPE_MAX,
9992};
9993
9994struct {
9995 const char *ext;
9996 int type;
9997 int (*load)(const char *path, char *payload, struct cert_key_and_chain *ckch, char **err);
9998 /* add a parsing callback */
William Lallemandf29cdef2019-10-23 15:00:52 +02009999} cert_exts[CERT_TYPE_MAX+1] = {
William Lallemand44b35322019-10-17 16:28:40 +020010000 [CERT_TYPE_PEM] = { "", CERT_TYPE_PEM, &ssl_sock_load_pem_into_ckch }, /* default mode, no extensions */
William Lallemand541a5342019-10-23 14:11:54 +020010001#if ((defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP) || defined OPENSSL_IS_BORINGSSL)
William Lallemand44b35322019-10-17 16:28:40 +020010002 [CERT_TYPE_OCSP] = { "ocsp", CERT_TYPE_OCSP, &ssl_sock_load_ocsp_response_from_file },
William Lallemand541a5342019-10-23 14:11:54 +020010003#endif
10004#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
William Lallemand44b35322019-10-17 16:28:40 +020010005 [CERT_TYPE_SCTL] = { "sctl", CERT_TYPE_SCTL, &ssl_sock_load_sctl_from_file },
William Lallemand541a5342019-10-23 14:11:54 +020010006#endif
William Lallemand44b35322019-10-17 16:28:40 +020010007 [CERT_TYPE_ISSUER] = { "issuer", CERT_TYPE_ISSUER, &ssl_sock_load_issuer_file_into_ckch },
William Lallemandf29cdef2019-10-23 15:00:52 +020010008 [CERT_TYPE_MAX] = { NULL, CERT_TYPE_MAX, NULL },
William Lallemand44b35322019-10-17 16:28:40 +020010009};
10010
William Lallemand430413e2019-10-28 14:30:47 +010010011/* states of the CLI IO handler for 'set ssl cert' */
10012enum {
10013 SETCERT_ST_INIT = 0,
10014 SETCERT_ST_GEN,
10015 SETCERT_ST_INSERT,
10016 SETCERT_ST_FIN,
10017};
William Lallemand8f840d72019-10-23 10:53:05 +020010018
William Lallemand430413e2019-10-28 14:30:47 +010010019/* release function of the `set ssl cert' command, free things and unlock the spinlock */
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010020static void cli_release_commit_cert(struct appctx *appctx)
William Lallemand8f840d72019-10-23 10:53:05 +020010021{
10022 struct ckch_store *new_ckchs;
10023 struct ckch_inst *ckchi, *ckchis;
William Lallemand8f840d72019-10-23 10:53:05 +020010024
William Lallemand430413e2019-10-28 14:30:47 +010010025 HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
William Lallemand8f840d72019-10-23 10:53:05 +020010026
William Lallemand430413e2019-10-28 14:30:47 +010010027 if (appctx->st2 != SETCERT_ST_FIN) {
William Lallemand8f840d72019-10-23 10:53:05 +020010028 /* 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 +010010029 new_ckchs = appctx->ctx.ssl.new_ckchs;
William Lallemand8f840d72019-10-23 10:53:05 +020010030
William Lallemandbeea2a42019-10-30 17:45:33 +010010031 if (!new_ckchs)
10032 return;
William Lallemand8f840d72019-10-23 10:53:05 +020010033
William Lallemandbeea2a42019-10-30 17:45:33 +010010034 /* if the allocation failed, we need to free everything from the temporary list */
10035 list_for_each_entry_safe(ckchi, ckchis, &new_ckchs->ckch_inst, by_ckchs) {
10036 struct sni_ctx *sc0, *sc0s;
William Lallemand8f840d72019-10-23 10:53:05 +020010037
William Lallemandbeea2a42019-10-30 17:45:33 +010010038 list_for_each_entry_safe(sc0, sc0s, &ckchi->sni_ctx, by_ckch_inst) {
10039 if (sc0->order == 0) /* we only free if it's the first inserted */
10040 SSL_CTX_free(sc0->ctx);
10041 LIST_DEL(&sc0->by_ckch_inst);
10042 free(sc0);
William Lallemand8f840d72019-10-23 10:53:05 +020010043 }
William Lallemandbeea2a42019-10-30 17:45:33 +010010044 LIST_DEL(&ckchi->by_ckchs);
10045 free(ckchi);
William Lallemand8f840d72019-10-23 10:53:05 +020010046 }
William Lallemandbeea2a42019-10-30 17:45:33 +010010047 ckchs_free(new_ckchs);
William Lallemand8f840d72019-10-23 10:53:05 +020010048 }
10049}
10050
10051
10052/*
10053 * This function tries to create the new ckch_inst and their SNIs
10054 */
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010055static int cli_io_handler_commit_cert(struct appctx *appctx)
William Lallemand8f840d72019-10-23 10:53:05 +020010056{
10057 struct stream_interface *si = appctx->owner;
10058 int y = 0;
10059 char *err = NULL;
10060 int errcode = 0;
10061 struct ckch_store *old_ckchs, *new_ckchs = NULL;
10062 struct ckch_inst *ckchi, *ckchis;
William Lallemand8f840d72019-10-23 10:53:05 +020010063 struct buffer *trash = alloc_trash_chunk();
10064
William Lallemand33cc76f2019-10-31 11:43:45 +010010065 if (trash == NULL)
10066 goto error;
10067
William Lallemand8f840d72019-10-23 10:53:05 +020010068 if (unlikely(si_ic(si)->flags & (CF_WRITE_ERROR|CF_SHUTW)))
10069 goto error;
10070
William Lallemand430413e2019-10-28 14:30:47 +010010071 while (1) {
10072 switch (appctx->st2) {
10073 case SETCERT_ST_INIT:
10074 /* This state just print the update message */
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010075 chunk_printf(trash, "Committing %s", ckchs_transaction.path);
William Lallemand430413e2019-10-28 14:30:47 +010010076 if (ci_putchk(si_ic(si), trash) == -1) {
10077 si_rx_room_blk(si);
William Lallemand8f840d72019-10-23 10:53:05 +020010078 goto yield;
William Lallemand430413e2019-10-28 14:30:47 +010010079 }
10080 appctx->st2 = SETCERT_ST_GEN;
10081 /* fallthrough */
10082 case SETCERT_ST_GEN:
10083 /*
10084 * This state generates the ckch instances with their
10085 * sni_ctxs and SSL_CTX.
10086 *
William Lallemand430413e2019-10-28 14:30:47 +010010087 * Since the SSL_CTX generation can be CPU consumer, we
10088 * yield every 10 instances.
10089 */
William Lallemand8f840d72019-10-23 10:53:05 +020010090
William Lallemandbeea2a42019-10-30 17:45:33 +010010091 old_ckchs = appctx->ctx.ssl.old_ckchs;
10092 new_ckchs = appctx->ctx.ssl.new_ckchs;
William Lallemand8f840d72019-10-23 10:53:05 +020010093
William Lallemandbeea2a42019-10-30 17:45:33 +010010094 if (!new_ckchs)
10095 continue;
William Lallemand8f840d72019-10-23 10:53:05 +020010096
William Lallemandbeea2a42019-10-30 17:45:33 +010010097 /* get the next ckchi to regenerate */
10098 ckchi = appctx->ctx.ssl.next_ckchi;
10099 /* we didn't start yet, set it to the first elem */
10100 if (ckchi == NULL)
10101 ckchi = LIST_ELEM(old_ckchs->ckch_inst.n, typeof(ckchi), by_ckchs);
William Lallemand8f840d72019-10-23 10:53:05 +020010102
William Lallemandbeea2a42019-10-30 17:45:33 +010010103 /* walk through the old ckch_inst and creates new ckch_inst using the updated ckchs */
10104 list_for_each_entry_from(ckchi, &old_ckchs->ckch_inst, by_ckchs) {
10105 struct ckch_inst *new_inst;
William Lallemand8f840d72019-10-23 10:53:05 +020010106
William Lallemandbeea2a42019-10-30 17:45:33 +010010107 /* it takes a lot of CPU to creates SSL_CTXs, so we yield every 10 CKCH instances */
10108 if (y >= 10) {
10109 /* save the next ckchi to compute */
10110 appctx->ctx.ssl.next_ckchi = ckchi;
10111 goto yield;
10112 }
William Lallemand8f840d72019-10-23 10:53:05 +020010113
William Lallemandbeea2a42019-10-30 17:45:33 +010010114 if (new_ckchs->multi)
10115 errcode |= ckch_inst_new_load_multi_store(new_ckchs->path, new_ckchs, ckchi->bind_conf, ckchi->ssl_conf, NULL, 0, &new_inst, &err);
10116 else
10117 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 +020010118
William Lallemandbeea2a42019-10-30 17:45:33 +010010119 if (errcode & ERR_CODE)
10120 goto error;
William Lallemand8f840d72019-10-23 10:53:05 +020010121
William Lallemand21724f02019-11-04 17:56:13 +010010122 /* if the previous ckchi was used as the default */
10123 if (ckchi->is_default)
10124 new_inst->is_default = 1;
10125
William Lallemandbeea2a42019-10-30 17:45:33 +010010126 /* display one dot per new instance */
10127 chunk_appendf(trash, ".");
10128 /* link the new ckch_inst to the duplicate */
10129 LIST_ADDQ(&new_ckchs->ckch_inst, &new_inst->by_ckchs);
10130 y++;
10131 }
William Lallemand430413e2019-10-28 14:30:47 +010010132 appctx->st2 = SETCERT_ST_INSERT;
10133 /* fallthrough */
10134 case SETCERT_ST_INSERT:
10135 /* The generation is finished, we can insert everything */
William Lallemand8f840d72019-10-23 10:53:05 +020010136
William Lallemandbeea2a42019-10-30 17:45:33 +010010137 old_ckchs = appctx->ctx.ssl.old_ckchs;
10138 new_ckchs = appctx->ctx.ssl.new_ckchs;
William Lallemand8f840d72019-10-23 10:53:05 +020010139
William Lallemandbeea2a42019-10-30 17:45:33 +010010140 if (!new_ckchs)
10141 continue;
William Lallemand430413e2019-10-28 14:30:47 +010010142
William Lallemand21724f02019-11-04 17:56:13 +010010143 /* First, we insert every new SNIs in the trees, also replace the default_ctx */
William Lallemandbeea2a42019-10-30 17:45:33 +010010144 list_for_each_entry_safe(ckchi, ckchis, &new_ckchs->ckch_inst, by_ckchs) {
10145 HA_RWLOCK_WRLOCK(SNI_LOCK, &ckchi->bind_conf->sni_lock);
10146 ssl_sock_load_cert_sni(ckchi, ckchi->bind_conf);
10147 HA_RWLOCK_WRUNLOCK(SNI_LOCK, &ckchi->bind_conf->sni_lock);
10148 }
William Lallemand8f840d72019-10-23 10:53:05 +020010149
William Lallemandbeea2a42019-10-30 17:45:33 +010010150 /* delete the old sni_ctx, the old ckch_insts and the ckch_store */
10151 list_for_each_entry_safe(ckchi, ckchis, &old_ckchs->ckch_inst, by_ckchs) {
10152 struct sni_ctx *sc0, *sc0s;
William Lallemand430413e2019-10-28 14:30:47 +010010153
William Lallemandbeea2a42019-10-30 17:45:33 +010010154 HA_RWLOCK_WRLOCK(SNI_LOCK, &ckchi->bind_conf->sni_lock);
10155 list_for_each_entry_safe(sc0, sc0s, &ckchi->sni_ctx, by_ckch_inst) {
10156 ebmb_delete(&sc0->name);
10157 LIST_DEL(&sc0->by_ckch_inst);
10158 free(sc0);
William Lallemand430413e2019-10-28 14:30:47 +010010159 }
William Lallemandbeea2a42019-10-30 17:45:33 +010010160 HA_RWLOCK_WRUNLOCK(SNI_LOCK, &ckchi->bind_conf->sni_lock);
10161 LIST_DEL(&ckchi->by_ckchs);
10162 free(ckchi);
10163 }
William Lallemand8f840d72019-10-23 10:53:05 +020010164
William Lallemandbeea2a42019-10-30 17:45:33 +010010165 /* Replace the old ckchs by the new one */
10166 ebmb_delete(&old_ckchs->node);
10167 ckchs_free(old_ckchs);
10168 ebst_insert(&ckchs_tree, &new_ckchs->node);
William Lallemand430413e2019-10-28 14:30:47 +010010169 appctx->st2 = SETCERT_ST_FIN;
10170 /* fallthrough */
10171 case SETCERT_ST_FIN:
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010172 /* we achieved the transaction, we can set everything to NULL */
10173 free(ckchs_transaction.path);
10174 ckchs_transaction.path = NULL;
10175 ckchs_transaction.new_ckchs = NULL;
10176 ckchs_transaction.old_ckchs = NULL;
William Lallemand430413e2019-10-28 14:30:47 +010010177 goto end;
10178 }
William Lallemand8f840d72019-10-23 10:53:05 +020010179 }
William Lallemand430413e2019-10-28 14:30:47 +010010180end:
William Lallemand8f840d72019-10-23 10:53:05 +020010181
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010182 chunk_appendf(trash, "\nSuccess!\n");
William Lallemand430413e2019-10-28 14:30:47 +010010183 if (ci_putchk(si_ic(si), trash) == -1)
10184 si_rx_room_blk(si);
10185 free_trash_chunk(trash);
10186 /* success: call the release function and don't come back */
10187 return 1;
William Lallemand8f840d72019-10-23 10:53:05 +020010188yield:
10189 /* store the state */
10190 if (ci_putchk(si_ic(si), trash) == -1)
10191 si_rx_room_blk(si);
10192 free_trash_chunk(trash);
10193 si_rx_endp_more(si); /* let's come back later */
William Lallemand8f840d72019-10-23 10:53:05 +020010194 return 0; /* should come back */
10195
10196error:
10197 /* spin unlock and free are done in the release function */
William Lallemand33cc76f2019-10-31 11:43:45 +010010198 if (trash) {
10199 chunk_appendf(trash, "\n%sFailed!\n", err);
10200 if (ci_putchk(si_ic(si), trash) == -1)
10201 si_rx_room_blk(si);
10202 free_trash_chunk(trash);
10203 }
William Lallemand430413e2019-10-28 14:30:47 +010010204 /* error: call the release function and don't come back */
10205 return 1;
William Lallemand8f840d72019-10-23 10:53:05 +020010206}
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010207
10208/*
10209 * Parsing function of 'commit ssl cert'
10210 */
10211static int cli_parse_commit_cert(char **args, char *payload, struct appctx *appctx, void *private)
10212{
10213 char *err = NULL;
10214
10215 if (!*args[3])
10216 return cli_err(appctx, "'commit ssl cert expects a filename\n");
10217
10218 /* The operations on the CKCH architecture are locked so we can
10219 * manipulate ckch_store and ckch_inst */
10220 if (HA_SPIN_TRYLOCK(CKCH_LOCK, &ckch_lock))
10221 return cli_err(appctx, "Can't commit the certificate!\nOperations on certificates are currently locked!\n");
10222
10223 if (!ckchs_transaction.path) {
10224 memprintf(&err, "No ongoing transaction! !\n");
10225 goto error;
10226 }
10227
10228 if (strcmp(ckchs_transaction.path, args[3]) != 0) {
10229 memprintf(&err, "The ongoing transaction is about '%s' but you are trying to set '%s'\n", ckchs_transaction.path, args[3]);
10230 goto error;
10231 }
10232
10233 /* init the appctx structure */
10234 appctx->st2 = SETCERT_ST_INIT;
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010235 appctx->ctx.ssl.next_ckchi = NULL;
10236 appctx->ctx.ssl.new_ckchs = ckchs_transaction.new_ckchs;
10237 appctx->ctx.ssl.old_ckchs = ckchs_transaction.old_ckchs;
10238
10239 /* we don't unlock there, it will be unlock after the IO handler, in the release handler */
10240 return 0;
10241
10242error:
10243
10244 HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
10245 err = memprintf(&err, "%sCan't commit %s!\n", err ? err : "", args[3]);
10246
10247 return cli_dynerr(appctx, err);
10248}
10249
10250
William Lallemand8f840d72019-10-23 10:53:05 +020010251/*
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010252 * Parsing function of `set ssl cert`, it updates or creates a temporary ckch.
William Lallemand8f840d72019-10-23 10:53:05 +020010253 */
William Lallemand150bfa82019-09-19 17:12:49 +020010254static int cli_parse_set_cert(char **args, char *payload, struct appctx *appctx, void *private)
10255{
William Lallemand0c3b7d92019-10-18 11:27:07 +020010256 struct ckch_store *new_ckchs = NULL;
William Lallemand8f840d72019-10-23 10:53:05 +020010257 struct ckch_store *old_ckchs = NULL;
William Lallemand150bfa82019-09-19 17:12:49 +020010258 char *err = NULL;
William Lallemand963b2e72019-10-14 11:38:36 +020010259 int i;
William Lallemand849eed62019-10-17 16:23:50 +020010260 int bundle = -1; /* TRUE if >= 0 (ckch index) */
Emeric Brunf69ed1d2019-10-17 11:56:56 +020010261 int errcode = 0;
William Lallemand44b35322019-10-17 16:28:40 +020010262 char *end;
10263 int type = CERT_TYPE_PEM;
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010264 struct cert_key_and_chain *ckch;
10265 struct buffer *buf;
William Lallemand8f840d72019-10-23 10:53:05 +020010266
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010267 if ((buf = alloc_trash_chunk()) == NULL)
10268 return cli_err(appctx, "Can't allocate memory\n");
William Lallemand150bfa82019-09-19 17:12:49 +020010269
10270 if (!*args[3] || !payload)
10271 return cli_err(appctx, "'set ssl cert expects a filename and a certificat as a payload\n");
10272
10273 /* The operations on the CKCH architecture are locked so we can
10274 * manipulate ckch_store and ckch_inst */
10275 if (HA_SPIN_TRYLOCK(CKCH_LOCK, &ckch_lock))
10276 return cli_err(appctx, "Can't update the certificate!\nOperations on certificates are currently locked!\n");
10277
William Lallemand8f840d72019-10-23 10:53:05 +020010278 if (!chunk_strcpy(buf, args[3])) {
10279 memprintf(&err, "%sCan't allocate memory\n", err ? err : "");
10280 errcode |= ERR_ALERT | ERR_FATAL;
10281 goto end;
10282 }
10283
William Lallemand44b35322019-10-17 16:28:40 +020010284 /* check which type of file we want to update */
William Lallemandf29cdef2019-10-23 15:00:52 +020010285 for (i = 0; cert_exts[i].type < CERT_TYPE_MAX; i++) {
William Lallemand8f840d72019-10-23 10:53:05 +020010286 end = strrchr(buf->area, '.');
William Lallemand44b35322019-10-17 16:28:40 +020010287 if (end && *cert_exts[i].ext && (!strcmp(end + 1, cert_exts[i].ext))) {
10288 *end = '\0';
10289 type = cert_exts[i].type;
10290 break;
10291 }
10292 }
10293
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010294 appctx->ctx.ssl.old_ckchs = NULL;
10295 appctx->ctx.ssl.new_ckchs = NULL;
William Lallemand849eed62019-10-17 16:23:50 +020010296
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010297 /* if there is an ongoing transaction */
10298 if (ckchs_transaction.path) {
10299 /* 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 +020010300#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010301 if (ckchs_transaction.new_ckchs->multi) {
Emmanuel Hocdet40f2f1e2019-10-30 17:31:28 +010010302 char *end;
William Lallemand963b2e72019-10-14 11:38:36 +020010303 int j;
William Lallemand150bfa82019-09-19 17:12:49 +020010304
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010305 /* check if it was used in a bundle by removing the
William Lallemand963b2e72019-10-14 11:38:36 +020010306 * .dsa/.rsa/.ecdsa at the end of the filename */
William Lallemand8f840d72019-10-23 10:53:05 +020010307 end = strrchr(buf->area, '.');
Emmanuel Hocdet40f2f1e2019-10-30 17:31:28 +010010308 for (j = 0; end && j < SSL_SOCK_NUM_KEYTYPES; j++) {
William Lallemand963b2e72019-10-14 11:38:36 +020010309 if (!strcmp(end + 1, SSL_SOCK_KEYTYPE_NAMES[j])) {
10310 bundle = j; /* keep the type of certificate so we insert it at the right place */
10311 *end = '\0'; /* it's a bundle let's end the string*/
10312 break;
10313 }
William Lallemand150bfa82019-09-19 17:12:49 +020010314 }
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010315 if (bundle < 0) {
10316 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);
10317 errcode |= ERR_ALERT | ERR_FATAL;
10318 goto end;
10319 }
10320 }
10321#endif
10322
10323 /* if there is an ongoing transaction, check if this is the same file */
10324 if (strcmp(ckchs_transaction.path, buf->area) != 0) {
10325 memprintf(&err, "The ongoing transaction is about '%s' but you are trying to set '%s'\n", ckchs_transaction.path, buf->area);
10326 errcode |= ERR_ALERT | ERR_FATAL;
10327 goto end;
William Lallemand150bfa82019-09-19 17:12:49 +020010328 }
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010329
10330 appctx->ctx.ssl.old_ckchs = ckchs_transaction.new_ckchs;
10331
10332 } else {
10333 struct ckch_store *find_ckchs[2] = { NULL, NULL };
10334
10335 /* lookup for the certificate in the tree:
10336 * check if this is used as a bundle AND as a unique certificate */
10337 for (i = 0; i < 2; i++) {
10338
10339 if ((find_ckchs[i] = ckchs_lookup(buf->area)) != NULL) {
10340 /* only the bundle name is in the tree and you should
10341 * never update a bundle name, only a filename */
10342 if (bundle < 0 && find_ckchs[i]->multi) {
10343 /* we tried to look for a non-bundle and we found a bundle */
10344 memprintf(&err, "%s%s is a multi-cert bundle. Try updating %s.{dsa,rsa,ecdsa}\n",
10345 err ? err : "", args[3], args[3]);
10346 errcode |= ERR_ALERT | ERR_FATAL;
10347 goto end;
10348 }
William Lallemand3246d942019-11-04 14:02:11 +010010349 /* If we want a bundle but this is not a bundle
10350 * example: When you try to update <file>.rsa, but
10351 * <file> is a regular file */
10352 if (bundle >= 0 && find_ckchs[i]->multi == 0) {
10353 find_ckchs[i] = NULL;
10354 break;
10355 }
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010356 }
10357#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
10358 {
Emmanuel Hocdet40f2f1e2019-10-30 17:31:28 +010010359 char *end;
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010360 int j;
10361
10362 /* check if it was used in a bundle by removing the
10363 * .dsa/.rsa/.ecdsa at the end of the filename */
10364 end = strrchr(buf->area, '.');
Emmanuel Hocdet40f2f1e2019-10-30 17:31:28 +010010365 for (j = 0; end && j < SSL_SOCK_NUM_KEYTYPES; j++) {
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010366 if (!strcmp(end + 1, SSL_SOCK_KEYTYPE_NAMES[j])) {
10367 bundle = j; /* keep the type of certificate so we insert it at the right place */
10368 *end = '\0'; /* it's a bundle let's end the string*/
10369 break;
10370 }
10371 }
William Lallemand37031b82019-11-04 13:38:53 +010010372 if (bundle < 0) /* we didn't find a bundle extension */
10373 break;
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010374 }
William Lallemand963b2e72019-10-14 11:38:36 +020010375#else
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010376 /* bundles are not supported here, so we don't need to lookup again */
10377 break;
William Lallemand963b2e72019-10-14 11:38:36 +020010378#endif
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010379 }
10380
10381 if (find_ckchs[0] && find_ckchs[1]) {
10382 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",
10383 err ? err : "", find_ckchs[0]->path, find_ckchs[1]->path);
10384 errcode |= ERR_ALERT | ERR_FATAL;
10385 goto end;
10386 }
10387
10388 appctx->ctx.ssl.old_ckchs = find_ckchs[0] ? find_ckchs[0] : find_ckchs[1];
William Lallemand150bfa82019-09-19 17:12:49 +020010389 }
10390
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010391 if (!appctx->ctx.ssl.old_ckchs) {
10392 memprintf(&err, "%sCan't replace a certificate which is not referenced by the configuration!\n",
William Lallemand150bfa82019-09-19 17:12:49 +020010393 err ? err : "");
Emeric Brunf69ed1d2019-10-17 11:56:56 +020010394 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemand8f840d72019-10-23 10:53:05 +020010395 goto end;
William Lallemand150bfa82019-09-19 17:12:49 +020010396 }
10397
William Lallemand8a7fdf02019-11-04 10:59:32 +010010398 if (!appctx->ctx.ssl.path) {
10399 /* this is a new transaction, set the path of the transaction */
10400 appctx->ctx.ssl.path = strdup(appctx->ctx.ssl.old_ckchs->path);
10401 if (!appctx->ctx.ssl.path) {
10402 memprintf(&err, "%sCan't allocate memory\n", err ? err : "");
10403 errcode |= ERR_ALERT | ERR_FATAL;
10404 goto end;
10405 }
10406 }
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010407
10408 old_ckchs = appctx->ctx.ssl.old_ckchs;
10409
10410 /* TODO: handle filters */
10411 if (old_ckchs->filters) {
10412 memprintf(&err, "%sCertificates used in crt-list with filters are not supported!\n",
10413 err ? err : "");
10414 errcode |= ERR_ALERT | ERR_FATAL;
10415 goto end;
10416 }
10417
10418 /* duplicate the ckch store */
10419 new_ckchs = ckchs_dup(old_ckchs);
10420 if (!new_ckchs) {
10421 memprintf(&err, "%sCannot allocate memory!\n",
10422 err ? err : "");
10423 errcode |= ERR_ALERT | ERR_FATAL;
10424 goto end;
10425 }
10426
10427 if (!new_ckchs->multi)
10428 ckch = new_ckchs->ckch;
10429 else
10430 ckch = &new_ckchs->ckch[bundle];
10431
10432 /* appply the change on the duplicate */
10433 if (cert_exts[type].load(buf->area, payload, ckch, &err) != 0) {
10434 memprintf(&err, "%sCan't load the payload\n", err ? err : "");
10435 errcode |= ERR_ALERT | ERR_FATAL;
10436 goto end;
10437 }
10438
10439 appctx->ctx.ssl.new_ckchs = new_ckchs;
10440
10441 /* we succeed, we can save the ckchs in the transaction */
10442
10443 /* if there wasn't a transaction, update the old ckchs */
10444 if (!ckchs_transaction.old_ckchs && !ckchs_transaction.old_ckchs) {
10445 ckchs_transaction.old_ckchs = appctx->ctx.ssl.old_ckchs;
10446 ckchs_transaction.path = appctx->ctx.ssl.path;
10447 err = memprintf(&err, "Transaction created for certificate %s!\n", ckchs_transaction.path);
10448 } else {
10449 err = memprintf(&err, "Transaction updated for certificate %s!\n", ckchs_transaction.path);
10450
10451 }
10452
10453 /* free the previous ckchs if there was a transaction */
10454 ckchs_free(ckchs_transaction.new_ckchs);
10455
10456 ckchs_transaction.new_ckchs = appctx->ctx.ssl.new_ckchs;
10457
10458
William Lallemand8f840d72019-10-23 10:53:05 +020010459 /* creates the SNI ctxs later in the IO handler */
William Lallemand150bfa82019-09-19 17:12:49 +020010460
William Lallemand8f840d72019-10-23 10:53:05 +020010461end:
10462 free_trash_chunk(buf);
William Lallemand150bfa82019-09-19 17:12:49 +020010463
Emeric Brunf69ed1d2019-10-17 11:56:56 +020010464 if (errcode & ERR_CODE) {
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010465
10466 ckchs_free(appctx->ctx.ssl.new_ckchs);
10467 appctx->ctx.ssl.new_ckchs = NULL;
10468
10469 appctx->ctx.ssl.old_ckchs = NULL;
10470
10471 free(appctx->ctx.ssl.path);
10472 appctx->ctx.ssl.path = NULL;
10473
10474 HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
William Lallemand44b35322019-10-17 16:28:40 +020010475 return cli_dynerr(appctx, memprintf(&err, "%sCan't update %s!\n", err ? err : "", args[3]));
William Lallemand430413e2019-10-28 14:30:47 +010010476 } else {
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010477
10478 HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
10479 return cli_dynmsg(appctx, LOG_NOTICE, err);
William Lallemand430413e2019-10-28 14:30:47 +010010480 }
William Lallemand8f840d72019-10-23 10:53:05 +020010481 /* TODO: handle the ERR_WARN which are not handled because of the io_handler */
William Lallemand150bfa82019-09-19 17:12:49 +020010482}
10483
William Lallemand0bc9c8a2019-11-19 15:51:51 +010010484/* parsing function of 'abort ssl cert' */
10485static int cli_parse_abort_cert(char **args, char *payload, struct appctx *appctx, void *private)
10486{
10487 char *err = NULL;
10488
10489 if (!*args[3])
10490 return cli_err(appctx, "'abort ssl cert' expects a filename\n");
10491
10492 /* The operations on the CKCH architecture are locked so we can
10493 * manipulate ckch_store and ckch_inst */
10494 if (HA_SPIN_TRYLOCK(CKCH_LOCK, &ckch_lock))
10495 return cli_err(appctx, "Can't abort!\nOperations on certificates are currently locked!\n");
10496
10497 if (!ckchs_transaction.path) {
10498 memprintf(&err, "No ongoing transaction!\n");
10499 goto error;
10500 }
10501
10502 if (strcmp(ckchs_transaction.path, args[3]) != 0) {
10503 memprintf(&err, "The ongoing transaction is about '%s' but you are trying to abort a transaction for '%s'\n", ckchs_transaction.path, args[3]);
10504 goto error;
10505 }
10506
10507 /* Only free the ckchs there, because the SNI and instances were not generated yet */
10508 ckchs_free(ckchs_transaction.new_ckchs);
10509 ckchs_transaction.new_ckchs = NULL;
10510 ckchs_free(ckchs_transaction.old_ckchs);
10511 ckchs_transaction.old_ckchs = NULL;
10512 free(ckchs_transaction.path);
10513 ckchs_transaction.path = NULL;
10514
10515 HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
10516
10517 err = memprintf(&err, "Transaction aborted for certificate '%s'!\n", args[3]);
10518 return cli_dynmsg(appctx, LOG_NOTICE, err);
10519
10520error:
10521 HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
10522
10523 return cli_dynerr(appctx, err);
10524}
10525
Aurélien Nephtaliabbf6072018-04-18 13:26:46 +020010526static int cli_parse_set_ocspresponse(char **args, char *payload, struct appctx *appctx, void *private)
William Lallemand32af2032016-10-29 18:09:35 +020010527{
10528#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
10529 char *err = NULL;
Willy Tarreau1c913e42018-08-22 05:26:57 +020010530 int i, j, ret;
Aurélien Nephtali1e0867c2018-04-18 14:04:58 +020010531
10532 if (!payload)
10533 payload = args[3];
William Lallemand32af2032016-10-29 18:09:35 +020010534
10535 /* Expect one parameter: the new response in base64 encoding */
Willy Tarreau9d008692019-08-09 11:21:01 +020010536 if (!*payload)
10537 return cli_err(appctx, "'set ssl ocsp-response' expects response in base64 encoding.\n");
Aurélien Nephtali1e0867c2018-04-18 14:04:58 +020010538
10539 /* remove \r and \n from the payload */
10540 for (i = 0, j = 0; payload[i]; i++) {
10541 if (payload[i] == '\r' || payload[i] == '\n')
10542 continue;
10543 payload[j++] = payload[i];
10544 }
10545 payload[j] = 0;
William Lallemand32af2032016-10-29 18:09:35 +020010546
Willy Tarreau1c913e42018-08-22 05:26:57 +020010547 ret = base64dec(payload, j, trash.area, trash.size);
Willy Tarreau9d008692019-08-09 11:21:01 +020010548 if (ret < 0)
10549 return cli_err(appctx, "'set ssl ocsp-response' received invalid base64 encoded response.\n");
William Lallemand32af2032016-10-29 18:09:35 +020010550
Willy Tarreau1c913e42018-08-22 05:26:57 +020010551 trash.data = ret;
William Lallemand32af2032016-10-29 18:09:35 +020010552 if (ssl_sock_update_ocsp_response(&trash, &err)) {
Willy Tarreau9d008692019-08-09 11:21:01 +020010553 if (err)
10554 return cli_dynerr(appctx, memprintf(&err, "%s.\n", err));
10555 else
10556 return cli_err(appctx, "Failed to update OCSP response.\n");
William Lallemand32af2032016-10-29 18:09:35 +020010557 }
Willy Tarreau9d008692019-08-09 11:21:01 +020010558
10559 return cli_msg(appctx, LOG_INFO, "OCSP Response updated!\n");
William Lallemand32af2032016-10-29 18:09:35 +020010560#else
Willy Tarreau9d008692019-08-09 11:21:01 +020010561 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 +020010562#endif
10563
Nenad Merdanovicc31499d2019-03-23 11:00:32 +010010564}
10565
Willy Tarreau86a394e2019-05-09 14:15:32 +020010566#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000100fL)
Nenad Merdanovicc31499d2019-03-23 11:00:32 +010010567static inline int sample_conv_var2smp_str(const struct arg *arg, struct sample *smp)
10568{
10569 switch (arg->type) {
10570 case ARGT_STR:
10571 smp->data.type = SMP_T_STR;
10572 smp->data.u.str = arg->data.str;
10573 return 1;
10574 case ARGT_VAR:
10575 if (!vars_get_by_desc(&arg->data.var, smp))
10576 return 0;
10577 if (!sample_casts[smp->data.type][SMP_T_STR])
10578 return 0;
10579 if (!sample_casts[smp->data.type][SMP_T_STR](smp))
10580 return 0;
10581 return 1;
10582 default:
10583 return 0;
10584 }
10585}
10586
10587static int check_aes_gcm(struct arg *args, struct sample_conv *conv,
10588 const char *file, int line, char **err)
10589{
10590 switch(args[0].data.sint) {
10591 case 128:
10592 case 192:
10593 case 256:
10594 break;
10595 default:
10596 memprintf(err, "key size must be 128, 192 or 256 (bits).");
10597 return 0;
10598 }
10599 /* Try to decode a variable. */
10600 vars_check_arg(&args[1], NULL);
10601 vars_check_arg(&args[2], NULL);
10602 vars_check_arg(&args[3], NULL);
10603 return 1;
10604}
10605
10606/* Arguements: AES size in bits, nonce, key, tag. The last three arguments are base64 encoded */
10607static int sample_conv_aes_gcm_dec(const struct arg *arg_p, struct sample *smp, void *private)
10608{
10609 struct sample nonce, key, aead_tag;
10610 struct buffer *smp_trash, *smp_trash_alloc;
10611 EVP_CIPHER_CTX *ctx;
10612 int dec_size, ret;
10613
10614 smp_set_owner(&nonce, smp->px, smp->sess, smp->strm, smp->opt);
10615 if (!sample_conv_var2smp_str(&arg_p[1], &nonce))
10616 return 0;
10617
10618 smp_set_owner(&key, smp->px, smp->sess, smp->strm, smp->opt);
10619 if (!sample_conv_var2smp_str(&arg_p[2], &key))
10620 return 0;
10621
10622 smp_set_owner(&aead_tag, smp->px, smp->sess, smp->strm, smp->opt);
10623 if (!sample_conv_var2smp_str(&arg_p[3], &aead_tag))
10624 return 0;
10625
10626 smp_trash = get_trash_chunk();
10627 smp_trash_alloc = alloc_trash_chunk();
10628 if (!smp_trash_alloc)
10629 return 0;
10630
10631 ctx = EVP_CIPHER_CTX_new();
10632
10633 if (!ctx)
10634 goto err;
10635
10636 dec_size = base64dec(nonce.data.u.str.area, nonce.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 /* Set cipher type and mode */
10642 switch(arg_p[0].data.sint) {
10643 case 128:
10644 EVP_DecryptInit_ex(ctx, EVP_aes_128_gcm(), NULL, NULL, NULL);
10645 break;
10646 case 192:
10647 EVP_DecryptInit_ex(ctx, EVP_aes_192_gcm(), NULL, NULL, NULL);
10648 break;
10649 case 256:
10650 EVP_DecryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL);
10651 break;
10652 }
10653
10654 EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, smp_trash->data, NULL);
10655
10656 /* Initialise IV */
10657 if(!EVP_DecryptInit_ex(ctx, NULL, NULL, NULL, (unsigned char *) smp_trash->area))
10658 goto err;
10659
10660 dec_size = base64dec(key.data.u.str.area, key.data.u.str.data, smp_trash->area, smp_trash->size);
10661 if (dec_size < 0)
10662 goto err;
10663 smp_trash->data = dec_size;
10664
10665 /* Initialise key */
10666 if (!EVP_DecryptInit_ex(ctx, NULL, NULL, (unsigned char *) smp_trash->area, NULL))
10667 goto err;
10668
10669 if (!EVP_DecryptUpdate(ctx, (unsigned char *) smp_trash->area, (int *) &smp_trash->data,
10670 (unsigned char *) smp->data.u.str.area, (int) smp->data.u.str.data))
10671 goto err;
10672
10673 dec_size = base64dec(aead_tag.data.u.str.area, aead_tag.data.u.str.data, smp_trash_alloc->area, smp_trash_alloc->size);
10674 if (dec_size < 0)
10675 goto err;
10676 smp_trash_alloc->data = dec_size;
10677 dec_size = smp_trash->data;
10678
10679 EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, smp_trash_alloc->data, (void *) smp_trash_alloc->area);
10680 ret = EVP_DecryptFinal_ex(ctx, (unsigned char *) smp_trash->area + smp_trash->data, (int *) &smp_trash->data);
10681
10682 if (ret <= 0)
10683 goto err;
10684
10685 smp->data.u.str.data = dec_size + smp_trash->data;
10686 smp->data.u.str.area = smp_trash->area;
10687 smp->data.type = SMP_T_BIN;
10688 smp->flags &= ~SMP_F_CONST;
10689 free_trash_chunk(smp_trash_alloc);
10690 return 1;
10691
10692err:
10693 free_trash_chunk(smp_trash_alloc);
10694 return 0;
William Lallemand32af2032016-10-29 18:09:35 +020010695}
Nenad Merdanovicc31499d2019-03-23 11:00:32 +010010696# endif
William Lallemand32af2032016-10-29 18:09:35 +020010697
10698/* register cli keywords */
10699static struct cli_kw_list cli_kws = {{ },{
10700#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
10701 { { "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 +020010702 { { "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 +020010703#endif
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +010010704 { { "set", "ssl", "ocsp-response", NULL }, NULL, cli_parse_set_ocspresponse, NULL },
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010705 { { "set", "ssl", "cert", NULL }, "set ssl cert <certfile> <payload> : replace a certificate file", cli_parse_set_cert, NULL, NULL },
10706 { { "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 +010010707 { { "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 +020010708 { { NULL }, NULL, NULL, NULL }
10709}};
10710
Willy Tarreau0108d902018-11-25 19:14:37 +010010711INITCALL1(STG_REGISTER, cli_register_kw, &cli_kws);
William Lallemand32af2032016-10-29 18:09:35 +020010712
Willy Tarreau7875d092012-09-10 08:20:03 +020010713/* Note: must not be declared <const> as its list will be overwritten.
10714 * Please take care of keeping this list alphabetically sorted.
10715 */
Willy Tarreaudc13c112013-06-21 23:16:39 +020010716static struct sample_fetch_kw_list sample_fetch_keywords = {ILH, {
Emeric Brun645ae792014-04-30 14:21:06 +020010717 { "ssl_bc", smp_fetch_ssl_fc, 0, NULL, SMP_T_BOOL, SMP_USE_L5SRV },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +020010718 { "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 +010010719#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Jérôme Magnine064a802018-12-03 22:21:04 +010010720 { "ssl_bc_alpn", smp_fetch_ssl_fc_alpn, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
Olivier Houchard6b77f492018-11-22 18:18:29 +010010721#endif
Emeric Brun645ae792014-04-30 14:21:06 +020010722 { "ssl_bc_cipher", smp_fetch_ssl_fc_cipher, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
Olivier Houchard6b77f492018-11-22 18:18:29 +010010723#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
10724 { "ssl_bc_npn", smp_fetch_ssl_fc_npn, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
10725#endif
Emeric Brun74f7ffa2018-02-19 16:14:12 +010010726 { "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 +020010727 { "ssl_bc_protocol", smp_fetch_ssl_fc_protocol, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
Emeric Brunb73a9b02014-04-30 18:49:19 +020010728 { "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 +020010729 { "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 +020010730#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
Emeric Brun645ae792014-04-30 14:21:06 +020010731 { "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 -040010732#endif
Emmanuel Hocdet839af572019-05-14 16:27:35 +020010733#if HA_OPENSSL_VERSION_NUMBER >= 0x10100000L
Patrick Hemmer65674662019-06-04 08:13:03 -040010734 { "ssl_bc_client_random", smp_fetch_ssl_fc_random, 0, NULL, SMP_T_BIN, SMP_USE_L5SRV },
10735 { "ssl_bc_server_random", smp_fetch_ssl_fc_random, 0, NULL, SMP_T_BIN, SMP_USE_L5SRV },
Patrick Hemmere0275472018-04-28 19:15:51 -040010736 { "ssl_bc_session_key", smp_fetch_ssl_fc_session_key, 0, NULL, SMP_T_BIN, SMP_USE_L5SRV },
10737#endif
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +020010738 { "ssl_c_ca_err", smp_fetch_ssl_c_ca_err, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
10739 { "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 +010010740 { "ssl_c_der", smp_fetch_ssl_x_der, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +020010741 { "ssl_c_err", smp_fetch_ssl_c_err, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Emeric Brunba841a12014-04-30 17:05:08 +020010742 { "ssl_c_i_dn", smp_fetch_ssl_x_i_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
10743 { "ssl_c_key_alg", smp_fetch_ssl_x_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
10744 { "ssl_c_notafter", smp_fetch_ssl_x_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
10745 { "ssl_c_notbefore", smp_fetch_ssl_x_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
10746 { "ssl_c_sig_alg", smp_fetch_ssl_x_sig_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
10747 { "ssl_c_s_dn", smp_fetch_ssl_x_s_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
10748 { "ssl_c_serial", smp_fetch_ssl_x_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
10749 { "ssl_c_sha1", smp_fetch_ssl_x_sha1, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +010010750 { "ssl_c_used", smp_fetch_ssl_c_used, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +020010751 { "ssl_c_verify", smp_fetch_ssl_c_verify, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
10752 { "ssl_c_version", smp_fetch_ssl_x_version, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Emeric Brun43e79582014-10-29 19:03:26 +010010753 { "ssl_f_der", smp_fetch_ssl_x_der, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Emeric Brunba841a12014-04-30 17:05:08 +020010754 { "ssl_f_i_dn", smp_fetch_ssl_x_i_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
10755 { "ssl_f_key_alg", smp_fetch_ssl_x_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
10756 { "ssl_f_notafter", smp_fetch_ssl_x_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
10757 { "ssl_f_notbefore", smp_fetch_ssl_x_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
10758 { "ssl_f_sig_alg", smp_fetch_ssl_x_sig_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
10759 { "ssl_f_s_dn", smp_fetch_ssl_x_s_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
10760 { "ssl_f_serial", smp_fetch_ssl_x_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Emeric Brun55f4fa82014-04-30 17:11:25 +020010761 { "ssl_f_sha1", smp_fetch_ssl_x_sha1, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +020010762 { "ssl_f_version", smp_fetch_ssl_x_version, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +010010763 { "ssl_fc", smp_fetch_ssl_fc, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +020010764 { "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 +010010765 { "ssl_fc_cipher", smp_fetch_ssl_fc_cipher, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +010010766 { "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 +020010767 { "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 +010010768 { "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 +020010769 { "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 +010010770#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +010010771 { "ssl_fc_npn", smp_fetch_ssl_fc_npn, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreaua33c6542012-10-15 13:19:06 +020010772#endif
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +010010773#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +010010774 { "ssl_fc_alpn", smp_fetch_ssl_fc_alpn, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreauab861d32013-04-02 02:30:41 +020010775#endif
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +010010776 { "ssl_fc_protocol", smp_fetch_ssl_fc_protocol, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreau9a1ab082019-05-09 13:26:41 +020010777#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
Emeric Brunb73a9b02014-04-30 18:49:19 +020010778 { "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 -040010779#endif
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +020010780 { "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 +020010781#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +010010782 { "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 -040010783#endif
Emmanuel Hocdet839af572019-05-14 16:27:35 +020010784#if HA_OPENSSL_VERSION_NUMBER >= 0x10100000L
Patrick Hemmer65674662019-06-04 08:13:03 -040010785 { "ssl_fc_client_random", smp_fetch_ssl_fc_random, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
10786 { "ssl_fc_server_random", smp_fetch_ssl_fc_random, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Patrick Hemmere0275472018-04-28 19:15:51 -040010787 { "ssl_fc_session_key", smp_fetch_ssl_fc_session_key, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
10788#endif
Patrick Hemmer41966772018-04-28 19:15:48 -040010789#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +010010790 { "ssl_fc_sni", smp_fetch_ssl_fc_sni, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Patrick Hemmer41966772018-04-28 19:15:48 -040010791#endif
Thierry FOURNIER5bf77322017-02-25 12:45:22 +010010792 { "ssl_fc_cipherlist_bin", smp_fetch_ssl_fc_cl_bin, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
10793 { "ssl_fc_cipherlist_hex", smp_fetch_ssl_fc_cl_hex, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
10794 { "ssl_fc_cipherlist_str", smp_fetch_ssl_fc_cl_str, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
10795 { "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 +020010796 { NULL, NULL, 0, 0, 0 },
10797}};
10798
Willy Tarreau0108d902018-11-25 19:14:37 +010010799INITCALL1(STG_REGISTER, sample_register_fetches, &sample_fetch_keywords);
10800
Willy Tarreau7875d092012-09-10 08:20:03 +020010801/* Note: must not be declared <const> as its list will be overwritten.
10802 * Please take care of keeping this list alphabetically sorted.
10803 */
Willy Tarreaudc13c112013-06-21 23:16:39 +020010804static struct acl_kw_list acl_kws = {ILH, {
Thierry FOURNIERc5a4e982014-03-05 16:07:08 +010010805 { "ssl_fc_sni_end", "ssl_fc_sni", PAT_MATCH_END },
10806 { "ssl_fc_sni_reg", "ssl_fc_sni", PAT_MATCH_REG },
Willy Tarreau8ed669b2013-01-11 15:49:37 +010010807 { /* END */ },
Willy Tarreau7875d092012-09-10 08:20:03 +020010808}};
10809
Willy Tarreau0108d902018-11-25 19:14:37 +010010810INITCALL1(STG_REGISTER, acl_register_keywords, &acl_kws);
10811
Willy Tarreau79eeafa2012-09-14 07:53:05 +020010812/* Note: must not be declared <const> as its list will be overwritten.
10813 * Please take care of keeping this list alphabetically sorted, doing so helps
10814 * all code contributors.
10815 * Optional keywords are also declared with a NULL ->parse() function so that
10816 * the config parser can report an appropriate error when a known keyword was
10817 * not enabled.
10818 */
Emmanuel Hocdet98263292016-12-29 18:26:15 +010010819static struct ssl_bind_kw ssl_bind_kws[] = {
Olivier Houchardc2aae742017-09-22 18:26:28 +020010820 { "allow-0rtt", ssl_bind_parse_allow_0rtt, 0 }, /* allow 0-RTT */
Emmanuel Hocdet98263292016-12-29 18:26:15 +010010821 { "alpn", ssl_bind_parse_alpn, 1 }, /* set ALPN supported protocols */
10822 { "ca-file", ssl_bind_parse_ca_file, 1 }, /* set CAfile to process verify on client cert */
10823 { "ciphers", ssl_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", ssl_bind_parse_ciphersuites, 1 }, /* set TLS 1.3 cipher suite */
10826#endif
Emmanuel Hocdet98263292016-12-29 18:26:15 +010010827 { "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 +010010828 { "curves", ssl_bind_parse_curves, 1 }, /* set SSL curve suite */
Emmanuel Hocdet98263292016-12-29 18:26:15 +010010829 { "ecdhe", ssl_bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +020010830 { "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 +010010831 { "npn", ssl_bind_parse_npn, 1 }, /* set NPN supported protocols */
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +020010832 { "ssl-min-ver", ssl_bind_parse_tls_method_minmax,1 }, /* minimum version */
10833 { "ssl-max-ver", ssl_bind_parse_tls_method_minmax,1 }, /* maximum version */
Emmanuel Hocdet98263292016-12-29 18:26:15 +010010834 { "verify", ssl_bind_parse_verify, 1 }, /* set SSL verify method */
10835 { NULL, NULL, 0 },
10836};
10837
Willy Tarreau0108d902018-11-25 19:14:37 +010010838/* no initcall for ssl_bind_kws, these ones are parsed in the parser loop */
10839
Willy Tarreau51fb7652012-09-18 18:24:39 +020010840static struct bind_kw_list bind_kws = { "SSL", { }, {
Olivier Houchardc2aae742017-09-22 18:26:28 +020010841 { "allow-0rtt", bind_parse_allow_0rtt, 0 }, /* Allow 0RTT */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +020010842 { "alpn", bind_parse_alpn, 1 }, /* set ALPN supported protocols */
10843 { "ca-file", bind_parse_ca_file, 1 }, /* set CAfile to process verify on client cert */
10844 { "ca-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ignore on verify depth > 0 */
10845 { "ca-sign-file", bind_parse_ca_sign_file, 1 }, /* set CAFile used to generate and sign server certs */
10846 { "ca-sign-pass", bind_parse_ca_sign_pass, 1 }, /* set CAKey passphrase */
10847 { "ciphers", bind_parse_ciphers, 1 }, /* set SSL cipher suite */
Emmanuel Hocdet839af572019-05-14 16:27:35 +020010848#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +020010849 { "ciphersuites", bind_parse_ciphersuites, 1 }, /* set TLS 1.3 cipher suite */
10850#endif
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +020010851 { "crl-file", bind_parse_crl_file, 1 }, /* set certificat revocation list file use on client cert verify */
10852 { "crt", bind_parse_crt, 1 }, /* load SSL certificates from this location */
10853 { "crt-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ingore on verify depth == 0 */
10854 { "crt-list", bind_parse_crt_list, 1 }, /* load a list of crt from this location */
10855 { "curves", bind_parse_curves, 1 }, /* set SSL curve suite */
10856 { "ecdhe", bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
10857 { "force-sslv3", bind_parse_tls_method_options, 0 }, /* force SSLv3 */
10858 { "force-tlsv10", bind_parse_tls_method_options, 0 }, /* force TLSv10 */
10859 { "force-tlsv11", bind_parse_tls_method_options, 0 }, /* force TLSv11 */
10860 { "force-tlsv12", bind_parse_tls_method_options, 0 }, /* force TLSv12 */
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +020010861 { "force-tlsv13", bind_parse_tls_method_options, 0 }, /* force TLSv13 */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +020010862 { "generate-certificates", bind_parse_generate_certs, 0 }, /* enable the server certificates generation */
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +020010863 { "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 +020010864 { "no-sslv3", bind_parse_tls_method_options, 0 }, /* disable SSLv3 */
10865 { "no-tlsv10", bind_parse_tls_method_options, 0 }, /* disable TLSv10 */
10866 { "no-tlsv11", bind_parse_tls_method_options, 0 }, /* disable TLSv11 */
10867 { "no-tlsv12", bind_parse_tls_method_options, 0 }, /* disable TLSv12 */
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +020010868 { "no-tlsv13", bind_parse_tls_method_options, 0 }, /* disable TLSv13 */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +020010869 { "no-tls-tickets", bind_parse_no_tls_tickets, 0 }, /* disable session resumption tickets */
10870 { "ssl", bind_parse_ssl, 0 }, /* enable SSL processing */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +020010871 { "ssl-min-ver", bind_parse_tls_method_minmax, 1 }, /* minimum version */
10872 { "ssl-max-ver", bind_parse_tls_method_minmax, 1 }, /* maximum version */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +020010873 { "strict-sni", bind_parse_strict_sni, 0 }, /* refuse negotiation if sni doesn't match a certificate */
10874 { "tls-ticket-keys", bind_parse_tls_ticket_keys, 1 }, /* set file to load TLS ticket keys from */
10875 { "verify", bind_parse_verify, 1 }, /* set SSL verify method */
10876 { "npn", bind_parse_npn, 1 }, /* set NPN supported protocols */
10877 { "prefer-client-ciphers", bind_parse_pcc, 0 }, /* prefer client ciphers */
Willy Tarreau79eeafa2012-09-14 07:53:05 +020010878 { NULL, NULL, 0 },
10879}};
Emeric Brun46591952012-05-18 15:47:34 +020010880
Willy Tarreau0108d902018-11-25 19:14:37 +010010881INITCALL1(STG_REGISTER, bind_register_keywords, &bind_kws);
10882
Willy Tarreau92faadf2012-10-10 23:04:25 +020010883/* Note: must not be declared <const> as its list will be overwritten.
10884 * Please take care of keeping this list alphabetically sorted, doing so helps
10885 * all code contributors.
10886 * Optional keywords are also declared with a NULL ->parse() function so that
10887 * the config parser can report an appropriate error when a known keyword was
10888 * not enabled.
10889 */
10890static struct srv_kw_list srv_kws = { "SSL", { }, {
Olivier Houchard522eea72017-11-03 16:27:47 +010010891 { "allow-0rtt", srv_parse_allow_0rtt, 0, 1 }, /* Allow using early data on this server */
Olivier Houchardc7566002018-11-20 23:33:50 +010010892 { "alpn", srv_parse_alpn, 1, 1 }, /* Set ALPN supported protocols */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +020010893 { "ca-file", srv_parse_ca_file, 1, 1 }, /* set CAfile to process verify server cert */
Olivier Houchard92150142018-12-21 19:47:01 +010010894 { "check-alpn", srv_parse_alpn, 1, 1 }, /* Set ALPN used for checks */
Olivier Houchard9130a962017-10-17 17:33:43 +020010895 { "check-sni", srv_parse_check_sni, 1, 1 }, /* set SNI */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +020010896 { "check-ssl", srv_parse_check_ssl, 0, 1 }, /* enable SSL for health checks */
10897 { "ciphers", srv_parse_ciphers, 1, 1 }, /* select the cipher suite */
Emmanuel Hocdet839af572019-05-14 16:27:35 +020010898#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +020010899 { "ciphersuites", srv_parse_ciphersuites, 1, 1 }, /* select the cipher suite */
10900#endif
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +020010901 { "crl-file", srv_parse_crl_file, 1, 1 }, /* set certificate revocation list file use on server cert verify */
10902 { "crt", srv_parse_crt, 1, 1 }, /* set client certificate */
10903 { "force-sslv3", srv_parse_tls_method_options, 0, 1 }, /* force SSLv3 */
10904 { "force-tlsv10", srv_parse_tls_method_options, 0, 1 }, /* force TLSv10 */
10905 { "force-tlsv11", srv_parse_tls_method_options, 0, 1 }, /* force TLSv11 */
10906 { "force-tlsv12", srv_parse_tls_method_options, 0, 1 }, /* force TLSv12 */
10907 { "force-tlsv13", srv_parse_tls_method_options, 0, 1 }, /* force TLSv13 */
10908 { "no-check-ssl", srv_parse_no_check_ssl, 0, 1 }, /* disable SSL for health checks */
10909 { "no-send-proxy-v2-ssl", srv_parse_no_send_proxy_ssl, 0, 1 }, /* do not send PROXY protocol header v2 with SSL info */
10910 { "no-send-proxy-v2-ssl-cn", srv_parse_no_send_proxy_cn, 0, 1 }, /* do not send PROXY protocol header v2 with CN */
10911 { "no-ssl", srv_parse_no_ssl, 0, 1 }, /* disable SSL processing */
10912 { "no-ssl-reuse", srv_parse_no_ssl_reuse, 0, 1 }, /* disable session reuse */
10913 { "no-sslv3", srv_parse_tls_method_options, 0, 0 }, /* disable SSLv3 */
10914 { "no-tlsv10", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv10 */
10915 { "no-tlsv11", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv11 */
10916 { "no-tlsv12", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv12 */
10917 { "no-tlsv13", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv13 */
10918 { "no-tls-tickets", srv_parse_no_tls_tickets, 0, 1 }, /* disable session resumption tickets */
Olivier Houchardc7566002018-11-20 23:33:50 +010010919 { "npn", srv_parse_npn, 1, 1 }, /* Set NPN supported protocols */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +020010920 { "send-proxy-v2-ssl", srv_parse_send_proxy_ssl, 0, 1 }, /* send PROXY protocol header v2 with SSL info */
10921 { "send-proxy-v2-ssl-cn", srv_parse_send_proxy_cn, 0, 1 }, /* send PROXY protocol header v2 with CN */
10922 { "sni", srv_parse_sni, 1, 1 }, /* send SNI extension */
10923 { "ssl", srv_parse_ssl, 0, 1 }, /* enable SSL processing */
10924 { "ssl-min-ver", srv_parse_tls_method_minmax, 1, 1 }, /* minimum version */
10925 { "ssl-max-ver", srv_parse_tls_method_minmax, 1, 1 }, /* maximum version */
10926 { "ssl-reuse", srv_parse_ssl_reuse, 0, 1 }, /* enable session reuse */
10927 { "tls-tickets", srv_parse_tls_tickets, 0, 1 }, /* enable session resumption tickets */
10928 { "verify", srv_parse_verify, 1, 1 }, /* set SSL verify method */
10929 { "verifyhost", srv_parse_verifyhost, 1, 1 }, /* require that SSL cert verifies for hostname */
Willy Tarreau92faadf2012-10-10 23:04:25 +020010930 { NULL, NULL, 0, 0 },
10931}};
10932
Willy Tarreau0108d902018-11-25 19:14:37 +010010933INITCALL1(STG_REGISTER, srv_register_keywords, &srv_kws);
10934
Emeric Brun2c86cbf2014-10-30 15:56:50 +010010935static struct cfg_kw_list cfg_kws = {ILH, {
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +010010936 { CFG_GLOBAL, "ca-base", ssl_parse_global_ca_crt_base },
10937 { CFG_GLOBAL, "crt-base", ssl_parse_global_ca_crt_base },
Willy Tarreau0bea58d2016-12-21 23:17:25 +010010938 { CFG_GLOBAL, "maxsslconn", ssl_parse_global_int },
Emeric Brun2c86cbf2014-10-30 15:56:50 +010010939 { CFG_GLOBAL, "ssl-default-bind-options", ssl_parse_default_bind_options },
10940 { CFG_GLOBAL, "ssl-default-server-options", ssl_parse_default_server_options },
Willy Tarreau14e36a12016-12-21 23:28:13 +010010941#ifndef OPENSSL_NO_DH
10942 { CFG_GLOBAL, "ssl-dh-param-file", ssl_parse_global_dh_param_file },
10943#endif
Grant Zhangfa6c7ee2017-01-14 01:42:15 +000010944 { CFG_GLOBAL, "ssl-mode-async", ssl_parse_global_ssl_async },
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020010945#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +000010946 { CFG_GLOBAL, "ssl-engine", ssl_parse_global_ssl_engine },
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020010947#endif
Willy Tarreau9ceda382016-12-21 23:13:03 +010010948 { CFG_GLOBAL, "tune.ssl.cachesize", ssl_parse_global_int },
10949#ifndef OPENSSL_NO_DH
10950 { CFG_GLOBAL, "tune.ssl.default-dh-param", ssl_parse_global_default_dh },
10951#endif
10952 { CFG_GLOBAL, "tune.ssl.force-private-cache", ssl_parse_global_private_cache },
10953 { CFG_GLOBAL, "tune.ssl.lifetime", ssl_parse_global_lifetime },
10954 { CFG_GLOBAL, "tune.ssl.maxrecord", ssl_parse_global_int },
10955 { CFG_GLOBAL, "tune.ssl.ssl-ctx-cache-size", ssl_parse_global_int },
Thierry FOURNIER5bf77322017-02-25 12:45:22 +010010956 { CFG_GLOBAL, "tune.ssl.capture-cipherlist-size", ssl_parse_global_capture_cipherlist },
Willy Tarreauf22e9682016-12-21 23:23:19 +010010957 { CFG_GLOBAL, "ssl-default-bind-ciphers", ssl_parse_global_ciphers },
10958 { CFG_GLOBAL, "ssl-default-server-ciphers", ssl_parse_global_ciphers },
Emmanuel Hocdet839af572019-05-14 16:27:35 +020010959#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +020010960 { CFG_GLOBAL, "ssl-default-bind-ciphersuites", ssl_parse_global_ciphersuites },
10961 { CFG_GLOBAL, "ssl-default-server-ciphersuites", ssl_parse_global_ciphersuites },
10962#endif
Emeric Brun2c86cbf2014-10-30 15:56:50 +010010963 { 0, NULL, NULL },
10964}};
10965
Willy Tarreau0108d902018-11-25 19:14:37 +010010966INITCALL1(STG_REGISTER, cfg_register_keywords, &cfg_kws);
10967
Nenad Merdanovicc31499d2019-03-23 11:00:32 +010010968/* Note: must not be declared <const> as its list will be overwritten */
10969static struct sample_conv_kw_list conv_kws = {ILH, {
Willy Tarreau86a394e2019-05-09 14:15:32 +020010970#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000100fL)
Nenad Merdanovicc31499d2019-03-23 11:00:32 +010010971 { "aes_gcm_dec", sample_conv_aes_gcm_dec, ARG4(4,SINT,STR,STR,STR), check_aes_gcm, SMP_T_BIN, SMP_T_BIN },
10972#endif
10973 { NULL, NULL, 0, 0, 0 },
10974}};
10975
10976INITCALL1(STG_REGISTER, sample_register_convs, &conv_kws);
10977
Willy Tarreauf7bc57c2012-10-03 00:19:48 +020010978/* transport-layer operations for SSL sockets */
Willy Tarreaud9f5cca2016-12-22 21:08:52 +010010979static struct xprt_ops ssl_sock = {
Emeric Brun46591952012-05-18 15:47:34 +020010980 .snd_buf = ssl_sock_from_buf,
10981 .rcv_buf = ssl_sock_to_buf,
Olivier Houcharddf357842019-03-21 16:30:07 +010010982 .subscribe = ssl_subscribe,
10983 .unsubscribe = ssl_unsubscribe,
Olivier Houchard5149b592019-05-23 17:47:36 +020010984 .remove_xprt = ssl_remove_xprt,
Olivier Houchard2e055482019-05-27 19:50:12 +020010985 .add_xprt = ssl_add_xprt,
Emeric Brun46591952012-05-18 15:47:34 +020010986 .rcv_pipe = NULL,
10987 .snd_pipe = NULL,
10988 .shutr = NULL,
10989 .shutw = ssl_sock_shutw,
10990 .close = ssl_sock_close,
10991 .init = ssl_sock_init,
Willy Tarreau55d37912016-12-21 23:38:39 +010010992 .prepare_bind_conf = ssl_sock_prepare_bind_conf,
Willy Tarreau795cdab2016-12-22 17:30:54 +010010993 .destroy_bind_conf = ssl_sock_destroy_bind_conf,
Willy Tarreau17d45382016-12-22 21:16:08 +010010994 .prepare_srv = ssl_sock_prepare_srv_ctx,
10995 .destroy_srv = ssl_sock_free_srv_ctx,
Willy Tarreau8743f7e2016-12-04 18:44:29 +010010996 .get_alpn = ssl_sock_get_alpn,
Willy Tarreau8e0bb0a2016-11-24 16:58:12 +010010997 .name = "SSL",
Emeric Brun46591952012-05-18 15:47:34 +020010998};
10999
Olivier Houchardccaa7de2017-10-02 11:51:03 +020011000enum act_return ssl_action_wait_for_hs(struct act_rule *rule, struct proxy *px,
11001 struct session *sess, struct stream *s, int flags)
11002{
11003 struct connection *conn;
Olivier Houchard6fa63d92017-11-27 18:41:32 +010011004 struct conn_stream *cs;
Olivier Houchardccaa7de2017-10-02 11:51:03 +020011005
11006 conn = objt_conn(sess->origin);
Olivier Houchard6fa63d92017-11-27 18:41:32 +010011007 cs = objt_cs(s->si[0].end);
Olivier Houchardccaa7de2017-10-02 11:51:03 +020011008
Olivier Houchard6fa63d92017-11-27 18:41:32 +010011009 if (conn && cs) {
Olivier Houchardccaa7de2017-10-02 11:51:03 +020011010 if (conn->flags & (CO_FL_EARLY_SSL_HS | CO_FL_SSL_WAIT_HS)) {
Olivier Houchard6fa63d92017-11-27 18:41:32 +010011011 cs->flags |= CS_FL_WAIT_FOR_HS;
Olivier Houchardccaa7de2017-10-02 11:51:03 +020011012 s->req.flags |= CF_READ_NULL;
11013 return ACT_RET_YIELD;
11014 }
11015 }
11016 return (ACT_RET_CONT);
11017}
11018
11019static enum act_parse_ret ssl_parse_wait_for_hs(const char **args, int *orig_arg, struct proxy *px, struct act_rule *rule, char **err)
11020{
11021 rule->action_ptr = ssl_action_wait_for_hs;
11022
11023 return ACT_RET_PRS_OK;
11024}
11025
11026static struct action_kw_list http_req_actions = {ILH, {
11027 { "wait-for-handshake", ssl_parse_wait_for_hs },
11028 { /* END */ }
11029}};
11030
Willy Tarreau0108d902018-11-25 19:14:37 +010011031INITCALL1(STG_REGISTER, http_req_keywords_register, &http_req_actions);
11032
Willy Tarreau5db847a2019-05-09 14:13:35 +020011033#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +010011034
11035static void ssl_sock_sctl_free_func(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, long argl, void *argp)
11036{
11037 if (ptr) {
11038 chunk_destroy(ptr);
11039 free(ptr);
11040 }
11041}
11042
11043#endif
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +010011044static void ssl_sock_capture_free_func(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, long argl, void *argp)
11045{
Willy Tarreaubafbe012017-11-24 17:34:44 +010011046 pool_free(pool_head_ssl_capture, ptr);
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +010011047}
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +010011048
Emeric Brun46591952012-05-18 15:47:34 +020011049__attribute__((constructor))
Willy Tarreau92faadf2012-10-10 23:04:25 +020011050static void __ssl_sock_init(void)
11051{
Ilya Shipitsin0590f442019-05-25 19:30:50 +050011052#if (!defined(OPENSSL_NO_COMP) && !defined(SSL_OP_NO_COMPRESSION))
Emeric Brun46591952012-05-18 15:47:34 +020011053 STACK_OF(SSL_COMP)* cm;
Ilya Shipitsine242f3d2019-05-25 03:38:14 +050011054 int n;
Ilya Shipitsin0590f442019-05-25 19:30:50 +050011055#endif
Emeric Brun46591952012-05-18 15:47:34 +020011056
Willy Tarreauef934602016-12-22 23:12:01 +010011057 if (global_ssl.listen_default_ciphers)
11058 global_ssl.listen_default_ciphers = strdup(global_ssl.listen_default_ciphers);
11059 if (global_ssl.connect_default_ciphers)
11060 global_ssl.connect_default_ciphers = strdup(global_ssl.connect_default_ciphers);
Emmanuel Hocdet839af572019-05-14 16:27:35 +020011061#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +020011062 if (global_ssl.listen_default_ciphersuites)
11063 global_ssl.listen_default_ciphersuites = strdup(global_ssl.listen_default_ciphersuites);
11064 if (global_ssl.connect_default_ciphersuites)
11065 global_ssl.connect_default_ciphersuites = strdup(global_ssl.connect_default_ciphersuites);
11066#endif
Willy Tarreau610f04b2014-02-13 11:36:41 +010011067
Willy Tarreau13e14102016-12-22 20:25:26 +010011068 xprt_register(XPRT_SSL, &ssl_sock);
Willy Tarreau9a1ab082019-05-09 13:26:41 +020011069#if HA_OPENSSL_VERSION_NUMBER < 0x10100000L
Emeric Brun46591952012-05-18 15:47:34 +020011070 SSL_library_init();
Rosen Penev68185952018-12-14 08:47:02 -080011071#endif
Ilya Shipitsin0590f442019-05-25 19:30:50 +050011072#if (!defined(OPENSSL_NO_COMP) && !defined(SSL_OP_NO_COMPRESSION))
Emeric Brun46591952012-05-18 15:47:34 +020011073 cm = SSL_COMP_get_compression_methods();
Ilya Shipitsine242f3d2019-05-25 03:38:14 +050011074 n = sk_SSL_COMP_num(cm);
11075 while (n--) {
11076 (void) sk_SSL_COMP_pop(cm);
11077 }
Ilya Shipitsin0590f442019-05-25 19:30:50 +050011078#endif
Ilya Shipitsine242f3d2019-05-25 03:38:14 +050011079
Willy Tarreau5db847a2019-05-09 14:13:35 +020011080#if defined(USE_THREAD) && (HA_OPENSSL_VERSION_NUMBER < 0x10100000L)
Emeric Brun821bb9b2017-06-15 16:37:39 +020011081 ssl_locking_init();
11082#endif
Willy Tarreau5db847a2019-05-09 14:13:35 +020011083#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +010011084 sctl_ex_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, ssl_sock_sctl_free_func);
11085#endif
Thierry FOURNIER28962c92018-06-17 21:37:05 +020011086 ssl_app_data_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL);
Thierry FOURNIER16ff0502018-06-17 21:33:01 +020011087 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 +020011088#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +000011089 ENGINE_load_builtin_engines();
Grant Zhangfa6c7ee2017-01-14 01:42:15 +000011090 hap_register_post_check(ssl_check_async_engine_count);
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020011091#endif
Willy Tarreaud1c57502016-12-22 22:46:15 +010011092#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
11093 hap_register_post_check(tlskeys_finalize_config);
11094#endif
Willy Tarreau80713382018-11-26 10:19:54 +010011095
11096 global.ssl_session_max_cost = SSL_SESSION_MAX_COST;
11097 global.ssl_handshake_max_cost = SSL_HANDSHAKE_MAX_COST;
11098
11099#ifndef OPENSSL_NO_DH
11100 ssl_dh_ptr_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, NULL);
11101 hap_register_post_deinit(ssl_free_dh);
11102#endif
11103#ifndef OPENSSL_NO_ENGINE
11104 hap_register_post_deinit(ssl_free_engines);
11105#endif
11106 /* Load SSL string for the verbose & debug mode. */
11107 ERR_load_SSL_strings();
Olivier Houcharda8955d52019-04-07 22:00:38 +020011108 ha_meth = BIO_meth_new(0x666, "ha methods");
11109 BIO_meth_set_write(ha_meth, ha_ssl_write);
11110 BIO_meth_set_read(ha_meth, ha_ssl_read);
11111 BIO_meth_set_ctrl(ha_meth, ha_ssl_ctrl);
11112 BIO_meth_set_create(ha_meth, ha_ssl_new);
11113 BIO_meth_set_destroy(ha_meth, ha_ssl_free);
11114 BIO_meth_set_puts(ha_meth, ha_ssl_puts);
11115 BIO_meth_set_gets(ha_meth, ha_ssl_gets);
William Lallemand150bfa82019-09-19 17:12:49 +020011116
11117 HA_SPIN_INIT(&ckch_lock);
Willy Tarreau80713382018-11-26 10:19:54 +010011118}
Willy Tarreaud92aa5c2015-01-15 21:34:39 +010011119
Willy Tarreau80713382018-11-26 10:19:54 +010011120/* Compute and register the version string */
11121static void ssl_register_build_options()
11122{
11123 char *ptr = NULL;
11124 int i;
11125
Willy Tarreauc2c0b612016-12-21 19:23:20 +010011126 memprintf(&ptr, "Built with OpenSSL version : "
11127#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet50e25e12017-03-24 15:20:03 +010011128 "BoringSSL");
Willy Tarreauc2c0b612016-12-21 19:23:20 +010011129#else /* OPENSSL_IS_BORINGSSL */
11130 OPENSSL_VERSION_TEXT
11131 "\nRunning on OpenSSL version : %s%s",
Rosen Penev68185952018-12-14 08:47:02 -080011132 OpenSSL_version(OPENSSL_VERSION),
Willy Tarreau1d158ab2019-05-09 13:41:45 +020011133 ((OPENSSL_VERSION_NUMBER ^ OpenSSL_version_num()) >> 8) ? " (VERSIONS DIFFER!)" : "");
Willy Tarreauc2c0b612016-12-21 19:23:20 +010011134#endif
11135 memprintf(&ptr, "%s\nOpenSSL library supports TLS extensions : "
Willy Tarreau9a1ab082019-05-09 13:26:41 +020011136#if HA_OPENSSL_VERSION_NUMBER < 0x00907000L
Willy Tarreauc2c0b612016-12-21 19:23:20 +010011137 "no (library version too old)"
11138#elif defined(OPENSSL_NO_TLSEXT)
11139 "no (disabled via OPENSSL_NO_TLSEXT)"
11140#else
11141 "yes"
11142#endif
11143 "", ptr);
11144
11145 memprintf(&ptr, "%s\nOpenSSL library supports SNI : "
11146#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
11147 "yes"
11148#else
11149#ifdef OPENSSL_NO_TLSEXT
11150 "no (because of OPENSSL_NO_TLSEXT)"
11151#else
11152 "no (version might be too old, 0.9.8f min needed)"
11153#endif
11154#endif
11155 "", ptr);
11156
Emmanuel Hocdetf80bc242017-07-12 14:25:38 +020011157 memprintf(&ptr, "%s\nOpenSSL library supports :", ptr);
11158 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
11159 if (methodVersions[i].option)
11160 memprintf(&ptr, "%s %s", ptr, methodVersions[i].name);
Emmanuel Hocdet50e25e12017-03-24 15:20:03 +010011161
Willy Tarreauc2c0b612016-12-21 19:23:20 +010011162 hap_register_build_opts(ptr, 1);
Willy Tarreau80713382018-11-26 10:19:54 +010011163}
Willy Tarreauc2c0b612016-12-21 19:23:20 +010011164
Willy Tarreau80713382018-11-26 10:19:54 +010011165INITCALL0(STG_REGISTER, ssl_register_build_options);
Remi Gacogne4f902b82015-05-28 16:23:00 +020011166
Emeric Brun46591952012-05-18 15:47:34 +020011167
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020011168#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +000011169void ssl_free_engines(void) {
11170 struct ssl_engine_list *wl, *wlb;
11171 /* free up engine list */
11172 list_for_each_entry_safe(wl, wlb, &openssl_engines, list) {
11173 ENGINE_finish(wl->e);
11174 ENGINE_free(wl->e);
11175 LIST_DEL(&wl->list);
11176 free(wl);
11177 }
11178}
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020011179#endif
Christopher Faulet31af49d2015-06-09 17:29:50 +020011180
Remi Gacogned3a23c32015-05-28 16:39:47 +020011181#ifndef OPENSSL_NO_DH
Grant Zhang872f9c22017-01-21 01:10:18 +000011182void ssl_free_dh(void) {
11183 if (local_dh_1024) {
11184 DH_free(local_dh_1024);
11185 local_dh_1024 = NULL;
11186 }
11187 if (local_dh_2048) {
11188 DH_free(local_dh_2048);
11189 local_dh_2048 = NULL;
11190 }
11191 if (local_dh_4096) {
11192 DH_free(local_dh_4096);
11193 local_dh_4096 = NULL;
11194 }
Remi Gacogne47783ef2015-05-29 15:53:22 +020011195 if (global_dh) {
11196 DH_free(global_dh);
11197 global_dh = NULL;
11198 }
Grant Zhang872f9c22017-01-21 01:10:18 +000011199}
11200#endif
11201
11202__attribute__((destructor))
11203static void __ssl_sock_deinit(void)
11204{
11205#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Emeric Brun821bb9b2017-06-15 16:37:39 +020011206 if (ssl_ctx_lru_tree) {
11207 lru64_destroy(ssl_ctx_lru_tree);
Christopher Faulet2a944ee2017-11-07 10:42:54 +010011208 HA_RWLOCK_DESTROY(&ssl_ctx_lru_rwlock);
Emeric Brun821bb9b2017-06-15 16:37:39 +020011209 }
Remi Gacogned3a23c32015-05-28 16:39:47 +020011210#endif
11211
Willy Tarreau5db847a2019-05-09 14:13:35 +020011212#if (HA_OPENSSL_VERSION_NUMBER < 0x10100000L)
Remi Gacogned3a23c32015-05-28 16:39:47 +020011213 ERR_remove_state(0);
11214 ERR_free_strings();
11215
11216 EVP_cleanup();
Rosen Penev68185952018-12-14 08:47:02 -080011217#endif
Remi Gacogned3a23c32015-05-28 16:39:47 +020011218
Willy Tarreau5db847a2019-05-09 14:13:35 +020011219#if (HA_OPENSSL_VERSION_NUMBER >= 0x00907000L) && (HA_OPENSSL_VERSION_NUMBER < 0x10100000L)
Remi Gacogned3a23c32015-05-28 16:39:47 +020011220 CRYPTO_cleanup_all_ex_data();
11221#endif
Olivier Houcharda8955d52019-04-07 22:00:38 +020011222 BIO_meth_free(ha_meth);
Remi Gacogned3a23c32015-05-28 16:39:47 +020011223}
11224
11225
Emeric Brun46591952012-05-18 15:47:34 +020011226/*
11227 * Local variables:
11228 * c-indent-level: 8
11229 * c-basic-offset: 8
11230 * End:
11231 */