blob: 8f205f6ba666c110e2902d93fa24c7c468c8507e [file] [log] [blame]
yanbzhu08ce6ab2015-12-02 13:01:29 -05001
Emeric Brun46591952012-05-18 15:47:34 +02002/*
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02003 * SSL/TLS transport layer over SOCK_STREAM sockets
Emeric Brun46591952012-05-18 15:47:34 +02004 *
5 * Copyright (C) 2012 EXCELIANCE, Emeric Brun <ebrun@exceliance.fr>
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version
10 * 2 of the License, or (at your option) any later version.
11 *
Willy Tarreau69845df2012-09-10 09:43:09 +020012 * Acknowledgement:
13 * We'd like to specially thank the Stud project authors for a very clean
14 * and well documented code which helped us understand how the OpenSSL API
15 * ought to be used in non-blocking mode. This is one difficult part which
16 * is not easy to get from the OpenSSL doc, and reading the Stud code made
17 * it much more obvious than the examples in the OpenSSL package. Keep up
18 * the good works, guys !
19 *
20 * Stud is an extremely efficient and scalable SSL/TLS proxy which combines
21 * particularly well with haproxy. For more info about this project, visit :
22 * https://github.com/bumptech/stud
23 *
Emeric Brun46591952012-05-18 15:47:34 +020024 */
25
Willy Tarreau8d164dc2019-05-10 09:35:00 +020026/* Note: do NOT include openssl/xxx.h here, do it in openssl-compat.h */
Emeric Brun46591952012-05-18 15:47:34 +020027#define _GNU_SOURCE
Emeric Brunfc0421f2012-09-07 17:30:07 +020028#include <ctype.h>
29#include <dirent.h>
Emeric Brun46591952012-05-18 15:47:34 +020030#include <errno.h>
31#include <fcntl.h>
32#include <stdio.h>
33#include <stdlib.h>
Emeric Brunfc0421f2012-09-07 17:30:07 +020034#include <string.h>
35#include <unistd.h>
Emeric Brun46591952012-05-18 15:47:34 +020036
37#include <sys/socket.h>
38#include <sys/stat.h>
39#include <sys/types.h>
Christopher Faulet31af49d2015-06-09 17:29:50 +020040#include <netdb.h>
Emeric Brun46591952012-05-18 15:47:34 +020041#include <netinet/tcp.h>
42
Christopher Faulet31af49d2015-06-09 17:29:50 +020043#include <import/lru.h>
44#include <import/xxhash.h>
45
Emeric Brun46591952012-05-18 15:47:34 +020046#include <common/buffer.h>
Willy Tarreau843b7cb2018-07-13 10:54:26 +020047#include <common/chunk.h>
Emeric Brun46591952012-05-18 15:47:34 +020048#include <common/compat.h>
49#include <common/config.h>
50#include <common/debug.h>
Willy Tarreau79eeafa2012-09-14 07:53:05 +020051#include <common/errors.h>
Willy Tarreau0108d902018-11-25 19:14:37 +010052#include <common/initcall.h>
Willy Tarreau55994562019-05-09 14:52:44 +020053#include <common/openssl-compat.h>
Emeric Brun46591952012-05-18 15:47:34 +020054#include <common/standard.h>
55#include <common/ticks.h>
56#include <common/time.h>
Emeric Brun2c86cbf2014-10-30 15:56:50 +010057#include <common/cfgparse.h>
Nenad Merdanovic05552d42015-02-27 19:56:49 +010058#include <common/base64.h>
Emeric Brun46591952012-05-18 15:47:34 +020059
Emeric Brunfc0421f2012-09-07 17:30:07 +020060#include <ebsttree.h>
61
William Lallemand32af2032016-10-29 18:09:35 +020062#include <types/applet.h>
63#include <types/cli.h>
Emeric Brunfc0421f2012-09-07 17:30:07 +020064#include <types/global.h>
65#include <types/ssl_sock.h>
William Lallemand32af2032016-10-29 18:09:35 +020066#include <types/stats.h>
Emeric Brunfc0421f2012-09-07 17:30:07 +020067
Willy Tarreau7875d092012-09-10 08:20:03 +020068#include <proto/acl.h>
69#include <proto/arg.h>
William Lallemand32af2032016-10-29 18:09:35 +020070#include <proto/channel.h>
Emeric Brun46591952012-05-18 15:47:34 +020071#include <proto/connection.h>
William Lallemand32af2032016-10-29 18:09:35 +020072#include <proto/cli.h>
Emeric Brun46591952012-05-18 15:47:34 +020073#include <proto/fd.h>
74#include <proto/freq_ctr.h>
75#include <proto/frontend.h>
Willy Tarreau61c112a2018-10-02 16:43:32 +020076#include <proto/http_rules.h>
Willy Tarreau79eeafa2012-09-14 07:53:05 +020077#include <proto/listener.h>
Thierry FOURNIERed66c292013-11-28 11:05:19 +010078#include <proto/pattern.h>
Christopher Faulet31af49d2015-06-09 17:29:50 +020079#include <proto/proto_tcp.h>
Christopher Fauletfc9cfe42019-07-16 14:54:53 +020080#include <proto/http_ana.h>
Willy Tarreau92faadf2012-10-10 23:04:25 +020081#include <proto/server.h>
William Lallemand32af2032016-10-29 18:09:35 +020082#include <proto/stream_interface.h>
Emeric Brun46591952012-05-18 15:47:34 +020083#include <proto/log.h>
Emeric Brun94324a42012-10-11 14:00:19 +020084#include <proto/proxy.h>
Emeric Brunfc0421f2012-09-07 17:30:07 +020085#include <proto/shctx.h>
Emeric Brun46591952012-05-18 15:47:34 +020086#include <proto/ssl_sock.h>
Willy Tarreau9ad7bd42015-04-03 19:19:59 +020087#include <proto/stream.h>
Emeric Brun46591952012-05-18 15:47:34 +020088#include <proto/task.h>
Nenad Merdanovicc31499d2019-03-23 11:00:32 +010089#include <proto/vars.h>
Emeric Brun46591952012-05-18 15:47:34 +020090
Willy Tarreau9356dac2019-05-10 09:22:53 +020091/* ***** READ THIS before adding code here! *****
92 *
93 * Due to API incompatibilities between multiple OpenSSL versions and their
94 * derivatives, it's often tempting to add macros to (re-)define certain
95 * symbols. Please do not do this here, and do it in common/openssl-compat.h
96 * exclusively so that the whole code consistently uses the same macros.
97 *
98 * Whenever possible if a macro is missing in certain versions, it's better
99 * to conditionally define it in openssl-compat.h than using lots of ifdefs.
100 */
101
Willy Tarreau518cedd2014-02-17 15:43:01 +0100102/* Warning, these are bits, not integers! */
Emeric Brune64aef12012-09-21 13:15:06 +0200103#define SSL_SOCK_ST_FL_VERIFY_DONE 0x00000001
Emeric Brund8b2bb52014-01-28 15:43:53 +0100104#define SSL_SOCK_ST_FL_16K_WBFSIZE 0x00000002
Willy Tarreau518cedd2014-02-17 15:43:01 +0100105#define SSL_SOCK_SEND_UNLIMITED 0x00000004
Emeric Brun29f037d2014-04-25 19:05:36 +0200106#define SSL_SOCK_RECV_HEARTBEAT 0x00000008
107
Emeric Brunf282a812012-09-21 15:27:54 +0200108/* bits 0xFFFF0000 are reserved to store verify errors */
109
110/* Verify errors macros */
111#define SSL_SOCK_CA_ERROR_TO_ST(e) (((e > 63) ? 63 : e) << (16))
112#define SSL_SOCK_CAEDEPTH_TO_ST(d) (((d > 15) ? 15 : d) << (6+16))
113#define SSL_SOCK_CRTERROR_TO_ST(e) (((e > 63) ? 63 : e) << (4+6+16))
114
115#define SSL_SOCK_ST_TO_CA_ERROR(s) ((s >> (16)) & 63)
116#define SSL_SOCK_ST_TO_CAEDEPTH(s) ((s >> (6+16)) & 15)
117#define SSL_SOCK_ST_TO_CRTERROR(s) ((s >> (4+6+16)) & 63)
Emeric Brune64aef12012-09-21 13:15:06 +0200118
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200119/* ssl_methods flags for ssl options */
120#define MC_SSL_O_ALL 0x0000
121#define MC_SSL_O_NO_SSLV3 0x0001 /* disable SSLv3 */
122#define MC_SSL_O_NO_TLSV10 0x0002 /* disable TLSv10 */
123#define MC_SSL_O_NO_TLSV11 0x0004 /* disable TLSv11 */
124#define MC_SSL_O_NO_TLSV12 0x0008 /* disable TLSv12 */
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +0200125#define MC_SSL_O_NO_TLSV13 0x0010 /* disable TLSv13 */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200126
127/* ssl_methods versions */
128enum {
129 CONF_TLSV_NONE = 0,
130 CONF_TLSV_MIN = 1,
131 CONF_SSLV3 = 1,
132 CONF_TLSV10 = 2,
133 CONF_TLSV11 = 3,
134 CONF_TLSV12 = 4,
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +0200135 CONF_TLSV13 = 5,
136 CONF_TLSV_MAX = 5,
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200137};
138
Emeric Brun850efd52014-01-29 12:24:34 +0100139/* server and bind verify method, it uses a global value as default */
140enum {
141 SSL_SOCK_VERIFY_DEFAULT = 0,
142 SSL_SOCK_VERIFY_REQUIRED = 1,
143 SSL_SOCK_VERIFY_OPTIONAL = 2,
144 SSL_SOCK_VERIFY_NONE = 3,
145};
146
William Lallemand3f85c9a2017-10-09 16:30:50 +0200147
Willy Tarreau71b734c2014-01-28 15:19:44 +0100148int sslconns = 0;
149int totalsslconns = 0;
Willy Tarreaud9f5cca2016-12-22 21:08:52 +0100150static struct xprt_ops ssl_sock;
Emeric Brunece0c332017-12-06 13:51:49 +0100151int nb_engines = 0;
Emeric Brune1f38db2012-09-03 20:36:47 +0200152
Willy Tarreauef934602016-12-22 23:12:01 +0100153static struct {
154 char *crt_base; /* base directory path for certificates */
155 char *ca_base; /* base directory path for CAs and CRLs */
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000156 int async; /* whether we use ssl async mode */
Willy Tarreauef934602016-12-22 23:12:01 +0100157
158 char *listen_default_ciphers;
159 char *connect_default_ciphers;
Emmanuel Hocdet839af572019-05-14 16:27:35 +0200160#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +0200161 char *listen_default_ciphersuites;
162 char *connect_default_ciphersuites;
163#endif
Willy Tarreauef934602016-12-22 23:12:01 +0100164 int listen_default_ssloptions;
165 int connect_default_ssloptions;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200166 struct tls_version_filter listen_default_sslmethods;
167 struct tls_version_filter connect_default_sslmethods;
Willy Tarreauef934602016-12-22 23:12:01 +0100168
169 int private_cache; /* Force to use a private session cache even if nbproc > 1 */
170 unsigned int life_time; /* SSL session lifetime in seconds */
171 unsigned int max_record; /* SSL max record size */
172 unsigned int default_dh_param; /* SSL maximum DH parameter size */
173 int ctx_cache; /* max number of entries in the ssl_ctx cache. */
Thierry FOURNIER5bf77322017-02-25 12:45:22 +0100174 int capture_cipherlist; /* Size of the cipherlist buffer. */
Willy Tarreauef934602016-12-22 23:12:01 +0100175} global_ssl = {
176#ifdef LISTEN_DEFAULT_CIPHERS
177 .listen_default_ciphers = LISTEN_DEFAULT_CIPHERS,
178#endif
179#ifdef CONNECT_DEFAULT_CIPHERS
180 .connect_default_ciphers = CONNECT_DEFAULT_CIPHERS,
181#endif
Emmanuel Hocdet839af572019-05-14 16:27:35 +0200182#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +0200183#ifdef LISTEN_DEFAULT_CIPHERSUITES
184 .listen_default_ciphersuites = LISTEN_DEFAULT_CIPHERSUITES,
185#endif
186#ifdef CONNECT_DEFAULT_CIPHERSUITES
187 .connect_default_ciphersuites = CONNECT_DEFAULT_CIPHERSUITES,
188#endif
189#endif
Willy Tarreauef934602016-12-22 23:12:01 +0100190 .listen_default_ssloptions = BC_SSL_O_NONE,
191 .connect_default_ssloptions = SRV_SSL_O_NONE,
192
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200193 .listen_default_sslmethods.flags = MC_SSL_O_ALL,
194 .listen_default_sslmethods.min = CONF_TLSV_NONE,
195 .listen_default_sslmethods.max = CONF_TLSV_NONE,
196 .connect_default_sslmethods.flags = MC_SSL_O_ALL,
197 .connect_default_sslmethods.min = CONF_TLSV_NONE,
198 .connect_default_sslmethods.max = CONF_TLSV_NONE,
199
Willy Tarreauef934602016-12-22 23:12:01 +0100200#ifdef DEFAULT_SSL_MAX_RECORD
201 .max_record = DEFAULT_SSL_MAX_RECORD,
202#endif
203 .default_dh_param = SSL_DEFAULT_DH_PARAM,
204 .ctx_cache = DEFAULT_SSL_CTX_CACHE,
Thierry FOURNIER5bf77322017-02-25 12:45:22 +0100205 .capture_cipherlist = 0,
Willy Tarreauef934602016-12-22 23:12:01 +0100206};
207
Olivier Houcharda8955d52019-04-07 22:00:38 +0200208static BIO_METHOD *ha_meth;
209
Olivier Houchard66ab4982019-02-26 18:37:15 +0100210struct ssl_sock_ctx {
Olivier Houcharda8955d52019-04-07 22:00:38 +0200211 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +0100212 SSL *ssl;
Olivier Houcharda8955d52019-04-07 22:00:38 +0200213 BIO *bio;
Olivier Houchard5149b592019-05-23 17:47:36 +0200214 const struct xprt_ops *xprt;
Olivier Houchard66ab4982019-02-26 18:37:15 +0100215 void *xprt_ctx;
Olivier Houchardea8dd942019-05-20 14:02:16 +0200216 struct wait_event wait_event;
217 struct wait_event *recv_wait;
218 struct wait_event *send_wait;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +0100219 int xprt_st; /* transport layer state, initialized to zero */
220 int tmp_early_data; /* 1st byte of early data, if any */
221 int sent_early_data; /* Amount of early data we sent so far */
222
Olivier Houchard66ab4982019-02-26 18:37:15 +0100223};
224
225DECLARE_STATIC_POOL(ssl_sock_ctx_pool, "ssl_sock_ctx_pool", sizeof(struct ssl_sock_ctx));
226
Olivier Houchardea8dd942019-05-20 14:02:16 +0200227static struct task *ssl_sock_io_cb(struct task *, void *, unsigned short);
Olivier Houchard000694c2019-05-23 14:45:12 +0200228static int ssl_sock_handshake(struct connection *conn, unsigned int flag);
Olivier Houchardea8dd942019-05-20 14:02:16 +0200229
Olivier Houcharda8955d52019-04-07 22:00:38 +0200230/* Methods to implement OpenSSL BIO */
231static int ha_ssl_write(BIO *h, const char *buf, int num)
232{
233 struct buffer tmpbuf;
234 struct ssl_sock_ctx *ctx;
235 int ret;
236
237 ctx = BIO_get_data(h);
238 tmpbuf.size = num;
239 tmpbuf.area = (void *)(uintptr_t)buf;
240 tmpbuf.data = num;
241 tmpbuf.head = 0;
242 ret = ctx->xprt->snd_buf(ctx->conn, ctx->xprt_ctx, &tmpbuf, num, 0);
Olivier Houchardb51937e2019-05-01 17:24:36 +0200243 if (ret == 0 && !(ctx->conn->flags & (CO_FL_ERROR | CO_FL_SOCK_WR_SH))) {
Olivier Houcharda8955d52019-04-07 22:00:38 +0200244 BIO_set_retry_write(h);
Olivier Houcharda28454e2019-04-24 12:04:36 +0200245 ret = -1;
Olivier Houchardb51937e2019-05-01 17:24:36 +0200246 } else if (ret == 0)
247 BIO_clear_retry_flags(h);
Olivier Houcharda8955d52019-04-07 22:00:38 +0200248 return ret;
249}
250
251static int ha_ssl_gets(BIO *h, char *buf, int size)
252{
253
254 return 0;
255}
256
257static int ha_ssl_puts(BIO *h, const char *str)
258{
259
260 return ha_ssl_write(h, str, strlen(str));
261}
262
263static int ha_ssl_read(BIO *h, char *buf, int size)
264{
265 struct buffer tmpbuf;
266 struct ssl_sock_ctx *ctx;
267 int ret;
268
269 ctx = BIO_get_data(h);
270 tmpbuf.size = size;
271 tmpbuf.area = buf;
272 tmpbuf.data = 0;
273 tmpbuf.head = 0;
274 ret = ctx->xprt->rcv_buf(ctx->conn, ctx->xprt_ctx, &tmpbuf, size, 0);
Olivier Houchardb51937e2019-05-01 17:24:36 +0200275 if (ret == 0 && !(ctx->conn->flags & (CO_FL_ERROR | CO_FL_SOCK_RD_SH))) {
Olivier Houcharda8955d52019-04-07 22:00:38 +0200276 BIO_set_retry_read(h);
Olivier Houcharda28454e2019-04-24 12:04:36 +0200277 ret = -1;
Olivier Houchardb51937e2019-05-01 17:24:36 +0200278 } else if (ret == 0)
279 BIO_clear_retry_flags(h);
Olivier Houcharda8955d52019-04-07 22:00:38 +0200280
281 return ret;
282}
283
284static long ha_ssl_ctrl(BIO *h, int cmd, long arg1, void *arg2)
285{
286 int ret = 0;
287 switch (cmd) {
288 case BIO_CTRL_DUP:
289 case BIO_CTRL_FLUSH:
290 ret = 1;
291 break;
292 }
293 return ret;
294}
295
296static int ha_ssl_new(BIO *h)
297{
298 BIO_set_init(h, 1);
299 BIO_set_data(h, NULL);
300 BIO_clear_flags(h, ~0);
301 return 1;
302}
303
304static int ha_ssl_free(BIO *data)
305{
306
307 return 1;
308}
309
310
Willy Tarreau5db847a2019-05-09 14:13:35 +0200311#if defined(USE_THREAD) && (HA_OPENSSL_VERSION_NUMBER < 0x10100000L)
Christopher Faulet9dcf9b62017-11-13 10:34:01 +0100312
Emeric Brun821bb9b2017-06-15 16:37:39 +0200313static HA_RWLOCK_T *ssl_rwlocks;
314
315
316unsigned long ssl_id_function(void)
317{
318 return (unsigned long)tid;
319}
320
321void ssl_locking_function(int mode, int n, const char * file, int line)
322{
323 if (mode & CRYPTO_LOCK) {
324 if (mode & CRYPTO_READ)
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100325 HA_RWLOCK_RDLOCK(SSL_LOCK, &ssl_rwlocks[n]);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200326 else
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100327 HA_RWLOCK_WRLOCK(SSL_LOCK, &ssl_rwlocks[n]);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200328 }
329 else {
330 if (mode & CRYPTO_READ)
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100331 HA_RWLOCK_RDUNLOCK(SSL_LOCK, &ssl_rwlocks[n]);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200332 else
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100333 HA_RWLOCK_WRUNLOCK(SSL_LOCK, &ssl_rwlocks[n]);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200334 }
335}
336
337static int ssl_locking_init(void)
338{
339 int i;
340
341 ssl_rwlocks = malloc(sizeof(HA_RWLOCK_T)*CRYPTO_num_locks());
342 if (!ssl_rwlocks)
343 return -1;
344
345 for (i = 0 ; i < CRYPTO_num_locks() ; i++)
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100346 HA_RWLOCK_INIT(&ssl_rwlocks[i]);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200347
348 CRYPTO_set_id_callback(ssl_id_function);
349 CRYPTO_set_locking_callback(ssl_locking_function);
350
351 return 0;
352}
Christopher Faulet9dcf9b62017-11-13 10:34:01 +0100353
Emeric Brun821bb9b2017-06-15 16:37:39 +0200354#endif
355
William Lallemand150bfa82019-09-19 17:12:49 +0200356__decl_hathreads(HA_SPINLOCK_T ckch_lock);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200357
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +0100358/* This memory pool is used for capturing clienthello parameters. */
Thierry FOURNIER5bf77322017-02-25 12:45:22 +0100359struct ssl_capture {
Thierry FOURNIER5bf77322017-02-25 12:45:22 +0100360 unsigned long long int xxh64;
361 unsigned char ciphersuite_len;
362 char ciphersuite[0];
363};
Willy Tarreaubafbe012017-11-24 17:34:44 +0100364struct pool_head *pool_head_ssl_capture = NULL;
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +0100365static int ssl_capture_ptr_index = -1;
Thierry FOURNIER28962c92018-06-17 21:37:05 +0200366static int ssl_app_data_index = -1;
Willy Tarreauef934602016-12-22 23:12:01 +0100367
Emmanuel Hocdet96b78342017-10-31 15:46:07 +0100368static int ssl_pkey_info_index = -1;
369
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200370#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
371struct list tlskeys_reference = LIST_HEAD_INIT(tlskeys_reference);
372#endif
373
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +0200374#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +0000375static unsigned int openssl_engines_initialized;
376struct list openssl_engines = LIST_HEAD_INIT(openssl_engines);
377struct ssl_engine_list {
378 struct list list;
379 ENGINE *e;
380};
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +0200381#endif
Grant Zhang872f9c22017-01-21 01:10:18 +0000382
Remi Gacogne8de54152014-07-15 11:36:40 +0200383#ifndef OPENSSL_NO_DH
Remi Gacogne4f902b82015-05-28 16:23:00 +0200384static int ssl_dh_ptr_index = -1;
Remi Gacogne47783ef2015-05-29 15:53:22 +0200385static DH *global_dh = NULL;
Remi Gacogne8de54152014-07-15 11:36:40 +0200386static DH *local_dh_1024 = NULL;
387static DH *local_dh_2048 = NULL;
388static DH *local_dh_4096 = NULL;
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +0100389static DH *ssl_get_tmp_dh(SSL *ssl, int export, int keylen);
Remi Gacogne8de54152014-07-15 11:36:40 +0200390#endif /* OPENSSL_NO_DH */
391
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100392#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Christopher Faulet31af49d2015-06-09 17:29:50 +0200393/* X509V3 Extensions that will be added on generated certificates */
394#define X509V3_EXT_SIZE 5
395static char *x509v3_ext_names[X509V3_EXT_SIZE] = {
396 "basicConstraints",
397 "nsComment",
398 "subjectKeyIdentifier",
399 "authorityKeyIdentifier",
400 "keyUsage",
401};
402static char *x509v3_ext_values[X509V3_EXT_SIZE] = {
403 "CA:FALSE",
404 "\"OpenSSL Generated Certificate\"",
405 "hash",
406 "keyid,issuer:always",
407 "nonRepudiation,digitalSignature,keyEncipherment"
408};
Christopher Faulet31af49d2015-06-09 17:29:50 +0200409/* LRU cache to store generated certificate */
410static struct lru64_head *ssl_ctx_lru_tree = NULL;
411static unsigned int ssl_ctx_lru_seed = 0;
Emeric Brun821bb9b2017-06-15 16:37:39 +0200412static unsigned int ssl_ctx_serial;
Willy Tarreau86abe442018-11-25 20:12:18 +0100413__decl_rwlock(ssl_ctx_lru_rwlock);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200414
Willy Tarreauc8ad3be2015-06-17 15:48:26 +0200415#endif // SSL_CTRL_SET_TLSEXT_HOSTNAME
416
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100417static struct ssl_bind_kw ssl_bind_kws[];
418
Willy Tarreau9a1ab082019-05-09 13:26:41 +0200419#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
yanbzhube2774d2015-12-10 15:07:30 -0500420/* The order here matters for picking a default context,
421 * keep the most common keytype at the bottom of the list
422 */
423const char *SSL_SOCK_KEYTYPE_NAMES[] = {
424 "dsa",
425 "ecdsa",
426 "rsa"
427};
428#define SSL_SOCK_NUM_KEYTYPES 3
Willy Tarreau30da7ad2015-12-14 11:28:33 +0100429#else
430#define SSL_SOCK_NUM_KEYTYPES 1
yanbzhube2774d2015-12-10 15:07:30 -0500431#endif
432
William Lallemandc3cd35f2017-11-28 11:04:43 +0100433static struct shared_context *ssl_shctx = NULL; /* ssl shared session cache */
William Lallemand4f45bb92017-10-30 20:08:51 +0100434static struct eb_root *sh_ssl_sess_tree; /* ssl shared session tree */
435
436#define sh_ssl_sess_tree_delete(s) ebmb_delete(&(s)->key);
437
438#define sh_ssl_sess_tree_insert(s) (struct sh_ssl_sess_hdr *)ebmb_insert(sh_ssl_sess_tree, \
439 &(s)->key, SSL_MAX_SSL_SESSION_ID_LENGTH);
440
441#define sh_ssl_sess_tree_lookup(k) (struct sh_ssl_sess_hdr *)ebmb_lookup(sh_ssl_sess_tree, \
442 (k), SSL_MAX_SSL_SESSION_ID_LENGTH);
William Lallemand3f85c9a2017-10-09 16:30:50 +0200443
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100444/*
445 * This function gives the detail of the SSL error. It is used only
446 * if the debug mode and the verbose mode are activated. It dump all
447 * the SSL error until the stack was empty.
448 */
449static forceinline void ssl_sock_dump_errors(struct connection *conn)
450{
451 unsigned long ret;
452
453 if (unlikely(global.mode & MODE_DEBUG)) {
454 while(1) {
455 ret = ERR_get_error();
456 if (ret == 0)
457 return;
458 fprintf(stderr, "fd[%04x] OpenSSL error[0x%lx] %s: %s\n",
Willy Tarreau585744b2017-08-24 14:31:19 +0200459 (unsigned short)conn->handle.fd, ret,
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100460 ERR_func_error_string(ret), ERR_reason_error_string(ret));
461 }
462 }
463}
464
yanbzhube2774d2015-12-10 15:07:30 -0500465
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +0200466#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +0000467static int ssl_init_single_engine(const char *engine_id, const char *def_algorithms)
468{
469 int err_code = ERR_ABORT;
470 ENGINE *engine;
471 struct ssl_engine_list *el;
472
473 /* grab the structural reference to the engine */
474 engine = ENGINE_by_id(engine_id);
475 if (engine == NULL) {
Christopher Faulet767a84b2017-11-24 16:50:31 +0100476 ha_alert("ssl-engine %s: failed to get structural reference\n", engine_id);
Grant Zhang872f9c22017-01-21 01:10:18 +0000477 goto fail_get;
478 }
479
480 if (!ENGINE_init(engine)) {
481 /* the engine couldn't initialise, release it */
Christopher Faulet767a84b2017-11-24 16:50:31 +0100482 ha_alert("ssl-engine %s: failed to initialize\n", engine_id);
Grant Zhang872f9c22017-01-21 01:10:18 +0000483 goto fail_init;
484 }
485
486 if (ENGINE_set_default_string(engine, def_algorithms) == 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +0100487 ha_alert("ssl-engine %s: failed on ENGINE_set_default_string\n", engine_id);
Grant Zhang872f9c22017-01-21 01:10:18 +0000488 goto fail_set_method;
489 }
490
491 el = calloc(1, sizeof(*el));
492 el->e = engine;
493 LIST_ADD(&openssl_engines, &el->list);
Emeric Brunece0c332017-12-06 13:51:49 +0100494 nb_engines++;
495 if (global_ssl.async)
496 global.ssl_used_async_engines = nb_engines;
Grant Zhang872f9c22017-01-21 01:10:18 +0000497 return 0;
498
499fail_set_method:
500 /* release the functional reference from ENGINE_init() */
501 ENGINE_finish(engine);
502
503fail_init:
504 /* release the structural reference from ENGINE_by_id() */
505 ENGINE_free(engine);
506
507fail_get:
508 return err_code;
509}
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +0200510#endif
Grant Zhang872f9c22017-01-21 01:10:18 +0000511
Willy Tarreau5db847a2019-05-09 14:13:35 +0200512#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brun3854e012017-05-17 20:42:48 +0200513/*
514 * openssl async fd handler
515 */
Emeric Brund0e095c2019-04-19 17:15:28 +0200516void ssl_async_fd_handler(int fd)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000517{
Olivier Houchardea8dd942019-05-20 14:02:16 +0200518 struct ssl_sock_ctx *ctx = fdtab[fd].owner;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000519
Emeric Brun3854e012017-05-17 20:42:48 +0200520 /* fd is an async enfine fd, we must stop
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000521 * to poll this fd until it is requested
522 */
Emeric Brunbbc16542017-06-02 15:54:06 +0000523 fd_stop_recv(fd);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000524 fd_cant_recv(fd);
525
526 /* crypto engine is available, let's notify the associated
527 * connection that it can pursue its processing.
528 */
Olivier Houchard03abf2d2019-05-28 10:12:02 +0200529 ssl_sock_io_cb(NULL, ctx, 0);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000530}
531
Emeric Brun3854e012017-05-17 20:42:48 +0200532/*
533 * openssl async delayed SSL_free handler
534 */
Emeric Brund0e095c2019-04-19 17:15:28 +0200535void ssl_async_fd_free(int fd)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000536{
537 SSL *ssl = fdtab[fd].owner;
Emeric Brun3854e012017-05-17 20:42:48 +0200538 OSSL_ASYNC_FD all_fd[32];
539 size_t num_all_fds = 0;
540 int i;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000541
Emeric Brun3854e012017-05-17 20:42:48 +0200542 /* We suppose that the async job for a same SSL *
543 * are serialized. So if we are awake it is
544 * because the running job has just finished
545 * and we can remove all async fds safely
546 */
547 SSL_get_all_async_fds(ssl, NULL, &num_all_fds);
548 if (num_all_fds > 32) {
549 send_log(NULL, LOG_EMERG, "haproxy: openssl returns too many async fds. It seems a bug. Process may crash\n");
550 return;
551 }
552
553 SSL_get_all_async_fds(ssl, all_fd, &num_all_fds);
554 for (i=0 ; i < num_all_fds ; i++)
555 fd_remove(all_fd[i]);
556
557 /* Now we can safely call SSL_free, no more pending job in engines */
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000558 SSL_free(ssl);
Olivier Houchard2be5a4c2019-03-08 18:54:43 +0100559 _HA_ATOMIC_SUB(&sslconns, 1);
560 _HA_ATOMIC_SUB(&jobs, 1);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000561}
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000562/*
Emeric Brun3854e012017-05-17 20:42:48 +0200563 * function used to manage a returned SSL_ERROR_WANT_ASYNC
564 * and enable/disable polling for async fds
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000565 */
Olivier Houchardea8dd942019-05-20 14:02:16 +0200566static inline void ssl_async_process_fds(struct ssl_sock_ctx *ctx)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000567{
Willy Tarreaua9786b62018-01-25 07:22:13 +0100568 OSSL_ASYNC_FD add_fd[32];
Emeric Brun3854e012017-05-17 20:42:48 +0200569 OSSL_ASYNC_FD del_fd[32];
Olivier Houchardea8dd942019-05-20 14:02:16 +0200570 SSL *ssl = ctx->ssl;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000571 size_t num_add_fds = 0;
572 size_t num_del_fds = 0;
Emeric Brun3854e012017-05-17 20:42:48 +0200573 int i;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000574
575 SSL_get_changed_async_fds(ssl, NULL, &num_add_fds, NULL,
576 &num_del_fds);
Emeric Brun3854e012017-05-17 20:42:48 +0200577 if (num_add_fds > 32 || num_del_fds > 32) {
578 send_log(NULL, LOG_EMERG, "haproxy: openssl returns too many async fds. It seems a bug. Process may crash\n");
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000579 return;
580 }
581
Emeric Brun3854e012017-05-17 20:42:48 +0200582 SSL_get_changed_async_fds(ssl, add_fd, &num_add_fds, del_fd, &num_del_fds);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000583
Emeric Brun3854e012017-05-17 20:42:48 +0200584 /* We remove unused fds from the fdtab */
585 for (i=0 ; i < num_del_fds ; i++)
586 fd_remove(del_fd[i]);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000587
Emeric Brun3854e012017-05-17 20:42:48 +0200588 /* We add new fds to the fdtab */
589 for (i=0 ; i < num_add_fds ; i++) {
Olivier Houchardea8dd942019-05-20 14:02:16 +0200590 fd_insert(add_fd[i], ctx, ssl_async_fd_handler, tid_bit);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000591 }
592
Emeric Brun3854e012017-05-17 20:42:48 +0200593 num_add_fds = 0;
594 SSL_get_all_async_fds(ssl, NULL, &num_add_fds);
595 if (num_add_fds > 32) {
596 send_log(NULL, LOG_EMERG, "haproxy: openssl returns too many async fds. It seems a bug. Process may crash\n");
597 return;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000598 }
Emeric Brun3854e012017-05-17 20:42:48 +0200599
600 /* We activate the polling for all known async fds */
601 SSL_get_all_async_fds(ssl, add_fd, &num_add_fds);
Emeric Brunce9e01c2017-05-31 10:02:53 +0000602 for (i=0 ; i < num_add_fds ; i++) {
Emeric Brun3854e012017-05-17 20:42:48 +0200603 fd_want_recv(add_fd[i]);
Emeric Brunce9e01c2017-05-31 10:02:53 +0000604 /* To ensure that the fd cache won't be used
605 * We'll prefer to catch a real RD event
606 * because handling an EAGAIN on this fd will
607 * result in a context switch and also
608 * some engines uses a fd in blocking mode.
609 */
610 fd_cant_recv(add_fd[i]);
611 }
Emeric Brun3854e012017-05-17 20:42:48 +0200612
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000613}
614#endif
615
William Lallemand104a7a62019-10-14 14:14:59 +0200616#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
Emeric Brun4f3c87a2014-06-20 15:46:13 +0200617/*
618 * This function returns the number of seconds elapsed
619 * since the Epoch, 1970-01-01 00:00:00 +0000 (UTC) and the
620 * date presented un ASN1_GENERALIZEDTIME.
621 *
622 * In parsing error case, it returns -1.
623 */
624static long asn1_generalizedtime_to_epoch(ASN1_GENERALIZEDTIME *d)
625{
626 long epoch;
627 char *p, *end;
628 const unsigned short month_offset[12] = {
629 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
630 };
631 int year, month;
632
633 if (!d || (d->type != V_ASN1_GENERALIZEDTIME)) return -1;
634
635 p = (char *)d->data;
636 end = p + d->length;
637
638 if (end - p < 4) return -1;
639 year = 1000 * (p[0] - '0') + 100 * (p[1] - '0') + 10 * (p[2] - '0') + p[3] - '0';
640 p += 4;
641 if (end - p < 2) return -1;
642 month = 10 * (p[0] - '0') + p[1] - '0';
643 if (month < 1 || month > 12) return -1;
644 /* Compute the number of seconds since 1 jan 1970 and the beginning of current month
645 We consider leap years and the current month (<marsh or not) */
646 epoch = ( ((year - 1970) * 365)
647 + ((year - (month < 3)) / 4 - (year - (month < 3)) / 100 + (year - (month < 3)) / 400)
648 - ((1970 - 1) / 4 - (1970 - 1) / 100 + (1970 - 1) / 400)
649 + month_offset[month-1]
650 ) * 24 * 60 * 60;
651 p += 2;
652 if (end - p < 2) return -1;
653 /* Add the number of seconds of completed days of current month */
654 epoch += (10 * (p[0] - '0') + p[1] - '0' - 1) * 24 * 60 * 60;
655 p += 2;
656 if (end - p < 2) return -1;
657 /* Add the completed hours of the current day */
658 epoch += (10 * (p[0] - '0') + p[1] - '0') * 60 * 60;
659 p += 2;
660 if (end - p < 2) return -1;
661 /* Add the completed minutes of the current hour */
662 epoch += (10 * (p[0] - '0') + p[1] - '0') * 60;
663 p += 2;
664 if (p == end) return -1;
665 /* Test if there is available seconds */
666 if (p[0] < '0' || p[0] > '9')
667 goto nosec;
668 if (end - p < 2) return -1;
669 /* Add the seconds of the current minute */
670 epoch += 10 * (p[0] - '0') + p[1] - '0';
671 p += 2;
672 if (p == end) return -1;
673 /* Ignore seconds float part if present */
674 if (p[0] == '.') {
675 do {
676 if (++p == end) return -1;
677 } while (p[0] >= '0' && p[0] <= '9');
678 }
679
680nosec:
681 if (p[0] == 'Z') {
682 if (end - p != 1) return -1;
683 return epoch;
684 }
685 else if (p[0] == '+') {
686 if (end - p != 5) return -1;
687 /* Apply timezone offset */
Frederik Deweerdt953917a2017-10-16 07:37:31 -0700688 return epoch - ((10 * (p[1] - '0') + p[2] - '0') * 60 * 60 + (10 * (p[3] - '0') + p[4] - '0')) * 60;
Emeric Brun4f3c87a2014-06-20 15:46:13 +0200689 }
690 else if (p[0] == '-') {
691 if (end - p != 5) return -1;
692 /* Apply timezone offset */
Frederik Deweerdt953917a2017-10-16 07:37:31 -0700693 return epoch + ((10 * (p[1] - '0') + p[2] - '0') * 60 * 60 + (10 * (p[3] - '0') + p[4] - '0')) * 60;
Emeric Brun4f3c87a2014-06-20 15:46:13 +0200694 }
695
696 return -1;
697}
698
William Lallemand104a7a62019-10-14 14:14:59 +0200699/*
700 * struct alignment works here such that the key.key is the same as key_data
701 * Do not change the placement of key_data
702 */
703struct certificate_ocsp {
704 struct ebmb_node key;
705 unsigned char key_data[OCSP_MAX_CERTID_ASN1_LENGTH];
706 struct buffer response;
707 long expire;
708};
709
710struct ocsp_cbk_arg {
711 int is_single;
712 int single_kt;
713 union {
714 struct certificate_ocsp *s_ocsp;
715 /*
716 * m_ocsp will have multiple entries dependent on key type
717 * Entry 0 - DSA
718 * Entry 1 - ECDSA
719 * Entry 2 - RSA
720 */
721 struct certificate_ocsp *m_ocsp[SSL_SOCK_NUM_KEYTYPES];
722 };
723};
724
Emeric Brun1d3865b2014-06-20 15:37:32 +0200725static struct eb_root cert_ocsp_tree = EB_ROOT_UNIQUE;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200726
727/* This function starts to check if the OCSP response (in DER format) contained
728 * in chunk 'ocsp_response' is valid (else exits on error).
729 * If 'cid' is not NULL, it will be compared to the OCSP certificate ID
730 * contained in the OCSP Response and exits on error if no match.
731 * If it's a valid OCSP Response:
732 * If 'ocsp' is not NULL, the chunk is copied in the OCSP response's container
733 * pointed by 'ocsp'.
734 * If 'ocsp' is NULL, the function looks up into the OCSP response's
735 * containers tree (using as index the ASN1 form of the OCSP Certificate ID extracted
736 * from the response) and exits on error if not found. Finally, If an OCSP response is
737 * already present in the container, it will be overwritten.
738 *
739 * Note: OCSP response containing more than one OCSP Single response is not
740 * considered valid.
741 *
742 * Returns 0 on success, 1 in error case.
743 */
Willy Tarreau83061a82018-07-13 11:56:34 +0200744static int ssl_sock_load_ocsp_response(struct buffer *ocsp_response,
745 struct certificate_ocsp *ocsp,
746 OCSP_CERTID *cid, char **err)
Emeric Brun4147b2e2014-06-16 18:36:30 +0200747{
748 OCSP_RESPONSE *resp;
749 OCSP_BASICRESP *bs = NULL;
750 OCSP_SINGLERESP *sr;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200751 OCSP_CERTID *id;
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200752 unsigned char *p = (unsigned char *) ocsp_response->area;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200753 int rc , count_sr;
Emeric Brun13a6b482014-06-20 15:44:34 +0200754 ASN1_GENERALIZEDTIME *revtime, *thisupd, *nextupd = NULL;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200755 int reason;
756 int ret = 1;
757
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200758 resp = d2i_OCSP_RESPONSE(NULL, (const unsigned char **)&p,
759 ocsp_response->data);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200760 if (!resp) {
761 memprintf(err, "Unable to parse OCSP response");
762 goto out;
763 }
764
765 rc = OCSP_response_status(resp);
766 if (rc != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
767 memprintf(err, "OCSP response status not successful");
768 goto out;
769 }
770
771 bs = OCSP_response_get1_basic(resp);
772 if (!bs) {
773 memprintf(err, "Failed to get basic response from OCSP Response");
774 goto out;
775 }
776
777 count_sr = OCSP_resp_count(bs);
778 if (count_sr > 1) {
779 memprintf(err, "OCSP response ignored because contains multiple single responses (%d)", count_sr);
780 goto out;
781 }
782
783 sr = OCSP_resp_get0(bs, 0);
784 if (!sr) {
785 memprintf(err, "Failed to get OCSP single response");
786 goto out;
787 }
788
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200789 id = (OCSP_CERTID*)OCSP_SINGLERESP_get0_id(sr);
790
Emeric Brun4147b2e2014-06-16 18:36:30 +0200791 rc = OCSP_single_get0_status(sr, &reason, &revtime, &thisupd, &nextupd);
Emmanuel Hocdetef607052017-10-24 14:57:16 +0200792 if (rc != V_OCSP_CERTSTATUS_GOOD && rc != V_OCSP_CERTSTATUS_REVOKED) {
Emmanuel Hocdet872085c2017-10-10 15:18:52 +0200793 memprintf(err, "OCSP single response: certificate status is unknown");
Emeric Brun4147b2e2014-06-16 18:36:30 +0200794 goto out;
795 }
796
Emeric Brun13a6b482014-06-20 15:44:34 +0200797 if (!nextupd) {
798 memprintf(err, "OCSP single response: missing nextupdate");
799 goto out;
800 }
801
Emeric Brunc8b27b62014-06-19 14:16:17 +0200802 rc = OCSP_check_validity(thisupd, nextupd, OCSP_MAX_RESPONSE_TIME_SKEW, -1);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200803 if (!rc) {
804 memprintf(err, "OCSP single response: no longer valid.");
805 goto out;
806 }
807
808 if (cid) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200809 if (OCSP_id_cmp(id, cid)) {
Emeric Brun4147b2e2014-06-16 18:36:30 +0200810 memprintf(err, "OCSP single response: Certificate ID does not match certificate and issuer");
811 goto out;
812 }
813 }
814
815 if (!ocsp) {
816 unsigned char key[OCSP_MAX_CERTID_ASN1_LENGTH];
817 unsigned char *p;
818
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200819 rc = i2d_OCSP_CERTID(id, NULL);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200820 if (!rc) {
821 memprintf(err, "OCSP single response: Unable to encode Certificate ID");
822 goto out;
823 }
824
825 if (rc > OCSP_MAX_CERTID_ASN1_LENGTH) {
826 memprintf(err, "OCSP single response: Certificate ID too long");
827 goto out;
828 }
829
830 p = key;
831 memset(key, 0, OCSP_MAX_CERTID_ASN1_LENGTH);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200832 i2d_OCSP_CERTID(id, &p);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200833 ocsp = (struct certificate_ocsp *)ebmb_lookup(&cert_ocsp_tree, key, OCSP_MAX_CERTID_ASN1_LENGTH);
834 if (!ocsp) {
835 memprintf(err, "OCSP single response: Certificate ID does not match any certificate or issuer");
836 goto out;
837 }
838 }
839
840 /* According to comments on "chunk_dup", the
841 previous chunk buffer will be freed */
842 if (!chunk_dup(&ocsp->response, ocsp_response)) {
843 memprintf(err, "OCSP response: Memory allocation error");
844 goto out;
845 }
846
Emeric Brun4f3c87a2014-06-20 15:46:13 +0200847 ocsp->expire = asn1_generalizedtime_to_epoch(nextupd) - OCSP_MAX_RESPONSE_TIME_SKEW;
848
Emeric Brun4147b2e2014-06-16 18:36:30 +0200849 ret = 0;
850out:
Janusz Dziemidowicz8d710492017-03-08 16:59:41 +0100851 ERR_clear_error();
852
Emeric Brun4147b2e2014-06-16 18:36:30 +0200853 if (bs)
854 OCSP_BASICRESP_free(bs);
855
856 if (resp)
857 OCSP_RESPONSE_free(resp);
858
859 return ret;
860}
861/*
862 * External function use to update the OCSP response in the OCSP response's
863 * containers tree. The chunk 'ocsp_response' must contain the OCSP response
864 * to update in DER format.
865 *
866 * Returns 0 on success, 1 in error case.
867 */
Willy Tarreau83061a82018-07-13 11:56:34 +0200868int ssl_sock_update_ocsp_response(struct buffer *ocsp_response, char **err)
Emeric Brun4147b2e2014-06-16 18:36:30 +0200869{
870 return ssl_sock_load_ocsp_response(ocsp_response, NULL, NULL, err);
871}
872
William Lallemand4a660132019-10-14 14:51:41 +0200873#endif
874
875#if ((defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP) || defined OPENSSL_IS_BORINGSSL)
Emeric Brun4147b2e2014-06-16 18:36:30 +0200876/*
877 * This function load the OCSP Resonse in DER format contained in file at
William Lallemand246c0242019-10-11 08:59:13 +0200878 * path 'ocsp_path'
Emeric Brun4147b2e2014-06-16 18:36:30 +0200879 *
880 * Returns 0 on success, 1 in error case.
881 */
William Lallemand246c0242019-10-11 08:59:13 +0200882static int ssl_sock_load_ocsp_response_from_file(const char *ocsp_path, struct buffer **ocsp_response, char **err)
Emeric Brun4147b2e2014-06-16 18:36:30 +0200883{
884 int fd = -1;
885 int r = 0;
886 int ret = 1;
887
888 fd = open(ocsp_path, O_RDONLY);
889 if (fd == -1) {
890 memprintf(err, "Error opening OCSP response file");
891 goto end;
892 }
893
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200894 trash.data = 0;
895 while (trash.data < trash.size) {
896 r = read(fd, trash.area + trash.data, trash.size - trash.data);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200897 if (r < 0) {
898 if (errno == EINTR)
899 continue;
900
901 memprintf(err, "Error reading OCSP response from file");
902 goto end;
903 }
904 else if (r == 0) {
905 break;
906 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200907 trash.data += r;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200908 }
909
William Lallemand246c0242019-10-11 08:59:13 +0200910 *ocsp_response = calloc(1, sizeof(**ocsp_response));
911 if (!chunk_dup(*ocsp_response, &trash)) {
912 free(*ocsp_response);
913 *ocsp_response = NULL;
914 goto end;
915 }
916
Emeric Brun4147b2e2014-06-16 18:36:30 +0200917 close(fd);
918 fd = -1;
919
William Lallemande0f48ae2019-10-15 13:44:57 +0200920 ret = 0;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200921end:
922 if (fd != -1)
923 close(fd);
924
925 return ret;
926}
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100927#endif
Emeric Brun4147b2e2014-06-16 18:36:30 +0200928
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100929#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
930static int ssl_tlsext_ticket_key_cb(SSL *s, unsigned char key_name[16], unsigned char *iv, EVP_CIPHER_CTX *ectx, HMAC_CTX *hctx, int enc)
931{
Christopher Faulet16f45c82018-02-16 11:23:49 +0100932 struct tls_keys_ref *ref;
Emeric Brun9e754772019-01-10 17:51:55 +0100933 union tls_sess_key *keys;
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100934 struct connection *conn;
935 int head;
936 int i;
Christopher Faulet16f45c82018-02-16 11:23:49 +0100937 int ret = -1; /* error by default */
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100938
Thierry FOURNIER28962c92018-06-17 21:37:05 +0200939 conn = SSL_get_ex_data(s, ssl_app_data_index);
Willy Tarreau07d94e42018-09-20 10:57:52 +0200940 ref = __objt_listener(conn->target)->bind_conf->keys_ref;
Christopher Faulet16f45c82018-02-16 11:23:49 +0100941 HA_RWLOCK_RDLOCK(TLSKEYS_REF_LOCK, &ref->lock);
942
943 keys = ref->tlskeys;
944 head = ref->tls_ticket_enc_index;
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100945
946 if (enc) {
947 memcpy(key_name, keys[head].name, 16);
948
949 if(!RAND_pseudo_bytes(iv, EVP_MAX_IV_LENGTH))
Christopher Faulet16f45c82018-02-16 11:23:49 +0100950 goto end;
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100951
Emeric Brun9e754772019-01-10 17:51:55 +0100952 if (ref->key_size_bits == 128) {
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100953
Emeric Brun9e754772019-01-10 17:51:55 +0100954 if(!EVP_EncryptInit_ex(ectx, EVP_aes_128_cbc(), NULL, keys[head].key_128.aes_key, iv))
955 goto end;
956
Willy Tarreau9356dac2019-05-10 09:22:53 +0200957 HMAC_Init_ex(hctx, keys[head].key_128.hmac_key, 16, TLS_TICKET_HASH_FUNCT(), NULL);
Emeric Brun9e754772019-01-10 17:51:55 +0100958 ret = 1;
959 }
960 else if (ref->key_size_bits == 256 ) {
961
962 if(!EVP_EncryptInit_ex(ectx, EVP_aes_256_cbc(), NULL, keys[head].key_256.aes_key, iv))
963 goto end;
964
Willy Tarreau9356dac2019-05-10 09:22:53 +0200965 HMAC_Init_ex(hctx, keys[head].key_256.hmac_key, 32, TLS_TICKET_HASH_FUNCT(), NULL);
Emeric Brun9e754772019-01-10 17:51:55 +0100966 ret = 1;
967 }
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100968 } else {
969 for (i = 0; i < TLS_TICKETS_NO; i++) {
970 if (!memcmp(key_name, keys[(head + i) % TLS_TICKETS_NO].name, 16))
971 goto found;
972 }
Christopher Faulet16f45c82018-02-16 11:23:49 +0100973 ret = 0;
974 goto end;
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100975
Christopher Faulet16f45c82018-02-16 11:23:49 +0100976 found:
Emeric Brun9e754772019-01-10 17:51:55 +0100977 if (ref->key_size_bits == 128) {
Willy Tarreau9356dac2019-05-10 09:22:53 +0200978 HMAC_Init_ex(hctx, keys[(head + i) % TLS_TICKETS_NO].key_128.hmac_key, 16, TLS_TICKET_HASH_FUNCT(), NULL);
Emeric Brun9e754772019-01-10 17:51:55 +0100979 if(!EVP_DecryptInit_ex(ectx, EVP_aes_128_cbc(), NULL, keys[(head + i) % TLS_TICKETS_NO].key_128.aes_key, iv))
980 goto end;
981 /* 2 for key renewal, 1 if current key is still valid */
982 ret = i ? 2 : 1;
983 }
984 else if (ref->key_size_bits == 256) {
Willy Tarreau9356dac2019-05-10 09:22:53 +0200985 HMAC_Init_ex(hctx, keys[(head + i) % TLS_TICKETS_NO].key_256.hmac_key, 32, TLS_TICKET_HASH_FUNCT(), NULL);
Emeric Brun9e754772019-01-10 17:51:55 +0100986 if(!EVP_DecryptInit_ex(ectx, EVP_aes_256_cbc(), NULL, keys[(head + i) % TLS_TICKETS_NO].key_256.aes_key, iv))
987 goto end;
988 /* 2 for key renewal, 1 if current key is still valid */
989 ret = i ? 2 : 1;
990 }
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100991 }
Emeric Brun9e754772019-01-10 17:51:55 +0100992
Christopher Faulet16f45c82018-02-16 11:23:49 +0100993 end:
994 HA_RWLOCK_RDUNLOCK(TLSKEYS_REF_LOCK, &ref->lock);
995 return ret;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200996}
997
998struct tls_keys_ref *tlskeys_ref_lookup(const char *filename)
999{
1000 struct tls_keys_ref *ref;
1001
1002 list_for_each_entry(ref, &tlskeys_reference, list)
1003 if (ref->filename && strcmp(filename, ref->filename) == 0)
1004 return ref;
1005 return NULL;
1006}
1007
1008struct tls_keys_ref *tlskeys_ref_lookupid(int unique_id)
1009{
1010 struct tls_keys_ref *ref;
1011
1012 list_for_each_entry(ref, &tlskeys_reference, list)
1013 if (ref->unique_id == unique_id)
1014 return ref;
1015 return NULL;
1016}
1017
Emeric Brun9e754772019-01-10 17:51:55 +01001018/* Update the key into ref: if keysize doesnt
1019 * match existing ones, this function returns -1
1020 * else it returns 0 on success.
1021 */
1022int ssl_sock_update_tlskey_ref(struct tls_keys_ref *ref,
Willy Tarreau83061a82018-07-13 11:56:34 +02001023 struct buffer *tlskey)
Christopher Faulet16f45c82018-02-16 11:23:49 +01001024{
Emeric Brun9e754772019-01-10 17:51:55 +01001025 if (ref->key_size_bits == 128) {
1026 if (tlskey->data != sizeof(struct tls_sess_key_128))
1027 return -1;
1028 }
1029 else if (ref->key_size_bits == 256) {
1030 if (tlskey->data != sizeof(struct tls_sess_key_256))
1031 return -1;
1032 }
1033 else
1034 return -1;
1035
Christopher Faulet16f45c82018-02-16 11:23:49 +01001036 HA_RWLOCK_WRLOCK(TLSKEYS_REF_LOCK, &ref->lock);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001037 memcpy((char *) (ref->tlskeys + ((ref->tls_ticket_enc_index + 2) % TLS_TICKETS_NO)),
1038 tlskey->area, tlskey->data);
Christopher Faulet16f45c82018-02-16 11:23:49 +01001039 ref->tls_ticket_enc_index = (ref->tls_ticket_enc_index + 1) % TLS_TICKETS_NO;
1040 HA_RWLOCK_WRUNLOCK(TLSKEYS_REF_LOCK, &ref->lock);
Emeric Brun9e754772019-01-10 17:51:55 +01001041
1042 return 0;
Christopher Faulet16f45c82018-02-16 11:23:49 +01001043}
1044
Willy Tarreau83061a82018-07-13 11:56:34 +02001045int ssl_sock_update_tlskey(char *filename, struct buffer *tlskey, char **err)
Christopher Faulet16f45c82018-02-16 11:23:49 +01001046{
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02001047 struct tls_keys_ref *ref = tlskeys_ref_lookup(filename);
1048
1049 if(!ref) {
1050 memprintf(err, "Unable to locate the referenced filename: %s", filename);
1051 return 1;
1052 }
Emeric Brun9e754772019-01-10 17:51:55 +01001053 if (ssl_sock_update_tlskey_ref(ref, tlskey) < 0) {
1054 memprintf(err, "Invalid key size");
1055 return 1;
1056 }
1057
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02001058 return 0;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01001059}
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02001060
1061/* This function finalize the configuration parsing. Its set all the
Willy Tarreaud1c57502016-12-22 22:46:15 +01001062 * automatic ids. It's called just after the basic checks. It returns
1063 * 0 on success otherwise ERR_*.
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02001064 */
Willy Tarreaud1c57502016-12-22 22:46:15 +01001065static int tlskeys_finalize_config(void)
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02001066{
1067 int i = 0;
1068 struct tls_keys_ref *ref, *ref2, *ref3;
1069 struct list tkr = LIST_HEAD_INIT(tkr);
1070
1071 list_for_each_entry(ref, &tlskeys_reference, list) {
1072 if (ref->unique_id == -1) {
1073 /* Look for the first free id. */
1074 while (1) {
1075 list_for_each_entry(ref2, &tlskeys_reference, list) {
1076 if (ref2->unique_id == i) {
1077 i++;
1078 break;
1079 }
1080 }
1081 if (&ref2->list == &tlskeys_reference)
1082 break;
1083 }
1084
1085 /* Uses the unique id and increment it for the next entry. */
1086 ref->unique_id = i;
1087 i++;
1088 }
1089 }
1090
1091 /* This sort the reference list by id. */
1092 list_for_each_entry_safe(ref, ref2, &tlskeys_reference, list) {
1093 LIST_DEL(&ref->list);
1094 list_for_each_entry(ref3, &tkr, list) {
1095 if (ref->unique_id < ref3->unique_id) {
1096 LIST_ADDQ(&ref3->list, &ref->list);
1097 break;
1098 }
1099 }
1100 if (&ref3->list == &tkr)
1101 LIST_ADDQ(&tkr, &ref->list);
1102 }
1103
1104 /* swap root */
1105 LIST_ADD(&tkr, &tlskeys_reference);
1106 LIST_DEL(&tkr);
Willy Tarreaud1c57502016-12-22 22:46:15 +01001107 return 0;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02001108}
Nenad Merdanovic05552d42015-02-27 19:56:49 +01001109#endif /* SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB */
1110
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01001111#ifndef OPENSSL_NO_OCSP
yanbzhube2774d2015-12-10 15:07:30 -05001112int ssl_sock_get_ocsp_arg_kt_index(int evp_keytype)
1113{
1114 switch (evp_keytype) {
1115 case EVP_PKEY_RSA:
1116 return 2;
1117 case EVP_PKEY_DSA:
1118 return 0;
1119 case EVP_PKEY_EC:
1120 return 1;
1121 }
1122
1123 return -1;
1124}
1125
Emeric Brun4147b2e2014-06-16 18:36:30 +02001126/*
1127 * Callback used to set OCSP status extension content in server hello.
1128 */
1129int ssl_sock_ocsp_stapling_cbk(SSL *ssl, void *arg)
1130{
yanbzhube2774d2015-12-10 15:07:30 -05001131 struct certificate_ocsp *ocsp;
1132 struct ocsp_cbk_arg *ocsp_arg;
1133 char *ssl_buf;
1134 EVP_PKEY *ssl_pkey;
1135 int key_type;
1136 int index;
1137
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02001138 ocsp_arg = arg;
yanbzhube2774d2015-12-10 15:07:30 -05001139
1140 ssl_pkey = SSL_get_privatekey(ssl);
1141 if (!ssl_pkey)
1142 return SSL_TLSEXT_ERR_NOACK;
1143
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001144 key_type = EVP_PKEY_base_id(ssl_pkey);
yanbzhube2774d2015-12-10 15:07:30 -05001145
1146 if (ocsp_arg->is_single && ocsp_arg->single_kt == key_type)
1147 ocsp = ocsp_arg->s_ocsp;
1148 else {
1149 /* For multiple certs per context, we have to find the correct OCSP response based on
1150 * the certificate type
1151 */
1152 index = ssl_sock_get_ocsp_arg_kt_index(key_type);
1153
1154 if (index < 0)
1155 return SSL_TLSEXT_ERR_NOACK;
1156
1157 ocsp = ocsp_arg->m_ocsp[index];
1158
1159 }
Emeric Brun4147b2e2014-06-16 18:36:30 +02001160
1161 if (!ocsp ||
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001162 !ocsp->response.area ||
1163 !ocsp->response.data ||
Emeric Brun4f3c87a2014-06-20 15:46:13 +02001164 (ocsp->expire < now.tv_sec))
Emeric Brun4147b2e2014-06-16 18:36:30 +02001165 return SSL_TLSEXT_ERR_NOACK;
1166
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001167 ssl_buf = OPENSSL_malloc(ocsp->response.data);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001168 if (!ssl_buf)
1169 return SSL_TLSEXT_ERR_NOACK;
1170
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001171 memcpy(ssl_buf, ocsp->response.area, ocsp->response.data);
1172 SSL_set_tlsext_status_ocsp_resp(ssl, ssl_buf, ocsp->response.data);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001173
1174 return SSL_TLSEXT_ERR_OK;
1175}
1176
William Lallemand4a660132019-10-14 14:51:41 +02001177#endif
1178
1179#if ((defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP) || defined OPENSSL_IS_BORINGSSL)
Emeric Brun4147b2e2014-06-16 18:36:30 +02001180/*
1181 * This function enables the handling of OCSP status extension on 'ctx' if a
William Lallemand246c0242019-10-11 08:59:13 +02001182 * ocsp_response buffer was found in the cert_key_and_chain. To enable OCSP
1183 * status extension, the issuer's certificate is mandatory. It should be
1184 * present in ckch->ocsp_issuer.
Emeric Brun4147b2e2014-06-16 18:36:30 +02001185 *
William Lallemand246c0242019-10-11 08:59:13 +02001186 * In addition, the ckch->ocsp_reponse buffer is loaded as a DER format of an
1187 * OCSP response. If file is empty or content is not a valid OCSP response,
1188 * OCSP status extension is enabled but OCSP response is ignored (a warning is
1189 * displayed).
Emeric Brun4147b2e2014-06-16 18:36:30 +02001190 *
1191 * Returns 1 if no ".ocsp" file found, 0 if OCSP status extension is
Joseph Herlant017b3da2018-11-15 09:07:59 -08001192 * successfully enabled, or -1 in other error case.
Emeric Brun4147b2e2014-06-16 18:36:30 +02001193 */
William Lallemand4a660132019-10-14 14:51:41 +02001194#ifndef OPENSSL_IS_BORINGSSL
William Lallemand246c0242019-10-11 08:59:13 +02001195static int ssl_sock_load_ocsp(SSL_CTX *ctx, const struct cert_key_and_chain *ckch)
Emeric Brun4147b2e2014-06-16 18:36:30 +02001196{
William Lallemand246c0242019-10-11 08:59:13 +02001197 X509 *x = NULL, *issuer = NULL;
Emeric Brun4147b2e2014-06-16 18:36:30 +02001198 OCSP_CERTID *cid = NULL;
Emeric Brun4147b2e2014-06-16 18:36:30 +02001199 char ocsp_path[MAXPATHLEN+1];
1200 int i, ret = -1;
Emeric Brun4147b2e2014-06-16 18:36:30 +02001201 struct certificate_ocsp *ocsp = NULL, *iocsp;
1202 char *warn = NULL;
1203 unsigned char *p;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001204 void (*callback) (void);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001205
Emeric Brun4147b2e2014-06-16 18:36:30 +02001206
William Lallemand246c0242019-10-11 08:59:13 +02001207 x = ckch->cert;
Emeric Brun4147b2e2014-06-16 18:36:30 +02001208 if (!x)
1209 goto out;
1210
William Lallemand246c0242019-10-11 08:59:13 +02001211 issuer = ckch->ocsp_issuer;
1212 if (!issuer)
1213 goto out;
Emeric Brun4147b2e2014-06-16 18:36:30 +02001214
1215 cid = OCSP_cert_to_id(0, x, issuer);
1216 if (!cid)
1217 goto out;
1218
1219 i = i2d_OCSP_CERTID(cid, NULL);
1220 if (!i || (i > OCSP_MAX_CERTID_ASN1_LENGTH))
1221 goto out;
1222
Vincent Bernat02779b62016-04-03 13:48:43 +02001223 ocsp = calloc(1, sizeof(*ocsp));
Emeric Brun4147b2e2014-06-16 18:36:30 +02001224 if (!ocsp)
1225 goto out;
1226
1227 p = ocsp->key_data;
1228 i2d_OCSP_CERTID(cid, &p);
1229
1230 iocsp = (struct certificate_ocsp *)ebmb_insert(&cert_ocsp_tree, &ocsp->key, OCSP_MAX_CERTID_ASN1_LENGTH);
1231 if (iocsp == ocsp)
1232 ocsp = NULL;
1233
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001234#ifndef SSL_CTX_get_tlsext_status_cb
1235# define SSL_CTX_get_tlsext_status_cb(ctx, cb) \
1236 *cb = (void (*) (void))ctx->tlsext_status_cb;
1237#endif
1238 SSL_CTX_get_tlsext_status_cb(ctx, &callback);
1239
1240 if (!callback) {
Vincent Bernat02779b62016-04-03 13:48:43 +02001241 struct ocsp_cbk_arg *cb_arg = calloc(1, sizeof(*cb_arg));
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001242 EVP_PKEY *pkey;
yanbzhube2774d2015-12-10 15:07:30 -05001243
1244 cb_arg->is_single = 1;
1245 cb_arg->s_ocsp = iocsp;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001246
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001247 pkey = X509_get_pubkey(x);
1248 cb_arg->single_kt = EVP_PKEY_base_id(pkey);
1249 EVP_PKEY_free(pkey);
yanbzhube2774d2015-12-10 15:07:30 -05001250
1251 SSL_CTX_set_tlsext_status_cb(ctx, ssl_sock_ocsp_stapling_cbk);
1252 SSL_CTX_set_tlsext_status_arg(ctx, cb_arg);
1253 } else {
1254 /*
1255 * If the ctx has a status CB, then we have previously set an OCSP staple for this ctx
1256 * Update that cb_arg with the new cert's staple
1257 */
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001258 struct ocsp_cbk_arg *cb_arg;
yanbzhube2774d2015-12-10 15:07:30 -05001259 struct certificate_ocsp *tmp_ocsp;
1260 int index;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001261 int key_type;
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001262 EVP_PKEY *pkey;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001263
1264#ifdef SSL_CTX_get_tlsext_status_arg
1265 SSL_CTX_ctrl(ctx, SSL_CTRL_GET_TLSEXT_STATUS_REQ_CB_ARG, 0, &cb_arg);
1266#else
1267 cb_arg = ctx->tlsext_status_arg;
1268#endif
yanbzhube2774d2015-12-10 15:07:30 -05001269
1270 /*
1271 * The following few lines will convert cb_arg from a single ocsp to multi ocsp
1272 * the order of operations below matter, take care when changing it
1273 */
1274 tmp_ocsp = cb_arg->s_ocsp;
1275 index = ssl_sock_get_ocsp_arg_kt_index(cb_arg->single_kt);
1276 cb_arg->s_ocsp = NULL;
1277 cb_arg->m_ocsp[index] = tmp_ocsp;
1278 cb_arg->is_single = 0;
1279 cb_arg->single_kt = 0;
1280
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001281 pkey = X509_get_pubkey(x);
1282 key_type = EVP_PKEY_base_id(pkey);
1283 EVP_PKEY_free(pkey);
1284
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001285 index = ssl_sock_get_ocsp_arg_kt_index(key_type);
yanbzhube2774d2015-12-10 15:07:30 -05001286 if (index >= 0 && !cb_arg->m_ocsp[index])
1287 cb_arg->m_ocsp[index] = iocsp;
1288
1289 }
Emeric Brun4147b2e2014-06-16 18:36:30 +02001290
1291 ret = 0;
1292
1293 warn = NULL;
William Lallemand246c0242019-10-11 08:59:13 +02001294 if (ssl_sock_load_ocsp_response(ckch->ocsp_response, ocsp, cid, &warn)) {
Emeric Brun4147b2e2014-06-16 18:36:30 +02001295 memprintf(&warn, "Loading '%s': %s. Content will be ignored", ocsp_path, warn ? warn : "failure");
Christopher Faulet767a84b2017-11-24 16:50:31 +01001296 ha_warning("%s.\n", warn);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001297 }
1298
1299out:
Emeric Brun4147b2e2014-06-16 18:36:30 +02001300 if (cid)
1301 OCSP_CERTID_free(cid);
1302
1303 if (ocsp)
1304 free(ocsp);
1305
1306 if (warn)
1307 free(warn);
1308
Emeric Brun4147b2e2014-06-16 18:36:30 +02001309 return ret;
1310}
William Lallemand4a660132019-10-14 14:51:41 +02001311#else /* OPENSSL_IS_BORINGSSL */
1312static int ssl_sock_load_ocsp(SSL_CTX *ctx, const struct cert_key_and_chain *ckch)
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02001313{
William Lallemand4a660132019-10-14 14:51:41 +02001314 return SSL_CTX_set_ocsp_response(ctx, (const uint8_t *)ckch->ocsp_response->area, ckch->ocsp_response->data);
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02001315}
1316#endif
1317
William Lallemand4a660132019-10-14 14:51:41 +02001318#endif
1319
1320
Willy Tarreau5db847a2019-05-09 14:13:35 +02001321#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001322
1323#define CT_EXTENSION_TYPE 18
1324
1325static int sctl_ex_index = -1;
1326
1327/*
1328 * Try to parse Signed Certificate Timestamp List structure. This function
1329 * makes only basic test if the data seems like SCTL. No signature validation
1330 * is performed.
1331 */
Willy Tarreau83061a82018-07-13 11:56:34 +02001332static int ssl_sock_parse_sctl(struct buffer *sctl)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001333{
1334 int ret = 1;
1335 int len, pos, sct_len;
1336 unsigned char *data;
1337
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001338 if (sctl->data < 2)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001339 goto out;
1340
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001341 data = (unsigned char *) sctl->area;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001342 len = (data[0] << 8) | data[1];
1343
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001344 if (len + 2 != sctl->data)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001345 goto out;
1346
1347 data = data + 2;
1348 pos = 0;
1349 while (pos < len) {
1350 if (len - pos < 2)
1351 goto out;
1352
1353 sct_len = (data[pos] << 8) | data[pos + 1];
1354 if (pos + sct_len + 2 > len)
1355 goto out;
1356
1357 pos += sct_len + 2;
1358 }
1359
1360 ret = 0;
1361
1362out:
1363 return ret;
1364}
1365
Willy Tarreau83061a82018-07-13 11:56:34 +02001366static int ssl_sock_load_sctl_from_file(const char *sctl_path,
1367 struct buffer **sctl)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001368{
1369 int fd = -1;
1370 int r = 0;
1371 int ret = 1;
1372
1373 *sctl = NULL;
1374
1375 fd = open(sctl_path, O_RDONLY);
1376 if (fd == -1)
1377 goto end;
1378
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001379 trash.data = 0;
1380 while (trash.data < trash.size) {
1381 r = read(fd, trash.area + trash.data, trash.size - trash.data);
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001382 if (r < 0) {
1383 if (errno == EINTR)
1384 continue;
1385
1386 goto end;
1387 }
1388 else if (r == 0) {
1389 break;
1390 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001391 trash.data += r;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001392 }
1393
1394 ret = ssl_sock_parse_sctl(&trash);
1395 if (ret)
1396 goto end;
1397
Vincent Bernat02779b62016-04-03 13:48:43 +02001398 *sctl = calloc(1, sizeof(**sctl));
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001399 if (!chunk_dup(*sctl, &trash)) {
1400 free(*sctl);
1401 *sctl = NULL;
1402 goto end;
1403 }
1404
1405end:
1406 if (fd != -1)
1407 close(fd);
1408
1409 return ret;
1410}
1411
1412int ssl_sock_sctl_add_cbk(SSL *ssl, unsigned ext_type, const unsigned char **out, size_t *outlen, int *al, void *add_arg)
1413{
Willy Tarreau83061a82018-07-13 11:56:34 +02001414 struct buffer *sctl = add_arg;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001415
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001416 *out = (unsigned char *) sctl->area;
1417 *outlen = sctl->data;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001418
1419 return 1;
1420}
1421
1422int ssl_sock_sctl_parse_cbk(SSL *s, unsigned int ext_type, const unsigned char *in, size_t inlen, int *al, void *parse_arg)
1423{
1424 return 1;
1425}
1426
William Lallemanda17f4112019-10-10 15:16:44 +02001427static int ssl_sock_load_sctl(SSL_CTX *ctx, struct buffer *sctl)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001428{
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001429 int ret = -1;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001430
William Lallemanda17f4112019-10-10 15:16:44 +02001431 if (!SSL_CTX_add_server_custom_ext(ctx, CT_EXTENSION_TYPE, ssl_sock_sctl_add_cbk, NULL, sctl, ssl_sock_sctl_parse_cbk, NULL))
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001432 goto out;
1433
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001434 SSL_CTX_set_ex_data(ctx, sctl_ex_index, sctl);
1435
1436 ret = 0;
1437
1438out:
1439 return ret;
1440}
1441
1442#endif
1443
Emeric Brune1f38db2012-09-03 20:36:47 +02001444void ssl_sock_infocbk(const SSL *ssl, int where, int ret)
1445{
Thierry FOURNIER28962c92018-06-17 21:37:05 +02001446 struct connection *conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001447 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
Emeric Brund8b2bb52014-01-28 15:43:53 +01001448 BIO *write_bio;
Willy Tarreau622317d2015-02-27 16:36:16 +01001449 (void)ret; /* shut gcc stupid warning */
Emeric Brune1f38db2012-09-03 20:36:47 +02001450
Dirkjan Bussink526894f2019-01-21 09:35:03 -08001451#ifndef SSL_OP_NO_RENEGOTIATION
1452 /* Please note that BoringSSL defines this macro to zero so don't
1453 * change this to #if and do not assign a default value to this macro!
1454 */
Emeric Brune1f38db2012-09-03 20:36:47 +02001455 if (where & SSL_CB_HANDSHAKE_START) {
1456 /* Disable renegotiation (CVE-2009-3555) */
Olivier Houchard90084a12017-11-23 18:21:29 +01001457 if ((conn->flags & (CO_FL_CONNECTED | CO_FL_EARLY_SSL_HS | CO_FL_EARLY_DATA)) == CO_FL_CONNECTED) {
Emeric Brune1f38db2012-09-03 20:36:47 +02001458 conn->flags |= CO_FL_ERROR;
Willy Tarreau20879a02012-12-03 16:32:10 +01001459 conn->err_code = CO_ER_SSL_RENEG;
1460 }
Emeric Brune1f38db2012-09-03 20:36:47 +02001461 }
Dirkjan Bussink526894f2019-01-21 09:35:03 -08001462#endif
Emeric Brund8b2bb52014-01-28 15:43:53 +01001463
1464 if ((where & SSL_CB_ACCEPT_LOOP) == SSL_CB_ACCEPT_LOOP) {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001465 if (!(ctx->xprt_st & SSL_SOCK_ST_FL_16K_WBFSIZE)) {
Emeric Brund8b2bb52014-01-28 15:43:53 +01001466 /* Long certificate chains optimz
1467 If write and read bios are differents, we
1468 consider that the buffering was activated,
1469 so we rise the output buffer size from 4k
1470 to 16k */
1471 write_bio = SSL_get_wbio(ssl);
1472 if (write_bio != SSL_get_rbio(ssl)) {
1473 BIO_set_write_buffer_size(write_bio, 16384);
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001474 ctx->xprt_st |= SSL_SOCK_ST_FL_16K_WBFSIZE;
Emeric Brund8b2bb52014-01-28 15:43:53 +01001475 }
1476 }
1477 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02001478}
1479
Emeric Brune64aef12012-09-21 13:15:06 +02001480/* Callback is called for each certificate of the chain during a verify
1481 ok is set to 1 if preverify detect no error on current certificate.
1482 Returns 0 to break the handshake, 1 otherwise. */
Evan Broderbe554312013-06-27 00:05:25 -07001483int ssl_sock_bind_verifycbk(int ok, X509_STORE_CTX *x_store)
Emeric Brune64aef12012-09-21 13:15:06 +02001484{
1485 SSL *ssl;
1486 struct connection *conn;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001487 struct ssl_sock_ctx *ctx;
Emeric Brun81c00f02012-09-21 14:31:21 +02001488 int err, depth;
Emeric Brune64aef12012-09-21 13:15:06 +02001489
1490 ssl = X509_STORE_CTX_get_ex_data(x_store, SSL_get_ex_data_X509_STORE_CTX_idx());
Thierry FOURNIER28962c92018-06-17 21:37:05 +02001491 conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Emeric Brune64aef12012-09-21 13:15:06 +02001492
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001493 ctx = conn->xprt_ctx;
1494
1495 ctx->xprt_st |= SSL_SOCK_ST_FL_VERIFY_DONE;
Emeric Brune64aef12012-09-21 13:15:06 +02001496
Emeric Brun81c00f02012-09-21 14:31:21 +02001497 if (ok) /* no errors */
1498 return ok;
1499
1500 depth = X509_STORE_CTX_get_error_depth(x_store);
1501 err = X509_STORE_CTX_get_error(x_store);
1502
1503 /* check if CA error needs to be ignored */
1504 if (depth > 0) {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001505 if (!SSL_SOCK_ST_TO_CA_ERROR(ctx->xprt_st)) {
1506 ctx->xprt_st |= SSL_SOCK_CA_ERROR_TO_ST(err);
1507 ctx->xprt_st |= SSL_SOCK_CAEDEPTH_TO_ST(depth);
Emeric Brunf282a812012-09-21 15:27:54 +02001508 }
1509
Willy Tarreau07d94e42018-09-20 10:57:52 +02001510 if (__objt_listener(conn->target)->bind_conf->ca_ignerr & (1ULL << err)) {
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02001511 ssl_sock_dump_errors(conn);
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001512 ERR_clear_error();
Emeric Brun81c00f02012-09-21 14:31:21 +02001513 return 1;
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001514 }
Emeric Brun81c00f02012-09-21 14:31:21 +02001515
Willy Tarreau20879a02012-12-03 16:32:10 +01001516 conn->err_code = CO_ER_SSL_CA_FAIL;
Emeric Brun81c00f02012-09-21 14:31:21 +02001517 return 0;
1518 }
1519
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001520 if (!SSL_SOCK_ST_TO_CRTERROR(ctx->xprt_st))
1521 ctx->xprt_st |= SSL_SOCK_CRTERROR_TO_ST(err);
Emeric Brunf282a812012-09-21 15:27:54 +02001522
Emeric Brun81c00f02012-09-21 14:31:21 +02001523 /* check if certificate error needs to be ignored */
Willy Tarreau07d94e42018-09-20 10:57:52 +02001524 if (__objt_listener(conn->target)->bind_conf->crt_ignerr & (1ULL << err)) {
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02001525 ssl_sock_dump_errors(conn);
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001526 ERR_clear_error();
Emeric Brun81c00f02012-09-21 14:31:21 +02001527 return 1;
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001528 }
Emeric Brun81c00f02012-09-21 14:31:21 +02001529
Willy Tarreau20879a02012-12-03 16:32:10 +01001530 conn->err_code = CO_ER_SSL_CRT_FAIL;
Emeric Brun81c00f02012-09-21 14:31:21 +02001531 return 0;
Emeric Brune64aef12012-09-21 13:15:06 +02001532}
1533
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001534static inline
1535void ssl_sock_parse_clienthello(int write_p, int version, int content_type,
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001536 const void *buf, size_t len, SSL *ssl)
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001537{
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001538 struct ssl_capture *capture;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001539 unsigned char *msg;
1540 unsigned char *end;
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001541 size_t rec_len;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001542
1543 /* This function is called for "from client" and "to server"
1544 * connections. The combination of write_p == 0 and content_type == 22
Joseph Herlant017b3da2018-11-15 09:07:59 -08001545 * is only available during "from client" connection.
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001546 */
1547
1548 /* "write_p" is set to 0 is the bytes are received messages,
1549 * otherwise it is set to 1.
1550 */
1551 if (write_p != 0)
1552 return;
1553
1554 /* content_type contains the type of message received or sent
1555 * according with the SSL/TLS protocol spec. This message is
1556 * encoded with one byte. The value 256 (two bytes) is used
1557 * for designing the SSL/TLS record layer. According with the
1558 * rfc6101, the expected message (other than 256) are:
1559 * - change_cipher_spec(20)
1560 * - alert(21)
1561 * - handshake(22)
1562 * - application_data(23)
1563 * - (255)
1564 * We are interessed by the handshake and specially the client
1565 * hello.
1566 */
1567 if (content_type != 22)
1568 return;
1569
1570 /* The message length is at least 4 bytes, containing the
1571 * message type and the message length.
1572 */
1573 if (len < 4)
1574 return;
1575
1576 /* First byte of the handshake message id the type of
1577 * message. The konwn types are:
1578 * - hello_request(0)
1579 * - client_hello(1)
1580 * - server_hello(2)
1581 * - certificate(11)
1582 * - server_key_exchange (12)
1583 * - certificate_request(13)
1584 * - server_hello_done(14)
1585 * We are interested by the client hello.
1586 */
1587 msg = (unsigned char *)buf;
1588 if (msg[0] != 1)
1589 return;
1590
1591 /* Next three bytes are the length of the message. The total length
1592 * must be this decoded length + 4. If the length given as argument
1593 * is not the same, we abort the protocol dissector.
1594 */
1595 rec_len = (msg[1] << 16) + (msg[2] << 8) + msg[3];
1596 if (len < rec_len + 4)
1597 return;
1598 msg += 4;
1599 end = msg + rec_len;
1600 if (end < msg)
1601 return;
1602
1603 /* Expect 2 bytes for protocol version (1 byte for major and 1 byte
1604 * for minor, the random, composed by 4 bytes for the unix time and
Baptiste Assmann6be139f2018-11-28 15:20:25 +01001605 * 28 bytes for unix payload. So we jump 1 + 1 + 4 + 28.
1606 */
1607 msg += 1 + 1 + 4 + 28;
1608 if (msg > end)
1609 return;
1610
1611 /* Next, is session id:
1612 * if present, we have to jump by length + 1 for the size information
1613 * if not present, we have to jump by 1 only
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001614 */
Baptiste Assmann6be139f2018-11-28 15:20:25 +01001615 if (msg[0] > 0)
1616 msg += msg[0];
1617 msg += 1;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001618 if (msg > end)
1619 return;
1620
1621 /* Next two bytes are the ciphersuite length. */
1622 if (msg + 2 > end)
1623 return;
1624 rec_len = (msg[0] << 8) + msg[1];
1625 msg += 2;
1626 if (msg + rec_len > end || msg + rec_len < msg)
1627 return;
1628
Willy Tarreaubafbe012017-11-24 17:34:44 +01001629 capture = pool_alloc_dirty(pool_head_ssl_capture);
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001630 if (!capture)
1631 return;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001632 /* Compute the xxh64 of the ciphersuite. */
1633 capture->xxh64 = XXH64(msg, rec_len, 0);
1634
1635 /* Capture the ciphersuite. */
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001636 capture->ciphersuite_len = (global_ssl.capture_cipherlist < rec_len) ?
1637 global_ssl.capture_cipherlist : rec_len;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001638 memcpy(capture->ciphersuite, msg, capture->ciphersuite_len);
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001639
1640 SSL_set_ex_data(ssl, ssl_capture_ptr_index, capture);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001641}
1642
Emeric Brun29f037d2014-04-25 19:05:36 +02001643/* Callback is called for ssl protocol analyse */
1644void ssl_sock_msgcbk(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg)
1645{
Emeric Brun29f037d2014-04-25 19:05:36 +02001646#ifdef TLS1_RT_HEARTBEAT
1647 /* test heartbeat received (write_p is set to 0
1648 for a received record) */
Willy Tarreauf51c6982014-04-25 20:02:39 +02001649 if ((content_type == TLS1_RT_HEARTBEAT) && (write_p == 0)) {
Thierry FOURNIER28962c92018-06-17 21:37:05 +02001650 struct connection *conn = SSL_get_ex_data(ssl, ssl_app_data_index);
William Lallemand7e1770b2019-05-13 14:31:34 +02001651 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
Willy Tarreauf51c6982014-04-25 20:02:39 +02001652 const unsigned char *p = buf;
1653 unsigned int payload;
1654
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001655 ctx->xprt_st |= SSL_SOCK_RECV_HEARTBEAT;
Willy Tarreauf51c6982014-04-25 20:02:39 +02001656
1657 /* Check if this is a CVE-2014-0160 exploitation attempt. */
1658 if (*p != TLS1_HB_REQUEST)
1659 return;
1660
Willy Tarreauaeed6722014-04-25 23:59:58 +02001661 if (len < 1 + 2 + 16) /* 1 type + 2 size + 0 payload + 16 padding */
Willy Tarreauf51c6982014-04-25 20:02:39 +02001662 goto kill_it;
1663
1664 payload = (p[1] * 256) + p[2];
Willy Tarreau3b2fdb62014-04-25 23:44:22 +02001665 if (3 + payload + 16 <= len)
Willy Tarreauf51c6982014-04-25 20:02:39 +02001666 return; /* OK no problem */
Willy Tarreauaeed6722014-04-25 23:59:58 +02001667 kill_it:
Willy Tarreau3b2fdb62014-04-25 23:44:22 +02001668 /* We have a clear heartbleed attack (CVE-2014-0160), the
1669 * advertised payload is larger than the advertised packet
1670 * length, so we have garbage in the buffer between the
1671 * payload and the end of the buffer (p+len). We can't know
1672 * if the SSL stack is patched, and we don't know if we can
1673 * safely wipe out the area between p+3+len and payload.
1674 * So instead, we prevent the response from being sent by
1675 * setting the max_send_fragment to 0 and we report an SSL
1676 * error, which will kill this connection. It will be reported
1677 * above as SSL_ERROR_SSL while an other handshake failure with
Willy Tarreauf51c6982014-04-25 20:02:39 +02001678 * a heartbeat message will be reported as SSL_ERROR_SYSCALL.
1679 */
Willy Tarreau3b2fdb62014-04-25 23:44:22 +02001680 ssl->max_send_fragment = 0;
Willy Tarreauf51c6982014-04-25 20:02:39 +02001681 SSLerr(SSL_F_TLS1_HEARTBEAT, SSL_R_SSL_HANDSHAKE_FAILURE);
1682 return;
1683 }
Emeric Brun29f037d2014-04-25 19:05:36 +02001684#endif
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001685 if (global_ssl.capture_cipherlist > 0)
1686 ssl_sock_parse_clienthello(write_p, version, content_type, buf, len, ssl);
Emeric Brun29f037d2014-04-25 19:05:36 +02001687}
1688
Bernard Spil13c53f82018-02-15 13:34:58 +01001689#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Olivier Houchardc7566002018-11-20 23:33:50 +01001690static int ssl_sock_srv_select_protos(SSL *s, unsigned char **out, unsigned char *outlen,
1691 const unsigned char *in, unsigned int inlen,
1692 void *arg)
1693{
1694 struct server *srv = arg;
1695
1696 if (SSL_select_next_proto(out, outlen, in, inlen, (unsigned char *)srv->ssl_ctx.npn_str,
1697 srv->ssl_ctx.npn_len) == OPENSSL_NPN_NEGOTIATED)
1698 return SSL_TLSEXT_ERR_OK;
1699 return SSL_TLSEXT_ERR_NOACK;
1700}
1701#endif
1702
1703#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02001704/* This callback is used so that the server advertises the list of
1705 * negociable protocols for NPN.
1706 */
1707static int ssl_sock_advertise_npn_protos(SSL *s, const unsigned char **data,
1708 unsigned int *len, void *arg)
1709{
Emmanuel Hocdet98263292016-12-29 18:26:15 +01001710 struct ssl_bind_conf *conf = arg;
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02001711
1712 *data = (const unsigned char *)conf->npn_str;
1713 *len = conf->npn_len;
1714 return SSL_TLSEXT_ERR_OK;
1715}
1716#endif
1717
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01001718#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02001719/* This callback is used so that the server advertises the list of
1720 * negociable protocols for ALPN.
1721 */
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01001722static int ssl_sock_advertise_alpn_protos(SSL *s, const unsigned char **out,
1723 unsigned char *outlen,
1724 const unsigned char *server,
1725 unsigned int server_len, void *arg)
Willy Tarreauab861d32013-04-02 02:30:41 +02001726{
Emmanuel Hocdet98263292016-12-29 18:26:15 +01001727 struct ssl_bind_conf *conf = arg;
Willy Tarreauab861d32013-04-02 02:30:41 +02001728
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01001729 if (SSL_select_next_proto((unsigned char**) out, outlen, (const unsigned char *)conf->alpn_str,
1730 conf->alpn_len, server, server_len) != OPENSSL_NPN_NEGOTIATED) {
1731 return SSL_TLSEXT_ERR_NOACK;
1732 }
Willy Tarreauab861d32013-04-02 02:30:41 +02001733 return SSL_TLSEXT_ERR_OK;
1734}
1735#endif
1736
Willy Tarreauc8ad3be2015-06-17 15:48:26 +02001737#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01001738#ifndef SSL_NO_GENERATE_CERTIFICATES
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001739
Christopher Faulet30548802015-06-11 13:39:32 +02001740/* Create a X509 certificate with the specified servername and serial. This
1741 * function returns a SSL_CTX object or NULL if an error occurs. */
Christopher Faulet7969a332015-10-09 11:15:03 +02001742static SSL_CTX *
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001743ssl_sock_do_create_cert(const char *servername, struct bind_conf *bind_conf, SSL *ssl)
Christopher Faulet31af49d2015-06-09 17:29:50 +02001744{
Christopher Faulet7969a332015-10-09 11:15:03 +02001745 X509 *cacert = bind_conf->ca_sign_cert;
1746 EVP_PKEY *capkey = bind_conf->ca_sign_pkey;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001747 SSL_CTX *ssl_ctx = NULL;
1748 X509 *newcrt = NULL;
1749 EVP_PKEY *pkey = NULL;
Emmanuel Hocdet15969292017-08-11 10:56:00 +02001750 SSL *tmp_ssl = NULL;
Emmanuel Hocdeta9b84022018-10-01 18:41:36 +02001751 CONF *ctmp = NULL;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001752 X509_NAME *name;
1753 const EVP_MD *digest;
1754 X509V3_CTX ctx;
1755 unsigned int i;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001756 int key_type;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001757
Christopher Faulet48a83322017-07-28 16:56:09 +02001758 /* Get the private key of the default certificate and use it */
Willy Tarreau5db847a2019-05-09 14:13:35 +02001759#if (HA_OPENSSL_VERSION_NUMBER >= 0x10002000L)
Emmanuel Hocdet15969292017-08-11 10:56:00 +02001760 pkey = SSL_CTX_get0_privatekey(bind_conf->default_ctx);
1761#else
1762 tmp_ssl = SSL_new(bind_conf->default_ctx);
1763 if (tmp_ssl)
1764 pkey = SSL_get_privatekey(tmp_ssl);
1765#endif
1766 if (!pkey)
Christopher Faulet31af49d2015-06-09 17:29:50 +02001767 goto mkcert_error;
1768
1769 /* Create the certificate */
1770 if (!(newcrt = X509_new()))
1771 goto mkcert_error;
1772
1773 /* Set version number for the certificate (X509v3) and the serial
1774 * number */
1775 if (X509_set_version(newcrt, 2L) != 1)
1776 goto mkcert_error;
Olivier Houchard2be5a4c2019-03-08 18:54:43 +01001777 ASN1_INTEGER_set(X509_get_serialNumber(newcrt), _HA_ATOMIC_ADD(&ssl_ctx_serial, 1));
Christopher Faulet31af49d2015-06-09 17:29:50 +02001778
1779 /* Set duration for the certificate */
Rosen Penev68185952018-12-14 08:47:02 -08001780 if (!X509_gmtime_adj(X509_getm_notBefore(newcrt), (long)-60*60*24) ||
1781 !X509_gmtime_adj(X509_getm_notAfter(newcrt),(long)60*60*24*365))
Christopher Faulet31af49d2015-06-09 17:29:50 +02001782 goto mkcert_error;
1783
1784 /* set public key in the certificate */
1785 if (X509_set_pubkey(newcrt, pkey) != 1)
1786 goto mkcert_error;
1787
1788 /* Set issuer name from the CA */
1789 if (!(name = X509_get_subject_name(cacert)))
1790 goto mkcert_error;
1791 if (X509_set_issuer_name(newcrt, name) != 1)
1792 goto mkcert_error;
1793
1794 /* Set the subject name using the same, but the CN */
1795 name = X509_NAME_dup(name);
1796 if (X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC,
1797 (const unsigned char *)servername,
1798 -1, -1, 0) != 1) {
1799 X509_NAME_free(name);
1800 goto mkcert_error;
1801 }
1802 if (X509_set_subject_name(newcrt, name) != 1) {
1803 X509_NAME_free(name);
1804 goto mkcert_error;
1805 }
1806 X509_NAME_free(name);
1807
1808 /* Add x509v3 extensions as specified */
Emmanuel Hocdeta9b84022018-10-01 18:41:36 +02001809 ctmp = NCONF_new(NULL);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001810 X509V3_set_ctx(&ctx, cacert, newcrt, NULL, NULL, 0);
1811 for (i = 0; i < X509V3_EXT_SIZE; i++) {
1812 X509_EXTENSION *ext;
1813
Emmanuel Hocdeta9b84022018-10-01 18:41:36 +02001814 if (!(ext = X509V3_EXT_nconf(ctmp, &ctx, x509v3_ext_names[i], x509v3_ext_values[i])))
Christopher Faulet31af49d2015-06-09 17:29:50 +02001815 goto mkcert_error;
1816 if (!X509_add_ext(newcrt, ext, -1)) {
1817 X509_EXTENSION_free(ext);
1818 goto mkcert_error;
1819 }
1820 X509_EXTENSION_free(ext);
1821 }
1822
1823 /* Sign the certificate with the CA private key */
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001824
1825 key_type = EVP_PKEY_base_id(capkey);
1826
1827 if (key_type == EVP_PKEY_DSA)
1828 digest = EVP_sha1();
1829 else if (key_type == EVP_PKEY_RSA)
Christopher Faulet31af49d2015-06-09 17:29:50 +02001830 digest = EVP_sha256();
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001831 else if (key_type == EVP_PKEY_EC)
Christopher Faulet7969a332015-10-09 11:15:03 +02001832 digest = EVP_sha256();
1833 else {
Willy Tarreau9a1ab082019-05-09 13:26:41 +02001834#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000000fL) && !defined(OPENSSL_IS_BORINGSSL)
Christopher Faulet7969a332015-10-09 11:15:03 +02001835 int nid;
1836
1837 if (EVP_PKEY_get_default_digest_nid(capkey, &nid) <= 0)
1838 goto mkcert_error;
1839 if (!(digest = EVP_get_digestbynid(nid)))
1840 goto mkcert_error;
Christopher Faulete7db2162015-10-19 13:59:24 +02001841#else
1842 goto mkcert_error;
1843#endif
Christopher Faulet7969a332015-10-09 11:15:03 +02001844 }
1845
Christopher Faulet31af49d2015-06-09 17:29:50 +02001846 if (!(X509_sign(newcrt, capkey, digest)))
1847 goto mkcert_error;
1848
1849 /* Create and set the new SSL_CTX */
1850 if (!(ssl_ctx = SSL_CTX_new(SSLv23_server_method())))
1851 goto mkcert_error;
1852 if (!SSL_CTX_use_PrivateKey(ssl_ctx, pkey))
1853 goto mkcert_error;
1854 if (!SSL_CTX_use_certificate(ssl_ctx, newcrt))
1855 goto mkcert_error;
1856 if (!SSL_CTX_check_private_key(ssl_ctx))
1857 goto mkcert_error;
1858
1859 if (newcrt) X509_free(newcrt);
Christopher Faulet7969a332015-10-09 11:15:03 +02001860
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01001861#ifndef OPENSSL_NO_DH
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001862 SSL_CTX_set_tmp_dh_callback(ssl_ctx, ssl_get_tmp_dh);
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01001863#endif
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001864#if defined(SSL_CTX_set_tmp_ecdh) && !defined(OPENSSL_NO_ECDH)
1865 {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01001866 const char *ecdhe = (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe : ECDHE_DEFAULT_CURVE);
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001867 EC_KEY *ecc;
1868 int nid;
1869
1870 if ((nid = OBJ_sn2nid(ecdhe)) == NID_undef)
1871 goto end;
1872 if (!(ecc = EC_KEY_new_by_curve_name(nid)))
1873 goto end;
1874 SSL_CTX_set_tmp_ecdh(ssl_ctx, ecc);
1875 EC_KEY_free(ecc);
1876 }
1877#endif
1878 end:
Christopher Faulet31af49d2015-06-09 17:29:50 +02001879 return ssl_ctx;
1880
1881 mkcert_error:
Emmanuel Hocdeta9b84022018-10-01 18:41:36 +02001882 if (ctmp) NCONF_free(ctmp);
Emmanuel Hocdet15969292017-08-11 10:56:00 +02001883 if (tmp_ssl) SSL_free(tmp_ssl);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001884 if (ssl_ctx) SSL_CTX_free(ssl_ctx);
1885 if (newcrt) X509_free(newcrt);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001886 return NULL;
1887}
1888
Christopher Faulet7969a332015-10-09 11:15:03 +02001889SSL_CTX *
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001890ssl_sock_create_cert(struct connection *conn, const char *servername, unsigned int key)
Christopher Faulet7969a332015-10-09 11:15:03 +02001891{
Willy Tarreau07d94e42018-09-20 10:57:52 +02001892 struct bind_conf *bind_conf = __objt_listener(conn->target)->bind_conf;
Olivier Houchard66ab4982019-02-26 18:37:15 +01001893 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001894
Olivier Houchard66ab4982019-02-26 18:37:15 +01001895 return ssl_sock_do_create_cert(servername, bind_conf, ctx->ssl);
Christopher Faulet7969a332015-10-09 11:15:03 +02001896}
1897
Christopher Faulet30548802015-06-11 13:39:32 +02001898/* Do a lookup for a certificate in the LRU cache used to store generated
Emeric Brun821bb9b2017-06-15 16:37:39 +02001899 * certificates and immediately assign it to the SSL session if not null. */
Christopher Faulet30548802015-06-11 13:39:32 +02001900SSL_CTX *
Emeric Brun821bb9b2017-06-15 16:37:39 +02001901ssl_sock_assign_generated_cert(unsigned int key, struct bind_conf *bind_conf, SSL *ssl)
Christopher Faulet30548802015-06-11 13:39:32 +02001902{
1903 struct lru64 *lru = NULL;
1904
1905 if (ssl_ctx_lru_tree) {
Willy Tarreau03f4ec42018-05-17 10:56:47 +02001906 HA_RWLOCK_WRLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001907 lru = lru64_lookup(key, ssl_ctx_lru_tree, bind_conf->ca_sign_cert, 0);
Emeric Brun821bb9b2017-06-15 16:37:39 +02001908 if (lru && lru->domain) {
1909 if (ssl)
1910 SSL_set_SSL_CTX(ssl, (SSL_CTX *)lru->data);
Willy Tarreau03f4ec42018-05-17 10:56:47 +02001911 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet30548802015-06-11 13:39:32 +02001912 return (SSL_CTX *)lru->data;
Emeric Brun821bb9b2017-06-15 16:37:39 +02001913 }
Willy Tarreau03f4ec42018-05-17 10:56:47 +02001914 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet30548802015-06-11 13:39:32 +02001915 }
1916 return NULL;
1917}
1918
Emeric Brun821bb9b2017-06-15 16:37:39 +02001919/* Same as <ssl_sock_assign_generated_cert> but without SSL session. This
1920 * function is not thread-safe, it should only be used to check if a certificate
1921 * exists in the lru cache (with no warranty it will not be removed by another
1922 * thread). It is kept for backward compatibility. */
1923SSL_CTX *
1924ssl_sock_get_generated_cert(unsigned int key, struct bind_conf *bind_conf)
1925{
1926 return ssl_sock_assign_generated_cert(key, bind_conf, NULL);
1927}
1928
Christopher Fauletd2cab922015-07-28 16:03:47 +02001929/* Set a certificate int the LRU cache used to store generated
1930 * certificate. Return 0 on success, otherwise -1 */
1931int
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001932ssl_sock_set_generated_cert(SSL_CTX *ssl_ctx, unsigned int key, struct bind_conf *bind_conf)
Christopher Faulet30548802015-06-11 13:39:32 +02001933{
1934 struct lru64 *lru = NULL;
1935
1936 if (ssl_ctx_lru_tree) {
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001937 HA_RWLOCK_WRLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001938 lru = lru64_get(key, ssl_ctx_lru_tree, bind_conf->ca_sign_cert, 0);
Emeric Brun821bb9b2017-06-15 16:37:39 +02001939 if (!lru) {
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001940 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Fauletd2cab922015-07-28 16:03:47 +02001941 return -1;
Emeric Brun821bb9b2017-06-15 16:37:39 +02001942 }
Christopher Faulet30548802015-06-11 13:39:32 +02001943 if (lru->domain && lru->data)
1944 lru->free((SSL_CTX *)lru->data);
Christopher Faulet7969a332015-10-09 11:15:03 +02001945 lru64_commit(lru, ssl_ctx, bind_conf->ca_sign_cert, 0, (void (*)(void *))SSL_CTX_free);
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001946 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Fauletd2cab922015-07-28 16:03:47 +02001947 return 0;
Christopher Faulet30548802015-06-11 13:39:32 +02001948 }
Christopher Fauletd2cab922015-07-28 16:03:47 +02001949 return -1;
Christopher Faulet30548802015-06-11 13:39:32 +02001950}
1951
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001952/* Compute the key of the certificate. */
Christopher Faulet30548802015-06-11 13:39:32 +02001953unsigned int
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001954ssl_sock_generated_cert_key(const void *data, size_t len)
Christopher Faulet30548802015-06-11 13:39:32 +02001955{
1956 return XXH32(data, len, ssl_ctx_lru_seed);
1957}
1958
Willy Tarreau2f63ef42015-10-20 15:16:01 +02001959/* Generate a cert and immediately assign it to the SSL session so that the cert's
1960 * refcount is maintained regardless of the cert's presence in the LRU cache.
1961 */
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001962static int
Christopher Faulet7969a332015-10-09 11:15:03 +02001963ssl_sock_generate_certificate(const char *servername, struct bind_conf *bind_conf, SSL *ssl)
Christopher Faulet31af49d2015-06-09 17:29:50 +02001964{
1965 X509 *cacert = bind_conf->ca_sign_cert;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001966 SSL_CTX *ssl_ctx = NULL;
1967 struct lru64 *lru = NULL;
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001968 unsigned int key;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001969
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001970 key = ssl_sock_generated_cert_key(servername, strlen(servername));
Christopher Faulet31af49d2015-06-09 17:29:50 +02001971 if (ssl_ctx_lru_tree) {
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001972 HA_RWLOCK_WRLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001973 lru = lru64_get(key, ssl_ctx_lru_tree, cacert, 0);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001974 if (lru && lru->domain)
1975 ssl_ctx = (SSL_CTX *)lru->data;
Christopher Fauletd2cab922015-07-28 16:03:47 +02001976 if (!ssl_ctx && lru) {
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001977 ssl_ctx = ssl_sock_do_create_cert(servername, bind_conf, ssl);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001978 lru64_commit(lru, ssl_ctx, cacert, 0, (void (*)(void *))SSL_CTX_free);
Christopher Fauletd2cab922015-07-28 16:03:47 +02001979 }
Willy Tarreau2f63ef42015-10-20 15:16:01 +02001980 SSL_set_SSL_CTX(ssl, ssl_ctx);
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001981 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001982 return 1;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001983 }
Willy Tarreau2f63ef42015-10-20 15:16:01 +02001984 else {
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001985 ssl_ctx = ssl_sock_do_create_cert(servername, bind_conf, ssl);
Willy Tarreau2f63ef42015-10-20 15:16:01 +02001986 SSL_set_SSL_CTX(ssl, ssl_ctx);
1987 /* No LRU cache, this CTX will be released as soon as the session dies */
1988 SSL_CTX_free(ssl_ctx);
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001989 return 1;
Willy Tarreau2f63ef42015-10-20 15:16:01 +02001990 }
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001991 return 0;
1992}
1993static int
1994ssl_sock_generate_certificate_from_conn(struct bind_conf *bind_conf, SSL *ssl)
1995{
1996 unsigned int key;
Thierry FOURNIER28962c92018-06-17 21:37:05 +02001997 struct connection *conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001998
Willy Tarreauf5bdb642019-07-17 11:29:32 +02001999 if (conn_get_dst(conn)) {
Willy Tarreau085a1512019-07-17 14:47:35 +02002000 key = ssl_sock_generated_cert_key(conn->dst, get_addr_len(conn->dst));
Emeric Brun821bb9b2017-06-15 16:37:39 +02002001 if (ssl_sock_assign_generated_cert(key, bind_conf, ssl))
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002002 return 1;
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002003 }
2004 return 0;
Christopher Faulet31af49d2015-06-09 17:29:50 +02002005}
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002006#endif /* !defined SSL_NO_GENERATE_CERTIFICATES */
Christopher Faulet31af49d2015-06-09 17:29:50 +02002007
Willy Tarreau9a1ab082019-05-09 13:26:41 +02002008#if (HA_OPENSSL_VERSION_NUMBER < 0x1010000fL)
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002009typedef enum { SET_CLIENT, SET_SERVER } set_context_func;
2010
2011static void ctx_set_SSLv3_func(SSL_CTX *ctx, set_context_func c)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002012{
Emmanuel Hocdet23877ab2017-07-12 12:53:02 +02002013#if SSL_OP_NO_SSLv3
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002014 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, SSLv3_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002015 : SSL_CTX_set_ssl_version(ctx, SSLv3_client_method());
2016#endif
2017}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002018static void ctx_set_TLSv10_func(SSL_CTX *ctx, set_context_func c) {
2019 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, TLSv1_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002020 : SSL_CTX_set_ssl_version(ctx, TLSv1_client_method());
2021}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002022static void ctx_set_TLSv11_func(SSL_CTX *ctx, set_context_func c) {
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002023#if SSL_OP_NO_TLSv1_1
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002024 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, TLSv1_1_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002025 : SSL_CTX_set_ssl_version(ctx, TLSv1_1_client_method());
2026#endif
2027}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002028static void ctx_set_TLSv12_func(SSL_CTX *ctx, set_context_func c) {
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002029#if SSL_OP_NO_TLSv1_2
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002030 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, TLSv1_2_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002031 : SSL_CTX_set_ssl_version(ctx, TLSv1_2_client_method());
2032#endif
2033}
Bertrand Jacquina25282b2018-08-14 00:56:13 +01002034/* TLSv1.2 is the last supported version in this context. */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002035static void ctx_set_TLSv13_func(SSL_CTX *ctx, set_context_func c) {}
2036/* Unusable in this context. */
2037static void ssl_set_SSLv3_func(SSL *ssl, set_context_func c) {}
2038static void ssl_set_TLSv10_func(SSL *ssl, set_context_func c) {}
2039static void ssl_set_TLSv11_func(SSL *ssl, set_context_func c) {}
2040static void ssl_set_TLSv12_func(SSL *ssl, set_context_func c) {}
2041static void ssl_set_TLSv13_func(SSL *ssl, set_context_func c) {}
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002042#else /* openssl >= 1.1.0 */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002043typedef enum { SET_MIN, SET_MAX } set_context_func;
2044
2045static void ctx_set_SSLv3_func(SSL_CTX *ctx, set_context_func c) {
2046 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, SSL3_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002047 : SSL_CTX_set_min_proto_version(ctx, SSL3_VERSION);
2048}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002049static void ssl_set_SSLv3_func(SSL *ssl, set_context_func c) {
2050 c == SET_MAX ? SSL_set_max_proto_version(ssl, SSL3_VERSION)
2051 : SSL_set_min_proto_version(ssl, SSL3_VERSION);
2052}
2053static void ctx_set_TLSv10_func(SSL_CTX *ctx, set_context_func c) {
2054 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002055 : SSL_CTX_set_min_proto_version(ctx, TLS1_VERSION);
2056}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002057static void ssl_set_TLSv10_func(SSL *ssl, set_context_func c) {
2058 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_VERSION)
2059 : SSL_set_min_proto_version(ssl, TLS1_VERSION);
2060}
2061static void ctx_set_TLSv11_func(SSL_CTX *ctx, set_context_func c) {
2062 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_1_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002063 : SSL_CTX_set_min_proto_version(ctx, TLS1_1_VERSION);
2064}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002065static void ssl_set_TLSv11_func(SSL *ssl, set_context_func c) {
2066 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_1_VERSION)
2067 : SSL_set_min_proto_version(ssl, TLS1_1_VERSION);
2068}
2069static void ctx_set_TLSv12_func(SSL_CTX *ctx, set_context_func c) {
2070 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_2_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002071 : SSL_CTX_set_min_proto_version(ctx, TLS1_2_VERSION);
2072}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002073static void ssl_set_TLSv12_func(SSL *ssl, set_context_func c) {
2074 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_2_VERSION)
2075 : SSL_set_min_proto_version(ssl, TLS1_2_VERSION);
2076}
2077static void ctx_set_TLSv13_func(SSL_CTX *ctx, set_context_func c) {
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002078#if SSL_OP_NO_TLSv1_3
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002079 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_3_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002080 : SSL_CTX_set_min_proto_version(ctx, TLS1_3_VERSION);
2081#endif
2082}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002083static void ssl_set_TLSv13_func(SSL *ssl, set_context_func c) {
2084#if SSL_OP_NO_TLSv1_3
2085 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_3_VERSION)
2086 : SSL_set_min_proto_version(ssl, TLS1_3_VERSION);
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002087#endif
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002088}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002089#endif
2090static void ctx_set_None_func(SSL_CTX *ctx, set_context_func c) { }
2091static void ssl_set_None_func(SSL *ssl, set_context_func c) { }
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002092
2093static struct {
2094 int option;
2095 uint16_t flag;
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002096 void (*ctx_set_version)(SSL_CTX *, set_context_func);
2097 void (*ssl_set_version)(SSL *, set_context_func);
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002098 const char *name;
2099} methodVersions[] = {
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002100 {0, 0, ctx_set_None_func, ssl_set_None_func, "NONE"}, /* CONF_TLSV_NONE */
2101 {SSL_OP_NO_SSLv3, MC_SSL_O_NO_SSLV3, ctx_set_SSLv3_func, ssl_set_SSLv3_func, "SSLv3"}, /* CONF_SSLV3 */
2102 {SSL_OP_NO_TLSv1, MC_SSL_O_NO_TLSV10, ctx_set_TLSv10_func, ssl_set_TLSv10_func, "TLSv1.0"}, /* CONF_TLSV10 */
2103 {SSL_OP_NO_TLSv1_1, MC_SSL_O_NO_TLSV11, ctx_set_TLSv11_func, ssl_set_TLSv11_func, "TLSv1.1"}, /* CONF_TLSV11 */
2104 {SSL_OP_NO_TLSv1_2, MC_SSL_O_NO_TLSV12, ctx_set_TLSv12_func, ssl_set_TLSv12_func, "TLSv1.2"}, /* CONF_TLSV12 */
2105 {SSL_OP_NO_TLSv1_3, MC_SSL_O_NO_TLSV13, ctx_set_TLSv13_func, ssl_set_TLSv13_func, "TLSv1.3"}, /* CONF_TLSV13 */
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002106};
2107
Emmanuel Hocdet530141f2017-03-01 18:54:56 +01002108static void ssl_sock_switchctx_set(SSL *ssl, SSL_CTX *ctx)
2109{
2110 SSL_set_verify(ssl, SSL_CTX_get_verify_mode(ctx), ssl_sock_bind_verifycbk);
2111 SSL_set_client_CA_list(ssl, SSL_dup_CA_list(SSL_CTX_get_client_CA_list(ctx)));
2112 SSL_set_SSL_CTX(ssl, ctx);
2113}
2114
Willy Tarreau5db847a2019-05-09 14:13:35 +02002115#if ((HA_OPENSSL_VERSION_NUMBER >= 0x10101000L) || defined(OPENSSL_IS_BORINGSSL))
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002116
2117static int ssl_sock_switchctx_err_cbk(SSL *ssl, int *al, void *priv)
2118{
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002119 struct bind_conf *s = priv;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002120 (void)al; /* shut gcc stupid warning */
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002121
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002122 if (SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name) || s->generate_certs)
2123 return SSL_TLSEXT_ERR_OK;
2124 return SSL_TLSEXT_ERR_NOACK;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002125}
2126
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002127#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002128static int ssl_sock_switchctx_cbk(const struct ssl_early_callback_ctx *ctx)
2129{
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002130 SSL *ssl = ctx->ssl;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002131#else
2132static int ssl_sock_switchctx_cbk(SSL *ssl, int *al, void *arg)
2133{
2134#endif
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002135 struct connection *conn;
2136 struct bind_conf *s;
2137 const uint8_t *extension_data;
2138 size_t extension_len;
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002139 int has_rsa_sig = 0, has_ecdsa_sig = 0;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002140
2141 char *wildp = NULL;
2142 const uint8_t *servername;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002143 size_t servername_len;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002144 struct ebmb_node *node, *n, *node_ecdsa = NULL, *node_rsa = NULL, *node_anonymous = NULL;
Olivier Houchardc2aae742017-09-22 18:26:28 +02002145 int allow_early = 0;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002146 int i;
2147
Thierry FOURNIER28962c92018-06-17 21:37:05 +02002148 conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Willy Tarreaua8825522018-10-15 13:20:07 +02002149 s = __objt_listener(conn->target)->bind_conf;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002150
Olivier Houchard9679ac92017-10-27 14:58:08 +02002151 if (s->ssl_conf.early_data)
Olivier Houchardc2aae742017-09-22 18:26:28 +02002152 allow_early = 1;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002153#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002154 if (SSL_early_callback_ctx_extension_get(ctx, TLSEXT_TYPE_server_name,
2155 &extension_data, &extension_len)) {
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002156#else
2157 if (SSL_client_hello_get0_ext(ssl, TLSEXT_TYPE_server_name, &extension_data, &extension_len)) {
2158#endif
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002159 /*
2160 * The server_name extension was given too much extensibility when it
2161 * was written, so parsing the normal case is a bit complex.
2162 */
2163 size_t len;
2164 if (extension_len <= 2)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002165 goto abort;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002166 /* Extract the length of the supplied list of names. */
2167 len = (*extension_data++) << 8;
2168 len |= *extension_data++;
2169 if (len + 2 != extension_len)
2170 goto abort;
2171 /*
2172 * The list in practice only has a single element, so we only consider
2173 * the first one.
2174 */
2175 if (len == 0 || *extension_data++ != TLSEXT_NAMETYPE_host_name)
2176 goto abort;
2177 extension_len = len - 1;
2178 /* Now we can finally pull out the byte array with the actual hostname. */
2179 if (extension_len <= 2)
2180 goto abort;
2181 len = (*extension_data++) << 8;
2182 len |= *extension_data++;
2183 if (len == 0 || len + 2 > extension_len || len > TLSEXT_MAXLEN_host_name
2184 || memchr(extension_data, 0, len) != NULL)
2185 goto abort;
2186 servername = extension_data;
2187 servername_len = len;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002188 } else {
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002189#if (!defined SSL_NO_GENERATE_CERTIFICATES)
2190 if (s->generate_certs && ssl_sock_generate_certificate_from_conn(s, ssl)) {
Olivier Houchardc2aae742017-09-22 18:26:28 +02002191 goto allow_early;
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002192 }
2193#endif
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002194 /* without SNI extension, is the default_ctx (need SSL_TLSEXT_ERR_NOACK) */
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002195 if (!s->strict_sni) {
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002196 ssl_sock_switchctx_set(ssl, s->default_ctx);
Olivier Houchardc2aae742017-09-22 18:26:28 +02002197 goto allow_early;
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002198 }
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002199 goto abort;
2200 }
2201
2202 /* extract/check clientHello informations */
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002203#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002204 if (SSL_early_callback_ctx_extension_get(ctx, TLSEXT_TYPE_signature_algorithms, &extension_data, &extension_len)) {
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002205#else
2206 if (SSL_client_hello_get0_ext(ssl, TLSEXT_TYPE_signature_algorithms, &extension_data, &extension_len)) {
2207#endif
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002208 uint8_t sign;
2209 size_t len;
2210 if (extension_len < 2)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002211 goto abort;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002212 len = (*extension_data++) << 8;
2213 len |= *extension_data++;
2214 if (len + 2 != extension_len)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002215 goto abort;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002216 if (len % 2 != 0)
2217 goto abort;
2218 for (; len > 0; len -= 2) {
2219 extension_data++; /* hash */
2220 sign = *extension_data++;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002221 switch (sign) {
2222 case TLSEXT_signature_rsa:
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002223 has_rsa_sig = 1;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002224 break;
2225 case TLSEXT_signature_ecdsa:
2226 has_ecdsa_sig = 1;
2227 break;
2228 default:
2229 continue;
2230 }
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002231 if (has_ecdsa_sig && has_rsa_sig)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002232 break;
2233 }
2234 } else {
Bertrand Jacquina25282b2018-08-14 00:56:13 +01002235 /* without TLSEXT_TYPE_signature_algorithms extension (< TLSv1.2) */
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002236 has_rsa_sig = 1;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002237 }
2238 if (has_ecdsa_sig) { /* in very rare case: has ecdsa sign but not a ECDSA cipher */
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002239 const SSL_CIPHER *cipher;
2240 size_t len;
2241 const uint8_t *cipher_suites;
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002242 has_ecdsa_sig = 0;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002243#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002244 len = ctx->cipher_suites_len;
2245 cipher_suites = ctx->cipher_suites;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002246#else
2247 len = SSL_client_hello_get0_ciphers(ssl, &cipher_suites);
2248#endif
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002249 if (len % 2 != 0)
2250 goto abort;
2251 for (; len != 0; len -= 2, cipher_suites += 2) {
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002252#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002253 uint16_t cipher_suite = (cipher_suites[0] << 8) | cipher_suites[1];
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002254 cipher = SSL_get_cipher_by_value(cipher_suite);
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002255#else
2256 cipher = SSL_CIPHER_find(ssl, cipher_suites);
2257#endif
Emmanuel Hocdet019f9b12017-10-02 17:12:06 +02002258 if (cipher && SSL_CIPHER_get_auth_nid(cipher) == NID_auth_ecdsa) {
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002259 has_ecdsa_sig = 1;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002260 break;
2261 }
2262 }
2263 }
2264
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002265 for (i = 0; i < trash.size && i < servername_len; i++) {
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002266 trash.area[i] = tolower(servername[i]);
2267 if (!wildp && (trash.area[i] == '.'))
2268 wildp = &trash.area[i];
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002269 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002270 trash.area[i] = 0;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002271
William Lallemand150bfa82019-09-19 17:12:49 +02002272 HA_RWLOCK_RDLOCK(SNI_LOCK, &s->sni_lock);
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002273 /* lookup in full qualified names */
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002274 node = ebst_lookup(&s->sni_ctx, trash.area);
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002275
2276 /* lookup a not neg filter */
2277 for (n = node; n; n = ebmb_next_dup(n)) {
2278 if (!container_of(n, struct sni_ctx, name)->neg) {
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002279 switch(container_of(n, struct sni_ctx, name)->kinfo.sig) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002280 case TLSEXT_signature_ecdsa:
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002281 if (!node_ecdsa)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002282 node_ecdsa = n;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002283 break;
2284 case TLSEXT_signature_rsa:
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002285 if (!node_rsa)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002286 node_rsa = n;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002287 break;
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002288 default: /* TLSEXT_signature_anonymous|dsa */
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002289 if (!node_anonymous)
2290 node_anonymous = n;
2291 break;
2292 }
2293 }
2294 }
2295 if (wildp) {
2296 /* lookup in wildcards names */
2297 node = ebst_lookup(&s->sni_w_ctx, wildp);
2298 for (n = node; n; n = ebmb_next_dup(n)) {
2299 if (!container_of(n, struct sni_ctx, name)->neg) {
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002300 switch(container_of(n, struct sni_ctx, name)->kinfo.sig) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002301 case TLSEXT_signature_ecdsa:
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002302 if (!node_ecdsa)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002303 node_ecdsa = n;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002304 break;
2305 case TLSEXT_signature_rsa:
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002306 if (!node_rsa)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002307 node_rsa = n;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002308 break;
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002309 default: /* TLSEXT_signature_anonymous|dsa */
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002310 if (!node_anonymous)
2311 node_anonymous = n;
2312 break;
2313 }
2314 }
2315 }
2316 }
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002317 /* select by key_signature priority order */
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002318 node = (has_ecdsa_sig && node_ecdsa) ? node_ecdsa
2319 : ((has_rsa_sig && node_rsa) ? node_rsa
2320 : (node_anonymous ? node_anonymous
2321 : (node_ecdsa ? node_ecdsa /* no ecdsa signature case (< TLSv1.2) */
2322 : node_rsa /* no rsa signature case (far far away) */
2323 )));
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002324 if (node) {
2325 /* switch ctx */
Emmanuel Hocdet43664762017-08-09 18:26:20 +02002326 struct ssl_bind_conf *conf = container_of(node, struct sni_ctx, name)->conf;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002327 ssl_sock_switchctx_set(ssl, container_of(node, struct sni_ctx, name)->ctx);
Olivier Houchard35a63cc2017-11-02 19:04:38 +01002328 if (conf) {
2329 methodVersions[conf->ssl_methods.min].ssl_set_version(ssl, SET_MIN);
2330 methodVersions[conf->ssl_methods.max].ssl_set_version(ssl, SET_MAX);
2331 if (conf->early_data)
2332 allow_early = 1;
2333 }
William Lallemand150bfa82019-09-19 17:12:49 +02002334 HA_RWLOCK_RDUNLOCK(CKCH_LOCK, &s->sni_lock);
Olivier Houchard35a63cc2017-11-02 19:04:38 +01002335 goto allow_early;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002336 }
William Lallemand150bfa82019-09-19 17:12:49 +02002337
2338 HA_RWLOCK_RDUNLOCK(CKCH_LOCK, &s->sni_lock);
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002339#if (!defined SSL_NO_GENERATE_CERTIFICATES)
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002340 if (s->generate_certs && ssl_sock_generate_certificate(trash.area, s, ssl)) {
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002341 /* switch ctx done in ssl_sock_generate_certificate */
Olivier Houchardc2aae742017-09-22 18:26:28 +02002342 goto allow_early;
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002343 }
2344#endif
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002345 if (!s->strict_sni) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002346 /* no certificate match, is the default_ctx */
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002347 ssl_sock_switchctx_set(ssl, s->default_ctx);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002348 }
Olivier Houchardc2aae742017-09-22 18:26:28 +02002349allow_early:
2350#ifdef OPENSSL_IS_BORINGSSL
2351 if (allow_early)
2352 SSL_set_early_data_enabled(ssl, 1);
2353#else
2354 if (!allow_early)
2355 SSL_set_max_early_data(ssl, 0);
2356#endif
2357 return 1;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002358 abort:
2359 /* abort handshake (was SSL_TLSEXT_ERR_ALERT_FATAL) */
2360 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002361#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002362 return ssl_select_cert_error;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002363#else
2364 *al = SSL_AD_UNRECOGNIZED_NAME;
2365 return 0;
2366#endif
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002367}
2368
2369#else /* OPENSSL_IS_BORINGSSL */
2370
Emeric Brunfc0421f2012-09-07 17:30:07 +02002371/* Sets the SSL ctx of <ssl> to match the advertised server name. Returns a
2372 * warning when no match is found, which implies the default (first) cert
2373 * will keep being used.
2374 */
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002375static int ssl_sock_switchctx_cbk(SSL *ssl, int *al, void *priv)
Emeric Brunfc0421f2012-09-07 17:30:07 +02002376{
2377 const char *servername;
2378 const char *wildp = NULL;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002379 struct ebmb_node *node, *n;
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002380 struct bind_conf *s = priv;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002381 int i;
2382 (void)al; /* shut gcc stupid warning */
2383
2384 servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
Emmanuel Hocdet65623372013-01-24 17:17:15 +01002385 if (!servername) {
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002386#if (!defined SSL_NO_GENERATE_CERTIFICATES)
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002387 if (s->generate_certs && ssl_sock_generate_certificate_from_conn(s, ssl))
2388 return SSL_TLSEXT_ERR_OK;
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002389#endif
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002390 if (s->strict_sni)
2391 return SSL_TLSEXT_ERR_ALERT_FATAL;
2392 ssl_sock_switchctx_set(ssl, s->default_ctx);
2393 return SSL_TLSEXT_ERR_NOACK;
Emmanuel Hocdet65623372013-01-24 17:17:15 +01002394 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02002395
Willy Tarreau19d14ef2012-10-29 16:51:55 +01002396 for (i = 0; i < trash.size; i++) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02002397 if (!servername[i])
2398 break;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002399 trash.area[i] = tolower(servername[i]);
2400 if (!wildp && (trash.area[i] == '.'))
2401 wildp = &trash.area[i];
Emeric Brunfc0421f2012-09-07 17:30:07 +02002402 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002403 trash.area[i] = 0;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002404
William Lallemand150bfa82019-09-19 17:12:49 +02002405 HA_RWLOCK_RDLOCK(SNI_LOCK, &s->sni_lock);
Emeric Brunfc0421f2012-09-07 17:30:07 +02002406 /* lookup in full qualified names */
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002407 node = ebst_lookup(&s->sni_ctx, trash.area);
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002408
2409 /* lookup a not neg filter */
2410 for (n = node; n; n = ebmb_next_dup(n)) {
2411 if (!container_of(n, struct sni_ctx, name)->neg) {
2412 node = n;
2413 break;
Emmanuel Hocdet65623372013-01-24 17:17:15 +01002414 }
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002415 }
2416 if (!node && wildp) {
2417 /* lookup in wildcards names */
Emeric Brunfc0421f2012-09-07 17:30:07 +02002418 node = ebst_lookup(&s->sni_w_ctx, wildp);
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002419 }
2420 if (!node || container_of(node, struct sni_ctx, name)->neg) {
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002421#if (!defined SSL_NO_GENERATE_CERTIFICATES)
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002422 if (s->generate_certs && ssl_sock_generate_certificate(servername, s, ssl)) {
2423 /* switch ctx done in ssl_sock_generate_certificate */
William Lallemand150bfa82019-09-19 17:12:49 +02002424 HA_RWLOCK_RDUNLOCK(SNI_LOCK, &s->sni_lock);
Christopher Faulet31af49d2015-06-09 17:29:50 +02002425 return SSL_TLSEXT_ERR_OK;
2426 }
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002427#endif
William Lallemand150bfa82019-09-19 17:12:49 +02002428 HA_RWLOCK_RDUNLOCK(SNI_LOCK, &s->sni_lock);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002429 if (s->strict_sni)
2430 return SSL_TLSEXT_ERR_ALERT_FATAL;
2431 ssl_sock_switchctx_set(ssl, s->default_ctx);
2432 return SSL_TLSEXT_ERR_OK;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002433 }
2434
2435 /* switch ctx */
Emmanuel Hocdet530141f2017-03-01 18:54:56 +01002436 ssl_sock_switchctx_set(ssl, container_of(node, struct sni_ctx, name)->ctx);
William Lallemand150bfa82019-09-19 17:12:49 +02002437 HA_RWLOCK_RDUNLOCK(SNI_LOCK, &s->sni_lock);
Emeric Brunfc0421f2012-09-07 17:30:07 +02002438 return SSL_TLSEXT_ERR_OK;
2439}
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002440#endif /* (!) OPENSSL_IS_BORINGSSL */
Emeric Brunfc0421f2012-09-07 17:30:07 +02002441#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
2442
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002443#ifndef OPENSSL_NO_DH
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002444
2445static DH * ssl_get_dh_1024(void)
2446{
Remi Gacogned3a341a2015-05-29 16:26:17 +02002447 static unsigned char dh1024_p[]={
2448 0xFA,0xF9,0x2A,0x22,0x2A,0xA7,0x7F,0xE1,0x67,0x4E,0x53,0xF7,
2449 0x56,0x13,0xC3,0xB1,0xE3,0x29,0x6B,0x66,0x31,0x6A,0x7F,0xB3,
2450 0xC2,0x68,0x6B,0xCB,0x1D,0x57,0x39,0x1D,0x1F,0xFF,0x1C,0xC9,
2451 0xA6,0xA4,0x98,0x82,0x31,0x5D,0x25,0xFF,0x8A,0xE0,0x73,0x96,
2452 0x81,0xC8,0x83,0x79,0xC1,0x5A,0x04,0xF8,0x37,0x0D,0xA8,0x3D,
2453 0xAE,0x74,0xBC,0xDB,0xB6,0xA4,0x75,0xD9,0x71,0x8A,0xA0,0x17,
2454 0x9E,0x2D,0xC8,0xA8,0xDF,0x2C,0x5F,0x82,0x95,0xF8,0x92,0x9B,
2455 0xA7,0x33,0x5F,0x89,0x71,0xC8,0x2D,0x6B,0x18,0x86,0xC4,0x94,
2456 0x22,0xA5,0x52,0x8D,0xF6,0xF6,0xD2,0x37,0x92,0x0F,0xA5,0xCC,
2457 0xDB,0x7B,0x1D,0x3D,0xA1,0x31,0xB7,0x80,0x8F,0x0B,0x67,0x5E,
2458 0x36,0xA5,0x60,0x0C,0xF1,0x95,0x33,0x8B,
2459 };
2460 static unsigned char dh1024_g[]={
2461 0x02,
2462 };
2463
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002464 BIGNUM *p;
2465 BIGNUM *g;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002466 DH *dh = DH_new();
2467 if (dh) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002468 p = BN_bin2bn(dh1024_p, sizeof dh1024_p, NULL);
2469 g = BN_bin2bn(dh1024_g, sizeof dh1024_g, NULL);
Remi Gacogned3a341a2015-05-29 16:26:17 +02002470
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002471 if (!p || !g) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002472 DH_free(dh);
2473 dh = NULL;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002474 } else {
2475 DH_set0_pqg(dh, p, NULL, g);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002476 }
2477 }
2478 return dh;
2479}
2480
2481static DH *ssl_get_dh_2048(void)
2482{
Remi Gacogned3a341a2015-05-29 16:26:17 +02002483 static unsigned char dh2048_p[]={
2484 0xEC,0x86,0xF8,0x70,0xA0,0x33,0x16,0xEC,0x05,0x1A,0x73,0x59,
2485 0xCD,0x1F,0x8B,0xF8,0x29,0xE4,0xD2,0xCF,0x52,0xDD,0xC2,0x24,
2486 0x8D,0xB5,0x38,0x9A,0xFB,0x5C,0xA4,0xE4,0xB2,0xDA,0xCE,0x66,
2487 0x50,0x74,0xA6,0x85,0x4D,0x4B,0x1D,0x30,0xB8,0x2B,0xF3,0x10,
2488 0xE9,0xA7,0x2D,0x05,0x71,0xE7,0x81,0xDF,0x8B,0x59,0x52,0x3B,
2489 0x5F,0x43,0x0B,0x68,0xF1,0xDB,0x07,0xBE,0x08,0x6B,0x1B,0x23,
2490 0xEE,0x4D,0xCC,0x9E,0x0E,0x43,0xA0,0x1E,0xDF,0x43,0x8C,0xEC,
2491 0xBE,0xBE,0x90,0xB4,0x51,0x54,0xB9,0x2F,0x7B,0x64,0x76,0x4E,
2492 0x5D,0xD4,0x2E,0xAE,0xC2,0x9E,0xAE,0x51,0x43,0x59,0xC7,0x77,
2493 0x9C,0x50,0x3C,0x0E,0xED,0x73,0x04,0x5F,0xF1,0x4C,0x76,0x2A,
2494 0xD8,0xF8,0xCF,0xFC,0x34,0x40,0xD1,0xB4,0x42,0x61,0x84,0x66,
2495 0x42,0x39,0x04,0xF8,0x68,0xB2,0x62,0xD7,0x55,0xED,0x1B,0x74,
2496 0x75,0x91,0xE0,0xC5,0x69,0xC1,0x31,0x5C,0xDB,0x7B,0x44,0x2E,
2497 0xCE,0x84,0x58,0x0D,0x1E,0x66,0x0C,0xC8,0x44,0x9E,0xFD,0x40,
2498 0x08,0x67,0x5D,0xFB,0xA7,0x76,0x8F,0x00,0x11,0x87,0xE9,0x93,
2499 0xF9,0x7D,0xC4,0xBC,0x74,0x55,0x20,0xD4,0x4A,0x41,0x2F,0x43,
2500 0x42,0x1A,0xC1,0xF2,0x97,0x17,0x49,0x27,0x37,0x6B,0x2F,0x88,
2501 0x7E,0x1C,0xA0,0xA1,0x89,0x92,0x27,0xD9,0x56,0x5A,0x71,0xC1,
2502 0x56,0x37,0x7E,0x3A,0x9D,0x05,0xE7,0xEE,0x5D,0x8F,0x82,0x17,
2503 0xBC,0xE9,0xC2,0x93,0x30,0x82,0xF9,0xF4,0xC9,0xAE,0x49,0xDB,
2504 0xD0,0x54,0xB4,0xD9,0x75,0x4D,0xFA,0x06,0xB8,0xD6,0x38,0x41,
2505 0xB7,0x1F,0x77,0xF3,
2506 };
2507 static unsigned char dh2048_g[]={
2508 0x02,
2509 };
2510
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002511 BIGNUM *p;
2512 BIGNUM *g;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002513 DH *dh = DH_new();
2514 if (dh) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002515 p = BN_bin2bn(dh2048_p, sizeof dh2048_p, NULL);
2516 g = BN_bin2bn(dh2048_g, sizeof dh2048_g, NULL);
Remi Gacogned3a341a2015-05-29 16:26:17 +02002517
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002518 if (!p || !g) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002519 DH_free(dh);
2520 dh = NULL;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002521 } else {
2522 DH_set0_pqg(dh, p, NULL, g);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002523 }
2524 }
2525 return dh;
2526}
2527
2528static DH *ssl_get_dh_4096(void)
2529{
Remi Gacogned3a341a2015-05-29 16:26:17 +02002530 static unsigned char dh4096_p[]={
2531 0xDE,0x16,0x94,0xCD,0x99,0x58,0x07,0xF1,0xF7,0x32,0x96,0x11,
2532 0x04,0x82,0xD4,0x84,0x72,0x80,0x99,0x06,0xCA,0xF0,0xA3,0x68,
2533 0x07,0xCE,0x64,0x50,0xE7,0x74,0x45,0x20,0x80,0x5E,0x4D,0xAD,
2534 0xA5,0xB6,0xED,0xFA,0x80,0x6C,0x3B,0x35,0xC4,0x9A,0x14,0x6B,
2535 0x32,0xBB,0xFD,0x1F,0x17,0x8E,0xB7,0x1F,0xD6,0xFA,0x3F,0x7B,
2536 0xEE,0x16,0xA5,0x62,0x33,0x0D,0xED,0xBC,0x4E,0x58,0xE5,0x47,
2537 0x4D,0xE9,0xAB,0x8E,0x38,0xD3,0x6E,0x90,0x57,0xE3,0x22,0x15,
2538 0x33,0xBD,0xF6,0x43,0x45,0xB5,0x10,0x0A,0xBE,0x2C,0xB4,0x35,
2539 0xB8,0x53,0x8D,0xAD,0xFB,0xA7,0x1F,0x85,0x58,0x41,0x7A,0x79,
2540 0x20,0x68,0xB3,0xE1,0x3D,0x08,0x76,0xBF,0x86,0x0D,0x49,0xE3,
2541 0x82,0x71,0x8C,0xB4,0x8D,0x81,0x84,0xD4,0xE7,0xBE,0x91,0xDC,
2542 0x26,0x39,0x48,0x0F,0x35,0xC4,0xCA,0x65,0xE3,0x40,0x93,0x52,
2543 0x76,0x58,0x7D,0xDD,0x51,0x75,0xDC,0x69,0x61,0xBF,0x47,0x2C,
2544 0x16,0x68,0x2D,0xC9,0x29,0xD3,0xE6,0xC0,0x99,0x48,0xA0,0x9A,
2545 0xC8,0x78,0xC0,0x6D,0x81,0x67,0x12,0x61,0x3F,0x71,0xBA,0x41,
2546 0x1F,0x6C,0x89,0x44,0x03,0xBA,0x3B,0x39,0x60,0xAA,0x28,0x55,
2547 0x59,0xAE,0xB8,0xFA,0xCB,0x6F,0xA5,0x1A,0xF7,0x2B,0xDD,0x52,
2548 0x8A,0x8B,0xE2,0x71,0xA6,0x5E,0x7E,0xD8,0x2E,0x18,0xE0,0x66,
2549 0xDF,0xDD,0x22,0x21,0x99,0x52,0x73,0xA6,0x33,0x20,0x65,0x0E,
2550 0x53,0xE7,0x6B,0x9B,0xC5,0xA3,0x2F,0x97,0x65,0x76,0xD3,0x47,
2551 0x23,0x77,0x12,0xB6,0x11,0x7B,0x24,0xED,0xF1,0xEF,0xC0,0xE2,
2552 0xA3,0x7E,0x67,0x05,0x3E,0x96,0x4D,0x45,0xC2,0x18,0xD1,0x73,
2553 0x9E,0x07,0xF3,0x81,0x6E,0x52,0x63,0xF6,0x20,0x76,0xB9,0x13,
2554 0xD2,0x65,0x30,0x18,0x16,0x09,0x16,0x9E,0x8F,0xF1,0xD2,0x10,
2555 0x5A,0xD3,0xD4,0xAF,0x16,0x61,0xDA,0x55,0x2E,0x18,0x5E,0x14,
2556 0x08,0x54,0x2E,0x2A,0x25,0xA2,0x1A,0x9B,0x8B,0x32,0xA9,0xFD,
2557 0xC2,0x48,0x96,0xE1,0x80,0xCA,0xE9,0x22,0x17,0xBB,0xCE,0x3E,
2558 0x9E,0xED,0xC7,0xF1,0x1F,0xEC,0x17,0x21,0xDC,0x7B,0x82,0x48,
2559 0x8E,0xBB,0x4B,0x9D,0x5B,0x04,0x04,0xDA,0xDB,0x39,0xDF,0x01,
2560 0x40,0xC3,0xAA,0x26,0x23,0x89,0x75,0xC6,0x0B,0xD0,0xA2,0x60,
2561 0x6A,0xF1,0xCC,0x65,0x18,0x98,0x1B,0x52,0xD2,0x74,0x61,0xCC,
2562 0xBD,0x60,0xAE,0xA3,0xA0,0x66,0x6A,0x16,0x34,0x92,0x3F,0x41,
2563 0x40,0x31,0x29,0xC0,0x2C,0x63,0xB2,0x07,0x8D,0xEB,0x94,0xB8,
2564 0xE8,0x47,0x92,0x52,0x93,0x6A,0x1B,0x7E,0x1A,0x61,0xB3,0x1B,
2565 0xF0,0xD6,0x72,0x9B,0xF1,0xB0,0xAF,0xBF,0x3E,0x65,0xEF,0x23,
2566 0x1D,0x6F,0xFF,0x70,0xCD,0x8A,0x4C,0x8A,0xA0,0x72,0x9D,0xBE,
2567 0xD4,0xBB,0x24,0x47,0x4A,0x68,0xB5,0xF5,0xC6,0xD5,0x7A,0xCD,
2568 0xCA,0x06,0x41,0x07,0xAD,0xC2,0x1E,0xE6,0x54,0xA7,0xAD,0x03,
2569 0xD9,0x12,0xC1,0x9C,0x13,0xB1,0xC9,0x0A,0x43,0x8E,0x1E,0x08,
2570 0xCE,0x50,0x82,0x73,0x5F,0xA7,0x55,0x1D,0xD9,0x59,0xAC,0xB5,
2571 0xEA,0x02,0x7F,0x6C,0x5B,0x74,0x96,0x98,0x67,0x24,0xA3,0x0F,
2572 0x15,0xFC,0xA9,0x7D,0x3E,0x67,0xD1,0x70,0xF8,0x97,0xF3,0x67,
2573 0xC5,0x8C,0x88,0x44,0x08,0x02,0xC7,0x2B,
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002574 };
Remi Gacogned3a341a2015-05-29 16:26:17 +02002575 static unsigned char dh4096_g[]={
2576 0x02,
2577 };
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002578
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002579 BIGNUM *p;
2580 BIGNUM *g;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002581 DH *dh = DH_new();
2582 if (dh) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002583 p = BN_bin2bn(dh4096_p, sizeof dh4096_p, NULL);
2584 g = BN_bin2bn(dh4096_g, sizeof dh4096_g, NULL);
Remi Gacogned3a341a2015-05-29 16:26:17 +02002585
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002586 if (!p || !g) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002587 DH_free(dh);
2588 dh = NULL;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002589 } else {
2590 DH_set0_pqg(dh, p, NULL, g);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002591 }
2592 }
2593 return dh;
2594}
2595
2596/* Returns Diffie-Hellman parameters matching the private key length
Willy Tarreauef934602016-12-22 23:12:01 +01002597 but not exceeding global_ssl.default_dh_param */
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002598static DH *ssl_get_tmp_dh(SSL *ssl, int export, int keylen)
2599{
2600 DH *dh = NULL;
2601 EVP_PKEY *pkey = SSL_get_privatekey(ssl);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002602 int type;
2603
2604 type = pkey ? EVP_PKEY_base_id(pkey) : EVP_PKEY_NONE;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002605
2606 /* The keylen supplied by OpenSSL can only be 512 or 1024.
2607 See ssl3_send_server_key_exchange() in ssl/s3_srvr.c
2608 */
2609 if (type == EVP_PKEY_RSA || type == EVP_PKEY_DSA) {
2610 keylen = EVP_PKEY_bits(pkey);
2611 }
2612
Willy Tarreauef934602016-12-22 23:12:01 +01002613 if (keylen > global_ssl.default_dh_param) {
2614 keylen = global_ssl.default_dh_param;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002615 }
2616
Remi Gacogned3a341a2015-05-29 16:26:17 +02002617 if (keylen >= 4096) {
Remi Gacogne8de54152014-07-15 11:36:40 +02002618 dh = local_dh_4096;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002619 }
2620 else if (keylen >= 2048) {
Remi Gacogne8de54152014-07-15 11:36:40 +02002621 dh = local_dh_2048;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002622 }
2623 else {
Remi Gacogne8de54152014-07-15 11:36:40 +02002624 dh = local_dh_1024;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002625 }
2626
2627 return dh;
2628}
2629
Remi Gacogne47783ef2015-05-29 15:53:22 +02002630static DH * ssl_sock_get_dh_from_file(const char *filename)
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002631{
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002632 DH *dh = NULL;
Remi Gacogne47783ef2015-05-29 15:53:22 +02002633 BIO *in = BIO_new(BIO_s_file());
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002634
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002635 if (in == NULL)
2636 goto end;
2637
Remi Gacogne47783ef2015-05-29 15:53:22 +02002638 if (BIO_read_filename(in, filename) <= 0)
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002639 goto end;
2640
Remi Gacogne47783ef2015-05-29 15:53:22 +02002641 dh = PEM_read_bio_DHparams(in, NULL, NULL, NULL);
2642
2643end:
2644 if (in)
2645 BIO_free(in);
2646
Emeric Brune1b4ed42018-08-16 15:14:12 +02002647 ERR_clear_error();
2648
Remi Gacogne47783ef2015-05-29 15:53:22 +02002649 return dh;
2650}
2651
2652int ssl_sock_load_global_dh_param_from_file(const char *filename)
2653{
2654 global_dh = ssl_sock_get_dh_from_file(filename);
2655
2656 if (global_dh) {
2657 return 0;
2658 }
2659
2660 return -1;
2661}
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002662#endif
2663
William Lallemand9117de92019-10-04 00:29:42 +02002664/* Alloc and init a ckch_inst */
2665static struct ckch_inst *ckch_inst_new()
2666{
2667 struct ckch_inst *ckch_inst;
2668
2669 ckch_inst = calloc(1, sizeof *ckch_inst);
2670 if (ckch_inst)
2671 LIST_INIT(&ckch_inst->sni_ctx);
2672
2673 return ckch_inst;
2674}
2675
2676
2677/* This function allocates a sni_ctx and adds it to the ckch_inst */
William Lallemand1d29c742019-10-04 00:53:29 +02002678static int ckch_inst_add_cert_sni(SSL_CTX *ctx, struct ckch_inst *ckch_inst,
William Lallemand9117de92019-10-04 00:29:42 +02002679 struct bind_conf *s, struct ssl_bind_conf *conf,
2680 struct pkey_info kinfo, char *name, int order)
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002681{
2682 struct sni_ctx *sc;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002683 int wild = 0, neg = 0;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002684
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002685 if (*name == '!') {
2686 neg = 1;
2687 name++;
2688 }
2689 if (*name == '*') {
2690 wild = 1;
2691 name++;
2692 }
2693 /* !* filter is a nop */
2694 if (neg && wild)
2695 return order;
2696 if (*name) {
2697 int j, len;
2698 len = strlen(name);
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002699 for (j = 0; j < len && j < trash.size; j++)
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002700 trash.area[j] = tolower(name[j]);
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002701 if (j >= trash.size)
William Lallemandfe49bb32019-10-03 23:46:33 +02002702 return -1;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002703 trash.area[j] = 0;
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002704
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002705 sc = malloc(sizeof(struct sni_ctx) + len + 1);
Thierry FOURNIER / OZON.IO7a3bd3b2016-10-06 10:35:29 +02002706 if (!sc)
William Lallemandfe49bb32019-10-03 23:46:33 +02002707 return -1;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002708 memcpy(sc->name.key, trash.area, len + 1);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002709 sc->ctx = ctx;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01002710 sc->conf = conf;
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002711 sc->kinfo = kinfo;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002712 sc->order = order++;
2713 sc->neg = neg;
William Lallemand1d29c742019-10-04 00:53:29 +02002714 sc->wild = wild;
2715 sc->name.node.leaf_p = NULL;
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01002716 if (kinfo.sig != TLSEXT_signature_anonymous)
2717 SSL_CTX_set_ex_data(ctx, ssl_pkey_info_index, &sc->kinfo);
William Lallemand9117de92019-10-04 00:29:42 +02002718
William Lallemand1d29c742019-10-04 00:53:29 +02002719 LIST_ADDQ(&ckch_inst->sni_ctx, &sc->by_ckch_inst);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002720 }
2721 return order;
2722}
2723
William Lallemand6af03992019-07-23 15:00:54 +02002724/*
William Lallemand1d29c742019-10-04 00:53:29 +02002725 * Insert the sni_ctxs that are listed in the ckch_inst, in the bind_conf's sni_ctx tree
2726 * This function can't return an error.
2727 *
2728 * *CAUTION*: The caller must lock the sni tree if called in multithreading mode
2729 */
2730static void ssl_sock_load_cert_sni(struct ckch_inst *ckch_inst, struct bind_conf *bind_conf)
2731{
2732
2733 struct sni_ctx *sc0, *sc0b, *sc1;
2734 struct ebmb_node *node;
2735
2736 list_for_each_entry_safe(sc0, sc0b, &ckch_inst->sni_ctx, by_ckch_inst) {
2737
2738 /* ignore if sc0 was already inserted in a tree */
2739 if (sc0->name.node.leaf_p)
2740 continue;
2741
2742 /* Check for duplicates. */
2743 if (sc0->wild)
2744 node = ebst_lookup(&bind_conf->sni_w_ctx, (char *)sc0->name.key);
2745 else
2746 node = ebst_lookup(&bind_conf->sni_ctx, (char *)sc0->name.key);
2747
2748 for (; node; node = ebmb_next_dup(node)) {
2749 sc1 = ebmb_entry(node, struct sni_ctx, name);
2750 if (sc1->ctx == sc0->ctx && sc1->conf == sc0->conf
2751 && sc1->neg == sc0->neg && sc1->wild == sc0->wild) {
2752 /* it's a duplicate, we should remove and free it */
2753 LIST_DEL(&sc0->by_ckch_inst);
2754 free(sc0);
2755 sc0 = NULL;
William Lallemande15029b2019-10-14 10:46:58 +02002756 break;
William Lallemand1d29c742019-10-04 00:53:29 +02002757 }
2758 }
2759
2760 /* if duplicate, ignore the insertion */
2761 if (!sc0)
2762 continue;
2763
2764 if (sc0->wild)
2765 ebst_insert(&bind_conf->sni_w_ctx, &sc0->name);
2766 else
2767 ebst_insert(&bind_conf->sni_ctx, &sc0->name);
2768 }
2769}
2770
2771/*
William Lallemande3af8fb2019-10-08 11:36:53 +02002772 * tree used to store the ckchs ordered by filename/bundle name
William Lallemand6af03992019-07-23 15:00:54 +02002773 */
William Lallemande3af8fb2019-10-08 11:36:53 +02002774struct eb_root ckchs_tree = EB_ROOT_UNIQUE;
William Lallemand6af03992019-07-23 15:00:54 +02002775
William Lallemandfa892222019-07-23 16:06:08 +02002776
Emeric Brun7a883362019-10-17 13:27:40 +02002777/* Loads Diffie-Hellman parameter from a ckchs to an SSL_CTX.
2778 * If there is no DH paramater availaible in the ckchs, the global
2779 * DH parameter is loaded into the SSL_CTX and if there is no
2780 * DH parameter available in ckchs nor in global, the default
2781 * DH parameters are applied on the SSL_CTX.
2782 * Returns a bitfield containing the flags:
2783 * ERR_FATAL in any fatal error case
2784 * ERR_ALERT if a reason of the error is availabine in err
2785 * ERR_WARN if a warning is available into err
2786 * The value 0 means there is no error nor warning and
2787 * the operation succeed.
2788 */
William Lallemandfa892222019-07-23 16:06:08 +02002789#ifndef OPENSSL_NO_DH
Emeric Brun7a883362019-10-17 13:27:40 +02002790static int ssl_sock_load_dh_params(SSL_CTX *ctx, const struct cert_key_and_chain *ckch,
2791 const char *path, char **err)
William Lallemandfa892222019-07-23 16:06:08 +02002792{
Emeric Brun7a883362019-10-17 13:27:40 +02002793 int ret = 0;
William Lallemandfa892222019-07-23 16:06:08 +02002794 DH *dh = NULL;
2795
William Lallemanda8c73742019-07-31 18:31:34 +02002796 if (ckch && ckch->dh) {
William Lallemandfa892222019-07-23 16:06:08 +02002797 dh = ckch->dh;
Emeric Bruna9363eb2019-10-17 14:53:03 +02002798 if (!SSL_CTX_set_tmp_dh(ctx, dh)) {
2799 memprintf(err, "%sunable to load the DH parameter specified in '%s'",
2800 err && *err ? *err : "", path);
2801#if defined(SSL_CTX_set_dh_auto)
2802 SSL_CTX_set_dh_auto(ctx, 1);
2803 memprintf(err, "%s, SSL library will use an automatically generated DH parameter.\n",
2804 err && *err ? *err : "");
2805#else
2806 memprintf(err, "%s, DH ciphers won't be available.\n",
2807 err && *err ? *err : "");
2808#endif
2809 ret |= ERR_WARN;
2810 goto end;
2811 }
William Lallemandfa892222019-07-23 16:06:08 +02002812
2813 if (ssl_dh_ptr_index >= 0) {
2814 /* store a pointer to the DH params to avoid complaining about
2815 ssl-default-dh-param not being set for this SSL_CTX */
2816 SSL_CTX_set_ex_data(ctx, ssl_dh_ptr_index, dh);
2817 }
2818 }
2819 else if (global_dh) {
Emeric Bruna9363eb2019-10-17 14:53:03 +02002820 if (!SSL_CTX_set_tmp_dh(ctx, global_dh)) {
2821 memprintf(err, "%sunable to use the global DH parameter for certificate '%s'",
2822 err && *err ? *err : "", path);
2823#if defined(SSL_CTX_set_dh_auto)
2824 SSL_CTX_set_dh_auto(ctx, 1);
2825 memprintf(err, "%s, SSL library will use an automatically generated DH parameter.\n",
2826 err && *err ? *err : "");
2827#else
2828 memprintf(err, "%s, DH ciphers won't be available.\n",
2829 err && *err ? *err : "");
2830#endif
2831 ret |= ERR_WARN;
2832 goto end;
2833 }
William Lallemandfa892222019-07-23 16:06:08 +02002834 }
2835 else {
2836 /* Clear openssl global errors stack */
2837 ERR_clear_error();
2838
2839 if (global_ssl.default_dh_param <= 1024) {
2840 /* we are limited to DH parameter of 1024 bits anyway */
2841 if (local_dh_1024 == NULL)
2842 local_dh_1024 = ssl_get_dh_1024();
2843
Emeric Brun7a883362019-10-17 13:27:40 +02002844 if (local_dh_1024 == NULL) {
2845 memprintf(err, "%sunable to load default 1024 bits DH parameter for certificate '%s'.\n",
2846 err && *err ? *err : "", path);
2847 ret |= ERR_ALERT | ERR_FATAL;
William Lallemandfa892222019-07-23 16:06:08 +02002848 goto end;
Emeric Brun7a883362019-10-17 13:27:40 +02002849 }
William Lallemandfa892222019-07-23 16:06:08 +02002850
Emeric Bruna9363eb2019-10-17 14:53:03 +02002851 if (!SSL_CTX_set_tmp_dh(ctx, local_dh_1024)) {
2852 memprintf(err, "%sunable to load default 1024 bits DH parameter for certificate '%s'.\n",
2853 err && *err ? *err : "", path);
2854#if defined(SSL_CTX_set_dh_auto)
2855 SSL_CTX_set_dh_auto(ctx, 1);
2856 memprintf(err, "%s, SSL library will use an automatically generated DH parameter.\n",
2857 err && *err ? *err : "");
2858#else
2859 memprintf(err, "%s, DH ciphers won't be available.\n",
2860 err && *err ? *err : "");
2861#endif
2862 ret |= ERR_WARN;
2863 goto end;
2864 }
William Lallemandfa892222019-07-23 16:06:08 +02002865 }
2866 else {
2867 SSL_CTX_set_tmp_dh_callback(ctx, ssl_get_tmp_dh);
2868 }
William Lallemandfa892222019-07-23 16:06:08 +02002869 }
2870
2871end:
William Lallemandfa892222019-07-23 16:06:08 +02002872 return ret;
2873}
2874#endif
yanbzhu08ce6ab2015-12-02 13:01:29 -05002875
yanbzhu488a4d22015-12-01 15:16:07 -05002876/* Frees the contents of a cert_key_and_chain
2877 */
2878static void ssl_sock_free_cert_key_and_chain_contents(struct cert_key_and_chain *ckch)
2879{
yanbzhu488a4d22015-12-01 15:16:07 -05002880 if (!ckch)
2881 return;
2882
2883 /* Free the certificate and set pointer to NULL */
2884 if (ckch->cert)
2885 X509_free(ckch->cert);
2886 ckch->cert = NULL;
2887
2888 /* Free the key and set pointer to NULL */
2889 if (ckch->key)
2890 EVP_PKEY_free(ckch->key);
2891 ckch->key = NULL;
2892
2893 /* Free each certificate in the chain */
Emmanuel Hocdet9246f8b2018-11-30 16:00:21 +01002894 if (ckch->chain)
2895 sk_X509_pop_free(ckch->chain, X509_free);
2896 ckch->chain = NULL;
yanbzhu488a4d22015-12-01 15:16:07 -05002897
2898}
2899
2900/* checks if a key and cert exists in the ckch
2901 */
William Lallemand1633e392019-09-30 12:58:13 +02002902#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
yanbzhu488a4d22015-12-01 15:16:07 -05002903static int ssl_sock_is_ckch_valid(struct cert_key_and_chain *ckch)
2904{
2905 return (ckch->cert != NULL && ckch->key != NULL);
2906}
William Lallemand1633e392019-09-30 12:58:13 +02002907#endif
yanbzhu488a4d22015-12-01 15:16:07 -05002908
William Lallemandf11365b2019-09-19 14:25:58 +02002909/* Loads the contents of a crt file (path) or BIO into a cert_key_and_chain
2910 * This allows us to carry the contents of the file without having to read the
2911 * file multiple times. The caller must call
2912 * ssl_sock_free_cert_key_and_chain_contents.
yanbzhu488a4d22015-12-01 15:16:07 -05002913 *
2914 * returns:
2915 * 0 on Success
2916 * 1 on SSL Failure
yanbzhu488a4d22015-12-01 15:16:07 -05002917 */
William Lallemandf11365b2019-09-19 14:25:58 +02002918static int ssl_sock_load_crt_file_into_ckch(const char *path, BIO *buf, struct cert_key_and_chain *ckch, char **err)
yanbzhu488a4d22015-12-01 15:16:07 -05002919{
2920
William Lallemandf11365b2019-09-19 14:25:58 +02002921 BIO *in = NULL;
Emmanuel Hocdet9246f8b2018-11-30 16:00:21 +01002922 X509 *ca;
yanbzhu488a4d22015-12-01 15:16:07 -05002923 int ret = 1;
2924
William Lallemandf11365b2019-09-19 14:25:58 +02002925 if (buf != NULL && path != NULL) {
2926 in = buf;
2927 } else if (path != NULL) {
2928 in = BIO_new(BIO_s_file());
2929 if (in == NULL)
2930 goto end;
yanbzhu488a4d22015-12-01 15:16:07 -05002931
William Lallemandf11365b2019-09-19 14:25:58 +02002932 if (BIO_read_filename(in, path) <= 0)
2933 goto end;
2934 } else {
yanbzhu488a4d22015-12-01 15:16:07 -05002935 goto end;
William Lallemandf11365b2019-09-19 14:25:58 +02002936 }
yanbzhu488a4d22015-12-01 15:16:07 -05002937
yanbzhu488a4d22015-12-01 15:16:07 -05002938 /* Read Private Key */
2939 ckch->key = PEM_read_bio_PrivateKey(in, NULL, NULL, NULL);
2940 if (ckch->key == NULL) {
2941 memprintf(err, "%sunable to load private key from file '%s'.\n",
2942 err && *err ? *err : "", path);
2943 goto end;
2944 }
2945
Emmanuel Hocdet54227d82019-07-30 17:04:01 +02002946#ifndef OPENSSL_NO_DH
William Lallemandfa892222019-07-23 16:06:08 +02002947 /* Seek back to beginning of file */
2948 if (BIO_reset(in) == -1) {
2949 memprintf(err, "%san error occurred while reading the file '%s'.\n",
2950 err && *err ? *err : "", path);
2951 goto end;
2952 }
2953
2954 ckch->dh = PEM_read_bio_DHparams(in, NULL, NULL, NULL);
2955 /* no need to check for NULL there, dh is not mandatory */
Emmanuel Hocdet54227d82019-07-30 17:04:01 +02002956#endif
William Lallemandfa892222019-07-23 16:06:08 +02002957
Willy Tarreaubb137a82016-04-06 19:02:38 +02002958 /* Seek back to beginning of file */
Thierry FOURNIER / OZON.IOd44ea3f2016-10-14 00:49:21 +02002959 if (BIO_reset(in) == -1) {
2960 memprintf(err, "%san error occurred while reading the file '%s'.\n",
2961 err && *err ? *err : "", path);
2962 goto end;
2963 }
Willy Tarreaubb137a82016-04-06 19:02:38 +02002964
2965 /* Read Certificate */
2966 ckch->cert = PEM_read_bio_X509_AUX(in, NULL, NULL, NULL);
2967 if (ckch->cert == NULL) {
2968 memprintf(err, "%sunable to load certificate from file '%s'.\n",
Emmanuel Hocdet9246f8b2018-11-30 16:00:21 +01002969 err && *err ? *err : "", path);
Willy Tarreaubb137a82016-04-06 19:02:38 +02002970 goto end;
2971 }
2972
Emmanuel Hocdet03e09f32019-07-30 14:21:25 +02002973 if (!X509_check_private_key(ckch->cert, ckch->key)) {
2974 memprintf(err, "%sinconsistencies between private key and certificate loaded from PEM file '%s'.\n",
2975 err && *err ? *err : "", path);
2976 goto end;
2977 }
2978
yanbzhu488a4d22015-12-01 15:16:07 -05002979 /* Read Certificate Chain */
Emmanuel Hocdet9246f8b2018-11-30 16:00:21 +01002980 ckch->chain = sk_X509_new_null();
2981 while ((ca = PEM_read_bio_X509(in, NULL, NULL, NULL)))
2982 if (!sk_X509_push(ckch->chain, ca)) {
2983 X509_free(ca);
2984 goto end;
2985 }
yanbzhu488a4d22015-12-01 15:16:07 -05002986
yanbzhu488a4d22015-12-01 15:16:07 -05002987 ret = ERR_get_error();
2988 if (ret && (ERR_GET_LIB(ret) != ERR_LIB_PEM && ERR_GET_REASON(ret) != PEM_R_NO_START_LINE)) {
2989 memprintf(err, "%sunable to load certificate chain from file '%s'.\n",
2990 err && *err ? *err : "", path);
2991 ret = 1;
2992 goto end;
William Lallemand246c0242019-10-11 08:59:13 +02002993 }
2994
2995 ret = 0;
2996
2997 /* don't try to do the next operations if we feed the ckch from the cli */
2998 if (buf)
2999 goto end;
3000
3001 ERR_clear_error();
3002 if (in) {
3003 BIO_free(in);
3004 in = NULL;
yanbzhu488a4d22015-12-01 15:16:07 -05003005 }
William Lallemanda17f4112019-10-10 15:16:44 +02003006
3007#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
3008 /* try to load the sctl file */
3009 {
3010 char fp[MAXPATHLEN+1];
3011 struct stat st;
3012
3013 snprintf(fp, MAXPATHLEN+1, "%s.sctl", path);
3014 if (stat(fp, &st) == 0) {
3015 if (ssl_sock_load_sctl_from_file(fp, &ckch->sctl)) {
3016 memprintf(err, "%s '%s.sctl' is present but cannot be read or parsed'.\n",
3017 *err ? *err : "", fp);
3018 ret = 1;
3019 goto end;
3020 }
3021 }
3022 }
3023#endif
yanbzhu488a4d22015-12-01 15:16:07 -05003024
William Lallemand246c0242019-10-11 08:59:13 +02003025 /* try to load an ocsp response file */
3026 {
3027 char fp[MAXPATHLEN+1];
3028 struct stat st;
3029
3030 snprintf(fp, MAXPATHLEN+1, "%s.ocsp", path);
3031 if (stat(fp, &st) == 0) {
3032 if (ssl_sock_load_ocsp_response_from_file(fp, &ckch->ocsp_response, err)) {
3033 ret = 1;
3034 goto end;
3035 }
3036 }
3037 }
3038
3039 if (ckch->ocsp_response) {
3040 X509 *issuer;
3041 int i;
3042
3043 /* check if one of the certificate of the chain is the issuer */
3044 for (i = 0; i < sk_X509_num(ckch->chain); i++) {
3045 issuer = sk_X509_value(ckch->chain, i);
3046 if (X509_check_issued(issuer, ckch->cert) == X509_V_OK) {
3047 ckch->ocsp_issuer = issuer;
3048 break;
3049 } else
3050 issuer = NULL;
3051 }
3052
3053 /* if no issuer was found, try to load an issuer from the .issuer */
3054 if (!issuer) {
3055 struct stat st;
3056 char fp[MAXPATHLEN+1];
3057
3058 snprintf(fp, MAXPATHLEN+1, "%s.issuer", path);
3059 if (stat(fp, &st) == 0) {
3060 if (BIO_read_filename(in, fp) <= 0) {
William Lallemand786188f2019-10-15 10:05:37 +02003061 memprintf(err, "%s '%s' is present but cannot be read or parsed'.\n",
William Lallemand246c0242019-10-11 08:59:13 +02003062 *err ? *err : "", fp);
3063 ret = 1;
3064 goto end;
3065 }
3066
3067 issuer = PEM_read_bio_X509_AUX(in, NULL, NULL, NULL);
3068 if (!issuer) {
William Lallemand786188f2019-10-15 10:05:37 +02003069 memprintf(err, "%s '%s' is present but cannot be read or parsed'.\n",
William Lallemand246c0242019-10-11 08:59:13 +02003070 *err ? *err : "", fp);
3071 ret = 1;
3072 goto end;
3073 }
3074
3075 if (X509_check_issued(ckch->ocsp_issuer, ckch->cert) != X509_V_OK) {
William Lallemand786188f2019-10-15 10:05:37 +02003076 memprintf(err, "%s '%s' is not an issuer'.\n",
William Lallemand246c0242019-10-11 08:59:13 +02003077 *err ? *err : "", fp);
3078 ret = 1;
3079 goto end;
3080 }
3081 } else {
3082 memprintf(err, "%sNo issuer found, cannot use the OCSP response'.\n",
3083 *err ? *err : "");
3084 ret = 1;
3085 goto end;
3086 }
3087 }
3088 }
3089
yanbzhu488a4d22015-12-01 15:16:07 -05003090 ret = 0;
3091
3092end:
3093
3094 ERR_clear_error();
William Lallemandf11365b2019-09-19 14:25:58 +02003095 if (in && !buf)
yanbzhu488a4d22015-12-01 15:16:07 -05003096 BIO_free(in);
3097
3098 /* Something went wrong in one of the reads */
3099 if (ret != 0)
3100 ssl_sock_free_cert_key_and_chain_contents(ckch);
3101
3102 return ret;
3103}
3104
3105/* Loads the info in ckch into ctx
Emeric Bruna96b5822019-10-17 13:25:14 +02003106 * Returns a bitfield containing the flags:
3107 * ERR_FATAL in any fatal error case
3108 * ERR_ALERT if the reason of the error is available in err
3109 * ERR_WARN if a warning is available into err
3110 * The value 0 means there is no error nor warning and
3111 * the operation succeed.
yanbzhu488a4d22015-12-01 15:16:07 -05003112 */
3113static int ssl_sock_put_ckch_into_ctx(const char *path, const struct cert_key_and_chain *ckch, SSL_CTX *ctx, char **err)
3114{
Emeric Bruna96b5822019-10-17 13:25:14 +02003115 int errcode = 0;
3116
yanbzhu488a4d22015-12-01 15:16:07 -05003117 if (SSL_CTX_use_PrivateKey(ctx, ckch->key) <= 0) {
3118 memprintf(err, "%sunable to load SSL private key into SSL Context '%s'.\n",
3119 err && *err ? *err : "", path);
Emeric Bruna96b5822019-10-17 13:25:14 +02003120 errcode |= ERR_ALERT | ERR_FATAL;
3121 return errcode;
yanbzhu488a4d22015-12-01 15:16:07 -05003122 }
3123
3124 if (!SSL_CTX_use_certificate(ctx, ckch->cert)) {
3125 memprintf(err, "%sunable to load SSL certificate into SSL Context '%s'.\n",
3126 err && *err ? *err : "", path);
Emeric Bruna96b5822019-10-17 13:25:14 +02003127 errcode |= ERR_ALERT | ERR_FATAL;
3128 goto end;
yanbzhu488a4d22015-12-01 15:16:07 -05003129 }
3130
yanbzhu488a4d22015-12-01 15:16:07 -05003131 /* Load all certs in the ckch into the ctx_chain for the ssl_ctx */
Emmanuel Hocdet1c65fdd2018-12-03 18:07:44 +01003132#ifdef SSL_CTX_set1_chain
Emmanuel Hocdet9246f8b2018-11-30 16:00:21 +01003133 if (!SSL_CTX_set1_chain(ctx, ckch->chain)) {
3134 memprintf(err, "%sunable to load chain certificate into SSL Context '%s'. Make sure you are linking against Openssl >= 1.0.2.\n",
3135 err && *err ? *err : "", path);
Emeric Bruna96b5822019-10-17 13:25:14 +02003136 errcode |= ERR_ALERT | ERR_FATAL;
3137 goto end;
yanbzhu488a4d22015-12-01 15:16:07 -05003138 }
Emmanuel Hocdet1c65fdd2018-12-03 18:07:44 +01003139#else
3140 { /* legacy compat (< openssl 1.0.2) */
3141 X509 *ca;
3142 while ((ca = sk_X509_shift(ckch->chain)))
3143 if (!SSL_CTX_add_extra_chain_cert(ctx, ca)) {
3144 memprintf(err, "%sunable to load chain certificate into SSL Context '%s'.\n",
3145 err && *err ? *err : "", path);
3146 X509_free(ca);
Emeric Bruna96b5822019-10-17 13:25:14 +02003147 errcode |= ERR_ALERT | ERR_FATAL;
3148 goto end;
Emmanuel Hocdet1c65fdd2018-12-03 18:07:44 +01003149 }
3150 }
3151#endif
yanbzhu488a4d22015-12-01 15:16:07 -05003152
William Lallemandfa892222019-07-23 16:06:08 +02003153#ifndef OPENSSL_NO_DH
3154 /* store a NULL pointer to indicate we have not yet loaded
3155 a custom DH param file */
3156 if (ssl_dh_ptr_index >= 0) {
3157 SSL_CTX_set_ex_data(ctx, ssl_dh_ptr_index, NULL);
3158 }
3159
Emeric Brun7a883362019-10-17 13:27:40 +02003160 errcode |= ssl_sock_load_dh_params(ctx, ckch, path, err);
3161 if (errcode & ERR_CODE) {
William Lallemandfa892222019-07-23 16:06:08 +02003162 memprintf(err, "%sunable to load DH parameters from file '%s'.\n",
3163 err && *err ? *err : "", path);
Emeric Bruna96b5822019-10-17 13:25:14 +02003164 goto end;
William Lallemandfa892222019-07-23 16:06:08 +02003165 }
3166#endif
3167
William Lallemanda17f4112019-10-10 15:16:44 +02003168#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
3169 if (sctl_ex_index >= 0 && ckch->sctl) {
3170 if (ssl_sock_load_sctl(ctx, ckch->sctl) < 0) {
3171 memprintf(err, "%s '%s.sctl' is present but cannot be read or parsed'.\n",
3172 *err ? *err : "", path);
Emeric Bruna96b5822019-10-17 13:25:14 +02003173 errcode |= ERR_ALERT | ERR_FATAL;
3174 goto end;
William Lallemanda17f4112019-10-10 15:16:44 +02003175 }
3176 }
3177#endif
3178
William Lallemand4a660132019-10-14 14:51:41 +02003179#if ((defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP) || defined OPENSSL_IS_BORINGSSL)
William Lallemand246c0242019-10-11 08:59:13 +02003180 /* Load OCSP Info into context */
3181 if (ckch->ocsp_response) {
3182 if (ssl_sock_load_ocsp(ctx, ckch) < 0) {
3183 if (err)
3184 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",
3185 *err ? *err : "", path);
Emeric Bruna96b5822019-10-17 13:25:14 +02003186 errcode |= ERR_ALERT | ERR_FATAL;
3187 goto end;
William Lallemand246c0242019-10-11 08:59:13 +02003188 }
3189 }
William Lallemand246c0242019-10-11 08:59:13 +02003190#endif
3191
Emeric Bruna96b5822019-10-17 13:25:14 +02003192 end:
3193 return errcode;
yanbzhu488a4d22015-12-01 15:16:07 -05003194}
3195
William Lallemandc4ecddf2019-07-31 16:50:08 +02003196#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
yanbzhu08ce6ab2015-12-02 13:01:29 -05003197
William Lallemand28a8fce2019-10-04 17:36:55 +02003198static int ssl_sock_populate_sni_keytypes_hplr(const char *str, struct eb_root *sni_keytypes, int key_index)
yanbzhu08ce6ab2015-12-02 13:01:29 -05003199{
3200 struct sni_keytype *s_kt = NULL;
3201 struct ebmb_node *node;
3202 int i;
3203
3204 for (i = 0; i < trash.size; i++) {
3205 if (!str[i])
3206 break;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02003207 trash.area[i] = tolower(str[i]);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003208 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +02003209 trash.area[i] = 0;
3210 node = ebst_lookup(sni_keytypes, trash.area);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003211 if (!node) {
3212 /* CN not found in tree */
3213 s_kt = malloc(sizeof(struct sni_keytype) + i + 1);
3214 /* Using memcpy here instead of strncpy.
3215 * strncpy will cause sig_abrt errors under certain versions of gcc with -O2
3216 * See: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=60792
3217 */
William Lallemand28a8fce2019-10-04 17:36:55 +02003218 if (!s_kt)
3219 return -1;
3220
Willy Tarreau843b7cb2018-07-13 10:54:26 +02003221 memcpy(s_kt->name.key, trash.area, i+1);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003222 s_kt->keytypes = 0;
3223 ebst_insert(sni_keytypes, &s_kt->name);
3224 } else {
3225 /* CN found in tree */
3226 s_kt = container_of(node, struct sni_keytype, name);
3227 }
3228
3229 /* Mark that this CN has the keytype of key_index via keytypes mask */
3230 s_kt->keytypes |= 1<<key_index;
3231
William Lallemand28a8fce2019-10-04 17:36:55 +02003232 return 0;
3233
yanbzhu08ce6ab2015-12-02 13:01:29 -05003234}
3235
William Lallemandc4ecddf2019-07-31 16:50:08 +02003236#endif
3237
William Lallemand36b84632019-07-18 19:28:17 +02003238/*
William Lallemande3af8fb2019-10-08 11:36:53 +02003239 * lookup a path into the ckchs tree.
William Lallemand6af03992019-07-23 15:00:54 +02003240 */
William Lallemande3af8fb2019-10-08 11:36:53 +02003241static inline struct ckch_store *ckchs_lookup(char *path)
William Lallemand6af03992019-07-23 15:00:54 +02003242{
3243 struct ebmb_node *eb;
3244
William Lallemande3af8fb2019-10-08 11:36:53 +02003245 eb = ebst_lookup(&ckchs_tree, path);
William Lallemand6af03992019-07-23 15:00:54 +02003246 if (!eb)
3247 return NULL;
3248
William Lallemande3af8fb2019-10-08 11:36:53 +02003249 return ebmb_entry(eb, struct ckch_store, node);
William Lallemand6af03992019-07-23 15:00:54 +02003250}
3251
3252/*
William Lallemande3af8fb2019-10-08 11:36:53 +02003253 * This function allocate a ckch_store and populate it with certificates from files.
William Lallemand36b84632019-07-18 19:28:17 +02003254 */
William Lallemande3af8fb2019-10-08 11:36:53 +02003255static struct ckch_store *ckchs_load_cert_file(char *path, int multi, char **err)
William Lallemand36b84632019-07-18 19:28:17 +02003256{
William Lallemande3af8fb2019-10-08 11:36:53 +02003257 struct ckch_store *ckchs;
William Lallemand36b84632019-07-18 19:28:17 +02003258
William Lallemande3af8fb2019-10-08 11:36:53 +02003259 ckchs = calloc(1, sizeof(*ckchs) + strlen(path) + 1);
3260 if (!ckchs) {
William Lallemand36b84632019-07-18 19:28:17 +02003261 memprintf(err, "%sunable to allocate memory.\n", err && *err ? *err : "");
3262 goto end;
3263 }
William Lallemande3af8fb2019-10-08 11:36:53 +02003264 ckchs->ckch = calloc(1, sizeof(*ckchs->ckch) * (multi ? SSL_SOCK_NUM_KEYTYPES : 1));
William Lallemand36b84632019-07-18 19:28:17 +02003265
William Lallemande3af8fb2019-10-08 11:36:53 +02003266 if (!ckchs->ckch) {
William Lallemand36b84632019-07-18 19:28:17 +02003267 memprintf(err, "%sunable to allocate memory.\n", err && *err ? *err : "");
3268 goto end;
3269 }
3270
William Lallemand9117de92019-10-04 00:29:42 +02003271 LIST_INIT(&ckchs->ckch_inst);
3272
William Lallemand36b84632019-07-18 19:28:17 +02003273 if (!multi) {
3274
William Lallemandf11365b2019-09-19 14:25:58 +02003275 if (ssl_sock_load_crt_file_into_ckch(path, NULL, ckchs->ckch, err) == 1)
William Lallemand36b84632019-07-18 19:28:17 +02003276 goto end;
3277
William Lallemande3af8fb2019-10-08 11:36:53 +02003278 /* insert into the ckchs tree */
3279 memcpy(ckchs->path, path, strlen(path) + 1);
3280 ebst_insert(&ckchs_tree, &ckchs->node);
William Lallemand36b84632019-07-18 19:28:17 +02003281 } else {
3282 int found = 0;
William Lallemandc4ecddf2019-07-31 16:50:08 +02003283#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
3284 char fp[MAXPATHLEN+1] = {0};
3285 int n = 0;
William Lallemand36b84632019-07-18 19:28:17 +02003286
3287 /* Load all possible certs and keys */
3288 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
3289 struct stat buf;
3290 snprintf(fp, sizeof(fp), "%s.%s", path, SSL_SOCK_KEYTYPE_NAMES[n]);
3291 if (stat(fp, &buf) == 0) {
William Lallemandf11365b2019-09-19 14:25:58 +02003292 if (ssl_sock_load_crt_file_into_ckch(fp, NULL, &ckchs->ckch[n], err) == 1)
William Lallemand36b84632019-07-18 19:28:17 +02003293 goto end;
3294 found = 1;
William Lallemande3af8fb2019-10-08 11:36:53 +02003295 ckchs->multi = 1;
William Lallemand36b84632019-07-18 19:28:17 +02003296 }
3297 }
William Lallemandc4ecddf2019-07-31 16:50:08 +02003298#endif
William Lallemand36b84632019-07-18 19:28:17 +02003299
3300 if (!found) {
William Lallemand6e5f2ce2019-08-01 14:43:20 +02003301 memprintf(err, "%sDidn't find any certificate for bundle '%s'.\n", err && *err ? *err : "", path);
William Lallemand36b84632019-07-18 19:28:17 +02003302 goto end;
3303 }
William Lallemande3af8fb2019-10-08 11:36:53 +02003304 /* insert into the ckchs tree */
3305 memcpy(ckchs->path, path, strlen(path) + 1);
3306 ebst_insert(&ckchs_tree, &ckchs->node);
William Lallemand36b84632019-07-18 19:28:17 +02003307 }
William Lallemande3af8fb2019-10-08 11:36:53 +02003308 return ckchs;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003309
William Lallemand36b84632019-07-18 19:28:17 +02003310end:
William Lallemande3af8fb2019-10-08 11:36:53 +02003311 if (ckchs) {
3312 free(ckchs->ckch);
3313 ebmb_delete(&ckchs->node);
William Lallemand6af03992019-07-23 15:00:54 +02003314 }
3315
William Lallemande3af8fb2019-10-08 11:36:53 +02003316 free(ckchs);
William Lallemand36b84632019-07-18 19:28:17 +02003317
3318 return NULL;
3319}
3320
William Lallemandc4ecddf2019-07-31 16:50:08 +02003321#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
3322
William Lallemand36b84632019-07-18 19:28:17 +02003323/*
William Lallemande3af8fb2019-10-08 11:36:53 +02003324 * Take a ckch_store which contains a multi-certificate bundle.
William Lallemand36b84632019-07-18 19:28:17 +02003325 * Group these certificates into a set of SSL_CTX*
yanbzhu08ce6ab2015-12-02 13:01:29 -05003326 * based on shared and unique CN and SAN entries. Add these SSL_CTX* to the SNI tree.
3327 *
Joseph Herlant017b3da2018-11-15 09:07:59 -08003328 * This will allow the user to explicitly group multiple cert/keys for a single purpose
yanbzhu08ce6ab2015-12-02 13:01:29 -05003329 *
Emeric Brun054563d2019-10-17 13:16:58 +02003330 * Returns a bitfield containing the flags:
3331 * ERR_FATAL in any fatal error case
3332 * ERR_ALERT if the reason of the error is available in err
3333 * ERR_WARN if a warning is available into err
William Lallemand36b84632019-07-18 19:28:17 +02003334 *
3335 * TODO: This function shouldn't access files anymore, sctl and ocsp file access
3336 * should be migrated to the ssl_sock_load_crt_file_into_ckch() function
yanbzhu08ce6ab2015-12-02 13:01:29 -05003337 */
Emeric Brun054563d2019-10-17 13:16:58 +02003338static int ckch_inst_new_load_multi_store(const char *path, struct ckch_store *ckchs,
3339 struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
3340 char **sni_filter, int fcount, struct ckch_inst **ckchi, char **err)
yanbzhu08ce6ab2015-12-02 13:01:29 -05003341{
William Lallemand36b84632019-07-18 19:28:17 +02003342 int i = 0, n = 0;
3343 struct cert_key_and_chain *certs_and_keys;
William Lallemand4b989f22019-10-04 18:36:55 +02003344 struct eb_root sni_keytypes_map = EB_ROOT;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003345 struct ebmb_node *node;
3346 struct ebmb_node *next;
3347 /* Array of SSL_CTX pointers corresponding to each possible combo
3348 * of keytypes
3349 */
3350 struct key_combo_ctx key_combos[SSL_SOCK_POSSIBLE_KT_COMBOS] = { {0} };
Emeric Brun054563d2019-10-17 13:16:58 +02003351 int errcode = 0;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003352 X509_NAME *xname = NULL;
3353 char *str = NULL;
3354#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
3355 STACK_OF(GENERAL_NAME) *names = NULL;
3356#endif
William Lallemand614ca0d2019-10-07 13:52:11 +02003357 struct ckch_inst *ckch_inst;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003358
Emeric Brun054563d2019-10-17 13:16:58 +02003359 *ckchi = NULL;
3360
William Lallemande3af8fb2019-10-08 11:36:53 +02003361 if (!ckchs || !ckchs->ckch || !ckchs->multi) {
William Lallemand36b84632019-07-18 19:28:17 +02003362 memprintf(err, "%sunable to load SSL certificate file '%s' file does not exist.\n",
3363 err && *err ? *err : "", path);
Emeric Brun054563d2019-10-17 13:16:58 +02003364 return ERR_ALERT | ERR_FATAL;
William Lallemand614ca0d2019-10-07 13:52:11 +02003365 }
3366
3367 ckch_inst = ckch_inst_new();
3368 if (!ckch_inst) {
3369 memprintf(err, "%sunable to allocate SSL context for cert '%s'.\n",
3370 err && *err ? *err : "", path);
Emeric Brun054563d2019-10-17 13:16:58 +02003371 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemand614ca0d2019-10-07 13:52:11 +02003372 goto end;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003373 }
3374
William Lallemande3af8fb2019-10-08 11:36:53 +02003375 certs_and_keys = ckchs->ckch;
William Lallemand36b84632019-07-18 19:28:17 +02003376
William Lallemand150bfa82019-09-19 17:12:49 +02003377 /* at least one of the instances is using filters during the config
3378 * parsing, that's ok to inherit this during loading on CLI */
3379 ckchs->filters = !!fcount;
3380
yanbzhu08ce6ab2015-12-02 13:01:29 -05003381 /* Process each ckch and update keytypes for each CN/SAN
3382 * for example, if CN/SAN www.a.com is associated with
3383 * certs with keytype 0 and 2, then at the end of the loop,
3384 * www.a.com will have:
3385 * keyindex = 0 | 1 | 4 = 5
3386 */
3387 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
William Lallemand28a8fce2019-10-04 17:36:55 +02003388 int ret;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003389
3390 if (!ssl_sock_is_ckch_valid(&certs_and_keys[n]))
3391 continue;
3392
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003393 if (fcount) {
William Lallemand28a8fce2019-10-04 17:36:55 +02003394 for (i = 0; i < fcount; i++) {
3395 ret = ssl_sock_populate_sni_keytypes_hplr(sni_filter[i], &sni_keytypes_map, n);
3396 if (ret < 0) {
3397 memprintf(err, "%sunable to allocate SSL context.\n",
3398 err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02003399 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemand28a8fce2019-10-04 17:36:55 +02003400 goto end;
3401 }
3402 }
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003403 } else {
3404 /* A lot of the following code is OpenSSL boilerplate for processing CN's and SAN's,
3405 * so the line that contains logic is marked via comments
3406 */
3407 xname = X509_get_subject_name(certs_and_keys[n].cert);
3408 i = -1;
3409 while ((i = X509_NAME_get_index_by_NID(xname, NID_commonName, i)) != -1) {
3410 X509_NAME_ENTRY *entry = X509_NAME_get_entry(xname, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003411 ASN1_STRING *value;
3412 value = X509_NAME_ENTRY_get_data(entry);
3413 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003414 /* Important line is here */
William Lallemand28a8fce2019-10-04 17:36:55 +02003415 ret = ssl_sock_populate_sni_keytypes_hplr(str, &sni_keytypes_map, n);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003416
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003417 OPENSSL_free(str);
3418 str = NULL;
William Lallemand28a8fce2019-10-04 17:36:55 +02003419 if (ret < 0) {
3420 memprintf(err, "%sunable to allocate SSL context.\n",
3421 err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02003422 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemand28a8fce2019-10-04 17:36:55 +02003423 goto end;
3424 }
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003425 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003426 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003427
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003428 /* Do the above logic for each SAN */
yanbzhu08ce6ab2015-12-02 13:01:29 -05003429#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003430 names = X509_get_ext_d2i(certs_and_keys[n].cert, NID_subject_alt_name, NULL, NULL);
3431 if (names) {
3432 for (i = 0; i < sk_GENERAL_NAME_num(names); i++) {
3433 GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003434
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003435 if (name->type == GEN_DNS) {
3436 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
3437 /* Important line is here */
William Lallemand28a8fce2019-10-04 17:36:55 +02003438 ret = ssl_sock_populate_sni_keytypes_hplr(str, &sni_keytypes_map, n);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003439
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003440 OPENSSL_free(str);
3441 str = NULL;
William Lallemand28a8fce2019-10-04 17:36:55 +02003442 if (ret < 0) {
3443 memprintf(err, "%sunable to allocate SSL context.\n",
3444 err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02003445 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemand28a8fce2019-10-04 17:36:55 +02003446 goto end;
3447 }
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003448 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003449 }
3450 }
3451 }
3452 }
3453#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
3454 }
3455
3456 /* If no files found, return error */
3457 if (eb_is_empty(&sni_keytypes_map)) {
3458 memprintf(err, "%sunable to load SSL certificate file '%s' file does not exist.\n",
3459 err && *err ? *err : "", path);
Emeric Brun054563d2019-10-17 13:16:58 +02003460 errcode |= ERR_ALERT | ERR_FATAL;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003461 goto end;
3462 }
3463
3464 /* We now have a map of CN/SAN to keytypes that are loaded in
3465 * Iterate through the map to create the SSL_CTX's (if needed)
3466 * and add each CTX to the SNI tree
3467 *
3468 * Some math here:
Joseph Herlant017b3da2018-11-15 09:07:59 -08003469 * There are 2^n - 1 possible combinations, each unique
yanbzhu08ce6ab2015-12-02 13:01:29 -05003470 * combination is denoted by the key in the map. Each key
3471 * has a value between 1 and 2^n - 1. Conveniently, the array
3472 * of SSL_CTX* is sized 2^n. So, we can simply use the i'th
3473 * entry in the array to correspond to the unique combo (key)
3474 * associated with i. This unique key combo (i) will be associated
3475 * with combos[i-1]
3476 */
3477
3478 node = ebmb_first(&sni_keytypes_map);
3479 while (node) {
3480 SSL_CTX *cur_ctx;
Bertrand Jacquin33423092016-11-13 16:37:13 +00003481 char cur_file[MAXPATHLEN+1];
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003482 const struct pkey_info kinfo = { .sig = TLSEXT_signature_anonymous, .bits = 0 };
yanbzhu08ce6ab2015-12-02 13:01:29 -05003483
3484 str = (char *)container_of(node, struct sni_keytype, name)->name.key;
3485 i = container_of(node, struct sni_keytype, name)->keytypes;
3486 cur_ctx = key_combos[i-1].ctx;
3487
3488 if (cur_ctx == NULL) {
3489 /* need to create SSL_CTX */
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003490 cur_ctx = SSL_CTX_new(SSLv23_server_method());
yanbzhu08ce6ab2015-12-02 13:01:29 -05003491 if (cur_ctx == NULL) {
3492 memprintf(err, "%sunable to allocate SSL context.\n",
3493 err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02003494 errcode |= ERR_ALERT | ERR_FATAL;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003495 goto end;
3496 }
3497
yanbzhube2774d2015-12-10 15:07:30 -05003498 /* Load all required certs/keys/chains/OCSPs info into SSL_CTX */
yanbzhu08ce6ab2015-12-02 13:01:29 -05003499 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
3500 if (i & (1<<n)) {
3501 /* Key combo contains ckch[n] */
Bertrand Jacquin33423092016-11-13 16:37:13 +00003502 snprintf(cur_file, MAXPATHLEN+1, "%s.%s", path, SSL_SOCK_KEYTYPE_NAMES[n]);
Emeric Bruna96b5822019-10-17 13:25:14 +02003503 errcode |= ssl_sock_put_ckch_into_ctx(cur_file, &certs_and_keys[n], cur_ctx, err);
3504 if (errcode & ERR_CODE)
yanbzhu08ce6ab2015-12-02 13:01:29 -05003505 goto end;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003506 }
3507 }
3508
yanbzhu08ce6ab2015-12-02 13:01:29 -05003509 /* Update key_combos */
3510 key_combos[i-1].ctx = cur_ctx;
3511 }
3512
3513 /* Update SNI Tree */
William Lallemand9117de92019-10-04 00:29:42 +02003514
William Lallemand1d29c742019-10-04 00:53:29 +02003515 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 +02003516 kinfo, str, key_combos[i-1].order);
3517 if (key_combos[i-1].order < 0) {
3518 memprintf(err, "%sunable to create a sni context.\n", err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02003519 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemandfe49bb32019-10-03 23:46:33 +02003520 goto end;
3521 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003522 node = ebmb_next(node);
3523 }
3524
3525
3526 /* Mark a default context if none exists, using the ctx that has the most shared keys */
3527 if (!bind_conf->default_ctx) {
3528 for (i = SSL_SOCK_POSSIBLE_KT_COMBOS - 1; i >= 0; i--) {
3529 if (key_combos[i].ctx) {
3530 bind_conf->default_ctx = key_combos[i].ctx;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003531 bind_conf->default_ssl_conf = ssl_conf;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003532 break;
3533 }
3534 }
3535 }
3536
William Lallemand614ca0d2019-10-07 13:52:11 +02003537 ckch_inst->bind_conf = bind_conf;
William Lallemand150bfa82019-09-19 17:12:49 +02003538 ckch_inst->ssl_conf = ssl_conf;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003539end:
3540
3541 if (names)
3542 sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
3543
yanbzhu08ce6ab2015-12-02 13:01:29 -05003544 node = ebmb_first(&sni_keytypes_map);
3545 while (node) {
3546 next = ebmb_next(node);
3547 ebmb_delete(node);
William Lallemand8ed5b962019-10-04 17:24:39 +02003548 free(ebmb_entry(node, struct sni_keytype, name));
yanbzhu08ce6ab2015-12-02 13:01:29 -05003549 node = next;
3550 }
3551
Emeric Brun054563d2019-10-17 13:16:58 +02003552 if (errcode & ERR_CODE && ckch_inst) {
William Lallemand0c6d12f2019-10-04 18:38:51 +02003553 struct sni_ctx *sc0, *sc0b;
3554
3555 /* free the SSL_CTX in case of error */
3556 for (i = 0; i < SSL_SOCK_POSSIBLE_KT_COMBOS; i++) {
3557 if (key_combos[i].ctx)
3558 SSL_CTX_free(key_combos[i].ctx);
3559 }
3560
3561 /* free the sni_ctx in case of error */
3562 list_for_each_entry_safe(sc0, sc0b, &ckch_inst->sni_ctx, by_ckch_inst) {
3563
3564 ebmb_delete(&sc0->name);
3565 LIST_DEL(&sc0->by_ckch_inst);
3566 free(sc0);
3567 }
William Lallemand614ca0d2019-10-07 13:52:11 +02003568 free(ckch_inst);
3569 ckch_inst = NULL;
William Lallemand0c6d12f2019-10-04 18:38:51 +02003570 }
3571
Emeric Brun054563d2019-10-17 13:16:58 +02003572 *ckchi = ckch_inst;
3573 return errcode;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003574}
3575#else
3576/* This is a dummy, that just logs an error and returns error */
Emeric Brun054563d2019-10-17 13:16:58 +02003577static int ckch_inst_new_load_multi_store(const char *path, struct ckch_store *ckchs,
3578 struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
3579 char **sni_filter, int fcount, struct ckch_inst **ckchi, char **err)
yanbzhu08ce6ab2015-12-02 13:01:29 -05003580{
3581 memprintf(err, "%sunable to stat SSL certificate from file '%s' : %s.\n",
3582 err && *err ? *err : "", path, strerror(errno));
Emeric Brun054563d2019-10-17 13:16:58 +02003583 return ERR_ALERT | ERR_FATAL;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003584}
3585
Willy Tarreau9a1ab082019-05-09 13:26:41 +02003586#endif /* #if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL: Support for loading multiple certs into a single SSL_CTX */
yanbzhu488a4d22015-12-01 15:16:07 -05003587
William Lallemand614ca0d2019-10-07 13:52:11 +02003588/*
3589 * This function allocate a ckch_inst and create its snis
Emeric Brun054563d2019-10-17 13:16:58 +02003590 *
3591 * Returns a bitfield containing the flags:
3592 * ERR_FATAL in any fatal error case
3593 * ERR_ALERT if the reason of the error is available in err
3594 * ERR_WARN if a warning is available into err
William Lallemand614ca0d2019-10-07 13:52:11 +02003595 */
Emeric Brun054563d2019-10-17 13:16:58 +02003596static int ckch_inst_new_load_store(const char *path, struct ckch_store *ckchs, struct bind_conf *bind_conf,
3597 struct ssl_bind_conf *ssl_conf, char **sni_filter, int fcount, struct ckch_inst **ckchi, char **err)
Emeric Brunfc0421f2012-09-07 17:30:07 +02003598{
William Lallemandc9402072019-05-15 15:33:54 +02003599 SSL_CTX *ctx;
William Lallemandc9402072019-05-15 15:33:54 +02003600 int i;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003601 int order = 0;
3602 X509_NAME *xname;
3603 char *str;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003604 EVP_PKEY *pkey;
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003605 struct pkey_info kinfo = { .sig = TLSEXT_signature_anonymous, .bits = 0 };
Emeric Brunfc0421f2012-09-07 17:30:07 +02003606#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
3607 STACK_OF(GENERAL_NAME) *names;
3608#endif
William Lallemand36b84632019-07-18 19:28:17 +02003609 struct cert_key_and_chain *ckch;
William Lallemand614ca0d2019-10-07 13:52:11 +02003610 struct ckch_inst *ckch_inst = NULL;
Emeric Brun054563d2019-10-17 13:16:58 +02003611 int errcode = 0;
3612
3613 *ckchi = NULL;
William Lallemanda59191b2019-05-15 16:08:56 +02003614
William Lallemande3af8fb2019-10-08 11:36:53 +02003615 if (!ckchs || !ckchs->ckch)
Emeric Brun054563d2019-10-17 13:16:58 +02003616 return ERR_FATAL;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003617
William Lallemande3af8fb2019-10-08 11:36:53 +02003618 ckch = ckchs->ckch;
William Lallemand36b84632019-07-18 19:28:17 +02003619
William Lallemand150bfa82019-09-19 17:12:49 +02003620 /* at least one of the instances is using filters during the config
3621 * parsing, that's ok to inherit this during loading on CLI */
3622 ckchs->filters = !!fcount;
3623
William Lallemandc9402072019-05-15 15:33:54 +02003624 ctx = SSL_CTX_new(SSLv23_server_method());
3625 if (!ctx) {
3626 memprintf(err, "%sunable to allocate SSL context for cert '%s'.\n",
3627 err && *err ? *err : "", path);
Emeric Brun054563d2019-10-17 13:16:58 +02003628 errcode |= ERR_ALERT | ERR_FATAL;
3629 goto error;
William Lallemandc9402072019-05-15 15:33:54 +02003630 }
3631
Emeric Bruna96b5822019-10-17 13:25:14 +02003632 errcode |= ssl_sock_put_ckch_into_ctx(path, ckch, ctx, err);
3633 if (errcode & ERR_CODE)
William Lallemand614ca0d2019-10-07 13:52:11 +02003634 goto error;
William Lallemand614ca0d2019-10-07 13:52:11 +02003635
3636 ckch_inst = ckch_inst_new();
3637 if (!ckch_inst) {
3638 memprintf(err, "%sunable to allocate SSL context for cert '%s'.\n",
3639 err && *err ? *err : "", path);
Emeric Brun054563d2019-10-17 13:16:58 +02003640 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemandd9199372019-10-04 15:37:05 +02003641 goto error;
William Lallemandc9402072019-05-15 15:33:54 +02003642 }
3643
William Lallemand36b84632019-07-18 19:28:17 +02003644 pkey = X509_get_pubkey(ckch->cert);
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003645 if (pkey) {
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003646 kinfo.bits = EVP_PKEY_bits(pkey);
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003647 switch(EVP_PKEY_base_id(pkey)) {
3648 case EVP_PKEY_RSA:
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003649 kinfo.sig = TLSEXT_signature_rsa;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003650 break;
3651 case EVP_PKEY_EC:
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003652 kinfo.sig = TLSEXT_signature_ecdsa;
3653 break;
3654 case EVP_PKEY_DSA:
3655 kinfo.sig = TLSEXT_signature_dsa;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003656 break;
3657 }
3658 EVP_PKEY_free(pkey);
3659 }
3660
Emeric Brun50bcecc2013-04-22 13:05:23 +02003661 if (fcount) {
William Lallemandfe49bb32019-10-03 23:46:33 +02003662 while (fcount--) {
William Lallemand1d29c742019-10-04 00:53:29 +02003663 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 +02003664 if (order < 0) {
3665 memprintf(err, "%sunable to create a sni context.\n", err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02003666 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemandd9199372019-10-04 15:37:05 +02003667 goto error;
William Lallemandfe49bb32019-10-03 23:46:33 +02003668 }
3669 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003670 }
3671 else {
Emeric Brunfc0421f2012-09-07 17:30:07 +02003672#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
William Lallemand36b84632019-07-18 19:28:17 +02003673 names = X509_get_ext_d2i(ckch->cert, NID_subject_alt_name, NULL, NULL);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003674 if (names) {
3675 for (i = 0; i < sk_GENERAL_NAME_num(names); i++) {
3676 GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i);
3677 if (name->type == GEN_DNS) {
3678 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
William Lallemand1d29c742019-10-04 00:53:29 +02003679 order = ckch_inst_add_cert_sni(ctx, ckch_inst, bind_conf, ssl_conf, kinfo, str, order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003680 OPENSSL_free(str);
William Lallemandfe49bb32019-10-03 23:46:33 +02003681 if (order < 0) {
3682 memprintf(err, "%sunable to create a sni context.\n", err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02003683 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemandd9199372019-10-04 15:37:05 +02003684 goto error;
William Lallemandfe49bb32019-10-03 23:46:33 +02003685 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003686 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003687 }
3688 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003689 sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003690 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003691#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
William Lallemand36b84632019-07-18 19:28:17 +02003692 xname = X509_get_subject_name(ckch->cert);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003693 i = -1;
3694 while ((i = X509_NAME_get_index_by_NID(xname, NID_commonName, i)) != -1) {
3695 X509_NAME_ENTRY *entry = X509_NAME_get_entry(xname, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003696 ASN1_STRING *value;
3697
3698 value = X509_NAME_ENTRY_get_data(entry);
3699 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
William Lallemand1d29c742019-10-04 00:53:29 +02003700 order = ckch_inst_add_cert_sni(ctx, ckch_inst, bind_conf, ssl_conf, kinfo, str, order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003701 OPENSSL_free(str);
William Lallemandfe49bb32019-10-03 23:46:33 +02003702 if (order < 0) {
3703 memprintf(err, "%sunable to create a sni context.\n", err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02003704 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemandd9199372019-10-04 15:37:05 +02003705 goto error;
William Lallemandfe49bb32019-10-03 23:46:33 +02003706 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003707 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003708 }
3709 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003710 /* we must not free the SSL_CTX anymore below, since it's already in
3711 * the tree, so it will be discovered and cleaned in time.
3712 */
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02003713
Emeric Brunfc0421f2012-09-07 17:30:07 +02003714#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
Willy Tarreau2a65ff02012-09-13 17:54:29 +02003715 if (bind_conf->default_ctx) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02003716 memprintf(err, "%sthis version of openssl cannot load multiple SSL certificates.\n",
3717 err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02003718 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemandd9199372019-10-04 15:37:05 +02003719 goto error;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003720 }
3721#endif
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003722 if (!bind_conf->default_ctx) {
Willy Tarreau2a65ff02012-09-13 17:54:29 +02003723 bind_conf->default_ctx = ctx;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003724 bind_conf->default_ssl_conf = ssl_conf;
3725 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003726
William Lallemand9117de92019-10-04 00:29:42 +02003727 /* everything succeed, the ckch instance can be used */
3728 ckch_inst->bind_conf = bind_conf;
William Lallemand150bfa82019-09-19 17:12:49 +02003729 ckch_inst->ssl_conf = ssl_conf;
William Lallemand9117de92019-10-04 00:29:42 +02003730
Emeric Brun054563d2019-10-17 13:16:58 +02003731 *ckchi = ckch_inst;
3732 return errcode;
William Lallemandd9199372019-10-04 15:37:05 +02003733
3734error:
3735 /* free the allocated sni_ctxs */
William Lallemand614ca0d2019-10-07 13:52:11 +02003736 if (ckch_inst) {
William Lallemandd9199372019-10-04 15:37:05 +02003737 struct sni_ctx *sc0, *sc0b;
3738
3739 list_for_each_entry_safe(sc0, sc0b, &ckch_inst->sni_ctx, by_ckch_inst) {
3740
3741 ebmb_delete(&sc0->name);
3742 LIST_DEL(&sc0->by_ckch_inst);
3743 free(sc0);
3744 }
William Lallemand614ca0d2019-10-07 13:52:11 +02003745 free(ckch_inst);
3746 ckch_inst = NULL;
William Lallemandd9199372019-10-04 15:37:05 +02003747 }
3748 /* We only created 1 SSL_CTX so we can free it there */
3749 SSL_CTX_free(ctx);
3750
Emeric Brun054563d2019-10-17 13:16:58 +02003751 return errcode;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003752}
3753
Willy Tarreau8c5414a2019-10-16 17:06:25 +02003754/* Returns a set of ERR_* flags possibly with an error in <err>. */
William Lallemand614ca0d2019-10-07 13:52:11 +02003755static int ssl_sock_load_ckchs(const char *path, struct ckch_store *ckchs,
3756 struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
3757 char **sni_filter, int fcount, char **err)
3758{
3759 struct ckch_inst *ckch_inst = NULL;
Emeric Brun054563d2019-10-17 13:16:58 +02003760 int errcode = 0;
William Lallemand614ca0d2019-10-07 13:52:11 +02003761
3762 /* we found the ckchs in the tree, we can use it directly */
3763 if (ckchs->multi)
Emeric Brun054563d2019-10-17 13:16:58 +02003764 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 +02003765 else
Emeric Brun054563d2019-10-17 13:16:58 +02003766 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 +02003767
Emeric Brun054563d2019-10-17 13:16:58 +02003768 if (errcode & ERR_CODE)
3769 return errcode;
William Lallemand614ca0d2019-10-07 13:52:11 +02003770
3771 ssl_sock_load_cert_sni(ckch_inst, bind_conf);
3772
3773 /* succeed, add the instance to the ckch_store's list of instance */
3774 LIST_ADDQ(&ckchs->ckch_inst, &ckch_inst->by_ckchs);
Emeric Brun054563d2019-10-17 13:16:58 +02003775 return errcode;
William Lallemand614ca0d2019-10-07 13:52:11 +02003776}
3777
3778
Willy Tarreaubbc91962019-10-16 16:42:19 +02003779/* Returns a set of ERR_* flags possibly with an error in <err>. */
Willy Tarreau03209342016-12-22 17:08:28 +01003780int ssl_sock_load_cert(char *path, struct bind_conf *bind_conf, char **err)
Emeric Brunfc0421f2012-09-07 17:30:07 +02003781{
Cyril Bonté3180f7b2015-01-25 00:16:08 +01003782 struct dirent **de_list;
3783 int i, n;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003784 DIR *dir;
3785 struct stat buf;
Willy Tarreauee2663b2012-12-06 11:36:59 +01003786 char *end;
3787 char fp[MAXPATHLEN+1];
Emeric Brunfc0421f2012-09-07 17:30:07 +02003788 int cfgerr = 0;
William Lallemande3af8fb2019-10-08 11:36:53 +02003789 struct ckch_store *ckchs;
Willy Tarreau9a1ab082019-05-09 13:26:41 +02003790#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
yanbzhu63ea8462015-12-09 13:35:14 -05003791 int is_bundle;
3792 int j;
3793#endif
William Lallemande3af8fb2019-10-08 11:36:53 +02003794 if ((ckchs = ckchs_lookup(path))) {
William Lallemande3af8fb2019-10-08 11:36:53 +02003795 /* we found the ckchs in the tree, we can use it directly */
Willy Tarreau8c5414a2019-10-16 17:06:25 +02003796 return ssl_sock_load_ckchs(path, ckchs, bind_conf, NULL, NULL, 0, err);
William Lallemand6af03992019-07-23 15:00:54 +02003797 }
3798
yanbzhu08ce6ab2015-12-02 13:01:29 -05003799 if (stat(path, &buf) == 0) {
3800 dir = opendir(path);
William Lallemand36b84632019-07-18 19:28:17 +02003801 if (!dir) {
William Lallemande3af8fb2019-10-08 11:36:53 +02003802 ckchs = ckchs_load_cert_file(path, 0, err);
3803 if (!ckchs)
Willy Tarreaubbc91962019-10-16 16:42:19 +02003804 return ERR_ALERT | ERR_FATAL;
3805
Willy Tarreau8c5414a2019-10-16 17:06:25 +02003806 return ssl_sock_load_ckchs(path, ckchs, bind_conf, NULL, NULL, 0, err);
William Lallemand36b84632019-07-18 19:28:17 +02003807 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003808
yanbzhu08ce6ab2015-12-02 13:01:29 -05003809 /* strip trailing slashes, including first one */
3810 for (end = path + strlen(path) - 1; end >= path && *end == '/'; end--)
3811 *end = 0;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003812
yanbzhu08ce6ab2015-12-02 13:01:29 -05003813 n = scandir(path, &de_list, 0, alphasort);
3814 if (n < 0) {
3815 memprintf(err, "%sunable to scan directory '%s' : %s.\n",
3816 err && *err ? *err : "", path, strerror(errno));
Willy Tarreaubbc91962019-10-16 16:42:19 +02003817 cfgerr |= ERR_ALERT | ERR_FATAL;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003818 }
3819 else {
3820 for (i = 0; i < n; i++) {
3821 struct dirent *de = de_list[i];
Emeric Brun2aab7222014-06-18 18:15:09 +02003822
yanbzhu08ce6ab2015-12-02 13:01:29 -05003823 end = strrchr(de->d_name, '.');
3824 if (end && (!strcmp(end, ".issuer") || !strcmp(end, ".ocsp") || !strcmp(end, ".sctl")))
3825 goto ignore_entry;
Cyril Bonté3180f7b2015-01-25 00:16:08 +01003826
yanbzhu08ce6ab2015-12-02 13:01:29 -05003827 snprintf(fp, sizeof(fp), "%s/%s", path, de->d_name);
3828 if (stat(fp, &buf) != 0) {
3829 memprintf(err, "%sunable to stat SSL certificate from file '%s' : %s.\n",
3830 err && *err ? *err : "", fp, strerror(errno));
Willy Tarreaubbc91962019-10-16 16:42:19 +02003831 cfgerr |= ERR_ALERT | ERR_FATAL;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003832 goto ignore_entry;
3833 }
3834 if (!S_ISREG(buf.st_mode))
3835 goto ignore_entry;
yanbzhu63ea8462015-12-09 13:35:14 -05003836
Willy Tarreau9a1ab082019-05-09 13:26:41 +02003837#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
yanbzhu63ea8462015-12-09 13:35:14 -05003838 is_bundle = 0;
3839 /* Check if current entry in directory is part of a multi-cert bundle */
3840
3841 if (end) {
3842 for (j = 0; j < SSL_SOCK_NUM_KEYTYPES; j++) {
3843 if (!strcmp(end + 1, SSL_SOCK_KEYTYPE_NAMES[j])) {
3844 is_bundle = 1;
3845 break;
3846 }
3847 }
3848
3849 if (is_bundle) {
3850 char dp[MAXPATHLEN+1] = {0}; /* this will be the filename w/o the keytype */
3851 int dp_len;
3852
3853 dp_len = end - de->d_name;
3854 snprintf(dp, dp_len + 1, "%s", de->d_name);
3855
3856 /* increment i and free de until we get to a non-bundle cert
3857 * Note here that we look at de_list[i + 1] before freeing de
3858 * this is important since ignore_entry will free de
3859 */
3860 while (i + 1 < n && !strncmp(de_list[i + 1]->d_name, dp, dp_len)) {
3861 free(de);
3862 i++;
3863 de = de_list[i];
3864 }
3865
3866 snprintf(fp, sizeof(fp), "%s/%s", path, dp);
William Lallemande3af8fb2019-10-08 11:36:53 +02003867 if ((ckchs = ckchs_lookup(fp)) == NULL)
3868 ckchs = ckchs_load_cert_file(fp, 1, err);
3869 if (!ckchs)
Willy Tarreaubbc91962019-10-16 16:42:19 +02003870 cfgerr |= ERR_ALERT | ERR_FATAL;
Willy Tarreau8c5414a2019-10-16 17:06:25 +02003871 else
3872 cfgerr |= ssl_sock_load_ckchs(path, ckchs, bind_conf, NULL, NULL, 0, err);
yanbzhu63ea8462015-12-09 13:35:14 -05003873 /* Successfully processed the bundle */
3874 goto ignore_entry;
3875 }
3876 }
3877
3878#endif
William Lallemande3af8fb2019-10-08 11:36:53 +02003879 if ((ckchs = ckchs_lookup(fp)) == NULL)
3880 ckchs = ckchs_load_cert_file(fp, 0, err);
3881 if (!ckchs)
Willy Tarreaubbc91962019-10-16 16:42:19 +02003882 cfgerr |= ERR_ALERT | ERR_FATAL;
William Lallemand614ca0d2019-10-07 13:52:11 +02003883 else
Willy Tarreau8c5414a2019-10-16 17:06:25 +02003884 cfgerr |= ssl_sock_load_ckchs(path, ckchs, bind_conf, NULL, NULL, 0, err);
William Lallemand36b84632019-07-18 19:28:17 +02003885
yanbzhu08ce6ab2015-12-02 13:01:29 -05003886ignore_entry:
3887 free(de);
Cyril Bonté3180f7b2015-01-25 00:16:08 +01003888 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003889 free(de_list);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003890 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003891 closedir(dir);
3892 return cfgerr;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003893 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003894
William Lallemande3af8fb2019-10-08 11:36:53 +02003895 ckchs = ckchs_load_cert_file(path, 1, err);
3896 if (!ckchs)
Willy Tarreaubbc91962019-10-16 16:42:19 +02003897 return ERR_ALERT | ERR_FATAL;
3898
Willy Tarreau8c5414a2019-10-16 17:06:25 +02003899 cfgerr |= ssl_sock_load_ckchs(path, ckchs, bind_conf, NULL, NULL, 0, err);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003900
Emeric Brunfc0421f2012-09-07 17:30:07 +02003901 return cfgerr;
3902}
3903
Thierry Fournier383085f2013-01-24 14:15:43 +01003904/* Make sure openssl opens /dev/urandom before the chroot. The work is only
3905 * done once. Zero is returned if the operation fails. No error is returned
3906 * if the random is said as not implemented, because we expect that openssl
3907 * will use another method once needed.
3908 */
3909static int ssl_initialize_random()
3910{
3911 unsigned char random;
3912 static int random_initialized = 0;
3913
3914 if (!random_initialized && RAND_bytes(&random, 1) != 0)
3915 random_initialized = 1;
3916
3917 return random_initialized;
3918}
3919
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003920/* release ssl bind conf */
3921void ssl_sock_free_ssl_conf(struct ssl_bind_conf *conf)
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003922{
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003923 if (conf) {
Bernard Spil13c53f82018-02-15 13:34:58 +01003924#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003925 free(conf->npn_str);
3926 conf->npn_str = NULL;
3927#endif
3928#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
3929 free(conf->alpn_str);
3930 conf->alpn_str = NULL;
3931#endif
3932 free(conf->ca_file);
3933 conf->ca_file = NULL;
3934 free(conf->crl_file);
3935 conf->crl_file = NULL;
3936 free(conf->ciphers);
3937 conf->ciphers = NULL;
Emmanuel Hocdet839af572019-05-14 16:27:35 +02003938#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02003939 free(conf->ciphersuites);
3940 conf->ciphersuites = NULL;
3941#endif
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01003942 free(conf->curves);
3943 conf->curves = NULL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003944 free(conf->ecdhe);
3945 conf->ecdhe = NULL;
3946 }
3947}
3948
Willy Tarreaubbc91962019-10-16 16:42:19 +02003949/* Returns a set of ERR_* flags possibly with an error in <err>. */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003950int ssl_sock_load_cert_list_file(char *file, struct bind_conf *bind_conf, struct proxy *curproxy, char **err)
3951{
3952 char thisline[CRT_LINESIZE];
3953 char path[MAXPATHLEN+1];
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003954 FILE *f;
yanbzhu1b04e5b2015-12-02 13:54:14 -05003955 struct stat buf;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003956 int linenum = 0;
3957 int cfgerr = 0;
William Lallemande3af8fb2019-10-08 11:36:53 +02003958 struct ckch_store *ckchs;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003959
Willy Tarreauad1731d2013-04-02 17:35:58 +02003960 if ((f = fopen(file, "r")) == NULL) {
3961 memprintf(err, "cannot open file '%s' : %s", file, strerror(errno));
Willy Tarreaubbc91962019-10-16 16:42:19 +02003962 return ERR_ALERT | ERR_FATAL;
Willy Tarreauad1731d2013-04-02 17:35:58 +02003963 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003964
3965 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003966 int arg, newarg, cur_arg, i, ssl_b = 0, ssl_e = 0;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003967 char *end;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003968 char *args[MAX_CRT_ARGS + 1];
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003969 char *line = thisline;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003970 char *crt_path;
3971 struct ssl_bind_conf *ssl_conf = NULL;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003972
3973 linenum++;
3974 end = line + strlen(line);
3975 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
3976 /* Check if we reached the limit and the last char is not \n.
3977 * Watch out for the last line without the terminating '\n'!
3978 */
Willy Tarreauad1731d2013-04-02 17:35:58 +02003979 memprintf(err, "line %d too long in file '%s', limit is %d characters",
3980 linenum, file, (int)sizeof(thisline)-1);
Willy Tarreaubbc91962019-10-16 16:42:19 +02003981 cfgerr |= ERR_ALERT | ERR_FATAL;
Willy Tarreauad1731d2013-04-02 17:35:58 +02003982 break;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003983 }
3984
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003985 arg = 0;
Emeric Brun50bcecc2013-04-22 13:05:23 +02003986 newarg = 1;
3987 while (*line) {
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003988 if (*line == '#' || *line == '\n' || *line == '\r') {
3989 /* end of string, end of loop */
3990 *line = 0;
3991 break;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003992 } else if (isspace(*line)) {
Emeric Brun50bcecc2013-04-22 13:05:23 +02003993 newarg = 1;
3994 *line = 0;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003995 } else if (*line == '[') {
3996 if (ssl_b) {
3997 memprintf(err, "too many '[' on line %d in file '%s'.", linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02003998 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003999 break;
4000 }
4001 if (!arg) {
4002 memprintf(err, "file must start with a cert on line %d in file '%s'", linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004003 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004004 break;
4005 }
4006 ssl_b = arg;
4007 newarg = 1;
4008 *line = 0;
4009 } else if (*line == ']') {
4010 if (ssl_e) {
4011 memprintf(err, "too many ']' on line %d in file '%s'.", linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004012 cfgerr |= ERR_ALERT | ERR_FATAL;
Emeric Brun50bcecc2013-04-22 13:05:23 +02004013 break;
4014 }
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004015 if (!ssl_b) {
4016 memprintf(err, "missing '[' in line %d in file '%s'.", linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004017 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004018 break;
4019 }
4020 ssl_e = arg;
4021 newarg = 1;
4022 *line = 0;
4023 } else if (newarg) {
4024 if (arg == MAX_CRT_ARGS) {
4025 memprintf(err, "too many args on line %d in file '%s'.", linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004026 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004027 break;
4028 }
Emeric Brun50bcecc2013-04-22 13:05:23 +02004029 newarg = 0;
4030 args[arg++] = line;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004031 }
Emeric Brun50bcecc2013-04-22 13:05:23 +02004032 line++;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004033 }
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02004034 if (cfgerr)
4035 break;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004036 args[arg++] = line;
Willy Tarreauad1731d2013-04-02 17:35:58 +02004037
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004038 /* empty line */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004039 if (!*args[0])
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004040 continue;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004041
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004042 crt_path = args[0];
4043 if (*crt_path != '/' && global_ssl.crt_base) {
4044 if ((strlen(global_ssl.crt_base) + 1 + strlen(crt_path)) > MAXPATHLEN) {
4045 memprintf(err, "'%s' : path too long on line %d in file '%s'",
4046 crt_path, linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004047 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004048 break;
4049 }
4050 snprintf(path, sizeof(path), "%s/%s", global_ssl.crt_base, crt_path);
4051 crt_path = path;
4052 }
4053
4054 ssl_conf = calloc(1, sizeof *ssl_conf);
4055 cur_arg = ssl_b ? ssl_b : 1;
4056 while (cur_arg < ssl_e) {
4057 newarg = 0;
4058 for (i = 0; ssl_bind_kws[i].kw != NULL; i++) {
4059 if (strcmp(ssl_bind_kws[i].kw, args[cur_arg]) == 0) {
4060 newarg = 1;
Willy Tarreaubbc91962019-10-16 16:42:19 +02004061 cfgerr |= ssl_bind_kws[i].parse(args, cur_arg, curproxy, ssl_conf, err);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004062 if (cur_arg + 1 + ssl_bind_kws[i].skip > ssl_e) {
4063 memprintf(err, "ssl args out of '[]' for %s on line %d in file '%s'",
4064 args[cur_arg], linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004065 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004066 }
4067 cur_arg += 1 + ssl_bind_kws[i].skip;
4068 break;
4069 }
4070 }
4071 if (!cfgerr && !newarg) {
4072 memprintf(err, "unknown ssl keyword %s on line %d in file '%s'.",
4073 args[cur_arg], linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004074 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004075 break;
4076 }
4077 }
Willy Tarreaubbc91962019-10-16 16:42:19 +02004078
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004079 if (cfgerr) {
4080 ssl_sock_free_ssl_conf(ssl_conf);
4081 free(ssl_conf);
4082 ssl_conf = NULL;
4083 break;
4084 }
4085
William Lallemande3af8fb2019-10-08 11:36:53 +02004086 if ((ckchs = ckchs_lookup(crt_path)) == NULL) {
William Lallemandeed4bf22019-10-10 11:38:13 +02004087 if (stat(crt_path, &buf) == 0)
William Lallemande3af8fb2019-10-08 11:36:53 +02004088 ckchs = ckchs_load_cert_file(crt_path, 0, err);
Emmanuel Hocdet1503e052019-07-31 18:30:33 +02004089 else
William Lallemande3af8fb2019-10-08 11:36:53 +02004090 ckchs = ckchs_load_cert_file(crt_path, 1, err);
yanbzhu1b04e5b2015-12-02 13:54:14 -05004091 }
4092
Willy Tarreau8c5414a2019-10-16 17:06:25 +02004093 if (!ckchs)
Willy Tarreaubbc91962019-10-16 16:42:19 +02004094 cfgerr |= ERR_ALERT | ERR_FATAL;
Willy Tarreau8c5414a2019-10-16 17:06:25 +02004095 else
4096 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 +02004097
Willy Tarreauad1731d2013-04-02 17:35:58 +02004098 if (cfgerr) {
4099 memprintf(err, "error processing line %d in file '%s' : %s", linenum, file, *err);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004100 break;
Willy Tarreauad1731d2013-04-02 17:35:58 +02004101 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004102 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004103 fclose(f);
4104 return cfgerr;
4105}
4106
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004107/* Create an initial CTX used to start the SSL connection before switchctx */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004108static int
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004109ssl_sock_initial_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02004110{
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004111 SSL_CTX *ctx = NULL;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004112 long options =
Emeric Brunfc0421f2012-09-07 17:30:07 +02004113 SSL_OP_ALL | /* all known workarounds for bugs */
4114 SSL_OP_NO_SSLv2 |
4115 SSL_OP_NO_COMPRESSION |
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02004116 SSL_OP_SINGLE_DH_USE |
Emeric Brun2b58d042012-09-20 17:10:03 +02004117 SSL_OP_SINGLE_ECDH_USE |
Emeric Brun3c4bc6e2012-10-04 18:44:19 +02004118 SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION |
Lukas Tribus926594f2018-05-18 17:55:57 +02004119 SSL_OP_PRIORITIZE_CHACHA |
Emeric Brun3c4bc6e2012-10-04 18:44:19 +02004120 SSL_OP_CIPHER_SERVER_PREFERENCE;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004121 long mode =
Emeric Brunfc0421f2012-09-07 17:30:07 +02004122 SSL_MODE_ENABLE_PARTIAL_WRITE |
4123 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
Willy Tarreau396a1862014-11-13 14:06:52 +01004124 SSL_MODE_RELEASE_BUFFERS |
4125 SSL_MODE_SMALL_BUFFERS;
Emmanuel Hocdet43664762017-08-09 18:26:20 +02004126 struct tls_version_filter *conf_ssl_methods = &bind_conf->ssl_conf.ssl_methods;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004127 int i, min, max, hole;
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004128 int flags = MC_SSL_O_ALL;
4129 int cfgerr = 0;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004130
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004131 ctx = SSL_CTX_new(SSLv23_server_method());
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004132 bind_conf->initial_ctx = ctx;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004133
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004134 if (conf_ssl_methods->flags && (conf_ssl_methods->min || conf_ssl_methods->max))
Christopher Faulet767a84b2017-11-24 16:50:31 +01004135 ha_warning("Proxy '%s': no-sslv3/no-tlsv1x are ignored for bind '%s' at [%s:%d]. "
4136 "Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
4137 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004138 else
4139 flags = conf_ssl_methods->flags;
4140
Emmanuel Hocdetbd695fe2017-05-15 15:53:41 +02004141 min = conf_ssl_methods->min;
4142 max = conf_ssl_methods->max;
4143 /* start with TLSv10 to remove SSLv3 per default */
4144 if (!min && (!max || max >= CONF_TLSV10))
4145 min = CONF_TLSV10;
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004146 /* Real min and max should be determinate with configuration and openssl's capabilities */
Emmanuel Hocdetbd695fe2017-05-15 15:53:41 +02004147 if (min)
4148 flags |= (methodVersions[min].flag - 1);
4149 if (max)
4150 flags |= ~((methodVersions[max].flag << 1) - 1);
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004151 /* find min, max and holes */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004152 min = max = CONF_TLSV_NONE;
4153 hole = 0;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004154 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004155 /* version is in openssl && version not disable in configuration */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004156 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004157 if (min) {
4158 if (hole) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004159 ha_warning("Proxy '%s': SSL/TLS versions range not contiguous for bind '%s' at [%s:%d]. "
4160 "Hole find for %s. Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
4161 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line,
4162 methodVersions[hole].name);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004163 hole = 0;
4164 }
4165 max = i;
4166 }
4167 else {
4168 min = max = i;
4169 }
4170 }
4171 else {
4172 if (min)
4173 hole = i;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004174 }
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004175 if (!min) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004176 ha_alert("Proxy '%s': all SSL/TLS versions are disabled for bind '%s' at [%s:%d].\n",
4177 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004178 cfgerr += 1;
4179 }
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02004180 /* save real min/max in bind_conf */
4181 conf_ssl_methods->min = min;
4182 conf_ssl_methods->max = max;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004183
Willy Tarreau9a1ab082019-05-09 13:26:41 +02004184#if (HA_OPENSSL_VERSION_NUMBER < 0x1010000fL)
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004185 /* Keep force-xxx implementation as it is in older haproxy. It's a
Joseph Herlant017b3da2018-11-15 09:07:59 -08004186 precautionary measure to avoid any surprise with older openssl version. */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004187 if (min == max)
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004188 methodVersions[min].ctx_set_version(ctx, SET_SERVER);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004189 else
4190 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
4191 if (flags & methodVersions[i].flag)
4192 options |= methodVersions[i].option;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004193#else /* openssl >= 1.1.0 */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004194 /* set the max_version is required to cap TLS version or activate new TLS (v1.3) */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004195 methodVersions[min].ctx_set_version(ctx, SET_MIN);
4196 methodVersions[max].ctx_set_version(ctx, SET_MAX);
Emeric Brunfa5c5c82017-04-28 16:19:51 +02004197#endif
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004198
4199 if (bind_conf->ssl_options & BC_SSL_O_NO_TLS_TICKETS)
4200 options |= SSL_OP_NO_TICKET;
4201 if (bind_conf->ssl_options & BC_SSL_O_PREF_CLIE_CIPH)
4202 options &= ~SSL_OP_CIPHER_SERVER_PREFERENCE;
Dirkjan Bussink526894f2019-01-21 09:35:03 -08004203
4204#ifdef SSL_OP_NO_RENEGOTIATION
4205 options |= SSL_OP_NO_RENEGOTIATION;
4206#endif
4207
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004208 SSL_CTX_set_options(ctx, options);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004209
Willy Tarreau5db847a2019-05-09 14:13:35 +02004210#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004211 if (global_ssl.async)
4212 mode |= SSL_MODE_ASYNC;
4213#endif
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004214 SSL_CTX_set_mode(ctx, mode);
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004215 if (global_ssl.life_time)
4216 SSL_CTX_set_timeout(ctx, global_ssl.life_time);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004217
4218#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
4219#ifdef OPENSSL_IS_BORINGSSL
4220 SSL_CTX_set_select_certificate_cb(ctx, ssl_sock_switchctx_cbk);
4221 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_err_cbk);
Willy Tarreau5db847a2019-05-09 14:13:35 +02004222#elif (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Olivier Houchard51088ce2019-01-02 18:46:41 +01004223 if (bind_conf->ssl_conf.early_data) {
4224 SSL_CTX_set_options(ctx, SSL_OP_NO_ANTI_REPLAY);
4225 SSL_CTX_set_max_early_data(ctx, global.tune.bufsize - global.tune.maxrewrite);
4226 }
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02004227 SSL_CTX_set_client_hello_cb(ctx, ssl_sock_switchctx_cbk, NULL);
4228 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_err_cbk);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004229#else
4230 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_cbk);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004231#endif
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02004232 SSL_CTX_set_tlsext_servername_arg(ctx, bind_conf);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004233#endif
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004234 return cfgerr;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004235}
4236
William Lallemand4f45bb92017-10-30 20:08:51 +01004237
4238static inline void sh_ssl_sess_free_blocks(struct shared_block *first, struct shared_block *block)
4239{
4240 if (first == block) {
4241 struct sh_ssl_sess_hdr *sh_ssl_sess = (struct sh_ssl_sess_hdr *)first->data;
4242 if (first->len > 0)
4243 sh_ssl_sess_tree_delete(sh_ssl_sess);
4244 }
4245}
4246
4247/* return first block from sh_ssl_sess */
4248static inline struct shared_block *sh_ssl_sess_first_block(struct sh_ssl_sess_hdr *sh_ssl_sess)
4249{
4250 return (struct shared_block *)((unsigned char *)sh_ssl_sess - ((struct shared_block *)NULL)->data);
4251
4252}
4253
4254/* store a session into the cache
4255 * s_id : session id padded with zero to SSL_MAX_SSL_SESSION_ID_LENGTH
4256 * data: asn1 encoded session
4257 * data_len: asn1 encoded session length
4258 * Returns 1 id session was stored (else 0)
4259 */
4260static int sh_ssl_sess_store(unsigned char *s_id, unsigned char *data, int data_len)
4261{
4262 struct shared_block *first;
4263 struct sh_ssl_sess_hdr *sh_ssl_sess, *oldsh_ssl_sess;
4264
Frédéric Lécaille0bec8072018-10-22 17:55:57 +02004265 first = shctx_row_reserve_hot(ssl_shctx, NULL, data_len + sizeof(struct sh_ssl_sess_hdr));
William Lallemand4f45bb92017-10-30 20:08:51 +01004266 if (!first) {
4267 /* Could not retrieve enough free blocks to store that session */
4268 return 0;
4269 }
4270
4271 /* STORE the key in the first elem */
4272 sh_ssl_sess = (struct sh_ssl_sess_hdr *)first->data;
4273 memcpy(sh_ssl_sess->key_data, s_id, SSL_MAX_SSL_SESSION_ID_LENGTH);
4274 first->len = sizeof(struct sh_ssl_sess_hdr);
4275
4276 /* it returns the already existing node
4277 or current node if none, never returns null */
4278 oldsh_ssl_sess = sh_ssl_sess_tree_insert(sh_ssl_sess);
4279 if (oldsh_ssl_sess != sh_ssl_sess) {
4280 /* NOTE: Row couldn't be in use because we lock read & write function */
4281 /* release the reserved row */
4282 shctx_row_dec_hot(ssl_shctx, first);
4283 /* replace the previous session already in the tree */
4284 sh_ssl_sess = oldsh_ssl_sess;
4285 /* ignore the previous session data, only use the header */
4286 first = sh_ssl_sess_first_block(sh_ssl_sess);
4287 shctx_row_inc_hot(ssl_shctx, first);
4288 first->len = sizeof(struct sh_ssl_sess_hdr);
4289 }
4290
Frédéric Lécaille0bec8072018-10-22 17:55:57 +02004291 if (shctx_row_data_append(ssl_shctx, first, NULL, data, data_len) < 0) {
William Lallemand99b90af2018-01-03 19:15:51 +01004292 shctx_row_dec_hot(ssl_shctx, first);
William Lallemand4f45bb92017-10-30 20:08:51 +01004293 return 0;
William Lallemand99b90af2018-01-03 19:15:51 +01004294 }
4295
4296 shctx_row_dec_hot(ssl_shctx, first);
William Lallemand4f45bb92017-10-30 20:08:51 +01004297
4298 return 1;
4299}
William Lallemanded0b5ad2017-10-30 19:36:36 +01004300
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004301/* SSL callback used when a new session is created while connecting to a server */
4302static int ssl_sess_new_srv_cb(SSL *ssl, SSL_SESSION *sess)
4303{
Thierry FOURNIER28962c92018-06-17 21:37:05 +02004304 struct connection *conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Olivier Houcharde6060c52017-11-16 17:42:52 +01004305 struct server *s;
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004306
Willy Tarreau07d94e42018-09-20 10:57:52 +02004307 s = __objt_server(conn->target);
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004308
Olivier Houcharde6060c52017-11-16 17:42:52 +01004309 if (!(s->ssl_ctx.options & SRV_SSL_O_NO_REUSE)) {
4310 int len;
4311 unsigned char *ptr;
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004312
Olivier Houcharde6060c52017-11-16 17:42:52 +01004313 len = i2d_SSL_SESSION(sess, NULL);
4314 if (s->ssl_ctx.reused_sess[tid].ptr && s->ssl_ctx.reused_sess[tid].allocated_size >= len) {
4315 ptr = s->ssl_ctx.reused_sess[tid].ptr;
4316 } else {
4317 free(s->ssl_ctx.reused_sess[tid].ptr);
4318 ptr = s->ssl_ctx.reused_sess[tid].ptr = malloc(len);
4319 s->ssl_ctx.reused_sess[tid].allocated_size = len;
4320 }
4321 if (s->ssl_ctx.reused_sess[tid].ptr) {
4322 s->ssl_ctx.reused_sess[tid].size = i2d_SSL_SESSION(sess,
4323 &ptr);
4324 }
4325 } else {
4326 free(s->ssl_ctx.reused_sess[tid].ptr);
4327 s->ssl_ctx.reused_sess[tid].ptr = NULL;
4328 }
4329
4330 return 0;
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004331}
4332
Olivier Houcharde6060c52017-11-16 17:42:52 +01004333
William Lallemanded0b5ad2017-10-30 19:36:36 +01004334/* SSL callback used on new session creation */
William Lallemand4f45bb92017-10-30 20:08:51 +01004335int sh_ssl_sess_new_cb(SSL *ssl, SSL_SESSION *sess)
William Lallemanded0b5ad2017-10-30 19:36:36 +01004336{
4337 unsigned char encsess[SHSESS_MAX_DATA_LEN]; /* encoded session */
4338 unsigned char encid[SSL_MAX_SSL_SESSION_ID_LENGTH]; /* encoded id */
4339 unsigned char *p;
4340 int data_len;
4341 unsigned int sid_length, sid_ctx_length;
4342 const unsigned char *sid_data;
4343 const unsigned char *sid_ctx_data;
4344
4345 /* Session id is already stored in to key and session id is known
4346 * so we dont store it to keep size.
4347 */
4348
4349 sid_data = SSL_SESSION_get_id(sess, &sid_length);
4350 sid_ctx_data = SSL_SESSION_get0_id_context(sess, &sid_ctx_length);
4351 SSL_SESSION_set1_id(sess, sid_data, 0);
4352 SSL_SESSION_set1_id_context(sess, sid_ctx_data, 0);
4353
4354 /* check if buffer is large enough for the ASN1 encoded session */
4355 data_len = i2d_SSL_SESSION(sess, NULL);
4356 if (data_len > SHSESS_MAX_DATA_LEN)
4357 goto err;
4358
4359 p = encsess;
4360
4361 /* process ASN1 session encoding before the lock */
4362 i2d_SSL_SESSION(sess, &p);
4363
4364 memcpy(encid, sid_data, sid_length);
4365 if (sid_length < SSL_MAX_SSL_SESSION_ID_LENGTH)
4366 memset(encid + sid_length, 0, SSL_MAX_SSL_SESSION_ID_LENGTH-sid_length);
4367
William Lallemanda3c77cf2017-10-30 23:44:40 +01004368 shctx_lock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004369 /* store to cache */
William Lallemand4f45bb92017-10-30 20:08:51 +01004370 sh_ssl_sess_store(encid, encsess, data_len);
William Lallemanda3c77cf2017-10-30 23:44:40 +01004371 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004372err:
4373 /* reset original length values */
4374 SSL_SESSION_set1_id(sess, sid_data, sid_length);
4375 SSL_SESSION_set1_id_context(sess, sid_ctx_data, sid_ctx_length);
4376
4377 return 0; /* do not increment session reference count */
4378}
4379
4380/* SSL callback used on lookup an existing session cause none found in internal cache */
William Lallemand4f45bb92017-10-30 20:08:51 +01004381SSL_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 +01004382{
William Lallemand4f45bb92017-10-30 20:08:51 +01004383 struct sh_ssl_sess_hdr *sh_ssl_sess;
William Lallemanded0b5ad2017-10-30 19:36:36 +01004384 unsigned char data[SHSESS_MAX_DATA_LEN], *p;
4385 unsigned char tmpkey[SSL_MAX_SSL_SESSION_ID_LENGTH];
William Lallemanded0b5ad2017-10-30 19:36:36 +01004386 SSL_SESSION *sess;
William Lallemand4f45bb92017-10-30 20:08:51 +01004387 struct shared_block *first;
William Lallemanded0b5ad2017-10-30 19:36:36 +01004388
4389 global.shctx_lookups++;
4390
4391 /* allow the session to be freed automatically by openssl */
4392 *do_copy = 0;
4393
4394 /* tree key is zeros padded sessionid */
4395 if (key_len < SSL_MAX_SSL_SESSION_ID_LENGTH) {
4396 memcpy(tmpkey, key, key_len);
4397 memset(tmpkey + key_len, 0, SSL_MAX_SSL_SESSION_ID_LENGTH - key_len);
4398 key = tmpkey;
4399 }
4400
4401 /* lock cache */
William Lallemanda3c77cf2017-10-30 23:44:40 +01004402 shctx_lock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004403
4404 /* lookup for session */
William Lallemand4f45bb92017-10-30 20:08:51 +01004405 sh_ssl_sess = sh_ssl_sess_tree_lookup(key);
4406 if (!sh_ssl_sess) {
William Lallemanded0b5ad2017-10-30 19:36:36 +01004407 /* no session found: unlock cache and exit */
William Lallemanda3c77cf2017-10-30 23:44:40 +01004408 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004409 global.shctx_misses++;
4410 return NULL;
4411 }
4412
William Lallemand4f45bb92017-10-30 20:08:51 +01004413 /* sh_ssl_sess (shared_block->data) is at the end of shared_block */
4414 first = sh_ssl_sess_first_block(sh_ssl_sess);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004415
William Lallemand4f45bb92017-10-30 20:08:51 +01004416 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 +01004417
William Lallemanda3c77cf2017-10-30 23:44:40 +01004418 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004419
4420 /* decode ASN1 session */
4421 p = data;
William Lallemand4f45bb92017-10-30 20:08:51 +01004422 sess = d2i_SSL_SESSION(NULL, (const unsigned char **)&p, first->len-sizeof(struct sh_ssl_sess_hdr));
William Lallemanded0b5ad2017-10-30 19:36:36 +01004423 /* Reset session id and session id contenxt */
4424 if (sess) {
4425 SSL_SESSION_set1_id(sess, key, key_len);
4426 SSL_SESSION_set1_id_context(sess, (const unsigned char *)SHCTX_APPNAME, strlen(SHCTX_APPNAME));
4427 }
4428
4429 return sess;
4430}
4431
William Lallemand4f45bb92017-10-30 20:08:51 +01004432
William Lallemanded0b5ad2017-10-30 19:36:36 +01004433/* SSL callback used to signal session is no more used in internal cache */
William Lallemand4f45bb92017-10-30 20:08:51 +01004434void sh_ssl_sess_remove_cb(SSL_CTX *ctx, SSL_SESSION *sess)
William Lallemanded0b5ad2017-10-30 19:36:36 +01004435{
William Lallemand4f45bb92017-10-30 20:08:51 +01004436 struct sh_ssl_sess_hdr *sh_ssl_sess;
William Lallemanded0b5ad2017-10-30 19:36:36 +01004437 unsigned char tmpkey[SSL_MAX_SSL_SESSION_ID_LENGTH];
4438 unsigned int sid_length;
4439 const unsigned char *sid_data;
4440 (void)ctx;
4441
4442 sid_data = SSL_SESSION_get_id(sess, &sid_length);
4443 /* tree key is zeros padded sessionid */
4444 if (sid_length < SSL_MAX_SSL_SESSION_ID_LENGTH) {
4445 memcpy(tmpkey, sid_data, sid_length);
4446 memset(tmpkey+sid_length, 0, SSL_MAX_SSL_SESSION_ID_LENGTH - sid_length);
4447 sid_data = tmpkey;
4448 }
4449
William Lallemanda3c77cf2017-10-30 23:44:40 +01004450 shctx_lock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004451
4452 /* lookup for session */
William Lallemand4f45bb92017-10-30 20:08:51 +01004453 sh_ssl_sess = sh_ssl_sess_tree_lookup(sid_data);
4454 if (sh_ssl_sess) {
William Lallemanded0b5ad2017-10-30 19:36:36 +01004455 /* free session */
William Lallemand4f45bb92017-10-30 20:08:51 +01004456 sh_ssl_sess_tree_delete(sh_ssl_sess);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004457 }
4458
4459 /* unlock cache */
William Lallemanda3c77cf2017-10-30 23:44:40 +01004460 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004461}
4462
4463/* Set session cache mode to server and disable openssl internal cache.
4464 * Set shared cache callbacks on an ssl context.
4465 * Shared context MUST be firstly initialized */
William Lallemand4f45bb92017-10-30 20:08:51 +01004466void ssl_set_shctx(SSL_CTX *ctx)
William Lallemanded0b5ad2017-10-30 19:36:36 +01004467{
4468 SSL_CTX_set_session_id_context(ctx, (const unsigned char *)SHCTX_APPNAME, strlen(SHCTX_APPNAME));
4469
4470 if (!ssl_shctx) {
4471 SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF);
4472 return;
4473 }
4474
4475 SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_SERVER |
4476 SSL_SESS_CACHE_NO_INTERNAL |
4477 SSL_SESS_CACHE_NO_AUTO_CLEAR);
4478
4479 /* Set callbacks */
William Lallemand4f45bb92017-10-30 20:08:51 +01004480 SSL_CTX_sess_set_new_cb(ctx, sh_ssl_sess_new_cb);
4481 SSL_CTX_sess_set_get_cb(ctx, sh_ssl_sess_get_cb);
4482 SSL_CTX_sess_set_remove_cb(ctx, sh_ssl_sess_remove_cb);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004483}
4484
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004485int ssl_sock_prepare_ctx(struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf, SSL_CTX *ctx)
4486{
4487 struct proxy *curproxy = bind_conf->frontend;
4488 int cfgerr = 0;
4489 int verify = SSL_VERIFY_NONE;
Willy Tarreau5d4cafb2018-01-04 18:55:19 +01004490 struct ssl_bind_conf __maybe_unused *ssl_conf_cur;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004491 const char *conf_ciphers;
Emmanuel Hocdet839af572019-05-14 16:27:35 +02004492#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02004493 const char *conf_ciphersuites;
4494#endif
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004495 const char *conf_curves = NULL;
Emeric Brunfc0421f2012-09-07 17:30:07 +02004496
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02004497 if (ssl_conf) {
4498 struct tls_version_filter *conf_ssl_methods = &ssl_conf->ssl_methods;
4499 int i, min, max;
4500 int flags = MC_SSL_O_ALL;
4501
4502 /* Real min and max should be determinate with configuration and openssl's capabilities */
Emmanuel Hocdet43664762017-08-09 18:26:20 +02004503 min = conf_ssl_methods->min ? conf_ssl_methods->min : bind_conf->ssl_conf.ssl_methods.min;
4504 max = conf_ssl_methods->max ? conf_ssl_methods->max : bind_conf->ssl_conf.ssl_methods.max;
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02004505 if (min)
4506 flags |= (methodVersions[min].flag - 1);
4507 if (max)
4508 flags |= ~((methodVersions[max].flag << 1) - 1);
4509 min = max = CONF_TLSV_NONE;
4510 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
4511 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
4512 if (min)
4513 max = i;
4514 else
4515 min = max = i;
4516 }
4517 /* save real min/max */
4518 conf_ssl_methods->min = min;
4519 conf_ssl_methods->max = max;
4520 if (!min) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004521 ha_alert("Proxy '%s': all SSL/TLS versions are disabled for bind '%s' at [%s:%d].\n",
4522 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02004523 cfgerr += 1;
4524 }
4525 }
4526
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004527 switch ((ssl_conf && ssl_conf->verify) ? ssl_conf->verify : bind_conf->ssl_conf.verify) {
Emeric Brun850efd52014-01-29 12:24:34 +01004528 case SSL_SOCK_VERIFY_NONE:
4529 verify = SSL_VERIFY_NONE;
4530 break;
4531 case SSL_SOCK_VERIFY_OPTIONAL:
4532 verify = SSL_VERIFY_PEER;
4533 break;
4534 case SSL_SOCK_VERIFY_REQUIRED:
4535 verify = SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
4536 break;
4537 }
4538 SSL_CTX_set_verify(ctx, verify, ssl_sock_bind_verifycbk);
4539 if (verify & SSL_VERIFY_PEER) {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004540 char *ca_file = (ssl_conf && ssl_conf->ca_file) ? ssl_conf->ca_file : bind_conf->ssl_conf.ca_file;
4541 char *crl_file = (ssl_conf && ssl_conf->crl_file) ? ssl_conf->crl_file : bind_conf->ssl_conf.crl_file;
4542 if (ca_file) {
Emeric Brund94b3fe2012-09-20 18:23:56 +02004543 /* load CAfile to verify */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004544 if (!SSL_CTX_load_verify_locations(ctx, ca_file, NULL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004545 ha_alert("Proxy '%s': unable to load CA file '%s' for bind '%s' at [%s:%d].\n",
4546 curproxy->id, ca_file, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brund94b3fe2012-09-20 18:23:56 +02004547 cfgerr++;
4548 }
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02004549 if (!((ssl_conf && ssl_conf->no_ca_names) || bind_conf->ssl_conf.no_ca_names)) {
4550 /* set CA names for client cert request, function returns void */
4551 SSL_CTX_set_client_CA_list(ctx, SSL_load_client_CA_file(ca_file));
4552 }
Emeric Brund94b3fe2012-09-20 18:23:56 +02004553 }
Emeric Brun850efd52014-01-29 12:24:34 +01004554 else {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004555 ha_alert("Proxy '%s': verify is enabled but no CA file specified for bind '%s' at [%s:%d].\n",
4556 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brun850efd52014-01-29 12:24:34 +01004557 cfgerr++;
4558 }
Emeric Brun051cdab2012-10-02 19:25:50 +02004559#ifdef X509_V_FLAG_CRL_CHECK
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004560 if (crl_file) {
Emeric Brund94b3fe2012-09-20 18:23:56 +02004561 X509_STORE *store = SSL_CTX_get_cert_store(ctx);
4562
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004563 if (!store || !X509_STORE_load_locations(store, crl_file, NULL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004564 ha_alert("Proxy '%s': unable to configure CRL file '%s' for bind '%s' at [%s:%d].\n",
4565 curproxy->id, crl_file, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brund94b3fe2012-09-20 18:23:56 +02004566 cfgerr++;
4567 }
Emeric Brun561e5742012-10-02 15:20:55 +02004568 else {
4569 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
4570 }
Emeric Brund94b3fe2012-09-20 18:23:56 +02004571 }
Emeric Brun051cdab2012-10-02 19:25:50 +02004572#endif
Emeric Brun644cde02012-12-14 11:21:13 +01004573 ERR_clear_error();
Emeric Brund94b3fe2012-09-20 18:23:56 +02004574 }
Nenad Merdanovic05552d42015-02-27 19:56:49 +01004575#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
Nenad Merdanovic146defa2015-05-09 08:46:00 +02004576 if(bind_conf->keys_ref) {
Nenad Merdanovic05552d42015-02-27 19:56:49 +01004577 if (!SSL_CTX_set_tlsext_ticket_key_cb(ctx, ssl_tlsext_ticket_key_cb)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004578 ha_alert("Proxy '%s': unable to set callback for TLS ticket validation for bind '%s' at [%s:%d].\n",
4579 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Nenad Merdanovic05552d42015-02-27 19:56:49 +01004580 cfgerr++;
4581 }
4582 }
4583#endif
4584
William Lallemand4f45bb92017-10-30 20:08:51 +01004585 ssl_set_shctx(ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004586 conf_ciphers = (ssl_conf && ssl_conf->ciphers) ? ssl_conf->ciphers : bind_conf->ssl_conf.ciphers;
4587 if (conf_ciphers &&
4588 !SSL_CTX_set_cipher_list(ctx, conf_ciphers)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004589 ha_alert("Proxy '%s': unable to set SSL cipher list to '%s' for bind '%s' at [%s:%d].\n",
4590 curproxy->id, conf_ciphers, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004591 cfgerr++;
4592 }
4593
Emmanuel Hocdet839af572019-05-14 16:27:35 +02004594#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02004595 conf_ciphersuites = (ssl_conf && ssl_conf->ciphersuites) ? ssl_conf->ciphersuites : bind_conf->ssl_conf.ciphersuites;
4596 if (conf_ciphersuites &&
4597 !SSL_CTX_set_ciphersuites(ctx, conf_ciphersuites)) {
4598 ha_alert("Proxy '%s': unable to set TLS 1.3 cipher suites to '%s' for bind '%s' at [%s:%d].\n",
4599 curproxy->id, conf_ciphersuites, bind_conf->arg, bind_conf->file, bind_conf->line);
4600 cfgerr++;
4601 }
4602#endif
4603
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01004604#ifndef OPENSSL_NO_DH
Remi Gacogne47783ef2015-05-29 15:53:22 +02004605 /* If tune.ssl.default-dh-param has not been set,
4606 neither has ssl-default-dh-file and no static DH
4607 params were in the certificate file. */
Willy Tarreauef934602016-12-22 23:12:01 +01004608 if (global_ssl.default_dh_param == 0 &&
Remi Gacogne47783ef2015-05-29 15:53:22 +02004609 global_dh == NULL &&
Remi Gacogne4f902b82015-05-28 16:23:00 +02004610 (ssl_dh_ptr_index == -1 ||
4611 SSL_CTX_get_ex_data(ctx, ssl_dh_ptr_index) == NULL)) {
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01004612 STACK_OF(SSL_CIPHER) * ciphers = NULL;
4613 const SSL_CIPHER * cipher = NULL;
4614 char cipher_description[128];
4615 /* The description of ciphers using an Ephemeral Diffie Hellman key exchange
4616 contains " Kx=DH " or " Kx=DH(". Beware of " Kx=DH/",
4617 which is not ephemeral DH. */
4618 const char dhe_description[] = " Kx=DH ";
4619 const char dhe_export_description[] = " Kx=DH(";
4620 int idx = 0;
4621 int dhe_found = 0;
4622 SSL *ssl = NULL;
Lukas Tribus90132722014-08-18 00:56:33 +02004623
Remi Gacogne23d5d372014-10-10 17:04:26 +02004624 ssl = SSL_new(ctx);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004625
Remi Gacogne23d5d372014-10-10 17:04:26 +02004626 if (ssl) {
4627 ciphers = SSL_get_ciphers(ssl);
4628
4629 if (ciphers) {
4630 for (idx = 0; idx < sk_SSL_CIPHER_num(ciphers); idx++) {
4631 cipher = sk_SSL_CIPHER_value(ciphers, idx);
4632 if (SSL_CIPHER_description(cipher, cipher_description, sizeof (cipher_description)) == cipher_description) {
4633 if (strstr(cipher_description, dhe_description) != NULL ||
4634 strstr(cipher_description, dhe_export_description) != NULL) {
4635 dhe_found = 1;
4636 break;
4637 }
Remi Gacognec1eab8c2014-06-12 18:20:11 +02004638 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004639 }
4640 }
Remi Gacogne23d5d372014-10-10 17:04:26 +02004641 SSL_free(ssl);
4642 ssl = NULL;
Lukas Tribus90132722014-08-18 00:56:33 +02004643 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004644
Lukas Tribus90132722014-08-18 00:56:33 +02004645 if (dhe_found) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004646 ha_warning("Setting tune.ssl.default-dh-param to 1024 by default, if your workload permits it you should set it to at least 2048. Please set a value >= 1024 to make this warning disappear.\n");
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004647 }
4648
Willy Tarreauef934602016-12-22 23:12:01 +01004649 global_ssl.default_dh_param = 1024;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004650 }
Remi Gacogne8de54152014-07-15 11:36:40 +02004651
Willy Tarreauef934602016-12-22 23:12:01 +01004652 if (global_ssl.default_dh_param >= 1024) {
Remi Gacogne8de54152014-07-15 11:36:40 +02004653 if (local_dh_1024 == NULL) {
4654 local_dh_1024 = ssl_get_dh_1024();
4655 }
Willy Tarreauef934602016-12-22 23:12:01 +01004656 if (global_ssl.default_dh_param >= 2048) {
Remi Gacogne8de54152014-07-15 11:36:40 +02004657 if (local_dh_2048 == NULL) {
4658 local_dh_2048 = ssl_get_dh_2048();
4659 }
Willy Tarreauef934602016-12-22 23:12:01 +01004660 if (global_ssl.default_dh_param >= 4096) {
Remi Gacogne8de54152014-07-15 11:36:40 +02004661 if (local_dh_4096 == NULL) {
4662 local_dh_4096 = ssl_get_dh_4096();
4663 }
Remi Gacogne8de54152014-07-15 11:36:40 +02004664 }
4665 }
4666 }
4667#endif /* OPENSSL_NO_DH */
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004668
Emeric Brunfc0421f2012-09-07 17:30:07 +02004669 SSL_CTX_set_info_callback(ctx, ssl_sock_infocbk);
Willy Tarreau9a1ab082019-05-09 13:26:41 +02004670#if HA_OPENSSL_VERSION_NUMBER >= 0x00907000L
Emeric Brun29f037d2014-04-25 19:05:36 +02004671 SSL_CTX_set_msg_callback(ctx, ssl_sock_msgcbk);
Willy Tarreau5cbe4ef2014-05-08 22:45:11 +02004672#endif
Emeric Brun29f037d2014-04-25 19:05:36 +02004673
Bernard Spil13c53f82018-02-15 13:34:58 +01004674#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004675 ssl_conf_cur = NULL;
4676 if (ssl_conf && ssl_conf->npn_str)
4677 ssl_conf_cur = ssl_conf;
4678 else if (bind_conf->ssl_conf.npn_str)
4679 ssl_conf_cur = &bind_conf->ssl_conf;
4680 if (ssl_conf_cur)
4681 SSL_CTX_set_next_protos_advertised_cb(ctx, ssl_sock_advertise_npn_protos, ssl_conf_cur);
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02004682#endif
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01004683#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004684 ssl_conf_cur = NULL;
4685 if (ssl_conf && ssl_conf->alpn_str)
4686 ssl_conf_cur = ssl_conf;
4687 else if (bind_conf->ssl_conf.alpn_str)
4688 ssl_conf_cur = &bind_conf->ssl_conf;
4689 if (ssl_conf_cur)
4690 SSL_CTX_set_alpn_select_cb(ctx, ssl_sock_advertise_alpn_protos, ssl_conf_cur);
Willy Tarreauab861d32013-04-02 02:30:41 +02004691#endif
Willy Tarreau9a1ab082019-05-09 13:26:41 +02004692#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004693 conf_curves = (ssl_conf && ssl_conf->curves) ? ssl_conf->curves : bind_conf->ssl_conf.curves;
4694 if (conf_curves) {
4695 if (!SSL_CTX_set1_curves_list(ctx, conf_curves)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004696 ha_alert("Proxy '%s': unable to set SSL curves list to '%s' for bind '%s' at [%s:%d].\n",
4697 curproxy->id, conf_curves, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004698 cfgerr++;
4699 }
Emmanuel Hocdeta52bb152017-03-20 11:11:49 +01004700#if defined(SSL_CTX_set_ecdh_auto)
4701 (void)SSL_CTX_set_ecdh_auto(ctx, 1);
4702#endif
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004703 }
4704#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02004705#if defined(SSL_CTX_set_tmp_ecdh) && !defined(OPENSSL_NO_ECDH)
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004706 if (!conf_curves) {
Emeric Brun2b58d042012-09-20 17:10:03 +02004707 int i;
4708 EC_KEY *ecdh;
Willy Tarreau9a1ab082019-05-09 13:26:41 +02004709#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004710 const char *ecdhe = (ssl_conf && ssl_conf->ecdhe) ? ssl_conf->ecdhe :
Olivier Houchardc2aae742017-09-22 18:26:28 +02004711 (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe :
4712 NULL);
4713
4714 if (ecdhe == NULL) {
Emeric Bruna9363eb2019-10-17 14:53:03 +02004715 SSL_CTX_set_ecdh_auto(ctx, 1);
Olivier Houchardc2aae742017-09-22 18:26:28 +02004716 return cfgerr;
4717 }
4718#else
4719 const char *ecdhe = (ssl_conf && ssl_conf->ecdhe) ? ssl_conf->ecdhe :
4720 (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe :
4721 ECDHE_DEFAULT_CURVE);
4722#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02004723
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004724 i = OBJ_sn2nid(ecdhe);
Emeric Brun2b58d042012-09-20 17:10:03 +02004725 if (!i || ((ecdh = EC_KEY_new_by_curve_name(i)) == NULL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004726 ha_alert("Proxy '%s': unable to set elliptic named curve to '%s' for bind '%s' at [%s:%d].\n",
4727 curproxy->id, ecdhe, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brun2b58d042012-09-20 17:10:03 +02004728 cfgerr++;
4729 }
4730 else {
4731 SSL_CTX_set_tmp_ecdh(ctx, ecdh);
4732 EC_KEY_free(ecdh);
4733 }
4734 }
4735#endif
4736
Emeric Brunfc0421f2012-09-07 17:30:07 +02004737 return cfgerr;
4738}
4739
Evan Broderbe554312013-06-27 00:05:25 -07004740static int ssl_sock_srv_hostcheck(const char *pattern, const char *hostname)
4741{
4742 const char *pattern_wildcard, *pattern_left_label_end, *hostname_left_label_end;
4743 size_t prefixlen, suffixlen;
4744
4745 /* Trivial case */
4746 if (strcmp(pattern, hostname) == 0)
4747 return 1;
4748
Evan Broderbe554312013-06-27 00:05:25 -07004749 /* The rest of this logic is based on RFC 6125, section 6.4.3
4750 * (http://tools.ietf.org/html/rfc6125#section-6.4.3) */
4751
Emeric Bruna848dae2013-10-08 11:27:28 +02004752 pattern_wildcard = NULL;
4753 pattern_left_label_end = pattern;
4754 while (*pattern_left_label_end != '.') {
4755 switch (*pattern_left_label_end) {
4756 case 0:
4757 /* End of label not found */
4758 return 0;
4759 case '*':
4760 /* If there is more than one wildcards */
4761 if (pattern_wildcard)
4762 return 0;
4763 pattern_wildcard = pattern_left_label_end;
4764 break;
4765 }
4766 pattern_left_label_end++;
4767 }
4768
4769 /* If it's not trivial and there is no wildcard, it can't
4770 * match */
4771 if (!pattern_wildcard)
Evan Broderbe554312013-06-27 00:05:25 -07004772 return 0;
4773
4774 /* Make sure all labels match except the leftmost */
4775 hostname_left_label_end = strchr(hostname, '.');
4776 if (!hostname_left_label_end
4777 || strcmp(pattern_left_label_end, hostname_left_label_end) != 0)
4778 return 0;
4779
4780 /* Make sure the leftmost label of the hostname is long enough
4781 * that the wildcard can match */
Emeric Brun369da852013-10-08 11:39:35 +02004782 if (hostname_left_label_end - hostname < (pattern_left_label_end - pattern) - 1)
Evan Broderbe554312013-06-27 00:05:25 -07004783 return 0;
4784
4785 /* Finally compare the string on either side of the
4786 * wildcard */
4787 prefixlen = pattern_wildcard - pattern;
4788 suffixlen = pattern_left_label_end - (pattern_wildcard + 1);
Emeric Bruna848dae2013-10-08 11:27:28 +02004789 if ((prefixlen && (memcmp(pattern, hostname, prefixlen) != 0))
4790 || (suffixlen && (memcmp(pattern_wildcard + 1, hostname_left_label_end - suffixlen, suffixlen) != 0)))
Evan Broderbe554312013-06-27 00:05:25 -07004791 return 0;
4792
4793 return 1;
4794}
4795
4796static int ssl_sock_srv_verifycbk(int ok, X509_STORE_CTX *ctx)
4797{
4798 SSL *ssl;
4799 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01004800 struct ssl_sock_ctx *ssl_ctx;
Willy Tarreau2ab88672017-07-05 18:23:03 +02004801 const char *servername;
Willy Tarreau71d058c2017-07-26 20:09:56 +02004802 const char *sni;
Evan Broderbe554312013-06-27 00:05:25 -07004803
4804 int depth;
4805 X509 *cert;
4806 STACK_OF(GENERAL_NAME) *alt_names;
4807 int i;
4808 X509_NAME *cert_subject;
4809 char *str;
4810
4811 if (ok == 0)
4812 return ok;
4813
4814 ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
Thierry FOURNIER28962c92018-06-17 21:37:05 +02004815 conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Olivier Houchard66ab4982019-02-26 18:37:15 +01004816 ssl_ctx = conn->xprt_ctx;
Evan Broderbe554312013-06-27 00:05:25 -07004817
Willy Tarreauad92a9a2017-07-28 11:38:41 +02004818 /* We're checking if the provided hostnames match the desired one. The
4819 * desired hostname comes from the SNI we presented if any, or if not
4820 * provided then it may have been explicitly stated using a "verifyhost"
4821 * directive. If neither is set, we don't care about the name so the
4822 * verification is OK.
Willy Tarreau2ab88672017-07-05 18:23:03 +02004823 */
Olivier Houchard66ab4982019-02-26 18:37:15 +01004824 servername = SSL_get_servername(ssl_ctx->ssl, TLSEXT_NAMETYPE_host_name);
Willy Tarreau71d058c2017-07-26 20:09:56 +02004825 sni = servername;
Willy Tarreau2ab88672017-07-05 18:23:03 +02004826 if (!servername) {
Willy Tarreau07d94e42018-09-20 10:57:52 +02004827 servername = __objt_server(conn->target)->ssl_ctx.verify_host;
Willy Tarreau2ab88672017-07-05 18:23:03 +02004828 if (!servername)
4829 return ok;
4830 }
Evan Broderbe554312013-06-27 00:05:25 -07004831
4832 /* We only need to verify the CN on the actual server cert,
4833 * not the indirect CAs */
4834 depth = X509_STORE_CTX_get_error_depth(ctx);
4835 if (depth != 0)
4836 return ok;
4837
4838 /* At this point, the cert is *not* OK unless we can find a
4839 * hostname match */
4840 ok = 0;
4841
4842 cert = X509_STORE_CTX_get_current_cert(ctx);
4843 /* It seems like this might happen if verify peer isn't set */
4844 if (!cert)
4845 return ok;
4846
4847 alt_names = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
4848 if (alt_names) {
4849 for (i = 0; !ok && i < sk_GENERAL_NAME_num(alt_names); i++) {
4850 GENERAL_NAME *name = sk_GENERAL_NAME_value(alt_names, i);
4851 if (name->type == GEN_DNS) {
Willy Tarreau9a1ab082019-05-09 13:26:41 +02004852#if HA_OPENSSL_VERSION_NUMBER < 0x00907000L
Emeric Bruna33410c2013-09-17 15:47:48 +02004853 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.ia5) >= 0) {
4854#else
Evan Broderbe554312013-06-27 00:05:25 -07004855 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
Emeric Bruna33410c2013-09-17 15:47:48 +02004856#endif
Evan Broderbe554312013-06-27 00:05:25 -07004857 ok = ssl_sock_srv_hostcheck(str, servername);
4858 OPENSSL_free(str);
4859 }
4860 }
4861 }
Emeric Brun4ad50a42013-09-17 15:19:54 +02004862 sk_GENERAL_NAME_pop_free(alt_names, GENERAL_NAME_free);
Evan Broderbe554312013-06-27 00:05:25 -07004863 }
4864
4865 cert_subject = X509_get_subject_name(cert);
4866 i = -1;
4867 while (!ok && (i = X509_NAME_get_index_by_NID(cert_subject, NID_commonName, i)) != -1) {
4868 X509_NAME_ENTRY *entry = X509_NAME_get_entry(cert_subject, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02004869 ASN1_STRING *value;
4870 value = X509_NAME_ENTRY_get_data(entry);
4871 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
Evan Broderbe554312013-06-27 00:05:25 -07004872 ok = ssl_sock_srv_hostcheck(str, servername);
4873 OPENSSL_free(str);
4874 }
4875 }
4876
Willy Tarreau71d058c2017-07-26 20:09:56 +02004877 /* report the mismatch and indicate if SNI was used or not */
4878 if (!ok && !conn->err_code)
4879 conn->err_code = sni ? CO_ER_SSL_MISMATCH_SNI : CO_ER_SSL_MISMATCH;
Evan Broderbe554312013-06-27 00:05:25 -07004880 return ok;
4881}
4882
Emeric Brun94324a42012-10-11 14:00:19 +02004883/* prepare ssl context from servers options. Returns an error count */
Willy Tarreau03209342016-12-22 17:08:28 +01004884int ssl_sock_prepare_srv_ctx(struct server *srv)
Emeric Brun94324a42012-10-11 14:00:19 +02004885{
Willy Tarreau03209342016-12-22 17:08:28 +01004886 struct proxy *curproxy = srv->proxy;
Emeric Brun94324a42012-10-11 14:00:19 +02004887 int cfgerr = 0;
Remi Gacogneaf5c3da2014-05-19 10:29:58 +02004888 long options =
Emeric Brun94324a42012-10-11 14:00:19 +02004889 SSL_OP_ALL | /* all known workarounds for bugs */
4890 SSL_OP_NO_SSLv2 |
4891 SSL_OP_NO_COMPRESSION;
Remi Gacogneaf5c3da2014-05-19 10:29:58 +02004892 long mode =
Emeric Brun94324a42012-10-11 14:00:19 +02004893 SSL_MODE_ENABLE_PARTIAL_WRITE |
4894 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
Willy Tarreau396a1862014-11-13 14:06:52 +01004895 SSL_MODE_RELEASE_BUFFERS |
4896 SSL_MODE_SMALL_BUFFERS;
Emeric Brun850efd52014-01-29 12:24:34 +01004897 int verify = SSL_VERIFY_NONE;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004898 SSL_CTX *ctx = NULL;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004899 struct tls_version_filter *conf_ssl_methods = &srv->ssl_ctx.methods;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004900 int i, min, max, hole;
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004901 int flags = MC_SSL_O_ALL;
Emeric Brun94324a42012-10-11 14:00:19 +02004902
Thierry Fournier383085f2013-01-24 14:15:43 +01004903 /* Make sure openssl opens /dev/urandom before the chroot */
4904 if (!ssl_initialize_random()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004905 ha_alert("OpenSSL random data generator initialization failed.\n");
Thierry Fournier383085f2013-01-24 14:15:43 +01004906 cfgerr++;
4907 }
4908
Willy Tarreaufce03112015-01-15 21:32:40 +01004909 /* Automatic memory computations need to know we use SSL there */
4910 global.ssl_used_backend = 1;
4911
4912 /* Initiate SSL context for current server */
Emeric Brun821bb9b2017-06-15 16:37:39 +02004913 if (!srv->ssl_ctx.reused_sess) {
Olivier Houcharde6060c52017-11-16 17:42:52 +01004914 if ((srv->ssl_ctx.reused_sess = calloc(1, global.nbthread*sizeof(*srv->ssl_ctx.reused_sess))) == NULL) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004915 ha_alert("Proxy '%s', server '%s' [%s:%d] out of memory.\n",
4916 curproxy->id, srv->id,
4917 srv->conf.file, srv->conf.line);
Emeric Brun821bb9b2017-06-15 16:37:39 +02004918 cfgerr++;
4919 return cfgerr;
4920 }
4921 }
Emeric Brun94324a42012-10-11 14:00:19 +02004922 if (srv->use_ssl)
4923 srv->xprt = &ssl_sock;
4924 if (srv->check.use_ssl)
Cyril Bonté9ce13112014-11-15 22:41:27 +01004925 srv->check.xprt = &ssl_sock;
Emeric Brun94324a42012-10-11 14:00:19 +02004926
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004927 ctx = SSL_CTX_new(SSLv23_client_method());
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004928 if (!ctx) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004929 ha_alert("config : %s '%s', server '%s': unable to allocate ssl context.\n",
4930 proxy_type_str(curproxy), curproxy->id,
4931 srv->id);
Emeric Brun94324a42012-10-11 14:00:19 +02004932 cfgerr++;
4933 return cfgerr;
4934 }
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004935
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004936 if (conf_ssl_methods->flags && (conf_ssl_methods->min || conf_ssl_methods->max))
Christopher Faulet767a84b2017-11-24 16:50:31 +01004937 ha_warning("config : %s '%s': no-sslv3/no-tlsv1x are ignored for server '%s'. "
4938 "Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
4939 proxy_type_str(curproxy), curproxy->id, srv->id);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004940 else
4941 flags = conf_ssl_methods->flags;
4942
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004943 /* Real min and max should be determinate with configuration and openssl's capabilities */
4944 if (conf_ssl_methods->min)
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004945 flags |= (methodVersions[conf_ssl_methods->min].flag - 1);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004946 if (conf_ssl_methods->max)
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004947 flags |= ~((methodVersions[conf_ssl_methods->max].flag << 1) - 1);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004948
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004949 /* find min, max and holes */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004950 min = max = CONF_TLSV_NONE;
4951 hole = 0;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004952 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004953 /* version is in openssl && version not disable in configuration */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004954 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004955 if (min) {
4956 if (hole) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004957 ha_warning("config : %s '%s': SSL/TLS versions range not contiguous for server '%s'. "
4958 "Hole find for %s. Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
4959 proxy_type_str(curproxy), curproxy->id, srv->id,
4960 methodVersions[hole].name);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004961 hole = 0;
4962 }
4963 max = i;
4964 }
4965 else {
4966 min = max = i;
4967 }
4968 }
4969 else {
4970 if (min)
4971 hole = i;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004972 }
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004973 if (!min) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004974 ha_alert("config : %s '%s': all SSL/TLS versions are disabled for server '%s'.\n",
4975 proxy_type_str(curproxy), curproxy->id, srv->id);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004976 cfgerr += 1;
4977 }
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004978
Willy Tarreau9a1ab082019-05-09 13:26:41 +02004979#if (HA_OPENSSL_VERSION_NUMBER < 0x1010000fL)
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004980 /* Keep force-xxx implementation as it is in older haproxy. It's a
Joseph Herlant017b3da2018-11-15 09:07:59 -08004981 precautionary measure to avoid any surprise with older openssl version. */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004982 if (min == max)
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004983 methodVersions[min].ctx_set_version(ctx, SET_CLIENT);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004984 else
4985 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
4986 if (flags & methodVersions[i].flag)
4987 options |= methodVersions[i].option;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004988#else /* openssl >= 1.1.0 */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004989 /* set the max_version is required to cap TLS version or activate new TLS (v1.3) */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004990 methodVersions[min].ctx_set_version(ctx, SET_MIN);
4991 methodVersions[max].ctx_set_version(ctx, SET_MAX);
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004992#endif
4993
4994 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLS_TICKETS)
4995 options |= SSL_OP_NO_TICKET;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004996 SSL_CTX_set_options(ctx, options);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004997
Willy Tarreau5db847a2019-05-09 14:13:35 +02004998#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004999 if (global_ssl.async)
5000 mode |= SSL_MODE_ASYNC;
5001#endif
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01005002 SSL_CTX_set_mode(ctx, mode);
5003 srv->ssl_ctx.ctx = ctx;
5004
Emeric Bruna7aa3092012-10-26 12:58:00 +02005005 if (srv->ssl_ctx.client_crt) {
5006 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 +01005007 ha_alert("config : %s '%s', server '%s': unable to load SSL private key from PEM file '%s'.\n",
5008 proxy_type_str(curproxy), curproxy->id,
5009 srv->id, srv->ssl_ctx.client_crt);
Emeric Bruna7aa3092012-10-26 12:58:00 +02005010 cfgerr++;
5011 }
5012 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 +01005013 ha_alert("config : %s '%s', server '%s': unable to load ssl certificate from PEM file '%s'.\n",
5014 proxy_type_str(curproxy), curproxy->id,
5015 srv->id, srv->ssl_ctx.client_crt);
Emeric Bruna7aa3092012-10-26 12:58:00 +02005016 cfgerr++;
5017 }
5018 else if (SSL_CTX_check_private_key(srv->ssl_ctx.ctx) <= 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005019 ha_alert("config : %s '%s', server '%s': inconsistencies between private key and certificate loaded from PEM file '%s'.\n",
5020 proxy_type_str(curproxy), curproxy->id,
5021 srv->id, srv->ssl_ctx.client_crt);
Emeric Bruna7aa3092012-10-26 12:58:00 +02005022 cfgerr++;
5023 }
5024 }
Emeric Brun94324a42012-10-11 14:00:19 +02005025
Emeric Brun850efd52014-01-29 12:24:34 +01005026 if (global.ssl_server_verify == SSL_SERVER_VERIFY_REQUIRED)
5027 verify = SSL_VERIFY_PEER;
Emeric Brun850efd52014-01-29 12:24:34 +01005028 switch (srv->ssl_ctx.verify) {
5029 case SSL_SOCK_VERIFY_NONE:
5030 verify = SSL_VERIFY_NONE;
5031 break;
5032 case SSL_SOCK_VERIFY_REQUIRED:
5033 verify = SSL_VERIFY_PEER;
5034 break;
5035 }
Evan Broderbe554312013-06-27 00:05:25 -07005036 SSL_CTX_set_verify(srv->ssl_ctx.ctx,
Emeric Brun850efd52014-01-29 12:24:34 +01005037 verify,
Willy Tarreau2ab88672017-07-05 18:23:03 +02005038 (srv->ssl_ctx.verify_host || (verify & SSL_VERIFY_PEER)) ? ssl_sock_srv_verifycbk : NULL);
Emeric Brun850efd52014-01-29 12:24:34 +01005039 if (verify & SSL_VERIFY_PEER) {
Emeric Brunef42d922012-10-11 16:11:36 +02005040 if (srv->ssl_ctx.ca_file) {
5041 /* load CAfile to verify */
5042 if (!SSL_CTX_load_verify_locations(srv->ssl_ctx.ctx, srv->ssl_ctx.ca_file, NULL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005043 ha_alert("Proxy '%s', server '%s' [%s:%d] unable to load CA file '%s'.\n",
5044 curproxy->id, srv->id,
5045 srv->conf.file, srv->conf.line, srv->ssl_ctx.ca_file);
Emeric Brunef42d922012-10-11 16:11:36 +02005046 cfgerr++;
5047 }
5048 }
Emeric Brun850efd52014-01-29 12:24:34 +01005049 else {
5050 if (global.ssl_server_verify == SSL_SERVER_VERIFY_REQUIRED)
Christopher Faulet767a84b2017-11-24 16:50:31 +01005051 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",
5052 curproxy->id, srv->id,
5053 srv->conf.file, srv->conf.line);
Emeric Brun850efd52014-01-29 12:24:34 +01005054 else
Christopher Faulet767a84b2017-11-24 16:50:31 +01005055 ha_alert("Proxy '%s', server '%s' [%s:%d] verify is enabled but no CA file specified.\n",
5056 curproxy->id, srv->id,
5057 srv->conf.file, srv->conf.line);
Emeric Brun850efd52014-01-29 12:24:34 +01005058 cfgerr++;
5059 }
Emeric Brunef42d922012-10-11 16:11:36 +02005060#ifdef X509_V_FLAG_CRL_CHECK
5061 if (srv->ssl_ctx.crl_file) {
5062 X509_STORE *store = SSL_CTX_get_cert_store(srv->ssl_ctx.ctx);
5063
5064 if (!store || !X509_STORE_load_locations(store, srv->ssl_ctx.crl_file, NULL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005065 ha_alert("Proxy '%s', server '%s' [%s:%d] unable to configure CRL file '%s'.\n",
5066 curproxy->id, srv->id,
5067 srv->conf.file, srv->conf.line, srv->ssl_ctx.crl_file);
Emeric Brunef42d922012-10-11 16:11:36 +02005068 cfgerr++;
5069 }
5070 else {
5071 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
5072 }
5073 }
5074#endif
5075 }
5076
Olivier Houchardbd84ac82017-11-03 13:43:35 +01005077 SSL_CTX_set_session_cache_mode(srv->ssl_ctx.ctx, SSL_SESS_CACHE_CLIENT |
5078 SSL_SESS_CACHE_NO_INTERNAL_STORE);
5079 SSL_CTX_sess_set_new_cb(srv->ssl_ctx.ctx, ssl_sess_new_srv_cb);
Emeric Brun94324a42012-10-11 14:00:19 +02005080 if (srv->ssl_ctx.ciphers &&
5081 !SSL_CTX_set_cipher_list(srv->ssl_ctx.ctx, srv->ssl_ctx.ciphers)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005082 ha_alert("Proxy '%s', server '%s' [%s:%d] : unable to set SSL cipher list to '%s'.\n",
5083 curproxy->id, srv->id,
5084 srv->conf.file, srv->conf.line, srv->ssl_ctx.ciphers);
Emeric Brun94324a42012-10-11 14:00:19 +02005085 cfgerr++;
5086 }
Dirkjan Bussink415150f2018-09-14 11:14:21 +02005087
Emmanuel Hocdet839af572019-05-14 16:27:35 +02005088#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02005089 if (srv->ssl_ctx.ciphersuites &&
Pierre Cheynierbc34cd12019-03-21 16:15:47 +00005090 !SSL_CTX_set_ciphersuites(srv->ssl_ctx.ctx, srv->ssl_ctx.ciphersuites)) {
Dirkjan Bussink415150f2018-09-14 11:14:21 +02005091 ha_alert("Proxy '%s', server '%s' [%s:%d] : unable to set TLS 1.3 cipher suites to '%s'.\n",
5092 curproxy->id, srv->id,
5093 srv->conf.file, srv->conf.line, srv->ssl_ctx.ciphersuites);
5094 cfgerr++;
5095 }
5096#endif
Olivier Houchardc7566002018-11-20 23:33:50 +01005097#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
5098 if (srv->ssl_ctx.npn_str)
5099 SSL_CTX_set_next_proto_select_cb(ctx, ssl_sock_srv_select_protos, srv);
5100#endif
5101#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
5102 if (srv->ssl_ctx.alpn_str)
5103 SSL_CTX_set_alpn_protos(ctx, (unsigned char *)srv->ssl_ctx.alpn_str, srv->ssl_ctx.alpn_len);
5104#endif
5105
Emeric Brun94324a42012-10-11 14:00:19 +02005106
5107 return cfgerr;
5108}
5109
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005110/* Walks down the two trees in bind_conf and prepares all certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +02005111 * be NULL, in which case nothing is done. Returns the number of errors
5112 * encountered.
5113 */
Willy Tarreau03209342016-12-22 17:08:28 +01005114int ssl_sock_prepare_all_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02005115{
5116 struct ebmb_node *node;
5117 struct sni_ctx *sni;
5118 int err = 0;
5119
Willy Tarreaufce03112015-01-15 21:32:40 +01005120 /* Automatic memory computations need to know we use SSL there */
5121 global.ssl_used_frontend = 1;
5122
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01005123 /* Make sure openssl opens /dev/urandom before the chroot */
5124 if (!ssl_initialize_random()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005125 ha_alert("OpenSSL random data generator initialization failed.\n");
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01005126 err++;
5127 }
5128 /* Create initial_ctx used to start the ssl connection before do switchctx */
5129 if (!bind_conf->initial_ctx) {
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005130 err += ssl_sock_initial_ctx(bind_conf);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01005131 /* It should not be necessary to call this function, but it's
5132 necessary first to check and move all initialisation related
5133 to initial_ctx in ssl_sock_initial_ctx. */
5134 err += ssl_sock_prepare_ctx(bind_conf, NULL, bind_conf->initial_ctx);
5135 }
Emeric Brun0bed9942014-10-30 19:25:24 +01005136 if (bind_conf->default_ctx)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005137 err += ssl_sock_prepare_ctx(bind_conf, bind_conf->default_ssl_conf, bind_conf->default_ctx);
Emeric Brun0bed9942014-10-30 19:25:24 +01005138
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005139 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02005140 while (node) {
5141 sni = ebmb_entry(node, struct sni_ctx, name);
Emeric Brun0bed9942014-10-30 19:25:24 +01005142 if (!sni->order && sni->ctx != bind_conf->default_ctx)
5143 /* only initialize the CTX on its first occurrence and
5144 if it is not the default_ctx */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005145 err += ssl_sock_prepare_ctx(bind_conf, sni->conf, sni->ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02005146 node = ebmb_next(node);
5147 }
5148
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005149 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02005150 while (node) {
5151 sni = ebmb_entry(node, struct sni_ctx, name);
Emeric Brun0bed9942014-10-30 19:25:24 +01005152 if (!sni->order && sni->ctx != bind_conf->default_ctx)
5153 /* only initialize the CTX on its first occurrence and
5154 if it is not the default_ctx */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005155 err += ssl_sock_prepare_ctx(bind_conf, sni->conf, sni->ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02005156 node = ebmb_next(node);
5157 }
5158 return err;
5159}
5160
Willy Tarreau55d37912016-12-21 23:38:39 +01005161/* Prepares all the contexts for a bind_conf and allocates the shared SSL
5162 * context if needed. Returns < 0 on error, 0 on success. The warnings and
5163 * alerts are directly emitted since the rest of the stack does it below.
5164 */
5165int ssl_sock_prepare_bind_conf(struct bind_conf *bind_conf)
5166{
5167 struct proxy *px = bind_conf->frontend;
5168 int alloc_ctx;
5169 int err;
5170
5171 if (!bind_conf->is_ssl) {
5172 if (bind_conf->default_ctx) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005173 ha_warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
5174 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreau55d37912016-12-21 23:38:39 +01005175 }
5176 return 0;
5177 }
5178 if (!bind_conf->default_ctx) {
Emmanuel Hocdetaa0d6372017-08-09 11:24:25 +02005179 if (bind_conf->strict_sni && !bind_conf->generate_certs) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005180 ha_warning("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d], ssl connections will fail (use 'crt').\n",
5181 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetaa0d6372017-08-09 11:24:25 +02005182 }
5183 else {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005184 ha_alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
5185 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetaa0d6372017-08-09 11:24:25 +02005186 return -1;
5187 }
Willy Tarreau55d37912016-12-21 23:38:39 +01005188 }
William Lallemandc61c0b32017-12-04 18:46:39 +01005189 if (!ssl_shctx && global.tune.sslcachesize) {
William Lallemandc3cd35f2017-11-28 11:04:43 +01005190 alloc_ctx = shctx_init(&ssl_shctx, global.tune.sslcachesize,
Frédéric Lécailleb7838af2018-10-22 16:21:39 +02005191 sizeof(struct sh_ssl_sess_hdr) + SHSESS_BLOCK_MIN_SIZE, -1,
William Lallemandc3cd35f2017-11-28 11:04:43 +01005192 sizeof(*sh_ssl_sess_tree),
5193 ((global.nbthread > 1) || (!global_ssl.private_cache && (global.nbproc > 1))) ? 1 : 0);
Frédéric Lécaille4c8aa112018-10-25 20:22:46 +02005194 if (alloc_ctx <= 0) {
William Lallemandc3cd35f2017-11-28 11:04:43 +01005195 if (alloc_ctx == SHCTX_E_INIT_LOCK)
5196 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");
5197 else
5198 ha_alert("Unable to allocate SSL session cache.\n");
5199 return -1;
5200 }
5201 /* free block callback */
5202 ssl_shctx->free_block = sh_ssl_sess_free_blocks;
5203 /* init the root tree within the extra space */
5204 sh_ssl_sess_tree = (void *)ssl_shctx + sizeof(struct shared_context);
5205 *sh_ssl_sess_tree = EB_ROOT_UNIQUE;
Willy Tarreau55d37912016-12-21 23:38:39 +01005206 }
Willy Tarreau55d37912016-12-21 23:38:39 +01005207 err = 0;
5208 /* initialize all certificate contexts */
5209 err += ssl_sock_prepare_all_ctx(bind_conf);
5210
5211 /* initialize CA variables if the certificates generation is enabled */
5212 err += ssl_sock_load_ca(bind_conf);
5213
5214 return -err;
5215}
Christopher Faulet77fe80c2015-07-29 13:02:40 +02005216
5217/* release ssl context allocated for servers. */
5218void ssl_sock_free_srv_ctx(struct server *srv)
5219{
Olivier Houchardc7566002018-11-20 23:33:50 +01005220#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
5221 if (srv->ssl_ctx.alpn_str)
5222 free(srv->ssl_ctx.alpn_str);
5223#endif
Lukas Tribusda95fd92018-11-25 13:21:27 +01005224#ifdef OPENSSL_NPN_NEGOTIATED
Olivier Houchardc7566002018-11-20 23:33:50 +01005225 if (srv->ssl_ctx.npn_str)
5226 free(srv->ssl_ctx.npn_str);
Lukas Tribus7706b852018-11-26 22:57:17 +01005227#endif
Christopher Faulet77fe80c2015-07-29 13:02:40 +02005228 if (srv->ssl_ctx.ctx)
5229 SSL_CTX_free(srv->ssl_ctx.ctx);
5230}
5231
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005232/* Walks down the two trees in bind_conf and frees all the certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +02005233 * be NULL, in which case nothing is done. The default_ctx is nullified too.
5234 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005235void ssl_sock_free_all_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02005236{
5237 struct ebmb_node *node, *back;
5238 struct sni_ctx *sni;
5239
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005240 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02005241 while (node) {
5242 sni = ebmb_entry(node, struct sni_ctx, name);
5243 back = ebmb_next(node);
5244 ebmb_delete(node);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005245 if (!sni->order) { /* only free the CTX on its first occurrence */
Emeric Brunfc0421f2012-09-07 17:30:07 +02005246 SSL_CTX_free(sni->ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005247 ssl_sock_free_ssl_conf(sni->conf);
5248 free(sni->conf);
5249 sni->conf = NULL;
5250 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02005251 free(sni);
5252 node = back;
5253 }
5254
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005255 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02005256 while (node) {
5257 sni = ebmb_entry(node, struct sni_ctx, name);
5258 back = ebmb_next(node);
5259 ebmb_delete(node);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005260 if (!sni->order) { /* only free the CTX on its first occurrence */
Emeric Brunfc0421f2012-09-07 17:30:07 +02005261 SSL_CTX_free(sni->ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005262 ssl_sock_free_ssl_conf(sni->conf);
5263 free(sni->conf);
5264 sni->conf = NULL;
5265 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02005266 free(sni);
5267 node = back;
5268 }
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01005269 SSL_CTX_free(bind_conf->initial_ctx);
5270 bind_conf->initial_ctx = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005271 bind_conf->default_ctx = NULL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005272 bind_conf->default_ssl_conf = NULL;
Emeric Brune1f38db2012-09-03 20:36:47 +02005273}
5274
Willy Tarreau795cdab2016-12-22 17:30:54 +01005275/* Destroys all the contexts for a bind_conf. This is used during deinit(). */
5276void ssl_sock_destroy_bind_conf(struct bind_conf *bind_conf)
5277{
5278 ssl_sock_free_ca(bind_conf);
5279 ssl_sock_free_all_ctx(bind_conf);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005280 ssl_sock_free_ssl_conf(&bind_conf->ssl_conf);
Willy Tarreau795cdab2016-12-22 17:30:54 +01005281 free(bind_conf->ca_sign_file);
5282 free(bind_conf->ca_sign_pass);
Willy Tarreau17b4aa12018-07-17 10:05:32 +02005283 if (bind_conf->keys_ref && !--bind_conf->keys_ref->refcount) {
Willy Tarreau795cdab2016-12-22 17:30:54 +01005284 free(bind_conf->keys_ref->filename);
5285 free(bind_conf->keys_ref->tlskeys);
5286 LIST_DEL(&bind_conf->keys_ref->list);
5287 free(bind_conf->keys_ref);
5288 }
5289 bind_conf->keys_ref = NULL;
Willy Tarreau795cdab2016-12-22 17:30:54 +01005290 bind_conf->ca_sign_pass = NULL;
5291 bind_conf->ca_sign_file = NULL;
Willy Tarreau795cdab2016-12-22 17:30:54 +01005292}
5293
Christopher Faulet31af49d2015-06-09 17:29:50 +02005294/* Load CA cert file and private key used to generate certificates */
5295int
Willy Tarreau03209342016-12-22 17:08:28 +01005296ssl_sock_load_ca(struct bind_conf *bind_conf)
Christopher Faulet31af49d2015-06-09 17:29:50 +02005297{
Willy Tarreau03209342016-12-22 17:08:28 +01005298 struct proxy *px = bind_conf->frontend;
Christopher Faulet31af49d2015-06-09 17:29:50 +02005299 FILE *fp;
5300 X509 *cacert = NULL;
5301 EVP_PKEY *capkey = NULL;
5302 int err = 0;
5303
Christopher Fauletf8bb0ce2017-09-15 09:52:49 +02005304 if (!bind_conf->generate_certs)
Christopher Faulet31af49d2015-06-09 17:29:50 +02005305 return err;
5306
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005307#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Emeric Brun821bb9b2017-06-15 16:37:39 +02005308 if (global_ssl.ctx_cache) {
Willy Tarreauef934602016-12-22 23:12:01 +01005309 ssl_ctx_lru_tree = lru64_new(global_ssl.ctx_cache);
Emeric Brun821bb9b2017-06-15 16:37:39 +02005310 }
Christopher Fauletd2cab922015-07-28 16:03:47 +02005311 ssl_ctx_lru_seed = (unsigned int)time(NULL);
Emeric Brun821bb9b2017-06-15 16:37:39 +02005312 ssl_ctx_serial = now_ms;
Willy Tarreaua84c2672015-10-09 12:10:13 +02005313#endif
Christopher Fauletd2cab922015-07-28 16:03:47 +02005314
Christopher Faulet31af49d2015-06-09 17:29:50 +02005315 if (!bind_conf->ca_sign_file) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005316 ha_alert("Proxy '%s': cannot enable certificate generation, "
5317 "no CA certificate File configured at [%s:%d].\n",
5318 px->id, bind_conf->file, bind_conf->line);
Christopher Faulet31af49d2015-06-09 17:29:50 +02005319 goto load_error;
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005320 }
Christopher Faulet31af49d2015-06-09 17:29:50 +02005321
5322 /* read in the CA certificate */
5323 if (!(fp = fopen(bind_conf->ca_sign_file, "r"))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005324 ha_alert("Proxy '%s': Failed to read CA certificate file '%s' at [%s:%d].\n",
5325 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Faulet31af49d2015-06-09 17:29:50 +02005326 goto load_error;
5327 }
5328 if (!(cacert = PEM_read_X509(fp, NULL, NULL, NULL))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005329 ha_alert("Proxy '%s': Failed to read CA certificate file '%s' at [%s:%d].\n",
5330 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005331 goto read_error;
Christopher Faulet31af49d2015-06-09 17:29:50 +02005332 }
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005333 rewind(fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02005334 if (!(capkey = PEM_read_PrivateKey(fp, NULL, NULL, bind_conf->ca_sign_pass))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005335 ha_alert("Proxy '%s': Failed to read CA private key file '%s' at [%s:%d].\n",
5336 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005337 goto read_error;
Christopher Faulet31af49d2015-06-09 17:29:50 +02005338 }
Christopher Faulet31af49d2015-06-09 17:29:50 +02005339
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005340 fclose (fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02005341 bind_conf->ca_sign_cert = cacert;
5342 bind_conf->ca_sign_pkey = capkey;
5343 return err;
5344
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005345 read_error:
5346 fclose (fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02005347 if (capkey) EVP_PKEY_free(capkey);
5348 if (cacert) X509_free(cacert);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005349 load_error:
5350 bind_conf->generate_certs = 0;
5351 err++;
Christopher Faulet31af49d2015-06-09 17:29:50 +02005352 return err;
5353}
5354
5355/* Release CA cert and private key used to generate certificated */
5356void
5357ssl_sock_free_ca(struct bind_conf *bind_conf)
5358{
Christopher Faulet31af49d2015-06-09 17:29:50 +02005359 if (bind_conf->ca_sign_pkey)
5360 EVP_PKEY_free(bind_conf->ca_sign_pkey);
5361 if (bind_conf->ca_sign_cert)
5362 X509_free(bind_conf->ca_sign_cert);
Willy Tarreau94ff03a2016-12-22 17:57:46 +01005363 bind_conf->ca_sign_pkey = NULL;
5364 bind_conf->ca_sign_cert = NULL;
Christopher Faulet31af49d2015-06-09 17:29:50 +02005365}
5366
Emeric Brun46591952012-05-18 15:47:34 +02005367/*
5368 * This function is called if SSL * context is not yet allocated. The function
5369 * is designed to be called before any other data-layer operation and sets the
5370 * handshake flag on the connection. It is safe to call it multiple times.
5371 * It returns 0 on success and -1 in error case.
5372 */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005373static int ssl_sock_init(struct connection *conn, void **xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02005374{
Olivier Houchard66ab4982019-02-26 18:37:15 +01005375 struct ssl_sock_ctx *ctx;
Emeric Brun46591952012-05-18 15:47:34 +02005376 /* already initialized */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005377 if (*xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02005378 return 0;
5379
Willy Tarreau3c728722014-01-23 13:50:42 +01005380 if (!conn_ctrl_ready(conn))
Willy Tarreauf79c8172013-10-21 16:30:56 +02005381 return 0;
5382
Olivier Houchard66ab4982019-02-26 18:37:15 +01005383 ctx = pool_alloc(ssl_sock_ctx_pool);
5384 if (!ctx) {
5385 conn->err_code = CO_ER_SSL_NO_MEM;
5386 return -1;
5387 }
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02005388 ctx->wait_event.tasklet = tasklet_new();
5389 if (!ctx->wait_event.tasklet) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02005390 conn->err_code = CO_ER_SSL_NO_MEM;
5391 pool_free(ssl_sock_ctx_pool, ctx);
5392 return -1;
5393 }
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02005394 ctx->wait_event.tasklet->process = ssl_sock_io_cb;
5395 ctx->wait_event.tasklet->context = ctx;
Olivier Houchardea8dd942019-05-20 14:02:16 +02005396 ctx->wait_event.events = 0;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01005397 ctx->sent_early_data = 0;
5398 ctx->tmp_early_data = -1;
Olivier Houcharda8955d52019-04-07 22:00:38 +02005399 ctx->conn = conn;
Olivier Houchard81284e62019-06-06 13:21:23 +02005400 ctx->send_wait = NULL;
5401 ctx->recv_wait = NULL;
Emeric Brun5762a0d2019-09-06 15:36:02 +02005402 ctx->xprt_st = 0;
5403 ctx->xprt_ctx = NULL;
Olivier Houcharda8955d52019-04-07 22:00:38 +02005404
5405 /* Only work with sockets for now, this should be adapted when we'll
5406 * add QUIC support.
5407 */
5408 ctx->xprt = xprt_get(XPRT_RAW);
Olivier Houchard19afb272019-05-23 18:24:07 +02005409 if (ctx->xprt->init) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02005410 if (ctx->xprt->init(conn, &ctx->xprt_ctx) != 0)
5411 goto err;
Olivier Houchard19afb272019-05-23 18:24:07 +02005412 }
Olivier Houchard66ab4982019-02-26 18:37:15 +01005413
Willy Tarreau20879a02012-12-03 16:32:10 +01005414 if (global.maxsslconn && sslconns >= global.maxsslconn) {
5415 conn->err_code = CO_ER_SSL_TOO_MANY;
Olivier Houchardea8dd942019-05-20 14:02:16 +02005416 goto err;
Willy Tarreau20879a02012-12-03 16:32:10 +01005417 }
Willy Tarreau403edff2012-09-06 11:58:37 +02005418
Emeric Brun46591952012-05-18 15:47:34 +02005419 /* If it is in client mode initiate SSL session
5420 in connect state otherwise accept state */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01005421 if (objt_server(conn->target)) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005422 int may_retry = 1;
5423
5424 retry_connect:
Emeric Brun46591952012-05-18 15:47:34 +02005425 /* Alloc a new SSL session ctx */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005426 ctx->ssl = SSL_new(__objt_server(conn->target)->ssl_ctx.ctx);
5427 if (!ctx->ssl) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005428 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005429 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005430 goto retry_connect;
5431 }
Willy Tarreau20879a02012-12-03 16:32:10 +01005432 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01005433 goto err;
Willy Tarreau20879a02012-12-03 16:32:10 +01005434 }
Olivier Houcharda8955d52019-04-07 22:00:38 +02005435 ctx->bio = BIO_new(ha_meth);
5436 if (!ctx->bio) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005437 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005438 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005439 goto retry_connect;
5440 }
Emeric Brun55476152014-11-12 17:35:37 +01005441 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01005442 goto err;
Emeric Brun55476152014-11-12 17:35:37 +01005443 }
Olivier Houcharda8955d52019-04-07 22:00:38 +02005444 BIO_set_data(ctx->bio, ctx);
Olivier Houcharda8955d52019-04-07 22:00:38 +02005445 SSL_set_bio(ctx->ssl, ctx->bio, ctx->bio);
Emeric Brun46591952012-05-18 15:47:34 +02005446
Evan Broderbe554312013-06-27 00:05:25 -07005447 /* set connection pointer */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005448 if (!SSL_set_ex_data(ctx->ssl, ssl_app_data_index, conn)) {
5449 SSL_free(ctx->ssl);
5450 ctx->ssl = NULL;
Emeric Brun55476152014-11-12 17:35:37 +01005451 conn->xprt_ctx = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005452 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005453 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005454 goto retry_connect;
5455 }
Emeric Brun55476152014-11-12 17:35:37 +01005456 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01005457 goto err;
Emeric Brun55476152014-11-12 17:35:37 +01005458 }
5459
Olivier Houchard66ab4982019-02-26 18:37:15 +01005460 SSL_set_connect_state(ctx->ssl);
Willy Tarreau07d94e42018-09-20 10:57:52 +02005461 if (__objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr) {
5462 const unsigned char *ptr = __objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr;
5463 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 +01005464 if (sess && !SSL_set_session(ctx->ssl, sess)) {
Olivier Houcharde6060c52017-11-16 17:42:52 +01005465 SSL_SESSION_free(sess);
Willy Tarreau07d94e42018-09-20 10:57:52 +02005466 free(__objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr);
5467 __objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr = NULL;
Olivier Houcharde6060c52017-11-16 17:42:52 +01005468 } else if (sess) {
5469 SSL_SESSION_free(sess);
Emeric Brun55476152014-11-12 17:35:37 +01005470 }
5471 }
Evan Broderbe554312013-06-27 00:05:25 -07005472
Emeric Brun46591952012-05-18 15:47:34 +02005473 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +02005474 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Willy Tarreau403edff2012-09-06 11:58:37 +02005475
Olivier Houchard2be5a4c2019-03-08 18:54:43 +01005476 _HA_ATOMIC_ADD(&sslconns, 1);
5477 _HA_ATOMIC_ADD(&totalsslconns, 1);
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005478 *xprt_ctx = ctx;
Olivier Houchardea8dd942019-05-20 14:02:16 +02005479 /* Start the handshake */
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02005480 tasklet_wakeup(ctx->wait_event.tasklet);
Olivier Houchardea8dd942019-05-20 14:02:16 +02005481 if (conn->flags & CO_FL_ERROR)
5482 goto err;
Emeric Brun46591952012-05-18 15:47:34 +02005483 return 0;
5484 }
Willy Tarreau3fdb3662012-11-12 00:42:33 +01005485 else if (objt_listener(conn->target)) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005486 int may_retry = 1;
5487
5488 retry_accept:
Emeric Brun46591952012-05-18 15:47:34 +02005489 /* Alloc a new SSL session ctx */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005490 ctx->ssl = SSL_new(__objt_listener(conn->target)->bind_conf->initial_ctx);
5491 if (!ctx->ssl) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005492 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005493 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005494 goto retry_accept;
5495 }
Willy Tarreau20879a02012-12-03 16:32:10 +01005496 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01005497 goto err;
Willy Tarreau20879a02012-12-03 16:32:10 +01005498 }
Emeric Brun46591952012-05-18 15:47:34 +02005499
Olivier Houcharda8955d52019-04-07 22:00:38 +02005500 ctx->bio = BIO_new(ha_meth);
5501 if (!ctx->bio) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005502 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005503 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005504 goto retry_accept;
5505 }
Emeric Brun55476152014-11-12 17:35:37 +01005506 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01005507 goto err;
Emeric Brun55476152014-11-12 17:35:37 +01005508 }
Olivier Houcharda8955d52019-04-07 22:00:38 +02005509 BIO_set_data(ctx->bio, ctx);
Olivier Houcharda8955d52019-04-07 22:00:38 +02005510 SSL_set_bio(ctx->ssl, ctx->bio, ctx->bio);
Emeric Brun46591952012-05-18 15:47:34 +02005511
Emeric Brune1f38db2012-09-03 20:36:47 +02005512 /* set connection pointer */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005513 if (!SSL_set_ex_data(ctx->ssl, ssl_app_data_index, conn)) {
5514 SSL_free(ctx->ssl);
5515 ctx->ssl = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005516 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005517 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005518 goto retry_accept;
5519 }
Emeric Brun55476152014-11-12 17:35:37 +01005520 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01005521 goto err;
Emeric Brun55476152014-11-12 17:35:37 +01005522 }
5523
Olivier Houchard66ab4982019-02-26 18:37:15 +01005524 SSL_set_accept_state(ctx->ssl);
Emeric Brune1f38db2012-09-03 20:36:47 +02005525
Emeric Brun46591952012-05-18 15:47:34 +02005526 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +02005527 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Emmanuel Hocdetf967c312019-08-05 18:04:16 +02005528#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Olivier Houchardc2aae742017-09-22 18:26:28 +02005529 conn->flags |= CO_FL_EARLY_SSL_HS;
5530#endif
Willy Tarreau403edff2012-09-06 11:58:37 +02005531
Olivier Houchard2be5a4c2019-03-08 18:54:43 +01005532 _HA_ATOMIC_ADD(&sslconns, 1);
5533 _HA_ATOMIC_ADD(&totalsslconns, 1);
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005534 *xprt_ctx = ctx;
Olivier Houchardea8dd942019-05-20 14:02:16 +02005535 /* Start the handshake */
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02005536 tasklet_wakeup(ctx->wait_event.tasklet);
Olivier Houchardea8dd942019-05-20 14:02:16 +02005537 if (conn->flags & CO_FL_ERROR)
5538 goto err;
Emeric Brun46591952012-05-18 15:47:34 +02005539 return 0;
5540 }
5541 /* don't know how to handle such a target */
Willy Tarreau20879a02012-12-03 16:32:10 +01005542 conn->err_code = CO_ER_SSL_NO_TARGET;
Olivier Houchard66ab4982019-02-26 18:37:15 +01005543err:
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02005544 if (ctx && ctx->wait_event.tasklet)
5545 tasklet_free(ctx->wait_event.tasklet);
Olivier Houchard66ab4982019-02-26 18:37:15 +01005546 pool_free(ssl_sock_ctx_pool, ctx);
Emeric Brun46591952012-05-18 15:47:34 +02005547 return -1;
5548}
5549
5550
5551/* This is the callback which is used when an SSL handshake is pending. It
5552 * updates the FD status if it wants some polling before being called again.
5553 * It returns 0 if it fails in a fatal way or needs to poll to go further,
5554 * otherwise it returns non-zero and removes itself from the connection's
5555 * flags (the bit is provided in <flag> by the caller).
5556 */
Olivier Houchard000694c2019-05-23 14:45:12 +02005557static int ssl_sock_handshake(struct connection *conn, unsigned int flag)
Emeric Brun46591952012-05-18 15:47:34 +02005558{
Olivier Houchard66ab4982019-02-26 18:37:15 +01005559 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
Emeric Brun46591952012-05-18 15:47:34 +02005560 int ret;
5561
Willy Tarreau3c728722014-01-23 13:50:42 +01005562 if (!conn_ctrl_ready(conn))
Willy Tarreauf79c8172013-10-21 16:30:56 +02005563 return 0;
5564
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005565 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02005566 goto out_error;
5567
Willy Tarreau5db847a2019-05-09 14:13:35 +02005568#if HA_OPENSSL_VERSION_NUMBER >= 0x10101000L
Olivier Houchardc2aae742017-09-22 18:26:28 +02005569 /*
5570 * Check if we have early data. If we do, we have to read them
5571 * before SSL_do_handshake() is called, And there's no way to
5572 * detect early data, except to try to read them
5573 */
5574 if (conn->flags & CO_FL_EARLY_SSL_HS) {
5575 size_t read_data;
5576
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01005577 ret = SSL_read_early_data(ctx->ssl, &ctx->tmp_early_data,
Olivier Houchardc2aae742017-09-22 18:26:28 +02005578 1, &read_data);
5579 if (ret == SSL_READ_EARLY_DATA_ERROR)
5580 goto check_error;
5581 if (ret == SSL_READ_EARLY_DATA_SUCCESS) {
5582 conn->flags &= ~(CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN);
5583 return 1;
5584 } else
5585 conn->flags &= ~CO_FL_EARLY_SSL_HS;
5586 }
5587#endif
Emeric Brun674b7432012-11-08 19:21:55 +01005588 /* If we use SSL_do_handshake to process a reneg initiated by
5589 * the remote peer, it sometimes returns SSL_ERROR_SSL.
5590 * Usually SSL_write and SSL_read are used and process implicitly
5591 * the reneg handshake.
5592 * Here we use SSL_peek as a workaround for reneg.
5593 */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005594 if ((conn->flags & CO_FL_CONNECTED) && SSL_renegotiate_pending(ctx->ssl)) {
Emeric Brun674b7432012-11-08 19:21:55 +01005595 char c;
5596
Olivier Houchard66ab4982019-02-26 18:37:15 +01005597 ret = SSL_peek(ctx->ssl, &c, 1);
Emeric Brun674b7432012-11-08 19:21:55 +01005598 if (ret <= 0) {
5599 /* handshake may have not been completed, let's find why */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005600 ret = SSL_get_error(ctx->ssl, ret);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005601
Emeric Brun674b7432012-11-08 19:21:55 +01005602 if (ret == SSL_ERROR_WANT_WRITE) {
5603 /* SSL handshake needs to write, L4 connection may not be ready */
Olivier Houchard03abf2d2019-05-28 10:12:02 +02005604 if (!(ctx->wait_event.events & SUB_RETRY_SEND))
Olivier Houchardea8dd942019-05-20 14:02:16 +02005605 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_SEND, &ctx->wait_event);
Emeric Brun674b7432012-11-08 19:21:55 +01005606 return 0;
5607 }
5608 else if (ret == SSL_ERROR_WANT_READ) {
5609 /* handshake may have been completed but we have
5610 * no more data to read.
5611 */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005612 if (!SSL_renegotiate_pending(ctx->ssl)) {
Emeric Brun674b7432012-11-08 19:21:55 +01005613 ret = 1;
5614 goto reneg_ok;
5615 }
5616 /* SSL handshake needs to read, L4 connection is ready */
Olivier Houchard03abf2d2019-05-28 10:12:02 +02005617 if (!(ctx->wait_event.events & SUB_RETRY_RECV))
Olivier Houchardea8dd942019-05-20 14:02:16 +02005618 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_RECV, &ctx->wait_event);
Emeric Brun674b7432012-11-08 19:21:55 +01005619 return 0;
5620 }
Willy Tarreau5db847a2019-05-09 14:13:35 +02005621#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005622 else if (ret == SSL_ERROR_WANT_ASYNC) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02005623 ssl_async_process_fds(ctx);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005624 return 0;
5625 }
5626#endif
Emeric Brun674b7432012-11-08 19:21:55 +01005627 else if (ret == SSL_ERROR_SYSCALL) {
5628 /* if errno is null, then connection was successfully established */
5629 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
5630 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Willy Tarreau20879a02012-12-03 16:32:10 +01005631 if (!conn->err_code) {
Lukas Tribus49799162019-07-08 14:29:15 +02005632#if defined(OPENSSL_IS_BORINGSSL) || defined(LIBRESSL_VERSION_NUMBER)
5633 /* do not handle empty handshakes in BoringSSL or LibreSSL */
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005634 conn->err_code = CO_ER_SSL_HANDSHAKE;
5635#else
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005636 int empty_handshake;
Willy Tarreau5db847a2019-05-09 14:13:35 +02005637#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL)
Lukas Tribus49799162019-07-08 14:29:15 +02005638 /* use SSL_get_state() in OpenSSL >= 1.1.0; SSL_state() is broken */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005639 OSSL_HANDSHAKE_STATE state = SSL_get_state((SSL *)ctx->ssl);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005640 empty_handshake = state == TLS_ST_BEFORE;
5641#else
Lukas Tribus49799162019-07-08 14:29:15 +02005642 /* access packet_length directly in OpenSSL <= 1.0.2; SSL_state() is broken */
5643 empty_handshake = !ctx->ssl->packet_length;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005644#endif
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005645 if (empty_handshake) {
Emeric Brun29f037d2014-04-25 19:05:36 +02005646 if (!errno) {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01005647 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emeric Brun29f037d2014-04-25 19:05:36 +02005648 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5649 else
5650 conn->err_code = CO_ER_SSL_EMPTY;
5651 }
5652 else {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01005653 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emeric Brun29f037d2014-04-25 19:05:36 +02005654 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5655 else
5656 conn->err_code = CO_ER_SSL_ABORT;
5657 }
5658 }
5659 else {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01005660 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emeric Brun29f037d2014-04-25 19:05:36 +02005661 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
Willy Tarreau20879a02012-12-03 16:32:10 +01005662 else
Emeric Brun29f037d2014-04-25 19:05:36 +02005663 conn->err_code = CO_ER_SSL_HANDSHAKE;
5664 }
Lukas Tribus49799162019-07-08 14:29:15 +02005665#endif /* BoringSSL or LibreSSL */
Willy Tarreau20879a02012-12-03 16:32:10 +01005666 }
Emeric Brun674b7432012-11-08 19:21:55 +01005667 goto out_error;
5668 }
5669 else {
5670 /* Fail on all other handshake errors */
5671 /* Note: OpenSSL may leave unread bytes in the socket's
5672 * buffer, causing an RST to be emitted upon close() on
5673 * TCP sockets. We first try to drain possibly pending
5674 * data to avoid this as much as possible.
5675 */
Willy Tarreaud85c4852015-03-13 00:40:28 +01005676 conn_sock_drain(conn);
Willy Tarreau20879a02012-12-03 16:32:10 +01005677 if (!conn->err_code)
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01005678 conn->err_code = (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT) ?
Willy Tarreauf51c6982014-04-25 20:02:39 +02005679 CO_ER_SSL_KILLED_HB : CO_ER_SSL_HANDSHAKE;
Emeric Brun674b7432012-11-08 19:21:55 +01005680 goto out_error;
5681 }
5682 }
5683 /* read some data: consider handshake completed */
5684 goto reneg_ok;
5685 }
Olivier Houchard66ab4982019-02-26 18:37:15 +01005686 ret = SSL_do_handshake(ctx->ssl);
Olivier Houchardc2aae742017-09-22 18:26:28 +02005687check_error:
Emeric Brun46591952012-05-18 15:47:34 +02005688 if (ret != 1) {
5689 /* handshake did not complete, let's find why */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005690 ret = SSL_get_error(ctx->ssl, ret);
Emeric Brun46591952012-05-18 15:47:34 +02005691
5692 if (ret == SSL_ERROR_WANT_WRITE) {
5693 /* SSL handshake needs to write, L4 connection may not be ready */
Olivier Houchard03abf2d2019-05-28 10:12:02 +02005694 if (!(ctx->wait_event.events & SUB_RETRY_SEND))
Olivier Houchardea8dd942019-05-20 14:02:16 +02005695 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_SEND, &ctx->wait_event);
Emeric Brun46591952012-05-18 15:47:34 +02005696 return 0;
5697 }
5698 else if (ret == SSL_ERROR_WANT_READ) {
5699 /* SSL handshake needs to read, L4 connection is ready */
Olivier Houchardea8dd942019-05-20 14:02:16 +02005700 if (!(ctx->wait_event.events & SUB_RETRY_RECV))
Olivier Houchardea8dd942019-05-20 14:02:16 +02005701 ctx->xprt->subscribe(conn, ctx->xprt_ctx,
5702 SUB_RETRY_RECV, &ctx->wait_event);
Emeric Brun46591952012-05-18 15:47:34 +02005703 return 0;
5704 }
Willy Tarreau5db847a2019-05-09 14:13:35 +02005705#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005706 else if (ret == SSL_ERROR_WANT_ASYNC) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02005707 ssl_async_process_fds(ctx);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005708 return 0;
5709 }
5710#endif
Willy Tarreau89230192012-09-28 20:22:13 +02005711 else if (ret == SSL_ERROR_SYSCALL) {
5712 /* if errno is null, then connection was successfully established */
5713 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
5714 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005715 if (!conn->err_code) {
Lukas Tribus49799162019-07-08 14:29:15 +02005716#if defined(OPENSSL_IS_BORINGSSL) || defined(LIBRESSL_VERSION_NUMBER)
5717 /* do not handle empty handshakes in BoringSSL or LibreSSL */
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005718 conn->err_code = CO_ER_SSL_HANDSHAKE;
5719#else
5720 int empty_handshake;
Willy Tarreau5db847a2019-05-09 14:13:35 +02005721#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL)
Lukas Tribus49799162019-07-08 14:29:15 +02005722 /* use SSL_get_state() in OpenSSL >= 1.1.0; SSL_state() is broken */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005723 OSSL_HANDSHAKE_STATE state = SSL_get_state(ctx->ssl);
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005724 empty_handshake = state == TLS_ST_BEFORE;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005725#else
Lukas Tribus49799162019-07-08 14:29:15 +02005726 /* access packet_length directly in OpenSSL <= 1.0.2; SSL_state() is broken */
5727 empty_handshake = !ctx->ssl->packet_length;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005728#endif
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005729 if (empty_handshake) {
5730 if (!errno) {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01005731 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005732 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5733 else
5734 conn->err_code = CO_ER_SSL_EMPTY;
5735 }
5736 else {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01005737 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005738 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5739 else
5740 conn->err_code = CO_ER_SSL_ABORT;
5741 }
Emeric Brun29f037d2014-04-25 19:05:36 +02005742 }
5743 else {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01005744 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emeric Brun29f037d2014-04-25 19:05:36 +02005745 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5746 else
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005747 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun29f037d2014-04-25 19:05:36 +02005748 }
Lukas Tribus49799162019-07-08 14:29:15 +02005749#endif /* BoringSSL or LibreSSL */
Emeric Brun29f037d2014-04-25 19:05:36 +02005750 }
Willy Tarreau89230192012-09-28 20:22:13 +02005751 goto out_error;
5752 }
Emeric Brun46591952012-05-18 15:47:34 +02005753 else {
5754 /* Fail on all other handshake errors */
Willy Tarreau566dc552012-10-19 20:52:18 +02005755 /* Note: OpenSSL may leave unread bytes in the socket's
5756 * buffer, causing an RST to be emitted upon close() on
5757 * TCP sockets. We first try to drain possibly pending
5758 * data to avoid this as much as possible.
5759 */
Willy Tarreaud85c4852015-03-13 00:40:28 +01005760 conn_sock_drain(conn);
Willy Tarreau20879a02012-12-03 16:32:10 +01005761 if (!conn->err_code)
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01005762 conn->err_code = (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT) ?
Willy Tarreauf51c6982014-04-25 20:02:39 +02005763 CO_ER_SSL_KILLED_HB : CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02005764 goto out_error;
5765 }
5766 }
Willy Tarreau5db847a2019-05-09 14:13:35 +02005767#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Olivier Houchard522eea72017-11-03 16:27:47 +01005768 else {
5769 /*
5770 * If the server refused the early data, we have to send a
5771 * 425 to the client, as we no longer have the data to sent
5772 * them again.
5773 */
5774 if ((conn->flags & CO_FL_EARLY_DATA) && (objt_server(conn->target))) {
Olivier Houchard66ab4982019-02-26 18:37:15 +01005775 if (SSL_get_early_data_status(ctx->ssl) == SSL_EARLY_DATA_REJECTED) {
Olivier Houchard522eea72017-11-03 16:27:47 +01005776 conn->err_code = CO_ER_SSL_EARLY_FAILED;
5777 goto out_error;
5778 }
5779 }
5780 }
5781#endif
5782
Emeric Brun46591952012-05-18 15:47:34 +02005783
Emeric Brun674b7432012-11-08 19:21:55 +01005784reneg_ok:
Emeric Brunb5e42a82017-06-06 12:35:14 +00005785
Willy Tarreau5db847a2019-05-09 14:13:35 +02005786#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00005787 /* ASYNC engine API doesn't support moving read/write
5788 * buffers. So we disable ASYNC mode right after
5789 * the handshake to avoid buffer oveflows.
5790 */
5791 if (global_ssl.async)
Olivier Houchard66ab4982019-02-26 18:37:15 +01005792 SSL_clear_mode(ctx->ssl, SSL_MODE_ASYNC);
Emeric Brunb5e42a82017-06-06 12:35:14 +00005793#endif
Emeric Brun46591952012-05-18 15:47:34 +02005794 /* Handshake succeeded */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005795 if (!SSL_session_reused(ctx->ssl)) {
Willy Tarreau0c9c2722014-05-28 12:28:58 +02005796 if (objt_server(conn->target)) {
5797 update_freq_ctr(&global.ssl_be_keys_per_sec, 1);
5798 if (global.ssl_be_keys_per_sec.curr_ctr > global.ssl_be_keys_max)
5799 global.ssl_be_keys_max = global.ssl_be_keys_per_sec.curr_ctr;
Emeric Brun46591952012-05-18 15:47:34 +02005800 }
Willy Tarreau0c9c2722014-05-28 12:28:58 +02005801 else {
5802 update_freq_ctr(&global.ssl_fe_keys_per_sec, 1);
5803 if (global.ssl_fe_keys_per_sec.curr_ctr > global.ssl_fe_keys_max)
5804 global.ssl_fe_keys_max = global.ssl_fe_keys_per_sec.curr_ctr;
5805 }
Emeric Brun46591952012-05-18 15:47:34 +02005806 }
5807
5808 /* The connection is now established at both layers, it's time to leave */
5809 conn->flags &= ~(flag | CO_FL_WAIT_L4_CONN | CO_FL_WAIT_L6_CONN);
5810 return 1;
5811
5812 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01005813 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02005814 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01005815 ERR_clear_error();
5816
Emeric Brun9fa89732012-10-04 17:09:56 +02005817 /* free resumed session if exists */
Willy Tarreau07d94e42018-09-20 10:57:52 +02005818 if (objt_server(conn->target) && __objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr) {
5819 free(__objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr);
5820 __objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr = NULL;
Emeric Brun9fa89732012-10-04 17:09:56 +02005821 }
5822
Emeric Brun46591952012-05-18 15:47:34 +02005823 /* Fail on all other handshake errors */
5824 conn->flags |= CO_FL_ERROR;
Willy Tarreau20879a02012-12-03 16:32:10 +01005825 if (!conn->err_code)
5826 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02005827 return 0;
5828}
5829
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005830static int ssl_subscribe(struct connection *conn, void *xprt_ctx, int event_type, void *param)
Olivier Houcharddf357842019-03-21 16:30:07 +01005831{
Olivier Houchardea8dd942019-05-20 14:02:16 +02005832 struct wait_event *sw;
5833 struct ssl_sock_ctx *ctx = xprt_ctx;
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005834
Olivier Houchard0ff28652019-06-24 18:57:39 +02005835 if (!ctx)
5836 return -1;
5837
Olivier Houchardea8dd942019-05-20 14:02:16 +02005838 if (event_type & SUB_RETRY_RECV) {
5839 sw = param;
5840 BUG_ON(ctx->recv_wait != NULL || (sw->events & SUB_RETRY_RECV));
5841 sw->events |= SUB_RETRY_RECV;
5842 ctx->recv_wait = sw;
5843 if (!(conn->flags & CO_FL_SSL_WAIT_HS) &&
5844 !(ctx->wait_event.events & SUB_RETRY_RECV))
5845 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_RECV, &ctx->wait_event);
5846 event_type &= ~SUB_RETRY_RECV;
5847 }
5848 if (event_type & SUB_RETRY_SEND) {
5849sw = param;
5850 BUG_ON(ctx->send_wait != NULL || (sw->events & SUB_RETRY_SEND));
5851 sw->events |= SUB_RETRY_SEND;
5852 ctx->send_wait = sw;
5853 if (!(conn->flags & CO_FL_SSL_WAIT_HS) &&
5854 !(ctx->wait_event.events & SUB_RETRY_SEND))
5855 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_SEND, &ctx->wait_event);
5856 event_type &= ~SUB_RETRY_SEND;
5857
5858 }
5859 if (event_type != 0)
5860 return -1;
5861 return 0;
Olivier Houcharddf357842019-03-21 16:30:07 +01005862}
5863
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005864static int ssl_unsubscribe(struct connection *conn, void *xprt_ctx, int event_type, void *param)
Olivier Houcharddf357842019-03-21 16:30:07 +01005865{
Olivier Houchardea8dd942019-05-20 14:02:16 +02005866 struct wait_event *sw;
5867 struct ssl_sock_ctx *ctx = xprt_ctx;
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005868
Olivier Houchardea8dd942019-05-20 14:02:16 +02005869 if (event_type & SUB_RETRY_RECV) {
5870 sw = param;
5871 BUG_ON(ctx->recv_wait != sw);
5872 ctx->recv_wait = NULL;
5873 sw->events &= ~SUB_RETRY_RECV;
5874 /* If we subscribed, and we're not doing the handshake,
5875 * then we subscribed because the upper layer asked for it,
5876 * as the upper layer is no longer interested, we can
5877 * unsubscribe too.
5878 */
5879 if (!(ctx->conn->flags & CO_FL_SSL_WAIT_HS) &&
5880 (ctx->wait_event.events & SUB_RETRY_RECV))
5881 conn_unsubscribe(conn, ctx->xprt_ctx, SUB_RETRY_RECV,
5882 &ctx->wait_event);
5883 }
5884 if (event_type & SUB_RETRY_SEND) {
5885 sw = param;
5886 BUG_ON(ctx->send_wait != sw);
5887 ctx->send_wait = NULL;
5888 sw->events &= ~SUB_RETRY_SEND;
5889 if (!(ctx->conn->flags & CO_FL_SSL_WAIT_HS) &&
5890 (ctx->wait_event.events & SUB_RETRY_SEND))
5891 conn_unsubscribe(conn, ctx->xprt_ctx, SUB_RETRY_SEND,
5892 &ctx->wait_event);
5893
5894 }
5895
5896 return 0;
Olivier Houcharddf357842019-03-21 16:30:07 +01005897}
5898
Olivier Houchard2e055482019-05-27 19:50:12 +02005899/* Use the provided XPRT as an underlying XPRT, and provide the old one.
5900 * Returns 0 on success, and non-zero on failure.
5901 */
5902static 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)
5903{
5904 struct ssl_sock_ctx *ctx = xprt_ctx;
5905
5906 if (oldxprt_ops != NULL)
5907 *oldxprt_ops = ctx->xprt;
5908 if (oldxprt_ctx != NULL)
5909 *oldxprt_ctx = ctx->xprt_ctx;
5910 ctx->xprt = toadd_ops;
5911 ctx->xprt_ctx = toadd_ctx;
5912 return 0;
5913}
5914
Olivier Houchard5149b592019-05-23 17:47:36 +02005915/* Remove the specified xprt. If if it our underlying XPRT, remove it and
5916 * return 0, otherwise just call the remove_xprt method from the underlying
5917 * XPRT.
5918 */
5919static int ssl_remove_xprt(struct connection *conn, void *xprt_ctx, void *toremove_ctx, const struct xprt_ops *newops, void *newctx)
5920{
5921 struct ssl_sock_ctx *ctx = xprt_ctx;
5922
5923 if (ctx->xprt_ctx == toremove_ctx) {
5924 ctx->xprt_ctx = newctx;
5925 ctx->xprt = newops;
5926 return 0;
5927 }
5928 return (ctx->xprt->remove_xprt(conn, ctx->xprt_ctx, toremove_ctx, newops, newctx));
5929}
5930
Olivier Houchardea8dd942019-05-20 14:02:16 +02005931static struct task *ssl_sock_io_cb(struct task *t, void *context, unsigned short state)
5932{
5933 struct ssl_sock_ctx *ctx = context;
5934
5935 /* First if we're doing an handshake, try that */
5936 if (ctx->conn->flags & CO_FL_SSL_WAIT_HS)
5937 ssl_sock_handshake(ctx->conn, CO_FL_SSL_WAIT_HS);
5938 /* If we had an error, or the handshake is done and I/O is available,
5939 * let the upper layer know.
5940 * If no mux was set up yet, and nobody subscribed, then call
5941 * xprt_done_cb() ourself if it's set, or destroy the connection,
5942 * we can't be sure conn_fd_handler() will be called again.
5943 */
5944 if ((ctx->conn->flags & CO_FL_ERROR) ||
5945 !(ctx->conn->flags & CO_FL_SSL_WAIT_HS)) {
5946 int ret = 0;
5947 int woke = 0;
5948
5949 /* On error, wake any waiter */
5950 if (ctx->recv_wait) {
5951 ctx->recv_wait->events &= ~SUB_RETRY_RECV;
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02005952 tasklet_wakeup(ctx->recv_wait->tasklet);
Olivier Houchardea8dd942019-05-20 14:02:16 +02005953 ctx->recv_wait = NULL;
5954 woke = 1;
5955 }
5956 if (ctx->send_wait) {
5957 ctx->send_wait->events &= ~SUB_RETRY_SEND;
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02005958 tasklet_wakeup(ctx->send_wait->tasklet);
Olivier Houchardea8dd942019-05-20 14:02:16 +02005959 ctx->send_wait = NULL;
5960 woke = 1;
5961 }
5962 /* If we're the first xprt for the connection, let the
5963 * upper layers know. If xprt_done_cb() is set, call it,
5964 * otherwise, we should have a mux, so call its wake
5965 * method if we didn't woke a tasklet already.
5966 */
5967 if (ctx->conn->xprt_ctx == ctx) {
5968 if (ctx->conn->xprt_done_cb)
5969 ret = ctx->conn->xprt_done_cb(ctx->conn);
5970 if (ret >= 0 && !woke && ctx->conn->mux && ctx->conn->mux->wake)
5971 ctx->conn->mux->wake(ctx->conn);
5972 return NULL;
5973 }
5974 }
5975 return NULL;
5976}
5977
Emeric Brun46591952012-05-18 15:47:34 +02005978/* Receive up to <count> bytes from connection <conn>'s socket and store them
Willy Tarreauabf08d92014-01-14 11:31:27 +01005979 * into buffer <buf>. Only one call to recv() is performed, unless the
Emeric Brun46591952012-05-18 15:47:34 +02005980 * buffer wraps, in which case a second call may be performed. The connection's
5981 * flags are updated with whatever special event is detected (error, read0,
5982 * empty). The caller is responsible for taking care of those events and
5983 * avoiding the call if inappropriate. The function does not call the
5984 * connection's polling update function, so the caller is responsible for this.
5985 */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005986static 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 +02005987{
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005988 struct ssl_sock_ctx *ctx = xprt_ctx;
Willy Tarreaubfc4d772018-07-18 11:22:03 +02005989 ssize_t ret;
5990 size_t try, done = 0;
Emeric Brun46591952012-05-18 15:47:34 +02005991
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005992 conn_refresh_polling_flags(conn);
5993
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005994 if (!ctx)
Emeric Brun46591952012-05-18 15:47:34 +02005995 goto out_error;
5996
5997 if (conn->flags & CO_FL_HANDSHAKE)
5998 /* a handshake was requested */
5999 return 0;
6000
Emeric Brun46591952012-05-18 15:47:34 +02006001 /* read the largest possible block. For this, we perform only one call
6002 * to recv() unless the buffer wraps and we exactly fill the first hunk,
6003 * in which case we accept to do it once again. A new attempt is made on
6004 * EINTR too.
6005 */
Willy Tarreau00b0fb92014-01-17 11:09:40 +01006006 while (count > 0) {
Olivier Houchardc2aae742017-09-22 18:26:28 +02006007 int need_out = 0;
6008
Willy Tarreau591d4452018-06-15 17:21:00 +02006009 try = b_contig_space(buf);
6010 if (!try)
6011 break;
6012
Willy Tarreauabf08d92014-01-14 11:31:27 +01006013 if (try > count)
6014 try = count;
Willy Tarreau591d4452018-06-15 17:21:00 +02006015
Olivier Houchardc2aae742017-09-22 18:26:28 +02006016 if (((conn->flags & (CO_FL_EARLY_SSL_HS | CO_FL_EARLY_DATA)) == CO_FL_EARLY_SSL_HS) &&
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006017 ctx->tmp_early_data != -1) {
6018 *b_tail(buf) = ctx->tmp_early_data;
Olivier Houchardc2aae742017-09-22 18:26:28 +02006019 done++;
6020 try--;
6021 count--;
Olivier Houchardacd14032018-06-28 18:17:23 +02006022 b_add(buf, 1);
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006023 ctx->tmp_early_data = -1;
Olivier Houchardc2aae742017-09-22 18:26:28 +02006024 continue;
6025 }
Willy Tarreauabf08d92014-01-14 11:31:27 +01006026
Willy Tarreau5db847a2019-05-09 14:13:35 +02006027#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Olivier Houchardc2aae742017-09-22 18:26:28 +02006028 if (conn->flags & CO_FL_EARLY_SSL_HS) {
6029 size_t read_length;
6030
Olivier Houchard66ab4982019-02-26 18:37:15 +01006031 ret = SSL_read_early_data(ctx->ssl,
Willy Tarreau8f9c72d2018-06-07 18:46:28 +02006032 b_tail(buf), try, &read_length);
Olivier Houchard522eea72017-11-03 16:27:47 +01006033 if (ret == SSL_READ_EARLY_DATA_SUCCESS &&
6034 read_length > 0)
Olivier Houchardc2aae742017-09-22 18:26:28 +02006035 conn->flags |= CO_FL_EARLY_DATA;
6036 if (ret == SSL_READ_EARLY_DATA_SUCCESS ||
6037 ret == SSL_READ_EARLY_DATA_FINISH) {
6038 if (ret == SSL_READ_EARLY_DATA_FINISH) {
6039 /*
6040 * We're done reading the early data,
6041 * let's make the handshake
6042 */
6043 conn->flags &= ~CO_FL_EARLY_SSL_HS;
6044 conn->flags |= CO_FL_SSL_WAIT_HS;
6045 need_out = 1;
Olivier Houchard965e84e2019-06-15 20:59:30 +02006046 /* Now initiate the handshake */
6047 tasklet_wakeup(ctx->wait_event.tasklet);
Olivier Houchardc2aae742017-09-22 18:26:28 +02006048 if (read_length == 0)
6049 break;
6050 }
6051 ret = read_length;
6052 }
6053 } else
6054#endif
Olivier Houchard66ab4982019-02-26 18:37:15 +01006055 ret = SSL_read(ctx->ssl, b_tail(buf), try);
Emmanuel Hocdetf967c312019-08-05 18:04:16 +02006056
Emeric Brune1f38db2012-09-03 20:36:47 +02006057 if (conn->flags & CO_FL_ERROR) {
6058 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01006059 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02006060 }
Emeric Brun46591952012-05-18 15:47:34 +02006061 if (ret > 0) {
Olivier Houchardacd14032018-06-28 18:17:23 +02006062 b_add(buf, ret);
Emeric Brun46591952012-05-18 15:47:34 +02006063 done += ret;
Emeric Brun46591952012-05-18 15:47:34 +02006064 count -= ret;
Emeric Brun46591952012-05-18 15:47:34 +02006065 }
Emeric Brun46591952012-05-18 15:47:34 +02006066 else {
Olivier Houchard66ab4982019-02-26 18:37:15 +01006067 ret = SSL_get_error(ctx->ssl, ret);
Emeric Brun46591952012-05-18 15:47:34 +02006068 if (ret == SSL_ERROR_WANT_WRITE) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01006069 /* handshake is running, and it needs to enable write */
Emeric Brun46591952012-05-18 15:47:34 +02006070 conn->flags |= CO_FL_SSL_WAIT_HS;
Olivier Houchardea8dd942019-05-20 14:02:16 +02006071 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_SEND, &ctx->wait_event);
Willy Tarreau5db847a2019-05-09 14:13:35 +02006072#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00006073 /* Async mode can be re-enabled, because we're leaving data state.*/
6074 if (global_ssl.async)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006075 SSL_set_mode(ctx->ssl, SSL_MODE_ASYNC);
Emeric Brunb5e42a82017-06-06 12:35:14 +00006076#endif
Emeric Brun46591952012-05-18 15:47:34 +02006077 break;
6078 }
6079 else if (ret == SSL_ERROR_WANT_READ) {
Olivier Houchard66ab4982019-02-26 18:37:15 +01006080 if (SSL_renegotiate_pending(ctx->ssl)) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02006081 ctx->xprt->subscribe(conn, ctx->xprt_ctx,
6082 SUB_RETRY_RECV,
6083 &ctx->wait_event);
Emeric Brun282a76a2012-11-08 18:02:56 +01006084 /* handshake is running, and it may need to re-enable read */
6085 conn->flags |= CO_FL_SSL_WAIT_HS;
Willy Tarreau5db847a2019-05-09 14:13:35 +02006086#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00006087 /* Async mode can be re-enabled, because we're leaving data state.*/
6088 if (global_ssl.async)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006089 SSL_set_mode(ctx->ssl, SSL_MODE_ASYNC);
Emeric Brunb5e42a82017-06-06 12:35:14 +00006090#endif
Emeric Brun282a76a2012-11-08 18:02:56 +01006091 break;
6092 }
Emeric Brun46591952012-05-18 15:47:34 +02006093 break;
Olivier Houchardc2aae742017-09-22 18:26:28 +02006094 } else if (ret == SSL_ERROR_ZERO_RETURN)
6095 goto read0;
Christopher Faulet4ac77a92018-02-19 14:25:15 +01006096 /* For SSL_ERROR_SYSCALL, make sure to clear the error
6097 * stack before shutting down the connection for
6098 * reading. */
Olivier Houchard7e2e5052018-02-13 15:17:23 +01006099 if (ret == SSL_ERROR_SYSCALL && (!errno || errno == EAGAIN))
6100 goto clear_ssl_error;
Emeric Brun46591952012-05-18 15:47:34 +02006101 /* otherwise it's a real error */
6102 goto out_error;
6103 }
Olivier Houchardc2aae742017-09-22 18:26:28 +02006104 if (need_out)
6105 break;
Emeric Brun46591952012-05-18 15:47:34 +02006106 }
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02006107 leave:
Emeric Brun46591952012-05-18 15:47:34 +02006108 return done;
6109
Christopher Faulet4ac77a92018-02-19 14:25:15 +01006110 clear_ssl_error:
6111 /* Clear openssl global errors stack */
6112 ssl_sock_dump_errors(conn);
6113 ERR_clear_error();
Emeric Brun46591952012-05-18 15:47:34 +02006114 read0:
6115 conn_sock_read0(conn);
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02006116 goto leave;
Christopher Faulet4ac77a92018-02-19 14:25:15 +01006117
Emeric Brun46591952012-05-18 15:47:34 +02006118 out_error:
Olivier Houchard7e2e5052018-02-13 15:17:23 +01006119 conn->flags |= CO_FL_ERROR;
Emeric Brun644cde02012-12-14 11:21:13 +01006120 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02006121 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01006122 ERR_clear_error();
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02006123 goto leave;
Emeric Brun46591952012-05-18 15:47:34 +02006124}
6125
6126
Willy Tarreau787db9a2018-06-14 18:31:46 +02006127/* Send up to <count> pending bytes from buffer <buf> to connection <conn>'s
6128 * socket. <flags> may contain some CO_SFL_* flags to hint the system about
6129 * other pending data for example, but this flag is ignored at the moment.
Emeric Brun46591952012-05-18 15:47:34 +02006130 * Only one call to send() is performed, unless the buffer wraps, in which case
6131 * a second call may be performed. The connection's flags are updated with
6132 * whatever special event is detected (error, empty). The caller is responsible
6133 * for taking care of those events and avoiding the call if inappropriate. The
6134 * function does not call the connection's polling update function, so the caller
Willy Tarreau787db9a2018-06-14 18:31:46 +02006135 * is responsible for this. The buffer's output is not adjusted, it's up to the
6136 * caller to take care of this. It's up to the caller to update the buffer's
6137 * contents based on the return value.
Emeric Brun46591952012-05-18 15:47:34 +02006138 */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006139static 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 +02006140{
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006141 struct ssl_sock_ctx *ctx = xprt_ctx;
Willy Tarreau787db9a2018-06-14 18:31:46 +02006142 ssize_t ret;
6143 size_t try, done;
Emeric Brun46591952012-05-18 15:47:34 +02006144
6145 done = 0;
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02006146 conn_refresh_polling_flags(conn);
Emeric Brun46591952012-05-18 15:47:34 +02006147
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006148 if (!ctx)
Emeric Brun46591952012-05-18 15:47:34 +02006149 goto out_error;
6150
Olivier Houchard010941f2019-05-03 20:56:19 +02006151 if (conn->flags & (CO_FL_HANDSHAKE | CO_FL_EARLY_SSL_HS))
Emeric Brun46591952012-05-18 15:47:34 +02006152 /* a handshake was requested */
6153 return 0;
6154
6155 /* send the largest possible block. For this we perform only one call
6156 * to send() unless the buffer wraps and we exactly fill the first hunk,
6157 * in which case we accept to do it once again.
6158 */
Willy Tarreau787db9a2018-06-14 18:31:46 +02006159 while (count) {
Willy Tarreau5db847a2019-05-09 14:13:35 +02006160#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Olivier Houchardc2aae742017-09-22 18:26:28 +02006161 size_t written_data;
6162#endif
6163
Willy Tarreau787db9a2018-06-14 18:31:46 +02006164 try = b_contig_data(buf, done);
6165 if (try > count)
6166 try = count;
Willy Tarreaubfd59462013-02-21 07:46:09 +01006167
Willy Tarreau7bed9452014-02-02 02:00:24 +01006168 if (!(flags & CO_SFL_STREAMER) &&
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006169 !(ctx->xprt_st & SSL_SOCK_SEND_UNLIMITED) &&
Willy Tarreauef934602016-12-22 23:12:01 +01006170 global_ssl.max_record && try > global_ssl.max_record) {
6171 try = global_ssl.max_record;
Willy Tarreau518cedd2014-02-17 15:43:01 +01006172 }
6173 else {
6174 /* we need to keep the information about the fact that
6175 * we're not limiting the upcoming send(), because if it
6176 * fails, we'll have to retry with at least as many data.
6177 */
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006178 ctx->xprt_st |= SSL_SOCK_SEND_UNLIMITED;
Willy Tarreau518cedd2014-02-17 15:43:01 +01006179 }
Willy Tarreaubfd59462013-02-21 07:46:09 +01006180
Willy Tarreau5db847a2019-05-09 14:13:35 +02006181#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Olivier Houchard010941f2019-05-03 20:56:19 +02006182 if (!SSL_is_init_finished(ctx->ssl) && conn_is_back(conn)) {
Olivier Houchardc2aae742017-09-22 18:26:28 +02006183 unsigned int max_early;
6184
Olivier Houchard522eea72017-11-03 16:27:47 +01006185 if (objt_listener(conn->target))
Olivier Houchard66ab4982019-02-26 18:37:15 +01006186 max_early = SSL_get_max_early_data(ctx->ssl);
Olivier Houchard522eea72017-11-03 16:27:47 +01006187 else {
Olivier Houchard66ab4982019-02-26 18:37:15 +01006188 if (SSL_get0_session(ctx->ssl))
6189 max_early = SSL_SESSION_get_max_early_data(SSL_get0_session(ctx->ssl));
Olivier Houchard522eea72017-11-03 16:27:47 +01006190 else
6191 max_early = 0;
6192 }
6193
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006194 if (try + ctx->sent_early_data > max_early) {
6195 try -= (try + ctx->sent_early_data) - max_early;
Olivier Houchard522eea72017-11-03 16:27:47 +01006196 if (try <= 0) {
Olivier Houchard010941f2019-05-03 20:56:19 +02006197 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Olivier Houchard965e84e2019-06-15 20:59:30 +02006198 tasklet_wakeup(ctx->wait_event.tasklet);
Olivier Houchardc2aae742017-09-22 18:26:28 +02006199 break;
Olivier Houchard522eea72017-11-03 16:27:47 +01006200 }
Olivier Houchardc2aae742017-09-22 18:26:28 +02006201 }
Olivier Houchard66ab4982019-02-26 18:37:15 +01006202 ret = SSL_write_early_data(ctx->ssl, b_peek(buf, done), try, &written_data);
Olivier Houchardc2aae742017-09-22 18:26:28 +02006203 if (ret == 1) {
6204 ret = written_data;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006205 ctx->sent_early_data += ret;
Olivier Houchard965e84e2019-06-15 20:59:30 +02006206 if (objt_server(conn->target)) {
Olivier Houchard522eea72017-11-03 16:27:47 +01006207 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN | CO_FL_EARLY_DATA;
Olivier Houchard965e84e2019-06-15 20:59:30 +02006208 /* Initiate the handshake, now */
6209 tasklet_wakeup(ctx->wait_event.tasklet);
6210 }
Olivier Houchard522eea72017-11-03 16:27:47 +01006211
Olivier Houchardc2aae742017-09-22 18:26:28 +02006212 }
6213
6214 } else
6215#endif
Olivier Houchard66ab4982019-02-26 18:37:15 +01006216 ret = SSL_write(ctx->ssl, b_peek(buf, done), try);
Willy Tarreau518cedd2014-02-17 15:43:01 +01006217
Emeric Brune1f38db2012-09-03 20:36:47 +02006218 if (conn->flags & CO_FL_ERROR) {
6219 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01006220 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02006221 }
Emeric Brun46591952012-05-18 15:47:34 +02006222 if (ret > 0) {
Olivier Houchardf24502b2019-01-17 19:09:11 +01006223 /* A send succeeded, so we can consier ourself connected */
6224 conn->flags |= CO_FL_CONNECTED;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006225 ctx->xprt_st &= ~SSL_SOCK_SEND_UNLIMITED;
Willy Tarreau787db9a2018-06-14 18:31:46 +02006226 count -= ret;
Emeric Brun46591952012-05-18 15:47:34 +02006227 done += ret;
Emeric Brun46591952012-05-18 15:47:34 +02006228 }
6229 else {
Olivier Houchard66ab4982019-02-26 18:37:15 +01006230 ret = SSL_get_error(ctx->ssl, ret);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006231
Emeric Brun46591952012-05-18 15:47:34 +02006232 if (ret == SSL_ERROR_WANT_WRITE) {
Olivier Houchard66ab4982019-02-26 18:37:15 +01006233 if (SSL_renegotiate_pending(ctx->ssl)) {
Emeric Brun282a76a2012-11-08 18:02:56 +01006234 /* handshake is running, and it may need to re-enable write */
6235 conn->flags |= CO_FL_SSL_WAIT_HS;
Olivier Houchardea8dd942019-05-20 14:02:16 +02006236 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_SEND, &ctx->wait_event);
Willy Tarreau5db847a2019-05-09 14:13:35 +02006237#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00006238 /* Async mode can be re-enabled, because we're leaving data state.*/
6239 if (global_ssl.async)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006240 SSL_set_mode(ctx->ssl, SSL_MODE_ASYNC);
Emeric Brunb5e42a82017-06-06 12:35:14 +00006241#endif
Emeric Brun282a76a2012-11-08 18:02:56 +01006242 break;
6243 }
Olivier Houchardea8dd942019-05-20 14:02:16 +02006244
Emeric Brun46591952012-05-18 15:47:34 +02006245 break;
6246 }
6247 else if (ret == SSL_ERROR_WANT_READ) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01006248 /* handshake is running, and it needs to enable read */
Emeric Brun46591952012-05-18 15:47:34 +02006249 conn->flags |= CO_FL_SSL_WAIT_HS;
Olivier Houchardea8dd942019-05-20 14:02:16 +02006250 ctx->xprt->subscribe(conn, ctx->xprt_ctx,
6251 SUB_RETRY_RECV,
6252 &ctx->wait_event);
Willy Tarreau5db847a2019-05-09 14:13:35 +02006253#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00006254 /* Async mode can be re-enabled, because we're leaving data state.*/
6255 if (global_ssl.async)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006256 SSL_set_mode(ctx->ssl, SSL_MODE_ASYNC);
Emeric Brunb5e42a82017-06-06 12:35:14 +00006257#endif
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006258 break;
6259 }
Emeric Brun46591952012-05-18 15:47:34 +02006260 goto out_error;
6261 }
6262 }
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02006263 leave:
Emeric Brun46591952012-05-18 15:47:34 +02006264 return done;
6265
6266 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01006267 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02006268 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01006269 ERR_clear_error();
6270
Emeric Brun46591952012-05-18 15:47:34 +02006271 conn->flags |= CO_FL_ERROR;
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02006272 goto leave;
Emeric Brun46591952012-05-18 15:47:34 +02006273}
6274
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006275static void ssl_sock_close(struct connection *conn, void *xprt_ctx) {
Emeric Brun46591952012-05-18 15:47:34 +02006276
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006277 struct ssl_sock_ctx *ctx = xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006278
Olivier Houchardea8dd942019-05-20 14:02:16 +02006279
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006280 if (ctx) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02006281 if (ctx->wait_event.events != 0)
6282 ctx->xprt->unsubscribe(ctx->conn, ctx->xprt_ctx,
6283 ctx->wait_event.events,
6284 &ctx->wait_event);
6285 if (ctx->send_wait) {
6286 ctx->send_wait->events &= ~SUB_RETRY_SEND;
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02006287 tasklet_wakeup(ctx->send_wait->tasklet);
Olivier Houchardea8dd942019-05-20 14:02:16 +02006288 }
6289 if (ctx->recv_wait) {
6290 ctx->recv_wait->events &= ~SUB_RETRY_RECV;
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02006291 tasklet_wakeup(ctx->recv_wait->tasklet);
Olivier Houchardea8dd942019-05-20 14:02:16 +02006292 }
Olivier Houchard692c1d02019-05-23 18:41:47 +02006293 if (ctx->xprt->close)
6294 ctx->xprt->close(conn, ctx->xprt_ctx);
Willy Tarreau5db847a2019-05-09 14:13:35 +02006295#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brun3854e012017-05-17 20:42:48 +02006296 if (global_ssl.async) {
6297 OSSL_ASYNC_FD all_fd[32], afd;
6298 size_t num_all_fds = 0;
6299 int i;
6300
Olivier Houchard66ab4982019-02-26 18:37:15 +01006301 SSL_get_all_async_fds(ctx->ssl, NULL, &num_all_fds);
Emeric Brun3854e012017-05-17 20:42:48 +02006302 if (num_all_fds > 32) {
6303 send_log(NULL, LOG_EMERG, "haproxy: openssl returns too many async fds. It seems a bug. Process may crash\n");
6304 return;
6305 }
6306
Olivier Houchard66ab4982019-02-26 18:37:15 +01006307 SSL_get_all_async_fds(ctx->ssl, all_fd, &num_all_fds);
Emeric Brun3854e012017-05-17 20:42:48 +02006308
6309 /* If an async job is pending, we must try to
6310 to catch the end using polling before calling
6311 SSL_free */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006312 if (num_all_fds && SSL_waiting_for_async(ctx->ssl)) {
Emeric Brun3854e012017-05-17 20:42:48 +02006313 for (i=0 ; i < num_all_fds ; i++) {
6314 /* switch on an handler designed to
6315 * handle the SSL_free
6316 */
6317 afd = all_fd[i];
6318 fdtab[afd].iocb = ssl_async_fd_free;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006319 fdtab[afd].owner = ctx->ssl;
Emeric Brun3854e012017-05-17 20:42:48 +02006320 fd_want_recv(afd);
Emeric Brunce9e01c2017-05-31 10:02:53 +00006321 /* To ensure that the fd cache won't be used
6322 * and we'll catch a real RD event.
6323 */
6324 fd_cant_recv(afd);
Emeric Brun3854e012017-05-17 20:42:48 +02006325 }
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02006326 tasklet_free(ctx->wait_event.tasklet);
Olivier Houchard66ab4982019-02-26 18:37:15 +01006327 pool_free(ssl_sock_ctx_pool, ctx);
Olivier Houchard2be5a4c2019-03-08 18:54:43 +01006328 _HA_ATOMIC_ADD(&jobs, 1);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006329 return;
6330 }
Emeric Brun3854e012017-05-17 20:42:48 +02006331 /* Else we can remove the fds from the fdtab
6332 * and call SSL_free.
6333 * note: we do a fd_remove and not a delete
6334 * because the fd is owned by the engine.
6335 * the engine is responsible to close
6336 */
6337 for (i=0 ; i < num_all_fds ; i++)
6338 fd_remove(all_fd[i]);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006339 }
6340#endif
Olivier Houchard66ab4982019-02-26 18:37:15 +01006341 SSL_free(ctx->ssl);
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02006342 tasklet_free(ctx->wait_event.tasklet);
Olivier Houchard66ab4982019-02-26 18:37:15 +01006343 pool_free(ssl_sock_ctx_pool, ctx);
Olivier Houchard2be5a4c2019-03-08 18:54:43 +01006344 _HA_ATOMIC_SUB(&sslconns, 1);
Emeric Brun46591952012-05-18 15:47:34 +02006345 }
Emeric Brun46591952012-05-18 15:47:34 +02006346}
6347
6348/* This function tries to perform a clean shutdown on an SSL connection, and in
6349 * any case, flags the connection as reusable if no handshake was in progress.
6350 */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006351static void ssl_sock_shutw(struct connection *conn, void *xprt_ctx, int clean)
Emeric Brun46591952012-05-18 15:47:34 +02006352{
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006353 struct ssl_sock_ctx *ctx = xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006354
Emeric Brun46591952012-05-18 15:47:34 +02006355 if (conn->flags & CO_FL_HANDSHAKE)
6356 return;
Emmanuel Hocdet405ff312017-01-08 14:07:39 +01006357 if (!clean)
6358 /* don't sent notify on SSL_shutdown */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006359 SSL_set_quiet_shutdown(ctx->ssl, 1);
Emeric Brun46591952012-05-18 15:47:34 +02006360 /* no handshake was in progress, try a clean ssl shutdown */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006361 if (SSL_shutdown(ctx->ssl) <= 0) {
Emeric Brun644cde02012-12-14 11:21:13 +01006362 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02006363 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01006364 ERR_clear_error();
6365 }
Emeric Brun46591952012-05-18 15:47:34 +02006366}
6367
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01006368/* used for ppv2 pkey alog (can be used for logging) */
Willy Tarreau83061a82018-07-13 11:56:34 +02006369int ssl_sock_get_pkey_algo(struct connection *conn, struct buffer *out)
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01006370{
Christopher Faulet82004142019-09-10 10:12:03 +02006371 struct ssl_sock_ctx *ctx;
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01006372 struct pkey_info *pkinfo;
6373 int bits = 0;
6374 int sig = TLSEXT_signature_anonymous;
6375 int len = -1;
6376
6377 if (!ssl_sock_is_ssl(conn))
6378 return 0;
Christopher Faulet82004142019-09-10 10:12:03 +02006379 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006380 pkinfo = SSL_CTX_get_ex_data(SSL_get_SSL_CTX(ctx->ssl), ssl_pkey_info_index);
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01006381 if (pkinfo) {
6382 sig = pkinfo->sig;
6383 bits = pkinfo->bits;
6384 } else {
6385 /* multicert and generated cert have no pkey info */
6386 X509 *crt;
6387 EVP_PKEY *pkey;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006388 crt = SSL_get_certificate(ctx->ssl);
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01006389 if (!crt)
6390 return 0;
6391 pkey = X509_get_pubkey(crt);
6392 if (pkey) {
6393 bits = EVP_PKEY_bits(pkey);
6394 switch(EVP_PKEY_base_id(pkey)) {
6395 case EVP_PKEY_RSA:
6396 sig = TLSEXT_signature_rsa;
6397 break;
6398 case EVP_PKEY_EC:
6399 sig = TLSEXT_signature_ecdsa;
6400 break;
6401 case EVP_PKEY_DSA:
6402 sig = TLSEXT_signature_dsa;
6403 break;
6404 }
6405 EVP_PKEY_free(pkey);
6406 }
6407 }
6408
6409 switch(sig) {
6410 case TLSEXT_signature_rsa:
6411 len = chunk_printf(out, "RSA%d", bits);
6412 break;
6413 case TLSEXT_signature_ecdsa:
6414 len = chunk_printf(out, "EC%d", bits);
6415 break;
6416 case TLSEXT_signature_dsa:
6417 len = chunk_printf(out, "DSA%d", bits);
6418 break;
6419 default:
6420 return 0;
6421 }
6422 if (len < 0)
6423 return 0;
6424 return 1;
6425}
6426
Emmanuel Hocdet283e0042017-11-02 14:05:23 +01006427/* used for ppv2 cert signature (can be used for logging) */
6428const char *ssl_sock_get_cert_sig(struct connection *conn)
6429{
Christopher Faulet82004142019-09-10 10:12:03 +02006430 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006431
Emmanuel Hocdet283e0042017-11-02 14:05:23 +01006432 __OPENSSL_110_CONST__ ASN1_OBJECT *algorithm;
6433 X509 *crt;
6434
6435 if (!ssl_sock_is_ssl(conn))
6436 return NULL;
Christopher Faulet82004142019-09-10 10:12:03 +02006437 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006438 crt = SSL_get_certificate(ctx->ssl);
Emmanuel Hocdet283e0042017-11-02 14:05:23 +01006439 if (!crt)
6440 return NULL;
6441 X509_ALGOR_get0(&algorithm, NULL, NULL, X509_get0_tbs_sigalg(crt));
6442 return OBJ_nid2sn(OBJ_obj2nid(algorithm));
6443}
6444
Emmanuel Hocdet253c3b72018-02-01 18:29:59 +01006445/* used for ppv2 authority */
6446const char *ssl_sock_get_sni(struct connection *conn)
6447{
6448#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Christopher Faulet82004142019-09-10 10:12:03 +02006449 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006450
Emmanuel Hocdet253c3b72018-02-01 18:29:59 +01006451 if (!ssl_sock_is_ssl(conn))
6452 return NULL;
Christopher Faulet82004142019-09-10 10:12:03 +02006453 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006454 return SSL_get_servername(ctx->ssl, TLSEXT_NAMETYPE_host_name);
Emmanuel Hocdet253c3b72018-02-01 18:29:59 +01006455#else
Olivier Houchard66ab4982019-02-26 18:37:15 +01006456 return NULL;
Emmanuel Hocdet253c3b72018-02-01 18:29:59 +01006457#endif
6458}
6459
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02006460/* used for logging/ppv2, may be changed for a sample fetch later */
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02006461const char *ssl_sock_get_cipher_name(struct connection *conn)
6462{
Christopher Faulet82004142019-09-10 10:12:03 +02006463 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006464
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02006465 if (!ssl_sock_is_ssl(conn))
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02006466 return NULL;
Christopher Faulet82004142019-09-10 10:12:03 +02006467 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006468 return SSL_get_cipher_name(ctx->ssl);
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02006469}
6470
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02006471/* used for logging/ppv2, may be changed for a sample fetch later */
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02006472const char *ssl_sock_get_proto_version(struct connection *conn)
6473{
Christopher Faulet82004142019-09-10 10:12:03 +02006474 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006475
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02006476 if (!ssl_sock_is_ssl(conn))
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02006477 return NULL;
Christopher Faulet82004142019-09-10 10:12:03 +02006478 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006479 return SSL_get_version(ctx->ssl);
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02006480}
6481
Willy Tarreau8d598402012-10-22 17:58:39 +02006482/* Extract a serial from a cert, and copy it to a chunk.
6483 * Returns 1 if serial is found and copied, 0 if no serial found and
6484 * -1 if output is not large enough.
6485 */
6486static int
Willy Tarreau83061a82018-07-13 11:56:34 +02006487ssl_sock_get_serial(X509 *crt, struct buffer *out)
Willy Tarreau8d598402012-10-22 17:58:39 +02006488{
6489 ASN1_INTEGER *serial;
6490
6491 serial = X509_get_serialNumber(crt);
6492 if (!serial)
6493 return 0;
6494
6495 if (out->size < serial->length)
6496 return -1;
6497
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006498 memcpy(out->area, serial->data, serial->length);
6499 out->data = serial->length;
Willy Tarreau8d598402012-10-22 17:58:39 +02006500 return 1;
6501}
6502
Emeric Brun43e79582014-10-29 19:03:26 +01006503/* Extract a cert to der, and copy it to a chunk.
Joseph Herlant017b3da2018-11-15 09:07:59 -08006504 * Returns 1 if the cert is found and copied, 0 on der conversion failure
6505 * and -1 if the output is not large enough.
Emeric Brun43e79582014-10-29 19:03:26 +01006506 */
6507static int
Willy Tarreau83061a82018-07-13 11:56:34 +02006508ssl_sock_crt2der(X509 *crt, struct buffer *out)
Emeric Brun43e79582014-10-29 19:03:26 +01006509{
6510 int len;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006511 unsigned char *p = (unsigned char *) out->area;;
Emeric Brun43e79582014-10-29 19:03:26 +01006512
6513 len =i2d_X509(crt, NULL);
6514 if (len <= 0)
6515 return 1;
6516
6517 if (out->size < len)
6518 return -1;
6519
6520 i2d_X509(crt,&p);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006521 out->data = len;
Emeric Brun43e79582014-10-29 19:03:26 +01006522 return 1;
6523}
6524
Emeric Brunce5ad802012-10-22 14:11:22 +02006525
Willy Tarreau83061a82018-07-13 11:56:34 +02006526/* Copy Date in ASN1_UTCTIME format in struct buffer out.
Emeric Brunce5ad802012-10-22 14:11:22 +02006527 * Returns 1 if serial is found and copied, 0 if no valid time found
6528 * and -1 if output is not large enough.
6529 */
6530static int
Willy Tarreau83061a82018-07-13 11:56:34 +02006531ssl_sock_get_time(ASN1_TIME *tm, struct buffer *out)
Emeric Brunce5ad802012-10-22 14:11:22 +02006532{
6533 if (tm->type == V_ASN1_GENERALIZEDTIME) {
6534 ASN1_GENERALIZEDTIME *gentm = (ASN1_GENERALIZEDTIME *)tm;
6535
6536 if (gentm->length < 12)
6537 return 0;
6538 if (gentm->data[0] != 0x32 || gentm->data[1] != 0x30)
6539 return 0;
6540 if (out->size < gentm->length-2)
6541 return -1;
6542
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006543 memcpy(out->area, gentm->data+2, gentm->length-2);
6544 out->data = gentm->length-2;
Emeric Brunce5ad802012-10-22 14:11:22 +02006545 return 1;
6546 }
6547 else if (tm->type == V_ASN1_UTCTIME) {
6548 ASN1_UTCTIME *utctm = (ASN1_UTCTIME *)tm;
6549
6550 if (utctm->length < 10)
6551 return 0;
6552 if (utctm->data[0] >= 0x35)
6553 return 0;
6554 if (out->size < utctm->length)
6555 return -1;
6556
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006557 memcpy(out->area, utctm->data, utctm->length);
6558 out->data = utctm->length;
Emeric Brunce5ad802012-10-22 14:11:22 +02006559 return 1;
6560 }
6561
6562 return 0;
6563}
6564
Emeric Brun87855892012-10-17 17:39:35 +02006565/* Extract an entry from a X509_NAME and copy its value to an output chunk.
6566 * Returns 1 if entry found, 0 if entry not found, or -1 if output not large enough.
6567 */
6568static int
Willy Tarreau83061a82018-07-13 11:56:34 +02006569ssl_sock_get_dn_entry(X509_NAME *a, const struct buffer *entry, int pos,
6570 struct buffer *out)
Emeric Brun87855892012-10-17 17:39:35 +02006571{
6572 X509_NAME_ENTRY *ne;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006573 ASN1_OBJECT *obj;
6574 ASN1_STRING *data;
6575 const unsigned char *data_ptr;
6576 int data_len;
Emeric Brun87855892012-10-17 17:39:35 +02006577 int i, j, n;
6578 int cur = 0;
6579 const char *s;
6580 char tmp[128];
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006581 int name_count;
6582
6583 name_count = X509_NAME_entry_count(a);
Emeric Brun87855892012-10-17 17:39:35 +02006584
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006585 out->data = 0;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006586 for (i = 0; i < name_count; i++) {
Emeric Brun87855892012-10-17 17:39:35 +02006587 if (pos < 0)
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006588 j = (name_count-1) - i;
Emeric Brun87855892012-10-17 17:39:35 +02006589 else
6590 j = i;
6591
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006592 ne = X509_NAME_get_entry(a, j);
6593 obj = X509_NAME_ENTRY_get_object(ne);
6594 data = X509_NAME_ENTRY_get_data(ne);
6595 data_ptr = ASN1_STRING_get0_data(data);
6596 data_len = ASN1_STRING_length(data);
6597 n = OBJ_obj2nid(obj);
Emeric Brun87855892012-10-17 17:39:35 +02006598 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006599 i2t_ASN1_OBJECT(tmp, sizeof(tmp), obj);
Emeric Brun87855892012-10-17 17:39:35 +02006600 s = tmp;
6601 }
6602
6603 if (chunk_strcasecmp(entry, s) != 0)
6604 continue;
6605
6606 if (pos < 0)
6607 cur--;
6608 else
6609 cur++;
6610
6611 if (cur != pos)
6612 continue;
6613
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006614 if (data_len > out->size)
Emeric Brun87855892012-10-17 17:39:35 +02006615 return -1;
6616
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006617 memcpy(out->area, data_ptr, data_len);
6618 out->data = data_len;
Emeric Brun87855892012-10-17 17:39:35 +02006619 return 1;
6620 }
6621
6622 return 0;
6623
6624}
6625
6626/* Extract and format full DN from a X509_NAME and copy result into a chunk
6627 * Returns 1 if dn entries exits, 0 if no dn entry found or -1 if output is not large enough.
6628 */
6629static int
Willy Tarreau83061a82018-07-13 11:56:34 +02006630ssl_sock_get_dn_oneline(X509_NAME *a, struct buffer *out)
Emeric Brun87855892012-10-17 17:39:35 +02006631{
6632 X509_NAME_ENTRY *ne;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006633 ASN1_OBJECT *obj;
6634 ASN1_STRING *data;
6635 const unsigned char *data_ptr;
6636 int data_len;
Emeric Brun87855892012-10-17 17:39:35 +02006637 int i, n, ln;
6638 int l = 0;
6639 const char *s;
6640 char *p;
6641 char tmp[128];
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006642 int name_count;
6643
6644
6645 name_count = X509_NAME_entry_count(a);
Emeric Brun87855892012-10-17 17:39:35 +02006646
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006647 out->data = 0;
6648 p = out->area;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006649 for (i = 0; i < name_count; i++) {
6650 ne = X509_NAME_get_entry(a, i);
6651 obj = X509_NAME_ENTRY_get_object(ne);
6652 data = X509_NAME_ENTRY_get_data(ne);
6653 data_ptr = ASN1_STRING_get0_data(data);
6654 data_len = ASN1_STRING_length(data);
6655 n = OBJ_obj2nid(obj);
Emeric Brun87855892012-10-17 17:39:35 +02006656 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006657 i2t_ASN1_OBJECT(tmp, sizeof(tmp), obj);
Emeric Brun87855892012-10-17 17:39:35 +02006658 s = tmp;
6659 }
6660 ln = strlen(s);
6661
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006662 l += 1 + ln + 1 + data_len;
Emeric Brun87855892012-10-17 17:39:35 +02006663 if (l > out->size)
6664 return -1;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006665 out->data = l;
Emeric Brun87855892012-10-17 17:39:35 +02006666
6667 *(p++)='/';
6668 memcpy(p, s, ln);
6669 p += ln;
6670 *(p++)='=';
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006671 memcpy(p, data_ptr, data_len);
6672 p += data_len;
Emeric Brun87855892012-10-17 17:39:35 +02006673 }
6674
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006675 if (!out->data)
Emeric Brun87855892012-10-17 17:39:35 +02006676 return 0;
6677
6678 return 1;
6679}
6680
Olivier Houchardab28a322018-12-21 19:45:40 +01006681void ssl_sock_set_alpn(struct connection *conn, const unsigned char *alpn, int len)
6682{
6683#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Christopher Faulet82004142019-09-10 10:12:03 +02006684 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006685
Olivier Houcharde488ea82019-06-28 14:10:33 +02006686 if (!ssl_sock_is_ssl(conn))
6687 return;
Christopher Faulet82004142019-09-10 10:12:03 +02006688 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006689 SSL_set_alpn_protos(ctx->ssl, alpn, len);
Olivier Houchardab28a322018-12-21 19:45:40 +01006690#endif
6691}
6692
Willy Tarreau119a4082016-12-22 21:58:38 +01006693/* Sets advertised SNI for outgoing connections. Please set <hostname> to NULL
6694 * to disable SNI.
6695 */
Willy Tarreau63076412015-07-10 11:33:32 +02006696void ssl_sock_set_servername(struct connection *conn, const char *hostname)
6697{
6698#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Christopher Faulet82004142019-09-10 10:12:03 +02006699 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006700
Willy Tarreau119a4082016-12-22 21:58:38 +01006701 char *prev_name;
6702
Willy Tarreau63076412015-07-10 11:33:32 +02006703 if (!ssl_sock_is_ssl(conn))
6704 return;
Christopher Faulet82004142019-09-10 10:12:03 +02006705 ctx = conn->xprt_ctx;
Willy Tarreau63076412015-07-10 11:33:32 +02006706
Willy Tarreau119a4082016-12-22 21:58:38 +01006707 /* if the SNI changes, we must destroy the reusable context so that a
6708 * new connection will present a new SNI. As an optimization we could
6709 * later imagine having a small cache of ssl_ctx to hold a few SNI per
6710 * server.
6711 */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006712 prev_name = (char *)SSL_get_servername(ctx->ssl, TLSEXT_NAMETYPE_host_name);
Willy Tarreau119a4082016-12-22 21:58:38 +01006713 if ((!prev_name && hostname) ||
6714 (prev_name && (!hostname || strcmp(hostname, prev_name) != 0)))
Olivier Houchard66ab4982019-02-26 18:37:15 +01006715 SSL_set_session(ctx->ssl, NULL);
Willy Tarreau119a4082016-12-22 21:58:38 +01006716
Olivier Houchard66ab4982019-02-26 18:37:15 +01006717 SSL_set_tlsext_host_name(ctx->ssl, hostname);
Willy Tarreau63076412015-07-10 11:33:32 +02006718#endif
6719}
6720
Emeric Brun0abf8362014-06-24 18:26:41 +02006721/* Extract peer certificate's common name into the chunk dest
6722 * Returns
6723 * the len of the extracted common name
6724 * or 0 if no CN found in DN
6725 * or -1 on error case (i.e. no peer certificate)
6726 */
Willy Tarreau83061a82018-07-13 11:56:34 +02006727int ssl_sock_get_remote_common_name(struct connection *conn,
6728 struct buffer *dest)
David Safb76832014-05-08 23:42:08 -04006729{
Christopher Faulet82004142019-09-10 10:12:03 +02006730 struct ssl_sock_ctx *ctx;
David Safb76832014-05-08 23:42:08 -04006731 X509 *crt = NULL;
6732 X509_NAME *name;
David Safb76832014-05-08 23:42:08 -04006733 const char find_cn[] = "CN";
Willy Tarreau83061a82018-07-13 11:56:34 +02006734 const struct buffer find_cn_chunk = {
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006735 .area = (char *)&find_cn,
6736 .data = sizeof(find_cn)-1
David Safb76832014-05-08 23:42:08 -04006737 };
Emeric Brun0abf8362014-06-24 18:26:41 +02006738 int result = -1;
David Safb76832014-05-08 23:42:08 -04006739
6740 if (!ssl_sock_is_ssl(conn))
Emeric Brun0abf8362014-06-24 18:26:41 +02006741 goto out;
Christopher Faulet82004142019-09-10 10:12:03 +02006742 ctx = conn->xprt_ctx;
David Safb76832014-05-08 23:42:08 -04006743
6744 /* SSL_get_peer_certificate, it increase X509 * ref count */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006745 crt = SSL_get_peer_certificate(ctx->ssl);
David Safb76832014-05-08 23:42:08 -04006746 if (!crt)
6747 goto out;
6748
6749 name = X509_get_subject_name(crt);
6750 if (!name)
6751 goto out;
David Safb76832014-05-08 23:42:08 -04006752
Emeric Brun0abf8362014-06-24 18:26:41 +02006753 result = ssl_sock_get_dn_entry(name, &find_cn_chunk, 1, dest);
6754out:
David Safb76832014-05-08 23:42:08 -04006755 if (crt)
6756 X509_free(crt);
6757
6758 return result;
6759}
6760
Dave McCowan328fb582014-07-30 10:39:13 -04006761/* returns 1 if client passed a certificate for this session, 0 if not */
6762int ssl_sock_get_cert_used_sess(struct connection *conn)
6763{
Christopher Faulet82004142019-09-10 10:12:03 +02006764 struct ssl_sock_ctx *ctx;
Dave McCowan328fb582014-07-30 10:39:13 -04006765 X509 *crt = NULL;
6766
6767 if (!ssl_sock_is_ssl(conn))
6768 return 0;
Christopher Faulet82004142019-09-10 10:12:03 +02006769 ctx = conn->xprt_ctx;
Dave McCowan328fb582014-07-30 10:39:13 -04006770
6771 /* SSL_get_peer_certificate, it increase X509 * ref count */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006772 crt = SSL_get_peer_certificate(ctx->ssl);
Dave McCowan328fb582014-07-30 10:39:13 -04006773 if (!crt)
6774 return 0;
6775
6776 X509_free(crt);
6777 return 1;
6778}
6779
6780/* returns 1 if client passed a certificate for this connection, 0 if not */
6781int ssl_sock_get_cert_used_conn(struct connection *conn)
David Safb76832014-05-08 23:42:08 -04006782{
Christopher Faulet82004142019-09-10 10:12:03 +02006783 struct ssl_sock_ctx *ctx;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006784
David Safb76832014-05-08 23:42:08 -04006785 if (!ssl_sock_is_ssl(conn))
6786 return 0;
Christopher Faulet82004142019-09-10 10:12:03 +02006787 ctx = conn->xprt_ctx;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006788 return SSL_SOCK_ST_FL_VERIFY_DONE & ctx->xprt_st ? 1 : 0;
David Safb76832014-05-08 23:42:08 -04006789}
6790
6791/* returns result from SSL verify */
6792unsigned int ssl_sock_get_verify_result(struct connection *conn)
6793{
Christopher Faulet82004142019-09-10 10:12:03 +02006794 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006795
David Safb76832014-05-08 23:42:08 -04006796 if (!ssl_sock_is_ssl(conn))
6797 return (unsigned int)X509_V_ERR_APPLICATION_VERIFICATION;
Christopher Faulet82004142019-09-10 10:12:03 +02006798 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006799 return (unsigned int)SSL_get_verify_result(ctx->ssl);
David Safb76832014-05-08 23:42:08 -04006800}
6801
Willy Tarreau8743f7e2016-12-04 18:44:29 +01006802/* Returns the application layer protocol name in <str> and <len> when known.
6803 * Zero is returned if the protocol name was not found, otherwise non-zero is
6804 * returned. The string is allocated in the SSL context and doesn't have to be
6805 * freed by the caller. NPN is also checked if available since older versions
6806 * of openssl (1.0.1) which are more common in field only support this one.
6807 */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006808static int ssl_sock_get_alpn(const struct connection *conn, void *xprt_ctx, const char **str, int *len)
Willy Tarreau8743f7e2016-12-04 18:44:29 +01006809{
Olivier Houchard66ab4982019-02-26 18:37:15 +01006810#if defined(TLSEXT_TYPE_application_layer_protocol_negotiation) || \
6811 defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006812 struct ssl_sock_ctx *ctx = xprt_ctx;
6813 if (!ctx)
Willy Tarreau8743f7e2016-12-04 18:44:29 +01006814 return 0;
6815
6816 *str = NULL;
6817
6818#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Olivier Houchard66ab4982019-02-26 18:37:15 +01006819 SSL_get0_alpn_selected(ctx->ssl, (const unsigned char **)str, (unsigned *)len);
Willy Tarreau8743f7e2016-12-04 18:44:29 +01006820 if (*str)
6821 return 1;
6822#endif
Bernard Spil13c53f82018-02-15 13:34:58 +01006823#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006824 SSL_get0_next_proto_negotiated(ctx->ssl, (const unsigned char **)str, (unsigned *)len);
Willy Tarreau8743f7e2016-12-04 18:44:29 +01006825 if (*str)
6826 return 1;
6827#endif
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006828#endif
Willy Tarreau8743f7e2016-12-04 18:44:29 +01006829 return 0;
6830}
6831
Willy Tarreau7875d092012-09-10 08:20:03 +02006832/***** Below are some sample fetching functions for ACL/patterns *****/
6833
Olivier Houchardccaa7de2017-10-02 11:51:03 +02006834static int
6835smp_fetch_ssl_fc_has_early(const struct arg *args, struct sample *smp, const char *kw, void *private)
6836{
6837 struct connection *conn;
6838
6839 conn = objt_conn(smp->sess->origin);
6840 if (!conn || conn->xprt != &ssl_sock)
6841 return 0;
6842
6843 smp->flags = 0;
6844 smp->data.type = SMP_T_BOOL;
Emmanuel Hocdetc9858012019-08-07 14:44:49 +02006845#ifdef OPENSSL_IS_BORINGSSL
6846 {
6847 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
6848 smp->data.u.sint = (SSL_in_early_data(ctx->ssl) &&
6849 SSL_early_data_accepted(ctx->ssl));
6850 }
6851#else
Olivier Houchard25ae45a2017-11-29 19:51:19 +01006852 smp->data.u.sint = ((conn->flags & CO_FL_EARLY_DATA) &&
6853 (conn->flags & (CO_FL_EARLY_SSL_HS | CO_FL_HANDSHAKE))) ? 1 : 0;
Emmanuel Hocdetc9858012019-08-07 14:44:49 +02006854#endif
Olivier Houchardccaa7de2017-10-02 11:51:03 +02006855 return 1;
6856}
6857
Emeric Brune64aef12012-09-21 13:15:06 +02006858/* boolean, returns true if client cert was present */
6859static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006860smp_fetch_ssl_fc_has_crt(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brune64aef12012-09-21 13:15:06 +02006861{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006862 struct connection *conn;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006863 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006864
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006865 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006866 if (!conn || conn->xprt != &ssl_sock)
Emeric Brune64aef12012-09-21 13:15:06 +02006867 return 0;
6868
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006869 ctx = conn->xprt_ctx;
6870
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006871 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brune64aef12012-09-21 13:15:06 +02006872 smp->flags |= SMP_F_MAY_CHANGE;
6873 return 0;
6874 }
6875
6876 smp->flags = 0;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006877 smp->data.type = SMP_T_BOOL;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006878 smp->data.u.sint = SSL_SOCK_ST_FL_VERIFY_DONE & ctx->xprt_st ? 1 : 0;
Emeric Brune64aef12012-09-21 13:15:06 +02006879
6880 return 1;
6881}
6882
Emeric Brun43e79582014-10-29 19:03:26 +01006883/* binary, returns a certificate in a binary chunk (der/raw).
6884 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6885 * should be use.
6886 */
6887static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006888smp_fetch_ssl_x_der(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun43e79582014-10-29 19:03:26 +01006889{
6890 int cert_peer = (kw[4] == 'c') ? 1 : 0;
6891 X509 *crt = NULL;
6892 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02006893 struct buffer *smp_trash;
Emeric Brun43e79582014-10-29 19:03:26 +01006894 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006895 struct ssl_sock_ctx *ctx;
Emeric Brun43e79582014-10-29 19:03:26 +01006896
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006897 conn = objt_conn(smp->sess->origin);
Emeric Brun43e79582014-10-29 19:03:26 +01006898 if (!conn || conn->xprt != &ssl_sock)
6899 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006900 ctx = conn->xprt_ctx;
Emeric Brun43e79582014-10-29 19:03:26 +01006901
6902 if (!(conn->flags & CO_FL_CONNECTED)) {
6903 smp->flags |= SMP_F_MAY_CHANGE;
6904 return 0;
6905 }
6906
6907 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006908 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brun43e79582014-10-29 19:03:26 +01006909 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01006910 crt = SSL_get_certificate(ctx->ssl);
Emeric Brun43e79582014-10-29 19:03:26 +01006911
6912 if (!crt)
6913 goto out;
6914
6915 smp_trash = get_trash_chunk();
6916 if (ssl_sock_crt2der(crt, smp_trash) <= 0)
6917 goto out;
6918
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006919 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006920 smp->data.type = SMP_T_BIN;
Emeric Brun43e79582014-10-29 19:03:26 +01006921 ret = 1;
6922out:
6923 /* SSL_get_peer_certificate, it increase X509 * ref count */
6924 if (cert_peer && crt)
6925 X509_free(crt);
6926 return ret;
6927}
6928
Emeric Brunba841a12014-04-30 17:05:08 +02006929/* binary, returns serial of certificate in a binary chunk.
6930 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6931 * should be use.
6932 */
Willy Tarreau8d598402012-10-22 17:58:39 +02006933static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006934smp_fetch_ssl_x_serial(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau8d598402012-10-22 17:58:39 +02006935{
Emeric Brunba841a12014-04-30 17:05:08 +02006936 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Willy Tarreau8d598402012-10-22 17:58:39 +02006937 X509 *crt = NULL;
6938 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02006939 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006940 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006941 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006942
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006943 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006944 if (!conn || conn->xprt != &ssl_sock)
Willy Tarreau8d598402012-10-22 17:58:39 +02006945 return 0;
6946
Olivier Houchard66ab4982019-02-26 18:37:15 +01006947 ctx = conn->xprt_ctx;
6948
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006949 if (!(conn->flags & CO_FL_CONNECTED)) {
Willy Tarreau8d598402012-10-22 17:58:39 +02006950 smp->flags |= SMP_F_MAY_CHANGE;
6951 return 0;
6952 }
6953
Emeric Brunba841a12014-04-30 17:05:08 +02006954 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006955 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02006956 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01006957 crt = SSL_get_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02006958
Willy Tarreau8d598402012-10-22 17:58:39 +02006959 if (!crt)
6960 goto out;
6961
Willy Tarreau47ca5452012-12-23 20:22:19 +01006962 smp_trash = get_trash_chunk();
Willy Tarreau8d598402012-10-22 17:58:39 +02006963 if (ssl_sock_get_serial(crt, smp_trash) <= 0)
6964 goto out;
6965
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006966 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006967 smp->data.type = SMP_T_BIN;
Willy Tarreau8d598402012-10-22 17:58:39 +02006968 ret = 1;
6969out:
Emeric Brunba841a12014-04-30 17:05:08 +02006970 /* SSL_get_peer_certificate, it increase X509 * ref count */
6971 if (cert_peer && crt)
Willy Tarreau8d598402012-10-22 17:58:39 +02006972 X509_free(crt);
6973 return ret;
6974}
Emeric Brune64aef12012-09-21 13:15:06 +02006975
Emeric Brunba841a12014-04-30 17:05:08 +02006976/* binary, returns the client certificate's SHA-1 fingerprint (SHA-1 hash of DER-encoded certificate) in a binary chunk.
6977 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6978 * should be use.
6979 */
James Votha051b4a2013-05-14 20:37:59 +02006980static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006981smp_fetch_ssl_x_sha1(const struct arg *args, struct sample *smp, const char *kw, void *private)
James Votha051b4a2013-05-14 20:37:59 +02006982{
Emeric Brunba841a12014-04-30 17:05:08 +02006983 int cert_peer = (kw[4] == 'c') ? 1 : 0;
James Votha051b4a2013-05-14 20:37:59 +02006984 X509 *crt = NULL;
6985 const EVP_MD *digest;
6986 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02006987 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006988 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006989 struct ssl_sock_ctx *ctx;
James Votha051b4a2013-05-14 20:37:59 +02006990
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006991 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006992 if (!conn || conn->xprt != &ssl_sock)
6993 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006994 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006995
6996 if (!(conn->flags & CO_FL_CONNECTED)) {
James Votha051b4a2013-05-14 20:37:59 +02006997 smp->flags |= SMP_F_MAY_CHANGE;
6998 return 0;
6999 }
7000
Emeric Brunba841a12014-04-30 17:05:08 +02007001 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007002 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007003 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007004 crt = SSL_get_certificate(ctx->ssl);
James Votha051b4a2013-05-14 20:37:59 +02007005 if (!crt)
7006 goto out;
7007
7008 smp_trash = get_trash_chunk();
7009 digest = EVP_sha1();
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007010 X509_digest(crt, digest, (unsigned char *) smp_trash->area,
7011 (unsigned int *)&smp_trash->data);
James Votha051b4a2013-05-14 20:37:59 +02007012
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007013 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007014 smp->data.type = SMP_T_BIN;
James Votha051b4a2013-05-14 20:37:59 +02007015 ret = 1;
7016out:
Emeric Brunba841a12014-04-30 17:05:08 +02007017 /* SSL_get_peer_certificate, it increase X509 * ref count */
7018 if (cert_peer && crt)
James Votha051b4a2013-05-14 20:37:59 +02007019 X509_free(crt);
7020 return ret;
7021}
7022
Emeric Brunba841a12014-04-30 17:05:08 +02007023/* string, returns certificate's notafter date in ASN1_UTCTIME format.
7024 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7025 * should be use.
7026 */
Emeric Brunce5ad802012-10-22 14:11:22 +02007027static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007028smp_fetch_ssl_x_notafter(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunce5ad802012-10-22 14:11:22 +02007029{
Emeric Brunba841a12014-04-30 17:05:08 +02007030 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brunce5ad802012-10-22 14:11:22 +02007031 X509 *crt = NULL;
7032 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02007033 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007034 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007035 struct ssl_sock_ctx *ctx;
Emeric Brunce5ad802012-10-22 14:11:22 +02007036
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007037 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007038 if (!conn || conn->xprt != &ssl_sock)
7039 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007040 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007041
7042 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02007043 smp->flags |= SMP_F_MAY_CHANGE;
7044 return 0;
7045 }
7046
Emeric Brunba841a12014-04-30 17:05:08 +02007047 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007048 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007049 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007050 crt = SSL_get_certificate(ctx->ssl);
Emeric Brunce5ad802012-10-22 14:11:22 +02007051 if (!crt)
7052 goto out;
7053
Willy Tarreau47ca5452012-12-23 20:22:19 +01007054 smp_trash = get_trash_chunk();
Rosen Penev68185952018-12-14 08:47:02 -08007055 if (ssl_sock_get_time(X509_getm_notAfter(crt), smp_trash) <= 0)
Emeric Brunce5ad802012-10-22 14:11:22 +02007056 goto out;
7057
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007058 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007059 smp->data.type = SMP_T_STR;
Emeric Brunce5ad802012-10-22 14:11:22 +02007060 ret = 1;
7061out:
Emeric Brunba841a12014-04-30 17:05:08 +02007062 /* SSL_get_peer_certificate, it increase X509 * ref count */
7063 if (cert_peer && crt)
Emeric Brunce5ad802012-10-22 14:11:22 +02007064 X509_free(crt);
7065 return ret;
7066}
7067
Emeric Brunba841a12014-04-30 17:05:08 +02007068/* string, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. of certificate's issuer
7069 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7070 * should be use.
7071 */
Emeric Brun87855892012-10-17 17:39:35 +02007072static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007073smp_fetch_ssl_x_i_dn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun87855892012-10-17 17:39:35 +02007074{
Emeric Brunba841a12014-04-30 17:05:08 +02007075 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun87855892012-10-17 17:39:35 +02007076 X509 *crt = NULL;
7077 X509_NAME *name;
7078 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02007079 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007080 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007081 struct ssl_sock_ctx *ctx;
Emeric Brun87855892012-10-17 17:39:35 +02007082
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007083 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007084 if (!conn || conn->xprt != &ssl_sock)
7085 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007086 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007087
7088 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02007089 smp->flags |= SMP_F_MAY_CHANGE;
7090 return 0;
7091 }
7092
Emeric Brunba841a12014-04-30 17:05:08 +02007093 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007094 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007095 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007096 crt = SSL_get_certificate(ctx->ssl);
Emeric Brun87855892012-10-17 17:39:35 +02007097 if (!crt)
7098 goto out;
7099
7100 name = X509_get_issuer_name(crt);
7101 if (!name)
7102 goto out;
7103
Willy Tarreau47ca5452012-12-23 20:22:19 +01007104 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02007105 if (args && args[0].type == ARGT_STR) {
7106 int pos = 1;
7107
7108 if (args[1].type == ARGT_SINT)
7109 pos = args[1].data.sint;
Emeric Brun87855892012-10-17 17:39:35 +02007110
7111 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
7112 goto out;
7113 }
7114 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
7115 goto out;
7116
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007117 smp->data.type = SMP_T_STR;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007118 smp->data.u.str = *smp_trash;
Emeric Brun87855892012-10-17 17:39:35 +02007119 ret = 1;
7120out:
Emeric Brunba841a12014-04-30 17:05:08 +02007121 /* SSL_get_peer_certificate, it increase X509 * ref count */
7122 if (cert_peer && crt)
Emeric Brun87855892012-10-17 17:39:35 +02007123 X509_free(crt);
7124 return ret;
7125}
7126
Emeric Brunba841a12014-04-30 17:05:08 +02007127/* string, returns notbefore date in ASN1_UTCTIME format.
7128 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7129 * should be use.
7130 */
Emeric Brunce5ad802012-10-22 14:11:22 +02007131static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007132smp_fetch_ssl_x_notbefore(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunce5ad802012-10-22 14:11:22 +02007133{
Emeric Brunba841a12014-04-30 17:05:08 +02007134 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brunce5ad802012-10-22 14:11:22 +02007135 X509 *crt = NULL;
7136 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02007137 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007138 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007139 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007140
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007141 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007142 if (!conn || conn->xprt != &ssl_sock)
Emeric Brunce5ad802012-10-22 14:11:22 +02007143 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007144 ctx = conn->xprt_ctx;
Emeric Brunce5ad802012-10-22 14:11:22 +02007145
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007146 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02007147 smp->flags |= SMP_F_MAY_CHANGE;
7148 return 0;
7149 }
7150
Emeric Brunba841a12014-04-30 17:05:08 +02007151 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007152 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007153 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007154 crt = SSL_get_certificate(ctx->ssl);
Emeric Brunce5ad802012-10-22 14:11:22 +02007155 if (!crt)
7156 goto out;
7157
Willy Tarreau47ca5452012-12-23 20:22:19 +01007158 smp_trash = get_trash_chunk();
Rosen Penev68185952018-12-14 08:47:02 -08007159 if (ssl_sock_get_time(X509_getm_notBefore(crt), smp_trash) <= 0)
Emeric Brunce5ad802012-10-22 14:11:22 +02007160 goto out;
7161
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007162 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007163 smp->data.type = SMP_T_STR;
Emeric Brunce5ad802012-10-22 14:11:22 +02007164 ret = 1;
7165out:
Emeric Brunba841a12014-04-30 17:05:08 +02007166 /* SSL_get_peer_certificate, it increase X509 * ref count */
7167 if (cert_peer && crt)
Emeric Brunce5ad802012-10-22 14:11:22 +02007168 X509_free(crt);
7169 return ret;
7170}
7171
Emeric Brunba841a12014-04-30 17:05:08 +02007172/* string, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. of certificate's subject
7173 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7174 * should be use.
7175 */
Emeric Brun87855892012-10-17 17:39:35 +02007176static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007177smp_fetch_ssl_x_s_dn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun87855892012-10-17 17:39:35 +02007178{
Emeric Brunba841a12014-04-30 17:05:08 +02007179 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun87855892012-10-17 17:39:35 +02007180 X509 *crt = NULL;
7181 X509_NAME *name;
7182 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02007183 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007184 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007185 struct ssl_sock_ctx *ctx;
Emeric Brun87855892012-10-17 17:39:35 +02007186
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007187 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007188 if (!conn || conn->xprt != &ssl_sock)
7189 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007190 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007191
7192 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02007193 smp->flags |= SMP_F_MAY_CHANGE;
7194 return 0;
7195 }
7196
Emeric Brunba841a12014-04-30 17:05:08 +02007197 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007198 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007199 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007200 crt = SSL_get_certificate(ctx->ssl);
Emeric Brun87855892012-10-17 17:39:35 +02007201 if (!crt)
7202 goto out;
7203
7204 name = X509_get_subject_name(crt);
7205 if (!name)
7206 goto out;
7207
Willy Tarreau47ca5452012-12-23 20:22:19 +01007208 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02007209 if (args && args[0].type == ARGT_STR) {
7210 int pos = 1;
7211
7212 if (args[1].type == ARGT_SINT)
7213 pos = args[1].data.sint;
Emeric Brun87855892012-10-17 17:39:35 +02007214
7215 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
7216 goto out;
7217 }
7218 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
7219 goto out;
7220
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007221 smp->data.type = SMP_T_STR;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007222 smp->data.u.str = *smp_trash;
Emeric Brun87855892012-10-17 17:39:35 +02007223 ret = 1;
7224out:
Emeric Brunba841a12014-04-30 17:05:08 +02007225 /* SSL_get_peer_certificate, it increase X509 * ref count */
7226 if (cert_peer && crt)
Emeric Brun87855892012-10-17 17:39:35 +02007227 X509_free(crt);
7228 return ret;
7229}
Emeric Brun9143d372012-12-20 15:44:16 +01007230
7231/* integer, returns true if current session use a client certificate */
7232static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007233smp_fetch_ssl_c_used(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun9143d372012-12-20 15:44:16 +01007234{
7235 X509 *crt;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007236 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007237 struct ssl_sock_ctx *ctx;
Emeric Brun9143d372012-12-20 15:44:16 +01007238
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007239 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007240 if (!conn || conn->xprt != &ssl_sock)
7241 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007242 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007243
7244 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun9143d372012-12-20 15:44:16 +01007245 smp->flags |= SMP_F_MAY_CHANGE;
7246 return 0;
7247 }
7248
7249 /* SSL_get_peer_certificate returns a ptr on allocated X509 struct */
Olivier Houchard66ab4982019-02-26 18:37:15 +01007250 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brun9143d372012-12-20 15:44:16 +01007251 if (crt) {
7252 X509_free(crt);
7253 }
7254
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007255 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007256 smp->data.u.sint = (crt != NULL);
Emeric Brun9143d372012-12-20 15:44:16 +01007257 return 1;
7258}
7259
Emeric Brunba841a12014-04-30 17:05:08 +02007260/* integer, returns the certificate version
7261 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7262 * should be use.
7263 */
Emeric Bruna7359fd2012-10-17 15:03:11 +02007264static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007265smp_fetch_ssl_x_version(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Bruna7359fd2012-10-17 15:03:11 +02007266{
Emeric Brunba841a12014-04-30 17:05:08 +02007267 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Bruna7359fd2012-10-17 15:03:11 +02007268 X509 *crt;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007269 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007270 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007271
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007272 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007273 if (!conn || conn->xprt != &ssl_sock)
Emeric Bruna7359fd2012-10-17 15:03:11 +02007274 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007275 ctx = conn->xprt_ctx;
Emeric Bruna7359fd2012-10-17 15:03:11 +02007276
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007277 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Bruna7359fd2012-10-17 15:03:11 +02007278 smp->flags |= SMP_F_MAY_CHANGE;
7279 return 0;
7280 }
7281
Emeric Brunba841a12014-04-30 17:05:08 +02007282 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007283 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007284 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007285 crt = SSL_get_certificate(ctx->ssl);
Emeric Bruna7359fd2012-10-17 15:03:11 +02007286 if (!crt)
7287 return 0;
7288
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007289 smp->data.u.sint = (unsigned int)(1 + X509_get_version(crt));
Emeric Brunba841a12014-04-30 17:05:08 +02007290 /* SSL_get_peer_certificate increase X509 * ref count */
7291 if (cert_peer)
7292 X509_free(crt);
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007293 smp->data.type = SMP_T_SINT;
Emeric Bruna7359fd2012-10-17 15:03:11 +02007294
7295 return 1;
7296}
7297
Emeric Brunba841a12014-04-30 17:05:08 +02007298/* string, returns the certificate's signature algorithm.
7299 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7300 * should be use.
7301 */
Emeric Brun7f56e742012-10-19 18:15:40 +02007302static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007303smp_fetch_ssl_x_sig_alg(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun7f56e742012-10-19 18:15:40 +02007304{
Emeric Brunba841a12014-04-30 17:05:08 +02007305 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun7f56e742012-10-19 18:15:40 +02007306 X509 *crt;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007307 __OPENSSL_110_CONST__ ASN1_OBJECT *algorithm;
Emeric Brun7f56e742012-10-19 18:15:40 +02007308 int nid;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007309 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007310 struct ssl_sock_ctx *ctx;
Emeric Brun7f56e742012-10-19 18:15:40 +02007311
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007312 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007313 if (!conn || conn->xprt != &ssl_sock)
7314 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007315 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007316
7317 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun7f56e742012-10-19 18:15:40 +02007318 smp->flags |= SMP_F_MAY_CHANGE;
7319 return 0;
7320 }
7321
Emeric Brunba841a12014-04-30 17:05:08 +02007322 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007323 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007324 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007325 crt = SSL_get_certificate(ctx->ssl);
Emeric Brun7f56e742012-10-19 18:15:40 +02007326 if (!crt)
7327 return 0;
7328
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007329 X509_ALGOR_get0(&algorithm, NULL, NULL, X509_get0_tbs_sigalg(crt));
7330 nid = OBJ_obj2nid(algorithm);
Emeric Brun7f56e742012-10-19 18:15:40 +02007331
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007332 smp->data.u.str.area = (char *)OBJ_nid2sn(nid);
7333 if (!smp->data.u.str.area) {
Emeric Brunba841a12014-04-30 17:05:08 +02007334 /* SSL_get_peer_certificate increase X509 * ref count */
7335 if (cert_peer)
7336 X509_free(crt);
Emeric Brun7f56e742012-10-19 18:15:40 +02007337 return 0;
Emeric Brun9bf3ba22013-10-07 14:31:44 +02007338 }
Emeric Brun7f56e742012-10-19 18:15:40 +02007339
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007340 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01007341 smp->flags |= SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007342 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brunba841a12014-04-30 17:05:08 +02007343 /* SSL_get_peer_certificate increase X509 * ref count */
7344 if (cert_peer)
7345 X509_free(crt);
Emeric Brun7f56e742012-10-19 18:15:40 +02007346
7347 return 1;
7348}
7349
Emeric Brunba841a12014-04-30 17:05:08 +02007350/* string, returns the certificate's key algorithm.
7351 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7352 * should be use.
7353 */
Emeric Brun521a0112012-10-22 12:22:55 +02007354static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007355smp_fetch_ssl_x_key_alg(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun521a0112012-10-22 12:22:55 +02007356{
Emeric Brunba841a12014-04-30 17:05:08 +02007357 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun521a0112012-10-22 12:22:55 +02007358 X509 *crt;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007359 ASN1_OBJECT *algorithm;
Emeric Brun521a0112012-10-22 12:22:55 +02007360 int nid;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007361 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007362 struct ssl_sock_ctx *ctx;
Emeric Brun521a0112012-10-22 12:22:55 +02007363
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007364 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007365 if (!conn || conn->xprt != &ssl_sock)
7366 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007367 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007368
7369 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun521a0112012-10-22 12:22:55 +02007370 smp->flags |= SMP_F_MAY_CHANGE;
7371 return 0;
7372 }
7373
Emeric Brunba841a12014-04-30 17:05:08 +02007374 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007375 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007376 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007377 crt = SSL_get_certificate(ctx->ssl);
Emeric Brun521a0112012-10-22 12:22:55 +02007378 if (!crt)
7379 return 0;
7380
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007381 X509_PUBKEY_get0_param(&algorithm, NULL, NULL, NULL, X509_get_X509_PUBKEY(crt));
7382 nid = OBJ_obj2nid(algorithm);
Emeric Brun521a0112012-10-22 12:22:55 +02007383
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007384 smp->data.u.str.area = (char *)OBJ_nid2sn(nid);
7385 if (!smp->data.u.str.area) {
Emeric Brunba841a12014-04-30 17:05:08 +02007386 /* SSL_get_peer_certificate increase X509 * ref count */
7387 if (cert_peer)
7388 X509_free(crt);
Emeric Brun521a0112012-10-22 12:22:55 +02007389 return 0;
Emeric Brun9bf3ba22013-10-07 14:31:44 +02007390 }
Emeric Brun521a0112012-10-22 12:22:55 +02007391
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007392 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01007393 smp->flags |= SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007394 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brunba841a12014-04-30 17:05:08 +02007395 if (cert_peer)
7396 X509_free(crt);
Emeric Brun521a0112012-10-22 12:22:55 +02007397
7398 return 1;
7399}
7400
Emeric Brun645ae792014-04-30 14:21:06 +02007401/* boolean, returns true if front conn. transport layer is SSL.
7402 * This function is also usable on backend conn if the fetch keyword 5th
7403 * char is 'b'.
7404 */
Willy Tarreau7875d092012-09-10 08:20:03 +02007405static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007406smp_fetch_ssl_fc(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02007407{
Emeric Bruneb8def92018-02-19 15:59:48 +01007408 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7409 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007410
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007411 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007412 smp->data.u.sint = (conn && conn->xprt == &ssl_sock);
Willy Tarreau7875d092012-09-10 08:20:03 +02007413 return 1;
7414}
7415
Emeric Brun2525b6b2012-10-18 15:59:43 +02007416/* boolean, returns true if client present a SNI */
Willy Tarreau7875d092012-09-10 08:20:03 +02007417static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007418smp_fetch_ssl_fc_has_sni(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02007419{
7420#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007421 struct connection *conn = objt_conn(smp->sess->origin);
Olivier Houchard66ab4982019-02-26 18:37:15 +01007422 struct ssl_sock_ctx *ctx = conn ? conn->xprt_ctx : NULL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007423
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007424 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007425 smp->data.u.sint = (conn && conn->xprt == &ssl_sock) &&
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007426 conn->xprt_ctx &&
Olivier Houchard66ab4982019-02-26 18:37:15 +01007427 SSL_get_servername(ctx->ssl, TLSEXT_NAMETYPE_host_name) != NULL;
Willy Tarreau7875d092012-09-10 08:20:03 +02007428 return 1;
7429#else
7430 return 0;
7431#endif
7432}
7433
Emeric Brun74f7ffa2018-02-19 16:14:12 +01007434/* boolean, returns true if client session has been resumed.
7435 * This function is also usable on backend conn if the fetch keyword 5th
7436 * char is 'b'.
7437 */
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02007438static int
7439smp_fetch_ssl_fc_is_resumed(const struct arg *args, struct sample *smp, const char *kw, void *private)
7440{
Emeric Brun74f7ffa2018-02-19 16:14:12 +01007441 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7442 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007443 struct ssl_sock_ctx *ctx = conn ? conn->xprt_ctx : NULL;
Emeric Brun74f7ffa2018-02-19 16:14:12 +01007444
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02007445
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007446 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007447 smp->data.u.sint = (conn && conn->xprt == &ssl_sock) &&
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02007448 conn->xprt_ctx &&
Olivier Houchard66ab4982019-02-26 18:37:15 +01007449 SSL_session_reused(ctx->ssl);
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02007450 return 1;
7451}
7452
Emeric Brun645ae792014-04-30 14:21:06 +02007453/* string, returns the used cipher if front conn. transport layer is SSL.
7454 * This function is also usable on backend conn if the fetch keyword 5th
7455 * char is 'b'.
7456 */
Emeric Brun589fcad2012-10-16 14:13:26 +02007457static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007458smp_fetch_ssl_fc_cipher(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02007459{
Emeric Bruneb8def92018-02-19 15:59:48 +01007460 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7461 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007462 struct ssl_sock_ctx *ctx;
Emeric Brun589fcad2012-10-16 14:13:26 +02007463
Willy Tarreaube508f12016-03-10 11:47:01 +01007464 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007465 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02007466 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007467 ctx = conn->xprt_ctx;
Emeric Brun589fcad2012-10-16 14:13:26 +02007468
Olivier Houchard66ab4982019-02-26 18:37:15 +01007469 smp->data.u.str.area = (char *)SSL_get_cipher_name(ctx->ssl);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007470 if (!smp->data.u.str.area)
Emeric Brun589fcad2012-10-16 14:13:26 +02007471 return 0;
7472
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007473 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01007474 smp->flags |= SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007475 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brun589fcad2012-10-16 14:13:26 +02007476
7477 return 1;
7478}
7479
Emeric Brun645ae792014-04-30 14:21:06 +02007480/* integer, returns the algoritm's keysize if front conn. transport layer
7481 * is SSL.
7482 * This function is also usable on backend conn if the fetch keyword 5th
7483 * char is 'b'.
7484 */
Emeric Brun589fcad2012-10-16 14:13:26 +02007485static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007486smp_fetch_ssl_fc_alg_keysize(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02007487{
Emeric Bruneb8def92018-02-19 15:59:48 +01007488 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7489 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007490 struct ssl_sock_ctx *ctx;
Willy Tarreaue237fe12016-03-10 17:05:28 +01007491 int sint;
Willy Tarreaube508f12016-03-10 11:47:01 +01007492
Emeric Brun589fcad2012-10-16 14:13:26 +02007493 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007494 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02007495 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007496 ctx = conn->xprt_ctx;
Emeric Brun589fcad2012-10-16 14:13:26 +02007497
Olivier Houchard66ab4982019-02-26 18:37:15 +01007498 if (!SSL_get_cipher_bits(ctx->ssl, &sint))
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007499 return 0;
7500
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007501 smp->data.u.sint = sint;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007502 smp->data.type = SMP_T_SINT;
Emeric Brun589fcad2012-10-16 14:13:26 +02007503
7504 return 1;
7505}
7506
Emeric Brun645ae792014-04-30 14:21:06 +02007507/* integer, returns the used keysize if front conn. transport layer is SSL.
7508 * This function is also usable on backend conn if the fetch keyword 5th
7509 * char is 'b'.
7510 */
Emeric Brun589fcad2012-10-16 14:13:26 +02007511static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007512smp_fetch_ssl_fc_use_keysize(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02007513{
Emeric Bruneb8def92018-02-19 15:59:48 +01007514 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7515 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007516 struct ssl_sock_ctx *ctx;
Willy Tarreaube508f12016-03-10 11:47:01 +01007517
Emeric Brun589fcad2012-10-16 14:13:26 +02007518 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007519 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7520 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007521 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007522
Olivier Houchard66ab4982019-02-26 18:37:15 +01007523 smp->data.u.sint = (unsigned int)SSL_get_cipher_bits(ctx->ssl, NULL);
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007524 if (!smp->data.u.sint)
Emeric Brun589fcad2012-10-16 14:13:26 +02007525 return 0;
7526
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007527 smp->data.type = SMP_T_SINT;
Emeric Brun589fcad2012-10-16 14:13:26 +02007528
7529 return 1;
7530}
7531
Bernard Spil13c53f82018-02-15 13:34:58 +01007532#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Willy Tarreau7875d092012-09-10 08:20:03 +02007533static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007534smp_fetch_ssl_fc_npn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreaua33c6542012-10-15 13:19:06 +02007535{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007536 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007537 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007538
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01007539 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007540 smp->data.type = SMP_T_STR;
Willy Tarreaua33c6542012-10-15 13:19:06 +02007541
Olivier Houchard6b77f492018-11-22 18:18:29 +01007542 conn = (kw[4] != 'b' ) ? objt_conn(smp->sess->origin) :
7543 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007544 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7545 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007546 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007547
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007548 smp->data.u.str.area = NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007549 SSL_get0_next_proto_negotiated(ctx->ssl,
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007550 (const unsigned char **)&smp->data.u.str.area,
7551 (unsigned *)&smp->data.u.str.data);
Willy Tarreaua33c6542012-10-15 13:19:06 +02007552
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007553 if (!smp->data.u.str.area)
Willy Tarreaua33c6542012-10-15 13:19:06 +02007554 return 0;
7555
7556 return 1;
Willy Tarreaua33c6542012-10-15 13:19:06 +02007557}
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02007558#endif
Willy Tarreaua33c6542012-10-15 13:19:06 +02007559
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01007560#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02007561static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007562smp_fetch_ssl_fc_alpn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreauab861d32013-04-02 02:30:41 +02007563{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007564 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007565 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007566
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01007567 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007568 smp->data.type = SMP_T_STR;
Willy Tarreauab861d32013-04-02 02:30:41 +02007569
Olivier Houchard6b77f492018-11-22 18:18:29 +01007570 conn = (kw[4] != 'b' ) ? objt_conn(smp->sess->origin) :
7571 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
7572
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007573 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Willy Tarreauab861d32013-04-02 02:30:41 +02007574 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007575 ctx = conn->xprt_ctx;
Willy Tarreauab861d32013-04-02 02:30:41 +02007576
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007577 smp->data.u.str.area = NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007578 SSL_get0_alpn_selected(ctx->ssl,
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007579 (const unsigned char **)&smp->data.u.str.area,
7580 (unsigned *)&smp->data.u.str.data);
Willy Tarreauab861d32013-04-02 02:30:41 +02007581
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007582 if (!smp->data.u.str.area)
Willy Tarreauab861d32013-04-02 02:30:41 +02007583 return 0;
7584
7585 return 1;
7586}
7587#endif
7588
Emeric Brun645ae792014-04-30 14:21:06 +02007589/* string, returns the used protocol if front conn. transport layer is SSL.
7590 * This function is also usable on backend conn if the fetch keyword 5th
7591 * char is 'b'.
7592 */
Willy Tarreaua33c6542012-10-15 13:19:06 +02007593static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007594smp_fetch_ssl_fc_protocol(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02007595{
Emeric Bruneb8def92018-02-19 15:59:48 +01007596 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7597 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007598 struct ssl_sock_ctx *ctx;
Willy Tarreaube508f12016-03-10 11:47:01 +01007599
Emeric Brun589fcad2012-10-16 14:13:26 +02007600 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007601 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7602 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007603 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007604
Olivier Houchard66ab4982019-02-26 18:37:15 +01007605 smp->data.u.str.area = (char *)SSL_get_version(ctx->ssl);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007606 if (!smp->data.u.str.area)
Emeric Brun589fcad2012-10-16 14:13:26 +02007607 return 0;
7608
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007609 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01007610 smp->flags = SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007611 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brun589fcad2012-10-16 14:13:26 +02007612
7613 return 1;
7614}
7615
Willy Tarreau87b09662015-04-03 00:22:06 +02007616/* binary, returns the SSL stream id if front conn. transport layer is SSL.
Emeric Brun645ae792014-04-30 14:21:06 +02007617 * This function is also usable on backend conn if the fetch keyword 5th
7618 * char is 'b'.
7619 */
Willy Tarreau9a1ab082019-05-09 13:26:41 +02007620#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
Emeric Brun589fcad2012-10-16 14:13:26 +02007621static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007622smp_fetch_ssl_fc_session_id(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunfe68f682012-10-16 14:59:28 +02007623{
Emeric Bruneb8def92018-02-19 15:59:48 +01007624 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7625 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaue237fe12016-03-10 17:05:28 +01007626 SSL_SESSION *ssl_sess;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007627 struct ssl_sock_ctx *ctx;
Willy Tarreaube508f12016-03-10 11:47:01 +01007628
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01007629 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007630 smp->data.type = SMP_T_BIN;
Emeric Brunfe68f682012-10-16 14:59:28 +02007631
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007632 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7633 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007634 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007635
Olivier Houchard66ab4982019-02-26 18:37:15 +01007636 ssl_sess = SSL_get_session(ctx->ssl);
Willy Tarreau192252e2015-04-04 01:47:55 +02007637 if (!ssl_sess)
Emeric Brunfe68f682012-10-16 14:59:28 +02007638 return 0;
7639
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007640 smp->data.u.str.area = (char *)SSL_SESSION_get_id(ssl_sess,
7641 (unsigned int *)&smp->data.u.str.data);
7642 if (!smp->data.u.str.area || !smp->data.u.str.data)
Emeric Brunfe68f682012-10-16 14:59:28 +02007643 return 0;
7644
7645 return 1;
Emeric Brunfe68f682012-10-16 14:59:28 +02007646}
Patrick Hemmer41966772018-04-28 19:15:48 -04007647#endif
7648
Emeric Brunfe68f682012-10-16 14:59:28 +02007649
Emmanuel Hocdet839af572019-05-14 16:27:35 +02007650#if HA_OPENSSL_VERSION_NUMBER >= 0x10100000L
Patrick Hemmere0275472018-04-28 19:15:51 -04007651static int
Patrick Hemmer65674662019-06-04 08:13:03 -04007652smp_fetch_ssl_fc_random(const struct arg *args, struct sample *smp, const char *kw, void *private)
7653{
7654 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7655 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
7656 struct buffer *data;
7657 struct ssl_sock_ctx *ctx;
7658
7659 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7660 return 0;
7661 ctx = conn->xprt_ctx;
7662
7663 data = get_trash_chunk();
7664 if (kw[7] == 'c')
7665 data->data = SSL_get_client_random(ctx->ssl,
7666 (unsigned char *) data->area,
7667 data->size);
7668 else
7669 data->data = SSL_get_server_random(ctx->ssl,
7670 (unsigned char *) data->area,
7671 data->size);
7672 if (!data->data)
7673 return 0;
7674
7675 smp->flags = 0;
7676 smp->data.type = SMP_T_BIN;
7677 smp->data.u.str = *data;
7678
7679 return 1;
7680}
7681
7682static int
Patrick Hemmere0275472018-04-28 19:15:51 -04007683smp_fetch_ssl_fc_session_key(const struct arg *args, struct sample *smp, const char *kw, void *private)
7684{
7685 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7686 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
7687 SSL_SESSION *ssl_sess;
Willy Tarreau83061a82018-07-13 11:56:34 +02007688 struct buffer *data;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007689 struct ssl_sock_ctx *ctx;
Patrick Hemmere0275472018-04-28 19:15:51 -04007690
7691 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7692 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007693 ctx = conn->xprt_ctx;
Patrick Hemmere0275472018-04-28 19:15:51 -04007694
Olivier Houchard66ab4982019-02-26 18:37:15 +01007695 ssl_sess = SSL_get_session(ctx->ssl);
Patrick Hemmere0275472018-04-28 19:15:51 -04007696 if (!ssl_sess)
7697 return 0;
7698
7699 data = get_trash_chunk();
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007700 data->data = SSL_SESSION_get_master_key(ssl_sess,
7701 (unsigned char *) data->area,
7702 data->size);
7703 if (!data->data)
Patrick Hemmere0275472018-04-28 19:15:51 -04007704 return 0;
7705
7706 smp->flags = 0;
7707 smp->data.type = SMP_T_BIN;
7708 smp->data.u.str = *data;
7709
7710 return 1;
7711}
7712#endif
7713
Patrick Hemmer41966772018-04-28 19:15:48 -04007714#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emeric Brunfe68f682012-10-16 14:59:28 +02007715static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007716smp_fetch_ssl_fc_sni(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02007717{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007718 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007719 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007720
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01007721 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007722 smp->data.type = SMP_T_STR;
Willy Tarreau7875d092012-09-10 08:20:03 +02007723
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007724 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007725 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7726 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007727 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007728
Olivier Houchard66ab4982019-02-26 18:37:15 +01007729 smp->data.u.str.area = (char *)SSL_get_servername(ctx->ssl, TLSEXT_NAMETYPE_host_name);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007730 if (!smp->data.u.str.area)
Willy Tarreau3e394c92012-09-14 23:56:58 +02007731 return 0;
7732
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007733 smp->data.u.str.data = strlen(smp->data.u.str.area);
Willy Tarreau7875d092012-09-10 08:20:03 +02007734 return 1;
Willy Tarreau7875d092012-09-10 08:20:03 +02007735}
Patrick Hemmer41966772018-04-28 19:15:48 -04007736#endif
Willy Tarreau7875d092012-09-10 08:20:03 +02007737
David Sc1ad52e2014-04-08 18:48:47 -04007738static int
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007739smp_fetch_ssl_fc_cl_bin(const struct arg *args, struct sample *smp, const char *kw, void *private)
7740{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007741 struct connection *conn;
7742 struct ssl_capture *capture;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007743 struct ssl_sock_ctx *ctx;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007744
7745 conn = objt_conn(smp->sess->origin);
7746 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7747 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007748 ctx = conn->xprt_ctx;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007749
Olivier Houchard66ab4982019-02-26 18:37:15 +01007750 capture = SSL_get_ex_data(ctx->ssl, ssl_capture_ptr_index);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007751 if (!capture)
7752 return 0;
7753
7754 smp->flags = SMP_F_CONST;
7755 smp->data.type = SMP_T_BIN;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007756 smp->data.u.str.area = capture->ciphersuite;
7757 smp->data.u.str.data = capture->ciphersuite_len;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007758 return 1;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007759}
7760
7761static int
7762smp_fetch_ssl_fc_cl_hex(const struct arg *args, struct sample *smp, const char *kw, void *private)
7763{
Willy Tarreau83061a82018-07-13 11:56:34 +02007764 struct buffer *data;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007765
7766 if (!smp_fetch_ssl_fc_cl_bin(args, smp, kw, private))
7767 return 0;
7768
7769 data = get_trash_chunk();
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007770 dump_binary(data, smp->data.u.str.area, smp->data.u.str.data);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007771 smp->data.type = SMP_T_BIN;
7772 smp->data.u.str = *data;
7773 return 1;
7774}
7775
7776static int
7777smp_fetch_ssl_fc_cl_xxh64(const struct arg *args, struct sample *smp, const char *kw, void *private)
7778{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007779 struct connection *conn;
7780 struct ssl_capture *capture;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007781 struct ssl_sock_ctx *ctx;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007782
7783 conn = objt_conn(smp->sess->origin);
7784 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7785 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007786 ctx = conn->xprt_ctx;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007787
Olivier Houchard66ab4982019-02-26 18:37:15 +01007788 capture = SSL_get_ex_data(ctx->ssl, ssl_capture_ptr_index);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007789 if (!capture)
7790 return 0;
7791
7792 smp->data.type = SMP_T_SINT;
7793 smp->data.u.sint = capture->xxh64;
7794 return 1;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007795}
7796
7797static int
7798smp_fetch_ssl_fc_cl_str(const struct arg *args, struct sample *smp, const char *kw, void *private)
7799{
Willy Tarreau5db847a2019-05-09 14:13:35 +02007800#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL)
Willy Tarreau83061a82018-07-13 11:56:34 +02007801 struct buffer *data;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007802 int i;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007803
7804 if (!smp_fetch_ssl_fc_cl_bin(args, smp, kw, private))
7805 return 0;
7806
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007807 data = get_trash_chunk();
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007808 for (i = 0; i + 1 < smp->data.u.str.data; i += 2) {
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02007809 const char *str;
7810 const SSL_CIPHER *cipher;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007811 const unsigned char *bin = (const unsigned char *) smp->data.u.str.area + i;
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02007812 uint16_t id = (bin[0] << 8) | bin[1];
7813#if defined(OPENSSL_IS_BORINGSSL)
7814 cipher = SSL_get_cipher_by_value(id);
7815#else
Willy Tarreaub7290772018-10-15 11:01:59 +02007816 struct connection *conn = __objt_conn(smp->sess->origin);
Olivier Houchard66ab4982019-02-26 18:37:15 +01007817 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
7818 cipher = SSL_CIPHER_find(ctx->ssl, bin);
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02007819#endif
7820 str = SSL_CIPHER_get_name(cipher);
7821 if (!str || strcmp(str, "(NONE)") == 0)
7822 chunk_appendf(data, "%sUNKNOWN(%04x)", i == 0 ? "" : ",", id);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007823 else
7824 chunk_appendf(data, "%s%s", i == 0 ? "" : ",", str);
7825 }
7826 smp->data.type = SMP_T_STR;
7827 smp->data.u.str = *data;
7828 return 1;
7829#else
7830 return smp_fetch_ssl_fc_cl_xxh64(args, smp, kw, private);
7831#endif
7832}
7833
Willy Tarreau9a1ab082019-05-09 13:26:41 +02007834#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007835static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007836smp_fetch_ssl_fc_unique_id(const struct arg *args, struct sample *smp, const char *kw, void *private)
David Sc1ad52e2014-04-08 18:48:47 -04007837{
Emeric Bruneb8def92018-02-19 15:59:48 +01007838 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7839 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
David Sc1ad52e2014-04-08 18:48:47 -04007840 int finished_len;
Willy Tarreau83061a82018-07-13 11:56:34 +02007841 struct buffer *finished_trash;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007842 struct ssl_sock_ctx *ctx;
David Sc1ad52e2014-04-08 18:48:47 -04007843
7844 smp->flags = 0;
David Sc1ad52e2014-04-08 18:48:47 -04007845 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7846 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007847 ctx = conn->xprt_ctx;
David Sc1ad52e2014-04-08 18:48:47 -04007848
7849 if (!(conn->flags & CO_FL_CONNECTED)) {
7850 smp->flags |= SMP_F_MAY_CHANGE;
7851 return 0;
7852 }
7853
7854 finished_trash = get_trash_chunk();
Olivier Houchard66ab4982019-02-26 18:37:15 +01007855 if (!SSL_session_reused(ctx->ssl))
7856 finished_len = SSL_get_peer_finished(ctx->ssl,
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007857 finished_trash->area,
7858 finished_trash->size);
David Sc1ad52e2014-04-08 18:48:47 -04007859 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007860 finished_len = SSL_get_finished(ctx->ssl,
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007861 finished_trash->area,
7862 finished_trash->size);
David Sc1ad52e2014-04-08 18:48:47 -04007863
7864 if (!finished_len)
7865 return 0;
7866
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007867 finished_trash->data = finished_len;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007868 smp->data.u.str = *finished_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007869 smp->data.type = SMP_T_BIN;
David Sc1ad52e2014-04-08 18:48:47 -04007870
7871 return 1;
David Sc1ad52e2014-04-08 18:48:47 -04007872}
Patrick Hemmer41966772018-04-28 19:15:48 -04007873#endif
David Sc1ad52e2014-04-08 18:48:47 -04007874
Emeric Brun2525b6b2012-10-18 15:59:43 +02007875/* integer, returns the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02007876static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007877smp_fetch_ssl_c_ca_err(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunf282a812012-09-21 15:27:54 +02007878{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007879 struct connection *conn;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007880 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007881
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007882 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007883 if (!conn || conn->xprt != &ssl_sock)
7884 return 0;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007885 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007886
7887 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02007888 smp->flags = SMP_F_MAY_CHANGE;
7889 return 0;
7890 }
7891
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007892 smp->data.type = SMP_T_SINT;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007893 smp->data.u.sint = (unsigned long long int)SSL_SOCK_ST_TO_CA_ERROR(ctx->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02007894 smp->flags = 0;
7895
7896 return 1;
7897}
7898
Emeric Brun2525b6b2012-10-18 15:59:43 +02007899/* integer, returns the depth of the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02007900static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007901smp_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 +02007902{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007903 struct connection *conn;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007904 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007905
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007906 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007907 if (!conn || conn->xprt != &ssl_sock)
Emeric Brunf282a812012-09-21 15:27:54 +02007908 return 0;
7909
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007910 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02007911 smp->flags = SMP_F_MAY_CHANGE;
7912 return 0;
7913 }
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007914 ctx = conn->xprt_ctx;
Emeric Brunf282a812012-09-21 15:27:54 +02007915
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007916 smp->data.type = SMP_T_SINT;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007917 smp->data.u.sint = (long long int)SSL_SOCK_ST_TO_CAEDEPTH(ctx->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02007918 smp->flags = 0;
7919
7920 return 1;
7921}
7922
Emeric Brun2525b6b2012-10-18 15:59:43 +02007923/* integer, returns the first verify error on client certificate */
Emeric Brunf282a812012-09-21 15:27:54 +02007924static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007925smp_fetch_ssl_c_err(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunf282a812012-09-21 15:27:54 +02007926{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007927 struct connection *conn;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007928 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007929
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007930 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007931 if (!conn || conn->xprt != &ssl_sock)
7932 return 0;
7933
7934 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02007935 smp->flags = SMP_F_MAY_CHANGE;
7936 return 0;
7937 }
7938
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007939 ctx = conn->xprt_ctx;
7940
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007941 smp->data.type = SMP_T_SINT;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007942 smp->data.u.sint = (long long int)SSL_SOCK_ST_TO_CRTERROR(ctx->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02007943 smp->flags = 0;
7944
7945 return 1;
7946}
7947
Emeric Brun2525b6b2012-10-18 15:59:43 +02007948/* integer, returns the verify result on client cert */
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02007949static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007950smp_fetch_ssl_c_verify(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02007951{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007952 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007953 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007954
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007955 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007956 if (!conn || conn->xprt != &ssl_sock)
7957 return 0;
7958
7959 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02007960 smp->flags = SMP_F_MAY_CHANGE;
7961 return 0;
7962 }
7963
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007964 if (!conn->xprt_ctx)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02007965 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007966 ctx = conn->xprt_ctx;
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02007967
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007968 smp->data.type = SMP_T_SINT;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007969 smp->data.u.sint = (long long int)SSL_get_verify_result(ctx->ssl);
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02007970 smp->flags = 0;
7971
7972 return 1;
7973}
7974
Emeric Brunfb510ea2012-10-05 12:00:26 +02007975/* parse the "ca-file" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007976static 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 +02007977{
7978 if (!*args[cur_arg + 1]) {
7979 if (err)
7980 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
7981 return ERR_ALERT | ERR_FATAL;
7982 }
7983
Willy Tarreauef934602016-12-22 23:12:01 +01007984 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
7985 memprintf(&conf->ca_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02007986 else
7987 memprintf(&conf->ca_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02007988
Emeric Brund94b3fe2012-09-20 18:23:56 +02007989 return 0;
7990}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007991static int bind_parse_ca_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7992{
7993 return ssl_bind_parse_ca_file(args, cur_arg, px, &conf->ssl_conf, err);
7994}
Emeric Brund94b3fe2012-09-20 18:23:56 +02007995
Christopher Faulet31af49d2015-06-09 17:29:50 +02007996/* parse the "ca-sign-file" bind keyword */
7997static int bind_parse_ca_sign_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7998{
7999 if (!*args[cur_arg + 1]) {
8000 if (err)
8001 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
8002 return ERR_ALERT | ERR_FATAL;
8003 }
8004
Willy Tarreauef934602016-12-22 23:12:01 +01008005 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
8006 memprintf(&conf->ca_sign_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Christopher Faulet31af49d2015-06-09 17:29:50 +02008007 else
8008 memprintf(&conf->ca_sign_file, "%s", args[cur_arg + 1]);
8009
8010 return 0;
8011}
8012
Bertrand Jacquinff13c062016-11-13 16:37:11 +00008013/* parse the "ca-sign-pass" bind keyword */
Christopher Faulet31af49d2015-06-09 17:29:50 +02008014static int bind_parse_ca_sign_pass(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8015{
8016 if (!*args[cur_arg + 1]) {
8017 if (err)
8018 memprintf(err, "'%s' : missing CAkey password", args[cur_arg]);
8019 return ERR_ALERT | ERR_FATAL;
8020 }
8021 memprintf(&conf->ca_sign_pass, "%s", args[cur_arg + 1]);
8022 return 0;
8023}
8024
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008025/* parse the "ciphers" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008026static 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 +02008027{
8028 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02008029 memprintf(err, "'%s' : missing cipher suite", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008030 return ERR_ALERT | ERR_FATAL;
8031 }
8032
Emeric Brun76d88952012-10-05 15:47:31 +02008033 free(conf->ciphers);
Willy Tarreau4348fad2012-09-20 16:48:07 +02008034 conf->ciphers = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008035 return 0;
8036}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008037static int bind_parse_ciphers(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8038{
8039 return ssl_bind_parse_ciphers(args, cur_arg, px, &conf->ssl_conf, err);
8040}
Dirkjan Bussink415150f2018-09-14 11:14:21 +02008041
Emmanuel Hocdet839af572019-05-14 16:27:35 +02008042#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02008043/* parse the "ciphersuites" bind keyword */
8044static int ssl_bind_parse_ciphersuites(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
8045{
8046 if (!*args[cur_arg + 1]) {
8047 memprintf(err, "'%s' : missing cipher suite", args[cur_arg]);
8048 return ERR_ALERT | ERR_FATAL;
8049 }
8050
8051 free(conf->ciphersuites);
8052 conf->ciphersuites = strdup(args[cur_arg + 1]);
8053 return 0;
8054}
8055static int bind_parse_ciphersuites(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8056{
8057 return ssl_bind_parse_ciphersuites(args, cur_arg, px, &conf->ssl_conf, err);
8058}
8059#endif
8060
Willy Tarreaubbc91962019-10-16 16:42:19 +02008061/* parse the "crt" bind keyword. Returns a set of ERR_* flags possibly with an error in <err>. */
Willy Tarreau4348fad2012-09-20 16:48:07 +02008062static 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 +02008063{
Willy Tarreau38011032013-08-13 16:59:39 +02008064 char path[MAXPATHLEN];
Willy Tarreaub75d6922014-04-14 18:05:41 +02008065
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008066 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02008067 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008068 return ERR_ALERT | ERR_FATAL;
8069 }
8070
Willy Tarreauef934602016-12-22 23:12:01 +01008071 if ((*args[cur_arg + 1] != '/' ) && global_ssl.crt_base) {
8072 if ((strlen(global_ssl.crt_base) + 1 + strlen(args[cur_arg + 1]) + 1) > MAXPATHLEN) {
Emeric Brunc8e8d122012-10-02 18:42:10 +02008073 memprintf(err, "'%s' : path too long", args[cur_arg]);
8074 return ERR_ALERT | ERR_FATAL;
8075 }
Willy Tarreauef934602016-12-22 23:12:01 +01008076 snprintf(path, sizeof(path), "%s/%s", global_ssl.crt_base, args[cur_arg + 1]);
Willy Tarreaubbc91962019-10-16 16:42:19 +02008077 return ssl_sock_load_cert(path, conf, err);
Emeric Brunc8e8d122012-10-02 18:42:10 +02008078 }
8079
Willy Tarreaubbc91962019-10-16 16:42:19 +02008080 return ssl_sock_load_cert(args[cur_arg + 1], conf, err);
Emeric Brund94b3fe2012-09-20 18:23:56 +02008081}
8082
Willy Tarreaubbc91962019-10-16 16:42:19 +02008083/* 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 +01008084static int bind_parse_crt_list(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8085{
Willy Tarreaubbc91962019-10-16 16:42:19 +02008086 int err_code;
8087
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01008088 if (!*args[cur_arg + 1]) {
8089 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
8090 return ERR_ALERT | ERR_FATAL;
8091 }
8092
Willy Tarreaubbc91962019-10-16 16:42:19 +02008093 err_code = ssl_sock_load_cert_list_file(args[cur_arg + 1], conf, px, err);
8094 if (err_code)
Willy Tarreauad1731d2013-04-02 17:35:58 +02008095 memprintf(err, "'%s' : %s", args[cur_arg], *err);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01008096
Willy Tarreaubbc91962019-10-16 16:42:19 +02008097 return err_code;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01008098}
8099
Emeric Brunfb510ea2012-10-05 12:00:26 +02008100/* parse the "crl-file" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008101static 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 +02008102{
Emeric Brun051cdab2012-10-02 19:25:50 +02008103#ifndef X509_V_FLAG_CRL_CHECK
8104 if (err)
8105 memprintf(err, "'%s' : library does not support CRL verify", args[cur_arg]);
8106 return ERR_ALERT | ERR_FATAL;
8107#else
Emeric Brund94b3fe2012-09-20 18:23:56 +02008108 if (!*args[cur_arg + 1]) {
8109 if (err)
8110 memprintf(err, "'%s' : missing CRLfile path", args[cur_arg]);
8111 return ERR_ALERT | ERR_FATAL;
8112 }
Emeric Brun2b58d042012-09-20 17:10:03 +02008113
Willy Tarreauef934602016-12-22 23:12:01 +01008114 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
8115 memprintf(&conf->crl_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02008116 else
8117 memprintf(&conf->crl_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02008118
Emeric Brun2b58d042012-09-20 17:10:03 +02008119 return 0;
Emeric Brun051cdab2012-10-02 19:25:50 +02008120#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02008121}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008122static int bind_parse_crl_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8123{
8124 return ssl_bind_parse_crl_file(args, cur_arg, px, &conf->ssl_conf, err);
8125}
Emeric Brun2b58d042012-09-20 17:10:03 +02008126
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01008127/* parse the "curves" bind keyword keyword */
8128static int ssl_bind_parse_curves(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
8129{
Willy Tarreau9a1ab082019-05-09 13:26:41 +02008130#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01008131 if (!*args[cur_arg + 1]) {
8132 if (err)
8133 memprintf(err, "'%s' : missing curve suite", args[cur_arg]);
8134 return ERR_ALERT | ERR_FATAL;
8135 }
8136 conf->curves = strdup(args[cur_arg + 1]);
8137 return 0;
8138#else
8139 if (err)
8140 memprintf(err, "'%s' : library does not support curve suite", args[cur_arg]);
8141 return ERR_ALERT | ERR_FATAL;
8142#endif
8143}
8144static int bind_parse_curves(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8145{
8146 return ssl_bind_parse_curves(args, cur_arg, px, &conf->ssl_conf, err);
8147}
8148
Bertrand Jacquinff13c062016-11-13 16:37:11 +00008149/* parse the "ecdhe" bind keyword keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008150static 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 +02008151{
Willy Tarreau9a1ab082019-05-09 13:26:41 +02008152#if HA_OPENSSL_VERSION_NUMBER < 0x0090800fL
Emeric Brun2b58d042012-09-20 17:10:03 +02008153 if (err)
8154 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (too old)", args[cur_arg]);
8155 return ERR_ALERT | ERR_FATAL;
8156#elif defined(OPENSSL_NO_ECDH)
8157 if (err)
8158 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (disabled via OPENSSL_NO_ECDH)", args[cur_arg]);
8159 return ERR_ALERT | ERR_FATAL;
8160#else
8161 if (!*args[cur_arg + 1]) {
8162 if (err)
8163 memprintf(err, "'%s' : missing named curve", args[cur_arg]);
8164 return ERR_ALERT | ERR_FATAL;
8165 }
8166
8167 conf->ecdhe = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008168
8169 return 0;
Emeric Brun2b58d042012-09-20 17:10:03 +02008170#endif
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008171}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008172static int bind_parse_ecdhe(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8173{
8174 return ssl_bind_parse_ecdhe(args, cur_arg, px, &conf->ssl_conf, err);
8175}
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008176
Bertrand Jacquinff13c062016-11-13 16:37:11 +00008177/* parse the "crt-ignore-err" and "ca-ignore-err" bind keywords */
Emeric Brun81c00f02012-09-21 14:31:21 +02008178static int bind_parse_ignore_err(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8179{
8180 int code;
8181 char *p = args[cur_arg + 1];
8182 unsigned long long *ignerr = &conf->crt_ignerr;
8183
8184 if (!*p) {
8185 if (err)
8186 memprintf(err, "'%s' : missing error IDs list", args[cur_arg]);
8187 return ERR_ALERT | ERR_FATAL;
8188 }
8189
8190 if (strcmp(args[cur_arg], "ca-ignore-err") == 0)
8191 ignerr = &conf->ca_ignerr;
8192
8193 if (strcmp(p, "all") == 0) {
8194 *ignerr = ~0ULL;
8195 return 0;
8196 }
8197
8198 while (p) {
8199 code = atoi(p);
8200 if ((code <= 0) || (code > 63)) {
8201 if (err)
8202 memprintf(err, "'%s' : ID '%d' out of range (1..63) in error IDs list '%s'",
8203 args[cur_arg], code, args[cur_arg + 1]);
8204 return ERR_ALERT | ERR_FATAL;
8205 }
8206 *ignerr |= 1ULL << code;
8207 p = strchr(p, ',');
8208 if (p)
8209 p++;
8210 }
8211
Emeric Brun2cb7ae52012-10-05 14:14:21 +02008212 return 0;
8213}
8214
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008215/* parse tls_method_options "no-xxx" and "force-xxx" */
8216static int parse_tls_method_options(char *arg, struct tls_version_filter *methods, char **err)
Emeric Brun2cb7ae52012-10-05 14:14:21 +02008217{
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008218 uint16_t v;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008219 char *p;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008220 p = strchr(arg, '-');
8221 if (!p)
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008222 goto fail;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008223 p++;
8224 if (!strcmp(p, "sslv3"))
8225 v = CONF_SSLV3;
8226 else if (!strcmp(p, "tlsv10"))
8227 v = CONF_TLSV10;
8228 else if (!strcmp(p, "tlsv11"))
8229 v = CONF_TLSV11;
8230 else if (!strcmp(p, "tlsv12"))
8231 v = CONF_TLSV12;
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +02008232 else if (!strcmp(p, "tlsv13"))
8233 v = CONF_TLSV13;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008234 else
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008235 goto fail;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008236 if (!strncmp(arg, "no-", 3))
8237 methods->flags |= methodVersions[v].flag;
8238 else if (!strncmp(arg, "force-", 6))
8239 methods->min = methods->max = v;
8240 else
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008241 goto fail;
Emeric Brun2d0c4822012-10-02 13:45:20 +02008242 return 0;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008243 fail:
8244 if (err)
8245 memprintf(err, "'%s' : option not implemented", arg);
8246 return ERR_ALERT | ERR_FATAL;
Emeric Brun2d0c4822012-10-02 13:45:20 +02008247}
8248
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008249static 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 +02008250{
Emmanuel Hocdet43664762017-08-09 18:26:20 +02008251 return parse_tls_method_options(args[cur_arg], &conf->ssl_conf.ssl_methods, err);
Emeric Brun2cb7ae52012-10-05 14:14:21 +02008252}
8253
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008254static 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 +02008255{
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008256 return parse_tls_method_options(args[*cur_arg], &newsrv->ssl_ctx.methods, err);
8257}
8258
8259/* parse tls_method min/max: "ssl-min-ver" and "ssl-max-ver" */
8260static int parse_tls_method_minmax(char **args, int cur_arg, struct tls_version_filter *methods, char **err)
8261{
8262 uint16_t i, v = 0;
8263 char *argv = args[cur_arg + 1];
8264 if (!*argv) {
8265 if (err)
8266 memprintf(err, "'%s' : missing the ssl/tls version", args[cur_arg]);
8267 return ERR_ALERT | ERR_FATAL;
8268 }
8269 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
8270 if (!strcmp(argv, methodVersions[i].name))
8271 v = i;
8272 if (!v) {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008273 if (err)
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008274 memprintf(err, "'%s' : unknown ssl/tls version", args[cur_arg + 1]);
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008275 return ERR_ALERT | ERR_FATAL;
8276 }
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008277 if (!strcmp("ssl-min-ver", args[cur_arg]))
8278 methods->min = v;
8279 else if (!strcmp("ssl-max-ver", args[cur_arg]))
8280 methods->max = v;
8281 else {
8282 if (err)
8283 memprintf(err, "'%s' : option not implemented", args[cur_arg]);
8284 return ERR_ALERT | ERR_FATAL;
8285 }
Emeric Brun2cb7ae52012-10-05 14:14:21 +02008286 return 0;
Emeric Brun2cb7ae52012-10-05 14:14:21 +02008287}
Emeric Brun2cb7ae52012-10-05 14:14:21 +02008288
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02008289static int ssl_bind_parse_tls_method_minmax(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
8290{
Willy Tarreau9a1ab082019-05-09 13:26:41 +02008291#if (HA_OPENSSL_VERSION_NUMBER < 0x10101000L) && !defined(OPENSSL_IS_BORINGSSL)
Christopher Faulet767a84b2017-11-24 16:50:31 +01008292 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 +02008293#endif
8294 return parse_tls_method_minmax(args, cur_arg, &conf->ssl_methods, err);
8295}
8296
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008297static int bind_parse_tls_method_minmax(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8298{
Emmanuel Hocdet43664762017-08-09 18:26:20 +02008299 return parse_tls_method_minmax(args, cur_arg, &conf->ssl_conf.ssl_methods, err);
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008300}
8301
8302static int srv_parse_tls_method_minmax(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8303{
8304 return parse_tls_method_minmax(args, *cur_arg, &newsrv->ssl_ctx.methods, err);
8305}
8306
Emeric Brun2d0c4822012-10-02 13:45:20 +02008307/* parse the "no-tls-tickets" bind keyword */
Emmanuel Hocdet4608ed92017-01-20 13:06:27 +01008308static 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 +02008309{
Emeric Brun89675492012-10-05 13:48:26 +02008310 conf->ssl_options |= BC_SSL_O_NO_TLS_TICKETS;
Emeric Brun81c00f02012-09-21 14:31:21 +02008311 return 0;
8312}
Emeric Brun2d0c4822012-10-02 13:45:20 +02008313
Olivier Houchardc2aae742017-09-22 18:26:28 +02008314/* parse the "allow-0rtt" bind keyword */
8315static int ssl_bind_parse_allow_0rtt(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
8316{
8317 conf->early_data = 1;
8318 return 0;
8319}
8320
8321static int bind_parse_allow_0rtt(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8322{
Olivier Houchard9679ac92017-10-27 14:58:08 +02008323 conf->ssl_conf.early_data = 1;
Olivier Houchardc2aae742017-09-22 18:26:28 +02008324 return 0;
8325}
8326
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02008327/* parse the "npn" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008328static 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 +02008329{
Bernard Spil13c53f82018-02-15 13:34:58 +01008330#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02008331 char *p1, *p2;
8332
8333 if (!*args[cur_arg + 1]) {
8334 memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[cur_arg]);
8335 return ERR_ALERT | ERR_FATAL;
8336 }
8337
8338 free(conf->npn_str);
8339
Willy Tarreau3724da12016-02-12 17:11:12 +01008340 /* the NPN string is built as a suite of (<len> <name>)*,
8341 * so we reuse each comma to store the next <len> and need
8342 * one more for the end of the string.
8343 */
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02008344 conf->npn_len = strlen(args[cur_arg + 1]) + 1;
Willy Tarreau3724da12016-02-12 17:11:12 +01008345 conf->npn_str = calloc(1, conf->npn_len + 1);
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02008346 memcpy(conf->npn_str + 1, args[cur_arg + 1], conf->npn_len);
8347
8348 /* replace commas with the name length */
8349 p1 = conf->npn_str;
8350 p2 = p1 + 1;
8351 while (1) {
8352 p2 = memchr(p1 + 1, ',', conf->npn_str + conf->npn_len - (p1 + 1));
8353 if (!p2)
8354 p2 = p1 + 1 + strlen(p1 + 1);
8355
8356 if (p2 - (p1 + 1) > 255) {
8357 *p2 = '\0';
8358 memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
8359 return ERR_ALERT | ERR_FATAL;
8360 }
8361
8362 *p1 = p2 - (p1 + 1);
8363 p1 = p2;
8364
8365 if (!*p2)
8366 break;
8367
8368 *(p2++) = '\0';
8369 }
8370 return 0;
8371#else
8372 if (err)
8373 memprintf(err, "'%s' : library does not support TLS NPN extension", args[cur_arg]);
8374 return ERR_ALERT | ERR_FATAL;
8375#endif
8376}
8377
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008378static int bind_parse_npn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8379{
8380 return ssl_bind_parse_npn(args, cur_arg, px, &conf->ssl_conf, err);
8381}
8382
Willy Tarreauab861d32013-04-02 02:30:41 +02008383/* parse the "alpn" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008384static 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 +02008385{
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01008386#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02008387 char *p1, *p2;
8388
8389 if (!*args[cur_arg + 1]) {
8390 memprintf(err, "'%s' : missing the comma-delimited ALPN protocol suite", args[cur_arg]);
8391 return ERR_ALERT | ERR_FATAL;
8392 }
8393
8394 free(conf->alpn_str);
8395
Marcoen Hirschbergbef60912016-02-12 17:05:24 +01008396 /* the ALPN string is built as a suite of (<len> <name>)*,
8397 * so we reuse each comma to store the next <len> and need
8398 * one more for the end of the string.
8399 */
Willy Tarreauab861d32013-04-02 02:30:41 +02008400 conf->alpn_len = strlen(args[cur_arg + 1]) + 1;
Marcoen Hirschbergbef60912016-02-12 17:05:24 +01008401 conf->alpn_str = calloc(1, conf->alpn_len + 1);
Willy Tarreauab861d32013-04-02 02:30:41 +02008402 memcpy(conf->alpn_str + 1, args[cur_arg + 1], conf->alpn_len);
8403
8404 /* replace commas with the name length */
8405 p1 = conf->alpn_str;
8406 p2 = p1 + 1;
8407 while (1) {
8408 p2 = memchr(p1 + 1, ',', conf->alpn_str + conf->alpn_len - (p1 + 1));
8409 if (!p2)
8410 p2 = p1 + 1 + strlen(p1 + 1);
8411
8412 if (p2 - (p1 + 1) > 255) {
8413 *p2 = '\0';
8414 memprintf(err, "'%s' : ALPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
8415 return ERR_ALERT | ERR_FATAL;
8416 }
8417
8418 *p1 = p2 - (p1 + 1);
8419 p1 = p2;
8420
8421 if (!*p2)
8422 break;
8423
8424 *(p2++) = '\0';
8425 }
8426 return 0;
8427#else
8428 if (err)
8429 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[cur_arg]);
8430 return ERR_ALERT | ERR_FATAL;
8431#endif
8432}
8433
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008434static int bind_parse_alpn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8435{
8436 return ssl_bind_parse_alpn(args, cur_arg, px, &conf->ssl_conf, err);
8437}
8438
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008439/* parse the "ssl" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02008440static 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 +02008441{
Willy Tarreau71a8c7c2016-12-21 22:04:54 +01008442 conf->xprt = &ssl_sock;
Willy Tarreau4348fad2012-09-20 16:48:07 +02008443 conf->is_ssl = 1;
Emeric Brun76d88952012-10-05 15:47:31 +02008444
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008445 if (global_ssl.listen_default_ciphers && !conf->ssl_conf.ciphers)
8446 conf->ssl_conf.ciphers = strdup(global_ssl.listen_default_ciphers);
Emmanuel Hocdet839af572019-05-14 16:27:35 +02008447#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02008448 if (global_ssl.listen_default_ciphersuites && !conf->ssl_conf.ciphersuites)
8449 conf->ssl_conf.ciphersuites = strdup(global_ssl.listen_default_ciphersuites);
8450#endif
Emmanuel Hocdet4608ed92017-01-20 13:06:27 +01008451 conf->ssl_options |= global_ssl.listen_default_ssloptions;
Emmanuel Hocdet43664762017-08-09 18:26:20 +02008452 conf->ssl_conf.ssl_methods.flags |= global_ssl.listen_default_sslmethods.flags;
8453 if (!conf->ssl_conf.ssl_methods.min)
8454 conf->ssl_conf.ssl_methods.min = global_ssl.listen_default_sslmethods.min;
8455 if (!conf->ssl_conf.ssl_methods.max)
8456 conf->ssl_conf.ssl_methods.max = global_ssl.listen_default_sslmethods.max;
Emeric Brun76d88952012-10-05 15:47:31 +02008457
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008458 return 0;
8459}
8460
Lukas Tribus53ae85c2017-05-04 15:45:40 +00008461/* parse the "prefer-client-ciphers" bind keyword */
8462static int bind_parse_pcc(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8463{
8464 conf->ssl_options |= BC_SSL_O_PREF_CLIE_CIPH;
8465 return 0;
8466}
8467
Christopher Faulet31af49d2015-06-09 17:29:50 +02008468/* parse the "generate-certificates" bind keyword */
8469static int bind_parse_generate_certs(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8470{
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01008471#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Christopher Faulet31af49d2015-06-09 17:29:50 +02008472 conf->generate_certs = 1;
8473#else
8474 memprintf(err, "%sthis version of openssl cannot generate SSL certificates.\n",
8475 err && *err ? *err : "");
8476#endif
8477 return 0;
8478}
8479
Emmanuel Hocdet65623372013-01-24 17:17:15 +01008480/* parse the "strict-sni" bind keyword */
8481static int bind_parse_strict_sni(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8482{
8483 conf->strict_sni = 1;
8484 return 0;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008485}
8486
8487/* parse the "tls-ticket-keys" bind keyword */
8488static int bind_parse_tls_ticket_keys(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8489{
8490#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
Christopher Faulete566f3d2019-10-21 09:55:49 +02008491 FILE *f = NULL;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008492 int i = 0;
8493 char thisline[LINESIZE];
Christopher Faulete566f3d2019-10-21 09:55:49 +02008494 struct tls_keys_ref *keys_ref = NULL;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008495
8496 if (!*args[cur_arg + 1]) {
8497 if (err)
8498 memprintf(err, "'%s' : missing TLS ticket keys file path", args[cur_arg]);
Christopher Faulete566f3d2019-10-21 09:55:49 +02008499 goto fail;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008500 }
8501
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02008502 keys_ref = tlskeys_ref_lookup(args[cur_arg + 1]);
Willy Tarreau17b4aa12018-07-17 10:05:32 +02008503 if (keys_ref) {
8504 keys_ref->refcount++;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02008505 conf->keys_ref = keys_ref;
8506 return 0;
8507 }
8508
Christopher Faulete566f3d2019-10-21 09:55:49 +02008509 keys_ref = calloc(1, sizeof(*keys_ref));
Emeric Brun09852f72019-01-10 10:51:13 +01008510 if (!keys_ref) {
8511 if (err)
8512 memprintf(err, "'%s' : allocation error", args[cur_arg+1]);
Christopher Faulete566f3d2019-10-21 09:55:49 +02008513 goto fail;
Emeric Brun09852f72019-01-10 10:51:13 +01008514 }
8515
Emeric Brun9e754772019-01-10 17:51:55 +01008516 keys_ref->tlskeys = malloc(TLS_TICKETS_NO * sizeof(union tls_sess_key));
Emeric Brun09852f72019-01-10 10:51:13 +01008517 if (!keys_ref->tlskeys) {
Emeric Brun09852f72019-01-10 10:51:13 +01008518 if (err)
8519 memprintf(err, "'%s' : allocation error", args[cur_arg+1]);
Christopher Faulete566f3d2019-10-21 09:55:49 +02008520 goto fail;
Emeric Brun09852f72019-01-10 10:51:13 +01008521 }
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008522
8523 if ((f = fopen(args[cur_arg + 1], "r")) == NULL) {
8524 if (err)
8525 memprintf(err, "'%s' : unable to load ssl tickets keys file", args[cur_arg+1]);
Christopher Faulete566f3d2019-10-21 09:55:49 +02008526 goto fail;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008527 }
8528
Nenad Merdanovic146defa2015-05-09 08:46:00 +02008529 keys_ref->filename = strdup(args[cur_arg + 1]);
Emeric Brun09852f72019-01-10 10:51:13 +01008530 if (!keys_ref->filename) {
Emeric Brun09852f72019-01-10 10:51:13 +01008531 if (err)
8532 memprintf(err, "'%s' : allocation error", args[cur_arg+1]);
Christopher Faulete566f3d2019-10-21 09:55:49 +02008533 goto fail;
Emeric Brun09852f72019-01-10 10:51:13 +01008534 }
Nenad Merdanovic146defa2015-05-09 08:46:00 +02008535
Emeric Brun9e754772019-01-10 17:51:55 +01008536 keys_ref->key_size_bits = 0;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008537 while (fgets(thisline, sizeof(thisline), f) != NULL) {
8538 int len = strlen(thisline);
Emeric Brun9e754772019-01-10 17:51:55 +01008539 int dec_size;
8540
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008541 /* Strip newline characters from the end */
8542 if(thisline[len - 1] == '\n')
8543 thisline[--len] = 0;
8544
8545 if(thisline[len - 1] == '\r')
8546 thisline[--len] = 0;
8547
Emeric Brun9e754772019-01-10 17:51:55 +01008548 dec_size = base64dec(thisline, len, (char *) (keys_ref->tlskeys + i % TLS_TICKETS_NO), sizeof(union tls_sess_key));
8549 if (dec_size < 0) {
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008550 if (err)
8551 memprintf(err, "'%s' : unable to decode base64 key on line %d", args[cur_arg+1], i + 1);
Christopher Faulete566f3d2019-10-21 09:55:49 +02008552 goto fail;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008553 }
Emeric Brun9e754772019-01-10 17:51:55 +01008554 else if (!keys_ref->key_size_bits && (dec_size == sizeof(struct tls_sess_key_128))) {
8555 keys_ref->key_size_bits = 128;
8556 }
8557 else if (!keys_ref->key_size_bits && (dec_size == sizeof(struct tls_sess_key_256))) {
8558 keys_ref->key_size_bits = 256;
8559 }
8560 else if (((dec_size != sizeof(struct tls_sess_key_128)) && (dec_size != sizeof(struct tls_sess_key_256)))
8561 || ((dec_size == sizeof(struct tls_sess_key_128) && (keys_ref->key_size_bits != 128)))
8562 || ((dec_size == sizeof(struct tls_sess_key_256) && (keys_ref->key_size_bits != 256)))) {
Emeric Brun9e754772019-01-10 17:51:55 +01008563 if (err)
8564 memprintf(err, "'%s' : wrong sized key on line %d", args[cur_arg+1], i + 1);
Christopher Faulete566f3d2019-10-21 09:55:49 +02008565 goto fail;
Emeric Brun9e754772019-01-10 17:51:55 +01008566 }
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008567 i++;
8568 }
8569
8570 if (i < TLS_TICKETS_NO) {
8571 if (err)
8572 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 +02008573 goto fail;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008574 }
8575
8576 fclose(f);
8577
8578 /* Use penultimate key for encryption, handle when TLS_TICKETS_NO = 1 */
Nenad Merdanovic17891152016-03-25 22:16:57 +01008579 i -= 2;
8580 keys_ref->tls_ticket_enc_index = i < 0 ? 0 : i % TLS_TICKETS_NO;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02008581 keys_ref->unique_id = -1;
Willy Tarreau17b4aa12018-07-17 10:05:32 +02008582 keys_ref->refcount = 1;
Christopher Faulet16f45c82018-02-16 11:23:49 +01008583 HA_RWLOCK_INIT(&keys_ref->lock);
Nenad Merdanovic146defa2015-05-09 08:46:00 +02008584 conf->keys_ref = keys_ref;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008585
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02008586 LIST_ADD(&tlskeys_reference, &keys_ref->list);
8587
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008588 return 0;
Christopher Faulete566f3d2019-10-21 09:55:49 +02008589
8590 fail:
8591 if (f)
8592 fclose(f);
8593 if (keys_ref) {
8594 free(keys_ref->filename);
8595 free(keys_ref->tlskeys);
8596 free(keys_ref);
8597 }
8598 return ERR_ALERT | ERR_FATAL;
8599
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008600#else
8601 if (err)
8602 memprintf(err, "'%s' : TLS ticket callback extension not supported", args[cur_arg]);
8603 return ERR_ALERT | ERR_FATAL;
8604#endif /* SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB */
Emmanuel Hocdet65623372013-01-24 17:17:15 +01008605}
8606
Emeric Brund94b3fe2012-09-20 18:23:56 +02008607/* parse the "verify" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008608static 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 +02008609{
8610 if (!*args[cur_arg + 1]) {
8611 if (err)
8612 memprintf(err, "'%s' : missing verify method", args[cur_arg]);
8613 return ERR_ALERT | ERR_FATAL;
8614 }
8615
8616 if (strcmp(args[cur_arg + 1], "none") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01008617 conf->verify = SSL_SOCK_VERIFY_NONE;
Emeric Brund94b3fe2012-09-20 18:23:56 +02008618 else if (strcmp(args[cur_arg + 1], "optional") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01008619 conf->verify = SSL_SOCK_VERIFY_OPTIONAL;
Emeric Brund94b3fe2012-09-20 18:23:56 +02008620 else if (strcmp(args[cur_arg + 1], "required") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01008621 conf->verify = SSL_SOCK_VERIFY_REQUIRED;
Emeric Brund94b3fe2012-09-20 18:23:56 +02008622 else {
8623 if (err)
8624 memprintf(err, "'%s' : unknown verify method '%s', only 'none', 'optional', and 'required' are supported\n",
8625 args[cur_arg], args[cur_arg + 1]);
8626 return ERR_ALERT | ERR_FATAL;
8627 }
8628
8629 return 0;
8630}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008631static int bind_parse_verify(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8632{
8633 return ssl_bind_parse_verify(args, cur_arg, px, &conf->ssl_conf, err);
8634}
Emeric Brund94b3fe2012-09-20 18:23:56 +02008635
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02008636/* parse the "no-ca-names" bind keyword */
8637static int ssl_bind_parse_no_ca_names(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
8638{
8639 conf->no_ca_names = 1;
8640 return 0;
8641}
8642static int bind_parse_no_ca_names(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8643{
8644 return ssl_bind_parse_no_ca_names(args, cur_arg, px, &conf->ssl_conf, err);
8645}
8646
Willy Tarreau92faadf2012-10-10 23:04:25 +02008647/************** "server" keywords ****************/
8648
Olivier Houchardc7566002018-11-20 23:33:50 +01008649/* parse the "npn" bind keyword */
8650static int srv_parse_npn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8651{
8652#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
8653 char *p1, *p2;
8654
8655 if (!*args[*cur_arg + 1]) {
8656 memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[*cur_arg]);
8657 return ERR_ALERT | ERR_FATAL;
8658 }
8659
8660 free(newsrv->ssl_ctx.npn_str);
8661
8662 /* the NPN string is built as a suite of (<len> <name>)*,
8663 * so we reuse each comma to store the next <len> and need
8664 * one more for the end of the string.
8665 */
8666 newsrv->ssl_ctx.npn_len = strlen(args[*cur_arg + 1]) + 1;
8667 newsrv->ssl_ctx.npn_str = calloc(1, newsrv->ssl_ctx.npn_len + 1);
8668 memcpy(newsrv->ssl_ctx.npn_str + 1, args[*cur_arg + 1],
8669 newsrv->ssl_ctx.npn_len);
8670
8671 /* replace commas with the name length */
8672 p1 = newsrv->ssl_ctx.npn_str;
8673 p2 = p1 + 1;
8674 while (1) {
8675 p2 = memchr(p1 + 1, ',', newsrv->ssl_ctx.npn_str +
8676 newsrv->ssl_ctx.npn_len - (p1 + 1));
8677 if (!p2)
8678 p2 = p1 + 1 + strlen(p1 + 1);
8679
8680 if (p2 - (p1 + 1) > 255) {
8681 *p2 = '\0';
8682 memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[*cur_arg], p1 + 1);
8683 return ERR_ALERT | ERR_FATAL;
8684 }
8685
8686 *p1 = p2 - (p1 + 1);
8687 p1 = p2;
8688
8689 if (!*p2)
8690 break;
8691
8692 *(p2++) = '\0';
8693 }
8694 return 0;
8695#else
8696 if (err)
8697 memprintf(err, "'%s' : library does not support TLS NPN extension", args[*cur_arg]);
8698 return ERR_ALERT | ERR_FATAL;
8699#endif
8700}
8701
Olivier Houchard92150142018-12-21 19:47:01 +01008702/* parse the "alpn" or the "check-alpn" server keyword */
Olivier Houchardc7566002018-11-20 23:33:50 +01008703static int srv_parse_alpn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8704{
8705#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
8706 char *p1, *p2;
Olivier Houchard92150142018-12-21 19:47:01 +01008707 char **alpn_str;
8708 int *alpn_len;
Olivier Houchardc7566002018-11-20 23:33:50 +01008709
Olivier Houchard92150142018-12-21 19:47:01 +01008710 if (*args[*cur_arg] == 'c') {
8711 alpn_str = &newsrv->check.alpn_str;
8712 alpn_len = &newsrv->check.alpn_len;
8713 } else {
8714 alpn_str = &newsrv->ssl_ctx.alpn_str;
8715 alpn_len = &newsrv->ssl_ctx.alpn_len;
8716
8717 }
Olivier Houchardc7566002018-11-20 23:33:50 +01008718 if (!*args[*cur_arg + 1]) {
8719 memprintf(err, "'%s' : missing the comma-delimited ALPN protocol suite", args[*cur_arg]);
8720 return ERR_ALERT | ERR_FATAL;
8721 }
8722
Olivier Houchard92150142018-12-21 19:47:01 +01008723 free(*alpn_str);
Olivier Houchardc7566002018-11-20 23:33:50 +01008724
8725 /* the ALPN string is built as a suite of (<len> <name>)*,
8726 * so we reuse each comma to store the next <len> and need
8727 * one more for the end of the string.
8728 */
Olivier Houchard92150142018-12-21 19:47:01 +01008729 *alpn_len = strlen(args[*cur_arg + 1]) + 1;
8730 *alpn_str = calloc(1, *alpn_len + 1);
8731 memcpy(*alpn_str + 1, args[*cur_arg + 1], *alpn_len);
Olivier Houchardc7566002018-11-20 23:33:50 +01008732
8733 /* replace commas with the name length */
Olivier Houchard92150142018-12-21 19:47:01 +01008734 p1 = *alpn_str;
Olivier Houchardc7566002018-11-20 23:33:50 +01008735 p2 = p1 + 1;
8736 while (1) {
Olivier Houchard92150142018-12-21 19:47:01 +01008737 p2 = memchr(p1 + 1, ',', *alpn_str + *alpn_len - (p1 + 1));
Olivier Houchardc7566002018-11-20 23:33:50 +01008738 if (!p2)
8739 p2 = p1 + 1 + strlen(p1 + 1);
8740
8741 if (p2 - (p1 + 1) > 255) {
8742 *p2 = '\0';
8743 memprintf(err, "'%s' : ALPN protocol name too long : '%s'", args[*cur_arg], p1 + 1);
8744 return ERR_ALERT | ERR_FATAL;
8745 }
8746
8747 *p1 = p2 - (p1 + 1);
8748 p1 = p2;
8749
8750 if (!*p2)
8751 break;
8752
8753 *(p2++) = '\0';
8754 }
8755 return 0;
8756#else
8757 if (err)
8758 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[*cur_arg]);
8759 return ERR_ALERT | ERR_FATAL;
8760#endif
8761}
8762
Emeric Brunef42d922012-10-11 16:11:36 +02008763/* parse the "ca-file" server keyword */
8764static int srv_parse_ca_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8765{
8766 if (!*args[*cur_arg + 1]) {
8767 if (err)
8768 memprintf(err, "'%s' : missing CAfile path", args[*cur_arg]);
8769 return ERR_ALERT | ERR_FATAL;
8770 }
8771
Willy Tarreauef934602016-12-22 23:12:01 +01008772 if ((*args[*cur_arg + 1] != '/') && global_ssl.ca_base)
8773 memprintf(&newsrv->ssl_ctx.ca_file, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02008774 else
8775 memprintf(&newsrv->ssl_ctx.ca_file, "%s", args[*cur_arg + 1]);
8776
8777 return 0;
8778}
8779
Olivier Houchard9130a962017-10-17 17:33:43 +02008780/* parse the "check-sni" server keyword */
8781static int srv_parse_check_sni(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8782{
8783 if (!*args[*cur_arg + 1]) {
8784 if (err)
8785 memprintf(err, "'%s' : missing SNI", args[*cur_arg]);
8786 return ERR_ALERT | ERR_FATAL;
8787 }
8788
8789 newsrv->check.sni = strdup(args[*cur_arg + 1]);
8790 if (!newsrv->check.sni) {
8791 memprintf(err, "'%s' : failed to allocate memory", args[*cur_arg]);
8792 return ERR_ALERT | ERR_FATAL;
8793 }
8794 return 0;
8795
8796}
8797
Willy Tarreau92faadf2012-10-10 23:04:25 +02008798/* parse the "check-ssl" server keyword */
8799static int srv_parse_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8800{
8801 newsrv->check.use_ssl = 1;
Willy Tarreauef934602016-12-22 23:12:01 +01008802 if (global_ssl.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
8803 newsrv->ssl_ctx.ciphers = strdup(global_ssl.connect_default_ciphers);
Emmanuel Hocdet839af572019-05-14 16:27:35 +02008804#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02008805 if (global_ssl.connect_default_ciphersuites && !newsrv->ssl_ctx.ciphersuites)
8806 newsrv->ssl_ctx.ciphersuites = strdup(global_ssl.connect_default_ciphersuites);
8807#endif
Willy Tarreauef934602016-12-22 23:12:01 +01008808 newsrv->ssl_ctx.options |= global_ssl.connect_default_ssloptions;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008809 newsrv->ssl_ctx.methods.flags |= global_ssl.connect_default_sslmethods.flags;
8810 if (!newsrv->ssl_ctx.methods.min)
8811 newsrv->ssl_ctx.methods.min = global_ssl.connect_default_sslmethods.min;
8812 if (!newsrv->ssl_ctx.methods.max)
8813 newsrv->ssl_ctx.methods.max = global_ssl.connect_default_sslmethods.max;
8814
Willy Tarreau92faadf2012-10-10 23:04:25 +02008815 return 0;
8816}
8817
8818/* parse the "ciphers" server keyword */
8819static int srv_parse_ciphers(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8820{
8821 if (!*args[*cur_arg + 1]) {
8822 memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
8823 return ERR_ALERT | ERR_FATAL;
8824 }
8825
8826 free(newsrv->ssl_ctx.ciphers);
8827 newsrv->ssl_ctx.ciphers = strdup(args[*cur_arg + 1]);
8828 return 0;
8829}
Dirkjan Bussink415150f2018-09-14 11:14:21 +02008830
Emmanuel Hocdet839af572019-05-14 16:27:35 +02008831#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02008832/* parse the "ciphersuites" server keyword */
8833static int srv_parse_ciphersuites(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8834{
8835 if (!*args[*cur_arg + 1]) {
8836 memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
8837 return ERR_ALERT | ERR_FATAL;
8838 }
8839
8840 free(newsrv->ssl_ctx.ciphersuites);
8841 newsrv->ssl_ctx.ciphersuites = strdup(args[*cur_arg + 1]);
8842 return 0;
8843}
8844#endif
Willy Tarreau92faadf2012-10-10 23:04:25 +02008845
Emeric Brunef42d922012-10-11 16:11:36 +02008846/* parse the "crl-file" server keyword */
8847static int srv_parse_crl_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8848{
8849#ifndef X509_V_FLAG_CRL_CHECK
8850 if (err)
8851 memprintf(err, "'%s' : library does not support CRL verify", args[*cur_arg]);
8852 return ERR_ALERT | ERR_FATAL;
8853#else
8854 if (!*args[*cur_arg + 1]) {
8855 if (err)
8856 memprintf(err, "'%s' : missing CRLfile path", args[*cur_arg]);
8857 return ERR_ALERT | ERR_FATAL;
8858 }
8859
Willy Tarreauef934602016-12-22 23:12:01 +01008860 if ((*args[*cur_arg + 1] != '/') && global_ssl.ca_base)
8861 memprintf(&newsrv->ssl_ctx.crl_file, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02008862 else
8863 memprintf(&newsrv->ssl_ctx.crl_file, "%s", args[*cur_arg + 1]);
8864
8865 return 0;
8866#endif
8867}
8868
Emeric Bruna7aa3092012-10-26 12:58:00 +02008869/* parse the "crt" server keyword */
8870static int srv_parse_crt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8871{
8872 if (!*args[*cur_arg + 1]) {
8873 if (err)
8874 memprintf(err, "'%s' : missing certificate file path", args[*cur_arg]);
8875 return ERR_ALERT | ERR_FATAL;
8876 }
8877
Willy Tarreauef934602016-12-22 23:12:01 +01008878 if ((*args[*cur_arg + 1] != '/') && global_ssl.crt_base)
Christopher Fauletff3a41e2017-11-23 09:13:32 +01008879 memprintf(&newsrv->ssl_ctx.client_crt, "%s/%s", global_ssl.crt_base, args[*cur_arg + 1]);
Emeric Bruna7aa3092012-10-26 12:58:00 +02008880 else
8881 memprintf(&newsrv->ssl_ctx.client_crt, "%s", args[*cur_arg + 1]);
8882
8883 return 0;
8884}
Emeric Brunef42d922012-10-11 16:11:36 +02008885
Frédéric Lécaille340ae602017-03-13 10:38:04 +01008886/* parse the "no-check-ssl" server keyword */
8887static int srv_parse_no_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8888{
8889 newsrv->check.use_ssl = 0;
8890 free(newsrv->ssl_ctx.ciphers);
8891 newsrv->ssl_ctx.ciphers = NULL;
8892 newsrv->ssl_ctx.options &= ~global_ssl.connect_default_ssloptions;
8893 return 0;
8894}
8895
Frédéric Lécaillee892c4c2017-03-13 12:08:01 +01008896/* parse the "no-send-proxy-v2-ssl" server keyword */
8897static int srv_parse_no_send_proxy_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8898{
8899 newsrv->pp_opts &= ~SRV_PP_V2;
8900 newsrv->pp_opts &= ~SRV_PP_V2_SSL;
8901 return 0;
8902}
8903
8904/* parse the "no-send-proxy-v2-ssl-cn" server keyword */
8905static int srv_parse_no_send_proxy_cn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8906{
8907 newsrv->pp_opts &= ~SRV_PP_V2;
8908 newsrv->pp_opts &= ~SRV_PP_V2_SSL;
8909 newsrv->pp_opts &= ~SRV_PP_V2_SSL_CN;
8910 return 0;
8911}
8912
Frédéric Lécaillee381d762017-03-13 11:54:17 +01008913/* parse the "no-ssl" server keyword */
8914static int srv_parse_no_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8915{
8916 newsrv->use_ssl = 0;
8917 free(newsrv->ssl_ctx.ciphers);
8918 newsrv->ssl_ctx.ciphers = NULL;
8919 return 0;
8920}
8921
Olivier Houchard522eea72017-11-03 16:27:47 +01008922/* parse the "allow-0rtt" server keyword */
8923static int srv_parse_allow_0rtt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8924{
8925 newsrv->ssl_ctx.options |= SRV_SSL_O_EARLY_DATA;
8926 return 0;
8927}
8928
Willy Tarreau2a3fb1c2015-02-05 16:47:07 +01008929/* parse the "no-ssl-reuse" server keyword */
8930static int srv_parse_no_ssl_reuse(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8931{
8932 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_REUSE;
8933 return 0;
8934}
8935
Emeric Brunf9c5c472012-10-11 15:28:34 +02008936/* parse the "no-tls-tickets" server keyword */
8937static int srv_parse_no_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8938{
8939 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLS_TICKETS;
8940 return 0;
8941}
David Safb76832014-05-08 23:42:08 -04008942/* parse the "send-proxy-v2-ssl" server keyword */
8943static int srv_parse_send_proxy_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8944{
8945 newsrv->pp_opts |= SRV_PP_V2;
8946 newsrv->pp_opts |= SRV_PP_V2_SSL;
8947 return 0;
8948}
8949
8950/* parse the "send-proxy-v2-ssl-cn" server keyword */
8951static int srv_parse_send_proxy_cn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8952{
8953 newsrv->pp_opts |= SRV_PP_V2;
8954 newsrv->pp_opts |= SRV_PP_V2_SSL;
8955 newsrv->pp_opts |= SRV_PP_V2_SSL_CN;
8956 return 0;
8957}
Emeric Brunf9c5c472012-10-11 15:28:34 +02008958
Willy Tarreau732eac42015-07-09 11:40:25 +02008959/* parse the "sni" server keyword */
8960static int srv_parse_sni(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8961{
8962#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
8963 memprintf(err, "'%s' : the current SSL library doesn't support the SNI TLS extension", args[*cur_arg]);
8964 return ERR_ALERT | ERR_FATAL;
8965#else
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01008966 char *arg;
Willy Tarreau732eac42015-07-09 11:40:25 +02008967
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01008968 arg = args[*cur_arg + 1];
8969 if (!*arg) {
Willy Tarreau732eac42015-07-09 11:40:25 +02008970 memprintf(err, "'%s' : missing sni expression", args[*cur_arg]);
8971 return ERR_ALERT | ERR_FATAL;
8972 }
8973
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01008974 free(newsrv->sni_expr);
8975 newsrv->sni_expr = strdup(arg);
Willy Tarreau732eac42015-07-09 11:40:25 +02008976
Willy Tarreau732eac42015-07-09 11:40:25 +02008977 return 0;
8978#endif
8979}
8980
Willy Tarreau92faadf2012-10-10 23:04:25 +02008981/* parse the "ssl" server keyword */
8982static int srv_parse_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8983{
8984 newsrv->use_ssl = 1;
Willy Tarreauef934602016-12-22 23:12:01 +01008985 if (global_ssl.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
8986 newsrv->ssl_ctx.ciphers = strdup(global_ssl.connect_default_ciphers);
Emmanuel Hocdet839af572019-05-14 16:27:35 +02008987#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02008988 if (global_ssl.connect_default_ciphersuites && !newsrv->ssl_ctx.ciphersuites)
8989 newsrv->ssl_ctx.ciphersuites = strdup(global_ssl.connect_default_ciphersuites);
8990#endif
Willy Tarreau92faadf2012-10-10 23:04:25 +02008991 return 0;
8992}
8993
Frédéric Lécaille2cfcdbe2017-03-13 11:32:20 +01008994/* parse the "ssl-reuse" server keyword */
8995static int srv_parse_ssl_reuse(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8996{
8997 newsrv->ssl_ctx.options &= ~SRV_SSL_O_NO_REUSE;
8998 return 0;
8999}
9000
Frédéric Lécaille2cfcdbe2017-03-13 11:32:20 +01009001/* parse the "tls-tickets" server keyword */
9002static int srv_parse_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9003{
9004 newsrv->ssl_ctx.options &= ~SRV_SSL_O_NO_TLS_TICKETS;
9005 return 0;
9006}
9007
Emeric Brunef42d922012-10-11 16:11:36 +02009008/* parse the "verify" server keyword */
9009static int srv_parse_verify(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9010{
9011 if (!*args[*cur_arg + 1]) {
9012 if (err)
9013 memprintf(err, "'%s' : missing verify method", args[*cur_arg]);
9014 return ERR_ALERT | ERR_FATAL;
9015 }
9016
9017 if (strcmp(args[*cur_arg + 1], "none") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01009018 newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_NONE;
Emeric Brunef42d922012-10-11 16:11:36 +02009019 else if (strcmp(args[*cur_arg + 1], "required") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01009020 newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_REQUIRED;
Emeric Brunef42d922012-10-11 16:11:36 +02009021 else {
9022 if (err)
9023 memprintf(err, "'%s' : unknown verify method '%s', only 'none' and 'required' are supported\n",
9024 args[*cur_arg], args[*cur_arg + 1]);
9025 return ERR_ALERT | ERR_FATAL;
9026 }
9027
Evan Broderbe554312013-06-27 00:05:25 -07009028 return 0;
9029}
9030
9031/* parse the "verifyhost" server keyword */
9032static int srv_parse_verifyhost(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9033{
9034 if (!*args[*cur_arg + 1]) {
9035 if (err)
9036 memprintf(err, "'%s' : missing hostname to verify against", args[*cur_arg]);
9037 return ERR_ALERT | ERR_FATAL;
9038 }
9039
Frédéric Lécaille273f3212017-03-13 15:52:01 +01009040 free(newsrv->ssl_ctx.verify_host);
Evan Broderbe554312013-06-27 00:05:25 -07009041 newsrv->ssl_ctx.verify_host = strdup(args[*cur_arg + 1]);
9042
Emeric Brunef42d922012-10-11 16:11:36 +02009043 return 0;
9044}
9045
Emeric Brun2c86cbf2014-10-30 15:56:50 +01009046/* parse the "ssl-default-bind-options" keyword in global section */
9047static int ssl_parse_default_bind_options(char **args, int section_type, struct proxy *curpx,
9048 struct proxy *defpx, const char *file, int line,
9049 char **err) {
9050 int i = 1;
9051
9052 if (*(args[i]) == 0) {
9053 memprintf(err, "global statement '%s' expects an option as an argument.", args[0]);
9054 return -1;
9055 }
9056 while (*(args[i])) {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02009057 if (!strcmp(args[i], "no-tls-tickets"))
Willy Tarreauef934602016-12-22 23:12:01 +01009058 global_ssl.listen_default_ssloptions |= BC_SSL_O_NO_TLS_TICKETS;
Lukas Tribus53ae85c2017-05-04 15:45:40 +00009059 else if (!strcmp(args[i], "prefer-client-ciphers"))
9060 global_ssl.listen_default_ssloptions |= BC_SSL_O_PREF_CLIE_CIPH;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02009061 else if (!strcmp(args[i], "ssl-min-ver") || !strcmp(args[i], "ssl-max-ver")) {
9062 if (!parse_tls_method_minmax(args, i, &global_ssl.listen_default_sslmethods, err))
9063 i++;
9064 else {
9065 memprintf(err, "%s on global statement '%s'.", *err, args[0]);
9066 return -1;
9067 }
9068 }
9069 else if (parse_tls_method_options(args[i], &global_ssl.listen_default_sslmethods, err)) {
Emeric Brun2c86cbf2014-10-30 15:56:50 +01009070 memprintf(err, "unknown option '%s' on global statement '%s'.", args[i], args[0]);
9071 return -1;
9072 }
9073 i++;
9074 }
9075 return 0;
9076}
9077
9078/* parse the "ssl-default-server-options" keyword in global section */
9079static int ssl_parse_default_server_options(char **args, int section_type, struct proxy *curpx,
9080 struct proxy *defpx, const char *file, int line,
9081 char **err) {
9082 int i = 1;
9083
9084 if (*(args[i]) == 0) {
9085 memprintf(err, "global statement '%s' expects an option as an argument.", args[0]);
9086 return -1;
9087 }
9088 while (*(args[i])) {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02009089 if (!strcmp(args[i], "no-tls-tickets"))
Willy Tarreauef934602016-12-22 23:12:01 +01009090 global_ssl.connect_default_ssloptions |= SRV_SSL_O_NO_TLS_TICKETS;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02009091 else if (!strcmp(args[i], "ssl-min-ver") || !strcmp(args[i], "ssl-max-ver")) {
9092 if (!parse_tls_method_minmax(args, i, &global_ssl.connect_default_sslmethods, err))
9093 i++;
9094 else {
9095 memprintf(err, "%s on global statement '%s'.", *err, args[0]);
9096 return -1;
9097 }
9098 }
9099 else if (parse_tls_method_options(args[i], &global_ssl.connect_default_sslmethods, err)) {
Emeric Brun2c86cbf2014-10-30 15:56:50 +01009100 memprintf(err, "unknown option '%s' on global statement '%s'.", args[i], args[0]);
9101 return -1;
9102 }
9103 i++;
9104 }
9105 return 0;
9106}
9107
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01009108/* parse the "ca-base" / "crt-base" keywords in global section.
9109 * Returns <0 on alert, >0 on warning, 0 on success.
9110 */
9111static int ssl_parse_global_ca_crt_base(char **args, int section_type, struct proxy *curpx,
9112 struct proxy *defpx, const char *file, int line,
9113 char **err)
9114{
9115 char **target;
9116
Willy Tarreauef934602016-12-22 23:12:01 +01009117 target = (args[0][1] == 'a') ? &global_ssl.ca_base : &global_ssl.crt_base;
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01009118
9119 if (too_many_args(1, args, err, NULL))
9120 return -1;
9121
9122 if (*target) {
9123 memprintf(err, "'%s' already specified.", args[0]);
9124 return -1;
9125 }
9126
9127 if (*(args[1]) == 0) {
9128 memprintf(err, "global statement '%s' expects a directory path as an argument.", args[0]);
9129 return -1;
9130 }
9131 *target = strdup(args[1]);
9132 return 0;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00009133}
9134
9135/* parse the "ssl-mode-async" keyword in global section.
9136 * Returns <0 on alert, >0 on warning, 0 on success.
9137 */
9138static int ssl_parse_global_ssl_async(char **args, int section_type, struct proxy *curpx,
9139 struct proxy *defpx, const char *file, int line,
9140 char **err)
9141{
Willy Tarreau5db847a2019-05-09 14:13:35 +02009142#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00009143 global_ssl.async = 1;
Emeric Brunece0c332017-12-06 13:51:49 +01009144 global.ssl_used_async_engines = nb_engines;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00009145 return 0;
9146#else
9147 memprintf(err, "'%s': openssl library does not support async mode", args[0]);
9148 return -1;
9149#endif
9150}
9151
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02009152#ifndef OPENSSL_NO_ENGINE
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00009153static int ssl_check_async_engine_count(void) {
9154 int err_code = 0;
9155
Emeric Brun3854e012017-05-17 20:42:48 +02009156 if (global_ssl.async && (openssl_engines_initialized > 32)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01009157 ha_alert("ssl-mode-async only supports a maximum of 32 engines.\n");
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00009158 err_code = ERR_ABORT;
9159 }
9160 return err_code;
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01009161}
9162
Grant Zhang872f9c22017-01-21 01:10:18 +00009163/* parse the "ssl-engine" keyword in global section.
9164 * Returns <0 on alert, >0 on warning, 0 on success.
9165 */
9166static int ssl_parse_global_ssl_engine(char **args, int section_type, struct proxy *curpx,
9167 struct proxy *defpx, const char *file, int line,
9168 char **err)
9169{
9170 char *algo;
9171 int ret = -1;
9172
9173 if (*(args[1]) == 0) {
9174 memprintf(err, "global statement '%s' expects a valid engine name as an argument.", args[0]);
9175 return ret;
9176 }
9177
9178 if (*(args[2]) == 0) {
9179 /* if no list of algorithms is given, it defaults to ALL */
9180 algo = strdup("ALL");
9181 goto add_engine;
9182 }
9183
9184 /* otherwise the expected format is ssl-engine <engine_name> algo <list of algo> */
9185 if (strcmp(args[2], "algo") != 0) {
9186 memprintf(err, "global statement '%s' expects to have algo keyword.", args[0]);
9187 return ret;
9188 }
9189
9190 if (*(args[3]) == 0) {
9191 memprintf(err, "global statement '%s' expects algorithm names as an argument.", args[0]);
9192 return ret;
9193 }
9194 algo = strdup(args[3]);
9195
9196add_engine:
9197 if (ssl_init_single_engine(args[1], algo)==0) {
9198 openssl_engines_initialized++;
9199 ret = 0;
9200 }
9201 free(algo);
9202 return ret;
9203}
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02009204#endif
Grant Zhang872f9c22017-01-21 01:10:18 +00009205
Willy Tarreauf22e9682016-12-21 23:23:19 +01009206/* parse the "ssl-default-bind-ciphers" / "ssl-default-server-ciphers" keywords
9207 * in global section. Returns <0 on alert, >0 on warning, 0 on success.
9208 */
9209static int ssl_parse_global_ciphers(char **args, int section_type, struct proxy *curpx,
9210 struct proxy *defpx, const char *file, int line,
9211 char **err)
9212{
9213 char **target;
9214
Willy Tarreauef934602016-12-22 23:12:01 +01009215 target = (args[0][12] == 'b') ? &global_ssl.listen_default_ciphers : &global_ssl.connect_default_ciphers;
Willy Tarreauf22e9682016-12-21 23:23:19 +01009216
9217 if (too_many_args(1, args, err, NULL))
9218 return -1;
9219
9220 if (*(args[1]) == 0) {
9221 memprintf(err, "global statement '%s' expects a cipher suite as an argument.", args[0]);
9222 return -1;
9223 }
9224
9225 free(*target);
9226 *target = strdup(args[1]);
9227 return 0;
9228}
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009229
Emmanuel Hocdet839af572019-05-14 16:27:35 +02009230#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009231/* parse the "ssl-default-bind-ciphersuites" / "ssl-default-server-ciphersuites" keywords
9232 * in global section. Returns <0 on alert, >0 on warning, 0 on success.
9233 */
9234static int ssl_parse_global_ciphersuites(char **args, int section_type, struct proxy *curpx,
9235 struct proxy *defpx, const char *file, int line,
9236 char **err)
9237{
9238 char **target;
9239
9240 target = (args[0][12] == 'b') ? &global_ssl.listen_default_ciphersuites : &global_ssl.connect_default_ciphersuites;
9241
9242 if (too_many_args(1, args, err, NULL))
9243 return -1;
9244
9245 if (*(args[1]) == 0) {
9246 memprintf(err, "global statement '%s' expects a cipher suite as an argument.", args[0]);
9247 return -1;
9248 }
9249
9250 free(*target);
9251 *target = strdup(args[1]);
9252 return 0;
9253}
9254#endif
Willy Tarreauf22e9682016-12-21 23:23:19 +01009255
Willy Tarreau9ceda382016-12-21 23:13:03 +01009256/* parse various global tune.ssl settings consisting in positive integers.
9257 * Returns <0 on alert, >0 on warning, 0 on success.
9258 */
9259static int ssl_parse_global_int(char **args, int section_type, struct proxy *curpx,
9260 struct proxy *defpx, const char *file, int line,
9261 char **err)
9262{
9263 int *target;
9264
9265 if (strcmp(args[0], "tune.ssl.cachesize") == 0)
9266 target = &global.tune.sslcachesize;
9267 else if (strcmp(args[0], "tune.ssl.maxrecord") == 0)
Willy Tarreauef934602016-12-22 23:12:01 +01009268 target = (int *)&global_ssl.max_record;
Willy Tarreau9ceda382016-12-21 23:13:03 +01009269 else if (strcmp(args[0], "tune.ssl.ssl-ctx-cache-size") == 0)
Willy Tarreauef934602016-12-22 23:12:01 +01009270 target = &global_ssl.ctx_cache;
Willy Tarreau0bea58d2016-12-21 23:17:25 +01009271 else if (strcmp(args[0], "maxsslconn") == 0)
9272 target = &global.maxsslconn;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01009273 else if (strcmp(args[0], "tune.ssl.capture-cipherlist-size") == 0)
9274 target = &global_ssl.capture_cipherlist;
Willy Tarreau9ceda382016-12-21 23:13:03 +01009275 else {
9276 memprintf(err, "'%s' keyword not unhandled (please report this bug).", args[0]);
9277 return -1;
9278 }
9279
9280 if (too_many_args(1, args, err, NULL))
9281 return -1;
9282
9283 if (*(args[1]) == 0) {
9284 memprintf(err, "'%s' expects an integer argument.", args[0]);
9285 return -1;
9286 }
9287
9288 *target = atoi(args[1]);
9289 if (*target < 0) {
9290 memprintf(err, "'%s' expects a positive numeric value.", args[0]);
9291 return -1;
9292 }
9293 return 0;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01009294}
9295
9296static int ssl_parse_global_capture_cipherlist(char **args, int section_type, struct proxy *curpx,
9297 struct proxy *defpx, const char *file, int line,
9298 char **err)
9299{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01009300 int ret;
9301
9302 ret = ssl_parse_global_int(args, section_type, curpx, defpx, file, line, err);
9303 if (ret != 0)
9304 return ret;
9305
Willy Tarreaubafbe012017-11-24 17:34:44 +01009306 if (pool_head_ssl_capture) {
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01009307 memprintf(err, "'%s' is already configured.", args[0]);
9308 return -1;
9309 }
9310
Willy Tarreaubafbe012017-11-24 17:34:44 +01009311 pool_head_ssl_capture = create_pool("ssl-capture", sizeof(struct ssl_capture) + global_ssl.capture_cipherlist, MEM_F_SHARED);
9312 if (!pool_head_ssl_capture) {
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01009313 memprintf(err, "Out of memory error.");
9314 return -1;
9315 }
9316 return 0;
Willy Tarreau9ceda382016-12-21 23:13:03 +01009317}
9318
9319/* parse "ssl.force-private-cache".
9320 * Returns <0 on alert, >0 on warning, 0 on success.
9321 */
9322static int ssl_parse_global_private_cache(char **args, int section_type, struct proxy *curpx,
9323 struct proxy *defpx, const char *file, int line,
9324 char **err)
9325{
9326 if (too_many_args(0, args, err, NULL))
9327 return -1;
9328
Willy Tarreauef934602016-12-22 23:12:01 +01009329 global_ssl.private_cache = 1;
Willy Tarreau9ceda382016-12-21 23:13:03 +01009330 return 0;
9331}
9332
9333/* parse "ssl.lifetime".
9334 * Returns <0 on alert, >0 on warning, 0 on success.
9335 */
9336static int ssl_parse_global_lifetime(char **args, int section_type, struct proxy *curpx,
9337 struct proxy *defpx, const char *file, int line,
9338 char **err)
9339{
9340 const char *res;
9341
9342 if (too_many_args(1, args, err, NULL))
9343 return -1;
9344
9345 if (*(args[1]) == 0) {
9346 memprintf(err, "'%s' expects ssl sessions <lifetime> in seconds as argument.", args[0]);
9347 return -1;
9348 }
9349
Willy Tarreauef934602016-12-22 23:12:01 +01009350 res = parse_time_err(args[1], &global_ssl.life_time, TIME_UNIT_S);
Willy Tarreau9faebe32019-06-07 19:00:37 +02009351 if (res == PARSE_TIME_OVER) {
9352 memprintf(err, "timer overflow in argument '%s' to <%s> (maximum value is 2147483647 s or ~68 years).",
9353 args[1], args[0]);
9354 return -1;
9355 }
9356 else if (res == PARSE_TIME_UNDER) {
9357 memprintf(err, "timer underflow in argument '%s' to <%s> (minimum non-null value is 1 s).",
9358 args[1], args[0]);
9359 return -1;
9360 }
9361 else if (res) {
Willy Tarreau9ceda382016-12-21 23:13:03 +01009362 memprintf(err, "unexpected character '%c' in argument to <%s>.", *res, args[0]);
9363 return -1;
9364 }
9365 return 0;
9366}
9367
9368#ifndef OPENSSL_NO_DH
Willy Tarreau14e36a12016-12-21 23:28:13 +01009369/* parse "ssl-dh-param-file".
9370 * Returns <0 on alert, >0 on warning, 0 on success.
9371 */
9372static int ssl_parse_global_dh_param_file(char **args, int section_type, struct proxy *curpx,
9373 struct proxy *defpx, const char *file, int line,
9374 char **err)
9375{
9376 if (too_many_args(1, args, err, NULL))
9377 return -1;
9378
9379 if (*(args[1]) == 0) {
9380 memprintf(err, "'%s' expects a file path as an argument.", args[0]);
9381 return -1;
9382 }
9383
9384 if (ssl_sock_load_global_dh_param_from_file(args[1])) {
9385 memprintf(err, "'%s': unable to load DH parameters from file <%s>.", args[0], args[1]);
9386 return -1;
9387 }
9388 return 0;
9389}
9390
Willy Tarreau9ceda382016-12-21 23:13:03 +01009391/* parse "ssl.default-dh-param".
9392 * Returns <0 on alert, >0 on warning, 0 on success.
9393 */
9394static int ssl_parse_global_default_dh(char **args, int section_type, struct proxy *curpx,
9395 struct proxy *defpx, const char *file, int line,
9396 char **err)
9397{
9398 if (too_many_args(1, args, err, NULL))
9399 return -1;
9400
9401 if (*(args[1]) == 0) {
9402 memprintf(err, "'%s' expects an integer argument.", args[0]);
9403 return -1;
9404 }
9405
Willy Tarreauef934602016-12-22 23:12:01 +01009406 global_ssl.default_dh_param = atoi(args[1]);
9407 if (global_ssl.default_dh_param < 1024) {
Willy Tarreau9ceda382016-12-21 23:13:03 +01009408 memprintf(err, "'%s' expects a value >= 1024.", args[0]);
9409 return -1;
9410 }
9411 return 0;
9412}
9413#endif
9414
9415
William Lallemand32af2032016-10-29 18:09:35 +02009416/* This function is used with TLS ticket keys management. It permits to browse
9417 * each reference. The variable <getnext> must contain the current node,
9418 * <end> point to the root node.
9419 */
9420#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
9421static inline
9422struct tls_keys_ref *tlskeys_list_get_next(struct tls_keys_ref *getnext, struct list *end)
9423{
9424 struct tls_keys_ref *ref = getnext;
9425
9426 while (1) {
9427
9428 /* Get next list entry. */
9429 ref = LIST_NEXT(&ref->list, struct tls_keys_ref *, list);
9430
9431 /* If the entry is the last of the list, return NULL. */
9432 if (&ref->list == end)
9433 return NULL;
9434
9435 return ref;
9436 }
9437}
9438
9439static inline
9440struct tls_keys_ref *tlskeys_ref_lookup_ref(const char *reference)
9441{
9442 int id;
9443 char *error;
9444
9445 /* If the reference starts by a '#', this is numeric id. */
9446 if (reference[0] == '#') {
9447 /* Try to convert the numeric id. If the conversion fails, the lookup fails. */
9448 id = strtol(reference + 1, &error, 10);
9449 if (*error != '\0')
9450 return NULL;
9451
9452 /* Perform the unique id lookup. */
9453 return tlskeys_ref_lookupid(id);
9454 }
9455
9456 /* Perform the string lookup. */
9457 return tlskeys_ref_lookup(reference);
9458}
9459#endif
9460
9461
9462#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
9463
9464static int cli_io_handler_tlskeys_files(struct appctx *appctx);
9465
9466static inline int cli_io_handler_tlskeys_entries(struct appctx *appctx) {
9467 return cli_io_handler_tlskeys_files(appctx);
9468}
9469
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009470/* dumps all tls keys. Relies on cli.i0 (non-null = only list file names), cli.i1
9471 * (next index to be dumped), and cli.p0 (next key reference).
9472 */
William Lallemand32af2032016-10-29 18:09:35 +02009473static int cli_io_handler_tlskeys_files(struct appctx *appctx) {
9474
9475 struct stream_interface *si = appctx->owner;
9476
9477 switch (appctx->st2) {
9478 case STAT_ST_INIT:
9479 /* Display the column headers. If the message cannot be sent,
Joseph Herlant017b3da2018-11-15 09:07:59 -08009480 * quit the function with returning 0. The function is called
William Lallemand32af2032016-10-29 18:09:35 +02009481 * later and restart at the state "STAT_ST_INIT".
9482 */
9483 chunk_reset(&trash);
9484
9485 if (appctx->io_handler == cli_io_handler_tlskeys_entries)
9486 chunk_appendf(&trash, "# id secret\n");
9487 else
9488 chunk_appendf(&trash, "# id (file)\n");
9489
Willy Tarreau06d80a92017-10-19 14:32:15 +02009490 if (ci_putchk(si_ic(si), &trash) == -1) {
Willy Tarreaudb398432018-11-15 11:08:52 +01009491 si_rx_room_blk(si);
William Lallemand32af2032016-10-29 18:09:35 +02009492 return 0;
9493 }
9494
William Lallemand32af2032016-10-29 18:09:35 +02009495 /* Now, we start the browsing of the references lists.
9496 * Note that the following call to LIST_ELEM return bad pointer. The only
9497 * available field of this pointer is <list>. It is used with the function
9498 * tlskeys_list_get_next() for retruning the first available entry
9499 */
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009500 if (appctx->ctx.cli.p0 == NULL) {
9501 appctx->ctx.cli.p0 = LIST_ELEM(&tlskeys_reference, struct tls_keys_ref *, list);
9502 appctx->ctx.cli.p0 = tlskeys_list_get_next(appctx->ctx.cli.p0, &tlskeys_reference);
William Lallemand32af2032016-10-29 18:09:35 +02009503 }
9504
9505 appctx->st2 = STAT_ST_LIST;
9506 /* fall through */
9507
9508 case STAT_ST_LIST:
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009509 while (appctx->ctx.cli.p0) {
9510 struct tls_keys_ref *ref = appctx->ctx.cli.p0;
William Lallemand32af2032016-10-29 18:09:35 +02009511
9512 chunk_reset(&trash);
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009513 if (appctx->io_handler == cli_io_handler_tlskeys_entries && appctx->ctx.cli.i1 == 0)
William Lallemand32af2032016-10-29 18:09:35 +02009514 chunk_appendf(&trash, "# ");
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009515
9516 if (appctx->ctx.cli.i1 == 0)
9517 chunk_appendf(&trash, "%d (%s)\n", ref->unique_id, ref->filename);
9518
William Lallemand32af2032016-10-29 18:09:35 +02009519 if (appctx->io_handler == cli_io_handler_tlskeys_entries) {
Christopher Faulet16f45c82018-02-16 11:23:49 +01009520 int head;
9521
9522 HA_RWLOCK_RDLOCK(TLSKEYS_REF_LOCK, &ref->lock);
9523 head = ref->tls_ticket_enc_index;
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009524 while (appctx->ctx.cli.i1 < TLS_TICKETS_NO) {
Willy Tarreau83061a82018-07-13 11:56:34 +02009525 struct buffer *t2 = get_trash_chunk();
William Lallemand32af2032016-10-29 18:09:35 +02009526
9527 chunk_reset(t2);
9528 /* should never fail here because we dump only a key in the t2 buffer */
Emeric Brun9e754772019-01-10 17:51:55 +01009529 if (ref->key_size_bits == 128) {
9530 t2->data = a2base64((char *)(ref->tlskeys + (head + 2 + appctx->ctx.cli.i1) % TLS_TICKETS_NO),
9531 sizeof(struct tls_sess_key_128),
9532 t2->area, t2->size);
9533 chunk_appendf(&trash, "%d.%d %s\n", ref->unique_id, appctx->ctx.cli.i1,
9534 t2->area);
9535 }
9536 else if (ref->key_size_bits == 256) {
9537 t2->data = a2base64((char *)(ref->tlskeys + (head + 2 + appctx->ctx.cli.i1) % TLS_TICKETS_NO),
9538 sizeof(struct tls_sess_key_256),
9539 t2->area, t2->size);
9540 chunk_appendf(&trash, "%d.%d %s\n", ref->unique_id, appctx->ctx.cli.i1,
9541 t2->area);
9542 }
9543 else {
9544 /* This case should never happen */
9545 chunk_appendf(&trash, "%d.%d <unknown>\n", ref->unique_id, appctx->ctx.cli.i1);
9546 }
William Lallemand32af2032016-10-29 18:09:35 +02009547
Willy Tarreau06d80a92017-10-19 14:32:15 +02009548 if (ci_putchk(si_ic(si), &trash) == -1) {
William Lallemand32af2032016-10-29 18:09:35 +02009549 /* let's try again later from this stream. We add ourselves into
9550 * this stream's users so that it can remove us upon termination.
9551 */
Christopher Faulet16f45c82018-02-16 11:23:49 +01009552 HA_RWLOCK_RDUNLOCK(TLSKEYS_REF_LOCK, &ref->lock);
Willy Tarreaudb398432018-11-15 11:08:52 +01009553 si_rx_room_blk(si);
William Lallemand32af2032016-10-29 18:09:35 +02009554 return 0;
9555 }
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009556 appctx->ctx.cli.i1++;
William Lallemand32af2032016-10-29 18:09:35 +02009557 }
Christopher Faulet16f45c82018-02-16 11:23:49 +01009558 HA_RWLOCK_RDUNLOCK(TLSKEYS_REF_LOCK, &ref->lock);
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009559 appctx->ctx.cli.i1 = 0;
William Lallemand32af2032016-10-29 18:09:35 +02009560 }
Willy Tarreau06d80a92017-10-19 14:32:15 +02009561 if (ci_putchk(si_ic(si), &trash) == -1) {
William Lallemand32af2032016-10-29 18:09:35 +02009562 /* let's try again later from this stream. We add ourselves into
9563 * this stream's users so that it can remove us upon termination.
9564 */
Willy Tarreaudb398432018-11-15 11:08:52 +01009565 si_rx_room_blk(si);
William Lallemand32af2032016-10-29 18:09:35 +02009566 return 0;
9567 }
9568
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009569 if (appctx->ctx.cli.i0 == 0) /* don't display everything if not necessary */
William Lallemand32af2032016-10-29 18:09:35 +02009570 break;
9571
9572 /* get next list entry and check the end of the list */
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009573 appctx->ctx.cli.p0 = tlskeys_list_get_next(appctx->ctx.cli.p0, &tlskeys_reference);
William Lallemand32af2032016-10-29 18:09:35 +02009574 }
9575
9576 appctx->st2 = STAT_ST_FIN;
9577 /* fall through */
9578
9579 default:
9580 appctx->st2 = STAT_ST_FIN;
9581 return 1;
9582 }
9583 return 0;
9584}
9585
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009586/* sets cli.i0 to non-zero if only file lists should be dumped */
Aurélien Nephtaliabbf6072018-04-18 13:26:46 +02009587static int cli_parse_show_tlskeys(char **args, char *payload, struct appctx *appctx, void *private)
William Lallemand32af2032016-10-29 18:09:35 +02009588{
William Lallemand32af2032016-10-29 18:09:35 +02009589 /* no parameter, shows only file list */
9590 if (!*args[2]) {
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009591 appctx->ctx.cli.i0 = 1;
William Lallemand32af2032016-10-29 18:09:35 +02009592 appctx->io_handler = cli_io_handler_tlskeys_files;
Willy Tarreau3067bfa2016-12-05 14:50:15 +01009593 return 0;
William Lallemand32af2032016-10-29 18:09:35 +02009594 }
9595
9596 if (args[2][0] == '*') {
9597 /* list every TLS ticket keys */
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009598 appctx->ctx.cli.i0 = 1;
William Lallemand32af2032016-10-29 18:09:35 +02009599 } else {
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009600 appctx->ctx.cli.p0 = tlskeys_ref_lookup_ref(args[2]);
Willy Tarreau9d008692019-08-09 11:21:01 +02009601 if (!appctx->ctx.cli.p0)
9602 return cli_err(appctx, "'show tls-keys' unable to locate referenced filename\n");
William Lallemand32af2032016-10-29 18:09:35 +02009603 }
William Lallemand32af2032016-10-29 18:09:35 +02009604 appctx->io_handler = cli_io_handler_tlskeys_entries;
Willy Tarreau3067bfa2016-12-05 14:50:15 +01009605 return 0;
William Lallemand32af2032016-10-29 18:09:35 +02009606}
9607
Aurélien Nephtaliabbf6072018-04-18 13:26:46 +02009608static int cli_parse_set_tlskeys(char **args, char *payload, struct appctx *appctx, void *private)
William Lallemand32af2032016-10-29 18:09:35 +02009609{
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009610 struct tls_keys_ref *ref;
Willy Tarreau1c913e42018-08-22 05:26:57 +02009611 int ret;
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009612
William Lallemand32af2032016-10-29 18:09:35 +02009613 /* Expect two parameters: the filename and the new new TLS key in encoding */
Willy Tarreau9d008692019-08-09 11:21:01 +02009614 if (!*args[3] || !*args[4])
9615 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 +02009616
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009617 ref = tlskeys_ref_lookup_ref(args[3]);
Willy Tarreau9d008692019-08-09 11:21:01 +02009618 if (!ref)
9619 return cli_err(appctx, "'set ssl tls-key' unable to locate referenced filename\n");
William Lallemand32af2032016-10-29 18:09:35 +02009620
Willy Tarreau1c913e42018-08-22 05:26:57 +02009621 ret = base64dec(args[4], strlen(args[4]), trash.area, trash.size);
Willy Tarreau9d008692019-08-09 11:21:01 +02009622 if (ret < 0)
9623 return cli_err(appctx, "'set ssl tls-key' received invalid base64 encoded TLS key.\n");
Emeric Brun9e754772019-01-10 17:51:55 +01009624
Willy Tarreau1c913e42018-08-22 05:26:57 +02009625 trash.data = ret;
Willy Tarreau9d008692019-08-09 11:21:01 +02009626 if (ssl_sock_update_tlskey_ref(ref, &trash) < 0)
9627 return cli_err(appctx, "'set ssl tls-key' received a key of wrong size.\n");
William Lallemand32af2032016-10-29 18:09:35 +02009628
Willy Tarreau9d008692019-08-09 11:21:01 +02009629 return cli_msg(appctx, LOG_INFO, "TLS ticket key updated!\n");
William Lallemand32af2032016-10-29 18:09:35 +02009630}
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01009631#endif
William Lallemand32af2032016-10-29 18:09:35 +02009632
William Lallemand150bfa82019-09-19 17:12:49 +02009633static int cli_parse_set_cert(char **args, char *payload, struct appctx *appctx, void *private)
9634{
9635 struct ckch_store *ckchs = NULL;
9636 struct cert_key_and_chain *ckch;
9637 struct list tmp_ckchi_list;
9638 BIO *mem;
9639 char *err = NULL;
William Lallemand963b2e72019-10-14 11:38:36 +02009640 int i;
William Lallemand150bfa82019-09-19 17:12:49 +02009641 int found = 0;
9642 int bundle = -1;
Emeric Brunf69ed1d2019-10-17 11:56:56 +02009643 int errcode = 0;
William Lallemand150bfa82019-09-19 17:12:49 +02009644
9645 if (!*args[3] || !payload)
9646 return cli_err(appctx, "'set ssl cert expects a filename and a certificat as a payload\n");
9647
9648 /* The operations on the CKCH architecture are locked so we can
9649 * manipulate ckch_store and ckch_inst */
9650 if (HA_SPIN_TRYLOCK(CKCH_LOCK, &ckch_lock))
9651 return cli_err(appctx, "Can't update the certificate!\nOperations on certificates are currently locked!\n");
9652
9653 LIST_INIT(&tmp_ckchi_list);
9654
9655 mem = BIO_new_mem_buf(payload, -1);
9656 if (!mem) {
9657 memprintf(&err, "%sCan't allocate memory\n", err ? err : "");
Emeric Brunf69ed1d2019-10-17 11:56:56 +02009658 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemand150bfa82019-09-19 17:12:49 +02009659 goto end;
9660 }
9661
9662 /* do 2 iterations, first one with a non-bundle entry, second one with a bundle entry */
9663 for (i = 0; i < 2; i++) {
9664
9665 if ((ckchs = ckchs_lookup(args[3])) != NULL) {
9666 struct ckch_inst *ckchi, *ckchis;
9667
9668 /* only the bundle name is in the tree and you should never update a bundle name, only a filename */
9669 if (bundle < 0 && ckchs->multi) {
9670 memprintf(&err, "%s%s is a multi-cert bundle. Try updating %s.{dsa,rsa,ecdsa}\n",
9671 err ? err : "", args[3], args[3]);
Emeric Brunf69ed1d2019-10-17 11:56:56 +02009672 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemand150bfa82019-09-19 17:12:49 +02009673 goto end;
9674 }
9675
9676 if (bundle < 0)
9677 ckch = ckchs->ckch;
9678 else
9679 ckch = &ckchs->ckch[bundle];
9680
9681 if (ckchs->filters) {
9682 memprintf(&err, "%sCertificates used in crt-list with filters are not supported!\n",
9683 err ? err : "");
Emeric Brunf69ed1d2019-10-17 11:56:56 +02009684 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemand150bfa82019-09-19 17:12:49 +02009685 goto end;
9686 }
9687
9688 found = 1;
9689
9690 if (ssl_sock_load_crt_file_into_ckch(args[3], mem, ckch, &err) != 0) {
Emeric Brunf69ed1d2019-10-17 11:56:56 +02009691 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemand150bfa82019-09-19 17:12:49 +02009692 goto end;
9693 }
9694
9695 /* walk through ckch_inst and creates new ckch_inst using the updated ckch */
9696 list_for_each_entry(ckchi, &ckchs->ckch_inst, by_ckchs) {
9697 struct ckch_inst *new_inst;
9698
9699 if (ckchs->multi)
Emeric Brun054563d2019-10-17 13:16:58 +02009700 errcode |= ckch_inst_new_load_multi_store(args[3], ckchs, ckchi->bind_conf, ckchi->ssl_conf, NULL, 0, &new_inst, &err);
William Lallemand150bfa82019-09-19 17:12:49 +02009701 else
Emeric Brun054563d2019-10-17 13:16:58 +02009702 errcode |= ckch_inst_new_load_store(args[3], ckchs, ckchi->bind_conf, ckchi->ssl_conf, NULL, 0, &new_inst, &err);
William Lallemand150bfa82019-09-19 17:12:49 +02009703
Emeric Brun054563d2019-10-17 13:16:58 +02009704 if (errcode & ERR_CODE)
William Lallemand150bfa82019-09-19 17:12:49 +02009705 goto end;
William Lallemand150bfa82019-09-19 17:12:49 +02009706
9707 /* link temporary the new ckch_inst */
9708 LIST_ADDQ(&tmp_ckchi_list, &new_inst->by_ckchs);
9709 }
9710
9711 /* once every allocation is done, delete the old sni_ctx & the old ckch_insts */
9712 list_for_each_entry_safe(ckchi, ckchis, &ckchs->ckch_inst, by_ckchs) {
9713 struct sni_ctx *sc0, *sc0s;
9714
9715 HA_RWLOCK_WRLOCK(CKCH_LOCK, &ckchi->bind_conf->sni_lock);
9716 list_for_each_entry_safe(sc0, sc0s, &ckchi->sni_ctx, by_ckch_inst) {
9717 ebmb_delete(&sc0->name);
9718 LIST_DEL(&sc0->by_ckch_inst);
9719 free(sc0);
9720 }
9721 HA_RWLOCK_WRUNLOCK(CKCH_LOCK, &ckchi->bind_conf->sni_lock);
9722 LIST_DEL(&ckchi->by_ckchs);
9723 free(ckchi);
9724 ckchi = NULL;
9725 }
9726 /* insert every new ckch instance in the actual list and insert the sni_ctx in the trees */
9727 list_for_each_entry_safe(ckchi, ckchis, &tmp_ckchi_list, by_ckchs) {
9728 LIST_DEL(&ckchi->by_ckchs);
9729 LIST_ADD(&ckchs->ckch_inst, &ckchi->by_ckchs);
9730 HA_RWLOCK_WRLOCK(CKCH_LOCK, &ckchi->bind_conf->sni_lock);
9731 ssl_sock_load_cert_sni(ckchi, ckchi->bind_conf);
9732 HA_RWLOCK_WRUNLOCK(CKCH_LOCK, &ckchi->bind_conf->sni_lock);
9733 }
9734 }
William Lallemand963b2e72019-10-14 11:38:36 +02009735#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
9736 {
9737 char *end = NULL;
9738 int j;
William Lallemand150bfa82019-09-19 17:12:49 +02009739
William Lallemand963b2e72019-10-14 11:38:36 +02009740 /* check if it was also used as a bundle by removing the
9741 * .dsa/.rsa/.ecdsa at the end of the filename */
9742 if (bundle >= 0)
William Lallemand150bfa82019-09-19 17:12:49 +02009743 break;
William Lallemand963b2e72019-10-14 11:38:36 +02009744 end = strrchr(args[3], '.');
9745 for (j = 0; *end && j < SSL_SOCK_NUM_KEYTYPES; j++) {
9746 if (!strcmp(end + 1, SSL_SOCK_KEYTYPE_NAMES[j])) {
9747 bundle = j; /* keep the type of certificate so we insert it at the right place */
9748 *end = '\0'; /* it's a bundle let's end the string*/
9749 break;
9750 }
William Lallemand150bfa82019-09-19 17:12:49 +02009751 }
9752 }
William Lallemand963b2e72019-10-14 11:38:36 +02009753#else
9754 /* bundles are not supported here, so we don't need to lookup again */
9755 break;
9756#endif
William Lallemand150bfa82019-09-19 17:12:49 +02009757 }
9758
9759 if (!found) {
William Lallemand150bfa82019-09-19 17:12:49 +02009760 memprintf(&err, "%sCan't replace a certificate name which is not referenced by the configuration!\n",
9761 err ? err : "");
Emeric Brunf69ed1d2019-10-17 11:56:56 +02009762 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemand150bfa82019-09-19 17:12:49 +02009763 }
9764
9765end:
9766
9767 HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
9768
9769 BIO_free(mem);
9770
Emeric Brunf69ed1d2019-10-17 11:56:56 +02009771 if (errcode & ERR_CODE) {
William Lallemand150bfa82019-09-19 17:12:49 +02009772 struct ckch_inst *ckchi, *ckchis;
9773 /* if the allocation failed, we need to free everything from the temporary list */
9774 list_for_each_entry_safe(ckchi, ckchis, &tmp_ckchi_list, by_ckchs) {
9775 struct sni_ctx *sc0, *sc0s;
9776
9777 list_for_each_entry_safe(sc0, sc0s, &ckchi->sni_ctx, by_ckch_inst) {
9778 if (sc0->order == 0) /* we only free if it's the first inserted */
9779 SSL_CTX_free(sc0->ctx);
9780 LIST_DEL(&sc0->by_ckch_inst);
9781 free(sc0);
9782 }
9783 LIST_DEL(&ckchi->by_ckchs);
9784 free(ckchi);
9785 }
9786 return cli_dynerr(appctx, memprintf(&err, "%sCan't update the certificate!\n", err ? err : ""));
Emeric Brunf69ed1d2019-10-17 11:56:56 +02009787 }
9788 else if (errcode & ERR_WARN) {
9789 return cli_dynmsg(appctx, LOG_WARNING, memprintf(&err, "%sCertificate updated!\n", err ? err : ""));
9790 }
9791 else {
William Lallemand150bfa82019-09-19 17:12:49 +02009792 return cli_dynmsg(appctx, LOG_INFO, memprintf(&err, "Certificate updated!"));
9793 }
9794}
9795
Aurélien Nephtaliabbf6072018-04-18 13:26:46 +02009796static int cli_parse_set_ocspresponse(char **args, char *payload, struct appctx *appctx, void *private)
William Lallemand32af2032016-10-29 18:09:35 +02009797{
9798#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
9799 char *err = NULL;
Willy Tarreau1c913e42018-08-22 05:26:57 +02009800 int i, j, ret;
Aurélien Nephtali1e0867c2018-04-18 14:04:58 +02009801
9802 if (!payload)
9803 payload = args[3];
William Lallemand32af2032016-10-29 18:09:35 +02009804
9805 /* Expect one parameter: the new response in base64 encoding */
Willy Tarreau9d008692019-08-09 11:21:01 +02009806 if (!*payload)
9807 return cli_err(appctx, "'set ssl ocsp-response' expects response in base64 encoding.\n");
Aurélien Nephtali1e0867c2018-04-18 14:04:58 +02009808
9809 /* remove \r and \n from the payload */
9810 for (i = 0, j = 0; payload[i]; i++) {
9811 if (payload[i] == '\r' || payload[i] == '\n')
9812 continue;
9813 payload[j++] = payload[i];
9814 }
9815 payload[j] = 0;
William Lallemand32af2032016-10-29 18:09:35 +02009816
Willy Tarreau1c913e42018-08-22 05:26:57 +02009817 ret = base64dec(payload, j, trash.area, trash.size);
Willy Tarreau9d008692019-08-09 11:21:01 +02009818 if (ret < 0)
9819 return cli_err(appctx, "'set ssl ocsp-response' received invalid base64 encoded response.\n");
William Lallemand32af2032016-10-29 18:09:35 +02009820
Willy Tarreau1c913e42018-08-22 05:26:57 +02009821 trash.data = ret;
William Lallemand32af2032016-10-29 18:09:35 +02009822 if (ssl_sock_update_ocsp_response(&trash, &err)) {
Willy Tarreau9d008692019-08-09 11:21:01 +02009823 if (err)
9824 return cli_dynerr(appctx, memprintf(&err, "%s.\n", err));
9825 else
9826 return cli_err(appctx, "Failed to update OCSP response.\n");
William Lallemand32af2032016-10-29 18:09:35 +02009827 }
Willy Tarreau9d008692019-08-09 11:21:01 +02009828
9829 return cli_msg(appctx, LOG_INFO, "OCSP Response updated!\n");
William Lallemand32af2032016-10-29 18:09:35 +02009830#else
Willy Tarreau9d008692019-08-09 11:21:01 +02009831 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 +02009832#endif
9833
Nenad Merdanovicc31499d2019-03-23 11:00:32 +01009834}
9835
Willy Tarreau86a394e2019-05-09 14:15:32 +02009836#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000100fL)
Nenad Merdanovicc31499d2019-03-23 11:00:32 +01009837static inline int sample_conv_var2smp_str(const struct arg *arg, struct sample *smp)
9838{
9839 switch (arg->type) {
9840 case ARGT_STR:
9841 smp->data.type = SMP_T_STR;
9842 smp->data.u.str = arg->data.str;
9843 return 1;
9844 case ARGT_VAR:
9845 if (!vars_get_by_desc(&arg->data.var, smp))
9846 return 0;
9847 if (!sample_casts[smp->data.type][SMP_T_STR])
9848 return 0;
9849 if (!sample_casts[smp->data.type][SMP_T_STR](smp))
9850 return 0;
9851 return 1;
9852 default:
9853 return 0;
9854 }
9855}
9856
9857static int check_aes_gcm(struct arg *args, struct sample_conv *conv,
9858 const char *file, int line, char **err)
9859{
9860 switch(args[0].data.sint) {
9861 case 128:
9862 case 192:
9863 case 256:
9864 break;
9865 default:
9866 memprintf(err, "key size must be 128, 192 or 256 (bits).");
9867 return 0;
9868 }
9869 /* Try to decode a variable. */
9870 vars_check_arg(&args[1], NULL);
9871 vars_check_arg(&args[2], NULL);
9872 vars_check_arg(&args[3], NULL);
9873 return 1;
9874}
9875
9876/* Arguements: AES size in bits, nonce, key, tag. The last three arguments are base64 encoded */
9877static int sample_conv_aes_gcm_dec(const struct arg *arg_p, struct sample *smp, void *private)
9878{
9879 struct sample nonce, key, aead_tag;
9880 struct buffer *smp_trash, *smp_trash_alloc;
9881 EVP_CIPHER_CTX *ctx;
9882 int dec_size, ret;
9883
9884 smp_set_owner(&nonce, smp->px, smp->sess, smp->strm, smp->opt);
9885 if (!sample_conv_var2smp_str(&arg_p[1], &nonce))
9886 return 0;
9887
9888 smp_set_owner(&key, smp->px, smp->sess, smp->strm, smp->opt);
9889 if (!sample_conv_var2smp_str(&arg_p[2], &key))
9890 return 0;
9891
9892 smp_set_owner(&aead_tag, smp->px, smp->sess, smp->strm, smp->opt);
9893 if (!sample_conv_var2smp_str(&arg_p[3], &aead_tag))
9894 return 0;
9895
9896 smp_trash = get_trash_chunk();
9897 smp_trash_alloc = alloc_trash_chunk();
9898 if (!smp_trash_alloc)
9899 return 0;
9900
9901 ctx = EVP_CIPHER_CTX_new();
9902
9903 if (!ctx)
9904 goto err;
9905
9906 dec_size = base64dec(nonce.data.u.str.area, nonce.data.u.str.data, smp_trash->area, smp_trash->size);
9907 if (dec_size < 0)
9908 goto err;
9909 smp_trash->data = dec_size;
9910
9911 /* Set cipher type and mode */
9912 switch(arg_p[0].data.sint) {
9913 case 128:
9914 EVP_DecryptInit_ex(ctx, EVP_aes_128_gcm(), NULL, NULL, NULL);
9915 break;
9916 case 192:
9917 EVP_DecryptInit_ex(ctx, EVP_aes_192_gcm(), NULL, NULL, NULL);
9918 break;
9919 case 256:
9920 EVP_DecryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL);
9921 break;
9922 }
9923
9924 EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, smp_trash->data, NULL);
9925
9926 /* Initialise IV */
9927 if(!EVP_DecryptInit_ex(ctx, NULL, NULL, NULL, (unsigned char *) smp_trash->area))
9928 goto err;
9929
9930 dec_size = base64dec(key.data.u.str.area, key.data.u.str.data, smp_trash->area, smp_trash->size);
9931 if (dec_size < 0)
9932 goto err;
9933 smp_trash->data = dec_size;
9934
9935 /* Initialise key */
9936 if (!EVP_DecryptInit_ex(ctx, NULL, NULL, (unsigned char *) smp_trash->area, NULL))
9937 goto err;
9938
9939 if (!EVP_DecryptUpdate(ctx, (unsigned char *) smp_trash->area, (int *) &smp_trash->data,
9940 (unsigned char *) smp->data.u.str.area, (int) smp->data.u.str.data))
9941 goto err;
9942
9943 dec_size = base64dec(aead_tag.data.u.str.area, aead_tag.data.u.str.data, smp_trash_alloc->area, smp_trash_alloc->size);
9944 if (dec_size < 0)
9945 goto err;
9946 smp_trash_alloc->data = dec_size;
9947 dec_size = smp_trash->data;
9948
9949 EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, smp_trash_alloc->data, (void *) smp_trash_alloc->area);
9950 ret = EVP_DecryptFinal_ex(ctx, (unsigned char *) smp_trash->area + smp_trash->data, (int *) &smp_trash->data);
9951
9952 if (ret <= 0)
9953 goto err;
9954
9955 smp->data.u.str.data = dec_size + smp_trash->data;
9956 smp->data.u.str.area = smp_trash->area;
9957 smp->data.type = SMP_T_BIN;
9958 smp->flags &= ~SMP_F_CONST;
9959 free_trash_chunk(smp_trash_alloc);
9960 return 1;
9961
9962err:
9963 free_trash_chunk(smp_trash_alloc);
9964 return 0;
William Lallemand32af2032016-10-29 18:09:35 +02009965}
Nenad Merdanovicc31499d2019-03-23 11:00:32 +01009966# endif
William Lallemand32af2032016-10-29 18:09:35 +02009967
9968/* register cli keywords */
9969static struct cli_kw_list cli_kws = {{ },{
9970#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
9971 { { "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 +02009972 { { "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 +02009973#endif
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01009974 { { "set", "ssl", "ocsp-response", NULL }, NULL, cli_parse_set_ocspresponse, NULL },
William Lallemand150bfa82019-09-19 17:12:49 +02009975 { { "set", "ssl", "cert", NULL }, "set ssl cert <certfile> <payload> : replace a certificate file", cli_parse_set_cert, NULL },
William Lallemand32af2032016-10-29 18:09:35 +02009976 { { NULL }, NULL, NULL, NULL }
9977}};
9978
Willy Tarreau0108d902018-11-25 19:14:37 +01009979INITCALL1(STG_REGISTER, cli_register_kw, &cli_kws);
William Lallemand32af2032016-10-29 18:09:35 +02009980
Willy Tarreau7875d092012-09-10 08:20:03 +02009981/* Note: must not be declared <const> as its list will be overwritten.
9982 * Please take care of keeping this list alphabetically sorted.
9983 */
Willy Tarreaudc13c112013-06-21 23:16:39 +02009984static struct sample_fetch_kw_list sample_fetch_keywords = {ILH, {
Emeric Brun645ae792014-04-30 14:21:06 +02009985 { "ssl_bc", smp_fetch_ssl_fc, 0, NULL, SMP_T_BOOL, SMP_USE_L5SRV },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02009986 { "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 +01009987#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Jérôme Magnine064a802018-12-03 22:21:04 +01009988 { "ssl_bc_alpn", smp_fetch_ssl_fc_alpn, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
Olivier Houchard6b77f492018-11-22 18:18:29 +01009989#endif
Emeric Brun645ae792014-04-30 14:21:06 +02009990 { "ssl_bc_cipher", smp_fetch_ssl_fc_cipher, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
Olivier Houchard6b77f492018-11-22 18:18:29 +01009991#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
9992 { "ssl_bc_npn", smp_fetch_ssl_fc_npn, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
9993#endif
Emeric Brun74f7ffa2018-02-19 16:14:12 +01009994 { "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 +02009995 { "ssl_bc_protocol", smp_fetch_ssl_fc_protocol, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
Emeric Brunb73a9b02014-04-30 18:49:19 +02009996 { "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 +02009997 { "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 +02009998#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
Emeric Brun645ae792014-04-30 14:21:06 +02009999 { "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 -040010000#endif
Emmanuel Hocdet839af572019-05-14 16:27:35 +020010001#if HA_OPENSSL_VERSION_NUMBER >= 0x10100000L
Patrick Hemmer65674662019-06-04 08:13:03 -040010002 { "ssl_bc_client_random", smp_fetch_ssl_fc_random, 0, NULL, SMP_T_BIN, SMP_USE_L5SRV },
10003 { "ssl_bc_server_random", smp_fetch_ssl_fc_random, 0, NULL, SMP_T_BIN, SMP_USE_L5SRV },
Patrick Hemmere0275472018-04-28 19:15:51 -040010004 { "ssl_bc_session_key", smp_fetch_ssl_fc_session_key, 0, NULL, SMP_T_BIN, SMP_USE_L5SRV },
10005#endif
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +020010006 { "ssl_c_ca_err", smp_fetch_ssl_c_ca_err, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
10007 { "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 +010010008 { "ssl_c_der", smp_fetch_ssl_x_der, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +020010009 { "ssl_c_err", smp_fetch_ssl_c_err, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Emeric Brunba841a12014-04-30 17:05:08 +020010010 { "ssl_c_i_dn", smp_fetch_ssl_x_i_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
10011 { "ssl_c_key_alg", smp_fetch_ssl_x_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
10012 { "ssl_c_notafter", smp_fetch_ssl_x_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
10013 { "ssl_c_notbefore", smp_fetch_ssl_x_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
10014 { "ssl_c_sig_alg", smp_fetch_ssl_x_sig_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
10015 { "ssl_c_s_dn", smp_fetch_ssl_x_s_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
10016 { "ssl_c_serial", smp_fetch_ssl_x_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
10017 { "ssl_c_sha1", smp_fetch_ssl_x_sha1, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +010010018 { "ssl_c_used", smp_fetch_ssl_c_used, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +020010019 { "ssl_c_verify", smp_fetch_ssl_c_verify, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
10020 { "ssl_c_version", smp_fetch_ssl_x_version, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Emeric Brun43e79582014-10-29 19:03:26 +010010021 { "ssl_f_der", smp_fetch_ssl_x_der, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Emeric Brunba841a12014-04-30 17:05:08 +020010022 { "ssl_f_i_dn", smp_fetch_ssl_x_i_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
10023 { "ssl_f_key_alg", smp_fetch_ssl_x_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
10024 { "ssl_f_notafter", smp_fetch_ssl_x_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
10025 { "ssl_f_notbefore", smp_fetch_ssl_x_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
10026 { "ssl_f_sig_alg", smp_fetch_ssl_x_sig_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
10027 { "ssl_f_s_dn", smp_fetch_ssl_x_s_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
10028 { "ssl_f_serial", smp_fetch_ssl_x_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Emeric Brun55f4fa82014-04-30 17:11:25 +020010029 { "ssl_f_sha1", smp_fetch_ssl_x_sha1, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +020010030 { "ssl_f_version", smp_fetch_ssl_x_version, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +010010031 { "ssl_fc", smp_fetch_ssl_fc, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +020010032 { "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 +010010033 { "ssl_fc_cipher", smp_fetch_ssl_fc_cipher, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +010010034 { "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 +020010035 { "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 +010010036 { "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 +020010037 { "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 +010010038#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +010010039 { "ssl_fc_npn", smp_fetch_ssl_fc_npn, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreaua33c6542012-10-15 13:19:06 +020010040#endif
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +010010041#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +010010042 { "ssl_fc_alpn", smp_fetch_ssl_fc_alpn, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreauab861d32013-04-02 02:30:41 +020010043#endif
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +010010044 { "ssl_fc_protocol", smp_fetch_ssl_fc_protocol, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreau9a1ab082019-05-09 13:26:41 +020010045#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
Emeric Brunb73a9b02014-04-30 18:49:19 +020010046 { "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 -040010047#endif
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +020010048 { "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 +020010049#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +010010050 { "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 -040010051#endif
Emmanuel Hocdet839af572019-05-14 16:27:35 +020010052#if HA_OPENSSL_VERSION_NUMBER >= 0x10100000L
Patrick Hemmer65674662019-06-04 08:13:03 -040010053 { "ssl_fc_client_random", smp_fetch_ssl_fc_random, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
10054 { "ssl_fc_server_random", smp_fetch_ssl_fc_random, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Patrick Hemmere0275472018-04-28 19:15:51 -040010055 { "ssl_fc_session_key", smp_fetch_ssl_fc_session_key, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
10056#endif
Patrick Hemmer41966772018-04-28 19:15:48 -040010057#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +010010058 { "ssl_fc_sni", smp_fetch_ssl_fc_sni, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Patrick Hemmer41966772018-04-28 19:15:48 -040010059#endif
Thierry FOURNIER5bf77322017-02-25 12:45:22 +010010060 { "ssl_fc_cipherlist_bin", smp_fetch_ssl_fc_cl_bin, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
10061 { "ssl_fc_cipherlist_hex", smp_fetch_ssl_fc_cl_hex, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
10062 { "ssl_fc_cipherlist_str", smp_fetch_ssl_fc_cl_str, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
10063 { "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 +020010064 { NULL, NULL, 0, 0, 0 },
10065}};
10066
Willy Tarreau0108d902018-11-25 19:14:37 +010010067INITCALL1(STG_REGISTER, sample_register_fetches, &sample_fetch_keywords);
10068
Willy Tarreau7875d092012-09-10 08:20:03 +020010069/* Note: must not be declared <const> as its list will be overwritten.
10070 * Please take care of keeping this list alphabetically sorted.
10071 */
Willy Tarreaudc13c112013-06-21 23:16:39 +020010072static struct acl_kw_list acl_kws = {ILH, {
Thierry FOURNIERc5a4e982014-03-05 16:07:08 +010010073 { "ssl_fc_sni_end", "ssl_fc_sni", PAT_MATCH_END },
10074 { "ssl_fc_sni_reg", "ssl_fc_sni", PAT_MATCH_REG },
Willy Tarreau8ed669b2013-01-11 15:49:37 +010010075 { /* END */ },
Willy Tarreau7875d092012-09-10 08:20:03 +020010076}};
10077
Willy Tarreau0108d902018-11-25 19:14:37 +010010078INITCALL1(STG_REGISTER, acl_register_keywords, &acl_kws);
10079
Willy Tarreau79eeafa2012-09-14 07:53:05 +020010080/* Note: must not be declared <const> as its list will be overwritten.
10081 * Please take care of keeping this list alphabetically sorted, doing so helps
10082 * all code contributors.
10083 * Optional keywords are also declared with a NULL ->parse() function so that
10084 * the config parser can report an appropriate error when a known keyword was
10085 * not enabled.
10086 */
Emmanuel Hocdet98263292016-12-29 18:26:15 +010010087static struct ssl_bind_kw ssl_bind_kws[] = {
Olivier Houchardc2aae742017-09-22 18:26:28 +020010088 { "allow-0rtt", ssl_bind_parse_allow_0rtt, 0 }, /* allow 0-RTT */
Emmanuel Hocdet98263292016-12-29 18:26:15 +010010089 { "alpn", ssl_bind_parse_alpn, 1 }, /* set ALPN supported protocols */
10090 { "ca-file", ssl_bind_parse_ca_file, 1 }, /* set CAfile to process verify on client cert */
10091 { "ciphers", ssl_bind_parse_ciphers, 1 }, /* set SSL cipher suite */
Emmanuel Hocdet839af572019-05-14 16:27:35 +020010092#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +020010093 { "ciphersuites", ssl_bind_parse_ciphersuites, 1 }, /* set TLS 1.3 cipher suite */
10094#endif
Emmanuel Hocdet98263292016-12-29 18:26:15 +010010095 { "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 +010010096 { "curves", ssl_bind_parse_curves, 1 }, /* set SSL curve suite */
Emmanuel Hocdet98263292016-12-29 18:26:15 +010010097 { "ecdhe", ssl_bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +020010098 { "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 +010010099 { "npn", ssl_bind_parse_npn, 1 }, /* set NPN supported protocols */
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +020010100 { "ssl-min-ver", ssl_bind_parse_tls_method_minmax,1 }, /* minimum version */
10101 { "ssl-max-ver", ssl_bind_parse_tls_method_minmax,1 }, /* maximum version */
Emmanuel Hocdet98263292016-12-29 18:26:15 +010010102 { "verify", ssl_bind_parse_verify, 1 }, /* set SSL verify method */
10103 { NULL, NULL, 0 },
10104};
10105
Willy Tarreau0108d902018-11-25 19:14:37 +010010106/* no initcall for ssl_bind_kws, these ones are parsed in the parser loop */
10107
Willy Tarreau51fb7652012-09-18 18:24:39 +020010108static struct bind_kw_list bind_kws = { "SSL", { }, {
Olivier Houchardc2aae742017-09-22 18:26:28 +020010109 { "allow-0rtt", bind_parse_allow_0rtt, 0 }, /* Allow 0RTT */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +020010110 { "alpn", bind_parse_alpn, 1 }, /* set ALPN supported protocols */
10111 { "ca-file", bind_parse_ca_file, 1 }, /* set CAfile to process verify on client cert */
10112 { "ca-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ignore on verify depth > 0 */
10113 { "ca-sign-file", bind_parse_ca_sign_file, 1 }, /* set CAFile used to generate and sign server certs */
10114 { "ca-sign-pass", bind_parse_ca_sign_pass, 1 }, /* set CAKey passphrase */
10115 { "ciphers", bind_parse_ciphers, 1 }, /* set SSL cipher suite */
Emmanuel Hocdet839af572019-05-14 16:27:35 +020010116#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +020010117 { "ciphersuites", bind_parse_ciphersuites, 1 }, /* set TLS 1.3 cipher suite */
10118#endif
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +020010119 { "crl-file", bind_parse_crl_file, 1 }, /* set certificat revocation list file use on client cert verify */
10120 { "crt", bind_parse_crt, 1 }, /* load SSL certificates from this location */
10121 { "crt-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ingore on verify depth == 0 */
10122 { "crt-list", bind_parse_crt_list, 1 }, /* load a list of crt from this location */
10123 { "curves", bind_parse_curves, 1 }, /* set SSL curve suite */
10124 { "ecdhe", bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
10125 { "force-sslv3", bind_parse_tls_method_options, 0 }, /* force SSLv3 */
10126 { "force-tlsv10", bind_parse_tls_method_options, 0 }, /* force TLSv10 */
10127 { "force-tlsv11", bind_parse_tls_method_options, 0 }, /* force TLSv11 */
10128 { "force-tlsv12", bind_parse_tls_method_options, 0 }, /* force TLSv12 */
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +020010129 { "force-tlsv13", bind_parse_tls_method_options, 0 }, /* force TLSv13 */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +020010130 { "generate-certificates", bind_parse_generate_certs, 0 }, /* enable the server certificates generation */
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +020010131 { "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 +020010132 { "no-sslv3", bind_parse_tls_method_options, 0 }, /* disable SSLv3 */
10133 { "no-tlsv10", bind_parse_tls_method_options, 0 }, /* disable TLSv10 */
10134 { "no-tlsv11", bind_parse_tls_method_options, 0 }, /* disable TLSv11 */
10135 { "no-tlsv12", bind_parse_tls_method_options, 0 }, /* disable TLSv12 */
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +020010136 { "no-tlsv13", bind_parse_tls_method_options, 0 }, /* disable TLSv13 */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +020010137 { "no-tls-tickets", bind_parse_no_tls_tickets, 0 }, /* disable session resumption tickets */
10138 { "ssl", bind_parse_ssl, 0 }, /* enable SSL processing */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +020010139 { "ssl-min-ver", bind_parse_tls_method_minmax, 1 }, /* minimum version */
10140 { "ssl-max-ver", bind_parse_tls_method_minmax, 1 }, /* maximum version */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +020010141 { "strict-sni", bind_parse_strict_sni, 0 }, /* refuse negotiation if sni doesn't match a certificate */
10142 { "tls-ticket-keys", bind_parse_tls_ticket_keys, 1 }, /* set file to load TLS ticket keys from */
10143 { "verify", bind_parse_verify, 1 }, /* set SSL verify method */
10144 { "npn", bind_parse_npn, 1 }, /* set NPN supported protocols */
10145 { "prefer-client-ciphers", bind_parse_pcc, 0 }, /* prefer client ciphers */
Willy Tarreau79eeafa2012-09-14 07:53:05 +020010146 { NULL, NULL, 0 },
10147}};
Emeric Brun46591952012-05-18 15:47:34 +020010148
Willy Tarreau0108d902018-11-25 19:14:37 +010010149INITCALL1(STG_REGISTER, bind_register_keywords, &bind_kws);
10150
Willy Tarreau92faadf2012-10-10 23:04:25 +020010151/* Note: must not be declared <const> as its list will be overwritten.
10152 * Please take care of keeping this list alphabetically sorted, doing so helps
10153 * all code contributors.
10154 * Optional keywords are also declared with a NULL ->parse() function so that
10155 * the config parser can report an appropriate error when a known keyword was
10156 * not enabled.
10157 */
10158static struct srv_kw_list srv_kws = { "SSL", { }, {
Olivier Houchard522eea72017-11-03 16:27:47 +010010159 { "allow-0rtt", srv_parse_allow_0rtt, 0, 1 }, /* Allow using early data on this server */
Olivier Houchardc7566002018-11-20 23:33:50 +010010160 { "alpn", srv_parse_alpn, 1, 1 }, /* Set ALPN supported protocols */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +020010161 { "ca-file", srv_parse_ca_file, 1, 1 }, /* set CAfile to process verify server cert */
Olivier Houchard92150142018-12-21 19:47:01 +010010162 { "check-alpn", srv_parse_alpn, 1, 1 }, /* Set ALPN used for checks */
Olivier Houchard9130a962017-10-17 17:33:43 +020010163 { "check-sni", srv_parse_check_sni, 1, 1 }, /* set SNI */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +020010164 { "check-ssl", srv_parse_check_ssl, 0, 1 }, /* enable SSL for health checks */
10165 { "ciphers", srv_parse_ciphers, 1, 1 }, /* select the cipher suite */
Emmanuel Hocdet839af572019-05-14 16:27:35 +020010166#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +020010167 { "ciphersuites", srv_parse_ciphersuites, 1, 1 }, /* select the cipher suite */
10168#endif
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +020010169 { "crl-file", srv_parse_crl_file, 1, 1 }, /* set certificate revocation list file use on server cert verify */
10170 { "crt", srv_parse_crt, 1, 1 }, /* set client certificate */
10171 { "force-sslv3", srv_parse_tls_method_options, 0, 1 }, /* force SSLv3 */
10172 { "force-tlsv10", srv_parse_tls_method_options, 0, 1 }, /* force TLSv10 */
10173 { "force-tlsv11", srv_parse_tls_method_options, 0, 1 }, /* force TLSv11 */
10174 { "force-tlsv12", srv_parse_tls_method_options, 0, 1 }, /* force TLSv12 */
10175 { "force-tlsv13", srv_parse_tls_method_options, 0, 1 }, /* force TLSv13 */
10176 { "no-check-ssl", srv_parse_no_check_ssl, 0, 1 }, /* disable SSL for health checks */
10177 { "no-send-proxy-v2-ssl", srv_parse_no_send_proxy_ssl, 0, 1 }, /* do not send PROXY protocol header v2 with SSL info */
10178 { "no-send-proxy-v2-ssl-cn", srv_parse_no_send_proxy_cn, 0, 1 }, /* do not send PROXY protocol header v2 with CN */
10179 { "no-ssl", srv_parse_no_ssl, 0, 1 }, /* disable SSL processing */
10180 { "no-ssl-reuse", srv_parse_no_ssl_reuse, 0, 1 }, /* disable session reuse */
10181 { "no-sslv3", srv_parse_tls_method_options, 0, 0 }, /* disable SSLv3 */
10182 { "no-tlsv10", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv10 */
10183 { "no-tlsv11", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv11 */
10184 { "no-tlsv12", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv12 */
10185 { "no-tlsv13", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv13 */
10186 { "no-tls-tickets", srv_parse_no_tls_tickets, 0, 1 }, /* disable session resumption tickets */
Olivier Houchardc7566002018-11-20 23:33:50 +010010187 { "npn", srv_parse_npn, 1, 1 }, /* Set NPN supported protocols */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +020010188 { "send-proxy-v2-ssl", srv_parse_send_proxy_ssl, 0, 1 }, /* send PROXY protocol header v2 with SSL info */
10189 { "send-proxy-v2-ssl-cn", srv_parse_send_proxy_cn, 0, 1 }, /* send PROXY protocol header v2 with CN */
10190 { "sni", srv_parse_sni, 1, 1 }, /* send SNI extension */
10191 { "ssl", srv_parse_ssl, 0, 1 }, /* enable SSL processing */
10192 { "ssl-min-ver", srv_parse_tls_method_minmax, 1, 1 }, /* minimum version */
10193 { "ssl-max-ver", srv_parse_tls_method_minmax, 1, 1 }, /* maximum version */
10194 { "ssl-reuse", srv_parse_ssl_reuse, 0, 1 }, /* enable session reuse */
10195 { "tls-tickets", srv_parse_tls_tickets, 0, 1 }, /* enable session resumption tickets */
10196 { "verify", srv_parse_verify, 1, 1 }, /* set SSL verify method */
10197 { "verifyhost", srv_parse_verifyhost, 1, 1 }, /* require that SSL cert verifies for hostname */
Willy Tarreau92faadf2012-10-10 23:04:25 +020010198 { NULL, NULL, 0, 0 },
10199}};
10200
Willy Tarreau0108d902018-11-25 19:14:37 +010010201INITCALL1(STG_REGISTER, srv_register_keywords, &srv_kws);
10202
Emeric Brun2c86cbf2014-10-30 15:56:50 +010010203static struct cfg_kw_list cfg_kws = {ILH, {
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +010010204 { CFG_GLOBAL, "ca-base", ssl_parse_global_ca_crt_base },
10205 { CFG_GLOBAL, "crt-base", ssl_parse_global_ca_crt_base },
Willy Tarreau0bea58d2016-12-21 23:17:25 +010010206 { CFG_GLOBAL, "maxsslconn", ssl_parse_global_int },
Emeric Brun2c86cbf2014-10-30 15:56:50 +010010207 { CFG_GLOBAL, "ssl-default-bind-options", ssl_parse_default_bind_options },
10208 { CFG_GLOBAL, "ssl-default-server-options", ssl_parse_default_server_options },
Willy Tarreau14e36a12016-12-21 23:28:13 +010010209#ifndef OPENSSL_NO_DH
10210 { CFG_GLOBAL, "ssl-dh-param-file", ssl_parse_global_dh_param_file },
10211#endif
Grant Zhangfa6c7ee2017-01-14 01:42:15 +000010212 { CFG_GLOBAL, "ssl-mode-async", ssl_parse_global_ssl_async },
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020010213#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +000010214 { CFG_GLOBAL, "ssl-engine", ssl_parse_global_ssl_engine },
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020010215#endif
Willy Tarreau9ceda382016-12-21 23:13:03 +010010216 { CFG_GLOBAL, "tune.ssl.cachesize", ssl_parse_global_int },
10217#ifndef OPENSSL_NO_DH
10218 { CFG_GLOBAL, "tune.ssl.default-dh-param", ssl_parse_global_default_dh },
10219#endif
10220 { CFG_GLOBAL, "tune.ssl.force-private-cache", ssl_parse_global_private_cache },
10221 { CFG_GLOBAL, "tune.ssl.lifetime", ssl_parse_global_lifetime },
10222 { CFG_GLOBAL, "tune.ssl.maxrecord", ssl_parse_global_int },
10223 { CFG_GLOBAL, "tune.ssl.ssl-ctx-cache-size", ssl_parse_global_int },
Thierry FOURNIER5bf77322017-02-25 12:45:22 +010010224 { CFG_GLOBAL, "tune.ssl.capture-cipherlist-size", ssl_parse_global_capture_cipherlist },
Willy Tarreauf22e9682016-12-21 23:23:19 +010010225 { CFG_GLOBAL, "ssl-default-bind-ciphers", ssl_parse_global_ciphers },
10226 { CFG_GLOBAL, "ssl-default-server-ciphers", ssl_parse_global_ciphers },
Emmanuel Hocdet839af572019-05-14 16:27:35 +020010227#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +020010228 { CFG_GLOBAL, "ssl-default-bind-ciphersuites", ssl_parse_global_ciphersuites },
10229 { CFG_GLOBAL, "ssl-default-server-ciphersuites", ssl_parse_global_ciphersuites },
10230#endif
Emeric Brun2c86cbf2014-10-30 15:56:50 +010010231 { 0, NULL, NULL },
10232}};
10233
Willy Tarreau0108d902018-11-25 19:14:37 +010010234INITCALL1(STG_REGISTER, cfg_register_keywords, &cfg_kws);
10235
Nenad Merdanovicc31499d2019-03-23 11:00:32 +010010236/* Note: must not be declared <const> as its list will be overwritten */
10237static struct sample_conv_kw_list conv_kws = {ILH, {
Willy Tarreau86a394e2019-05-09 14:15:32 +020010238#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000100fL)
Nenad Merdanovicc31499d2019-03-23 11:00:32 +010010239 { "aes_gcm_dec", sample_conv_aes_gcm_dec, ARG4(4,SINT,STR,STR,STR), check_aes_gcm, SMP_T_BIN, SMP_T_BIN },
10240#endif
10241 { NULL, NULL, 0, 0, 0 },
10242}};
10243
10244INITCALL1(STG_REGISTER, sample_register_convs, &conv_kws);
10245
Willy Tarreauf7bc57c2012-10-03 00:19:48 +020010246/* transport-layer operations for SSL sockets */
Willy Tarreaud9f5cca2016-12-22 21:08:52 +010010247static struct xprt_ops ssl_sock = {
Emeric Brun46591952012-05-18 15:47:34 +020010248 .snd_buf = ssl_sock_from_buf,
10249 .rcv_buf = ssl_sock_to_buf,
Olivier Houcharddf357842019-03-21 16:30:07 +010010250 .subscribe = ssl_subscribe,
10251 .unsubscribe = ssl_unsubscribe,
Olivier Houchard5149b592019-05-23 17:47:36 +020010252 .remove_xprt = ssl_remove_xprt,
Olivier Houchard2e055482019-05-27 19:50:12 +020010253 .add_xprt = ssl_add_xprt,
Emeric Brun46591952012-05-18 15:47:34 +020010254 .rcv_pipe = NULL,
10255 .snd_pipe = NULL,
10256 .shutr = NULL,
10257 .shutw = ssl_sock_shutw,
10258 .close = ssl_sock_close,
10259 .init = ssl_sock_init,
Willy Tarreau55d37912016-12-21 23:38:39 +010010260 .prepare_bind_conf = ssl_sock_prepare_bind_conf,
Willy Tarreau795cdab2016-12-22 17:30:54 +010010261 .destroy_bind_conf = ssl_sock_destroy_bind_conf,
Willy Tarreau17d45382016-12-22 21:16:08 +010010262 .prepare_srv = ssl_sock_prepare_srv_ctx,
10263 .destroy_srv = ssl_sock_free_srv_ctx,
Willy Tarreau8743f7e2016-12-04 18:44:29 +010010264 .get_alpn = ssl_sock_get_alpn,
Willy Tarreau8e0bb0a2016-11-24 16:58:12 +010010265 .name = "SSL",
Emeric Brun46591952012-05-18 15:47:34 +020010266};
10267
Olivier Houchardccaa7de2017-10-02 11:51:03 +020010268enum act_return ssl_action_wait_for_hs(struct act_rule *rule, struct proxy *px,
10269 struct session *sess, struct stream *s, int flags)
10270{
10271 struct connection *conn;
Olivier Houchard6fa63d92017-11-27 18:41:32 +010010272 struct conn_stream *cs;
Olivier Houchardccaa7de2017-10-02 11:51:03 +020010273
10274 conn = objt_conn(sess->origin);
Olivier Houchard6fa63d92017-11-27 18:41:32 +010010275 cs = objt_cs(s->si[0].end);
Olivier Houchardccaa7de2017-10-02 11:51:03 +020010276
Olivier Houchard6fa63d92017-11-27 18:41:32 +010010277 if (conn && cs) {
Olivier Houchardccaa7de2017-10-02 11:51:03 +020010278 if (conn->flags & (CO_FL_EARLY_SSL_HS | CO_FL_SSL_WAIT_HS)) {
Olivier Houchard6fa63d92017-11-27 18:41:32 +010010279 cs->flags |= CS_FL_WAIT_FOR_HS;
Olivier Houchardccaa7de2017-10-02 11:51:03 +020010280 s->req.flags |= CF_READ_NULL;
10281 return ACT_RET_YIELD;
10282 }
10283 }
10284 return (ACT_RET_CONT);
10285}
10286
10287static enum act_parse_ret ssl_parse_wait_for_hs(const char **args, int *orig_arg, struct proxy *px, struct act_rule *rule, char **err)
10288{
10289 rule->action_ptr = ssl_action_wait_for_hs;
10290
10291 return ACT_RET_PRS_OK;
10292}
10293
10294static struct action_kw_list http_req_actions = {ILH, {
10295 { "wait-for-handshake", ssl_parse_wait_for_hs },
10296 { /* END */ }
10297}};
10298
Willy Tarreau0108d902018-11-25 19:14:37 +010010299INITCALL1(STG_REGISTER, http_req_keywords_register, &http_req_actions);
10300
Willy Tarreau5db847a2019-05-09 14:13:35 +020010301#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +010010302
10303static void ssl_sock_sctl_free_func(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, long argl, void *argp)
10304{
10305 if (ptr) {
10306 chunk_destroy(ptr);
10307 free(ptr);
10308 }
10309}
10310
10311#endif
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +010010312static void ssl_sock_capture_free_func(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, long argl, void *argp)
10313{
Willy Tarreaubafbe012017-11-24 17:34:44 +010010314 pool_free(pool_head_ssl_capture, ptr);
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +010010315}
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +010010316
Emeric Brun46591952012-05-18 15:47:34 +020010317__attribute__((constructor))
Willy Tarreau92faadf2012-10-10 23:04:25 +020010318static void __ssl_sock_init(void)
10319{
Ilya Shipitsin0590f442019-05-25 19:30:50 +050010320#if (!defined(OPENSSL_NO_COMP) && !defined(SSL_OP_NO_COMPRESSION))
Emeric Brun46591952012-05-18 15:47:34 +020010321 STACK_OF(SSL_COMP)* cm;
Ilya Shipitsine242f3d2019-05-25 03:38:14 +050010322 int n;
Ilya Shipitsin0590f442019-05-25 19:30:50 +050010323#endif
Emeric Brun46591952012-05-18 15:47:34 +020010324
Willy Tarreauef934602016-12-22 23:12:01 +010010325 if (global_ssl.listen_default_ciphers)
10326 global_ssl.listen_default_ciphers = strdup(global_ssl.listen_default_ciphers);
10327 if (global_ssl.connect_default_ciphers)
10328 global_ssl.connect_default_ciphers = strdup(global_ssl.connect_default_ciphers);
Emmanuel Hocdet839af572019-05-14 16:27:35 +020010329#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +020010330 if (global_ssl.listen_default_ciphersuites)
10331 global_ssl.listen_default_ciphersuites = strdup(global_ssl.listen_default_ciphersuites);
10332 if (global_ssl.connect_default_ciphersuites)
10333 global_ssl.connect_default_ciphersuites = strdup(global_ssl.connect_default_ciphersuites);
10334#endif
Willy Tarreau610f04b2014-02-13 11:36:41 +010010335
Willy Tarreau13e14102016-12-22 20:25:26 +010010336 xprt_register(XPRT_SSL, &ssl_sock);
Willy Tarreau9a1ab082019-05-09 13:26:41 +020010337#if HA_OPENSSL_VERSION_NUMBER < 0x10100000L
Emeric Brun46591952012-05-18 15:47:34 +020010338 SSL_library_init();
Rosen Penev68185952018-12-14 08:47:02 -080010339#endif
Ilya Shipitsin0590f442019-05-25 19:30:50 +050010340#if (!defined(OPENSSL_NO_COMP) && !defined(SSL_OP_NO_COMPRESSION))
Emeric Brun46591952012-05-18 15:47:34 +020010341 cm = SSL_COMP_get_compression_methods();
Ilya Shipitsine242f3d2019-05-25 03:38:14 +050010342 n = sk_SSL_COMP_num(cm);
10343 while (n--) {
10344 (void) sk_SSL_COMP_pop(cm);
10345 }
Ilya Shipitsin0590f442019-05-25 19:30:50 +050010346#endif
Ilya Shipitsine242f3d2019-05-25 03:38:14 +050010347
Willy Tarreau5db847a2019-05-09 14:13:35 +020010348#if defined(USE_THREAD) && (HA_OPENSSL_VERSION_NUMBER < 0x10100000L)
Emeric Brun821bb9b2017-06-15 16:37:39 +020010349 ssl_locking_init();
10350#endif
Willy Tarreau5db847a2019-05-09 14:13:35 +020010351#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +010010352 sctl_ex_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, ssl_sock_sctl_free_func);
10353#endif
Thierry FOURNIER28962c92018-06-17 21:37:05 +020010354 ssl_app_data_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL);
Thierry FOURNIER16ff0502018-06-17 21:33:01 +020010355 ssl_capture_ptr_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, ssl_sock_capture_free_func);
Emmanuel Hocdet96b78342017-10-31 15:46:07 +010010356 ssl_pkey_info_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, NULL);
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020010357#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +000010358 ENGINE_load_builtin_engines();
Grant Zhangfa6c7ee2017-01-14 01:42:15 +000010359 hap_register_post_check(ssl_check_async_engine_count);
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020010360#endif
Willy Tarreaud1c57502016-12-22 22:46:15 +010010361#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
10362 hap_register_post_check(tlskeys_finalize_config);
10363#endif
Willy Tarreau80713382018-11-26 10:19:54 +010010364
10365 global.ssl_session_max_cost = SSL_SESSION_MAX_COST;
10366 global.ssl_handshake_max_cost = SSL_HANDSHAKE_MAX_COST;
10367
10368#ifndef OPENSSL_NO_DH
10369 ssl_dh_ptr_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, NULL);
10370 hap_register_post_deinit(ssl_free_dh);
10371#endif
10372#ifndef OPENSSL_NO_ENGINE
10373 hap_register_post_deinit(ssl_free_engines);
10374#endif
10375 /* Load SSL string for the verbose & debug mode. */
10376 ERR_load_SSL_strings();
Olivier Houcharda8955d52019-04-07 22:00:38 +020010377 ha_meth = BIO_meth_new(0x666, "ha methods");
10378 BIO_meth_set_write(ha_meth, ha_ssl_write);
10379 BIO_meth_set_read(ha_meth, ha_ssl_read);
10380 BIO_meth_set_ctrl(ha_meth, ha_ssl_ctrl);
10381 BIO_meth_set_create(ha_meth, ha_ssl_new);
10382 BIO_meth_set_destroy(ha_meth, ha_ssl_free);
10383 BIO_meth_set_puts(ha_meth, ha_ssl_puts);
10384 BIO_meth_set_gets(ha_meth, ha_ssl_gets);
William Lallemand150bfa82019-09-19 17:12:49 +020010385
10386 HA_SPIN_INIT(&ckch_lock);
Willy Tarreau80713382018-11-26 10:19:54 +010010387}
Willy Tarreaud92aa5c2015-01-15 21:34:39 +010010388
Willy Tarreau80713382018-11-26 10:19:54 +010010389/* Compute and register the version string */
10390static void ssl_register_build_options()
10391{
10392 char *ptr = NULL;
10393 int i;
10394
Willy Tarreauc2c0b612016-12-21 19:23:20 +010010395 memprintf(&ptr, "Built with OpenSSL version : "
10396#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet50e25e12017-03-24 15:20:03 +010010397 "BoringSSL");
Willy Tarreauc2c0b612016-12-21 19:23:20 +010010398#else /* OPENSSL_IS_BORINGSSL */
10399 OPENSSL_VERSION_TEXT
10400 "\nRunning on OpenSSL version : %s%s",
Rosen Penev68185952018-12-14 08:47:02 -080010401 OpenSSL_version(OPENSSL_VERSION),
Willy Tarreau1d158ab2019-05-09 13:41:45 +020010402 ((OPENSSL_VERSION_NUMBER ^ OpenSSL_version_num()) >> 8) ? " (VERSIONS DIFFER!)" : "");
Willy Tarreauc2c0b612016-12-21 19:23:20 +010010403#endif
10404 memprintf(&ptr, "%s\nOpenSSL library supports TLS extensions : "
Willy Tarreau9a1ab082019-05-09 13:26:41 +020010405#if HA_OPENSSL_VERSION_NUMBER < 0x00907000L
Willy Tarreauc2c0b612016-12-21 19:23:20 +010010406 "no (library version too old)"
10407#elif defined(OPENSSL_NO_TLSEXT)
10408 "no (disabled via OPENSSL_NO_TLSEXT)"
10409#else
10410 "yes"
10411#endif
10412 "", ptr);
10413
10414 memprintf(&ptr, "%s\nOpenSSL library supports SNI : "
10415#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
10416 "yes"
10417#else
10418#ifdef OPENSSL_NO_TLSEXT
10419 "no (because of OPENSSL_NO_TLSEXT)"
10420#else
10421 "no (version might be too old, 0.9.8f min needed)"
10422#endif
10423#endif
10424 "", ptr);
10425
Emmanuel Hocdetf80bc242017-07-12 14:25:38 +020010426 memprintf(&ptr, "%s\nOpenSSL library supports :", ptr);
10427 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
10428 if (methodVersions[i].option)
10429 memprintf(&ptr, "%s %s", ptr, methodVersions[i].name);
Emmanuel Hocdet50e25e12017-03-24 15:20:03 +010010430
Willy Tarreauc2c0b612016-12-21 19:23:20 +010010431 hap_register_build_opts(ptr, 1);
Willy Tarreau80713382018-11-26 10:19:54 +010010432}
Willy Tarreauc2c0b612016-12-21 19:23:20 +010010433
Willy Tarreau80713382018-11-26 10:19:54 +010010434INITCALL0(STG_REGISTER, ssl_register_build_options);
Remi Gacogne4f902b82015-05-28 16:23:00 +020010435
Emeric Brun46591952012-05-18 15:47:34 +020010436
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020010437#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +000010438void ssl_free_engines(void) {
10439 struct ssl_engine_list *wl, *wlb;
10440 /* free up engine list */
10441 list_for_each_entry_safe(wl, wlb, &openssl_engines, list) {
10442 ENGINE_finish(wl->e);
10443 ENGINE_free(wl->e);
10444 LIST_DEL(&wl->list);
10445 free(wl);
10446 }
10447}
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020010448#endif
Christopher Faulet31af49d2015-06-09 17:29:50 +020010449
Remi Gacogned3a23c32015-05-28 16:39:47 +020010450#ifndef OPENSSL_NO_DH
Grant Zhang872f9c22017-01-21 01:10:18 +000010451void ssl_free_dh(void) {
10452 if (local_dh_1024) {
10453 DH_free(local_dh_1024);
10454 local_dh_1024 = NULL;
10455 }
10456 if (local_dh_2048) {
10457 DH_free(local_dh_2048);
10458 local_dh_2048 = NULL;
10459 }
10460 if (local_dh_4096) {
10461 DH_free(local_dh_4096);
10462 local_dh_4096 = NULL;
10463 }
Remi Gacogne47783ef2015-05-29 15:53:22 +020010464 if (global_dh) {
10465 DH_free(global_dh);
10466 global_dh = NULL;
10467 }
Grant Zhang872f9c22017-01-21 01:10:18 +000010468}
10469#endif
10470
10471__attribute__((destructor))
10472static void __ssl_sock_deinit(void)
10473{
10474#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Emeric Brun821bb9b2017-06-15 16:37:39 +020010475 if (ssl_ctx_lru_tree) {
10476 lru64_destroy(ssl_ctx_lru_tree);
Christopher Faulet2a944ee2017-11-07 10:42:54 +010010477 HA_RWLOCK_DESTROY(&ssl_ctx_lru_rwlock);
Emeric Brun821bb9b2017-06-15 16:37:39 +020010478 }
Remi Gacogned3a23c32015-05-28 16:39:47 +020010479#endif
10480
Willy Tarreau5db847a2019-05-09 14:13:35 +020010481#if (HA_OPENSSL_VERSION_NUMBER < 0x10100000L)
Remi Gacogned3a23c32015-05-28 16:39:47 +020010482 ERR_remove_state(0);
10483 ERR_free_strings();
10484
10485 EVP_cleanup();
Rosen Penev68185952018-12-14 08:47:02 -080010486#endif
Remi Gacogned3a23c32015-05-28 16:39:47 +020010487
Willy Tarreau5db847a2019-05-09 14:13:35 +020010488#if (HA_OPENSSL_VERSION_NUMBER >= 0x00907000L) && (HA_OPENSSL_VERSION_NUMBER < 0x10100000L)
Remi Gacogned3a23c32015-05-28 16:39:47 +020010489 CRYPTO_cleanup_all_ex_data();
10490#endif
Olivier Houcharda8955d52019-04-07 22:00:38 +020010491 BIO_meth_free(ha_meth);
Remi Gacogned3a23c32015-05-28 16:39:47 +020010492}
10493
10494
Emeric Brun46591952012-05-18 15:47:34 +020010495/*
10496 * Local variables:
10497 * c-indent-level: 8
10498 * c-basic-offset: 8
10499 * End:
10500 */