blob: e537e61686ff390845968e8f354c1e344a9b8cb6 [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 Lallemand3b5f3602019-10-16 18:05:05 +0200878 * path 'ocsp_path' or base64 in a buffer <buf>
Emeric Brun4147b2e2014-06-16 18:36:30 +0200879 *
880 * Returns 0 on success, 1 in error case.
881 */
William Lallemand3b5f3602019-10-16 18:05:05 +0200882static int ssl_sock_load_ocsp_response_from_file(const char *ocsp_path, char *buf, struct cert_key_and_chain *ckch, char **err)
Emeric Brun4147b2e2014-06-16 18:36:30 +0200883{
884 int fd = -1;
885 int r = 0;
886 int ret = 1;
William Lallemand3b5f3602019-10-16 18:05:05 +0200887 struct buffer *ocsp_response;
888 struct buffer *src = NULL;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200889
William Lallemand3b5f3602019-10-16 18:05:05 +0200890 if (buf) {
891 int i, j;
892 /* if it's from a buffer it will be base64 */
Emeric Brun4147b2e2014-06-16 18:36:30 +0200893
William Lallemand3b5f3602019-10-16 18:05:05 +0200894 /* remove \r and \n from the payload */
895 for (i = 0, j = 0; buf[i]; i++) {
896 if (buf[i] == '\r' || buf[i] == '\n')
Emeric Brun4147b2e2014-06-16 18:36:30 +0200897 continue;
William Lallemand3b5f3602019-10-16 18:05:05 +0200898 buf[j++] = buf[i];
899 }
900 buf[j] = 0;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200901
William Lallemand3b5f3602019-10-16 18:05:05 +0200902 ret = base64dec(buf, j, trash.area, trash.size);
903 if (ret < 0) {
904 memprintf(err, "Error reading OCSP response in base64 format");
Emeric Brun4147b2e2014-06-16 18:36:30 +0200905 goto end;
906 }
William Lallemand3b5f3602019-10-16 18:05:05 +0200907 trash.data = ret;
908 src = &trash;
909 } else {
910 fd = open(ocsp_path, O_RDONLY);
911 if (fd == -1) {
912 memprintf(err, "Error opening OCSP response file");
913 goto end;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200914 }
William Lallemand3b5f3602019-10-16 18:05:05 +0200915
916 trash.data = 0;
917 while (trash.data < trash.size) {
918 r = read(fd, trash.area + trash.data, trash.size - trash.data);
919 if (r < 0) {
920 if (errno == EINTR)
921 continue;
922
923 memprintf(err, "Error reading OCSP response from file");
924 goto end;
925 }
926 else if (r == 0) {
927 break;
928 }
929 trash.data += r;
930 }
931 close(fd);
932 fd = -1;
933 src = &trash;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200934 }
935
William Lallemand3b5f3602019-10-16 18:05:05 +0200936 ocsp_response = calloc(1, sizeof(*ocsp_response));
937 if (!chunk_dup(ocsp_response, src)) {
938 free(ocsp_response);
939 ocsp_response = NULL;
William Lallemand246c0242019-10-11 08:59:13 +0200940 goto end;
941 }
942
William Lallemand3b5f3602019-10-16 18:05:05 +0200943 ckch->ocsp_response = ocsp_response;
William Lallemande0f48ae2019-10-15 13:44:57 +0200944 ret = 0;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200945end:
946 if (fd != -1)
947 close(fd);
948
949 return ret;
950}
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100951#endif
Emeric Brun4147b2e2014-06-16 18:36:30 +0200952
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100953#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
954static 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)
955{
Christopher Faulet16f45c82018-02-16 11:23:49 +0100956 struct tls_keys_ref *ref;
Emeric Brun9e754772019-01-10 17:51:55 +0100957 union tls_sess_key *keys;
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100958 struct connection *conn;
959 int head;
960 int i;
Christopher Faulet16f45c82018-02-16 11:23:49 +0100961 int ret = -1; /* error by default */
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100962
Thierry FOURNIER28962c92018-06-17 21:37:05 +0200963 conn = SSL_get_ex_data(s, ssl_app_data_index);
Willy Tarreau07d94e42018-09-20 10:57:52 +0200964 ref = __objt_listener(conn->target)->bind_conf->keys_ref;
Christopher Faulet16f45c82018-02-16 11:23:49 +0100965 HA_RWLOCK_RDLOCK(TLSKEYS_REF_LOCK, &ref->lock);
966
967 keys = ref->tlskeys;
968 head = ref->tls_ticket_enc_index;
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100969
970 if (enc) {
971 memcpy(key_name, keys[head].name, 16);
972
973 if(!RAND_pseudo_bytes(iv, EVP_MAX_IV_LENGTH))
Christopher Faulet16f45c82018-02-16 11:23:49 +0100974 goto end;
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100975
Emeric Brun9e754772019-01-10 17:51:55 +0100976 if (ref->key_size_bits == 128) {
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100977
Emeric Brun9e754772019-01-10 17:51:55 +0100978 if(!EVP_EncryptInit_ex(ectx, EVP_aes_128_cbc(), NULL, keys[head].key_128.aes_key, iv))
979 goto end;
980
Willy Tarreau9356dac2019-05-10 09:22:53 +0200981 HMAC_Init_ex(hctx, keys[head].key_128.hmac_key, 16, TLS_TICKET_HASH_FUNCT(), NULL);
Emeric Brun9e754772019-01-10 17:51:55 +0100982 ret = 1;
983 }
984 else if (ref->key_size_bits == 256 ) {
985
986 if(!EVP_EncryptInit_ex(ectx, EVP_aes_256_cbc(), NULL, keys[head].key_256.aes_key, iv))
987 goto end;
988
Willy Tarreau9356dac2019-05-10 09:22:53 +0200989 HMAC_Init_ex(hctx, keys[head].key_256.hmac_key, 32, TLS_TICKET_HASH_FUNCT(), NULL);
Emeric Brun9e754772019-01-10 17:51:55 +0100990 ret = 1;
991 }
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100992 } else {
993 for (i = 0; i < TLS_TICKETS_NO; i++) {
994 if (!memcmp(key_name, keys[(head + i) % TLS_TICKETS_NO].name, 16))
995 goto found;
996 }
Christopher Faulet16f45c82018-02-16 11:23:49 +0100997 ret = 0;
998 goto end;
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100999
Christopher Faulet16f45c82018-02-16 11:23:49 +01001000 found:
Emeric Brun9e754772019-01-10 17:51:55 +01001001 if (ref->key_size_bits == 128) {
Willy Tarreau9356dac2019-05-10 09:22:53 +02001002 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 +01001003 if(!EVP_DecryptInit_ex(ectx, EVP_aes_128_cbc(), NULL, keys[(head + i) % TLS_TICKETS_NO].key_128.aes_key, iv))
1004 goto end;
1005 /* 2 for key renewal, 1 if current key is still valid */
1006 ret = i ? 2 : 1;
1007 }
1008 else if (ref->key_size_bits == 256) {
Willy Tarreau9356dac2019-05-10 09:22:53 +02001009 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 +01001010 if(!EVP_DecryptInit_ex(ectx, EVP_aes_256_cbc(), NULL, keys[(head + i) % TLS_TICKETS_NO].key_256.aes_key, iv))
1011 goto end;
1012 /* 2 for key renewal, 1 if current key is still valid */
1013 ret = i ? 2 : 1;
1014 }
Nenad Merdanovic05552d42015-02-27 19:56:49 +01001015 }
Emeric Brun9e754772019-01-10 17:51:55 +01001016
Christopher Faulet16f45c82018-02-16 11:23:49 +01001017 end:
1018 HA_RWLOCK_RDUNLOCK(TLSKEYS_REF_LOCK, &ref->lock);
1019 return ret;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02001020}
1021
1022struct tls_keys_ref *tlskeys_ref_lookup(const char *filename)
1023{
1024 struct tls_keys_ref *ref;
1025
1026 list_for_each_entry(ref, &tlskeys_reference, list)
1027 if (ref->filename && strcmp(filename, ref->filename) == 0)
1028 return ref;
1029 return NULL;
1030}
1031
1032struct tls_keys_ref *tlskeys_ref_lookupid(int unique_id)
1033{
1034 struct tls_keys_ref *ref;
1035
1036 list_for_each_entry(ref, &tlskeys_reference, list)
1037 if (ref->unique_id == unique_id)
1038 return ref;
1039 return NULL;
1040}
1041
Emeric Brun9e754772019-01-10 17:51:55 +01001042/* Update the key into ref: if keysize doesnt
1043 * match existing ones, this function returns -1
1044 * else it returns 0 on success.
1045 */
1046int ssl_sock_update_tlskey_ref(struct tls_keys_ref *ref,
Willy Tarreau83061a82018-07-13 11:56:34 +02001047 struct buffer *tlskey)
Christopher Faulet16f45c82018-02-16 11:23:49 +01001048{
Emeric Brun9e754772019-01-10 17:51:55 +01001049 if (ref->key_size_bits == 128) {
1050 if (tlskey->data != sizeof(struct tls_sess_key_128))
1051 return -1;
1052 }
1053 else if (ref->key_size_bits == 256) {
1054 if (tlskey->data != sizeof(struct tls_sess_key_256))
1055 return -1;
1056 }
1057 else
1058 return -1;
1059
Christopher Faulet16f45c82018-02-16 11:23:49 +01001060 HA_RWLOCK_WRLOCK(TLSKEYS_REF_LOCK, &ref->lock);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001061 memcpy((char *) (ref->tlskeys + ((ref->tls_ticket_enc_index + 2) % TLS_TICKETS_NO)),
1062 tlskey->area, tlskey->data);
Christopher Faulet16f45c82018-02-16 11:23:49 +01001063 ref->tls_ticket_enc_index = (ref->tls_ticket_enc_index + 1) % TLS_TICKETS_NO;
1064 HA_RWLOCK_WRUNLOCK(TLSKEYS_REF_LOCK, &ref->lock);
Emeric Brun9e754772019-01-10 17:51:55 +01001065
1066 return 0;
Christopher Faulet16f45c82018-02-16 11:23:49 +01001067}
1068
Willy Tarreau83061a82018-07-13 11:56:34 +02001069int ssl_sock_update_tlskey(char *filename, struct buffer *tlskey, char **err)
Christopher Faulet16f45c82018-02-16 11:23:49 +01001070{
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02001071 struct tls_keys_ref *ref = tlskeys_ref_lookup(filename);
1072
1073 if(!ref) {
1074 memprintf(err, "Unable to locate the referenced filename: %s", filename);
1075 return 1;
1076 }
Emeric Brun9e754772019-01-10 17:51:55 +01001077 if (ssl_sock_update_tlskey_ref(ref, tlskey) < 0) {
1078 memprintf(err, "Invalid key size");
1079 return 1;
1080 }
1081
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02001082 return 0;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01001083}
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02001084
1085/* This function finalize the configuration parsing. Its set all the
Willy Tarreaud1c57502016-12-22 22:46:15 +01001086 * automatic ids. It's called just after the basic checks. It returns
1087 * 0 on success otherwise ERR_*.
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02001088 */
Willy Tarreaud1c57502016-12-22 22:46:15 +01001089static int tlskeys_finalize_config(void)
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02001090{
1091 int i = 0;
1092 struct tls_keys_ref *ref, *ref2, *ref3;
1093 struct list tkr = LIST_HEAD_INIT(tkr);
1094
1095 list_for_each_entry(ref, &tlskeys_reference, list) {
1096 if (ref->unique_id == -1) {
1097 /* Look for the first free id. */
1098 while (1) {
1099 list_for_each_entry(ref2, &tlskeys_reference, list) {
1100 if (ref2->unique_id == i) {
1101 i++;
1102 break;
1103 }
1104 }
1105 if (&ref2->list == &tlskeys_reference)
1106 break;
1107 }
1108
1109 /* Uses the unique id and increment it for the next entry. */
1110 ref->unique_id = i;
1111 i++;
1112 }
1113 }
1114
1115 /* This sort the reference list by id. */
1116 list_for_each_entry_safe(ref, ref2, &tlskeys_reference, list) {
1117 LIST_DEL(&ref->list);
1118 list_for_each_entry(ref3, &tkr, list) {
1119 if (ref->unique_id < ref3->unique_id) {
1120 LIST_ADDQ(&ref3->list, &ref->list);
1121 break;
1122 }
1123 }
1124 if (&ref3->list == &tkr)
1125 LIST_ADDQ(&tkr, &ref->list);
1126 }
1127
1128 /* swap root */
1129 LIST_ADD(&tkr, &tlskeys_reference);
1130 LIST_DEL(&tkr);
Willy Tarreaud1c57502016-12-22 22:46:15 +01001131 return 0;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02001132}
Nenad Merdanovic05552d42015-02-27 19:56:49 +01001133#endif /* SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB */
1134
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01001135#ifndef OPENSSL_NO_OCSP
yanbzhube2774d2015-12-10 15:07:30 -05001136int ssl_sock_get_ocsp_arg_kt_index(int evp_keytype)
1137{
1138 switch (evp_keytype) {
1139 case EVP_PKEY_RSA:
1140 return 2;
1141 case EVP_PKEY_DSA:
1142 return 0;
1143 case EVP_PKEY_EC:
1144 return 1;
1145 }
1146
1147 return -1;
1148}
1149
Emeric Brun4147b2e2014-06-16 18:36:30 +02001150/*
1151 * Callback used to set OCSP status extension content in server hello.
1152 */
1153int ssl_sock_ocsp_stapling_cbk(SSL *ssl, void *arg)
1154{
yanbzhube2774d2015-12-10 15:07:30 -05001155 struct certificate_ocsp *ocsp;
1156 struct ocsp_cbk_arg *ocsp_arg;
1157 char *ssl_buf;
1158 EVP_PKEY *ssl_pkey;
1159 int key_type;
1160 int index;
1161
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02001162 ocsp_arg = arg;
yanbzhube2774d2015-12-10 15:07:30 -05001163
1164 ssl_pkey = SSL_get_privatekey(ssl);
1165 if (!ssl_pkey)
1166 return SSL_TLSEXT_ERR_NOACK;
1167
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001168 key_type = EVP_PKEY_base_id(ssl_pkey);
yanbzhube2774d2015-12-10 15:07:30 -05001169
1170 if (ocsp_arg->is_single && ocsp_arg->single_kt == key_type)
1171 ocsp = ocsp_arg->s_ocsp;
1172 else {
1173 /* For multiple certs per context, we have to find the correct OCSP response based on
1174 * the certificate type
1175 */
1176 index = ssl_sock_get_ocsp_arg_kt_index(key_type);
1177
1178 if (index < 0)
1179 return SSL_TLSEXT_ERR_NOACK;
1180
1181 ocsp = ocsp_arg->m_ocsp[index];
1182
1183 }
Emeric Brun4147b2e2014-06-16 18:36:30 +02001184
1185 if (!ocsp ||
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001186 !ocsp->response.area ||
1187 !ocsp->response.data ||
Emeric Brun4f3c87a2014-06-20 15:46:13 +02001188 (ocsp->expire < now.tv_sec))
Emeric Brun4147b2e2014-06-16 18:36:30 +02001189 return SSL_TLSEXT_ERR_NOACK;
1190
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001191 ssl_buf = OPENSSL_malloc(ocsp->response.data);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001192 if (!ssl_buf)
1193 return SSL_TLSEXT_ERR_NOACK;
1194
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001195 memcpy(ssl_buf, ocsp->response.area, ocsp->response.data);
1196 SSL_set_tlsext_status_ocsp_resp(ssl, ssl_buf, ocsp->response.data);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001197
1198 return SSL_TLSEXT_ERR_OK;
1199}
1200
William Lallemand4a660132019-10-14 14:51:41 +02001201#endif
1202
1203#if ((defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP) || defined OPENSSL_IS_BORINGSSL)
Emeric Brun4147b2e2014-06-16 18:36:30 +02001204/*
1205 * This function enables the handling of OCSP status extension on 'ctx' if a
William Lallemand246c0242019-10-11 08:59:13 +02001206 * ocsp_response buffer was found in the cert_key_and_chain. To enable OCSP
1207 * status extension, the issuer's certificate is mandatory. It should be
1208 * present in ckch->ocsp_issuer.
Emeric Brun4147b2e2014-06-16 18:36:30 +02001209 *
William Lallemand246c0242019-10-11 08:59:13 +02001210 * In addition, the ckch->ocsp_reponse buffer is loaded as a DER format of an
1211 * OCSP response. If file is empty or content is not a valid OCSP response,
1212 * OCSP status extension is enabled but OCSP response is ignored (a warning is
1213 * displayed).
Emeric Brun4147b2e2014-06-16 18:36:30 +02001214 *
1215 * Returns 1 if no ".ocsp" file found, 0 if OCSP status extension is
Joseph Herlant017b3da2018-11-15 09:07:59 -08001216 * successfully enabled, or -1 in other error case.
Emeric Brun4147b2e2014-06-16 18:36:30 +02001217 */
William Lallemand4a660132019-10-14 14:51:41 +02001218#ifndef OPENSSL_IS_BORINGSSL
William Lallemand246c0242019-10-11 08:59:13 +02001219static int ssl_sock_load_ocsp(SSL_CTX *ctx, const struct cert_key_and_chain *ckch)
Emeric Brun4147b2e2014-06-16 18:36:30 +02001220{
William Lallemand246c0242019-10-11 08:59:13 +02001221 X509 *x = NULL, *issuer = NULL;
Emeric Brun4147b2e2014-06-16 18:36:30 +02001222 OCSP_CERTID *cid = NULL;
Emeric Brun4147b2e2014-06-16 18:36:30 +02001223 int i, ret = -1;
Emeric Brun4147b2e2014-06-16 18:36:30 +02001224 struct certificate_ocsp *ocsp = NULL, *iocsp;
1225 char *warn = NULL;
1226 unsigned char *p;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001227 void (*callback) (void);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001228
Emeric Brun4147b2e2014-06-16 18:36:30 +02001229
William Lallemand246c0242019-10-11 08:59:13 +02001230 x = ckch->cert;
Emeric Brun4147b2e2014-06-16 18:36:30 +02001231 if (!x)
1232 goto out;
1233
William Lallemand246c0242019-10-11 08:59:13 +02001234 issuer = ckch->ocsp_issuer;
1235 if (!issuer)
1236 goto out;
Emeric Brun4147b2e2014-06-16 18:36:30 +02001237
1238 cid = OCSP_cert_to_id(0, x, issuer);
1239 if (!cid)
1240 goto out;
1241
1242 i = i2d_OCSP_CERTID(cid, NULL);
1243 if (!i || (i > OCSP_MAX_CERTID_ASN1_LENGTH))
1244 goto out;
1245
Vincent Bernat02779b62016-04-03 13:48:43 +02001246 ocsp = calloc(1, sizeof(*ocsp));
Emeric Brun4147b2e2014-06-16 18:36:30 +02001247 if (!ocsp)
1248 goto out;
1249
1250 p = ocsp->key_data;
1251 i2d_OCSP_CERTID(cid, &p);
1252
1253 iocsp = (struct certificate_ocsp *)ebmb_insert(&cert_ocsp_tree, &ocsp->key, OCSP_MAX_CERTID_ASN1_LENGTH);
1254 if (iocsp == ocsp)
1255 ocsp = NULL;
1256
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001257#ifndef SSL_CTX_get_tlsext_status_cb
1258# define SSL_CTX_get_tlsext_status_cb(ctx, cb) \
1259 *cb = (void (*) (void))ctx->tlsext_status_cb;
1260#endif
1261 SSL_CTX_get_tlsext_status_cb(ctx, &callback);
1262
1263 if (!callback) {
Vincent Bernat02779b62016-04-03 13:48:43 +02001264 struct ocsp_cbk_arg *cb_arg = calloc(1, sizeof(*cb_arg));
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001265 EVP_PKEY *pkey;
yanbzhube2774d2015-12-10 15:07:30 -05001266
1267 cb_arg->is_single = 1;
1268 cb_arg->s_ocsp = iocsp;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001269
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001270 pkey = X509_get_pubkey(x);
1271 cb_arg->single_kt = EVP_PKEY_base_id(pkey);
1272 EVP_PKEY_free(pkey);
yanbzhube2774d2015-12-10 15:07:30 -05001273
1274 SSL_CTX_set_tlsext_status_cb(ctx, ssl_sock_ocsp_stapling_cbk);
1275 SSL_CTX_set_tlsext_status_arg(ctx, cb_arg);
1276 } else {
1277 /*
1278 * If the ctx has a status CB, then we have previously set an OCSP staple for this ctx
1279 * Update that cb_arg with the new cert's staple
1280 */
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001281 struct ocsp_cbk_arg *cb_arg;
yanbzhube2774d2015-12-10 15:07:30 -05001282 struct certificate_ocsp *tmp_ocsp;
1283 int index;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001284 int key_type;
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001285 EVP_PKEY *pkey;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001286
1287#ifdef SSL_CTX_get_tlsext_status_arg
1288 SSL_CTX_ctrl(ctx, SSL_CTRL_GET_TLSEXT_STATUS_REQ_CB_ARG, 0, &cb_arg);
1289#else
1290 cb_arg = ctx->tlsext_status_arg;
1291#endif
yanbzhube2774d2015-12-10 15:07:30 -05001292
1293 /*
1294 * The following few lines will convert cb_arg from a single ocsp to multi ocsp
1295 * the order of operations below matter, take care when changing it
1296 */
1297 tmp_ocsp = cb_arg->s_ocsp;
1298 index = ssl_sock_get_ocsp_arg_kt_index(cb_arg->single_kt);
1299 cb_arg->s_ocsp = NULL;
1300 cb_arg->m_ocsp[index] = tmp_ocsp;
1301 cb_arg->is_single = 0;
1302 cb_arg->single_kt = 0;
1303
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001304 pkey = X509_get_pubkey(x);
1305 key_type = EVP_PKEY_base_id(pkey);
1306 EVP_PKEY_free(pkey);
1307
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001308 index = ssl_sock_get_ocsp_arg_kt_index(key_type);
yanbzhube2774d2015-12-10 15:07:30 -05001309 if (index >= 0 && !cb_arg->m_ocsp[index])
1310 cb_arg->m_ocsp[index] = iocsp;
1311
1312 }
Emeric Brun4147b2e2014-06-16 18:36:30 +02001313
1314 ret = 0;
1315
1316 warn = NULL;
William Lallemand246c0242019-10-11 08:59:13 +02001317 if (ssl_sock_load_ocsp_response(ckch->ocsp_response, ocsp, cid, &warn)) {
William Lallemand3b5f3602019-10-16 18:05:05 +02001318 memprintf(&warn, "Loading: %s. Content will be ignored", warn ? warn : "failure");
Christopher Faulet767a84b2017-11-24 16:50:31 +01001319 ha_warning("%s.\n", warn);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001320 }
1321
1322out:
Emeric Brun4147b2e2014-06-16 18:36:30 +02001323 if (cid)
1324 OCSP_CERTID_free(cid);
1325
1326 if (ocsp)
1327 free(ocsp);
1328
1329 if (warn)
1330 free(warn);
1331
Emeric Brun4147b2e2014-06-16 18:36:30 +02001332 return ret;
1333}
William Lallemand4a660132019-10-14 14:51:41 +02001334#else /* OPENSSL_IS_BORINGSSL */
1335static int ssl_sock_load_ocsp(SSL_CTX *ctx, const struct cert_key_and_chain *ckch)
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02001336{
William Lallemand4a660132019-10-14 14:51:41 +02001337 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 +02001338}
1339#endif
1340
William Lallemand4a660132019-10-14 14:51:41 +02001341#endif
1342
1343
Willy Tarreau5db847a2019-05-09 14:13:35 +02001344#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001345
1346#define CT_EXTENSION_TYPE 18
1347
1348static int sctl_ex_index = -1;
1349
1350/*
1351 * Try to parse Signed Certificate Timestamp List structure. This function
1352 * makes only basic test if the data seems like SCTL. No signature validation
1353 * is performed.
1354 */
Willy Tarreau83061a82018-07-13 11:56:34 +02001355static int ssl_sock_parse_sctl(struct buffer *sctl)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001356{
1357 int ret = 1;
1358 int len, pos, sct_len;
1359 unsigned char *data;
1360
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001361 if (sctl->data < 2)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001362 goto out;
1363
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001364 data = (unsigned char *) sctl->area;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001365 len = (data[0] << 8) | data[1];
1366
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001367 if (len + 2 != sctl->data)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001368 goto out;
1369
1370 data = data + 2;
1371 pos = 0;
1372 while (pos < len) {
1373 if (len - pos < 2)
1374 goto out;
1375
1376 sct_len = (data[pos] << 8) | data[pos + 1];
1377 if (pos + sct_len + 2 > len)
1378 goto out;
1379
1380 pos += sct_len + 2;
1381 }
1382
1383 ret = 0;
1384
1385out:
1386 return ret;
1387}
1388
William Lallemand0dfae6c2019-10-16 18:06:58 +02001389/* Try to load a sctl from a buffer <buf> if not NULL, or read the file <sctl_path>
1390 * It fills the ckch->sctl buffer
1391 * return 0 on success or != 0 on failure */
1392static int ssl_sock_load_sctl_from_file(const char *sctl_path, char *buf, struct cert_key_and_chain *ckch, char **err)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001393{
1394 int fd = -1;
1395 int r = 0;
1396 int ret = 1;
William Lallemand0dfae6c2019-10-16 18:06:58 +02001397 struct buffer tmp;
1398 struct buffer *src;
1399 struct buffer *sctl;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001400
William Lallemand0dfae6c2019-10-16 18:06:58 +02001401 if (buf) {
1402 tmp.area = buf;
1403 tmp.data = strlen(buf);
1404 tmp.size = tmp.data + 1;
1405 src = &tmp;
1406 } else {
1407 fd = open(sctl_path, O_RDONLY);
1408 if (fd == -1)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001409 goto end;
William Lallemand0dfae6c2019-10-16 18:06:58 +02001410
1411 trash.data = 0;
1412 while (trash.data < trash.size) {
1413 r = read(fd, trash.area + trash.data, trash.size - trash.data);
1414 if (r < 0) {
1415 if (errno == EINTR)
1416 continue;
1417 goto end;
1418 }
1419 else if (r == 0) {
1420 break;
1421 }
1422 trash.data += r;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001423 }
William Lallemand0dfae6c2019-10-16 18:06:58 +02001424 src = &trash;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001425 }
1426
William Lallemand0dfae6c2019-10-16 18:06:58 +02001427 ret = ssl_sock_parse_sctl(src);
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001428 if (ret)
1429 goto end;
1430
William Lallemand0dfae6c2019-10-16 18:06:58 +02001431 sctl = calloc(1, sizeof(*sctl));
1432 if (!chunk_dup(sctl, src)) {
1433 free(sctl);
1434 sctl = NULL;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001435 goto end;
1436 }
William Lallemand0dfae6c2019-10-16 18:06:58 +02001437 ret = 0;
1438 /* TODO: free the previous SCTL in the ckch */
1439 ckch->sctl = sctl;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001440
1441end:
1442 if (fd != -1)
1443 close(fd);
1444
1445 return ret;
1446}
1447
1448int ssl_sock_sctl_add_cbk(SSL *ssl, unsigned ext_type, const unsigned char **out, size_t *outlen, int *al, void *add_arg)
1449{
Willy Tarreau83061a82018-07-13 11:56:34 +02001450 struct buffer *sctl = add_arg;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001451
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001452 *out = (unsigned char *) sctl->area;
1453 *outlen = sctl->data;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001454
1455 return 1;
1456}
1457
1458int ssl_sock_sctl_parse_cbk(SSL *s, unsigned int ext_type, const unsigned char *in, size_t inlen, int *al, void *parse_arg)
1459{
1460 return 1;
1461}
1462
William Lallemanda17f4112019-10-10 15:16:44 +02001463static int ssl_sock_load_sctl(SSL_CTX *ctx, struct buffer *sctl)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001464{
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001465 int ret = -1;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001466
William Lallemanda17f4112019-10-10 15:16:44 +02001467 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 +01001468 goto out;
1469
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001470 SSL_CTX_set_ex_data(ctx, sctl_ex_index, sctl);
1471
1472 ret = 0;
1473
1474out:
1475 return ret;
1476}
1477
1478#endif
1479
Emeric Brune1f38db2012-09-03 20:36:47 +02001480void ssl_sock_infocbk(const SSL *ssl, int where, int ret)
1481{
Thierry FOURNIER28962c92018-06-17 21:37:05 +02001482 struct connection *conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001483 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
Emeric Brund8b2bb52014-01-28 15:43:53 +01001484 BIO *write_bio;
Willy Tarreau622317d2015-02-27 16:36:16 +01001485 (void)ret; /* shut gcc stupid warning */
Emeric Brune1f38db2012-09-03 20:36:47 +02001486
Dirkjan Bussink526894f2019-01-21 09:35:03 -08001487#ifndef SSL_OP_NO_RENEGOTIATION
1488 /* Please note that BoringSSL defines this macro to zero so don't
1489 * change this to #if and do not assign a default value to this macro!
1490 */
Emeric Brune1f38db2012-09-03 20:36:47 +02001491 if (where & SSL_CB_HANDSHAKE_START) {
1492 /* Disable renegotiation (CVE-2009-3555) */
Olivier Houchard90084a12017-11-23 18:21:29 +01001493 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 +02001494 conn->flags |= CO_FL_ERROR;
Willy Tarreau20879a02012-12-03 16:32:10 +01001495 conn->err_code = CO_ER_SSL_RENEG;
1496 }
Emeric Brune1f38db2012-09-03 20:36:47 +02001497 }
Dirkjan Bussink526894f2019-01-21 09:35:03 -08001498#endif
Emeric Brund8b2bb52014-01-28 15:43:53 +01001499
1500 if ((where & SSL_CB_ACCEPT_LOOP) == SSL_CB_ACCEPT_LOOP) {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001501 if (!(ctx->xprt_st & SSL_SOCK_ST_FL_16K_WBFSIZE)) {
Emeric Brund8b2bb52014-01-28 15:43:53 +01001502 /* Long certificate chains optimz
1503 If write and read bios are differents, we
1504 consider that the buffering was activated,
1505 so we rise the output buffer size from 4k
1506 to 16k */
1507 write_bio = SSL_get_wbio(ssl);
1508 if (write_bio != SSL_get_rbio(ssl)) {
1509 BIO_set_write_buffer_size(write_bio, 16384);
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001510 ctx->xprt_st |= SSL_SOCK_ST_FL_16K_WBFSIZE;
Emeric Brund8b2bb52014-01-28 15:43:53 +01001511 }
1512 }
1513 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02001514}
1515
Emeric Brune64aef12012-09-21 13:15:06 +02001516/* Callback is called for each certificate of the chain during a verify
1517 ok is set to 1 if preverify detect no error on current certificate.
1518 Returns 0 to break the handshake, 1 otherwise. */
Evan Broderbe554312013-06-27 00:05:25 -07001519int ssl_sock_bind_verifycbk(int ok, X509_STORE_CTX *x_store)
Emeric Brune64aef12012-09-21 13:15:06 +02001520{
1521 SSL *ssl;
1522 struct connection *conn;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001523 struct ssl_sock_ctx *ctx;
Emeric Brun81c00f02012-09-21 14:31:21 +02001524 int err, depth;
Emeric Brune64aef12012-09-21 13:15:06 +02001525
1526 ssl = X509_STORE_CTX_get_ex_data(x_store, SSL_get_ex_data_X509_STORE_CTX_idx());
Thierry FOURNIER28962c92018-06-17 21:37:05 +02001527 conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Emeric Brune64aef12012-09-21 13:15:06 +02001528
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001529 ctx = conn->xprt_ctx;
1530
1531 ctx->xprt_st |= SSL_SOCK_ST_FL_VERIFY_DONE;
Emeric Brune64aef12012-09-21 13:15:06 +02001532
Emeric Brun81c00f02012-09-21 14:31:21 +02001533 if (ok) /* no errors */
1534 return ok;
1535
1536 depth = X509_STORE_CTX_get_error_depth(x_store);
1537 err = X509_STORE_CTX_get_error(x_store);
1538
1539 /* check if CA error needs to be ignored */
1540 if (depth > 0) {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001541 if (!SSL_SOCK_ST_TO_CA_ERROR(ctx->xprt_st)) {
1542 ctx->xprt_st |= SSL_SOCK_CA_ERROR_TO_ST(err);
1543 ctx->xprt_st |= SSL_SOCK_CAEDEPTH_TO_ST(depth);
Emeric Brunf282a812012-09-21 15:27:54 +02001544 }
1545
Willy Tarreau07d94e42018-09-20 10:57:52 +02001546 if (__objt_listener(conn->target)->bind_conf->ca_ignerr & (1ULL << err)) {
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02001547 ssl_sock_dump_errors(conn);
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001548 ERR_clear_error();
Emeric Brun81c00f02012-09-21 14:31:21 +02001549 return 1;
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001550 }
Emeric Brun81c00f02012-09-21 14:31:21 +02001551
Willy Tarreau20879a02012-12-03 16:32:10 +01001552 conn->err_code = CO_ER_SSL_CA_FAIL;
Emeric Brun81c00f02012-09-21 14:31:21 +02001553 return 0;
1554 }
1555
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001556 if (!SSL_SOCK_ST_TO_CRTERROR(ctx->xprt_st))
1557 ctx->xprt_st |= SSL_SOCK_CRTERROR_TO_ST(err);
Emeric Brunf282a812012-09-21 15:27:54 +02001558
Emeric Brun81c00f02012-09-21 14:31:21 +02001559 /* check if certificate error needs to be ignored */
Willy Tarreau07d94e42018-09-20 10:57:52 +02001560 if (__objt_listener(conn->target)->bind_conf->crt_ignerr & (1ULL << err)) {
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02001561 ssl_sock_dump_errors(conn);
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001562 ERR_clear_error();
Emeric Brun81c00f02012-09-21 14:31:21 +02001563 return 1;
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001564 }
Emeric Brun81c00f02012-09-21 14:31:21 +02001565
Willy Tarreau20879a02012-12-03 16:32:10 +01001566 conn->err_code = CO_ER_SSL_CRT_FAIL;
Emeric Brun81c00f02012-09-21 14:31:21 +02001567 return 0;
Emeric Brune64aef12012-09-21 13:15:06 +02001568}
1569
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001570static inline
1571void ssl_sock_parse_clienthello(int write_p, int version, int content_type,
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001572 const void *buf, size_t len, SSL *ssl)
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001573{
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001574 struct ssl_capture *capture;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001575 unsigned char *msg;
1576 unsigned char *end;
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001577 size_t rec_len;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001578
1579 /* This function is called for "from client" and "to server"
1580 * connections. The combination of write_p == 0 and content_type == 22
Joseph Herlant017b3da2018-11-15 09:07:59 -08001581 * is only available during "from client" connection.
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001582 */
1583
1584 /* "write_p" is set to 0 is the bytes are received messages,
1585 * otherwise it is set to 1.
1586 */
1587 if (write_p != 0)
1588 return;
1589
1590 /* content_type contains the type of message received or sent
1591 * according with the SSL/TLS protocol spec. This message is
1592 * encoded with one byte. The value 256 (two bytes) is used
1593 * for designing the SSL/TLS record layer. According with the
1594 * rfc6101, the expected message (other than 256) are:
1595 * - change_cipher_spec(20)
1596 * - alert(21)
1597 * - handshake(22)
1598 * - application_data(23)
1599 * - (255)
1600 * We are interessed by the handshake and specially the client
1601 * hello.
1602 */
1603 if (content_type != 22)
1604 return;
1605
1606 /* The message length is at least 4 bytes, containing the
1607 * message type and the message length.
1608 */
1609 if (len < 4)
1610 return;
1611
1612 /* First byte of the handshake message id the type of
1613 * message. The konwn types are:
1614 * - hello_request(0)
1615 * - client_hello(1)
1616 * - server_hello(2)
1617 * - certificate(11)
1618 * - server_key_exchange (12)
1619 * - certificate_request(13)
1620 * - server_hello_done(14)
1621 * We are interested by the client hello.
1622 */
1623 msg = (unsigned char *)buf;
1624 if (msg[0] != 1)
1625 return;
1626
1627 /* Next three bytes are the length of the message. The total length
1628 * must be this decoded length + 4. If the length given as argument
1629 * is not the same, we abort the protocol dissector.
1630 */
1631 rec_len = (msg[1] << 16) + (msg[2] << 8) + msg[3];
1632 if (len < rec_len + 4)
1633 return;
1634 msg += 4;
1635 end = msg + rec_len;
1636 if (end < msg)
1637 return;
1638
1639 /* Expect 2 bytes for protocol version (1 byte for major and 1 byte
1640 * for minor, the random, composed by 4 bytes for the unix time and
Baptiste Assmann6be139f2018-11-28 15:20:25 +01001641 * 28 bytes for unix payload. So we jump 1 + 1 + 4 + 28.
1642 */
1643 msg += 1 + 1 + 4 + 28;
1644 if (msg > end)
1645 return;
1646
1647 /* Next, is session id:
1648 * if present, we have to jump by length + 1 for the size information
1649 * if not present, we have to jump by 1 only
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001650 */
Baptiste Assmann6be139f2018-11-28 15:20:25 +01001651 if (msg[0] > 0)
1652 msg += msg[0];
1653 msg += 1;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001654 if (msg > end)
1655 return;
1656
1657 /* Next two bytes are the ciphersuite length. */
1658 if (msg + 2 > end)
1659 return;
1660 rec_len = (msg[0] << 8) + msg[1];
1661 msg += 2;
1662 if (msg + rec_len > end || msg + rec_len < msg)
1663 return;
1664
Willy Tarreaubafbe012017-11-24 17:34:44 +01001665 capture = pool_alloc_dirty(pool_head_ssl_capture);
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001666 if (!capture)
1667 return;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001668 /* Compute the xxh64 of the ciphersuite. */
1669 capture->xxh64 = XXH64(msg, rec_len, 0);
1670
1671 /* Capture the ciphersuite. */
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001672 capture->ciphersuite_len = (global_ssl.capture_cipherlist < rec_len) ?
1673 global_ssl.capture_cipherlist : rec_len;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001674 memcpy(capture->ciphersuite, msg, capture->ciphersuite_len);
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001675
1676 SSL_set_ex_data(ssl, ssl_capture_ptr_index, capture);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001677}
1678
Emeric Brun29f037d2014-04-25 19:05:36 +02001679/* Callback is called for ssl protocol analyse */
1680void ssl_sock_msgcbk(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg)
1681{
Emeric Brun29f037d2014-04-25 19:05:36 +02001682#ifdef TLS1_RT_HEARTBEAT
1683 /* test heartbeat received (write_p is set to 0
1684 for a received record) */
Willy Tarreauf51c6982014-04-25 20:02:39 +02001685 if ((content_type == TLS1_RT_HEARTBEAT) && (write_p == 0)) {
Thierry FOURNIER28962c92018-06-17 21:37:05 +02001686 struct connection *conn = SSL_get_ex_data(ssl, ssl_app_data_index);
William Lallemand7e1770b2019-05-13 14:31:34 +02001687 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
Willy Tarreauf51c6982014-04-25 20:02:39 +02001688 const unsigned char *p = buf;
1689 unsigned int payload;
1690
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001691 ctx->xprt_st |= SSL_SOCK_RECV_HEARTBEAT;
Willy Tarreauf51c6982014-04-25 20:02:39 +02001692
1693 /* Check if this is a CVE-2014-0160 exploitation attempt. */
1694 if (*p != TLS1_HB_REQUEST)
1695 return;
1696
Willy Tarreauaeed6722014-04-25 23:59:58 +02001697 if (len < 1 + 2 + 16) /* 1 type + 2 size + 0 payload + 16 padding */
Willy Tarreauf51c6982014-04-25 20:02:39 +02001698 goto kill_it;
1699
1700 payload = (p[1] * 256) + p[2];
Willy Tarreau3b2fdb62014-04-25 23:44:22 +02001701 if (3 + payload + 16 <= len)
Willy Tarreauf51c6982014-04-25 20:02:39 +02001702 return; /* OK no problem */
Willy Tarreauaeed6722014-04-25 23:59:58 +02001703 kill_it:
Willy Tarreau3b2fdb62014-04-25 23:44:22 +02001704 /* We have a clear heartbleed attack (CVE-2014-0160), the
1705 * advertised payload is larger than the advertised packet
1706 * length, so we have garbage in the buffer between the
1707 * payload and the end of the buffer (p+len). We can't know
1708 * if the SSL stack is patched, and we don't know if we can
1709 * safely wipe out the area between p+3+len and payload.
1710 * So instead, we prevent the response from being sent by
1711 * setting the max_send_fragment to 0 and we report an SSL
1712 * error, which will kill this connection. It will be reported
1713 * above as SSL_ERROR_SSL while an other handshake failure with
Willy Tarreauf51c6982014-04-25 20:02:39 +02001714 * a heartbeat message will be reported as SSL_ERROR_SYSCALL.
1715 */
Willy Tarreau3b2fdb62014-04-25 23:44:22 +02001716 ssl->max_send_fragment = 0;
Willy Tarreauf51c6982014-04-25 20:02:39 +02001717 SSLerr(SSL_F_TLS1_HEARTBEAT, SSL_R_SSL_HANDSHAKE_FAILURE);
1718 return;
1719 }
Emeric Brun29f037d2014-04-25 19:05:36 +02001720#endif
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001721 if (global_ssl.capture_cipherlist > 0)
1722 ssl_sock_parse_clienthello(write_p, version, content_type, buf, len, ssl);
Emeric Brun29f037d2014-04-25 19:05:36 +02001723}
1724
Bernard Spil13c53f82018-02-15 13:34:58 +01001725#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Olivier Houchardc7566002018-11-20 23:33:50 +01001726static int ssl_sock_srv_select_protos(SSL *s, unsigned char **out, unsigned char *outlen,
1727 const unsigned char *in, unsigned int inlen,
1728 void *arg)
1729{
1730 struct server *srv = arg;
1731
1732 if (SSL_select_next_proto(out, outlen, in, inlen, (unsigned char *)srv->ssl_ctx.npn_str,
1733 srv->ssl_ctx.npn_len) == OPENSSL_NPN_NEGOTIATED)
1734 return SSL_TLSEXT_ERR_OK;
1735 return SSL_TLSEXT_ERR_NOACK;
1736}
1737#endif
1738
1739#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02001740/* This callback is used so that the server advertises the list of
1741 * negociable protocols for NPN.
1742 */
1743static int ssl_sock_advertise_npn_protos(SSL *s, const unsigned char **data,
1744 unsigned int *len, void *arg)
1745{
Emmanuel Hocdet98263292016-12-29 18:26:15 +01001746 struct ssl_bind_conf *conf = arg;
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02001747
1748 *data = (const unsigned char *)conf->npn_str;
1749 *len = conf->npn_len;
1750 return SSL_TLSEXT_ERR_OK;
1751}
1752#endif
1753
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01001754#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02001755/* This callback is used so that the server advertises the list of
1756 * negociable protocols for ALPN.
1757 */
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01001758static int ssl_sock_advertise_alpn_protos(SSL *s, const unsigned char **out,
1759 unsigned char *outlen,
1760 const unsigned char *server,
1761 unsigned int server_len, void *arg)
Willy Tarreauab861d32013-04-02 02:30:41 +02001762{
Emmanuel Hocdet98263292016-12-29 18:26:15 +01001763 struct ssl_bind_conf *conf = arg;
Willy Tarreauab861d32013-04-02 02:30:41 +02001764
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01001765 if (SSL_select_next_proto((unsigned char**) out, outlen, (const unsigned char *)conf->alpn_str,
1766 conf->alpn_len, server, server_len) != OPENSSL_NPN_NEGOTIATED) {
1767 return SSL_TLSEXT_ERR_NOACK;
1768 }
Willy Tarreauab861d32013-04-02 02:30:41 +02001769 return SSL_TLSEXT_ERR_OK;
1770}
1771#endif
1772
Willy Tarreauc8ad3be2015-06-17 15:48:26 +02001773#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01001774#ifndef SSL_NO_GENERATE_CERTIFICATES
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001775
Christopher Faulet30548802015-06-11 13:39:32 +02001776/* Create a X509 certificate with the specified servername and serial. This
1777 * function returns a SSL_CTX object or NULL if an error occurs. */
Christopher Faulet7969a332015-10-09 11:15:03 +02001778static SSL_CTX *
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001779ssl_sock_do_create_cert(const char *servername, struct bind_conf *bind_conf, SSL *ssl)
Christopher Faulet31af49d2015-06-09 17:29:50 +02001780{
Christopher Faulet7969a332015-10-09 11:15:03 +02001781 X509 *cacert = bind_conf->ca_sign_cert;
1782 EVP_PKEY *capkey = bind_conf->ca_sign_pkey;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001783 SSL_CTX *ssl_ctx = NULL;
1784 X509 *newcrt = NULL;
1785 EVP_PKEY *pkey = NULL;
Emmanuel Hocdet15969292017-08-11 10:56:00 +02001786 SSL *tmp_ssl = NULL;
Emmanuel Hocdeta9b84022018-10-01 18:41:36 +02001787 CONF *ctmp = NULL;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001788 X509_NAME *name;
1789 const EVP_MD *digest;
1790 X509V3_CTX ctx;
1791 unsigned int i;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001792 int key_type;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001793
Christopher Faulet48a83322017-07-28 16:56:09 +02001794 /* Get the private key of the default certificate and use it */
Willy Tarreau5db847a2019-05-09 14:13:35 +02001795#if (HA_OPENSSL_VERSION_NUMBER >= 0x10002000L)
Emmanuel Hocdet15969292017-08-11 10:56:00 +02001796 pkey = SSL_CTX_get0_privatekey(bind_conf->default_ctx);
1797#else
1798 tmp_ssl = SSL_new(bind_conf->default_ctx);
1799 if (tmp_ssl)
1800 pkey = SSL_get_privatekey(tmp_ssl);
1801#endif
1802 if (!pkey)
Christopher Faulet31af49d2015-06-09 17:29:50 +02001803 goto mkcert_error;
1804
1805 /* Create the certificate */
1806 if (!(newcrt = X509_new()))
1807 goto mkcert_error;
1808
1809 /* Set version number for the certificate (X509v3) and the serial
1810 * number */
1811 if (X509_set_version(newcrt, 2L) != 1)
1812 goto mkcert_error;
Olivier Houchard2be5a4c2019-03-08 18:54:43 +01001813 ASN1_INTEGER_set(X509_get_serialNumber(newcrt), _HA_ATOMIC_ADD(&ssl_ctx_serial, 1));
Christopher Faulet31af49d2015-06-09 17:29:50 +02001814
1815 /* Set duration for the certificate */
Rosen Penev68185952018-12-14 08:47:02 -08001816 if (!X509_gmtime_adj(X509_getm_notBefore(newcrt), (long)-60*60*24) ||
1817 !X509_gmtime_adj(X509_getm_notAfter(newcrt),(long)60*60*24*365))
Christopher Faulet31af49d2015-06-09 17:29:50 +02001818 goto mkcert_error;
1819
1820 /* set public key in the certificate */
1821 if (X509_set_pubkey(newcrt, pkey) != 1)
1822 goto mkcert_error;
1823
1824 /* Set issuer name from the CA */
1825 if (!(name = X509_get_subject_name(cacert)))
1826 goto mkcert_error;
1827 if (X509_set_issuer_name(newcrt, name) != 1)
1828 goto mkcert_error;
1829
1830 /* Set the subject name using the same, but the CN */
1831 name = X509_NAME_dup(name);
1832 if (X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC,
1833 (const unsigned char *)servername,
1834 -1, -1, 0) != 1) {
1835 X509_NAME_free(name);
1836 goto mkcert_error;
1837 }
1838 if (X509_set_subject_name(newcrt, name) != 1) {
1839 X509_NAME_free(name);
1840 goto mkcert_error;
1841 }
1842 X509_NAME_free(name);
1843
1844 /* Add x509v3 extensions as specified */
Emmanuel Hocdeta9b84022018-10-01 18:41:36 +02001845 ctmp = NCONF_new(NULL);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001846 X509V3_set_ctx(&ctx, cacert, newcrt, NULL, NULL, 0);
1847 for (i = 0; i < X509V3_EXT_SIZE; i++) {
1848 X509_EXTENSION *ext;
1849
Emmanuel Hocdeta9b84022018-10-01 18:41:36 +02001850 if (!(ext = X509V3_EXT_nconf(ctmp, &ctx, x509v3_ext_names[i], x509v3_ext_values[i])))
Christopher Faulet31af49d2015-06-09 17:29:50 +02001851 goto mkcert_error;
1852 if (!X509_add_ext(newcrt, ext, -1)) {
1853 X509_EXTENSION_free(ext);
1854 goto mkcert_error;
1855 }
1856 X509_EXTENSION_free(ext);
1857 }
1858
1859 /* Sign the certificate with the CA private key */
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001860
1861 key_type = EVP_PKEY_base_id(capkey);
1862
1863 if (key_type == EVP_PKEY_DSA)
1864 digest = EVP_sha1();
1865 else if (key_type == EVP_PKEY_RSA)
Christopher Faulet31af49d2015-06-09 17:29:50 +02001866 digest = EVP_sha256();
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001867 else if (key_type == EVP_PKEY_EC)
Christopher Faulet7969a332015-10-09 11:15:03 +02001868 digest = EVP_sha256();
1869 else {
Willy Tarreau9a1ab082019-05-09 13:26:41 +02001870#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000000fL) && !defined(OPENSSL_IS_BORINGSSL)
Christopher Faulet7969a332015-10-09 11:15:03 +02001871 int nid;
1872
1873 if (EVP_PKEY_get_default_digest_nid(capkey, &nid) <= 0)
1874 goto mkcert_error;
1875 if (!(digest = EVP_get_digestbynid(nid)))
1876 goto mkcert_error;
Christopher Faulete7db2162015-10-19 13:59:24 +02001877#else
1878 goto mkcert_error;
1879#endif
Christopher Faulet7969a332015-10-09 11:15:03 +02001880 }
1881
Christopher Faulet31af49d2015-06-09 17:29:50 +02001882 if (!(X509_sign(newcrt, capkey, digest)))
1883 goto mkcert_error;
1884
1885 /* Create and set the new SSL_CTX */
1886 if (!(ssl_ctx = SSL_CTX_new(SSLv23_server_method())))
1887 goto mkcert_error;
1888 if (!SSL_CTX_use_PrivateKey(ssl_ctx, pkey))
1889 goto mkcert_error;
1890 if (!SSL_CTX_use_certificate(ssl_ctx, newcrt))
1891 goto mkcert_error;
1892 if (!SSL_CTX_check_private_key(ssl_ctx))
1893 goto mkcert_error;
1894
1895 if (newcrt) X509_free(newcrt);
Christopher Faulet7969a332015-10-09 11:15:03 +02001896
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01001897#ifndef OPENSSL_NO_DH
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001898 SSL_CTX_set_tmp_dh_callback(ssl_ctx, ssl_get_tmp_dh);
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01001899#endif
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001900#if defined(SSL_CTX_set_tmp_ecdh) && !defined(OPENSSL_NO_ECDH)
1901 {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01001902 const char *ecdhe = (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe : ECDHE_DEFAULT_CURVE);
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001903 EC_KEY *ecc;
1904 int nid;
1905
1906 if ((nid = OBJ_sn2nid(ecdhe)) == NID_undef)
1907 goto end;
1908 if (!(ecc = EC_KEY_new_by_curve_name(nid)))
1909 goto end;
1910 SSL_CTX_set_tmp_ecdh(ssl_ctx, ecc);
1911 EC_KEY_free(ecc);
1912 }
1913#endif
1914 end:
Christopher Faulet31af49d2015-06-09 17:29:50 +02001915 return ssl_ctx;
1916
1917 mkcert_error:
Emmanuel Hocdeta9b84022018-10-01 18:41:36 +02001918 if (ctmp) NCONF_free(ctmp);
Emmanuel Hocdet15969292017-08-11 10:56:00 +02001919 if (tmp_ssl) SSL_free(tmp_ssl);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001920 if (ssl_ctx) SSL_CTX_free(ssl_ctx);
1921 if (newcrt) X509_free(newcrt);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001922 return NULL;
1923}
1924
Christopher Faulet7969a332015-10-09 11:15:03 +02001925SSL_CTX *
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001926ssl_sock_create_cert(struct connection *conn, const char *servername, unsigned int key)
Christopher Faulet7969a332015-10-09 11:15:03 +02001927{
Willy Tarreau07d94e42018-09-20 10:57:52 +02001928 struct bind_conf *bind_conf = __objt_listener(conn->target)->bind_conf;
Olivier Houchard66ab4982019-02-26 18:37:15 +01001929 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001930
Olivier Houchard66ab4982019-02-26 18:37:15 +01001931 return ssl_sock_do_create_cert(servername, bind_conf, ctx->ssl);
Christopher Faulet7969a332015-10-09 11:15:03 +02001932}
1933
Christopher Faulet30548802015-06-11 13:39:32 +02001934/* Do a lookup for a certificate in the LRU cache used to store generated
Emeric Brun821bb9b2017-06-15 16:37:39 +02001935 * certificates and immediately assign it to the SSL session if not null. */
Christopher Faulet30548802015-06-11 13:39:32 +02001936SSL_CTX *
Emeric Brun821bb9b2017-06-15 16:37:39 +02001937ssl_sock_assign_generated_cert(unsigned int key, struct bind_conf *bind_conf, SSL *ssl)
Christopher Faulet30548802015-06-11 13:39:32 +02001938{
1939 struct lru64 *lru = NULL;
1940
1941 if (ssl_ctx_lru_tree) {
Willy Tarreau03f4ec42018-05-17 10:56:47 +02001942 HA_RWLOCK_WRLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001943 lru = lru64_lookup(key, ssl_ctx_lru_tree, bind_conf->ca_sign_cert, 0);
Emeric Brun821bb9b2017-06-15 16:37:39 +02001944 if (lru && lru->domain) {
1945 if (ssl)
1946 SSL_set_SSL_CTX(ssl, (SSL_CTX *)lru->data);
Willy Tarreau03f4ec42018-05-17 10:56:47 +02001947 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet30548802015-06-11 13:39:32 +02001948 return (SSL_CTX *)lru->data;
Emeric Brun821bb9b2017-06-15 16:37:39 +02001949 }
Willy Tarreau03f4ec42018-05-17 10:56:47 +02001950 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet30548802015-06-11 13:39:32 +02001951 }
1952 return NULL;
1953}
1954
Emeric Brun821bb9b2017-06-15 16:37:39 +02001955/* Same as <ssl_sock_assign_generated_cert> but without SSL session. This
1956 * function is not thread-safe, it should only be used to check if a certificate
1957 * exists in the lru cache (with no warranty it will not be removed by another
1958 * thread). It is kept for backward compatibility. */
1959SSL_CTX *
1960ssl_sock_get_generated_cert(unsigned int key, struct bind_conf *bind_conf)
1961{
1962 return ssl_sock_assign_generated_cert(key, bind_conf, NULL);
1963}
1964
Christopher Fauletd2cab922015-07-28 16:03:47 +02001965/* Set a certificate int the LRU cache used to store generated
1966 * certificate. Return 0 on success, otherwise -1 */
1967int
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001968ssl_sock_set_generated_cert(SSL_CTX *ssl_ctx, unsigned int key, struct bind_conf *bind_conf)
Christopher Faulet30548802015-06-11 13:39:32 +02001969{
1970 struct lru64 *lru = NULL;
1971
1972 if (ssl_ctx_lru_tree) {
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001973 HA_RWLOCK_WRLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001974 lru = lru64_get(key, ssl_ctx_lru_tree, bind_conf->ca_sign_cert, 0);
Emeric Brun821bb9b2017-06-15 16:37:39 +02001975 if (!lru) {
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001976 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Fauletd2cab922015-07-28 16:03:47 +02001977 return -1;
Emeric Brun821bb9b2017-06-15 16:37:39 +02001978 }
Christopher Faulet30548802015-06-11 13:39:32 +02001979 if (lru->domain && lru->data)
1980 lru->free((SSL_CTX *)lru->data);
Christopher Faulet7969a332015-10-09 11:15:03 +02001981 lru64_commit(lru, ssl_ctx, bind_conf->ca_sign_cert, 0, (void (*)(void *))SSL_CTX_free);
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001982 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Fauletd2cab922015-07-28 16:03:47 +02001983 return 0;
Christopher Faulet30548802015-06-11 13:39:32 +02001984 }
Christopher Fauletd2cab922015-07-28 16:03:47 +02001985 return -1;
Christopher Faulet30548802015-06-11 13:39:32 +02001986}
1987
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001988/* Compute the key of the certificate. */
Christopher Faulet30548802015-06-11 13:39:32 +02001989unsigned int
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001990ssl_sock_generated_cert_key(const void *data, size_t len)
Christopher Faulet30548802015-06-11 13:39:32 +02001991{
1992 return XXH32(data, len, ssl_ctx_lru_seed);
1993}
1994
Willy Tarreau2f63ef42015-10-20 15:16:01 +02001995/* Generate a cert and immediately assign it to the SSL session so that the cert's
1996 * refcount is maintained regardless of the cert's presence in the LRU cache.
1997 */
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001998static int
Christopher Faulet7969a332015-10-09 11:15:03 +02001999ssl_sock_generate_certificate(const char *servername, struct bind_conf *bind_conf, SSL *ssl)
Christopher Faulet31af49d2015-06-09 17:29:50 +02002000{
2001 X509 *cacert = bind_conf->ca_sign_cert;
Christopher Faulet31af49d2015-06-09 17:29:50 +02002002 SSL_CTX *ssl_ctx = NULL;
2003 struct lru64 *lru = NULL;
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002004 unsigned int key;
Christopher Faulet31af49d2015-06-09 17:29:50 +02002005
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002006 key = ssl_sock_generated_cert_key(servername, strlen(servername));
Christopher Faulet31af49d2015-06-09 17:29:50 +02002007 if (ssl_ctx_lru_tree) {
Christopher Faulet2a944ee2017-11-07 10:42:54 +01002008 HA_RWLOCK_WRLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002009 lru = lru64_get(key, ssl_ctx_lru_tree, cacert, 0);
Christopher Faulet31af49d2015-06-09 17:29:50 +02002010 if (lru && lru->domain)
2011 ssl_ctx = (SSL_CTX *)lru->data;
Christopher Fauletd2cab922015-07-28 16:03:47 +02002012 if (!ssl_ctx && lru) {
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002013 ssl_ctx = ssl_sock_do_create_cert(servername, bind_conf, ssl);
Christopher Faulet31af49d2015-06-09 17:29:50 +02002014 lru64_commit(lru, ssl_ctx, cacert, 0, (void (*)(void *))SSL_CTX_free);
Christopher Fauletd2cab922015-07-28 16:03:47 +02002015 }
Willy Tarreau2f63ef42015-10-20 15:16:01 +02002016 SSL_set_SSL_CTX(ssl, ssl_ctx);
Christopher Faulet2a944ee2017-11-07 10:42:54 +01002017 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002018 return 1;
Christopher Faulet31af49d2015-06-09 17:29:50 +02002019 }
Willy Tarreau2f63ef42015-10-20 15:16:01 +02002020 else {
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002021 ssl_ctx = ssl_sock_do_create_cert(servername, bind_conf, ssl);
Willy Tarreau2f63ef42015-10-20 15:16:01 +02002022 SSL_set_SSL_CTX(ssl, ssl_ctx);
2023 /* No LRU cache, this CTX will be released as soon as the session dies */
2024 SSL_CTX_free(ssl_ctx);
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002025 return 1;
Willy Tarreau2f63ef42015-10-20 15:16:01 +02002026 }
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002027 return 0;
2028}
2029static int
2030ssl_sock_generate_certificate_from_conn(struct bind_conf *bind_conf, SSL *ssl)
2031{
2032 unsigned int key;
Thierry FOURNIER28962c92018-06-17 21:37:05 +02002033 struct connection *conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002034
Willy Tarreauf5bdb642019-07-17 11:29:32 +02002035 if (conn_get_dst(conn)) {
Willy Tarreau085a1512019-07-17 14:47:35 +02002036 key = ssl_sock_generated_cert_key(conn->dst, get_addr_len(conn->dst));
Emeric Brun821bb9b2017-06-15 16:37:39 +02002037 if (ssl_sock_assign_generated_cert(key, bind_conf, ssl))
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002038 return 1;
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002039 }
2040 return 0;
Christopher Faulet31af49d2015-06-09 17:29:50 +02002041}
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002042#endif /* !defined SSL_NO_GENERATE_CERTIFICATES */
Christopher Faulet31af49d2015-06-09 17:29:50 +02002043
Willy Tarreau9a1ab082019-05-09 13:26:41 +02002044#if (HA_OPENSSL_VERSION_NUMBER < 0x1010000fL)
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002045typedef enum { SET_CLIENT, SET_SERVER } set_context_func;
2046
2047static void ctx_set_SSLv3_func(SSL_CTX *ctx, set_context_func c)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002048{
Emmanuel Hocdet23877ab2017-07-12 12:53:02 +02002049#if SSL_OP_NO_SSLv3
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002050 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, SSLv3_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002051 : SSL_CTX_set_ssl_version(ctx, SSLv3_client_method());
2052#endif
2053}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002054static void ctx_set_TLSv10_func(SSL_CTX *ctx, set_context_func c) {
2055 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, TLSv1_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002056 : SSL_CTX_set_ssl_version(ctx, TLSv1_client_method());
2057}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002058static void ctx_set_TLSv11_func(SSL_CTX *ctx, set_context_func c) {
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002059#if SSL_OP_NO_TLSv1_1
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002060 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, TLSv1_1_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002061 : SSL_CTX_set_ssl_version(ctx, TLSv1_1_client_method());
2062#endif
2063}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002064static void ctx_set_TLSv12_func(SSL_CTX *ctx, set_context_func c) {
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002065#if SSL_OP_NO_TLSv1_2
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002066 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, TLSv1_2_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002067 : SSL_CTX_set_ssl_version(ctx, TLSv1_2_client_method());
2068#endif
2069}
Bertrand Jacquina25282b2018-08-14 00:56:13 +01002070/* TLSv1.2 is the last supported version in this context. */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002071static void ctx_set_TLSv13_func(SSL_CTX *ctx, set_context_func c) {}
2072/* Unusable in this context. */
2073static void ssl_set_SSLv3_func(SSL *ssl, set_context_func c) {}
2074static void ssl_set_TLSv10_func(SSL *ssl, set_context_func c) {}
2075static void ssl_set_TLSv11_func(SSL *ssl, set_context_func c) {}
2076static void ssl_set_TLSv12_func(SSL *ssl, set_context_func c) {}
2077static void ssl_set_TLSv13_func(SSL *ssl, set_context_func c) {}
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002078#else /* openssl >= 1.1.0 */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002079typedef enum { SET_MIN, SET_MAX } set_context_func;
2080
2081static void ctx_set_SSLv3_func(SSL_CTX *ctx, set_context_func c) {
2082 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, SSL3_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002083 : SSL_CTX_set_min_proto_version(ctx, SSL3_VERSION);
2084}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002085static void ssl_set_SSLv3_func(SSL *ssl, set_context_func c) {
2086 c == SET_MAX ? SSL_set_max_proto_version(ssl, SSL3_VERSION)
2087 : SSL_set_min_proto_version(ssl, SSL3_VERSION);
2088}
2089static void ctx_set_TLSv10_func(SSL_CTX *ctx, set_context_func c) {
2090 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002091 : SSL_CTX_set_min_proto_version(ctx, TLS1_VERSION);
2092}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002093static void ssl_set_TLSv10_func(SSL *ssl, set_context_func c) {
2094 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_VERSION)
2095 : SSL_set_min_proto_version(ssl, TLS1_VERSION);
2096}
2097static void ctx_set_TLSv11_func(SSL_CTX *ctx, set_context_func c) {
2098 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_1_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002099 : SSL_CTX_set_min_proto_version(ctx, TLS1_1_VERSION);
2100}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002101static void ssl_set_TLSv11_func(SSL *ssl, set_context_func c) {
2102 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_1_VERSION)
2103 : SSL_set_min_proto_version(ssl, TLS1_1_VERSION);
2104}
2105static void ctx_set_TLSv12_func(SSL_CTX *ctx, set_context_func c) {
2106 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_2_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002107 : SSL_CTX_set_min_proto_version(ctx, TLS1_2_VERSION);
2108}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002109static void ssl_set_TLSv12_func(SSL *ssl, set_context_func c) {
2110 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_2_VERSION)
2111 : SSL_set_min_proto_version(ssl, TLS1_2_VERSION);
2112}
2113static void ctx_set_TLSv13_func(SSL_CTX *ctx, set_context_func c) {
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002114#if SSL_OP_NO_TLSv1_3
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002115 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_3_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002116 : SSL_CTX_set_min_proto_version(ctx, TLS1_3_VERSION);
2117#endif
2118}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002119static void ssl_set_TLSv13_func(SSL *ssl, set_context_func c) {
2120#if SSL_OP_NO_TLSv1_3
2121 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_3_VERSION)
2122 : SSL_set_min_proto_version(ssl, TLS1_3_VERSION);
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002123#endif
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002124}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002125#endif
2126static void ctx_set_None_func(SSL_CTX *ctx, set_context_func c) { }
2127static void ssl_set_None_func(SSL *ssl, set_context_func c) { }
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002128
2129static struct {
2130 int option;
2131 uint16_t flag;
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002132 void (*ctx_set_version)(SSL_CTX *, set_context_func);
2133 void (*ssl_set_version)(SSL *, set_context_func);
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002134 const char *name;
2135} methodVersions[] = {
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002136 {0, 0, ctx_set_None_func, ssl_set_None_func, "NONE"}, /* CONF_TLSV_NONE */
2137 {SSL_OP_NO_SSLv3, MC_SSL_O_NO_SSLV3, ctx_set_SSLv3_func, ssl_set_SSLv3_func, "SSLv3"}, /* CONF_SSLV3 */
2138 {SSL_OP_NO_TLSv1, MC_SSL_O_NO_TLSV10, ctx_set_TLSv10_func, ssl_set_TLSv10_func, "TLSv1.0"}, /* CONF_TLSV10 */
2139 {SSL_OP_NO_TLSv1_1, MC_SSL_O_NO_TLSV11, ctx_set_TLSv11_func, ssl_set_TLSv11_func, "TLSv1.1"}, /* CONF_TLSV11 */
2140 {SSL_OP_NO_TLSv1_2, MC_SSL_O_NO_TLSV12, ctx_set_TLSv12_func, ssl_set_TLSv12_func, "TLSv1.2"}, /* CONF_TLSV12 */
2141 {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 +02002142};
2143
Emmanuel Hocdet530141f2017-03-01 18:54:56 +01002144static void ssl_sock_switchctx_set(SSL *ssl, SSL_CTX *ctx)
2145{
2146 SSL_set_verify(ssl, SSL_CTX_get_verify_mode(ctx), ssl_sock_bind_verifycbk);
2147 SSL_set_client_CA_list(ssl, SSL_dup_CA_list(SSL_CTX_get_client_CA_list(ctx)));
2148 SSL_set_SSL_CTX(ssl, ctx);
2149}
2150
Willy Tarreau5db847a2019-05-09 14:13:35 +02002151#if ((HA_OPENSSL_VERSION_NUMBER >= 0x10101000L) || defined(OPENSSL_IS_BORINGSSL))
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002152
2153static int ssl_sock_switchctx_err_cbk(SSL *ssl, int *al, void *priv)
2154{
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002155 struct bind_conf *s = priv;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002156 (void)al; /* shut gcc stupid warning */
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002157
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002158 if (SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name) || s->generate_certs)
2159 return SSL_TLSEXT_ERR_OK;
2160 return SSL_TLSEXT_ERR_NOACK;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002161}
2162
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002163#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002164static int ssl_sock_switchctx_cbk(const struct ssl_early_callback_ctx *ctx)
2165{
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002166 SSL *ssl = ctx->ssl;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002167#else
2168static int ssl_sock_switchctx_cbk(SSL *ssl, int *al, void *arg)
2169{
2170#endif
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002171 struct connection *conn;
2172 struct bind_conf *s;
2173 const uint8_t *extension_data;
2174 size_t extension_len;
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002175 int has_rsa_sig = 0, has_ecdsa_sig = 0;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002176
2177 char *wildp = NULL;
2178 const uint8_t *servername;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002179 size_t servername_len;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002180 struct ebmb_node *node, *n, *node_ecdsa = NULL, *node_rsa = NULL, *node_anonymous = NULL;
Olivier Houchardc2aae742017-09-22 18:26:28 +02002181 int allow_early = 0;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002182 int i;
2183
Thierry FOURNIER28962c92018-06-17 21:37:05 +02002184 conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Willy Tarreaua8825522018-10-15 13:20:07 +02002185 s = __objt_listener(conn->target)->bind_conf;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002186
Olivier Houchard9679ac92017-10-27 14:58:08 +02002187 if (s->ssl_conf.early_data)
Olivier Houchardc2aae742017-09-22 18:26:28 +02002188 allow_early = 1;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002189#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002190 if (SSL_early_callback_ctx_extension_get(ctx, TLSEXT_TYPE_server_name,
2191 &extension_data, &extension_len)) {
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002192#else
2193 if (SSL_client_hello_get0_ext(ssl, TLSEXT_TYPE_server_name, &extension_data, &extension_len)) {
2194#endif
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002195 /*
2196 * The server_name extension was given too much extensibility when it
2197 * was written, so parsing the normal case is a bit complex.
2198 */
2199 size_t len;
2200 if (extension_len <= 2)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002201 goto abort;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002202 /* Extract the length of the supplied list of names. */
2203 len = (*extension_data++) << 8;
2204 len |= *extension_data++;
2205 if (len + 2 != extension_len)
2206 goto abort;
2207 /*
2208 * The list in practice only has a single element, so we only consider
2209 * the first one.
2210 */
2211 if (len == 0 || *extension_data++ != TLSEXT_NAMETYPE_host_name)
2212 goto abort;
2213 extension_len = len - 1;
2214 /* Now we can finally pull out the byte array with the actual hostname. */
2215 if (extension_len <= 2)
2216 goto abort;
2217 len = (*extension_data++) << 8;
2218 len |= *extension_data++;
2219 if (len == 0 || len + 2 > extension_len || len > TLSEXT_MAXLEN_host_name
2220 || memchr(extension_data, 0, len) != NULL)
2221 goto abort;
2222 servername = extension_data;
2223 servername_len = len;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002224 } else {
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002225#if (!defined SSL_NO_GENERATE_CERTIFICATES)
2226 if (s->generate_certs && ssl_sock_generate_certificate_from_conn(s, ssl)) {
Olivier Houchardc2aae742017-09-22 18:26:28 +02002227 goto allow_early;
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002228 }
2229#endif
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002230 /* without SNI extension, is the default_ctx (need SSL_TLSEXT_ERR_NOACK) */
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002231 if (!s->strict_sni) {
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002232 ssl_sock_switchctx_set(ssl, s->default_ctx);
Olivier Houchardc2aae742017-09-22 18:26:28 +02002233 goto allow_early;
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002234 }
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002235 goto abort;
2236 }
2237
2238 /* extract/check clientHello informations */
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002239#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002240 if (SSL_early_callback_ctx_extension_get(ctx, TLSEXT_TYPE_signature_algorithms, &extension_data, &extension_len)) {
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002241#else
2242 if (SSL_client_hello_get0_ext(ssl, TLSEXT_TYPE_signature_algorithms, &extension_data, &extension_len)) {
2243#endif
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002244 uint8_t sign;
2245 size_t len;
2246 if (extension_len < 2)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002247 goto abort;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002248 len = (*extension_data++) << 8;
2249 len |= *extension_data++;
2250 if (len + 2 != extension_len)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002251 goto abort;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002252 if (len % 2 != 0)
2253 goto abort;
2254 for (; len > 0; len -= 2) {
2255 extension_data++; /* hash */
2256 sign = *extension_data++;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002257 switch (sign) {
2258 case TLSEXT_signature_rsa:
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002259 has_rsa_sig = 1;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002260 break;
2261 case TLSEXT_signature_ecdsa:
2262 has_ecdsa_sig = 1;
2263 break;
2264 default:
2265 continue;
2266 }
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002267 if (has_ecdsa_sig && has_rsa_sig)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002268 break;
2269 }
2270 } else {
Bertrand Jacquina25282b2018-08-14 00:56:13 +01002271 /* without TLSEXT_TYPE_signature_algorithms extension (< TLSv1.2) */
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002272 has_rsa_sig = 1;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002273 }
2274 if (has_ecdsa_sig) { /* in very rare case: has ecdsa sign but not a ECDSA cipher */
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002275 const SSL_CIPHER *cipher;
2276 size_t len;
2277 const uint8_t *cipher_suites;
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002278 has_ecdsa_sig = 0;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002279#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002280 len = ctx->cipher_suites_len;
2281 cipher_suites = ctx->cipher_suites;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002282#else
2283 len = SSL_client_hello_get0_ciphers(ssl, &cipher_suites);
2284#endif
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002285 if (len % 2 != 0)
2286 goto abort;
2287 for (; len != 0; len -= 2, cipher_suites += 2) {
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002288#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002289 uint16_t cipher_suite = (cipher_suites[0] << 8) | cipher_suites[1];
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002290 cipher = SSL_get_cipher_by_value(cipher_suite);
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002291#else
2292 cipher = SSL_CIPHER_find(ssl, cipher_suites);
2293#endif
Emmanuel Hocdet019f9b12017-10-02 17:12:06 +02002294 if (cipher && SSL_CIPHER_get_auth_nid(cipher) == NID_auth_ecdsa) {
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002295 has_ecdsa_sig = 1;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002296 break;
2297 }
2298 }
2299 }
2300
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002301 for (i = 0; i < trash.size && i < servername_len; i++) {
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002302 trash.area[i] = tolower(servername[i]);
2303 if (!wildp && (trash.area[i] == '.'))
2304 wildp = &trash.area[i];
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002305 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002306 trash.area[i] = 0;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002307
William Lallemand150bfa82019-09-19 17:12:49 +02002308 HA_RWLOCK_RDLOCK(SNI_LOCK, &s->sni_lock);
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002309 /* lookup in full qualified names */
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002310 node = ebst_lookup(&s->sni_ctx, trash.area);
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002311
2312 /* lookup a not neg filter */
2313 for (n = node; n; n = ebmb_next_dup(n)) {
2314 if (!container_of(n, struct sni_ctx, name)->neg) {
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002315 switch(container_of(n, struct sni_ctx, name)->kinfo.sig) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002316 case TLSEXT_signature_ecdsa:
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002317 if (!node_ecdsa)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002318 node_ecdsa = n;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002319 break;
2320 case TLSEXT_signature_rsa:
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002321 if (!node_rsa)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002322 node_rsa = n;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002323 break;
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002324 default: /* TLSEXT_signature_anonymous|dsa */
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002325 if (!node_anonymous)
2326 node_anonymous = n;
2327 break;
2328 }
2329 }
2330 }
2331 if (wildp) {
2332 /* lookup in wildcards names */
2333 node = ebst_lookup(&s->sni_w_ctx, wildp);
2334 for (n = node; n; n = ebmb_next_dup(n)) {
2335 if (!container_of(n, struct sni_ctx, name)->neg) {
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002336 switch(container_of(n, struct sni_ctx, name)->kinfo.sig) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002337 case TLSEXT_signature_ecdsa:
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002338 if (!node_ecdsa)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002339 node_ecdsa = n;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002340 break;
2341 case TLSEXT_signature_rsa:
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002342 if (!node_rsa)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002343 node_rsa = n;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002344 break;
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002345 default: /* TLSEXT_signature_anonymous|dsa */
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002346 if (!node_anonymous)
2347 node_anonymous = n;
2348 break;
2349 }
2350 }
2351 }
2352 }
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002353 /* select by key_signature priority order */
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002354 node = (has_ecdsa_sig && node_ecdsa) ? node_ecdsa
2355 : ((has_rsa_sig && node_rsa) ? node_rsa
2356 : (node_anonymous ? node_anonymous
2357 : (node_ecdsa ? node_ecdsa /* no ecdsa signature case (< TLSv1.2) */
2358 : node_rsa /* no rsa signature case (far far away) */
2359 )));
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002360 if (node) {
2361 /* switch ctx */
Emmanuel Hocdet43664762017-08-09 18:26:20 +02002362 struct ssl_bind_conf *conf = container_of(node, struct sni_ctx, name)->conf;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002363 ssl_sock_switchctx_set(ssl, container_of(node, struct sni_ctx, name)->ctx);
Olivier Houchard35a63cc2017-11-02 19:04:38 +01002364 if (conf) {
2365 methodVersions[conf->ssl_methods.min].ssl_set_version(ssl, SET_MIN);
2366 methodVersions[conf->ssl_methods.max].ssl_set_version(ssl, SET_MAX);
2367 if (conf->early_data)
2368 allow_early = 1;
2369 }
William Lallemand02010472019-10-18 11:02:19 +02002370 HA_RWLOCK_RDUNLOCK(SNI_LOCK, &s->sni_lock);
Olivier Houchard35a63cc2017-11-02 19:04:38 +01002371 goto allow_early;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002372 }
William Lallemand150bfa82019-09-19 17:12:49 +02002373
William Lallemand02010472019-10-18 11:02:19 +02002374 HA_RWLOCK_RDUNLOCK(SNI_LOCK, &s->sni_lock);
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002375#if (!defined SSL_NO_GENERATE_CERTIFICATES)
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002376 if (s->generate_certs && ssl_sock_generate_certificate(trash.area, s, ssl)) {
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002377 /* switch ctx done in ssl_sock_generate_certificate */
Olivier Houchardc2aae742017-09-22 18:26:28 +02002378 goto allow_early;
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002379 }
2380#endif
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002381 if (!s->strict_sni) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002382 /* no certificate match, is the default_ctx */
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002383 ssl_sock_switchctx_set(ssl, s->default_ctx);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002384 }
Olivier Houchardc2aae742017-09-22 18:26:28 +02002385allow_early:
2386#ifdef OPENSSL_IS_BORINGSSL
2387 if (allow_early)
2388 SSL_set_early_data_enabled(ssl, 1);
2389#else
2390 if (!allow_early)
2391 SSL_set_max_early_data(ssl, 0);
2392#endif
2393 return 1;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002394 abort:
2395 /* abort handshake (was SSL_TLSEXT_ERR_ALERT_FATAL) */
2396 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002397#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002398 return ssl_select_cert_error;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002399#else
2400 *al = SSL_AD_UNRECOGNIZED_NAME;
2401 return 0;
2402#endif
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002403}
2404
2405#else /* OPENSSL_IS_BORINGSSL */
2406
Emeric Brunfc0421f2012-09-07 17:30:07 +02002407/* Sets the SSL ctx of <ssl> to match the advertised server name. Returns a
2408 * warning when no match is found, which implies the default (first) cert
2409 * will keep being used.
2410 */
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002411static int ssl_sock_switchctx_cbk(SSL *ssl, int *al, void *priv)
Emeric Brunfc0421f2012-09-07 17:30:07 +02002412{
2413 const char *servername;
2414 const char *wildp = NULL;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002415 struct ebmb_node *node, *n;
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002416 struct bind_conf *s = priv;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002417 int i;
2418 (void)al; /* shut gcc stupid warning */
2419
2420 servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
Emmanuel Hocdet65623372013-01-24 17:17:15 +01002421 if (!servername) {
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002422#if (!defined SSL_NO_GENERATE_CERTIFICATES)
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002423 if (s->generate_certs && ssl_sock_generate_certificate_from_conn(s, ssl))
2424 return SSL_TLSEXT_ERR_OK;
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002425#endif
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002426 if (s->strict_sni)
2427 return SSL_TLSEXT_ERR_ALERT_FATAL;
2428 ssl_sock_switchctx_set(ssl, s->default_ctx);
2429 return SSL_TLSEXT_ERR_NOACK;
Emmanuel Hocdet65623372013-01-24 17:17:15 +01002430 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02002431
Willy Tarreau19d14ef2012-10-29 16:51:55 +01002432 for (i = 0; i < trash.size; i++) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02002433 if (!servername[i])
2434 break;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002435 trash.area[i] = tolower(servername[i]);
2436 if (!wildp && (trash.area[i] == '.'))
2437 wildp = &trash.area[i];
Emeric Brunfc0421f2012-09-07 17:30:07 +02002438 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002439 trash.area[i] = 0;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002440
William Lallemand150bfa82019-09-19 17:12:49 +02002441 HA_RWLOCK_RDLOCK(SNI_LOCK, &s->sni_lock);
Emeric Brunfc0421f2012-09-07 17:30:07 +02002442 /* lookup in full qualified names */
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002443 node = ebst_lookup(&s->sni_ctx, trash.area);
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002444
2445 /* lookup a not neg filter */
2446 for (n = node; n; n = ebmb_next_dup(n)) {
2447 if (!container_of(n, struct sni_ctx, name)->neg) {
2448 node = n;
2449 break;
Emmanuel Hocdet65623372013-01-24 17:17:15 +01002450 }
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002451 }
2452 if (!node && wildp) {
2453 /* lookup in wildcards names */
Emeric Brunfc0421f2012-09-07 17:30:07 +02002454 node = ebst_lookup(&s->sni_w_ctx, wildp);
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002455 }
2456 if (!node || container_of(node, struct sni_ctx, name)->neg) {
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002457#if (!defined SSL_NO_GENERATE_CERTIFICATES)
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002458 if (s->generate_certs && ssl_sock_generate_certificate(servername, s, ssl)) {
2459 /* switch ctx done in ssl_sock_generate_certificate */
William Lallemand150bfa82019-09-19 17:12:49 +02002460 HA_RWLOCK_RDUNLOCK(SNI_LOCK, &s->sni_lock);
Christopher Faulet31af49d2015-06-09 17:29:50 +02002461 return SSL_TLSEXT_ERR_OK;
2462 }
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002463#endif
William Lallemand150bfa82019-09-19 17:12:49 +02002464 HA_RWLOCK_RDUNLOCK(SNI_LOCK, &s->sni_lock);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002465 if (s->strict_sni)
2466 return SSL_TLSEXT_ERR_ALERT_FATAL;
2467 ssl_sock_switchctx_set(ssl, s->default_ctx);
2468 return SSL_TLSEXT_ERR_OK;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002469 }
2470
2471 /* switch ctx */
Emmanuel Hocdet530141f2017-03-01 18:54:56 +01002472 ssl_sock_switchctx_set(ssl, container_of(node, struct sni_ctx, name)->ctx);
William Lallemand150bfa82019-09-19 17:12:49 +02002473 HA_RWLOCK_RDUNLOCK(SNI_LOCK, &s->sni_lock);
Emeric Brunfc0421f2012-09-07 17:30:07 +02002474 return SSL_TLSEXT_ERR_OK;
2475}
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002476#endif /* (!) OPENSSL_IS_BORINGSSL */
Emeric Brunfc0421f2012-09-07 17:30:07 +02002477#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
2478
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002479#ifndef OPENSSL_NO_DH
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002480
2481static DH * ssl_get_dh_1024(void)
2482{
Remi Gacogned3a341a2015-05-29 16:26:17 +02002483 static unsigned char dh1024_p[]={
2484 0xFA,0xF9,0x2A,0x22,0x2A,0xA7,0x7F,0xE1,0x67,0x4E,0x53,0xF7,
2485 0x56,0x13,0xC3,0xB1,0xE3,0x29,0x6B,0x66,0x31,0x6A,0x7F,0xB3,
2486 0xC2,0x68,0x6B,0xCB,0x1D,0x57,0x39,0x1D,0x1F,0xFF,0x1C,0xC9,
2487 0xA6,0xA4,0x98,0x82,0x31,0x5D,0x25,0xFF,0x8A,0xE0,0x73,0x96,
2488 0x81,0xC8,0x83,0x79,0xC1,0x5A,0x04,0xF8,0x37,0x0D,0xA8,0x3D,
2489 0xAE,0x74,0xBC,0xDB,0xB6,0xA4,0x75,0xD9,0x71,0x8A,0xA0,0x17,
2490 0x9E,0x2D,0xC8,0xA8,0xDF,0x2C,0x5F,0x82,0x95,0xF8,0x92,0x9B,
2491 0xA7,0x33,0x5F,0x89,0x71,0xC8,0x2D,0x6B,0x18,0x86,0xC4,0x94,
2492 0x22,0xA5,0x52,0x8D,0xF6,0xF6,0xD2,0x37,0x92,0x0F,0xA5,0xCC,
2493 0xDB,0x7B,0x1D,0x3D,0xA1,0x31,0xB7,0x80,0x8F,0x0B,0x67,0x5E,
2494 0x36,0xA5,0x60,0x0C,0xF1,0x95,0x33,0x8B,
2495 };
2496 static unsigned char dh1024_g[]={
2497 0x02,
2498 };
2499
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002500 BIGNUM *p;
2501 BIGNUM *g;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002502 DH *dh = DH_new();
2503 if (dh) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002504 p = BN_bin2bn(dh1024_p, sizeof dh1024_p, NULL);
2505 g = BN_bin2bn(dh1024_g, sizeof dh1024_g, NULL);
Remi Gacogned3a341a2015-05-29 16:26:17 +02002506
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002507 if (!p || !g) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002508 DH_free(dh);
2509 dh = NULL;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002510 } else {
2511 DH_set0_pqg(dh, p, NULL, g);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002512 }
2513 }
2514 return dh;
2515}
2516
2517static DH *ssl_get_dh_2048(void)
2518{
Remi Gacogned3a341a2015-05-29 16:26:17 +02002519 static unsigned char dh2048_p[]={
2520 0xEC,0x86,0xF8,0x70,0xA0,0x33,0x16,0xEC,0x05,0x1A,0x73,0x59,
2521 0xCD,0x1F,0x8B,0xF8,0x29,0xE4,0xD2,0xCF,0x52,0xDD,0xC2,0x24,
2522 0x8D,0xB5,0x38,0x9A,0xFB,0x5C,0xA4,0xE4,0xB2,0xDA,0xCE,0x66,
2523 0x50,0x74,0xA6,0x85,0x4D,0x4B,0x1D,0x30,0xB8,0x2B,0xF3,0x10,
2524 0xE9,0xA7,0x2D,0x05,0x71,0xE7,0x81,0xDF,0x8B,0x59,0x52,0x3B,
2525 0x5F,0x43,0x0B,0x68,0xF1,0xDB,0x07,0xBE,0x08,0x6B,0x1B,0x23,
2526 0xEE,0x4D,0xCC,0x9E,0x0E,0x43,0xA0,0x1E,0xDF,0x43,0x8C,0xEC,
2527 0xBE,0xBE,0x90,0xB4,0x51,0x54,0xB9,0x2F,0x7B,0x64,0x76,0x4E,
2528 0x5D,0xD4,0x2E,0xAE,0xC2,0x9E,0xAE,0x51,0x43,0x59,0xC7,0x77,
2529 0x9C,0x50,0x3C,0x0E,0xED,0x73,0x04,0x5F,0xF1,0x4C,0x76,0x2A,
2530 0xD8,0xF8,0xCF,0xFC,0x34,0x40,0xD1,0xB4,0x42,0x61,0x84,0x66,
2531 0x42,0x39,0x04,0xF8,0x68,0xB2,0x62,0xD7,0x55,0xED,0x1B,0x74,
2532 0x75,0x91,0xE0,0xC5,0x69,0xC1,0x31,0x5C,0xDB,0x7B,0x44,0x2E,
2533 0xCE,0x84,0x58,0x0D,0x1E,0x66,0x0C,0xC8,0x44,0x9E,0xFD,0x40,
2534 0x08,0x67,0x5D,0xFB,0xA7,0x76,0x8F,0x00,0x11,0x87,0xE9,0x93,
2535 0xF9,0x7D,0xC4,0xBC,0x74,0x55,0x20,0xD4,0x4A,0x41,0x2F,0x43,
2536 0x42,0x1A,0xC1,0xF2,0x97,0x17,0x49,0x27,0x37,0x6B,0x2F,0x88,
2537 0x7E,0x1C,0xA0,0xA1,0x89,0x92,0x27,0xD9,0x56,0x5A,0x71,0xC1,
2538 0x56,0x37,0x7E,0x3A,0x9D,0x05,0xE7,0xEE,0x5D,0x8F,0x82,0x17,
2539 0xBC,0xE9,0xC2,0x93,0x30,0x82,0xF9,0xF4,0xC9,0xAE,0x49,0xDB,
2540 0xD0,0x54,0xB4,0xD9,0x75,0x4D,0xFA,0x06,0xB8,0xD6,0x38,0x41,
2541 0xB7,0x1F,0x77,0xF3,
2542 };
2543 static unsigned char dh2048_g[]={
2544 0x02,
2545 };
2546
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002547 BIGNUM *p;
2548 BIGNUM *g;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002549 DH *dh = DH_new();
2550 if (dh) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002551 p = BN_bin2bn(dh2048_p, sizeof dh2048_p, NULL);
2552 g = BN_bin2bn(dh2048_g, sizeof dh2048_g, NULL);
Remi Gacogned3a341a2015-05-29 16:26:17 +02002553
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002554 if (!p || !g) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002555 DH_free(dh);
2556 dh = NULL;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002557 } else {
2558 DH_set0_pqg(dh, p, NULL, g);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002559 }
2560 }
2561 return dh;
2562}
2563
2564static DH *ssl_get_dh_4096(void)
2565{
Remi Gacogned3a341a2015-05-29 16:26:17 +02002566 static unsigned char dh4096_p[]={
2567 0xDE,0x16,0x94,0xCD,0x99,0x58,0x07,0xF1,0xF7,0x32,0x96,0x11,
2568 0x04,0x82,0xD4,0x84,0x72,0x80,0x99,0x06,0xCA,0xF0,0xA3,0x68,
2569 0x07,0xCE,0x64,0x50,0xE7,0x74,0x45,0x20,0x80,0x5E,0x4D,0xAD,
2570 0xA5,0xB6,0xED,0xFA,0x80,0x6C,0x3B,0x35,0xC4,0x9A,0x14,0x6B,
2571 0x32,0xBB,0xFD,0x1F,0x17,0x8E,0xB7,0x1F,0xD6,0xFA,0x3F,0x7B,
2572 0xEE,0x16,0xA5,0x62,0x33,0x0D,0xED,0xBC,0x4E,0x58,0xE5,0x47,
2573 0x4D,0xE9,0xAB,0x8E,0x38,0xD3,0x6E,0x90,0x57,0xE3,0x22,0x15,
2574 0x33,0xBD,0xF6,0x43,0x45,0xB5,0x10,0x0A,0xBE,0x2C,0xB4,0x35,
2575 0xB8,0x53,0x8D,0xAD,0xFB,0xA7,0x1F,0x85,0x58,0x41,0x7A,0x79,
2576 0x20,0x68,0xB3,0xE1,0x3D,0x08,0x76,0xBF,0x86,0x0D,0x49,0xE3,
2577 0x82,0x71,0x8C,0xB4,0x8D,0x81,0x84,0xD4,0xE7,0xBE,0x91,0xDC,
2578 0x26,0x39,0x48,0x0F,0x35,0xC4,0xCA,0x65,0xE3,0x40,0x93,0x52,
2579 0x76,0x58,0x7D,0xDD,0x51,0x75,0xDC,0x69,0x61,0xBF,0x47,0x2C,
2580 0x16,0x68,0x2D,0xC9,0x29,0xD3,0xE6,0xC0,0x99,0x48,0xA0,0x9A,
2581 0xC8,0x78,0xC0,0x6D,0x81,0x67,0x12,0x61,0x3F,0x71,0xBA,0x41,
2582 0x1F,0x6C,0x89,0x44,0x03,0xBA,0x3B,0x39,0x60,0xAA,0x28,0x55,
2583 0x59,0xAE,0xB8,0xFA,0xCB,0x6F,0xA5,0x1A,0xF7,0x2B,0xDD,0x52,
2584 0x8A,0x8B,0xE2,0x71,0xA6,0x5E,0x7E,0xD8,0x2E,0x18,0xE0,0x66,
2585 0xDF,0xDD,0x22,0x21,0x99,0x52,0x73,0xA6,0x33,0x20,0x65,0x0E,
2586 0x53,0xE7,0x6B,0x9B,0xC5,0xA3,0x2F,0x97,0x65,0x76,0xD3,0x47,
2587 0x23,0x77,0x12,0xB6,0x11,0x7B,0x24,0xED,0xF1,0xEF,0xC0,0xE2,
2588 0xA3,0x7E,0x67,0x05,0x3E,0x96,0x4D,0x45,0xC2,0x18,0xD1,0x73,
2589 0x9E,0x07,0xF3,0x81,0x6E,0x52,0x63,0xF6,0x20,0x76,0xB9,0x13,
2590 0xD2,0x65,0x30,0x18,0x16,0x09,0x16,0x9E,0x8F,0xF1,0xD2,0x10,
2591 0x5A,0xD3,0xD4,0xAF,0x16,0x61,0xDA,0x55,0x2E,0x18,0x5E,0x14,
2592 0x08,0x54,0x2E,0x2A,0x25,0xA2,0x1A,0x9B,0x8B,0x32,0xA9,0xFD,
2593 0xC2,0x48,0x96,0xE1,0x80,0xCA,0xE9,0x22,0x17,0xBB,0xCE,0x3E,
2594 0x9E,0xED,0xC7,0xF1,0x1F,0xEC,0x17,0x21,0xDC,0x7B,0x82,0x48,
2595 0x8E,0xBB,0x4B,0x9D,0x5B,0x04,0x04,0xDA,0xDB,0x39,0xDF,0x01,
2596 0x40,0xC3,0xAA,0x26,0x23,0x89,0x75,0xC6,0x0B,0xD0,0xA2,0x60,
2597 0x6A,0xF1,0xCC,0x65,0x18,0x98,0x1B,0x52,0xD2,0x74,0x61,0xCC,
2598 0xBD,0x60,0xAE,0xA3,0xA0,0x66,0x6A,0x16,0x34,0x92,0x3F,0x41,
2599 0x40,0x31,0x29,0xC0,0x2C,0x63,0xB2,0x07,0x8D,0xEB,0x94,0xB8,
2600 0xE8,0x47,0x92,0x52,0x93,0x6A,0x1B,0x7E,0x1A,0x61,0xB3,0x1B,
2601 0xF0,0xD6,0x72,0x9B,0xF1,0xB0,0xAF,0xBF,0x3E,0x65,0xEF,0x23,
2602 0x1D,0x6F,0xFF,0x70,0xCD,0x8A,0x4C,0x8A,0xA0,0x72,0x9D,0xBE,
2603 0xD4,0xBB,0x24,0x47,0x4A,0x68,0xB5,0xF5,0xC6,0xD5,0x7A,0xCD,
2604 0xCA,0x06,0x41,0x07,0xAD,0xC2,0x1E,0xE6,0x54,0xA7,0xAD,0x03,
2605 0xD9,0x12,0xC1,0x9C,0x13,0xB1,0xC9,0x0A,0x43,0x8E,0x1E,0x08,
2606 0xCE,0x50,0x82,0x73,0x5F,0xA7,0x55,0x1D,0xD9,0x59,0xAC,0xB5,
2607 0xEA,0x02,0x7F,0x6C,0x5B,0x74,0x96,0x98,0x67,0x24,0xA3,0x0F,
2608 0x15,0xFC,0xA9,0x7D,0x3E,0x67,0xD1,0x70,0xF8,0x97,0xF3,0x67,
2609 0xC5,0x8C,0x88,0x44,0x08,0x02,0xC7,0x2B,
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002610 };
Remi Gacogned3a341a2015-05-29 16:26:17 +02002611 static unsigned char dh4096_g[]={
2612 0x02,
2613 };
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002614
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002615 BIGNUM *p;
2616 BIGNUM *g;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002617 DH *dh = DH_new();
2618 if (dh) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002619 p = BN_bin2bn(dh4096_p, sizeof dh4096_p, NULL);
2620 g = BN_bin2bn(dh4096_g, sizeof dh4096_g, NULL);
Remi Gacogned3a341a2015-05-29 16:26:17 +02002621
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002622 if (!p || !g) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002623 DH_free(dh);
2624 dh = NULL;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002625 } else {
2626 DH_set0_pqg(dh, p, NULL, g);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002627 }
2628 }
2629 return dh;
2630}
2631
2632/* Returns Diffie-Hellman parameters matching the private key length
Willy Tarreauef934602016-12-22 23:12:01 +01002633 but not exceeding global_ssl.default_dh_param */
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002634static DH *ssl_get_tmp_dh(SSL *ssl, int export, int keylen)
2635{
2636 DH *dh = NULL;
2637 EVP_PKEY *pkey = SSL_get_privatekey(ssl);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002638 int type;
2639
2640 type = pkey ? EVP_PKEY_base_id(pkey) : EVP_PKEY_NONE;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002641
2642 /* The keylen supplied by OpenSSL can only be 512 or 1024.
2643 See ssl3_send_server_key_exchange() in ssl/s3_srvr.c
2644 */
2645 if (type == EVP_PKEY_RSA || type == EVP_PKEY_DSA) {
2646 keylen = EVP_PKEY_bits(pkey);
2647 }
2648
Willy Tarreauef934602016-12-22 23:12:01 +01002649 if (keylen > global_ssl.default_dh_param) {
2650 keylen = global_ssl.default_dh_param;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002651 }
2652
Remi Gacogned3a341a2015-05-29 16:26:17 +02002653 if (keylen >= 4096) {
Remi Gacogne8de54152014-07-15 11:36:40 +02002654 dh = local_dh_4096;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002655 }
2656 else if (keylen >= 2048) {
Remi Gacogne8de54152014-07-15 11:36:40 +02002657 dh = local_dh_2048;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002658 }
2659 else {
Remi Gacogne8de54152014-07-15 11:36:40 +02002660 dh = local_dh_1024;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002661 }
2662
2663 return dh;
2664}
2665
Remi Gacogne47783ef2015-05-29 15:53:22 +02002666static DH * ssl_sock_get_dh_from_file(const char *filename)
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002667{
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002668 DH *dh = NULL;
Remi Gacogne47783ef2015-05-29 15:53:22 +02002669 BIO *in = BIO_new(BIO_s_file());
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002670
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002671 if (in == NULL)
2672 goto end;
2673
Remi Gacogne47783ef2015-05-29 15:53:22 +02002674 if (BIO_read_filename(in, filename) <= 0)
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002675 goto end;
2676
Remi Gacogne47783ef2015-05-29 15:53:22 +02002677 dh = PEM_read_bio_DHparams(in, NULL, NULL, NULL);
2678
2679end:
2680 if (in)
2681 BIO_free(in);
2682
Emeric Brune1b4ed42018-08-16 15:14:12 +02002683 ERR_clear_error();
2684
Remi Gacogne47783ef2015-05-29 15:53:22 +02002685 return dh;
2686}
2687
2688int ssl_sock_load_global_dh_param_from_file(const char *filename)
2689{
2690 global_dh = ssl_sock_get_dh_from_file(filename);
2691
2692 if (global_dh) {
2693 return 0;
2694 }
2695
2696 return -1;
2697}
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002698#endif
2699
William Lallemand9117de92019-10-04 00:29:42 +02002700/* Alloc and init a ckch_inst */
2701static struct ckch_inst *ckch_inst_new()
2702{
2703 struct ckch_inst *ckch_inst;
2704
2705 ckch_inst = calloc(1, sizeof *ckch_inst);
2706 if (ckch_inst)
2707 LIST_INIT(&ckch_inst->sni_ctx);
2708
2709 return ckch_inst;
2710}
2711
2712
2713/* This function allocates a sni_ctx and adds it to the ckch_inst */
William Lallemand1d29c742019-10-04 00:53:29 +02002714static int ckch_inst_add_cert_sni(SSL_CTX *ctx, struct ckch_inst *ckch_inst,
William Lallemand9117de92019-10-04 00:29:42 +02002715 struct bind_conf *s, struct ssl_bind_conf *conf,
2716 struct pkey_info kinfo, char *name, int order)
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002717{
2718 struct sni_ctx *sc;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002719 int wild = 0, neg = 0;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002720
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002721 if (*name == '!') {
2722 neg = 1;
2723 name++;
2724 }
2725 if (*name == '*') {
2726 wild = 1;
2727 name++;
2728 }
2729 /* !* filter is a nop */
2730 if (neg && wild)
2731 return order;
2732 if (*name) {
2733 int j, len;
2734 len = strlen(name);
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002735 for (j = 0; j < len && j < trash.size; j++)
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002736 trash.area[j] = tolower(name[j]);
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002737 if (j >= trash.size)
William Lallemandfe49bb32019-10-03 23:46:33 +02002738 return -1;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002739 trash.area[j] = 0;
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002740
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002741 sc = malloc(sizeof(struct sni_ctx) + len + 1);
Thierry FOURNIER / OZON.IO7a3bd3b2016-10-06 10:35:29 +02002742 if (!sc)
William Lallemandfe49bb32019-10-03 23:46:33 +02002743 return -1;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002744 memcpy(sc->name.key, trash.area, len + 1);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002745 sc->ctx = ctx;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01002746 sc->conf = conf;
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002747 sc->kinfo = kinfo;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002748 sc->order = order++;
2749 sc->neg = neg;
William Lallemand1d29c742019-10-04 00:53:29 +02002750 sc->wild = wild;
2751 sc->name.node.leaf_p = NULL;
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01002752 if (kinfo.sig != TLSEXT_signature_anonymous)
2753 SSL_CTX_set_ex_data(ctx, ssl_pkey_info_index, &sc->kinfo);
William Lallemand9117de92019-10-04 00:29:42 +02002754
William Lallemand1d29c742019-10-04 00:53:29 +02002755 LIST_ADDQ(&ckch_inst->sni_ctx, &sc->by_ckch_inst);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002756 }
2757 return order;
2758}
2759
William Lallemand6af03992019-07-23 15:00:54 +02002760/*
William Lallemand1d29c742019-10-04 00:53:29 +02002761 * Insert the sni_ctxs that are listed in the ckch_inst, in the bind_conf's sni_ctx tree
2762 * This function can't return an error.
2763 *
2764 * *CAUTION*: The caller must lock the sni tree if called in multithreading mode
2765 */
2766static void ssl_sock_load_cert_sni(struct ckch_inst *ckch_inst, struct bind_conf *bind_conf)
2767{
2768
2769 struct sni_ctx *sc0, *sc0b, *sc1;
2770 struct ebmb_node *node;
2771
2772 list_for_each_entry_safe(sc0, sc0b, &ckch_inst->sni_ctx, by_ckch_inst) {
2773
2774 /* ignore if sc0 was already inserted in a tree */
2775 if (sc0->name.node.leaf_p)
2776 continue;
2777
2778 /* Check for duplicates. */
2779 if (sc0->wild)
2780 node = ebst_lookup(&bind_conf->sni_w_ctx, (char *)sc0->name.key);
2781 else
2782 node = ebst_lookup(&bind_conf->sni_ctx, (char *)sc0->name.key);
2783
2784 for (; node; node = ebmb_next_dup(node)) {
2785 sc1 = ebmb_entry(node, struct sni_ctx, name);
2786 if (sc1->ctx == sc0->ctx && sc1->conf == sc0->conf
2787 && sc1->neg == sc0->neg && sc1->wild == sc0->wild) {
2788 /* it's a duplicate, we should remove and free it */
2789 LIST_DEL(&sc0->by_ckch_inst);
2790 free(sc0);
2791 sc0 = NULL;
William Lallemande15029b2019-10-14 10:46:58 +02002792 break;
William Lallemand1d29c742019-10-04 00:53:29 +02002793 }
2794 }
2795
2796 /* if duplicate, ignore the insertion */
2797 if (!sc0)
2798 continue;
2799
2800 if (sc0->wild)
2801 ebst_insert(&bind_conf->sni_w_ctx, &sc0->name);
2802 else
2803 ebst_insert(&bind_conf->sni_ctx, &sc0->name);
2804 }
2805}
2806
2807/*
William Lallemande3af8fb2019-10-08 11:36:53 +02002808 * tree used to store the ckchs ordered by filename/bundle name
William Lallemand6af03992019-07-23 15:00:54 +02002809 */
William Lallemande3af8fb2019-10-08 11:36:53 +02002810struct eb_root ckchs_tree = EB_ROOT_UNIQUE;
William Lallemand6af03992019-07-23 15:00:54 +02002811
William Lallemandfa892222019-07-23 16:06:08 +02002812
Emeric Brun7a883362019-10-17 13:27:40 +02002813/* Loads Diffie-Hellman parameter from a ckchs to an SSL_CTX.
2814 * If there is no DH paramater availaible in the ckchs, the global
2815 * DH parameter is loaded into the SSL_CTX and if there is no
2816 * DH parameter available in ckchs nor in global, the default
2817 * DH parameters are applied on the SSL_CTX.
2818 * Returns a bitfield containing the flags:
2819 * ERR_FATAL in any fatal error case
2820 * ERR_ALERT if a reason of the error is availabine in err
2821 * ERR_WARN if a warning is available into err
2822 * The value 0 means there is no error nor warning and
2823 * the operation succeed.
2824 */
William Lallemandfa892222019-07-23 16:06:08 +02002825#ifndef OPENSSL_NO_DH
Emeric Brun7a883362019-10-17 13:27:40 +02002826static int ssl_sock_load_dh_params(SSL_CTX *ctx, const struct cert_key_and_chain *ckch,
2827 const char *path, char **err)
William Lallemandfa892222019-07-23 16:06:08 +02002828{
Emeric Brun7a883362019-10-17 13:27:40 +02002829 int ret = 0;
William Lallemandfa892222019-07-23 16:06:08 +02002830 DH *dh = NULL;
2831
William Lallemanda8c73742019-07-31 18:31:34 +02002832 if (ckch && ckch->dh) {
William Lallemandfa892222019-07-23 16:06:08 +02002833 dh = ckch->dh;
Emeric Bruna9363eb2019-10-17 14:53:03 +02002834 if (!SSL_CTX_set_tmp_dh(ctx, dh)) {
2835 memprintf(err, "%sunable to load the DH parameter specified in '%s'",
2836 err && *err ? *err : "", path);
2837#if defined(SSL_CTX_set_dh_auto)
2838 SSL_CTX_set_dh_auto(ctx, 1);
2839 memprintf(err, "%s, SSL library will use an automatically generated DH parameter.\n",
2840 err && *err ? *err : "");
2841#else
2842 memprintf(err, "%s, DH ciphers won't be available.\n",
2843 err && *err ? *err : "");
2844#endif
2845 ret |= ERR_WARN;
2846 goto end;
2847 }
William Lallemandfa892222019-07-23 16:06:08 +02002848
2849 if (ssl_dh_ptr_index >= 0) {
2850 /* store a pointer to the DH params to avoid complaining about
2851 ssl-default-dh-param not being set for this SSL_CTX */
2852 SSL_CTX_set_ex_data(ctx, ssl_dh_ptr_index, dh);
2853 }
2854 }
2855 else if (global_dh) {
Emeric Bruna9363eb2019-10-17 14:53:03 +02002856 if (!SSL_CTX_set_tmp_dh(ctx, global_dh)) {
2857 memprintf(err, "%sunable to use the global DH parameter for certificate '%s'",
2858 err && *err ? *err : "", path);
2859#if defined(SSL_CTX_set_dh_auto)
2860 SSL_CTX_set_dh_auto(ctx, 1);
2861 memprintf(err, "%s, SSL library will use an automatically generated DH parameter.\n",
2862 err && *err ? *err : "");
2863#else
2864 memprintf(err, "%s, DH ciphers won't be available.\n",
2865 err && *err ? *err : "");
2866#endif
2867 ret |= ERR_WARN;
2868 goto end;
2869 }
William Lallemandfa892222019-07-23 16:06:08 +02002870 }
2871 else {
2872 /* Clear openssl global errors stack */
2873 ERR_clear_error();
2874
2875 if (global_ssl.default_dh_param <= 1024) {
2876 /* we are limited to DH parameter of 1024 bits anyway */
2877 if (local_dh_1024 == NULL)
2878 local_dh_1024 = ssl_get_dh_1024();
2879
Emeric Brun7a883362019-10-17 13:27:40 +02002880 if (local_dh_1024 == NULL) {
2881 memprintf(err, "%sunable to load default 1024 bits DH parameter for certificate '%s'.\n",
2882 err && *err ? *err : "", path);
2883 ret |= ERR_ALERT | ERR_FATAL;
William Lallemandfa892222019-07-23 16:06:08 +02002884 goto end;
Emeric Brun7a883362019-10-17 13:27:40 +02002885 }
William Lallemandfa892222019-07-23 16:06:08 +02002886
Emeric Bruna9363eb2019-10-17 14:53:03 +02002887 if (!SSL_CTX_set_tmp_dh(ctx, local_dh_1024)) {
2888 memprintf(err, "%sunable to load default 1024 bits DH parameter for certificate '%s'.\n",
2889 err && *err ? *err : "", path);
2890#if defined(SSL_CTX_set_dh_auto)
2891 SSL_CTX_set_dh_auto(ctx, 1);
2892 memprintf(err, "%s, SSL library will use an automatically generated DH parameter.\n",
2893 err && *err ? *err : "");
2894#else
2895 memprintf(err, "%s, DH ciphers won't be available.\n",
2896 err && *err ? *err : "");
2897#endif
2898 ret |= ERR_WARN;
2899 goto end;
2900 }
William Lallemandfa892222019-07-23 16:06:08 +02002901 }
2902 else {
2903 SSL_CTX_set_tmp_dh_callback(ctx, ssl_get_tmp_dh);
2904 }
William Lallemandfa892222019-07-23 16:06:08 +02002905 }
2906
2907end:
William Lallemandfa892222019-07-23 16:06:08 +02002908 return ret;
2909}
2910#endif
yanbzhu08ce6ab2015-12-02 13:01:29 -05002911
yanbzhu488a4d22015-12-01 15:16:07 -05002912/* Frees the contents of a cert_key_and_chain
2913 */
2914static void ssl_sock_free_cert_key_and_chain_contents(struct cert_key_and_chain *ckch)
2915{
yanbzhu488a4d22015-12-01 15:16:07 -05002916 if (!ckch)
2917 return;
2918
2919 /* Free the certificate and set pointer to NULL */
2920 if (ckch->cert)
2921 X509_free(ckch->cert);
2922 ckch->cert = NULL;
2923
2924 /* Free the key and set pointer to NULL */
2925 if (ckch->key)
2926 EVP_PKEY_free(ckch->key);
2927 ckch->key = NULL;
2928
2929 /* Free each certificate in the chain */
Emmanuel Hocdet9246f8b2018-11-30 16:00:21 +01002930 if (ckch->chain)
2931 sk_X509_pop_free(ckch->chain, X509_free);
2932 ckch->chain = NULL;
yanbzhu488a4d22015-12-01 15:16:07 -05002933
2934}
2935
2936/* checks if a key and cert exists in the ckch
2937 */
William Lallemand1633e392019-09-30 12:58:13 +02002938#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
yanbzhu488a4d22015-12-01 15:16:07 -05002939static int ssl_sock_is_ckch_valid(struct cert_key_and_chain *ckch)
2940{
2941 return (ckch->cert != NULL && ckch->key != NULL);
2942}
William Lallemand1633e392019-09-30 12:58:13 +02002943#endif
yanbzhu488a4d22015-12-01 15:16:07 -05002944
William Lallemandf9568fc2019-10-16 18:27:58 +02002945/*
2946 * return 0 on success or != 0 on failure
2947 */
2948static int ssl_sock_load_issuer_file_into_ckch(const char *path, char *buf, struct cert_key_and_chain *ckch, char **err)
2949{
2950 int ret = 1;
2951 BIO *in = NULL;
2952 X509 *issuer;
2953
2954 if (buf) {
2955 /* reading from a buffer */
2956 in = BIO_new_mem_buf(buf, -1);
2957 if (in == NULL) {
2958 memprintf(err, "%sCan't allocate memory\n", err && *err ? *err : "");
2959 goto end;
2960 }
2961
2962 } else {
2963 /* reading from a file */
2964 in = BIO_new(BIO_s_file());
2965 if (in == NULL)
2966 goto end;
2967
2968 if (BIO_read_filename(in, path) <= 0)
2969 goto end;
2970 }
2971
2972 issuer = PEM_read_bio_X509_AUX(in, NULL, NULL, NULL);
2973 if (!issuer) {
2974 memprintf(err, "%s'%s' cannot be read or parsed'.\n",
2975 *err ? *err : "", path);
2976 goto end;
2977 }
2978 ret = 0;
2979 ckch->ocsp_issuer = issuer;
2980
2981end:
2982
2983 ERR_clear_error();
2984 if (in)
2985 BIO_free(in);
2986
2987 return ret;
2988}
2989
William Lallemand96a9c972019-10-17 11:56:17 +02002990
2991/*
2992 * Try to load a PEM file from a <path> or a buffer <buf>
2993 * The PEM must contain at least a Private Key and a Certificate,
2994 * It could contain a DH and a certificate chain.
yanbzhu488a4d22015-12-01 15:16:07 -05002995 *
William Lallemand96a9c972019-10-17 11:56:17 +02002996 * If it failed you should not attempt to use the ckch but free it.
2997 *
2998 * Return 0 on success or != 0 on failure
yanbzhu488a4d22015-12-01 15:16:07 -05002999 */
William Lallemand96a9c972019-10-17 11:56:17 +02003000static int ssl_sock_load_pem_into_ckch(const char *path, char *buf, struct cert_key_and_chain *ckch , char **err)
yanbzhu488a4d22015-12-01 15:16:07 -05003001{
William Lallemandf11365b2019-09-19 14:25:58 +02003002 BIO *in = NULL;
yanbzhu488a4d22015-12-01 15:16:07 -05003003 int ret = 1;
William Lallemand96a9c972019-10-17 11:56:17 +02003004 X509 *ca = NULL;
3005 X509 *cert = NULL;
3006 EVP_PKEY *key = NULL;
3007 DH *dh;
3008
3009 if (buf) {
3010 /* reading from a buffer */
3011 in = BIO_new_mem_buf(buf, -1);
3012 if (in == NULL) {
3013 memprintf(err, "%sCan't allocate memory\n", err && *err ? *err : "");
3014 goto end;
3015 }
yanbzhu488a4d22015-12-01 15:16:07 -05003016
William Lallemand96a9c972019-10-17 11:56:17 +02003017 } else {
3018 /* reading from a file */
William Lallemandf11365b2019-09-19 14:25:58 +02003019 in = BIO_new(BIO_s_file());
3020 if (in == NULL)
3021 goto end;
yanbzhu488a4d22015-12-01 15:16:07 -05003022
William Lallemandf11365b2019-09-19 14:25:58 +02003023 if (BIO_read_filename(in, path) <= 0)
3024 goto end;
William Lallemandf11365b2019-09-19 14:25:58 +02003025 }
yanbzhu488a4d22015-12-01 15:16:07 -05003026
yanbzhu488a4d22015-12-01 15:16:07 -05003027 /* Read Private Key */
William Lallemand96a9c972019-10-17 11:56:17 +02003028 key = PEM_read_bio_PrivateKey(in, NULL, NULL, NULL);
3029 if (key == NULL) {
yanbzhu488a4d22015-12-01 15:16:07 -05003030 memprintf(err, "%sunable to load private key from file '%s'.\n",
William Lallemand96a9c972019-10-17 11:56:17 +02003031 err && *err ? *err : "", path);
yanbzhu488a4d22015-12-01 15:16:07 -05003032 goto end;
3033 }
3034
Emmanuel Hocdet54227d82019-07-30 17:04:01 +02003035#ifndef OPENSSL_NO_DH
William Lallemandfa892222019-07-23 16:06:08 +02003036 /* Seek back to beginning of file */
3037 if (BIO_reset(in) == -1) {
3038 memprintf(err, "%san error occurred while reading the file '%s'.\n",
3039 err && *err ? *err : "", path);
3040 goto end;
3041 }
3042
William Lallemand96a9c972019-10-17 11:56:17 +02003043 dh = PEM_read_bio_DHparams(in, NULL, NULL, NULL);
3044 /* no need to return an error there, dh is not mandatory */
3045
3046 if (dh) {
3047 if (ckch->dh)
3048 DH_free(ckch->dh);
3049 ckch->dh = dh;
3050 }
3051
Emmanuel Hocdet54227d82019-07-30 17:04:01 +02003052#endif
William Lallemandfa892222019-07-23 16:06:08 +02003053
Willy Tarreaubb137a82016-04-06 19:02:38 +02003054 /* Seek back to beginning of file */
Thierry FOURNIER / OZON.IOd44ea3f2016-10-14 00:49:21 +02003055 if (BIO_reset(in) == -1) {
3056 memprintf(err, "%san error occurred while reading the file '%s'.\n",
3057 err && *err ? *err : "", path);
3058 goto end;
3059 }
Willy Tarreaubb137a82016-04-06 19:02:38 +02003060
3061 /* Read Certificate */
William Lallemand96a9c972019-10-17 11:56:17 +02003062 cert = PEM_read_bio_X509_AUX(in, NULL, NULL, NULL);
3063 if (cert == NULL) {
Willy Tarreaubb137a82016-04-06 19:02:38 +02003064 memprintf(err, "%sunable to load certificate from file '%s'.\n",
William Lallemand96a9c972019-10-17 11:56:17 +02003065 err && *err ? *err : "", path);
Willy Tarreaubb137a82016-04-06 19:02:38 +02003066 goto end;
3067 }
3068
William Lallemand96a9c972019-10-17 11:56:17 +02003069 if (!X509_check_private_key(cert, key)) {
Emmanuel Hocdet03e09f32019-07-30 14:21:25 +02003070 memprintf(err, "%sinconsistencies between private key and certificate loaded from PEM file '%s'.\n",
William Lallemand96a9c972019-10-17 11:56:17 +02003071 err && *err ? *err : "", path);
Emmanuel Hocdet03e09f32019-07-30 14:21:25 +02003072 goto end;
3073 }
3074
William Lallemand96a9c972019-10-17 11:56:17 +02003075 /* Key and Cert are good, we can use them in the ckch */
3076 if (ckch->key) /* free the previous key */
3077 EVP_PKEY_free(ckch->key);
3078 ckch->key = key;
3079
3080 if (ckch->cert) /* free the previous cert */
3081 X509_free(ckch->cert);
3082 ckch->cert = cert;
3083
3084 /* Look for a Certificate Chain */
3085 ca = PEM_read_bio_X509(in, NULL, NULL, NULL);
3086 if (ca) {
3087 /* there is a chain a in the PEM, clean the previous one in the CKCH */
3088 if (ckch->chain) /* free the previous chain */
3089 sk_X509_pop_free(ckch->chain, X509_free);
3090 ckch->chain = sk_X509_new_null();
3091 if (!sk_X509_push(ckch->chain, ca)) {
3092 X509_free(ca);
3093 goto end;
3094 }
3095 }
3096 /* look for other crt in the chain */
Emmanuel Hocdet9246f8b2018-11-30 16:00:21 +01003097 while ((ca = PEM_read_bio_X509(in, NULL, NULL, NULL)))
3098 if (!sk_X509_push(ckch->chain, ca)) {
3099 X509_free(ca);
3100 goto end;
3101 }
yanbzhu488a4d22015-12-01 15:16:07 -05003102
yanbzhu488a4d22015-12-01 15:16:07 -05003103 ret = ERR_get_error();
3104 if (ret && (ERR_GET_LIB(ret) != ERR_LIB_PEM && ERR_GET_REASON(ret) != PEM_R_NO_START_LINE)) {
3105 memprintf(err, "%sunable to load certificate chain from file '%s'.\n",
William Lallemand96a9c972019-10-17 11:56:17 +02003106 err && *err ? *err : "", path);
yanbzhu488a4d22015-12-01 15:16:07 -05003107 goto end;
William Lallemand246c0242019-10-11 08:59:13 +02003108 }
3109
3110 ret = 0;
3111
William Lallemand96a9c972019-10-17 11:56:17 +02003112end:
William Lallemand246c0242019-10-11 08:59:13 +02003113
3114 ERR_clear_error();
William Lallemand96a9c972019-10-17 11:56:17 +02003115 if (in)
William Lallemand246c0242019-10-11 08:59:13 +02003116 BIO_free(in);
William Lallemand96a9c972019-10-17 11:56:17 +02003117 if (ret != 0) {
3118 if (key)
3119 EVP_PKEY_free(key);
3120 if (cert)
3121 X509_free(cert);
yanbzhu488a4d22015-12-01 15:16:07 -05003122 }
William Lallemanda17f4112019-10-10 15:16:44 +02003123
William Lallemand96a9c972019-10-17 11:56:17 +02003124 return ret;
3125}
3126
3127/*
3128 * Try to load in a ckch every files related to a ckch.
3129 * (PEM, sctl, ocsp, issuer etc.)
3130 *
3131 * This function is only used to load files during the configuration parsing,
3132 * it is not used with the CLI.
3133 *
3134 * This allows us to carry the contents of the file without having to read the
3135 * file multiple times. The caller must call
3136 * ssl_sock_free_cert_key_and_chain_contents.
3137 *
3138 * returns:
3139 * 0 on Success
3140 * 1 on SSL Failure
3141 */
3142static int ssl_sock_load_files_into_ckch(const char *path, struct cert_key_and_chain *ckch, char **err)
3143{
3144 int ret = 1;
3145
3146 /* try to load the PEM */
3147 if (ssl_sock_load_pem_into_ckch(path, NULL, ckch , err) != 0) {
3148 goto end;
3149 }
3150
William Lallemanda17f4112019-10-10 15:16:44 +02003151#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
3152 /* try to load the sctl file */
3153 {
3154 char fp[MAXPATHLEN+1];
3155 struct stat st;
3156
3157 snprintf(fp, MAXPATHLEN+1, "%s.sctl", path);
3158 if (stat(fp, &st) == 0) {
William Lallemand0dfae6c2019-10-16 18:06:58 +02003159 if (ssl_sock_load_sctl_from_file(fp, NULL, ckch, err)) {
William Lallemanda17f4112019-10-10 15:16:44 +02003160 memprintf(err, "%s '%s.sctl' is present but cannot be read or parsed'.\n",
3161 *err ? *err : "", fp);
3162 ret = 1;
3163 goto end;
3164 }
3165 }
3166 }
3167#endif
yanbzhu488a4d22015-12-01 15:16:07 -05003168
William Lallemand246c0242019-10-11 08:59:13 +02003169 /* try to load an ocsp response file */
3170 {
3171 char fp[MAXPATHLEN+1];
3172 struct stat st;
3173
3174 snprintf(fp, MAXPATHLEN+1, "%s.ocsp", path);
3175 if (stat(fp, &st) == 0) {
William Lallemand3b5f3602019-10-16 18:05:05 +02003176 if (ssl_sock_load_ocsp_response_from_file(fp, NULL, ckch, err)) {
William Lallemand246c0242019-10-11 08:59:13 +02003177 ret = 1;
3178 goto end;
3179 }
3180 }
3181 }
3182
3183 if (ckch->ocsp_response) {
3184 X509 *issuer;
3185 int i;
3186
3187 /* check if one of the certificate of the chain is the issuer */
3188 for (i = 0; i < sk_X509_num(ckch->chain); i++) {
3189 issuer = sk_X509_value(ckch->chain, i);
3190 if (X509_check_issued(issuer, ckch->cert) == X509_V_OK) {
3191 ckch->ocsp_issuer = issuer;
3192 break;
3193 } else
3194 issuer = NULL;
3195 }
3196
3197 /* if no issuer was found, try to load an issuer from the .issuer */
3198 if (!issuer) {
3199 struct stat st;
3200 char fp[MAXPATHLEN+1];
3201
3202 snprintf(fp, MAXPATHLEN+1, "%s.issuer", path);
3203 if (stat(fp, &st) == 0) {
William Lallemandf9568fc2019-10-16 18:27:58 +02003204 if (ssl_sock_load_issuer_file_into_ckch(fp, NULL, ckch, err)) {
William Lallemand246c0242019-10-11 08:59:13 +02003205 ret = 1;
3206 goto end;
3207 }
3208
3209 if (X509_check_issued(ckch->ocsp_issuer, ckch->cert) != X509_V_OK) {
William Lallemand786188f2019-10-15 10:05:37 +02003210 memprintf(err, "%s '%s' is not an issuer'.\n",
William Lallemand246c0242019-10-11 08:59:13 +02003211 *err ? *err : "", fp);
3212 ret = 1;
3213 goto end;
3214 }
3215 } else {
3216 memprintf(err, "%sNo issuer found, cannot use the OCSP response'.\n",
3217 *err ? *err : "");
3218 ret = 1;
3219 goto end;
3220 }
3221 }
3222 }
3223
yanbzhu488a4d22015-12-01 15:16:07 -05003224 ret = 0;
3225
3226end:
3227
3228 ERR_clear_error();
yanbzhu488a4d22015-12-01 15:16:07 -05003229
3230 /* Something went wrong in one of the reads */
3231 if (ret != 0)
3232 ssl_sock_free_cert_key_and_chain_contents(ckch);
3233
3234 return ret;
3235}
3236
3237/* Loads the info in ckch into ctx
Emeric Bruna96b5822019-10-17 13:25:14 +02003238 * Returns a bitfield containing the flags:
3239 * ERR_FATAL in any fatal error case
3240 * ERR_ALERT if the reason of the error is available in err
3241 * ERR_WARN if a warning is available into err
3242 * The value 0 means there is no error nor warning and
3243 * the operation succeed.
yanbzhu488a4d22015-12-01 15:16:07 -05003244 */
3245static int ssl_sock_put_ckch_into_ctx(const char *path, const struct cert_key_and_chain *ckch, SSL_CTX *ctx, char **err)
3246{
Emeric Bruna96b5822019-10-17 13:25:14 +02003247 int errcode = 0;
3248
yanbzhu488a4d22015-12-01 15:16:07 -05003249 if (SSL_CTX_use_PrivateKey(ctx, ckch->key) <= 0) {
3250 memprintf(err, "%sunable to load SSL private key into SSL Context '%s'.\n",
3251 err && *err ? *err : "", path);
Emeric Bruna96b5822019-10-17 13:25:14 +02003252 errcode |= ERR_ALERT | ERR_FATAL;
3253 return errcode;
yanbzhu488a4d22015-12-01 15:16:07 -05003254 }
3255
3256 if (!SSL_CTX_use_certificate(ctx, ckch->cert)) {
3257 memprintf(err, "%sunable to load SSL certificate into SSL Context '%s'.\n",
3258 err && *err ? *err : "", path);
Emeric Bruna96b5822019-10-17 13:25:14 +02003259 errcode |= ERR_ALERT | ERR_FATAL;
3260 goto end;
yanbzhu488a4d22015-12-01 15:16:07 -05003261 }
3262
yanbzhu488a4d22015-12-01 15:16:07 -05003263 /* Load all certs in the ckch into the ctx_chain for the ssl_ctx */
Emmanuel Hocdet1c65fdd2018-12-03 18:07:44 +01003264#ifdef SSL_CTX_set1_chain
Emmanuel Hocdet9246f8b2018-11-30 16:00:21 +01003265 if (!SSL_CTX_set1_chain(ctx, ckch->chain)) {
3266 memprintf(err, "%sunable to load chain certificate into SSL Context '%s'. Make sure you are linking against Openssl >= 1.0.2.\n",
3267 err && *err ? *err : "", path);
Emeric Bruna96b5822019-10-17 13:25:14 +02003268 errcode |= ERR_ALERT | ERR_FATAL;
3269 goto end;
yanbzhu488a4d22015-12-01 15:16:07 -05003270 }
Emmanuel Hocdet1c65fdd2018-12-03 18:07:44 +01003271#else
3272 { /* legacy compat (< openssl 1.0.2) */
3273 X509 *ca;
3274 while ((ca = sk_X509_shift(ckch->chain)))
3275 if (!SSL_CTX_add_extra_chain_cert(ctx, ca)) {
3276 memprintf(err, "%sunable to load chain certificate into SSL Context '%s'.\n",
3277 err && *err ? *err : "", path);
3278 X509_free(ca);
Emeric Bruna96b5822019-10-17 13:25:14 +02003279 errcode |= ERR_ALERT | ERR_FATAL;
3280 goto end;
Emmanuel Hocdet1c65fdd2018-12-03 18:07:44 +01003281 }
3282 }
3283#endif
yanbzhu488a4d22015-12-01 15:16:07 -05003284
William Lallemandfa892222019-07-23 16:06:08 +02003285#ifndef OPENSSL_NO_DH
3286 /* store a NULL pointer to indicate we have not yet loaded
3287 a custom DH param file */
3288 if (ssl_dh_ptr_index >= 0) {
3289 SSL_CTX_set_ex_data(ctx, ssl_dh_ptr_index, NULL);
3290 }
3291
Emeric Brun7a883362019-10-17 13:27:40 +02003292 errcode |= ssl_sock_load_dh_params(ctx, ckch, path, err);
3293 if (errcode & ERR_CODE) {
William Lallemandfa892222019-07-23 16:06:08 +02003294 memprintf(err, "%sunable to load DH parameters from file '%s'.\n",
3295 err && *err ? *err : "", path);
Emeric Bruna96b5822019-10-17 13:25:14 +02003296 goto end;
William Lallemandfa892222019-07-23 16:06:08 +02003297 }
3298#endif
3299
William Lallemanda17f4112019-10-10 15:16:44 +02003300#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
3301 if (sctl_ex_index >= 0 && ckch->sctl) {
3302 if (ssl_sock_load_sctl(ctx, ckch->sctl) < 0) {
3303 memprintf(err, "%s '%s.sctl' is present but cannot be read or parsed'.\n",
3304 *err ? *err : "", path);
Emeric Bruna96b5822019-10-17 13:25:14 +02003305 errcode |= ERR_ALERT | ERR_FATAL;
3306 goto end;
William Lallemanda17f4112019-10-10 15:16:44 +02003307 }
3308 }
3309#endif
3310
William Lallemand4a660132019-10-14 14:51:41 +02003311#if ((defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP) || defined OPENSSL_IS_BORINGSSL)
William Lallemand246c0242019-10-11 08:59:13 +02003312 /* Load OCSP Info into context */
3313 if (ckch->ocsp_response) {
3314 if (ssl_sock_load_ocsp(ctx, ckch) < 0) {
3315 if (err)
3316 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",
3317 *err ? *err : "", path);
Emeric Bruna96b5822019-10-17 13:25:14 +02003318 errcode |= ERR_ALERT | ERR_FATAL;
3319 goto end;
William Lallemand246c0242019-10-11 08:59:13 +02003320 }
3321 }
William Lallemand246c0242019-10-11 08:59:13 +02003322#endif
3323
Emeric Bruna96b5822019-10-17 13:25:14 +02003324 end:
3325 return errcode;
yanbzhu488a4d22015-12-01 15:16:07 -05003326}
3327
William Lallemandc4ecddf2019-07-31 16:50:08 +02003328#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
yanbzhu08ce6ab2015-12-02 13:01:29 -05003329
William Lallemand28a8fce2019-10-04 17:36:55 +02003330static int ssl_sock_populate_sni_keytypes_hplr(const char *str, struct eb_root *sni_keytypes, int key_index)
yanbzhu08ce6ab2015-12-02 13:01:29 -05003331{
3332 struct sni_keytype *s_kt = NULL;
3333 struct ebmb_node *node;
3334 int i;
3335
3336 for (i = 0; i < trash.size; i++) {
3337 if (!str[i])
3338 break;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02003339 trash.area[i] = tolower(str[i]);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003340 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +02003341 trash.area[i] = 0;
3342 node = ebst_lookup(sni_keytypes, trash.area);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003343 if (!node) {
3344 /* CN not found in tree */
3345 s_kt = malloc(sizeof(struct sni_keytype) + i + 1);
3346 /* Using memcpy here instead of strncpy.
3347 * strncpy will cause sig_abrt errors under certain versions of gcc with -O2
3348 * See: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=60792
3349 */
William Lallemand28a8fce2019-10-04 17:36:55 +02003350 if (!s_kt)
3351 return -1;
3352
Willy Tarreau843b7cb2018-07-13 10:54:26 +02003353 memcpy(s_kt->name.key, trash.area, i+1);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003354 s_kt->keytypes = 0;
3355 ebst_insert(sni_keytypes, &s_kt->name);
3356 } else {
3357 /* CN found in tree */
3358 s_kt = container_of(node, struct sni_keytype, name);
3359 }
3360
3361 /* Mark that this CN has the keytype of key_index via keytypes mask */
3362 s_kt->keytypes |= 1<<key_index;
3363
William Lallemand28a8fce2019-10-04 17:36:55 +02003364 return 0;
3365
yanbzhu08ce6ab2015-12-02 13:01:29 -05003366}
3367
William Lallemandc4ecddf2019-07-31 16:50:08 +02003368#endif
3369
William Lallemand36b84632019-07-18 19:28:17 +02003370/*
William Lallemande3af8fb2019-10-08 11:36:53 +02003371 * lookup a path into the ckchs tree.
William Lallemand6af03992019-07-23 15:00:54 +02003372 */
William Lallemande3af8fb2019-10-08 11:36:53 +02003373static inline struct ckch_store *ckchs_lookup(char *path)
William Lallemand6af03992019-07-23 15:00:54 +02003374{
3375 struct ebmb_node *eb;
3376
William Lallemande3af8fb2019-10-08 11:36:53 +02003377 eb = ebst_lookup(&ckchs_tree, path);
William Lallemand6af03992019-07-23 15:00:54 +02003378 if (!eb)
3379 return NULL;
3380
William Lallemande3af8fb2019-10-08 11:36:53 +02003381 return ebmb_entry(eb, struct ckch_store, node);
William Lallemand6af03992019-07-23 15:00:54 +02003382}
3383
3384/*
William Lallemande3af8fb2019-10-08 11:36:53 +02003385 * This function allocate a ckch_store and populate it with certificates from files.
William Lallemand36b84632019-07-18 19:28:17 +02003386 */
William Lallemande3af8fb2019-10-08 11:36:53 +02003387static struct ckch_store *ckchs_load_cert_file(char *path, int multi, char **err)
William Lallemand36b84632019-07-18 19:28:17 +02003388{
William Lallemande3af8fb2019-10-08 11:36:53 +02003389 struct ckch_store *ckchs;
William Lallemand36b84632019-07-18 19:28:17 +02003390
William Lallemande3af8fb2019-10-08 11:36:53 +02003391 ckchs = calloc(1, sizeof(*ckchs) + strlen(path) + 1);
3392 if (!ckchs) {
William Lallemand36b84632019-07-18 19:28:17 +02003393 memprintf(err, "%sunable to allocate memory.\n", err && *err ? *err : "");
3394 goto end;
3395 }
William Lallemande3af8fb2019-10-08 11:36:53 +02003396 ckchs->ckch = calloc(1, sizeof(*ckchs->ckch) * (multi ? SSL_SOCK_NUM_KEYTYPES : 1));
William Lallemand36b84632019-07-18 19:28:17 +02003397
William Lallemande3af8fb2019-10-08 11:36:53 +02003398 if (!ckchs->ckch) {
William Lallemand36b84632019-07-18 19:28:17 +02003399 memprintf(err, "%sunable to allocate memory.\n", err && *err ? *err : "");
3400 goto end;
3401 }
3402
William Lallemand9117de92019-10-04 00:29:42 +02003403 LIST_INIT(&ckchs->ckch_inst);
3404
William Lallemand36b84632019-07-18 19:28:17 +02003405 if (!multi) {
3406
William Lallemand96a9c972019-10-17 11:56:17 +02003407 if (ssl_sock_load_files_into_ckch(path, ckchs->ckch, err) == 1)
William Lallemand36b84632019-07-18 19:28:17 +02003408 goto end;
3409
William Lallemande3af8fb2019-10-08 11:36:53 +02003410 /* insert into the ckchs tree */
3411 memcpy(ckchs->path, path, strlen(path) + 1);
3412 ebst_insert(&ckchs_tree, &ckchs->node);
William Lallemand36b84632019-07-18 19:28:17 +02003413 } else {
3414 int found = 0;
William Lallemandc4ecddf2019-07-31 16:50:08 +02003415#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
3416 char fp[MAXPATHLEN+1] = {0};
3417 int n = 0;
William Lallemand36b84632019-07-18 19:28:17 +02003418
3419 /* Load all possible certs and keys */
3420 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
3421 struct stat buf;
3422 snprintf(fp, sizeof(fp), "%s.%s", path, SSL_SOCK_KEYTYPE_NAMES[n]);
3423 if (stat(fp, &buf) == 0) {
William Lallemand96a9c972019-10-17 11:56:17 +02003424 if (ssl_sock_load_files_into_ckch(fp, &ckchs->ckch[n], err) == 1)
William Lallemand36b84632019-07-18 19:28:17 +02003425 goto end;
3426 found = 1;
William Lallemande3af8fb2019-10-08 11:36:53 +02003427 ckchs->multi = 1;
William Lallemand36b84632019-07-18 19:28:17 +02003428 }
3429 }
William Lallemandc4ecddf2019-07-31 16:50:08 +02003430#endif
William Lallemand36b84632019-07-18 19:28:17 +02003431
3432 if (!found) {
William Lallemand6e5f2ce2019-08-01 14:43:20 +02003433 memprintf(err, "%sDidn't find any certificate for bundle '%s'.\n", err && *err ? *err : "", path);
William Lallemand36b84632019-07-18 19:28:17 +02003434 goto end;
3435 }
William Lallemande3af8fb2019-10-08 11:36:53 +02003436 /* insert into the ckchs tree */
3437 memcpy(ckchs->path, path, strlen(path) + 1);
3438 ebst_insert(&ckchs_tree, &ckchs->node);
William Lallemand36b84632019-07-18 19:28:17 +02003439 }
William Lallemande3af8fb2019-10-08 11:36:53 +02003440 return ckchs;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003441
William Lallemand36b84632019-07-18 19:28:17 +02003442end:
William Lallemande3af8fb2019-10-08 11:36:53 +02003443 if (ckchs) {
3444 free(ckchs->ckch);
3445 ebmb_delete(&ckchs->node);
William Lallemand6af03992019-07-23 15:00:54 +02003446 }
3447
William Lallemande3af8fb2019-10-08 11:36:53 +02003448 free(ckchs);
William Lallemand36b84632019-07-18 19:28:17 +02003449
3450 return NULL;
3451}
3452
William Lallemandc4ecddf2019-07-31 16:50:08 +02003453#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
3454
William Lallemand36b84632019-07-18 19:28:17 +02003455/*
William Lallemande3af8fb2019-10-08 11:36:53 +02003456 * Take a ckch_store which contains a multi-certificate bundle.
William Lallemand36b84632019-07-18 19:28:17 +02003457 * Group these certificates into a set of SSL_CTX*
yanbzhu08ce6ab2015-12-02 13:01:29 -05003458 * based on shared and unique CN and SAN entries. Add these SSL_CTX* to the SNI tree.
3459 *
Joseph Herlant017b3da2018-11-15 09:07:59 -08003460 * This will allow the user to explicitly group multiple cert/keys for a single purpose
yanbzhu08ce6ab2015-12-02 13:01:29 -05003461 *
Emeric Brun054563d2019-10-17 13:16:58 +02003462 * Returns a bitfield containing the flags:
3463 * ERR_FATAL in any fatal error case
3464 * ERR_ALERT if the reason of the error is available in err
3465 * ERR_WARN if a warning is available into err
William Lallemand36b84632019-07-18 19:28:17 +02003466 *
yanbzhu08ce6ab2015-12-02 13:01:29 -05003467 */
Emeric Brun054563d2019-10-17 13:16:58 +02003468static int ckch_inst_new_load_multi_store(const char *path, struct ckch_store *ckchs,
3469 struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
3470 char **sni_filter, int fcount, struct ckch_inst **ckchi, char **err)
yanbzhu08ce6ab2015-12-02 13:01:29 -05003471{
William Lallemand36b84632019-07-18 19:28:17 +02003472 int i = 0, n = 0;
3473 struct cert_key_and_chain *certs_and_keys;
William Lallemand4b989f22019-10-04 18:36:55 +02003474 struct eb_root sni_keytypes_map = EB_ROOT;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003475 struct ebmb_node *node;
3476 struct ebmb_node *next;
3477 /* Array of SSL_CTX pointers corresponding to each possible combo
3478 * of keytypes
3479 */
3480 struct key_combo_ctx key_combos[SSL_SOCK_POSSIBLE_KT_COMBOS] = { {0} };
Emeric Brun054563d2019-10-17 13:16:58 +02003481 int errcode = 0;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003482 X509_NAME *xname = NULL;
3483 char *str = NULL;
3484#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
3485 STACK_OF(GENERAL_NAME) *names = NULL;
3486#endif
William Lallemand614ca0d2019-10-07 13:52:11 +02003487 struct ckch_inst *ckch_inst;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003488
Emeric Brun054563d2019-10-17 13:16:58 +02003489 *ckchi = NULL;
3490
William Lallemande3af8fb2019-10-08 11:36:53 +02003491 if (!ckchs || !ckchs->ckch || !ckchs->multi) {
William Lallemand36b84632019-07-18 19:28:17 +02003492 memprintf(err, "%sunable to load SSL certificate file '%s' file does not exist.\n",
3493 err && *err ? *err : "", path);
Emeric Brun054563d2019-10-17 13:16:58 +02003494 return ERR_ALERT | ERR_FATAL;
William Lallemand614ca0d2019-10-07 13:52:11 +02003495 }
3496
3497 ckch_inst = ckch_inst_new();
3498 if (!ckch_inst) {
3499 memprintf(err, "%sunable to allocate SSL context for cert '%s'.\n",
3500 err && *err ? *err : "", path);
Emeric Brun054563d2019-10-17 13:16:58 +02003501 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemand614ca0d2019-10-07 13:52:11 +02003502 goto end;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003503 }
3504
William Lallemande3af8fb2019-10-08 11:36:53 +02003505 certs_and_keys = ckchs->ckch;
William Lallemand36b84632019-07-18 19:28:17 +02003506
William Lallemand150bfa82019-09-19 17:12:49 +02003507 /* at least one of the instances is using filters during the config
3508 * parsing, that's ok to inherit this during loading on CLI */
3509 ckchs->filters = !!fcount;
3510
yanbzhu08ce6ab2015-12-02 13:01:29 -05003511 /* Process each ckch and update keytypes for each CN/SAN
3512 * for example, if CN/SAN www.a.com is associated with
3513 * certs with keytype 0 and 2, then at the end of the loop,
3514 * www.a.com will have:
3515 * keyindex = 0 | 1 | 4 = 5
3516 */
3517 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
William Lallemand28a8fce2019-10-04 17:36:55 +02003518 int ret;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003519
3520 if (!ssl_sock_is_ckch_valid(&certs_and_keys[n]))
3521 continue;
3522
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003523 if (fcount) {
William Lallemand28a8fce2019-10-04 17:36:55 +02003524 for (i = 0; i < fcount; i++) {
3525 ret = ssl_sock_populate_sni_keytypes_hplr(sni_filter[i], &sni_keytypes_map, n);
3526 if (ret < 0) {
3527 memprintf(err, "%sunable to allocate SSL context.\n",
3528 err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02003529 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemand28a8fce2019-10-04 17:36:55 +02003530 goto end;
3531 }
3532 }
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003533 } else {
3534 /* A lot of the following code is OpenSSL boilerplate for processing CN's and SAN's,
3535 * so the line that contains logic is marked via comments
3536 */
3537 xname = X509_get_subject_name(certs_and_keys[n].cert);
3538 i = -1;
3539 while ((i = X509_NAME_get_index_by_NID(xname, NID_commonName, i)) != -1) {
3540 X509_NAME_ENTRY *entry = X509_NAME_get_entry(xname, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003541 ASN1_STRING *value;
3542 value = X509_NAME_ENTRY_get_data(entry);
3543 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003544 /* Important line is here */
William Lallemand28a8fce2019-10-04 17:36:55 +02003545 ret = ssl_sock_populate_sni_keytypes_hplr(str, &sni_keytypes_map, n);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003546
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003547 OPENSSL_free(str);
3548 str = NULL;
William Lallemand28a8fce2019-10-04 17:36:55 +02003549 if (ret < 0) {
3550 memprintf(err, "%sunable to allocate SSL context.\n",
3551 err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02003552 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemand28a8fce2019-10-04 17:36:55 +02003553 goto end;
3554 }
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003555 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003556 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003557
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003558 /* Do the above logic for each SAN */
yanbzhu08ce6ab2015-12-02 13:01:29 -05003559#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003560 names = X509_get_ext_d2i(certs_and_keys[n].cert, NID_subject_alt_name, NULL, NULL);
3561 if (names) {
3562 for (i = 0; i < sk_GENERAL_NAME_num(names); i++) {
3563 GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003564
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003565 if (name->type == GEN_DNS) {
3566 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
3567 /* Important line is here */
William Lallemand28a8fce2019-10-04 17:36:55 +02003568 ret = ssl_sock_populate_sni_keytypes_hplr(str, &sni_keytypes_map, n);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003569
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003570 OPENSSL_free(str);
3571 str = NULL;
William Lallemand28a8fce2019-10-04 17:36:55 +02003572 if (ret < 0) {
3573 memprintf(err, "%sunable to allocate SSL context.\n",
3574 err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02003575 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemand28a8fce2019-10-04 17:36:55 +02003576 goto end;
3577 }
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003578 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003579 }
3580 }
3581 }
3582 }
3583#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
3584 }
3585
3586 /* If no files found, return error */
3587 if (eb_is_empty(&sni_keytypes_map)) {
3588 memprintf(err, "%sunable to load SSL certificate file '%s' file does not exist.\n",
3589 err && *err ? *err : "", path);
Emeric Brun054563d2019-10-17 13:16:58 +02003590 errcode |= ERR_ALERT | ERR_FATAL;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003591 goto end;
3592 }
3593
3594 /* We now have a map of CN/SAN to keytypes that are loaded in
3595 * Iterate through the map to create the SSL_CTX's (if needed)
3596 * and add each CTX to the SNI tree
3597 *
3598 * Some math here:
Joseph Herlant017b3da2018-11-15 09:07:59 -08003599 * There are 2^n - 1 possible combinations, each unique
yanbzhu08ce6ab2015-12-02 13:01:29 -05003600 * combination is denoted by the key in the map. Each key
3601 * has a value between 1 and 2^n - 1. Conveniently, the array
3602 * of SSL_CTX* is sized 2^n. So, we can simply use the i'th
3603 * entry in the array to correspond to the unique combo (key)
3604 * associated with i. This unique key combo (i) will be associated
3605 * with combos[i-1]
3606 */
3607
3608 node = ebmb_first(&sni_keytypes_map);
3609 while (node) {
3610 SSL_CTX *cur_ctx;
Bertrand Jacquin33423092016-11-13 16:37:13 +00003611 char cur_file[MAXPATHLEN+1];
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003612 const struct pkey_info kinfo = { .sig = TLSEXT_signature_anonymous, .bits = 0 };
yanbzhu08ce6ab2015-12-02 13:01:29 -05003613
3614 str = (char *)container_of(node, struct sni_keytype, name)->name.key;
3615 i = container_of(node, struct sni_keytype, name)->keytypes;
3616 cur_ctx = key_combos[i-1].ctx;
3617
3618 if (cur_ctx == NULL) {
3619 /* need to create SSL_CTX */
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003620 cur_ctx = SSL_CTX_new(SSLv23_server_method());
yanbzhu08ce6ab2015-12-02 13:01:29 -05003621 if (cur_ctx == NULL) {
3622 memprintf(err, "%sunable to allocate SSL context.\n",
3623 err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02003624 errcode |= ERR_ALERT | ERR_FATAL;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003625 goto end;
3626 }
3627
yanbzhube2774d2015-12-10 15:07:30 -05003628 /* Load all required certs/keys/chains/OCSPs info into SSL_CTX */
yanbzhu08ce6ab2015-12-02 13:01:29 -05003629 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
3630 if (i & (1<<n)) {
3631 /* Key combo contains ckch[n] */
Bertrand Jacquin33423092016-11-13 16:37:13 +00003632 snprintf(cur_file, MAXPATHLEN+1, "%s.%s", path, SSL_SOCK_KEYTYPE_NAMES[n]);
Emeric Bruna96b5822019-10-17 13:25:14 +02003633 errcode |= ssl_sock_put_ckch_into_ctx(cur_file, &certs_and_keys[n], cur_ctx, err);
3634 if (errcode & ERR_CODE)
yanbzhu08ce6ab2015-12-02 13:01:29 -05003635 goto end;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003636 }
3637 }
3638
yanbzhu08ce6ab2015-12-02 13:01:29 -05003639 /* Update key_combos */
3640 key_combos[i-1].ctx = cur_ctx;
3641 }
3642
3643 /* Update SNI Tree */
William Lallemand9117de92019-10-04 00:29:42 +02003644
William Lallemand1d29c742019-10-04 00:53:29 +02003645 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 +02003646 kinfo, str, key_combos[i-1].order);
3647 if (key_combos[i-1].order < 0) {
3648 memprintf(err, "%sunable to create a sni context.\n", err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02003649 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemandfe49bb32019-10-03 23:46:33 +02003650 goto end;
3651 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003652 node = ebmb_next(node);
3653 }
3654
3655
3656 /* Mark a default context if none exists, using the ctx that has the most shared keys */
3657 if (!bind_conf->default_ctx) {
3658 for (i = SSL_SOCK_POSSIBLE_KT_COMBOS - 1; i >= 0; i--) {
3659 if (key_combos[i].ctx) {
3660 bind_conf->default_ctx = key_combos[i].ctx;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003661 bind_conf->default_ssl_conf = ssl_conf;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003662 break;
3663 }
3664 }
3665 }
3666
William Lallemand614ca0d2019-10-07 13:52:11 +02003667 ckch_inst->bind_conf = bind_conf;
William Lallemand150bfa82019-09-19 17:12:49 +02003668 ckch_inst->ssl_conf = ssl_conf;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003669end:
3670
3671 if (names)
3672 sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
3673
yanbzhu08ce6ab2015-12-02 13:01:29 -05003674 node = ebmb_first(&sni_keytypes_map);
3675 while (node) {
3676 next = ebmb_next(node);
3677 ebmb_delete(node);
William Lallemand8ed5b962019-10-04 17:24:39 +02003678 free(ebmb_entry(node, struct sni_keytype, name));
yanbzhu08ce6ab2015-12-02 13:01:29 -05003679 node = next;
3680 }
3681
Emeric Brun054563d2019-10-17 13:16:58 +02003682 if (errcode & ERR_CODE && ckch_inst) {
William Lallemand0c6d12f2019-10-04 18:38:51 +02003683 struct sni_ctx *sc0, *sc0b;
3684
3685 /* free the SSL_CTX in case of error */
3686 for (i = 0; i < SSL_SOCK_POSSIBLE_KT_COMBOS; i++) {
3687 if (key_combos[i].ctx)
3688 SSL_CTX_free(key_combos[i].ctx);
3689 }
3690
3691 /* free the sni_ctx in case of error */
3692 list_for_each_entry_safe(sc0, sc0b, &ckch_inst->sni_ctx, by_ckch_inst) {
3693
3694 ebmb_delete(&sc0->name);
3695 LIST_DEL(&sc0->by_ckch_inst);
3696 free(sc0);
3697 }
William Lallemand614ca0d2019-10-07 13:52:11 +02003698 free(ckch_inst);
3699 ckch_inst = NULL;
William Lallemand0c6d12f2019-10-04 18:38:51 +02003700 }
3701
Emeric Brun054563d2019-10-17 13:16:58 +02003702 *ckchi = ckch_inst;
3703 return errcode;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003704}
3705#else
3706/* This is a dummy, that just logs an error and returns error */
Emeric Brun054563d2019-10-17 13:16:58 +02003707static int ckch_inst_new_load_multi_store(const char *path, struct ckch_store *ckchs,
3708 struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
3709 char **sni_filter, int fcount, struct ckch_inst **ckchi, char **err)
yanbzhu08ce6ab2015-12-02 13:01:29 -05003710{
3711 memprintf(err, "%sunable to stat SSL certificate from file '%s' : %s.\n",
3712 err && *err ? *err : "", path, strerror(errno));
Emeric Brun054563d2019-10-17 13:16:58 +02003713 return ERR_ALERT | ERR_FATAL;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003714}
3715
Willy Tarreau9a1ab082019-05-09 13:26:41 +02003716#endif /* #if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL: Support for loading multiple certs into a single SSL_CTX */
yanbzhu488a4d22015-12-01 15:16:07 -05003717
William Lallemand614ca0d2019-10-07 13:52:11 +02003718/*
3719 * This function allocate a ckch_inst and create its snis
Emeric Brun054563d2019-10-17 13:16:58 +02003720 *
3721 * Returns a bitfield containing the flags:
3722 * ERR_FATAL in any fatal error case
3723 * ERR_ALERT if the reason of the error is available in err
3724 * ERR_WARN if a warning is available into err
William Lallemand614ca0d2019-10-07 13:52:11 +02003725 */
Emeric Brun054563d2019-10-17 13:16:58 +02003726static int ckch_inst_new_load_store(const char *path, struct ckch_store *ckchs, struct bind_conf *bind_conf,
3727 struct ssl_bind_conf *ssl_conf, char **sni_filter, int fcount, struct ckch_inst **ckchi, char **err)
Emeric Brunfc0421f2012-09-07 17:30:07 +02003728{
William Lallemandc9402072019-05-15 15:33:54 +02003729 SSL_CTX *ctx;
William Lallemandc9402072019-05-15 15:33:54 +02003730 int i;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003731 int order = 0;
3732 X509_NAME *xname;
3733 char *str;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003734 EVP_PKEY *pkey;
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003735 struct pkey_info kinfo = { .sig = TLSEXT_signature_anonymous, .bits = 0 };
Emeric Brunfc0421f2012-09-07 17:30:07 +02003736#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
3737 STACK_OF(GENERAL_NAME) *names;
3738#endif
William Lallemand36b84632019-07-18 19:28:17 +02003739 struct cert_key_and_chain *ckch;
William Lallemand614ca0d2019-10-07 13:52:11 +02003740 struct ckch_inst *ckch_inst = NULL;
Emeric Brun054563d2019-10-17 13:16:58 +02003741 int errcode = 0;
3742
3743 *ckchi = NULL;
William Lallemanda59191b2019-05-15 16:08:56 +02003744
William Lallemande3af8fb2019-10-08 11:36:53 +02003745 if (!ckchs || !ckchs->ckch)
Emeric Brun054563d2019-10-17 13:16:58 +02003746 return ERR_FATAL;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003747
William Lallemande3af8fb2019-10-08 11:36:53 +02003748 ckch = ckchs->ckch;
William Lallemand36b84632019-07-18 19:28:17 +02003749
William Lallemand150bfa82019-09-19 17:12:49 +02003750 /* at least one of the instances is using filters during the config
3751 * parsing, that's ok to inherit this during loading on CLI */
3752 ckchs->filters = !!fcount;
3753
William Lallemandc9402072019-05-15 15:33:54 +02003754 ctx = SSL_CTX_new(SSLv23_server_method());
3755 if (!ctx) {
3756 memprintf(err, "%sunable to allocate SSL context for cert '%s'.\n",
3757 err && *err ? *err : "", path);
Emeric Brun054563d2019-10-17 13:16:58 +02003758 errcode |= ERR_ALERT | ERR_FATAL;
3759 goto error;
William Lallemandc9402072019-05-15 15:33:54 +02003760 }
3761
Emeric Bruna96b5822019-10-17 13:25:14 +02003762 errcode |= ssl_sock_put_ckch_into_ctx(path, ckch, ctx, err);
3763 if (errcode & ERR_CODE)
William Lallemand614ca0d2019-10-07 13:52:11 +02003764 goto error;
William Lallemand614ca0d2019-10-07 13:52:11 +02003765
3766 ckch_inst = ckch_inst_new();
3767 if (!ckch_inst) {
3768 memprintf(err, "%sunable to allocate SSL context for cert '%s'.\n",
3769 err && *err ? *err : "", path);
Emeric Brun054563d2019-10-17 13:16:58 +02003770 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemandd9199372019-10-04 15:37:05 +02003771 goto error;
William Lallemandc9402072019-05-15 15:33:54 +02003772 }
3773
William Lallemand36b84632019-07-18 19:28:17 +02003774 pkey = X509_get_pubkey(ckch->cert);
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003775 if (pkey) {
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003776 kinfo.bits = EVP_PKEY_bits(pkey);
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003777 switch(EVP_PKEY_base_id(pkey)) {
3778 case EVP_PKEY_RSA:
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003779 kinfo.sig = TLSEXT_signature_rsa;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003780 break;
3781 case EVP_PKEY_EC:
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003782 kinfo.sig = TLSEXT_signature_ecdsa;
3783 break;
3784 case EVP_PKEY_DSA:
3785 kinfo.sig = TLSEXT_signature_dsa;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003786 break;
3787 }
3788 EVP_PKEY_free(pkey);
3789 }
3790
Emeric Brun50bcecc2013-04-22 13:05:23 +02003791 if (fcount) {
William Lallemandfe49bb32019-10-03 23:46:33 +02003792 while (fcount--) {
William Lallemand1d29c742019-10-04 00:53:29 +02003793 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 +02003794 if (order < 0) {
3795 memprintf(err, "%sunable to create a sni context.\n", err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02003796 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemandd9199372019-10-04 15:37:05 +02003797 goto error;
William Lallemandfe49bb32019-10-03 23:46:33 +02003798 }
3799 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003800 }
3801 else {
Emeric Brunfc0421f2012-09-07 17:30:07 +02003802#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
William Lallemand36b84632019-07-18 19:28:17 +02003803 names = X509_get_ext_d2i(ckch->cert, NID_subject_alt_name, NULL, NULL);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003804 if (names) {
3805 for (i = 0; i < sk_GENERAL_NAME_num(names); i++) {
3806 GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i);
3807 if (name->type == GEN_DNS) {
3808 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
William Lallemand1d29c742019-10-04 00:53:29 +02003809 order = ckch_inst_add_cert_sni(ctx, ckch_inst, bind_conf, ssl_conf, kinfo, str, order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003810 OPENSSL_free(str);
William Lallemandfe49bb32019-10-03 23:46:33 +02003811 if (order < 0) {
3812 memprintf(err, "%sunable to create a sni context.\n", err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02003813 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemandd9199372019-10-04 15:37:05 +02003814 goto error;
William Lallemandfe49bb32019-10-03 23:46:33 +02003815 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003816 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003817 }
3818 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003819 sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003820 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003821#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
William Lallemand36b84632019-07-18 19:28:17 +02003822 xname = X509_get_subject_name(ckch->cert);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003823 i = -1;
3824 while ((i = X509_NAME_get_index_by_NID(xname, NID_commonName, i)) != -1) {
3825 X509_NAME_ENTRY *entry = X509_NAME_get_entry(xname, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003826 ASN1_STRING *value;
3827
3828 value = X509_NAME_ENTRY_get_data(entry);
3829 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
William Lallemand1d29c742019-10-04 00:53:29 +02003830 order = ckch_inst_add_cert_sni(ctx, ckch_inst, bind_conf, ssl_conf, kinfo, str, order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003831 OPENSSL_free(str);
William Lallemandfe49bb32019-10-03 23:46:33 +02003832 if (order < 0) {
3833 memprintf(err, "%sunable to create a sni context.\n", err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02003834 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemandd9199372019-10-04 15:37:05 +02003835 goto error;
William Lallemandfe49bb32019-10-03 23:46:33 +02003836 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003837 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003838 }
3839 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003840 /* we must not free the SSL_CTX anymore below, since it's already in
3841 * the tree, so it will be discovered and cleaned in time.
3842 */
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02003843
Emeric Brunfc0421f2012-09-07 17:30:07 +02003844#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
Willy Tarreau2a65ff02012-09-13 17:54:29 +02003845 if (bind_conf->default_ctx) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02003846 memprintf(err, "%sthis version of openssl cannot load multiple SSL certificates.\n",
3847 err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02003848 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemandd9199372019-10-04 15:37:05 +02003849 goto error;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003850 }
3851#endif
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003852 if (!bind_conf->default_ctx) {
Willy Tarreau2a65ff02012-09-13 17:54:29 +02003853 bind_conf->default_ctx = ctx;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003854 bind_conf->default_ssl_conf = ssl_conf;
3855 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003856
William Lallemand9117de92019-10-04 00:29:42 +02003857 /* everything succeed, the ckch instance can be used */
3858 ckch_inst->bind_conf = bind_conf;
William Lallemand150bfa82019-09-19 17:12:49 +02003859 ckch_inst->ssl_conf = ssl_conf;
William Lallemand9117de92019-10-04 00:29:42 +02003860
Emeric Brun054563d2019-10-17 13:16:58 +02003861 *ckchi = ckch_inst;
3862 return errcode;
William Lallemandd9199372019-10-04 15:37:05 +02003863
3864error:
3865 /* free the allocated sni_ctxs */
William Lallemand614ca0d2019-10-07 13:52:11 +02003866 if (ckch_inst) {
William Lallemandd9199372019-10-04 15:37:05 +02003867 struct sni_ctx *sc0, *sc0b;
3868
3869 list_for_each_entry_safe(sc0, sc0b, &ckch_inst->sni_ctx, by_ckch_inst) {
3870
3871 ebmb_delete(&sc0->name);
3872 LIST_DEL(&sc0->by_ckch_inst);
3873 free(sc0);
3874 }
William Lallemand614ca0d2019-10-07 13:52:11 +02003875 free(ckch_inst);
3876 ckch_inst = NULL;
William Lallemandd9199372019-10-04 15:37:05 +02003877 }
3878 /* We only created 1 SSL_CTX so we can free it there */
3879 SSL_CTX_free(ctx);
3880
Emeric Brun054563d2019-10-17 13:16:58 +02003881 return errcode;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003882}
3883
Willy Tarreau8c5414a2019-10-16 17:06:25 +02003884/* Returns a set of ERR_* flags possibly with an error in <err>. */
William Lallemand614ca0d2019-10-07 13:52:11 +02003885static int ssl_sock_load_ckchs(const char *path, struct ckch_store *ckchs,
3886 struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
3887 char **sni_filter, int fcount, char **err)
3888{
3889 struct ckch_inst *ckch_inst = NULL;
Emeric Brun054563d2019-10-17 13:16:58 +02003890 int errcode = 0;
William Lallemand614ca0d2019-10-07 13:52:11 +02003891
3892 /* we found the ckchs in the tree, we can use it directly */
3893 if (ckchs->multi)
Emeric Brun054563d2019-10-17 13:16:58 +02003894 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 +02003895 else
Emeric Brun054563d2019-10-17 13:16:58 +02003896 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 +02003897
Emeric Brun054563d2019-10-17 13:16:58 +02003898 if (errcode & ERR_CODE)
3899 return errcode;
William Lallemand614ca0d2019-10-07 13:52:11 +02003900
3901 ssl_sock_load_cert_sni(ckch_inst, bind_conf);
3902
3903 /* succeed, add the instance to the ckch_store's list of instance */
3904 LIST_ADDQ(&ckchs->ckch_inst, &ckch_inst->by_ckchs);
Emeric Brun054563d2019-10-17 13:16:58 +02003905 return errcode;
William Lallemand614ca0d2019-10-07 13:52:11 +02003906}
3907
3908
Willy Tarreaubbc91962019-10-16 16:42:19 +02003909/* Returns a set of ERR_* flags possibly with an error in <err>. */
Willy Tarreau03209342016-12-22 17:08:28 +01003910int ssl_sock_load_cert(char *path, struct bind_conf *bind_conf, char **err)
Emeric Brunfc0421f2012-09-07 17:30:07 +02003911{
Cyril Bonté3180f7b2015-01-25 00:16:08 +01003912 struct dirent **de_list;
3913 int i, n;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003914 DIR *dir;
3915 struct stat buf;
Willy Tarreauee2663b2012-12-06 11:36:59 +01003916 char *end;
3917 char fp[MAXPATHLEN+1];
Emeric Brunfc0421f2012-09-07 17:30:07 +02003918 int cfgerr = 0;
William Lallemande3af8fb2019-10-08 11:36:53 +02003919 struct ckch_store *ckchs;
Willy Tarreau9a1ab082019-05-09 13:26:41 +02003920#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
yanbzhu63ea8462015-12-09 13:35:14 -05003921 int is_bundle;
3922 int j;
3923#endif
William Lallemande3af8fb2019-10-08 11:36:53 +02003924 if ((ckchs = ckchs_lookup(path))) {
William Lallemande3af8fb2019-10-08 11:36:53 +02003925 /* we found the ckchs in the tree, we can use it directly */
Willy Tarreau8c5414a2019-10-16 17:06:25 +02003926 return ssl_sock_load_ckchs(path, ckchs, bind_conf, NULL, NULL, 0, err);
William Lallemand6af03992019-07-23 15:00:54 +02003927 }
3928
yanbzhu08ce6ab2015-12-02 13:01:29 -05003929 if (stat(path, &buf) == 0) {
3930 dir = opendir(path);
William Lallemand36b84632019-07-18 19:28:17 +02003931 if (!dir) {
William Lallemande3af8fb2019-10-08 11:36:53 +02003932 ckchs = ckchs_load_cert_file(path, 0, err);
3933 if (!ckchs)
Willy Tarreaubbc91962019-10-16 16:42:19 +02003934 return ERR_ALERT | ERR_FATAL;
3935
Willy Tarreau8c5414a2019-10-16 17:06:25 +02003936 return ssl_sock_load_ckchs(path, ckchs, bind_conf, NULL, NULL, 0, err);
William Lallemand36b84632019-07-18 19:28:17 +02003937 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003938
yanbzhu08ce6ab2015-12-02 13:01:29 -05003939 /* strip trailing slashes, including first one */
3940 for (end = path + strlen(path) - 1; end >= path && *end == '/'; end--)
3941 *end = 0;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003942
yanbzhu08ce6ab2015-12-02 13:01:29 -05003943 n = scandir(path, &de_list, 0, alphasort);
3944 if (n < 0) {
3945 memprintf(err, "%sunable to scan directory '%s' : %s.\n",
3946 err && *err ? *err : "", path, strerror(errno));
Willy Tarreaubbc91962019-10-16 16:42:19 +02003947 cfgerr |= ERR_ALERT | ERR_FATAL;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003948 }
3949 else {
3950 for (i = 0; i < n; i++) {
3951 struct dirent *de = de_list[i];
Emeric Brun2aab7222014-06-18 18:15:09 +02003952
yanbzhu08ce6ab2015-12-02 13:01:29 -05003953 end = strrchr(de->d_name, '.');
3954 if (end && (!strcmp(end, ".issuer") || !strcmp(end, ".ocsp") || !strcmp(end, ".sctl")))
3955 goto ignore_entry;
Cyril Bonté3180f7b2015-01-25 00:16:08 +01003956
yanbzhu08ce6ab2015-12-02 13:01:29 -05003957 snprintf(fp, sizeof(fp), "%s/%s", path, de->d_name);
3958 if (stat(fp, &buf) != 0) {
3959 memprintf(err, "%sunable to stat SSL certificate from file '%s' : %s.\n",
3960 err && *err ? *err : "", fp, strerror(errno));
Willy Tarreaubbc91962019-10-16 16:42:19 +02003961 cfgerr |= ERR_ALERT | ERR_FATAL;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003962 goto ignore_entry;
3963 }
3964 if (!S_ISREG(buf.st_mode))
3965 goto ignore_entry;
yanbzhu63ea8462015-12-09 13:35:14 -05003966
Willy Tarreau9a1ab082019-05-09 13:26:41 +02003967#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
yanbzhu63ea8462015-12-09 13:35:14 -05003968 is_bundle = 0;
3969 /* Check if current entry in directory is part of a multi-cert bundle */
3970
3971 if (end) {
3972 for (j = 0; j < SSL_SOCK_NUM_KEYTYPES; j++) {
3973 if (!strcmp(end + 1, SSL_SOCK_KEYTYPE_NAMES[j])) {
3974 is_bundle = 1;
3975 break;
3976 }
3977 }
3978
3979 if (is_bundle) {
3980 char dp[MAXPATHLEN+1] = {0}; /* this will be the filename w/o the keytype */
3981 int dp_len;
3982
3983 dp_len = end - de->d_name;
3984 snprintf(dp, dp_len + 1, "%s", de->d_name);
3985
3986 /* increment i and free de until we get to a non-bundle cert
3987 * Note here that we look at de_list[i + 1] before freeing de
3988 * this is important since ignore_entry will free de
3989 */
3990 while (i + 1 < n && !strncmp(de_list[i + 1]->d_name, dp, dp_len)) {
3991 free(de);
3992 i++;
3993 de = de_list[i];
3994 }
3995
3996 snprintf(fp, sizeof(fp), "%s/%s", path, dp);
William Lallemande3af8fb2019-10-08 11:36:53 +02003997 if ((ckchs = ckchs_lookup(fp)) == NULL)
3998 ckchs = ckchs_load_cert_file(fp, 1, err);
3999 if (!ckchs)
Willy Tarreaubbc91962019-10-16 16:42:19 +02004000 cfgerr |= ERR_ALERT | ERR_FATAL;
Willy Tarreau8c5414a2019-10-16 17:06:25 +02004001 else
4002 cfgerr |= ssl_sock_load_ckchs(path, ckchs, bind_conf, NULL, NULL, 0, err);
yanbzhu63ea8462015-12-09 13:35:14 -05004003 /* Successfully processed the bundle */
4004 goto ignore_entry;
4005 }
4006 }
4007
4008#endif
William Lallemande3af8fb2019-10-08 11:36:53 +02004009 if ((ckchs = ckchs_lookup(fp)) == NULL)
4010 ckchs = ckchs_load_cert_file(fp, 0, err);
4011 if (!ckchs)
Willy Tarreaubbc91962019-10-16 16:42:19 +02004012 cfgerr |= ERR_ALERT | ERR_FATAL;
William Lallemand614ca0d2019-10-07 13:52:11 +02004013 else
Willy Tarreau8c5414a2019-10-16 17:06:25 +02004014 cfgerr |= ssl_sock_load_ckchs(path, ckchs, bind_conf, NULL, NULL, 0, err);
William Lallemand36b84632019-07-18 19:28:17 +02004015
yanbzhu08ce6ab2015-12-02 13:01:29 -05004016ignore_entry:
4017 free(de);
Cyril Bonté3180f7b2015-01-25 00:16:08 +01004018 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05004019 free(de_list);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004020 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05004021 closedir(dir);
4022 return cfgerr;
Emeric Brunfc0421f2012-09-07 17:30:07 +02004023 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05004024
William Lallemande3af8fb2019-10-08 11:36:53 +02004025 ckchs = ckchs_load_cert_file(path, 1, err);
4026 if (!ckchs)
Willy Tarreaubbc91962019-10-16 16:42:19 +02004027 return ERR_ALERT | ERR_FATAL;
4028
Willy Tarreau8c5414a2019-10-16 17:06:25 +02004029 cfgerr |= ssl_sock_load_ckchs(path, ckchs, bind_conf, NULL, NULL, 0, err);
yanbzhu08ce6ab2015-12-02 13:01:29 -05004030
Emeric Brunfc0421f2012-09-07 17:30:07 +02004031 return cfgerr;
4032}
4033
Thierry Fournier383085f2013-01-24 14:15:43 +01004034/* Make sure openssl opens /dev/urandom before the chroot. The work is only
4035 * done once. Zero is returned if the operation fails. No error is returned
4036 * if the random is said as not implemented, because we expect that openssl
4037 * will use another method once needed.
4038 */
4039static int ssl_initialize_random()
4040{
4041 unsigned char random;
4042 static int random_initialized = 0;
4043
4044 if (!random_initialized && RAND_bytes(&random, 1) != 0)
4045 random_initialized = 1;
4046
4047 return random_initialized;
4048}
4049
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004050/* release ssl bind conf */
4051void ssl_sock_free_ssl_conf(struct ssl_bind_conf *conf)
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004052{
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004053 if (conf) {
Bernard Spil13c53f82018-02-15 13:34:58 +01004054#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004055 free(conf->npn_str);
4056 conf->npn_str = NULL;
4057#endif
4058#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
4059 free(conf->alpn_str);
4060 conf->alpn_str = NULL;
4061#endif
4062 free(conf->ca_file);
4063 conf->ca_file = NULL;
4064 free(conf->crl_file);
4065 conf->crl_file = NULL;
4066 free(conf->ciphers);
4067 conf->ciphers = NULL;
Emmanuel Hocdet839af572019-05-14 16:27:35 +02004068#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02004069 free(conf->ciphersuites);
4070 conf->ciphersuites = NULL;
4071#endif
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004072 free(conf->curves);
4073 conf->curves = NULL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004074 free(conf->ecdhe);
4075 conf->ecdhe = NULL;
4076 }
4077}
4078
Willy Tarreaubbc91962019-10-16 16:42:19 +02004079/* Returns a set of ERR_* flags possibly with an error in <err>. */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004080int ssl_sock_load_cert_list_file(char *file, struct bind_conf *bind_conf, struct proxy *curproxy, char **err)
4081{
4082 char thisline[CRT_LINESIZE];
4083 char path[MAXPATHLEN+1];
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004084 FILE *f;
yanbzhu1b04e5b2015-12-02 13:54:14 -05004085 struct stat buf;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004086 int linenum = 0;
4087 int cfgerr = 0;
William Lallemande3af8fb2019-10-08 11:36:53 +02004088 struct ckch_store *ckchs;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004089
Willy Tarreauad1731d2013-04-02 17:35:58 +02004090 if ((f = fopen(file, "r")) == NULL) {
4091 memprintf(err, "cannot open file '%s' : %s", file, strerror(errno));
Willy Tarreaubbc91962019-10-16 16:42:19 +02004092 return ERR_ALERT | ERR_FATAL;
Willy Tarreauad1731d2013-04-02 17:35:58 +02004093 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004094
4095 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004096 int arg, newarg, cur_arg, i, ssl_b = 0, ssl_e = 0;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004097 char *end;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004098 char *args[MAX_CRT_ARGS + 1];
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004099 char *line = thisline;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004100 char *crt_path;
4101 struct ssl_bind_conf *ssl_conf = NULL;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004102
4103 linenum++;
4104 end = line + strlen(line);
4105 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
4106 /* Check if we reached the limit and the last char is not \n.
4107 * Watch out for the last line without the terminating '\n'!
4108 */
Willy Tarreauad1731d2013-04-02 17:35:58 +02004109 memprintf(err, "line %d too long in file '%s', limit is %d characters",
4110 linenum, file, (int)sizeof(thisline)-1);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004111 cfgerr |= ERR_ALERT | ERR_FATAL;
Willy Tarreauad1731d2013-04-02 17:35:58 +02004112 break;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004113 }
4114
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004115 arg = 0;
Emeric Brun50bcecc2013-04-22 13:05:23 +02004116 newarg = 1;
4117 while (*line) {
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004118 if (*line == '#' || *line == '\n' || *line == '\r') {
4119 /* end of string, end of loop */
4120 *line = 0;
4121 break;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004122 } else if (isspace(*line)) {
Emeric Brun50bcecc2013-04-22 13:05:23 +02004123 newarg = 1;
4124 *line = 0;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004125 } else if (*line == '[') {
4126 if (ssl_b) {
4127 memprintf(err, "too many '[' on line %d in file '%s'.", linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004128 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004129 break;
4130 }
4131 if (!arg) {
4132 memprintf(err, "file must start with a cert on line %d in file '%s'", linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004133 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004134 break;
4135 }
4136 ssl_b = arg;
4137 newarg = 1;
4138 *line = 0;
4139 } else if (*line == ']') {
4140 if (ssl_e) {
4141 memprintf(err, "too many ']' on line %d in file '%s'.", linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004142 cfgerr |= ERR_ALERT | ERR_FATAL;
Emeric Brun50bcecc2013-04-22 13:05:23 +02004143 break;
4144 }
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004145 if (!ssl_b) {
4146 memprintf(err, "missing '[' in line %d in file '%s'.", linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004147 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004148 break;
4149 }
4150 ssl_e = arg;
4151 newarg = 1;
4152 *line = 0;
4153 } else if (newarg) {
4154 if (arg == MAX_CRT_ARGS) {
4155 memprintf(err, "too many args on line %d in file '%s'.", linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004156 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004157 break;
4158 }
Emeric Brun50bcecc2013-04-22 13:05:23 +02004159 newarg = 0;
4160 args[arg++] = line;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004161 }
Emeric Brun50bcecc2013-04-22 13:05:23 +02004162 line++;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004163 }
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02004164 if (cfgerr)
4165 break;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004166 args[arg++] = line;
Willy Tarreauad1731d2013-04-02 17:35:58 +02004167
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004168 /* empty line */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004169 if (!*args[0])
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004170 continue;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004171
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004172 crt_path = args[0];
4173 if (*crt_path != '/' && global_ssl.crt_base) {
4174 if ((strlen(global_ssl.crt_base) + 1 + strlen(crt_path)) > MAXPATHLEN) {
4175 memprintf(err, "'%s' : path too long on line %d in file '%s'",
4176 crt_path, linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004177 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004178 break;
4179 }
4180 snprintf(path, sizeof(path), "%s/%s", global_ssl.crt_base, crt_path);
4181 crt_path = path;
4182 }
4183
4184 ssl_conf = calloc(1, sizeof *ssl_conf);
4185 cur_arg = ssl_b ? ssl_b : 1;
4186 while (cur_arg < ssl_e) {
4187 newarg = 0;
4188 for (i = 0; ssl_bind_kws[i].kw != NULL; i++) {
4189 if (strcmp(ssl_bind_kws[i].kw, args[cur_arg]) == 0) {
4190 newarg = 1;
Willy Tarreaubbc91962019-10-16 16:42:19 +02004191 cfgerr |= ssl_bind_kws[i].parse(args, cur_arg, curproxy, ssl_conf, err);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004192 if (cur_arg + 1 + ssl_bind_kws[i].skip > ssl_e) {
4193 memprintf(err, "ssl args out of '[]' for %s on line %d in file '%s'",
4194 args[cur_arg], linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004195 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004196 }
4197 cur_arg += 1 + ssl_bind_kws[i].skip;
4198 break;
4199 }
4200 }
4201 if (!cfgerr && !newarg) {
4202 memprintf(err, "unknown ssl keyword %s on line %d in file '%s'.",
4203 args[cur_arg], linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004204 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004205 break;
4206 }
4207 }
Willy Tarreaubbc91962019-10-16 16:42:19 +02004208
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004209 if (cfgerr) {
4210 ssl_sock_free_ssl_conf(ssl_conf);
4211 free(ssl_conf);
4212 ssl_conf = NULL;
4213 break;
4214 }
4215
William Lallemande3af8fb2019-10-08 11:36:53 +02004216 if ((ckchs = ckchs_lookup(crt_path)) == NULL) {
William Lallemandeed4bf22019-10-10 11:38:13 +02004217 if (stat(crt_path, &buf) == 0)
William Lallemande3af8fb2019-10-08 11:36:53 +02004218 ckchs = ckchs_load_cert_file(crt_path, 0, err);
Emmanuel Hocdet1503e052019-07-31 18:30:33 +02004219 else
William Lallemande3af8fb2019-10-08 11:36:53 +02004220 ckchs = ckchs_load_cert_file(crt_path, 1, err);
yanbzhu1b04e5b2015-12-02 13:54:14 -05004221 }
4222
Willy Tarreau8c5414a2019-10-16 17:06:25 +02004223 if (!ckchs)
Willy Tarreaubbc91962019-10-16 16:42:19 +02004224 cfgerr |= ERR_ALERT | ERR_FATAL;
Willy Tarreau8c5414a2019-10-16 17:06:25 +02004225 else
4226 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 +02004227
Willy Tarreauad1731d2013-04-02 17:35:58 +02004228 if (cfgerr) {
4229 memprintf(err, "error processing line %d in file '%s' : %s", linenum, file, *err);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004230 break;
Willy Tarreauad1731d2013-04-02 17:35:58 +02004231 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004232 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004233 fclose(f);
4234 return cfgerr;
4235}
4236
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004237/* Create an initial CTX used to start the SSL connection before switchctx */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004238static int
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004239ssl_sock_initial_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02004240{
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004241 SSL_CTX *ctx = NULL;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004242 long options =
Emeric Brunfc0421f2012-09-07 17:30:07 +02004243 SSL_OP_ALL | /* all known workarounds for bugs */
4244 SSL_OP_NO_SSLv2 |
4245 SSL_OP_NO_COMPRESSION |
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02004246 SSL_OP_SINGLE_DH_USE |
Emeric Brun2b58d042012-09-20 17:10:03 +02004247 SSL_OP_SINGLE_ECDH_USE |
Emeric Brun3c4bc6e2012-10-04 18:44:19 +02004248 SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION |
Lukas Tribus926594f2018-05-18 17:55:57 +02004249 SSL_OP_PRIORITIZE_CHACHA |
Emeric Brun3c4bc6e2012-10-04 18:44:19 +02004250 SSL_OP_CIPHER_SERVER_PREFERENCE;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004251 long mode =
Emeric Brunfc0421f2012-09-07 17:30:07 +02004252 SSL_MODE_ENABLE_PARTIAL_WRITE |
4253 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
Willy Tarreau396a1862014-11-13 14:06:52 +01004254 SSL_MODE_RELEASE_BUFFERS |
4255 SSL_MODE_SMALL_BUFFERS;
Emmanuel Hocdet43664762017-08-09 18:26:20 +02004256 struct tls_version_filter *conf_ssl_methods = &bind_conf->ssl_conf.ssl_methods;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004257 int i, min, max, hole;
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004258 int flags = MC_SSL_O_ALL;
4259 int cfgerr = 0;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004260
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004261 ctx = SSL_CTX_new(SSLv23_server_method());
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004262 bind_conf->initial_ctx = ctx;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004263
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004264 if (conf_ssl_methods->flags && (conf_ssl_methods->min || conf_ssl_methods->max))
Christopher Faulet767a84b2017-11-24 16:50:31 +01004265 ha_warning("Proxy '%s': no-sslv3/no-tlsv1x are ignored for bind '%s' at [%s:%d]. "
4266 "Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
4267 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004268 else
4269 flags = conf_ssl_methods->flags;
4270
Emmanuel Hocdetbd695fe2017-05-15 15:53:41 +02004271 min = conf_ssl_methods->min;
4272 max = conf_ssl_methods->max;
4273 /* start with TLSv10 to remove SSLv3 per default */
4274 if (!min && (!max || max >= CONF_TLSV10))
4275 min = CONF_TLSV10;
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004276 /* Real min and max should be determinate with configuration and openssl's capabilities */
Emmanuel Hocdetbd695fe2017-05-15 15:53:41 +02004277 if (min)
4278 flags |= (methodVersions[min].flag - 1);
4279 if (max)
4280 flags |= ~((methodVersions[max].flag << 1) - 1);
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004281 /* find min, max and holes */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004282 min = max = CONF_TLSV_NONE;
4283 hole = 0;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004284 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004285 /* version is in openssl && version not disable in configuration */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004286 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004287 if (min) {
4288 if (hole) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004289 ha_warning("Proxy '%s': SSL/TLS versions range not contiguous for bind '%s' at [%s:%d]. "
4290 "Hole find for %s. Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
4291 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line,
4292 methodVersions[hole].name);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004293 hole = 0;
4294 }
4295 max = i;
4296 }
4297 else {
4298 min = max = i;
4299 }
4300 }
4301 else {
4302 if (min)
4303 hole = i;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004304 }
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004305 if (!min) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004306 ha_alert("Proxy '%s': all SSL/TLS versions are disabled for bind '%s' at [%s:%d].\n",
4307 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004308 cfgerr += 1;
4309 }
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02004310 /* save real min/max in bind_conf */
4311 conf_ssl_methods->min = min;
4312 conf_ssl_methods->max = max;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004313
Willy Tarreau9a1ab082019-05-09 13:26:41 +02004314#if (HA_OPENSSL_VERSION_NUMBER < 0x1010000fL)
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004315 /* Keep force-xxx implementation as it is in older haproxy. It's a
Joseph Herlant017b3da2018-11-15 09:07:59 -08004316 precautionary measure to avoid any surprise with older openssl version. */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004317 if (min == max)
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004318 methodVersions[min].ctx_set_version(ctx, SET_SERVER);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004319 else
4320 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
4321 if (flags & methodVersions[i].flag)
4322 options |= methodVersions[i].option;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004323#else /* openssl >= 1.1.0 */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004324 /* set the max_version is required to cap TLS version or activate new TLS (v1.3) */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004325 methodVersions[min].ctx_set_version(ctx, SET_MIN);
4326 methodVersions[max].ctx_set_version(ctx, SET_MAX);
Emeric Brunfa5c5c82017-04-28 16:19:51 +02004327#endif
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004328
4329 if (bind_conf->ssl_options & BC_SSL_O_NO_TLS_TICKETS)
4330 options |= SSL_OP_NO_TICKET;
4331 if (bind_conf->ssl_options & BC_SSL_O_PREF_CLIE_CIPH)
4332 options &= ~SSL_OP_CIPHER_SERVER_PREFERENCE;
Dirkjan Bussink526894f2019-01-21 09:35:03 -08004333
4334#ifdef SSL_OP_NO_RENEGOTIATION
4335 options |= SSL_OP_NO_RENEGOTIATION;
4336#endif
4337
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004338 SSL_CTX_set_options(ctx, options);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004339
Willy Tarreau5db847a2019-05-09 14:13:35 +02004340#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004341 if (global_ssl.async)
4342 mode |= SSL_MODE_ASYNC;
4343#endif
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004344 SSL_CTX_set_mode(ctx, mode);
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004345 if (global_ssl.life_time)
4346 SSL_CTX_set_timeout(ctx, global_ssl.life_time);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004347
4348#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
4349#ifdef OPENSSL_IS_BORINGSSL
4350 SSL_CTX_set_select_certificate_cb(ctx, ssl_sock_switchctx_cbk);
4351 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_err_cbk);
Willy Tarreau5db847a2019-05-09 14:13:35 +02004352#elif (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Olivier Houchard51088ce2019-01-02 18:46:41 +01004353 if (bind_conf->ssl_conf.early_data) {
4354 SSL_CTX_set_options(ctx, SSL_OP_NO_ANTI_REPLAY);
4355 SSL_CTX_set_max_early_data(ctx, global.tune.bufsize - global.tune.maxrewrite);
4356 }
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02004357 SSL_CTX_set_client_hello_cb(ctx, ssl_sock_switchctx_cbk, NULL);
4358 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_err_cbk);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004359#else
4360 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_cbk);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004361#endif
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02004362 SSL_CTX_set_tlsext_servername_arg(ctx, bind_conf);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004363#endif
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004364 return cfgerr;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004365}
4366
William Lallemand4f45bb92017-10-30 20:08:51 +01004367
4368static inline void sh_ssl_sess_free_blocks(struct shared_block *first, struct shared_block *block)
4369{
4370 if (first == block) {
4371 struct sh_ssl_sess_hdr *sh_ssl_sess = (struct sh_ssl_sess_hdr *)first->data;
4372 if (first->len > 0)
4373 sh_ssl_sess_tree_delete(sh_ssl_sess);
4374 }
4375}
4376
4377/* return first block from sh_ssl_sess */
4378static inline struct shared_block *sh_ssl_sess_first_block(struct sh_ssl_sess_hdr *sh_ssl_sess)
4379{
4380 return (struct shared_block *)((unsigned char *)sh_ssl_sess - ((struct shared_block *)NULL)->data);
4381
4382}
4383
4384/* store a session into the cache
4385 * s_id : session id padded with zero to SSL_MAX_SSL_SESSION_ID_LENGTH
4386 * data: asn1 encoded session
4387 * data_len: asn1 encoded session length
4388 * Returns 1 id session was stored (else 0)
4389 */
4390static int sh_ssl_sess_store(unsigned char *s_id, unsigned char *data, int data_len)
4391{
4392 struct shared_block *first;
4393 struct sh_ssl_sess_hdr *sh_ssl_sess, *oldsh_ssl_sess;
4394
Frédéric Lécaille0bec8072018-10-22 17:55:57 +02004395 first = shctx_row_reserve_hot(ssl_shctx, NULL, data_len + sizeof(struct sh_ssl_sess_hdr));
William Lallemand4f45bb92017-10-30 20:08:51 +01004396 if (!first) {
4397 /* Could not retrieve enough free blocks to store that session */
4398 return 0;
4399 }
4400
4401 /* STORE the key in the first elem */
4402 sh_ssl_sess = (struct sh_ssl_sess_hdr *)first->data;
4403 memcpy(sh_ssl_sess->key_data, s_id, SSL_MAX_SSL_SESSION_ID_LENGTH);
4404 first->len = sizeof(struct sh_ssl_sess_hdr);
4405
4406 /* it returns the already existing node
4407 or current node if none, never returns null */
4408 oldsh_ssl_sess = sh_ssl_sess_tree_insert(sh_ssl_sess);
4409 if (oldsh_ssl_sess != sh_ssl_sess) {
4410 /* NOTE: Row couldn't be in use because we lock read & write function */
4411 /* release the reserved row */
4412 shctx_row_dec_hot(ssl_shctx, first);
4413 /* replace the previous session already in the tree */
4414 sh_ssl_sess = oldsh_ssl_sess;
4415 /* ignore the previous session data, only use the header */
4416 first = sh_ssl_sess_first_block(sh_ssl_sess);
4417 shctx_row_inc_hot(ssl_shctx, first);
4418 first->len = sizeof(struct sh_ssl_sess_hdr);
4419 }
4420
Frédéric Lécaille0bec8072018-10-22 17:55:57 +02004421 if (shctx_row_data_append(ssl_shctx, first, NULL, data, data_len) < 0) {
William Lallemand99b90af2018-01-03 19:15:51 +01004422 shctx_row_dec_hot(ssl_shctx, first);
William Lallemand4f45bb92017-10-30 20:08:51 +01004423 return 0;
William Lallemand99b90af2018-01-03 19:15:51 +01004424 }
4425
4426 shctx_row_dec_hot(ssl_shctx, first);
William Lallemand4f45bb92017-10-30 20:08:51 +01004427
4428 return 1;
4429}
William Lallemanded0b5ad2017-10-30 19:36:36 +01004430
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004431/* SSL callback used when a new session is created while connecting to a server */
4432static int ssl_sess_new_srv_cb(SSL *ssl, SSL_SESSION *sess)
4433{
Thierry FOURNIER28962c92018-06-17 21:37:05 +02004434 struct connection *conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Olivier Houcharde6060c52017-11-16 17:42:52 +01004435 struct server *s;
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004436
Willy Tarreau07d94e42018-09-20 10:57:52 +02004437 s = __objt_server(conn->target);
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004438
Olivier Houcharde6060c52017-11-16 17:42:52 +01004439 if (!(s->ssl_ctx.options & SRV_SSL_O_NO_REUSE)) {
4440 int len;
4441 unsigned char *ptr;
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004442
Olivier Houcharde6060c52017-11-16 17:42:52 +01004443 len = i2d_SSL_SESSION(sess, NULL);
4444 if (s->ssl_ctx.reused_sess[tid].ptr && s->ssl_ctx.reused_sess[tid].allocated_size >= len) {
4445 ptr = s->ssl_ctx.reused_sess[tid].ptr;
4446 } else {
4447 free(s->ssl_ctx.reused_sess[tid].ptr);
4448 ptr = s->ssl_ctx.reused_sess[tid].ptr = malloc(len);
4449 s->ssl_ctx.reused_sess[tid].allocated_size = len;
4450 }
4451 if (s->ssl_ctx.reused_sess[tid].ptr) {
4452 s->ssl_ctx.reused_sess[tid].size = i2d_SSL_SESSION(sess,
4453 &ptr);
4454 }
4455 } else {
4456 free(s->ssl_ctx.reused_sess[tid].ptr);
4457 s->ssl_ctx.reused_sess[tid].ptr = NULL;
4458 }
4459
4460 return 0;
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004461}
4462
Olivier Houcharde6060c52017-11-16 17:42:52 +01004463
William Lallemanded0b5ad2017-10-30 19:36:36 +01004464/* SSL callback used on new session creation */
William Lallemand4f45bb92017-10-30 20:08:51 +01004465int sh_ssl_sess_new_cb(SSL *ssl, SSL_SESSION *sess)
William Lallemanded0b5ad2017-10-30 19:36:36 +01004466{
4467 unsigned char encsess[SHSESS_MAX_DATA_LEN]; /* encoded session */
4468 unsigned char encid[SSL_MAX_SSL_SESSION_ID_LENGTH]; /* encoded id */
4469 unsigned char *p;
4470 int data_len;
Emeric Bruneb469652019-10-08 18:27:37 +02004471 unsigned int sid_length;
William Lallemanded0b5ad2017-10-30 19:36:36 +01004472 const unsigned char *sid_data;
William Lallemanded0b5ad2017-10-30 19:36:36 +01004473
4474 /* Session id is already stored in to key and session id is known
4475 * so we dont store it to keep size.
Emeric Bruneb469652019-10-08 18:27:37 +02004476 * note: SSL_SESSION_set1_id is using
4477 * a memcpy so we need to use a different pointer
4478 * than sid_data or sid_ctx_data to avoid valgrind
4479 * complaining.
William Lallemanded0b5ad2017-10-30 19:36:36 +01004480 */
4481
4482 sid_data = SSL_SESSION_get_id(sess, &sid_length);
Emeric Bruneb469652019-10-08 18:27:37 +02004483
4484 /* copy value in an other buffer */
4485 memcpy(encid, sid_data, sid_length);
4486
4487 /* pad with 0 */
4488 if (sid_length < SSL_MAX_SSL_SESSION_ID_LENGTH)
4489 memset(encid + sid_length, 0, SSL_MAX_SSL_SESSION_ID_LENGTH-sid_length);
4490
4491 /* force length to zero to avoid ASN1 encoding */
4492 SSL_SESSION_set1_id(sess, encid, 0);
4493
4494 /* force length to zero to avoid ASN1 encoding */
4495 SSL_SESSION_set1_id_context(sess, (const unsigned char *)SHCTX_APPNAME, 0);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004496
4497 /* check if buffer is large enough for the ASN1 encoded session */
4498 data_len = i2d_SSL_SESSION(sess, NULL);
4499 if (data_len > SHSESS_MAX_DATA_LEN)
4500 goto err;
4501
4502 p = encsess;
4503
4504 /* process ASN1 session encoding before the lock */
4505 i2d_SSL_SESSION(sess, &p);
4506
William Lallemanded0b5ad2017-10-30 19:36:36 +01004507
William Lallemanda3c77cf2017-10-30 23:44:40 +01004508 shctx_lock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004509 /* store to cache */
William Lallemand4f45bb92017-10-30 20:08:51 +01004510 sh_ssl_sess_store(encid, encsess, data_len);
William Lallemanda3c77cf2017-10-30 23:44:40 +01004511 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004512err:
4513 /* reset original length values */
Emeric Bruneb469652019-10-08 18:27:37 +02004514 SSL_SESSION_set1_id(sess, encid, sid_length);
4515 SSL_SESSION_set1_id_context(sess, (const unsigned char *)SHCTX_APPNAME, strlen(SHCTX_APPNAME));
William Lallemanded0b5ad2017-10-30 19:36:36 +01004516
4517 return 0; /* do not increment session reference count */
4518}
4519
4520/* SSL callback used on lookup an existing session cause none found in internal cache */
William Lallemand4f45bb92017-10-30 20:08:51 +01004521SSL_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 +01004522{
William Lallemand4f45bb92017-10-30 20:08:51 +01004523 struct sh_ssl_sess_hdr *sh_ssl_sess;
William Lallemanded0b5ad2017-10-30 19:36:36 +01004524 unsigned char data[SHSESS_MAX_DATA_LEN], *p;
4525 unsigned char tmpkey[SSL_MAX_SSL_SESSION_ID_LENGTH];
William Lallemanded0b5ad2017-10-30 19:36:36 +01004526 SSL_SESSION *sess;
William Lallemand4f45bb92017-10-30 20:08:51 +01004527 struct shared_block *first;
William Lallemanded0b5ad2017-10-30 19:36:36 +01004528
4529 global.shctx_lookups++;
4530
4531 /* allow the session to be freed automatically by openssl */
4532 *do_copy = 0;
4533
4534 /* tree key is zeros padded sessionid */
4535 if (key_len < SSL_MAX_SSL_SESSION_ID_LENGTH) {
4536 memcpy(tmpkey, key, key_len);
4537 memset(tmpkey + key_len, 0, SSL_MAX_SSL_SESSION_ID_LENGTH - key_len);
4538 key = tmpkey;
4539 }
4540
4541 /* lock cache */
William Lallemanda3c77cf2017-10-30 23:44:40 +01004542 shctx_lock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004543
4544 /* lookup for session */
William Lallemand4f45bb92017-10-30 20:08:51 +01004545 sh_ssl_sess = sh_ssl_sess_tree_lookup(key);
4546 if (!sh_ssl_sess) {
William Lallemanded0b5ad2017-10-30 19:36:36 +01004547 /* no session found: unlock cache and exit */
William Lallemanda3c77cf2017-10-30 23:44:40 +01004548 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004549 global.shctx_misses++;
4550 return NULL;
4551 }
4552
William Lallemand4f45bb92017-10-30 20:08:51 +01004553 /* sh_ssl_sess (shared_block->data) is at the end of shared_block */
4554 first = sh_ssl_sess_first_block(sh_ssl_sess);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004555
William Lallemand4f45bb92017-10-30 20:08:51 +01004556 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 +01004557
William Lallemanda3c77cf2017-10-30 23:44:40 +01004558 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004559
4560 /* decode ASN1 session */
4561 p = data;
William Lallemand4f45bb92017-10-30 20:08:51 +01004562 sess = d2i_SSL_SESSION(NULL, (const unsigned char **)&p, first->len-sizeof(struct sh_ssl_sess_hdr));
William Lallemanded0b5ad2017-10-30 19:36:36 +01004563 /* Reset session id and session id contenxt */
4564 if (sess) {
4565 SSL_SESSION_set1_id(sess, key, key_len);
4566 SSL_SESSION_set1_id_context(sess, (const unsigned char *)SHCTX_APPNAME, strlen(SHCTX_APPNAME));
4567 }
4568
4569 return sess;
4570}
4571
William Lallemand4f45bb92017-10-30 20:08:51 +01004572
William Lallemanded0b5ad2017-10-30 19:36:36 +01004573/* SSL callback used to signal session is no more used in internal cache */
William Lallemand4f45bb92017-10-30 20:08:51 +01004574void sh_ssl_sess_remove_cb(SSL_CTX *ctx, SSL_SESSION *sess)
William Lallemanded0b5ad2017-10-30 19:36:36 +01004575{
William Lallemand4f45bb92017-10-30 20:08:51 +01004576 struct sh_ssl_sess_hdr *sh_ssl_sess;
William Lallemanded0b5ad2017-10-30 19:36:36 +01004577 unsigned char tmpkey[SSL_MAX_SSL_SESSION_ID_LENGTH];
4578 unsigned int sid_length;
4579 const unsigned char *sid_data;
4580 (void)ctx;
4581
4582 sid_data = SSL_SESSION_get_id(sess, &sid_length);
4583 /* tree key is zeros padded sessionid */
4584 if (sid_length < SSL_MAX_SSL_SESSION_ID_LENGTH) {
4585 memcpy(tmpkey, sid_data, sid_length);
4586 memset(tmpkey+sid_length, 0, SSL_MAX_SSL_SESSION_ID_LENGTH - sid_length);
4587 sid_data = tmpkey;
4588 }
4589
William Lallemanda3c77cf2017-10-30 23:44:40 +01004590 shctx_lock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004591
4592 /* lookup for session */
William Lallemand4f45bb92017-10-30 20:08:51 +01004593 sh_ssl_sess = sh_ssl_sess_tree_lookup(sid_data);
4594 if (sh_ssl_sess) {
William Lallemanded0b5ad2017-10-30 19:36:36 +01004595 /* free session */
William Lallemand4f45bb92017-10-30 20:08:51 +01004596 sh_ssl_sess_tree_delete(sh_ssl_sess);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004597 }
4598
4599 /* unlock cache */
William Lallemanda3c77cf2017-10-30 23:44:40 +01004600 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004601}
4602
4603/* Set session cache mode to server and disable openssl internal cache.
4604 * Set shared cache callbacks on an ssl context.
4605 * Shared context MUST be firstly initialized */
William Lallemand4f45bb92017-10-30 20:08:51 +01004606void ssl_set_shctx(SSL_CTX *ctx)
William Lallemanded0b5ad2017-10-30 19:36:36 +01004607{
4608 SSL_CTX_set_session_id_context(ctx, (const unsigned char *)SHCTX_APPNAME, strlen(SHCTX_APPNAME));
4609
4610 if (!ssl_shctx) {
4611 SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF);
4612 return;
4613 }
4614
4615 SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_SERVER |
4616 SSL_SESS_CACHE_NO_INTERNAL |
4617 SSL_SESS_CACHE_NO_AUTO_CLEAR);
4618
4619 /* Set callbacks */
William Lallemand4f45bb92017-10-30 20:08:51 +01004620 SSL_CTX_sess_set_new_cb(ctx, sh_ssl_sess_new_cb);
4621 SSL_CTX_sess_set_get_cb(ctx, sh_ssl_sess_get_cb);
4622 SSL_CTX_sess_set_remove_cb(ctx, sh_ssl_sess_remove_cb);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004623}
4624
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004625int ssl_sock_prepare_ctx(struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf, SSL_CTX *ctx)
4626{
4627 struct proxy *curproxy = bind_conf->frontend;
4628 int cfgerr = 0;
4629 int verify = SSL_VERIFY_NONE;
Willy Tarreau5d4cafb2018-01-04 18:55:19 +01004630 struct ssl_bind_conf __maybe_unused *ssl_conf_cur;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004631 const char *conf_ciphers;
Emmanuel Hocdet839af572019-05-14 16:27:35 +02004632#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02004633 const char *conf_ciphersuites;
4634#endif
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004635 const char *conf_curves = NULL;
Emeric Brunfc0421f2012-09-07 17:30:07 +02004636
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02004637 if (ssl_conf) {
4638 struct tls_version_filter *conf_ssl_methods = &ssl_conf->ssl_methods;
4639 int i, min, max;
4640 int flags = MC_SSL_O_ALL;
4641
4642 /* Real min and max should be determinate with configuration and openssl's capabilities */
Emmanuel Hocdet43664762017-08-09 18:26:20 +02004643 min = conf_ssl_methods->min ? conf_ssl_methods->min : bind_conf->ssl_conf.ssl_methods.min;
4644 max = conf_ssl_methods->max ? conf_ssl_methods->max : bind_conf->ssl_conf.ssl_methods.max;
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02004645 if (min)
4646 flags |= (methodVersions[min].flag - 1);
4647 if (max)
4648 flags |= ~((methodVersions[max].flag << 1) - 1);
4649 min = max = CONF_TLSV_NONE;
4650 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
4651 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
4652 if (min)
4653 max = i;
4654 else
4655 min = max = i;
4656 }
4657 /* save real min/max */
4658 conf_ssl_methods->min = min;
4659 conf_ssl_methods->max = max;
4660 if (!min) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004661 ha_alert("Proxy '%s': all SSL/TLS versions are disabled for bind '%s' at [%s:%d].\n",
4662 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02004663 cfgerr += 1;
4664 }
4665 }
4666
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004667 switch ((ssl_conf && ssl_conf->verify) ? ssl_conf->verify : bind_conf->ssl_conf.verify) {
Emeric Brun850efd52014-01-29 12:24:34 +01004668 case SSL_SOCK_VERIFY_NONE:
4669 verify = SSL_VERIFY_NONE;
4670 break;
4671 case SSL_SOCK_VERIFY_OPTIONAL:
4672 verify = SSL_VERIFY_PEER;
4673 break;
4674 case SSL_SOCK_VERIFY_REQUIRED:
4675 verify = SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
4676 break;
4677 }
4678 SSL_CTX_set_verify(ctx, verify, ssl_sock_bind_verifycbk);
4679 if (verify & SSL_VERIFY_PEER) {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004680 char *ca_file = (ssl_conf && ssl_conf->ca_file) ? ssl_conf->ca_file : bind_conf->ssl_conf.ca_file;
4681 char *crl_file = (ssl_conf && ssl_conf->crl_file) ? ssl_conf->crl_file : bind_conf->ssl_conf.crl_file;
4682 if (ca_file) {
Emeric Brund94b3fe2012-09-20 18:23:56 +02004683 /* load CAfile to verify */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004684 if (!SSL_CTX_load_verify_locations(ctx, ca_file, NULL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004685 ha_alert("Proxy '%s': unable to load CA file '%s' for bind '%s' at [%s:%d].\n",
4686 curproxy->id, ca_file, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brund94b3fe2012-09-20 18:23:56 +02004687 cfgerr++;
4688 }
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02004689 if (!((ssl_conf && ssl_conf->no_ca_names) || bind_conf->ssl_conf.no_ca_names)) {
4690 /* set CA names for client cert request, function returns void */
4691 SSL_CTX_set_client_CA_list(ctx, SSL_load_client_CA_file(ca_file));
4692 }
Emeric Brund94b3fe2012-09-20 18:23:56 +02004693 }
Emeric Brun850efd52014-01-29 12:24:34 +01004694 else {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004695 ha_alert("Proxy '%s': verify is enabled but no CA file specified for bind '%s' at [%s:%d].\n",
4696 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brun850efd52014-01-29 12:24:34 +01004697 cfgerr++;
4698 }
Emeric Brun051cdab2012-10-02 19:25:50 +02004699#ifdef X509_V_FLAG_CRL_CHECK
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004700 if (crl_file) {
Emeric Brund94b3fe2012-09-20 18:23:56 +02004701 X509_STORE *store = SSL_CTX_get_cert_store(ctx);
4702
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004703 if (!store || !X509_STORE_load_locations(store, crl_file, NULL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004704 ha_alert("Proxy '%s': unable to configure CRL file '%s' for bind '%s' at [%s:%d].\n",
4705 curproxy->id, crl_file, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brund94b3fe2012-09-20 18:23:56 +02004706 cfgerr++;
4707 }
Emeric Brun561e5742012-10-02 15:20:55 +02004708 else {
4709 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
4710 }
Emeric Brund94b3fe2012-09-20 18:23:56 +02004711 }
Emeric Brun051cdab2012-10-02 19:25:50 +02004712#endif
Emeric Brun644cde02012-12-14 11:21:13 +01004713 ERR_clear_error();
Emeric Brund94b3fe2012-09-20 18:23:56 +02004714 }
Nenad Merdanovic05552d42015-02-27 19:56:49 +01004715#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
Nenad Merdanovic146defa2015-05-09 08:46:00 +02004716 if(bind_conf->keys_ref) {
Nenad Merdanovic05552d42015-02-27 19:56:49 +01004717 if (!SSL_CTX_set_tlsext_ticket_key_cb(ctx, ssl_tlsext_ticket_key_cb)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004718 ha_alert("Proxy '%s': unable to set callback for TLS ticket validation for bind '%s' at [%s:%d].\n",
4719 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Nenad Merdanovic05552d42015-02-27 19:56:49 +01004720 cfgerr++;
4721 }
4722 }
4723#endif
4724
William Lallemand4f45bb92017-10-30 20:08:51 +01004725 ssl_set_shctx(ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004726 conf_ciphers = (ssl_conf && ssl_conf->ciphers) ? ssl_conf->ciphers : bind_conf->ssl_conf.ciphers;
4727 if (conf_ciphers &&
4728 !SSL_CTX_set_cipher_list(ctx, conf_ciphers)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004729 ha_alert("Proxy '%s': unable to set SSL cipher list to '%s' for bind '%s' at [%s:%d].\n",
4730 curproxy->id, conf_ciphers, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004731 cfgerr++;
4732 }
4733
Emmanuel Hocdet839af572019-05-14 16:27:35 +02004734#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02004735 conf_ciphersuites = (ssl_conf && ssl_conf->ciphersuites) ? ssl_conf->ciphersuites : bind_conf->ssl_conf.ciphersuites;
4736 if (conf_ciphersuites &&
4737 !SSL_CTX_set_ciphersuites(ctx, conf_ciphersuites)) {
4738 ha_alert("Proxy '%s': unable to set TLS 1.3 cipher suites to '%s' for bind '%s' at [%s:%d].\n",
4739 curproxy->id, conf_ciphersuites, bind_conf->arg, bind_conf->file, bind_conf->line);
4740 cfgerr++;
4741 }
4742#endif
4743
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01004744#ifndef OPENSSL_NO_DH
Remi Gacogne47783ef2015-05-29 15:53:22 +02004745 /* If tune.ssl.default-dh-param has not been set,
4746 neither has ssl-default-dh-file and no static DH
4747 params were in the certificate file. */
Willy Tarreauef934602016-12-22 23:12:01 +01004748 if (global_ssl.default_dh_param == 0 &&
Remi Gacogne47783ef2015-05-29 15:53:22 +02004749 global_dh == NULL &&
Remi Gacogne4f902b82015-05-28 16:23:00 +02004750 (ssl_dh_ptr_index == -1 ||
4751 SSL_CTX_get_ex_data(ctx, ssl_dh_ptr_index) == NULL)) {
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01004752 STACK_OF(SSL_CIPHER) * ciphers = NULL;
4753 const SSL_CIPHER * cipher = NULL;
4754 char cipher_description[128];
4755 /* The description of ciphers using an Ephemeral Diffie Hellman key exchange
4756 contains " Kx=DH " or " Kx=DH(". Beware of " Kx=DH/",
4757 which is not ephemeral DH. */
4758 const char dhe_description[] = " Kx=DH ";
4759 const char dhe_export_description[] = " Kx=DH(";
4760 int idx = 0;
4761 int dhe_found = 0;
4762 SSL *ssl = NULL;
Lukas Tribus90132722014-08-18 00:56:33 +02004763
Remi Gacogne23d5d372014-10-10 17:04:26 +02004764 ssl = SSL_new(ctx);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004765
Remi Gacogne23d5d372014-10-10 17:04:26 +02004766 if (ssl) {
4767 ciphers = SSL_get_ciphers(ssl);
4768
4769 if (ciphers) {
4770 for (idx = 0; idx < sk_SSL_CIPHER_num(ciphers); idx++) {
4771 cipher = sk_SSL_CIPHER_value(ciphers, idx);
4772 if (SSL_CIPHER_description(cipher, cipher_description, sizeof (cipher_description)) == cipher_description) {
4773 if (strstr(cipher_description, dhe_description) != NULL ||
4774 strstr(cipher_description, dhe_export_description) != NULL) {
4775 dhe_found = 1;
4776 break;
4777 }
Remi Gacognec1eab8c2014-06-12 18:20:11 +02004778 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004779 }
4780 }
Remi Gacogne23d5d372014-10-10 17:04:26 +02004781 SSL_free(ssl);
4782 ssl = NULL;
Lukas Tribus90132722014-08-18 00:56:33 +02004783 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004784
Lukas Tribus90132722014-08-18 00:56:33 +02004785 if (dhe_found) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004786 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 +02004787 }
4788
Willy Tarreauef934602016-12-22 23:12:01 +01004789 global_ssl.default_dh_param = 1024;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004790 }
Remi Gacogne8de54152014-07-15 11:36:40 +02004791
Willy Tarreauef934602016-12-22 23:12:01 +01004792 if (global_ssl.default_dh_param >= 1024) {
Remi Gacogne8de54152014-07-15 11:36:40 +02004793 if (local_dh_1024 == NULL) {
4794 local_dh_1024 = ssl_get_dh_1024();
4795 }
Willy Tarreauef934602016-12-22 23:12:01 +01004796 if (global_ssl.default_dh_param >= 2048) {
Remi Gacogne8de54152014-07-15 11:36:40 +02004797 if (local_dh_2048 == NULL) {
4798 local_dh_2048 = ssl_get_dh_2048();
4799 }
Willy Tarreauef934602016-12-22 23:12:01 +01004800 if (global_ssl.default_dh_param >= 4096) {
Remi Gacogne8de54152014-07-15 11:36:40 +02004801 if (local_dh_4096 == NULL) {
4802 local_dh_4096 = ssl_get_dh_4096();
4803 }
Remi Gacogne8de54152014-07-15 11:36:40 +02004804 }
4805 }
4806 }
4807#endif /* OPENSSL_NO_DH */
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004808
Emeric Brunfc0421f2012-09-07 17:30:07 +02004809 SSL_CTX_set_info_callback(ctx, ssl_sock_infocbk);
Willy Tarreau9a1ab082019-05-09 13:26:41 +02004810#if HA_OPENSSL_VERSION_NUMBER >= 0x00907000L
Emeric Brun29f037d2014-04-25 19:05:36 +02004811 SSL_CTX_set_msg_callback(ctx, ssl_sock_msgcbk);
Willy Tarreau5cbe4ef2014-05-08 22:45:11 +02004812#endif
Emeric Brun29f037d2014-04-25 19:05:36 +02004813
Bernard Spil13c53f82018-02-15 13:34:58 +01004814#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004815 ssl_conf_cur = NULL;
4816 if (ssl_conf && ssl_conf->npn_str)
4817 ssl_conf_cur = ssl_conf;
4818 else if (bind_conf->ssl_conf.npn_str)
4819 ssl_conf_cur = &bind_conf->ssl_conf;
4820 if (ssl_conf_cur)
4821 SSL_CTX_set_next_protos_advertised_cb(ctx, ssl_sock_advertise_npn_protos, ssl_conf_cur);
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02004822#endif
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01004823#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004824 ssl_conf_cur = NULL;
4825 if (ssl_conf && ssl_conf->alpn_str)
4826 ssl_conf_cur = ssl_conf;
4827 else if (bind_conf->ssl_conf.alpn_str)
4828 ssl_conf_cur = &bind_conf->ssl_conf;
4829 if (ssl_conf_cur)
4830 SSL_CTX_set_alpn_select_cb(ctx, ssl_sock_advertise_alpn_protos, ssl_conf_cur);
Willy Tarreauab861d32013-04-02 02:30:41 +02004831#endif
Willy Tarreau9a1ab082019-05-09 13:26:41 +02004832#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004833 conf_curves = (ssl_conf && ssl_conf->curves) ? ssl_conf->curves : bind_conf->ssl_conf.curves;
4834 if (conf_curves) {
4835 if (!SSL_CTX_set1_curves_list(ctx, conf_curves)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004836 ha_alert("Proxy '%s': unable to set SSL curves list to '%s' for bind '%s' at [%s:%d].\n",
4837 curproxy->id, conf_curves, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004838 cfgerr++;
4839 }
Emmanuel Hocdeta52bb152017-03-20 11:11:49 +01004840#if defined(SSL_CTX_set_ecdh_auto)
4841 (void)SSL_CTX_set_ecdh_auto(ctx, 1);
4842#endif
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004843 }
4844#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02004845#if defined(SSL_CTX_set_tmp_ecdh) && !defined(OPENSSL_NO_ECDH)
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004846 if (!conf_curves) {
Emeric Brun2b58d042012-09-20 17:10:03 +02004847 int i;
4848 EC_KEY *ecdh;
Willy Tarreau9a1ab082019-05-09 13:26:41 +02004849#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004850 const char *ecdhe = (ssl_conf && ssl_conf->ecdhe) ? ssl_conf->ecdhe :
Olivier Houchardc2aae742017-09-22 18:26:28 +02004851 (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe :
4852 NULL);
4853
4854 if (ecdhe == NULL) {
Emeric Bruna9363eb2019-10-17 14:53:03 +02004855 SSL_CTX_set_ecdh_auto(ctx, 1);
Olivier Houchardc2aae742017-09-22 18:26:28 +02004856 return cfgerr;
4857 }
4858#else
4859 const char *ecdhe = (ssl_conf && ssl_conf->ecdhe) ? ssl_conf->ecdhe :
4860 (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe :
4861 ECDHE_DEFAULT_CURVE);
4862#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02004863
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004864 i = OBJ_sn2nid(ecdhe);
Emeric Brun2b58d042012-09-20 17:10:03 +02004865 if (!i || ((ecdh = EC_KEY_new_by_curve_name(i)) == NULL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004866 ha_alert("Proxy '%s': unable to set elliptic named curve to '%s' for bind '%s' at [%s:%d].\n",
4867 curproxy->id, ecdhe, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brun2b58d042012-09-20 17:10:03 +02004868 cfgerr++;
4869 }
4870 else {
4871 SSL_CTX_set_tmp_ecdh(ctx, ecdh);
4872 EC_KEY_free(ecdh);
4873 }
4874 }
4875#endif
4876
Emeric Brunfc0421f2012-09-07 17:30:07 +02004877 return cfgerr;
4878}
4879
Evan Broderbe554312013-06-27 00:05:25 -07004880static int ssl_sock_srv_hostcheck(const char *pattern, const char *hostname)
4881{
4882 const char *pattern_wildcard, *pattern_left_label_end, *hostname_left_label_end;
4883 size_t prefixlen, suffixlen;
4884
4885 /* Trivial case */
4886 if (strcmp(pattern, hostname) == 0)
4887 return 1;
4888
Evan Broderbe554312013-06-27 00:05:25 -07004889 /* The rest of this logic is based on RFC 6125, section 6.4.3
4890 * (http://tools.ietf.org/html/rfc6125#section-6.4.3) */
4891
Emeric Bruna848dae2013-10-08 11:27:28 +02004892 pattern_wildcard = NULL;
4893 pattern_left_label_end = pattern;
4894 while (*pattern_left_label_end != '.') {
4895 switch (*pattern_left_label_end) {
4896 case 0:
4897 /* End of label not found */
4898 return 0;
4899 case '*':
4900 /* If there is more than one wildcards */
4901 if (pattern_wildcard)
4902 return 0;
4903 pattern_wildcard = pattern_left_label_end;
4904 break;
4905 }
4906 pattern_left_label_end++;
4907 }
4908
4909 /* If it's not trivial and there is no wildcard, it can't
4910 * match */
4911 if (!pattern_wildcard)
Evan Broderbe554312013-06-27 00:05:25 -07004912 return 0;
4913
4914 /* Make sure all labels match except the leftmost */
4915 hostname_left_label_end = strchr(hostname, '.');
4916 if (!hostname_left_label_end
4917 || strcmp(pattern_left_label_end, hostname_left_label_end) != 0)
4918 return 0;
4919
4920 /* Make sure the leftmost label of the hostname is long enough
4921 * that the wildcard can match */
Emeric Brun369da852013-10-08 11:39:35 +02004922 if (hostname_left_label_end - hostname < (pattern_left_label_end - pattern) - 1)
Evan Broderbe554312013-06-27 00:05:25 -07004923 return 0;
4924
4925 /* Finally compare the string on either side of the
4926 * wildcard */
4927 prefixlen = pattern_wildcard - pattern;
4928 suffixlen = pattern_left_label_end - (pattern_wildcard + 1);
Emeric Bruna848dae2013-10-08 11:27:28 +02004929 if ((prefixlen && (memcmp(pattern, hostname, prefixlen) != 0))
4930 || (suffixlen && (memcmp(pattern_wildcard + 1, hostname_left_label_end - suffixlen, suffixlen) != 0)))
Evan Broderbe554312013-06-27 00:05:25 -07004931 return 0;
4932
4933 return 1;
4934}
4935
4936static int ssl_sock_srv_verifycbk(int ok, X509_STORE_CTX *ctx)
4937{
4938 SSL *ssl;
4939 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01004940 struct ssl_sock_ctx *ssl_ctx;
Willy Tarreau2ab88672017-07-05 18:23:03 +02004941 const char *servername;
Willy Tarreau71d058c2017-07-26 20:09:56 +02004942 const char *sni;
Evan Broderbe554312013-06-27 00:05:25 -07004943
4944 int depth;
4945 X509 *cert;
4946 STACK_OF(GENERAL_NAME) *alt_names;
4947 int i;
4948 X509_NAME *cert_subject;
4949 char *str;
4950
4951 if (ok == 0)
4952 return ok;
4953
4954 ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
Thierry FOURNIER28962c92018-06-17 21:37:05 +02004955 conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Olivier Houchard66ab4982019-02-26 18:37:15 +01004956 ssl_ctx = conn->xprt_ctx;
Evan Broderbe554312013-06-27 00:05:25 -07004957
Willy Tarreauad92a9a2017-07-28 11:38:41 +02004958 /* We're checking if the provided hostnames match the desired one. The
4959 * desired hostname comes from the SNI we presented if any, or if not
4960 * provided then it may have been explicitly stated using a "verifyhost"
4961 * directive. If neither is set, we don't care about the name so the
4962 * verification is OK.
Willy Tarreau2ab88672017-07-05 18:23:03 +02004963 */
Olivier Houchard66ab4982019-02-26 18:37:15 +01004964 servername = SSL_get_servername(ssl_ctx->ssl, TLSEXT_NAMETYPE_host_name);
Willy Tarreau71d058c2017-07-26 20:09:56 +02004965 sni = servername;
Willy Tarreau2ab88672017-07-05 18:23:03 +02004966 if (!servername) {
Willy Tarreau07d94e42018-09-20 10:57:52 +02004967 servername = __objt_server(conn->target)->ssl_ctx.verify_host;
Willy Tarreau2ab88672017-07-05 18:23:03 +02004968 if (!servername)
4969 return ok;
4970 }
Evan Broderbe554312013-06-27 00:05:25 -07004971
4972 /* We only need to verify the CN on the actual server cert,
4973 * not the indirect CAs */
4974 depth = X509_STORE_CTX_get_error_depth(ctx);
4975 if (depth != 0)
4976 return ok;
4977
4978 /* At this point, the cert is *not* OK unless we can find a
4979 * hostname match */
4980 ok = 0;
4981
4982 cert = X509_STORE_CTX_get_current_cert(ctx);
4983 /* It seems like this might happen if verify peer isn't set */
4984 if (!cert)
4985 return ok;
4986
4987 alt_names = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
4988 if (alt_names) {
4989 for (i = 0; !ok && i < sk_GENERAL_NAME_num(alt_names); i++) {
4990 GENERAL_NAME *name = sk_GENERAL_NAME_value(alt_names, i);
4991 if (name->type == GEN_DNS) {
Willy Tarreau9a1ab082019-05-09 13:26:41 +02004992#if HA_OPENSSL_VERSION_NUMBER < 0x00907000L
Emeric Bruna33410c2013-09-17 15:47:48 +02004993 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.ia5) >= 0) {
4994#else
Evan Broderbe554312013-06-27 00:05:25 -07004995 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
Emeric Bruna33410c2013-09-17 15:47:48 +02004996#endif
Evan Broderbe554312013-06-27 00:05:25 -07004997 ok = ssl_sock_srv_hostcheck(str, servername);
4998 OPENSSL_free(str);
4999 }
5000 }
5001 }
Emeric Brun4ad50a42013-09-17 15:19:54 +02005002 sk_GENERAL_NAME_pop_free(alt_names, GENERAL_NAME_free);
Evan Broderbe554312013-06-27 00:05:25 -07005003 }
5004
5005 cert_subject = X509_get_subject_name(cert);
5006 i = -1;
5007 while (!ok && (i = X509_NAME_get_index_by_NID(cert_subject, NID_commonName, i)) != -1) {
5008 X509_NAME_ENTRY *entry = X509_NAME_get_entry(cert_subject, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005009 ASN1_STRING *value;
5010 value = X509_NAME_ENTRY_get_data(entry);
5011 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
Evan Broderbe554312013-06-27 00:05:25 -07005012 ok = ssl_sock_srv_hostcheck(str, servername);
5013 OPENSSL_free(str);
5014 }
5015 }
5016
Willy Tarreau71d058c2017-07-26 20:09:56 +02005017 /* report the mismatch and indicate if SNI was used or not */
5018 if (!ok && !conn->err_code)
5019 conn->err_code = sni ? CO_ER_SSL_MISMATCH_SNI : CO_ER_SSL_MISMATCH;
Evan Broderbe554312013-06-27 00:05:25 -07005020 return ok;
5021}
5022
Emeric Brun94324a42012-10-11 14:00:19 +02005023/* prepare ssl context from servers options. Returns an error count */
Willy Tarreau03209342016-12-22 17:08:28 +01005024int ssl_sock_prepare_srv_ctx(struct server *srv)
Emeric Brun94324a42012-10-11 14:00:19 +02005025{
Willy Tarreau03209342016-12-22 17:08:28 +01005026 struct proxy *curproxy = srv->proxy;
Emeric Brun94324a42012-10-11 14:00:19 +02005027 int cfgerr = 0;
Remi Gacogneaf5c3da2014-05-19 10:29:58 +02005028 long options =
Emeric Brun94324a42012-10-11 14:00:19 +02005029 SSL_OP_ALL | /* all known workarounds for bugs */
5030 SSL_OP_NO_SSLv2 |
5031 SSL_OP_NO_COMPRESSION;
Remi Gacogneaf5c3da2014-05-19 10:29:58 +02005032 long mode =
Emeric Brun94324a42012-10-11 14:00:19 +02005033 SSL_MODE_ENABLE_PARTIAL_WRITE |
5034 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
Willy Tarreau396a1862014-11-13 14:06:52 +01005035 SSL_MODE_RELEASE_BUFFERS |
5036 SSL_MODE_SMALL_BUFFERS;
Emeric Brun850efd52014-01-29 12:24:34 +01005037 int verify = SSL_VERIFY_NONE;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01005038 SSL_CTX *ctx = NULL;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005039 struct tls_version_filter *conf_ssl_methods = &srv->ssl_ctx.methods;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005040 int i, min, max, hole;
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005041 int flags = MC_SSL_O_ALL;
Emeric Brun94324a42012-10-11 14:00:19 +02005042
Thierry Fournier383085f2013-01-24 14:15:43 +01005043 /* Make sure openssl opens /dev/urandom before the chroot */
5044 if (!ssl_initialize_random()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005045 ha_alert("OpenSSL random data generator initialization failed.\n");
Thierry Fournier383085f2013-01-24 14:15:43 +01005046 cfgerr++;
5047 }
5048
Willy Tarreaufce03112015-01-15 21:32:40 +01005049 /* Automatic memory computations need to know we use SSL there */
5050 global.ssl_used_backend = 1;
5051
5052 /* Initiate SSL context for current server */
Emeric Brun821bb9b2017-06-15 16:37:39 +02005053 if (!srv->ssl_ctx.reused_sess) {
Olivier Houcharde6060c52017-11-16 17:42:52 +01005054 if ((srv->ssl_ctx.reused_sess = calloc(1, global.nbthread*sizeof(*srv->ssl_ctx.reused_sess))) == NULL) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005055 ha_alert("Proxy '%s', server '%s' [%s:%d] out of memory.\n",
5056 curproxy->id, srv->id,
5057 srv->conf.file, srv->conf.line);
Emeric Brun821bb9b2017-06-15 16:37:39 +02005058 cfgerr++;
5059 return cfgerr;
5060 }
5061 }
Emeric Brun94324a42012-10-11 14:00:19 +02005062 if (srv->use_ssl)
5063 srv->xprt = &ssl_sock;
5064 if (srv->check.use_ssl)
Cyril Bonté9ce13112014-11-15 22:41:27 +01005065 srv->check.xprt = &ssl_sock;
Emeric Brun94324a42012-10-11 14:00:19 +02005066
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005067 ctx = SSL_CTX_new(SSLv23_client_method());
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01005068 if (!ctx) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005069 ha_alert("config : %s '%s', server '%s': unable to allocate ssl context.\n",
5070 proxy_type_str(curproxy), curproxy->id,
5071 srv->id);
Emeric Brun94324a42012-10-11 14:00:19 +02005072 cfgerr++;
5073 return cfgerr;
5074 }
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005075
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005076 if (conf_ssl_methods->flags && (conf_ssl_methods->min || conf_ssl_methods->max))
Christopher Faulet767a84b2017-11-24 16:50:31 +01005077 ha_warning("config : %s '%s': no-sslv3/no-tlsv1x are ignored for server '%s'. "
5078 "Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
5079 proxy_type_str(curproxy), curproxy->id, srv->id);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005080 else
5081 flags = conf_ssl_methods->flags;
5082
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005083 /* Real min and max should be determinate with configuration and openssl's capabilities */
5084 if (conf_ssl_methods->min)
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005085 flags |= (methodVersions[conf_ssl_methods->min].flag - 1);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005086 if (conf_ssl_methods->max)
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005087 flags |= ~((methodVersions[conf_ssl_methods->max].flag << 1) - 1);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005088
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02005089 /* find min, max and holes */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005090 min = max = CONF_TLSV_NONE;
5091 hole = 0;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005092 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005093 /* version is in openssl && version not disable in configuration */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005094 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005095 if (min) {
5096 if (hole) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005097 ha_warning("config : %s '%s': SSL/TLS versions range not contiguous for server '%s'. "
5098 "Hole find for %s. Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
5099 proxy_type_str(curproxy), curproxy->id, srv->id,
5100 methodVersions[hole].name);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005101 hole = 0;
5102 }
5103 max = i;
5104 }
5105 else {
5106 min = max = i;
5107 }
5108 }
5109 else {
5110 if (min)
5111 hole = i;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005112 }
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005113 if (!min) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005114 ha_alert("config : %s '%s': all SSL/TLS versions are disabled for server '%s'.\n",
5115 proxy_type_str(curproxy), curproxy->id, srv->id);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005116 cfgerr += 1;
5117 }
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005118
Willy Tarreau9a1ab082019-05-09 13:26:41 +02005119#if (HA_OPENSSL_VERSION_NUMBER < 0x1010000fL)
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005120 /* Keep force-xxx implementation as it is in older haproxy. It's a
Joseph Herlant017b3da2018-11-15 09:07:59 -08005121 precautionary measure to avoid any surprise with older openssl version. */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005122 if (min == max)
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02005123 methodVersions[min].ctx_set_version(ctx, SET_CLIENT);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005124 else
5125 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
5126 if (flags & methodVersions[i].flag)
5127 options |= methodVersions[i].option;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005128#else /* openssl >= 1.1.0 */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005129 /* set the max_version is required to cap TLS version or activate new TLS (v1.3) */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02005130 methodVersions[min].ctx_set_version(ctx, SET_MIN);
5131 methodVersions[max].ctx_set_version(ctx, SET_MAX);
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005132#endif
5133
5134 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLS_TICKETS)
5135 options |= SSL_OP_NO_TICKET;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01005136 SSL_CTX_set_options(ctx, options);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005137
Willy Tarreau5db847a2019-05-09 14:13:35 +02005138#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005139 if (global_ssl.async)
5140 mode |= SSL_MODE_ASYNC;
5141#endif
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01005142 SSL_CTX_set_mode(ctx, mode);
5143 srv->ssl_ctx.ctx = ctx;
5144
Emeric Bruna7aa3092012-10-26 12:58:00 +02005145 if (srv->ssl_ctx.client_crt) {
5146 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 +01005147 ha_alert("config : %s '%s', server '%s': unable to load SSL private key from PEM file '%s'.\n",
5148 proxy_type_str(curproxy), curproxy->id,
5149 srv->id, srv->ssl_ctx.client_crt);
Emeric Bruna7aa3092012-10-26 12:58:00 +02005150 cfgerr++;
5151 }
5152 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 +01005153 ha_alert("config : %s '%s', server '%s': unable to load ssl certificate from PEM file '%s'.\n",
5154 proxy_type_str(curproxy), curproxy->id,
5155 srv->id, srv->ssl_ctx.client_crt);
Emeric Bruna7aa3092012-10-26 12:58:00 +02005156 cfgerr++;
5157 }
5158 else if (SSL_CTX_check_private_key(srv->ssl_ctx.ctx) <= 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005159 ha_alert("config : %s '%s', server '%s': inconsistencies between private key and certificate loaded from PEM file '%s'.\n",
5160 proxy_type_str(curproxy), curproxy->id,
5161 srv->id, srv->ssl_ctx.client_crt);
Emeric Bruna7aa3092012-10-26 12:58:00 +02005162 cfgerr++;
5163 }
5164 }
Emeric Brun94324a42012-10-11 14:00:19 +02005165
Emeric Brun850efd52014-01-29 12:24:34 +01005166 if (global.ssl_server_verify == SSL_SERVER_VERIFY_REQUIRED)
5167 verify = SSL_VERIFY_PEER;
Emeric Brun850efd52014-01-29 12:24:34 +01005168 switch (srv->ssl_ctx.verify) {
5169 case SSL_SOCK_VERIFY_NONE:
5170 verify = SSL_VERIFY_NONE;
5171 break;
5172 case SSL_SOCK_VERIFY_REQUIRED:
5173 verify = SSL_VERIFY_PEER;
5174 break;
5175 }
Evan Broderbe554312013-06-27 00:05:25 -07005176 SSL_CTX_set_verify(srv->ssl_ctx.ctx,
Emeric Brun850efd52014-01-29 12:24:34 +01005177 verify,
Willy Tarreau2ab88672017-07-05 18:23:03 +02005178 (srv->ssl_ctx.verify_host || (verify & SSL_VERIFY_PEER)) ? ssl_sock_srv_verifycbk : NULL);
Emeric Brun850efd52014-01-29 12:24:34 +01005179 if (verify & SSL_VERIFY_PEER) {
Emeric Brunef42d922012-10-11 16:11:36 +02005180 if (srv->ssl_ctx.ca_file) {
5181 /* load CAfile to verify */
5182 if (!SSL_CTX_load_verify_locations(srv->ssl_ctx.ctx, srv->ssl_ctx.ca_file, NULL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005183 ha_alert("Proxy '%s', server '%s' [%s:%d] unable to load CA file '%s'.\n",
5184 curproxy->id, srv->id,
5185 srv->conf.file, srv->conf.line, srv->ssl_ctx.ca_file);
Emeric Brunef42d922012-10-11 16:11:36 +02005186 cfgerr++;
5187 }
5188 }
Emeric Brun850efd52014-01-29 12:24:34 +01005189 else {
5190 if (global.ssl_server_verify == SSL_SERVER_VERIFY_REQUIRED)
Christopher Faulet767a84b2017-11-24 16:50:31 +01005191 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",
5192 curproxy->id, srv->id,
5193 srv->conf.file, srv->conf.line);
Emeric Brun850efd52014-01-29 12:24:34 +01005194 else
Christopher Faulet767a84b2017-11-24 16:50:31 +01005195 ha_alert("Proxy '%s', server '%s' [%s:%d] verify is enabled but no CA file specified.\n",
5196 curproxy->id, srv->id,
5197 srv->conf.file, srv->conf.line);
Emeric Brun850efd52014-01-29 12:24:34 +01005198 cfgerr++;
5199 }
Emeric Brunef42d922012-10-11 16:11:36 +02005200#ifdef X509_V_FLAG_CRL_CHECK
5201 if (srv->ssl_ctx.crl_file) {
5202 X509_STORE *store = SSL_CTX_get_cert_store(srv->ssl_ctx.ctx);
5203
5204 if (!store || !X509_STORE_load_locations(store, srv->ssl_ctx.crl_file, NULL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005205 ha_alert("Proxy '%s', server '%s' [%s:%d] unable to configure CRL file '%s'.\n",
5206 curproxy->id, srv->id,
5207 srv->conf.file, srv->conf.line, srv->ssl_ctx.crl_file);
Emeric Brunef42d922012-10-11 16:11:36 +02005208 cfgerr++;
5209 }
5210 else {
5211 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
5212 }
5213 }
5214#endif
5215 }
5216
Olivier Houchardbd84ac82017-11-03 13:43:35 +01005217 SSL_CTX_set_session_cache_mode(srv->ssl_ctx.ctx, SSL_SESS_CACHE_CLIENT |
5218 SSL_SESS_CACHE_NO_INTERNAL_STORE);
5219 SSL_CTX_sess_set_new_cb(srv->ssl_ctx.ctx, ssl_sess_new_srv_cb);
Emeric Brun94324a42012-10-11 14:00:19 +02005220 if (srv->ssl_ctx.ciphers &&
5221 !SSL_CTX_set_cipher_list(srv->ssl_ctx.ctx, srv->ssl_ctx.ciphers)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005222 ha_alert("Proxy '%s', server '%s' [%s:%d] : unable to set SSL cipher list to '%s'.\n",
5223 curproxy->id, srv->id,
5224 srv->conf.file, srv->conf.line, srv->ssl_ctx.ciphers);
Emeric Brun94324a42012-10-11 14:00:19 +02005225 cfgerr++;
5226 }
Dirkjan Bussink415150f2018-09-14 11:14:21 +02005227
Emmanuel Hocdet839af572019-05-14 16:27:35 +02005228#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02005229 if (srv->ssl_ctx.ciphersuites &&
Pierre Cheynierbc34cd12019-03-21 16:15:47 +00005230 !SSL_CTX_set_ciphersuites(srv->ssl_ctx.ctx, srv->ssl_ctx.ciphersuites)) {
Dirkjan Bussink415150f2018-09-14 11:14:21 +02005231 ha_alert("Proxy '%s', server '%s' [%s:%d] : unable to set TLS 1.3 cipher suites to '%s'.\n",
5232 curproxy->id, srv->id,
5233 srv->conf.file, srv->conf.line, srv->ssl_ctx.ciphersuites);
5234 cfgerr++;
5235 }
5236#endif
Olivier Houchardc7566002018-11-20 23:33:50 +01005237#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
5238 if (srv->ssl_ctx.npn_str)
5239 SSL_CTX_set_next_proto_select_cb(ctx, ssl_sock_srv_select_protos, srv);
5240#endif
5241#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
5242 if (srv->ssl_ctx.alpn_str)
5243 SSL_CTX_set_alpn_protos(ctx, (unsigned char *)srv->ssl_ctx.alpn_str, srv->ssl_ctx.alpn_len);
5244#endif
5245
Emeric Brun94324a42012-10-11 14:00:19 +02005246
5247 return cfgerr;
5248}
5249
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005250/* Walks down the two trees in bind_conf and prepares all certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +02005251 * be NULL, in which case nothing is done. Returns the number of errors
5252 * encountered.
5253 */
Willy Tarreau03209342016-12-22 17:08:28 +01005254int ssl_sock_prepare_all_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02005255{
5256 struct ebmb_node *node;
5257 struct sni_ctx *sni;
5258 int err = 0;
5259
Willy Tarreaufce03112015-01-15 21:32:40 +01005260 /* Automatic memory computations need to know we use SSL there */
5261 global.ssl_used_frontend = 1;
5262
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01005263 /* Make sure openssl opens /dev/urandom before the chroot */
5264 if (!ssl_initialize_random()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005265 ha_alert("OpenSSL random data generator initialization failed.\n");
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01005266 err++;
5267 }
5268 /* Create initial_ctx used to start the ssl connection before do switchctx */
5269 if (!bind_conf->initial_ctx) {
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005270 err += ssl_sock_initial_ctx(bind_conf);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01005271 /* It should not be necessary to call this function, but it's
5272 necessary first to check and move all initialisation related
5273 to initial_ctx in ssl_sock_initial_ctx. */
5274 err += ssl_sock_prepare_ctx(bind_conf, NULL, bind_conf->initial_ctx);
5275 }
Emeric Brun0bed9942014-10-30 19:25:24 +01005276 if (bind_conf->default_ctx)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005277 err += ssl_sock_prepare_ctx(bind_conf, bind_conf->default_ssl_conf, bind_conf->default_ctx);
Emeric Brun0bed9942014-10-30 19:25:24 +01005278
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005279 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02005280 while (node) {
5281 sni = ebmb_entry(node, struct sni_ctx, name);
Emeric Brun0bed9942014-10-30 19:25:24 +01005282 if (!sni->order && sni->ctx != bind_conf->default_ctx)
5283 /* only initialize the CTX on its first occurrence and
5284 if it is not the default_ctx */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005285 err += ssl_sock_prepare_ctx(bind_conf, sni->conf, sni->ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02005286 node = ebmb_next(node);
5287 }
5288
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005289 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02005290 while (node) {
5291 sni = ebmb_entry(node, struct sni_ctx, name);
Emeric Brun0bed9942014-10-30 19:25:24 +01005292 if (!sni->order && sni->ctx != bind_conf->default_ctx)
5293 /* only initialize the CTX on its first occurrence and
5294 if it is not the default_ctx */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005295 err += ssl_sock_prepare_ctx(bind_conf, sni->conf, sni->ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02005296 node = ebmb_next(node);
5297 }
5298 return err;
5299}
5300
Willy Tarreau55d37912016-12-21 23:38:39 +01005301/* Prepares all the contexts for a bind_conf and allocates the shared SSL
5302 * context if needed. Returns < 0 on error, 0 on success. The warnings and
5303 * alerts are directly emitted since the rest of the stack does it below.
5304 */
5305int ssl_sock_prepare_bind_conf(struct bind_conf *bind_conf)
5306{
5307 struct proxy *px = bind_conf->frontend;
5308 int alloc_ctx;
5309 int err;
5310
5311 if (!bind_conf->is_ssl) {
5312 if (bind_conf->default_ctx) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005313 ha_warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
5314 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreau55d37912016-12-21 23:38:39 +01005315 }
5316 return 0;
5317 }
5318 if (!bind_conf->default_ctx) {
Emmanuel Hocdetaa0d6372017-08-09 11:24:25 +02005319 if (bind_conf->strict_sni && !bind_conf->generate_certs) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005320 ha_warning("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d], ssl connections will fail (use 'crt').\n",
5321 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetaa0d6372017-08-09 11:24:25 +02005322 }
5323 else {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005324 ha_alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
5325 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetaa0d6372017-08-09 11:24:25 +02005326 return -1;
5327 }
Willy Tarreau55d37912016-12-21 23:38:39 +01005328 }
William Lallemandc61c0b32017-12-04 18:46:39 +01005329 if (!ssl_shctx && global.tune.sslcachesize) {
William Lallemandc3cd35f2017-11-28 11:04:43 +01005330 alloc_ctx = shctx_init(&ssl_shctx, global.tune.sslcachesize,
Frédéric Lécailleb7838af2018-10-22 16:21:39 +02005331 sizeof(struct sh_ssl_sess_hdr) + SHSESS_BLOCK_MIN_SIZE, -1,
William Lallemandc3cd35f2017-11-28 11:04:43 +01005332 sizeof(*sh_ssl_sess_tree),
5333 ((global.nbthread > 1) || (!global_ssl.private_cache && (global.nbproc > 1))) ? 1 : 0);
Frédéric Lécaille4c8aa112018-10-25 20:22:46 +02005334 if (alloc_ctx <= 0) {
William Lallemandc3cd35f2017-11-28 11:04:43 +01005335 if (alloc_ctx == SHCTX_E_INIT_LOCK)
5336 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");
5337 else
5338 ha_alert("Unable to allocate SSL session cache.\n");
5339 return -1;
5340 }
5341 /* free block callback */
5342 ssl_shctx->free_block = sh_ssl_sess_free_blocks;
5343 /* init the root tree within the extra space */
5344 sh_ssl_sess_tree = (void *)ssl_shctx + sizeof(struct shared_context);
5345 *sh_ssl_sess_tree = EB_ROOT_UNIQUE;
Willy Tarreau55d37912016-12-21 23:38:39 +01005346 }
Willy Tarreau55d37912016-12-21 23:38:39 +01005347 err = 0;
5348 /* initialize all certificate contexts */
5349 err += ssl_sock_prepare_all_ctx(bind_conf);
5350
5351 /* initialize CA variables if the certificates generation is enabled */
5352 err += ssl_sock_load_ca(bind_conf);
5353
5354 return -err;
5355}
Christopher Faulet77fe80c2015-07-29 13:02:40 +02005356
5357/* release ssl context allocated for servers. */
5358void ssl_sock_free_srv_ctx(struct server *srv)
5359{
Olivier Houchardc7566002018-11-20 23:33:50 +01005360#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
5361 if (srv->ssl_ctx.alpn_str)
5362 free(srv->ssl_ctx.alpn_str);
5363#endif
Lukas Tribusda95fd92018-11-25 13:21:27 +01005364#ifdef OPENSSL_NPN_NEGOTIATED
Olivier Houchardc7566002018-11-20 23:33:50 +01005365 if (srv->ssl_ctx.npn_str)
5366 free(srv->ssl_ctx.npn_str);
Lukas Tribus7706b852018-11-26 22:57:17 +01005367#endif
Christopher Faulet77fe80c2015-07-29 13:02:40 +02005368 if (srv->ssl_ctx.ctx)
5369 SSL_CTX_free(srv->ssl_ctx.ctx);
5370}
5371
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005372/* Walks down the two trees in bind_conf and frees all the certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +02005373 * be NULL, in which case nothing is done. The default_ctx is nullified too.
5374 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005375void ssl_sock_free_all_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02005376{
5377 struct ebmb_node *node, *back;
5378 struct sni_ctx *sni;
5379
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005380 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02005381 while (node) {
5382 sni = ebmb_entry(node, struct sni_ctx, name);
5383 back = ebmb_next(node);
5384 ebmb_delete(node);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005385 if (!sni->order) { /* only free the CTX on its first occurrence */
Emeric Brunfc0421f2012-09-07 17:30:07 +02005386 SSL_CTX_free(sni->ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005387 ssl_sock_free_ssl_conf(sni->conf);
5388 free(sni->conf);
5389 sni->conf = NULL;
5390 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02005391 free(sni);
5392 node = back;
5393 }
5394
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005395 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02005396 while (node) {
5397 sni = ebmb_entry(node, struct sni_ctx, name);
5398 back = ebmb_next(node);
5399 ebmb_delete(node);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005400 if (!sni->order) { /* only free the CTX on its first occurrence */
Emeric Brunfc0421f2012-09-07 17:30:07 +02005401 SSL_CTX_free(sni->ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005402 ssl_sock_free_ssl_conf(sni->conf);
5403 free(sni->conf);
5404 sni->conf = NULL;
5405 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02005406 free(sni);
5407 node = back;
5408 }
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01005409 SSL_CTX_free(bind_conf->initial_ctx);
5410 bind_conf->initial_ctx = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005411 bind_conf->default_ctx = NULL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005412 bind_conf->default_ssl_conf = NULL;
Emeric Brune1f38db2012-09-03 20:36:47 +02005413}
5414
Willy Tarreau795cdab2016-12-22 17:30:54 +01005415/* Destroys all the contexts for a bind_conf. This is used during deinit(). */
5416void ssl_sock_destroy_bind_conf(struct bind_conf *bind_conf)
5417{
5418 ssl_sock_free_ca(bind_conf);
5419 ssl_sock_free_all_ctx(bind_conf);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005420 ssl_sock_free_ssl_conf(&bind_conf->ssl_conf);
Willy Tarreau795cdab2016-12-22 17:30:54 +01005421 free(bind_conf->ca_sign_file);
5422 free(bind_conf->ca_sign_pass);
Willy Tarreau17b4aa12018-07-17 10:05:32 +02005423 if (bind_conf->keys_ref && !--bind_conf->keys_ref->refcount) {
Willy Tarreau795cdab2016-12-22 17:30:54 +01005424 free(bind_conf->keys_ref->filename);
5425 free(bind_conf->keys_ref->tlskeys);
5426 LIST_DEL(&bind_conf->keys_ref->list);
5427 free(bind_conf->keys_ref);
5428 }
5429 bind_conf->keys_ref = NULL;
Willy Tarreau795cdab2016-12-22 17:30:54 +01005430 bind_conf->ca_sign_pass = NULL;
5431 bind_conf->ca_sign_file = NULL;
Willy Tarreau795cdab2016-12-22 17:30:54 +01005432}
5433
Christopher Faulet31af49d2015-06-09 17:29:50 +02005434/* Load CA cert file and private key used to generate certificates */
5435int
Willy Tarreau03209342016-12-22 17:08:28 +01005436ssl_sock_load_ca(struct bind_conf *bind_conf)
Christopher Faulet31af49d2015-06-09 17:29:50 +02005437{
Willy Tarreau03209342016-12-22 17:08:28 +01005438 struct proxy *px = bind_conf->frontend;
Christopher Faulet31af49d2015-06-09 17:29:50 +02005439 FILE *fp;
5440 X509 *cacert = NULL;
5441 EVP_PKEY *capkey = NULL;
5442 int err = 0;
5443
Christopher Fauletf8bb0ce2017-09-15 09:52:49 +02005444 if (!bind_conf->generate_certs)
Christopher Faulet31af49d2015-06-09 17:29:50 +02005445 return err;
5446
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005447#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Emeric Brun821bb9b2017-06-15 16:37:39 +02005448 if (global_ssl.ctx_cache) {
Willy Tarreauef934602016-12-22 23:12:01 +01005449 ssl_ctx_lru_tree = lru64_new(global_ssl.ctx_cache);
Emeric Brun821bb9b2017-06-15 16:37:39 +02005450 }
Christopher Fauletd2cab922015-07-28 16:03:47 +02005451 ssl_ctx_lru_seed = (unsigned int)time(NULL);
Emeric Brun821bb9b2017-06-15 16:37:39 +02005452 ssl_ctx_serial = now_ms;
Willy Tarreaua84c2672015-10-09 12:10:13 +02005453#endif
Christopher Fauletd2cab922015-07-28 16:03:47 +02005454
Christopher Faulet31af49d2015-06-09 17:29:50 +02005455 if (!bind_conf->ca_sign_file) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005456 ha_alert("Proxy '%s': cannot enable certificate generation, "
5457 "no CA certificate File configured at [%s:%d].\n",
5458 px->id, bind_conf->file, bind_conf->line);
Christopher Faulet31af49d2015-06-09 17:29:50 +02005459 goto load_error;
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005460 }
Christopher Faulet31af49d2015-06-09 17:29:50 +02005461
5462 /* read in the CA certificate */
5463 if (!(fp = fopen(bind_conf->ca_sign_file, "r"))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005464 ha_alert("Proxy '%s': Failed to read CA certificate file '%s' at [%s:%d].\n",
5465 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Faulet31af49d2015-06-09 17:29:50 +02005466 goto load_error;
5467 }
5468 if (!(cacert = PEM_read_X509(fp, NULL, NULL, NULL))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005469 ha_alert("Proxy '%s': Failed to read CA certificate file '%s' at [%s:%d].\n",
5470 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005471 goto read_error;
Christopher Faulet31af49d2015-06-09 17:29:50 +02005472 }
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005473 rewind(fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02005474 if (!(capkey = PEM_read_PrivateKey(fp, NULL, NULL, bind_conf->ca_sign_pass))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005475 ha_alert("Proxy '%s': Failed to read CA private key file '%s' at [%s:%d].\n",
5476 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005477 goto read_error;
Christopher Faulet31af49d2015-06-09 17:29:50 +02005478 }
Christopher Faulet31af49d2015-06-09 17:29:50 +02005479
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005480 fclose (fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02005481 bind_conf->ca_sign_cert = cacert;
5482 bind_conf->ca_sign_pkey = capkey;
5483 return err;
5484
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005485 read_error:
5486 fclose (fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02005487 if (capkey) EVP_PKEY_free(capkey);
5488 if (cacert) X509_free(cacert);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005489 load_error:
5490 bind_conf->generate_certs = 0;
5491 err++;
Christopher Faulet31af49d2015-06-09 17:29:50 +02005492 return err;
5493}
5494
5495/* Release CA cert and private key used to generate certificated */
5496void
5497ssl_sock_free_ca(struct bind_conf *bind_conf)
5498{
Christopher Faulet31af49d2015-06-09 17:29:50 +02005499 if (bind_conf->ca_sign_pkey)
5500 EVP_PKEY_free(bind_conf->ca_sign_pkey);
5501 if (bind_conf->ca_sign_cert)
5502 X509_free(bind_conf->ca_sign_cert);
Willy Tarreau94ff03a2016-12-22 17:57:46 +01005503 bind_conf->ca_sign_pkey = NULL;
5504 bind_conf->ca_sign_cert = NULL;
Christopher Faulet31af49d2015-06-09 17:29:50 +02005505}
5506
Emeric Brun46591952012-05-18 15:47:34 +02005507/*
5508 * This function is called if SSL * context is not yet allocated. The function
5509 * is designed to be called before any other data-layer operation and sets the
5510 * handshake flag on the connection. It is safe to call it multiple times.
5511 * It returns 0 on success and -1 in error case.
5512 */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005513static int ssl_sock_init(struct connection *conn, void **xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02005514{
Olivier Houchard66ab4982019-02-26 18:37:15 +01005515 struct ssl_sock_ctx *ctx;
Emeric Brun46591952012-05-18 15:47:34 +02005516 /* already initialized */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005517 if (*xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02005518 return 0;
5519
Willy Tarreau3c728722014-01-23 13:50:42 +01005520 if (!conn_ctrl_ready(conn))
Willy Tarreauf79c8172013-10-21 16:30:56 +02005521 return 0;
5522
Olivier Houchard66ab4982019-02-26 18:37:15 +01005523 ctx = pool_alloc(ssl_sock_ctx_pool);
5524 if (!ctx) {
5525 conn->err_code = CO_ER_SSL_NO_MEM;
5526 return -1;
5527 }
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02005528 ctx->wait_event.tasklet = tasklet_new();
5529 if (!ctx->wait_event.tasklet) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02005530 conn->err_code = CO_ER_SSL_NO_MEM;
5531 pool_free(ssl_sock_ctx_pool, ctx);
5532 return -1;
5533 }
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02005534 ctx->wait_event.tasklet->process = ssl_sock_io_cb;
5535 ctx->wait_event.tasklet->context = ctx;
Olivier Houchardea8dd942019-05-20 14:02:16 +02005536 ctx->wait_event.events = 0;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01005537 ctx->sent_early_data = 0;
5538 ctx->tmp_early_data = -1;
Olivier Houcharda8955d52019-04-07 22:00:38 +02005539 ctx->conn = conn;
Olivier Houchard81284e62019-06-06 13:21:23 +02005540 ctx->send_wait = NULL;
5541 ctx->recv_wait = NULL;
Emeric Brun5762a0d2019-09-06 15:36:02 +02005542 ctx->xprt_st = 0;
5543 ctx->xprt_ctx = NULL;
Olivier Houcharda8955d52019-04-07 22:00:38 +02005544
5545 /* Only work with sockets for now, this should be adapted when we'll
5546 * add QUIC support.
5547 */
5548 ctx->xprt = xprt_get(XPRT_RAW);
Olivier Houchard19afb272019-05-23 18:24:07 +02005549 if (ctx->xprt->init) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02005550 if (ctx->xprt->init(conn, &ctx->xprt_ctx) != 0)
5551 goto err;
Olivier Houchard19afb272019-05-23 18:24:07 +02005552 }
Olivier Houchard66ab4982019-02-26 18:37:15 +01005553
Willy Tarreau20879a02012-12-03 16:32:10 +01005554 if (global.maxsslconn && sslconns >= global.maxsslconn) {
5555 conn->err_code = CO_ER_SSL_TOO_MANY;
Olivier Houchardea8dd942019-05-20 14:02:16 +02005556 goto err;
Willy Tarreau20879a02012-12-03 16:32:10 +01005557 }
Willy Tarreau403edff2012-09-06 11:58:37 +02005558
Emeric Brun46591952012-05-18 15:47:34 +02005559 /* If it is in client mode initiate SSL session
5560 in connect state otherwise accept state */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01005561 if (objt_server(conn->target)) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005562 int may_retry = 1;
5563
5564 retry_connect:
Emeric Brun46591952012-05-18 15:47:34 +02005565 /* Alloc a new SSL session ctx */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005566 ctx->ssl = SSL_new(__objt_server(conn->target)->ssl_ctx.ctx);
5567 if (!ctx->ssl) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005568 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005569 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005570 goto retry_connect;
5571 }
Willy Tarreau20879a02012-12-03 16:32:10 +01005572 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01005573 goto err;
Willy Tarreau20879a02012-12-03 16:32:10 +01005574 }
Olivier Houcharda8955d52019-04-07 22:00:38 +02005575 ctx->bio = BIO_new(ha_meth);
5576 if (!ctx->bio) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005577 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005578 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005579 goto retry_connect;
5580 }
Emeric Brun55476152014-11-12 17:35:37 +01005581 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01005582 goto err;
Emeric Brun55476152014-11-12 17:35:37 +01005583 }
Olivier Houcharda8955d52019-04-07 22:00:38 +02005584 BIO_set_data(ctx->bio, ctx);
Olivier Houcharda8955d52019-04-07 22:00:38 +02005585 SSL_set_bio(ctx->ssl, ctx->bio, ctx->bio);
Emeric Brun46591952012-05-18 15:47:34 +02005586
Evan Broderbe554312013-06-27 00:05:25 -07005587 /* set connection pointer */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005588 if (!SSL_set_ex_data(ctx->ssl, ssl_app_data_index, conn)) {
5589 SSL_free(ctx->ssl);
5590 ctx->ssl = NULL;
Emeric Brun55476152014-11-12 17:35:37 +01005591 conn->xprt_ctx = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005592 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005593 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005594 goto retry_connect;
5595 }
Emeric Brun55476152014-11-12 17:35:37 +01005596 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01005597 goto err;
Emeric Brun55476152014-11-12 17:35:37 +01005598 }
5599
Olivier Houchard66ab4982019-02-26 18:37:15 +01005600 SSL_set_connect_state(ctx->ssl);
Willy Tarreau07d94e42018-09-20 10:57:52 +02005601 if (__objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr) {
5602 const unsigned char *ptr = __objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr;
5603 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 +01005604 if (sess && !SSL_set_session(ctx->ssl, sess)) {
Olivier Houcharde6060c52017-11-16 17:42:52 +01005605 SSL_SESSION_free(sess);
Willy Tarreau07d94e42018-09-20 10:57:52 +02005606 free(__objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr);
5607 __objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr = NULL;
Olivier Houcharde6060c52017-11-16 17:42:52 +01005608 } else if (sess) {
5609 SSL_SESSION_free(sess);
Emeric Brun55476152014-11-12 17:35:37 +01005610 }
5611 }
Evan Broderbe554312013-06-27 00:05:25 -07005612
Emeric Brun46591952012-05-18 15:47:34 +02005613 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +02005614 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Willy Tarreau403edff2012-09-06 11:58:37 +02005615
Olivier Houchard2be5a4c2019-03-08 18:54:43 +01005616 _HA_ATOMIC_ADD(&sslconns, 1);
5617 _HA_ATOMIC_ADD(&totalsslconns, 1);
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005618 *xprt_ctx = ctx;
Olivier Houchardea8dd942019-05-20 14:02:16 +02005619 /* Start the handshake */
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02005620 tasklet_wakeup(ctx->wait_event.tasklet);
Olivier Houchardea8dd942019-05-20 14:02:16 +02005621 if (conn->flags & CO_FL_ERROR)
5622 goto err;
Emeric Brun46591952012-05-18 15:47:34 +02005623 return 0;
5624 }
Willy Tarreau3fdb3662012-11-12 00:42:33 +01005625 else if (objt_listener(conn->target)) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005626 int may_retry = 1;
5627
5628 retry_accept:
Emeric Brun46591952012-05-18 15:47:34 +02005629 /* Alloc a new SSL session ctx */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005630 ctx->ssl = SSL_new(__objt_listener(conn->target)->bind_conf->initial_ctx);
5631 if (!ctx->ssl) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005632 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005633 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005634 goto retry_accept;
5635 }
Willy Tarreau20879a02012-12-03 16:32:10 +01005636 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01005637 goto err;
Willy Tarreau20879a02012-12-03 16:32:10 +01005638 }
Emeric Brun46591952012-05-18 15:47:34 +02005639
Olivier Houcharda8955d52019-04-07 22:00:38 +02005640 ctx->bio = BIO_new(ha_meth);
5641 if (!ctx->bio) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005642 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005643 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005644 goto retry_accept;
5645 }
Emeric Brun55476152014-11-12 17:35:37 +01005646 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01005647 goto err;
Emeric Brun55476152014-11-12 17:35:37 +01005648 }
Olivier Houcharda8955d52019-04-07 22:00:38 +02005649 BIO_set_data(ctx->bio, ctx);
Olivier Houcharda8955d52019-04-07 22:00:38 +02005650 SSL_set_bio(ctx->ssl, ctx->bio, ctx->bio);
Emeric Brun46591952012-05-18 15:47:34 +02005651
Emeric Brune1f38db2012-09-03 20:36:47 +02005652 /* set connection pointer */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005653 if (!SSL_set_ex_data(ctx->ssl, ssl_app_data_index, conn)) {
5654 SSL_free(ctx->ssl);
5655 ctx->ssl = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005656 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005657 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005658 goto retry_accept;
5659 }
Emeric Brun55476152014-11-12 17:35:37 +01005660 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01005661 goto err;
Emeric Brun55476152014-11-12 17:35:37 +01005662 }
5663
Olivier Houchard66ab4982019-02-26 18:37:15 +01005664 SSL_set_accept_state(ctx->ssl);
Emeric Brune1f38db2012-09-03 20:36:47 +02005665
Emeric Brun46591952012-05-18 15:47:34 +02005666 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +02005667 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Emmanuel Hocdetf967c312019-08-05 18:04:16 +02005668#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Olivier Houchardc2aae742017-09-22 18:26:28 +02005669 conn->flags |= CO_FL_EARLY_SSL_HS;
5670#endif
Willy Tarreau403edff2012-09-06 11:58:37 +02005671
Olivier Houchard2be5a4c2019-03-08 18:54:43 +01005672 _HA_ATOMIC_ADD(&sslconns, 1);
5673 _HA_ATOMIC_ADD(&totalsslconns, 1);
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005674 *xprt_ctx = ctx;
Olivier Houchardea8dd942019-05-20 14:02:16 +02005675 /* Start the handshake */
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02005676 tasklet_wakeup(ctx->wait_event.tasklet);
Olivier Houchardea8dd942019-05-20 14:02:16 +02005677 if (conn->flags & CO_FL_ERROR)
5678 goto err;
Emeric Brun46591952012-05-18 15:47:34 +02005679 return 0;
5680 }
5681 /* don't know how to handle such a target */
Willy Tarreau20879a02012-12-03 16:32:10 +01005682 conn->err_code = CO_ER_SSL_NO_TARGET;
Olivier Houchard66ab4982019-02-26 18:37:15 +01005683err:
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02005684 if (ctx && ctx->wait_event.tasklet)
5685 tasklet_free(ctx->wait_event.tasklet);
Olivier Houchard66ab4982019-02-26 18:37:15 +01005686 pool_free(ssl_sock_ctx_pool, ctx);
Emeric Brun46591952012-05-18 15:47:34 +02005687 return -1;
5688}
5689
5690
5691/* This is the callback which is used when an SSL handshake is pending. It
5692 * updates the FD status if it wants some polling before being called again.
5693 * It returns 0 if it fails in a fatal way or needs to poll to go further,
5694 * otherwise it returns non-zero and removes itself from the connection's
5695 * flags (the bit is provided in <flag> by the caller).
5696 */
Olivier Houchard000694c2019-05-23 14:45:12 +02005697static int ssl_sock_handshake(struct connection *conn, unsigned int flag)
Emeric Brun46591952012-05-18 15:47:34 +02005698{
Olivier Houchard66ab4982019-02-26 18:37:15 +01005699 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
Emeric Brun46591952012-05-18 15:47:34 +02005700 int ret;
5701
Willy Tarreau3c728722014-01-23 13:50:42 +01005702 if (!conn_ctrl_ready(conn))
Willy Tarreauf79c8172013-10-21 16:30:56 +02005703 return 0;
5704
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005705 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02005706 goto out_error;
5707
Willy Tarreau5db847a2019-05-09 14:13:35 +02005708#if HA_OPENSSL_VERSION_NUMBER >= 0x10101000L
Olivier Houchardc2aae742017-09-22 18:26:28 +02005709 /*
5710 * Check if we have early data. If we do, we have to read them
5711 * before SSL_do_handshake() is called, And there's no way to
5712 * detect early data, except to try to read them
5713 */
5714 if (conn->flags & CO_FL_EARLY_SSL_HS) {
5715 size_t read_data;
5716
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01005717 ret = SSL_read_early_data(ctx->ssl, &ctx->tmp_early_data,
Olivier Houchardc2aae742017-09-22 18:26:28 +02005718 1, &read_data);
5719 if (ret == SSL_READ_EARLY_DATA_ERROR)
5720 goto check_error;
5721 if (ret == SSL_READ_EARLY_DATA_SUCCESS) {
5722 conn->flags &= ~(CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN);
5723 return 1;
5724 } else
5725 conn->flags &= ~CO_FL_EARLY_SSL_HS;
5726 }
5727#endif
Emeric Brun674b7432012-11-08 19:21:55 +01005728 /* If we use SSL_do_handshake to process a reneg initiated by
5729 * the remote peer, it sometimes returns SSL_ERROR_SSL.
5730 * Usually SSL_write and SSL_read are used and process implicitly
5731 * the reneg handshake.
5732 * Here we use SSL_peek as a workaround for reneg.
5733 */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005734 if ((conn->flags & CO_FL_CONNECTED) && SSL_renegotiate_pending(ctx->ssl)) {
Emeric Brun674b7432012-11-08 19:21:55 +01005735 char c;
5736
Olivier Houchard66ab4982019-02-26 18:37:15 +01005737 ret = SSL_peek(ctx->ssl, &c, 1);
Emeric Brun674b7432012-11-08 19:21:55 +01005738 if (ret <= 0) {
5739 /* handshake may have not been completed, let's find why */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005740 ret = SSL_get_error(ctx->ssl, ret);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005741
Emeric Brun674b7432012-11-08 19:21:55 +01005742 if (ret == SSL_ERROR_WANT_WRITE) {
5743 /* SSL handshake needs to write, L4 connection may not be ready */
Olivier Houchard03abf2d2019-05-28 10:12:02 +02005744 if (!(ctx->wait_event.events & SUB_RETRY_SEND))
Olivier Houchardea8dd942019-05-20 14:02:16 +02005745 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_SEND, &ctx->wait_event);
Emeric Brun674b7432012-11-08 19:21:55 +01005746 return 0;
5747 }
5748 else if (ret == SSL_ERROR_WANT_READ) {
5749 /* handshake may have been completed but we have
5750 * no more data to read.
5751 */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005752 if (!SSL_renegotiate_pending(ctx->ssl)) {
Emeric Brun674b7432012-11-08 19:21:55 +01005753 ret = 1;
5754 goto reneg_ok;
5755 }
5756 /* SSL handshake needs to read, L4 connection is ready */
Olivier Houchard03abf2d2019-05-28 10:12:02 +02005757 if (!(ctx->wait_event.events & SUB_RETRY_RECV))
Olivier Houchardea8dd942019-05-20 14:02:16 +02005758 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_RECV, &ctx->wait_event);
Emeric Brun674b7432012-11-08 19:21:55 +01005759 return 0;
5760 }
Willy Tarreau5db847a2019-05-09 14:13:35 +02005761#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005762 else if (ret == SSL_ERROR_WANT_ASYNC) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02005763 ssl_async_process_fds(ctx);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005764 return 0;
5765 }
5766#endif
Emeric Brun674b7432012-11-08 19:21:55 +01005767 else if (ret == SSL_ERROR_SYSCALL) {
5768 /* if errno is null, then connection was successfully established */
5769 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
5770 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Willy Tarreau20879a02012-12-03 16:32:10 +01005771 if (!conn->err_code) {
Lukas Tribus49799162019-07-08 14:29:15 +02005772#if defined(OPENSSL_IS_BORINGSSL) || defined(LIBRESSL_VERSION_NUMBER)
5773 /* do not handle empty handshakes in BoringSSL or LibreSSL */
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005774 conn->err_code = CO_ER_SSL_HANDSHAKE;
5775#else
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005776 int empty_handshake;
Willy Tarreau5db847a2019-05-09 14:13:35 +02005777#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL)
Lukas Tribus49799162019-07-08 14:29:15 +02005778 /* use SSL_get_state() in OpenSSL >= 1.1.0; SSL_state() is broken */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005779 OSSL_HANDSHAKE_STATE state = SSL_get_state((SSL *)ctx->ssl);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005780 empty_handshake = state == TLS_ST_BEFORE;
5781#else
Lukas Tribus49799162019-07-08 14:29:15 +02005782 /* access packet_length directly in OpenSSL <= 1.0.2; SSL_state() is broken */
5783 empty_handshake = !ctx->ssl->packet_length;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005784#endif
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005785 if (empty_handshake) {
Emeric Brun29f037d2014-04-25 19:05:36 +02005786 if (!errno) {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01005787 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emeric Brun29f037d2014-04-25 19:05:36 +02005788 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5789 else
5790 conn->err_code = CO_ER_SSL_EMPTY;
5791 }
5792 else {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01005793 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emeric Brun29f037d2014-04-25 19:05:36 +02005794 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5795 else
5796 conn->err_code = CO_ER_SSL_ABORT;
5797 }
5798 }
5799 else {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01005800 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emeric Brun29f037d2014-04-25 19:05:36 +02005801 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
Willy Tarreau20879a02012-12-03 16:32:10 +01005802 else
Emeric Brun29f037d2014-04-25 19:05:36 +02005803 conn->err_code = CO_ER_SSL_HANDSHAKE;
5804 }
Lukas Tribus49799162019-07-08 14:29:15 +02005805#endif /* BoringSSL or LibreSSL */
Willy Tarreau20879a02012-12-03 16:32:10 +01005806 }
Emeric Brun674b7432012-11-08 19:21:55 +01005807 goto out_error;
5808 }
5809 else {
5810 /* Fail on all other handshake errors */
5811 /* Note: OpenSSL may leave unread bytes in the socket's
5812 * buffer, causing an RST to be emitted upon close() on
5813 * TCP sockets. We first try to drain possibly pending
5814 * data to avoid this as much as possible.
5815 */
Willy Tarreaud85c4852015-03-13 00:40:28 +01005816 conn_sock_drain(conn);
Willy Tarreau20879a02012-12-03 16:32:10 +01005817 if (!conn->err_code)
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01005818 conn->err_code = (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT) ?
Willy Tarreauf51c6982014-04-25 20:02:39 +02005819 CO_ER_SSL_KILLED_HB : CO_ER_SSL_HANDSHAKE;
Emeric Brun674b7432012-11-08 19:21:55 +01005820 goto out_error;
5821 }
5822 }
5823 /* read some data: consider handshake completed */
5824 goto reneg_ok;
5825 }
Olivier Houchard66ab4982019-02-26 18:37:15 +01005826 ret = SSL_do_handshake(ctx->ssl);
Olivier Houchardc2aae742017-09-22 18:26:28 +02005827check_error:
Emeric Brun46591952012-05-18 15:47:34 +02005828 if (ret != 1) {
5829 /* handshake did not complete, let's find why */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005830 ret = SSL_get_error(ctx->ssl, ret);
Emeric Brun46591952012-05-18 15:47:34 +02005831
5832 if (ret == SSL_ERROR_WANT_WRITE) {
5833 /* SSL handshake needs to write, L4 connection may not be ready */
Olivier Houchard03abf2d2019-05-28 10:12:02 +02005834 if (!(ctx->wait_event.events & SUB_RETRY_SEND))
Olivier Houchardea8dd942019-05-20 14:02:16 +02005835 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_SEND, &ctx->wait_event);
Emeric Brun46591952012-05-18 15:47:34 +02005836 return 0;
5837 }
5838 else if (ret == SSL_ERROR_WANT_READ) {
5839 /* SSL handshake needs to read, L4 connection is ready */
Olivier Houchardea8dd942019-05-20 14:02:16 +02005840 if (!(ctx->wait_event.events & SUB_RETRY_RECV))
Olivier Houchardea8dd942019-05-20 14:02:16 +02005841 ctx->xprt->subscribe(conn, ctx->xprt_ctx,
5842 SUB_RETRY_RECV, &ctx->wait_event);
Emeric Brun46591952012-05-18 15:47:34 +02005843 return 0;
5844 }
Willy Tarreau5db847a2019-05-09 14:13:35 +02005845#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005846 else if (ret == SSL_ERROR_WANT_ASYNC) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02005847 ssl_async_process_fds(ctx);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005848 return 0;
5849 }
5850#endif
Willy Tarreau89230192012-09-28 20:22:13 +02005851 else if (ret == SSL_ERROR_SYSCALL) {
5852 /* if errno is null, then connection was successfully established */
5853 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
5854 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005855 if (!conn->err_code) {
Lukas Tribus49799162019-07-08 14:29:15 +02005856#if defined(OPENSSL_IS_BORINGSSL) || defined(LIBRESSL_VERSION_NUMBER)
5857 /* do not handle empty handshakes in BoringSSL or LibreSSL */
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005858 conn->err_code = CO_ER_SSL_HANDSHAKE;
5859#else
5860 int empty_handshake;
Willy Tarreau5db847a2019-05-09 14:13:35 +02005861#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL)
Lukas Tribus49799162019-07-08 14:29:15 +02005862 /* use SSL_get_state() in OpenSSL >= 1.1.0; SSL_state() is broken */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005863 OSSL_HANDSHAKE_STATE state = SSL_get_state(ctx->ssl);
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005864 empty_handshake = state == TLS_ST_BEFORE;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005865#else
Lukas Tribus49799162019-07-08 14:29:15 +02005866 /* access packet_length directly in OpenSSL <= 1.0.2; SSL_state() is broken */
5867 empty_handshake = !ctx->ssl->packet_length;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005868#endif
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005869 if (empty_handshake) {
5870 if (!errno) {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01005871 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005872 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5873 else
5874 conn->err_code = CO_ER_SSL_EMPTY;
5875 }
5876 else {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01005877 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005878 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5879 else
5880 conn->err_code = CO_ER_SSL_ABORT;
5881 }
Emeric Brun29f037d2014-04-25 19:05:36 +02005882 }
5883 else {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01005884 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emeric Brun29f037d2014-04-25 19:05:36 +02005885 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5886 else
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005887 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun29f037d2014-04-25 19:05:36 +02005888 }
Lukas Tribus49799162019-07-08 14:29:15 +02005889#endif /* BoringSSL or LibreSSL */
Emeric Brun29f037d2014-04-25 19:05:36 +02005890 }
Willy Tarreau89230192012-09-28 20:22:13 +02005891 goto out_error;
5892 }
Emeric Brun46591952012-05-18 15:47:34 +02005893 else {
5894 /* Fail on all other handshake errors */
Willy Tarreau566dc552012-10-19 20:52:18 +02005895 /* Note: OpenSSL may leave unread bytes in the socket's
5896 * buffer, causing an RST to be emitted upon close() on
5897 * TCP sockets. We first try to drain possibly pending
5898 * data to avoid this as much as possible.
5899 */
Willy Tarreaud85c4852015-03-13 00:40:28 +01005900 conn_sock_drain(conn);
Willy Tarreau20879a02012-12-03 16:32:10 +01005901 if (!conn->err_code)
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01005902 conn->err_code = (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT) ?
Willy Tarreauf51c6982014-04-25 20:02:39 +02005903 CO_ER_SSL_KILLED_HB : CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02005904 goto out_error;
5905 }
5906 }
Willy Tarreau5db847a2019-05-09 14:13:35 +02005907#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Olivier Houchard522eea72017-11-03 16:27:47 +01005908 else {
5909 /*
5910 * If the server refused the early data, we have to send a
5911 * 425 to the client, as we no longer have the data to sent
5912 * them again.
5913 */
5914 if ((conn->flags & CO_FL_EARLY_DATA) && (objt_server(conn->target))) {
Olivier Houchard66ab4982019-02-26 18:37:15 +01005915 if (SSL_get_early_data_status(ctx->ssl) == SSL_EARLY_DATA_REJECTED) {
Olivier Houchard522eea72017-11-03 16:27:47 +01005916 conn->err_code = CO_ER_SSL_EARLY_FAILED;
5917 goto out_error;
5918 }
5919 }
5920 }
5921#endif
5922
Emeric Brun46591952012-05-18 15:47:34 +02005923
Emeric Brun674b7432012-11-08 19:21:55 +01005924reneg_ok:
Emeric Brunb5e42a82017-06-06 12:35:14 +00005925
Willy Tarreau5db847a2019-05-09 14:13:35 +02005926#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00005927 /* ASYNC engine API doesn't support moving read/write
5928 * buffers. So we disable ASYNC mode right after
5929 * the handshake to avoid buffer oveflows.
5930 */
5931 if (global_ssl.async)
Olivier Houchard66ab4982019-02-26 18:37:15 +01005932 SSL_clear_mode(ctx->ssl, SSL_MODE_ASYNC);
Emeric Brunb5e42a82017-06-06 12:35:14 +00005933#endif
Emeric Brun46591952012-05-18 15:47:34 +02005934 /* Handshake succeeded */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005935 if (!SSL_session_reused(ctx->ssl)) {
Willy Tarreau0c9c2722014-05-28 12:28:58 +02005936 if (objt_server(conn->target)) {
5937 update_freq_ctr(&global.ssl_be_keys_per_sec, 1);
5938 if (global.ssl_be_keys_per_sec.curr_ctr > global.ssl_be_keys_max)
5939 global.ssl_be_keys_max = global.ssl_be_keys_per_sec.curr_ctr;
Emeric Brun46591952012-05-18 15:47:34 +02005940 }
Willy Tarreau0c9c2722014-05-28 12:28:58 +02005941 else {
5942 update_freq_ctr(&global.ssl_fe_keys_per_sec, 1);
5943 if (global.ssl_fe_keys_per_sec.curr_ctr > global.ssl_fe_keys_max)
5944 global.ssl_fe_keys_max = global.ssl_fe_keys_per_sec.curr_ctr;
5945 }
Emeric Brun46591952012-05-18 15:47:34 +02005946 }
5947
5948 /* The connection is now established at both layers, it's time to leave */
5949 conn->flags &= ~(flag | CO_FL_WAIT_L4_CONN | CO_FL_WAIT_L6_CONN);
5950 return 1;
5951
5952 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01005953 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02005954 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01005955 ERR_clear_error();
5956
Emeric Brun9fa89732012-10-04 17:09:56 +02005957 /* free resumed session if exists */
Willy Tarreau07d94e42018-09-20 10:57:52 +02005958 if (objt_server(conn->target) && __objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr) {
5959 free(__objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr);
5960 __objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr = NULL;
Emeric Brun9fa89732012-10-04 17:09:56 +02005961 }
5962
Emeric Brun46591952012-05-18 15:47:34 +02005963 /* Fail on all other handshake errors */
5964 conn->flags |= CO_FL_ERROR;
Willy Tarreau20879a02012-12-03 16:32:10 +01005965 if (!conn->err_code)
5966 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02005967 return 0;
5968}
5969
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005970static int ssl_subscribe(struct connection *conn, void *xprt_ctx, int event_type, void *param)
Olivier Houcharddf357842019-03-21 16:30:07 +01005971{
Olivier Houchardea8dd942019-05-20 14:02:16 +02005972 struct wait_event *sw;
5973 struct ssl_sock_ctx *ctx = xprt_ctx;
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005974
Olivier Houchard0ff28652019-06-24 18:57:39 +02005975 if (!ctx)
5976 return -1;
5977
Olivier Houchardea8dd942019-05-20 14:02:16 +02005978 if (event_type & SUB_RETRY_RECV) {
5979 sw = param;
5980 BUG_ON(ctx->recv_wait != NULL || (sw->events & SUB_RETRY_RECV));
5981 sw->events |= SUB_RETRY_RECV;
5982 ctx->recv_wait = sw;
5983 if (!(conn->flags & CO_FL_SSL_WAIT_HS) &&
5984 !(ctx->wait_event.events & SUB_RETRY_RECV))
5985 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_RECV, &ctx->wait_event);
5986 event_type &= ~SUB_RETRY_RECV;
5987 }
5988 if (event_type & SUB_RETRY_SEND) {
5989sw = param;
5990 BUG_ON(ctx->send_wait != NULL || (sw->events & SUB_RETRY_SEND));
5991 sw->events |= SUB_RETRY_SEND;
5992 ctx->send_wait = sw;
5993 if (!(conn->flags & CO_FL_SSL_WAIT_HS) &&
5994 !(ctx->wait_event.events & SUB_RETRY_SEND))
5995 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_SEND, &ctx->wait_event);
5996 event_type &= ~SUB_RETRY_SEND;
5997
5998 }
5999 if (event_type != 0)
6000 return -1;
6001 return 0;
Olivier Houcharddf357842019-03-21 16:30:07 +01006002}
6003
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006004static int ssl_unsubscribe(struct connection *conn, void *xprt_ctx, int event_type, void *param)
Olivier Houcharddf357842019-03-21 16:30:07 +01006005{
Olivier Houchardea8dd942019-05-20 14:02:16 +02006006 struct wait_event *sw;
6007 struct ssl_sock_ctx *ctx = xprt_ctx;
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006008
Olivier Houchardea8dd942019-05-20 14:02:16 +02006009 if (event_type & SUB_RETRY_RECV) {
6010 sw = param;
6011 BUG_ON(ctx->recv_wait != sw);
6012 ctx->recv_wait = NULL;
6013 sw->events &= ~SUB_RETRY_RECV;
6014 /* If we subscribed, and we're not doing the handshake,
6015 * then we subscribed because the upper layer asked for it,
6016 * as the upper layer is no longer interested, we can
6017 * unsubscribe too.
6018 */
6019 if (!(ctx->conn->flags & CO_FL_SSL_WAIT_HS) &&
6020 (ctx->wait_event.events & SUB_RETRY_RECV))
6021 conn_unsubscribe(conn, ctx->xprt_ctx, SUB_RETRY_RECV,
6022 &ctx->wait_event);
6023 }
6024 if (event_type & SUB_RETRY_SEND) {
6025 sw = param;
6026 BUG_ON(ctx->send_wait != sw);
6027 ctx->send_wait = NULL;
6028 sw->events &= ~SUB_RETRY_SEND;
6029 if (!(ctx->conn->flags & CO_FL_SSL_WAIT_HS) &&
6030 (ctx->wait_event.events & SUB_RETRY_SEND))
6031 conn_unsubscribe(conn, ctx->xprt_ctx, SUB_RETRY_SEND,
6032 &ctx->wait_event);
6033
6034 }
6035
6036 return 0;
Olivier Houcharddf357842019-03-21 16:30:07 +01006037}
6038
Olivier Houchard2e055482019-05-27 19:50:12 +02006039/* Use the provided XPRT as an underlying XPRT, and provide the old one.
6040 * Returns 0 on success, and non-zero on failure.
6041 */
6042static 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)
6043{
6044 struct ssl_sock_ctx *ctx = xprt_ctx;
6045
6046 if (oldxprt_ops != NULL)
6047 *oldxprt_ops = ctx->xprt;
6048 if (oldxprt_ctx != NULL)
6049 *oldxprt_ctx = ctx->xprt_ctx;
6050 ctx->xprt = toadd_ops;
6051 ctx->xprt_ctx = toadd_ctx;
6052 return 0;
6053}
6054
Olivier Houchard5149b592019-05-23 17:47:36 +02006055/* Remove the specified xprt. If if it our underlying XPRT, remove it and
6056 * return 0, otherwise just call the remove_xprt method from the underlying
6057 * XPRT.
6058 */
6059static int ssl_remove_xprt(struct connection *conn, void *xprt_ctx, void *toremove_ctx, const struct xprt_ops *newops, void *newctx)
6060{
6061 struct ssl_sock_ctx *ctx = xprt_ctx;
6062
6063 if (ctx->xprt_ctx == toremove_ctx) {
6064 ctx->xprt_ctx = newctx;
6065 ctx->xprt = newops;
6066 return 0;
6067 }
6068 return (ctx->xprt->remove_xprt(conn, ctx->xprt_ctx, toremove_ctx, newops, newctx));
6069}
6070
Olivier Houchardea8dd942019-05-20 14:02:16 +02006071static struct task *ssl_sock_io_cb(struct task *t, void *context, unsigned short state)
6072{
6073 struct ssl_sock_ctx *ctx = context;
6074
6075 /* First if we're doing an handshake, try that */
6076 if (ctx->conn->flags & CO_FL_SSL_WAIT_HS)
6077 ssl_sock_handshake(ctx->conn, CO_FL_SSL_WAIT_HS);
6078 /* If we had an error, or the handshake is done and I/O is available,
6079 * let the upper layer know.
6080 * If no mux was set up yet, and nobody subscribed, then call
6081 * xprt_done_cb() ourself if it's set, or destroy the connection,
6082 * we can't be sure conn_fd_handler() will be called again.
6083 */
6084 if ((ctx->conn->flags & CO_FL_ERROR) ||
6085 !(ctx->conn->flags & CO_FL_SSL_WAIT_HS)) {
6086 int ret = 0;
6087 int woke = 0;
6088
6089 /* On error, wake any waiter */
6090 if (ctx->recv_wait) {
6091 ctx->recv_wait->events &= ~SUB_RETRY_RECV;
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02006092 tasklet_wakeup(ctx->recv_wait->tasklet);
Olivier Houchardea8dd942019-05-20 14:02:16 +02006093 ctx->recv_wait = NULL;
6094 woke = 1;
6095 }
6096 if (ctx->send_wait) {
6097 ctx->send_wait->events &= ~SUB_RETRY_SEND;
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02006098 tasklet_wakeup(ctx->send_wait->tasklet);
Olivier Houchardea8dd942019-05-20 14:02:16 +02006099 ctx->send_wait = NULL;
6100 woke = 1;
6101 }
6102 /* If we're the first xprt for the connection, let the
6103 * upper layers know. If xprt_done_cb() is set, call it,
6104 * otherwise, we should have a mux, so call its wake
6105 * method if we didn't woke a tasklet already.
6106 */
6107 if (ctx->conn->xprt_ctx == ctx) {
6108 if (ctx->conn->xprt_done_cb)
6109 ret = ctx->conn->xprt_done_cb(ctx->conn);
6110 if (ret >= 0 && !woke && ctx->conn->mux && ctx->conn->mux->wake)
6111 ctx->conn->mux->wake(ctx->conn);
6112 return NULL;
6113 }
6114 }
6115 return NULL;
6116}
6117
Emeric Brun46591952012-05-18 15:47:34 +02006118/* Receive up to <count> bytes from connection <conn>'s socket and store them
Willy Tarreauabf08d92014-01-14 11:31:27 +01006119 * into buffer <buf>. Only one call to recv() is performed, unless the
Emeric Brun46591952012-05-18 15:47:34 +02006120 * buffer wraps, in which case a second call may be performed. The connection's
6121 * flags are updated with whatever special event is detected (error, read0,
6122 * empty). The caller is responsible for taking care of those events and
6123 * avoiding the call if inappropriate. The function does not call the
6124 * connection's polling update function, so the caller is responsible for this.
6125 */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006126static 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 +02006127{
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006128 struct ssl_sock_ctx *ctx = xprt_ctx;
Willy Tarreaubfc4d772018-07-18 11:22:03 +02006129 ssize_t ret;
6130 size_t try, done = 0;
Emeric Brun46591952012-05-18 15:47:34 +02006131
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02006132 conn_refresh_polling_flags(conn);
6133
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006134 if (!ctx)
Emeric Brun46591952012-05-18 15:47:34 +02006135 goto out_error;
6136
6137 if (conn->flags & CO_FL_HANDSHAKE)
6138 /* a handshake was requested */
6139 return 0;
6140
Emeric Brun46591952012-05-18 15:47:34 +02006141 /* read the largest possible block. For this, we perform only one call
6142 * to recv() unless the buffer wraps and we exactly fill the first hunk,
6143 * in which case we accept to do it once again. A new attempt is made on
6144 * EINTR too.
6145 */
Willy Tarreau00b0fb92014-01-17 11:09:40 +01006146 while (count > 0) {
Olivier Houchardc2aae742017-09-22 18:26:28 +02006147 int need_out = 0;
6148
Willy Tarreau591d4452018-06-15 17:21:00 +02006149 try = b_contig_space(buf);
6150 if (!try)
6151 break;
6152
Willy Tarreauabf08d92014-01-14 11:31:27 +01006153 if (try > count)
6154 try = count;
Willy Tarreau591d4452018-06-15 17:21:00 +02006155
Olivier Houchardc2aae742017-09-22 18:26:28 +02006156 if (((conn->flags & (CO_FL_EARLY_SSL_HS | CO_FL_EARLY_DATA)) == CO_FL_EARLY_SSL_HS) &&
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006157 ctx->tmp_early_data != -1) {
6158 *b_tail(buf) = ctx->tmp_early_data;
Olivier Houchardc2aae742017-09-22 18:26:28 +02006159 done++;
6160 try--;
6161 count--;
Olivier Houchardacd14032018-06-28 18:17:23 +02006162 b_add(buf, 1);
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006163 ctx->tmp_early_data = -1;
Olivier Houchardc2aae742017-09-22 18:26:28 +02006164 continue;
6165 }
Willy Tarreauabf08d92014-01-14 11:31:27 +01006166
Willy Tarreau5db847a2019-05-09 14:13:35 +02006167#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Olivier Houchardc2aae742017-09-22 18:26:28 +02006168 if (conn->flags & CO_FL_EARLY_SSL_HS) {
6169 size_t read_length;
6170
Olivier Houchard66ab4982019-02-26 18:37:15 +01006171 ret = SSL_read_early_data(ctx->ssl,
Willy Tarreau8f9c72d2018-06-07 18:46:28 +02006172 b_tail(buf), try, &read_length);
Olivier Houchard522eea72017-11-03 16:27:47 +01006173 if (ret == SSL_READ_EARLY_DATA_SUCCESS &&
6174 read_length > 0)
Olivier Houchardc2aae742017-09-22 18:26:28 +02006175 conn->flags |= CO_FL_EARLY_DATA;
6176 if (ret == SSL_READ_EARLY_DATA_SUCCESS ||
6177 ret == SSL_READ_EARLY_DATA_FINISH) {
6178 if (ret == SSL_READ_EARLY_DATA_FINISH) {
6179 /*
6180 * We're done reading the early data,
6181 * let's make the handshake
6182 */
6183 conn->flags &= ~CO_FL_EARLY_SSL_HS;
6184 conn->flags |= CO_FL_SSL_WAIT_HS;
6185 need_out = 1;
Olivier Houchard965e84e2019-06-15 20:59:30 +02006186 /* Now initiate the handshake */
6187 tasklet_wakeup(ctx->wait_event.tasklet);
Olivier Houchardc2aae742017-09-22 18:26:28 +02006188 if (read_length == 0)
6189 break;
6190 }
6191 ret = read_length;
6192 }
6193 } else
6194#endif
Olivier Houchard66ab4982019-02-26 18:37:15 +01006195 ret = SSL_read(ctx->ssl, b_tail(buf), try);
Emmanuel Hocdetf967c312019-08-05 18:04:16 +02006196
Emeric Brune1f38db2012-09-03 20:36:47 +02006197 if (conn->flags & CO_FL_ERROR) {
6198 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01006199 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02006200 }
Emeric Brun46591952012-05-18 15:47:34 +02006201 if (ret > 0) {
Olivier Houchardacd14032018-06-28 18:17:23 +02006202 b_add(buf, ret);
Emeric Brun46591952012-05-18 15:47:34 +02006203 done += ret;
Emeric Brun46591952012-05-18 15:47:34 +02006204 count -= ret;
Emeric Brun46591952012-05-18 15:47:34 +02006205 }
Emeric Brun46591952012-05-18 15:47:34 +02006206 else {
Olivier Houchard66ab4982019-02-26 18:37:15 +01006207 ret = SSL_get_error(ctx->ssl, ret);
Emeric Brun46591952012-05-18 15:47:34 +02006208 if (ret == SSL_ERROR_WANT_WRITE) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01006209 /* handshake is running, and it needs to enable write */
Emeric Brun46591952012-05-18 15:47:34 +02006210 conn->flags |= CO_FL_SSL_WAIT_HS;
Olivier Houchardea8dd942019-05-20 14:02:16 +02006211 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_SEND, &ctx->wait_event);
Willy Tarreau5db847a2019-05-09 14:13:35 +02006212#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00006213 /* Async mode can be re-enabled, because we're leaving data state.*/
6214 if (global_ssl.async)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006215 SSL_set_mode(ctx->ssl, SSL_MODE_ASYNC);
Emeric Brunb5e42a82017-06-06 12:35:14 +00006216#endif
Emeric Brun46591952012-05-18 15:47:34 +02006217 break;
6218 }
6219 else if (ret == SSL_ERROR_WANT_READ) {
Olivier Houchard66ab4982019-02-26 18:37:15 +01006220 if (SSL_renegotiate_pending(ctx->ssl)) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02006221 ctx->xprt->subscribe(conn, ctx->xprt_ctx,
6222 SUB_RETRY_RECV,
6223 &ctx->wait_event);
Emeric Brun282a76a2012-11-08 18:02:56 +01006224 /* handshake is running, and it may need to re-enable read */
6225 conn->flags |= CO_FL_SSL_WAIT_HS;
Willy Tarreau5db847a2019-05-09 14:13:35 +02006226#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00006227 /* Async mode can be re-enabled, because we're leaving data state.*/
6228 if (global_ssl.async)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006229 SSL_set_mode(ctx->ssl, SSL_MODE_ASYNC);
Emeric Brunb5e42a82017-06-06 12:35:14 +00006230#endif
Emeric Brun282a76a2012-11-08 18:02:56 +01006231 break;
6232 }
Emeric Brun46591952012-05-18 15:47:34 +02006233 break;
Olivier Houchardc2aae742017-09-22 18:26:28 +02006234 } else if (ret == SSL_ERROR_ZERO_RETURN)
6235 goto read0;
Christopher Faulet4ac77a92018-02-19 14:25:15 +01006236 /* For SSL_ERROR_SYSCALL, make sure to clear the error
6237 * stack before shutting down the connection for
6238 * reading. */
Olivier Houchard7e2e5052018-02-13 15:17:23 +01006239 if (ret == SSL_ERROR_SYSCALL && (!errno || errno == EAGAIN))
6240 goto clear_ssl_error;
Emeric Brun46591952012-05-18 15:47:34 +02006241 /* otherwise it's a real error */
6242 goto out_error;
6243 }
Olivier Houchardc2aae742017-09-22 18:26:28 +02006244 if (need_out)
6245 break;
Emeric Brun46591952012-05-18 15:47:34 +02006246 }
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02006247 leave:
Emeric Brun46591952012-05-18 15:47:34 +02006248 return done;
6249
Christopher Faulet4ac77a92018-02-19 14:25:15 +01006250 clear_ssl_error:
6251 /* Clear openssl global errors stack */
6252 ssl_sock_dump_errors(conn);
6253 ERR_clear_error();
Emeric Brun46591952012-05-18 15:47:34 +02006254 read0:
6255 conn_sock_read0(conn);
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02006256 goto leave;
Christopher Faulet4ac77a92018-02-19 14:25:15 +01006257
Emeric Brun46591952012-05-18 15:47:34 +02006258 out_error:
Olivier Houchard7e2e5052018-02-13 15:17:23 +01006259 conn->flags |= CO_FL_ERROR;
Emeric Brun644cde02012-12-14 11:21:13 +01006260 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02006261 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01006262 ERR_clear_error();
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02006263 goto leave;
Emeric Brun46591952012-05-18 15:47:34 +02006264}
6265
6266
Willy Tarreau787db9a2018-06-14 18:31:46 +02006267/* Send up to <count> pending bytes from buffer <buf> to connection <conn>'s
6268 * socket. <flags> may contain some CO_SFL_* flags to hint the system about
6269 * other pending data for example, but this flag is ignored at the moment.
Emeric Brun46591952012-05-18 15:47:34 +02006270 * Only one call to send() is performed, unless the buffer wraps, in which case
6271 * a second call may be performed. The connection's flags are updated with
6272 * whatever special event is detected (error, empty). The caller is responsible
6273 * for taking care of those events and avoiding the call if inappropriate. The
6274 * function does not call the connection's polling update function, so the caller
Willy Tarreau787db9a2018-06-14 18:31:46 +02006275 * is responsible for this. The buffer's output is not adjusted, it's up to the
6276 * caller to take care of this. It's up to the caller to update the buffer's
6277 * contents based on the return value.
Emeric Brun46591952012-05-18 15:47:34 +02006278 */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006279static 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 +02006280{
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006281 struct ssl_sock_ctx *ctx = xprt_ctx;
Willy Tarreau787db9a2018-06-14 18:31:46 +02006282 ssize_t ret;
6283 size_t try, done;
Emeric Brun46591952012-05-18 15:47:34 +02006284
6285 done = 0;
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02006286 conn_refresh_polling_flags(conn);
Emeric Brun46591952012-05-18 15:47:34 +02006287
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006288 if (!ctx)
Emeric Brun46591952012-05-18 15:47:34 +02006289 goto out_error;
6290
Olivier Houchard010941f2019-05-03 20:56:19 +02006291 if (conn->flags & (CO_FL_HANDSHAKE | CO_FL_EARLY_SSL_HS))
Emeric Brun46591952012-05-18 15:47:34 +02006292 /* a handshake was requested */
6293 return 0;
6294
6295 /* send the largest possible block. For this we perform only one call
6296 * to send() unless the buffer wraps and we exactly fill the first hunk,
6297 * in which case we accept to do it once again.
6298 */
Willy Tarreau787db9a2018-06-14 18:31:46 +02006299 while (count) {
Willy Tarreau5db847a2019-05-09 14:13:35 +02006300#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Olivier Houchardc2aae742017-09-22 18:26:28 +02006301 size_t written_data;
6302#endif
6303
Willy Tarreau787db9a2018-06-14 18:31:46 +02006304 try = b_contig_data(buf, done);
6305 if (try > count)
6306 try = count;
Willy Tarreaubfd59462013-02-21 07:46:09 +01006307
Willy Tarreau7bed9452014-02-02 02:00:24 +01006308 if (!(flags & CO_SFL_STREAMER) &&
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006309 !(ctx->xprt_st & SSL_SOCK_SEND_UNLIMITED) &&
Willy Tarreauef934602016-12-22 23:12:01 +01006310 global_ssl.max_record && try > global_ssl.max_record) {
6311 try = global_ssl.max_record;
Willy Tarreau518cedd2014-02-17 15:43:01 +01006312 }
6313 else {
6314 /* we need to keep the information about the fact that
6315 * we're not limiting the upcoming send(), because if it
6316 * fails, we'll have to retry with at least as many data.
6317 */
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006318 ctx->xprt_st |= SSL_SOCK_SEND_UNLIMITED;
Willy Tarreau518cedd2014-02-17 15:43:01 +01006319 }
Willy Tarreaubfd59462013-02-21 07:46:09 +01006320
Willy Tarreau5db847a2019-05-09 14:13:35 +02006321#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Olivier Houchard010941f2019-05-03 20:56:19 +02006322 if (!SSL_is_init_finished(ctx->ssl) && conn_is_back(conn)) {
Olivier Houchardc2aae742017-09-22 18:26:28 +02006323 unsigned int max_early;
6324
Olivier Houchard522eea72017-11-03 16:27:47 +01006325 if (objt_listener(conn->target))
Olivier Houchard66ab4982019-02-26 18:37:15 +01006326 max_early = SSL_get_max_early_data(ctx->ssl);
Olivier Houchard522eea72017-11-03 16:27:47 +01006327 else {
Olivier Houchard66ab4982019-02-26 18:37:15 +01006328 if (SSL_get0_session(ctx->ssl))
6329 max_early = SSL_SESSION_get_max_early_data(SSL_get0_session(ctx->ssl));
Olivier Houchard522eea72017-11-03 16:27:47 +01006330 else
6331 max_early = 0;
6332 }
6333
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006334 if (try + ctx->sent_early_data > max_early) {
6335 try -= (try + ctx->sent_early_data) - max_early;
Olivier Houchard522eea72017-11-03 16:27:47 +01006336 if (try <= 0) {
Olivier Houchard010941f2019-05-03 20:56:19 +02006337 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Olivier Houchard965e84e2019-06-15 20:59:30 +02006338 tasklet_wakeup(ctx->wait_event.tasklet);
Olivier Houchardc2aae742017-09-22 18:26:28 +02006339 break;
Olivier Houchard522eea72017-11-03 16:27:47 +01006340 }
Olivier Houchardc2aae742017-09-22 18:26:28 +02006341 }
Olivier Houchard66ab4982019-02-26 18:37:15 +01006342 ret = SSL_write_early_data(ctx->ssl, b_peek(buf, done), try, &written_data);
Olivier Houchardc2aae742017-09-22 18:26:28 +02006343 if (ret == 1) {
6344 ret = written_data;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006345 ctx->sent_early_data += ret;
Olivier Houchard965e84e2019-06-15 20:59:30 +02006346 if (objt_server(conn->target)) {
Olivier Houchard522eea72017-11-03 16:27:47 +01006347 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN | CO_FL_EARLY_DATA;
Olivier Houchard965e84e2019-06-15 20:59:30 +02006348 /* Initiate the handshake, now */
6349 tasklet_wakeup(ctx->wait_event.tasklet);
6350 }
Olivier Houchard522eea72017-11-03 16:27:47 +01006351
Olivier Houchardc2aae742017-09-22 18:26:28 +02006352 }
6353
6354 } else
6355#endif
Olivier Houchard66ab4982019-02-26 18:37:15 +01006356 ret = SSL_write(ctx->ssl, b_peek(buf, done), try);
Willy Tarreau518cedd2014-02-17 15:43:01 +01006357
Emeric Brune1f38db2012-09-03 20:36:47 +02006358 if (conn->flags & CO_FL_ERROR) {
6359 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01006360 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02006361 }
Emeric Brun46591952012-05-18 15:47:34 +02006362 if (ret > 0) {
Olivier Houchardf24502b2019-01-17 19:09:11 +01006363 /* A send succeeded, so we can consier ourself connected */
6364 conn->flags |= CO_FL_CONNECTED;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006365 ctx->xprt_st &= ~SSL_SOCK_SEND_UNLIMITED;
Willy Tarreau787db9a2018-06-14 18:31:46 +02006366 count -= ret;
Emeric Brun46591952012-05-18 15:47:34 +02006367 done += ret;
Emeric Brun46591952012-05-18 15:47:34 +02006368 }
6369 else {
Olivier Houchard66ab4982019-02-26 18:37:15 +01006370 ret = SSL_get_error(ctx->ssl, ret);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006371
Emeric Brun46591952012-05-18 15:47:34 +02006372 if (ret == SSL_ERROR_WANT_WRITE) {
Olivier Houchard66ab4982019-02-26 18:37:15 +01006373 if (SSL_renegotiate_pending(ctx->ssl)) {
Emeric Brun282a76a2012-11-08 18:02:56 +01006374 /* handshake is running, and it may need to re-enable write */
6375 conn->flags |= CO_FL_SSL_WAIT_HS;
Olivier Houchardea8dd942019-05-20 14:02:16 +02006376 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_SEND, &ctx->wait_event);
Willy Tarreau5db847a2019-05-09 14:13:35 +02006377#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00006378 /* Async mode can be re-enabled, because we're leaving data state.*/
6379 if (global_ssl.async)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006380 SSL_set_mode(ctx->ssl, SSL_MODE_ASYNC);
Emeric Brunb5e42a82017-06-06 12:35:14 +00006381#endif
Emeric Brun282a76a2012-11-08 18:02:56 +01006382 break;
6383 }
Olivier Houchardea8dd942019-05-20 14:02:16 +02006384
Emeric Brun46591952012-05-18 15:47:34 +02006385 break;
6386 }
6387 else if (ret == SSL_ERROR_WANT_READ) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01006388 /* handshake is running, and it needs to enable read */
Emeric Brun46591952012-05-18 15:47:34 +02006389 conn->flags |= CO_FL_SSL_WAIT_HS;
Olivier Houchardea8dd942019-05-20 14:02:16 +02006390 ctx->xprt->subscribe(conn, ctx->xprt_ctx,
6391 SUB_RETRY_RECV,
6392 &ctx->wait_event);
Willy Tarreau5db847a2019-05-09 14:13:35 +02006393#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00006394 /* Async mode can be re-enabled, because we're leaving data state.*/
6395 if (global_ssl.async)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006396 SSL_set_mode(ctx->ssl, SSL_MODE_ASYNC);
Emeric Brunb5e42a82017-06-06 12:35:14 +00006397#endif
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006398 break;
6399 }
Emeric Brun46591952012-05-18 15:47:34 +02006400 goto out_error;
6401 }
6402 }
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02006403 leave:
Emeric Brun46591952012-05-18 15:47:34 +02006404 return done;
6405
6406 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01006407 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02006408 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01006409 ERR_clear_error();
6410
Emeric Brun46591952012-05-18 15:47:34 +02006411 conn->flags |= CO_FL_ERROR;
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02006412 goto leave;
Emeric Brun46591952012-05-18 15:47:34 +02006413}
6414
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006415static void ssl_sock_close(struct connection *conn, void *xprt_ctx) {
Emeric Brun46591952012-05-18 15:47:34 +02006416
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006417 struct ssl_sock_ctx *ctx = xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006418
Olivier Houchardea8dd942019-05-20 14:02:16 +02006419
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006420 if (ctx) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02006421 if (ctx->wait_event.events != 0)
6422 ctx->xprt->unsubscribe(ctx->conn, ctx->xprt_ctx,
6423 ctx->wait_event.events,
6424 &ctx->wait_event);
6425 if (ctx->send_wait) {
6426 ctx->send_wait->events &= ~SUB_RETRY_SEND;
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02006427 tasklet_wakeup(ctx->send_wait->tasklet);
Olivier Houchardea8dd942019-05-20 14:02:16 +02006428 }
6429 if (ctx->recv_wait) {
6430 ctx->recv_wait->events &= ~SUB_RETRY_RECV;
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02006431 tasklet_wakeup(ctx->recv_wait->tasklet);
Olivier Houchardea8dd942019-05-20 14:02:16 +02006432 }
Olivier Houchard692c1d02019-05-23 18:41:47 +02006433 if (ctx->xprt->close)
6434 ctx->xprt->close(conn, ctx->xprt_ctx);
Willy Tarreau5db847a2019-05-09 14:13:35 +02006435#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brun3854e012017-05-17 20:42:48 +02006436 if (global_ssl.async) {
6437 OSSL_ASYNC_FD all_fd[32], afd;
6438 size_t num_all_fds = 0;
6439 int i;
6440
Olivier Houchard66ab4982019-02-26 18:37:15 +01006441 SSL_get_all_async_fds(ctx->ssl, NULL, &num_all_fds);
Emeric Brun3854e012017-05-17 20:42:48 +02006442 if (num_all_fds > 32) {
6443 send_log(NULL, LOG_EMERG, "haproxy: openssl returns too many async fds. It seems a bug. Process may crash\n");
6444 return;
6445 }
6446
Olivier Houchard66ab4982019-02-26 18:37:15 +01006447 SSL_get_all_async_fds(ctx->ssl, all_fd, &num_all_fds);
Emeric Brun3854e012017-05-17 20:42:48 +02006448
6449 /* If an async job is pending, we must try to
6450 to catch the end using polling before calling
6451 SSL_free */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006452 if (num_all_fds && SSL_waiting_for_async(ctx->ssl)) {
Emeric Brun3854e012017-05-17 20:42:48 +02006453 for (i=0 ; i < num_all_fds ; i++) {
6454 /* switch on an handler designed to
6455 * handle the SSL_free
6456 */
6457 afd = all_fd[i];
6458 fdtab[afd].iocb = ssl_async_fd_free;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006459 fdtab[afd].owner = ctx->ssl;
Emeric Brun3854e012017-05-17 20:42:48 +02006460 fd_want_recv(afd);
Emeric Brunce9e01c2017-05-31 10:02:53 +00006461 /* To ensure that the fd cache won't be used
6462 * and we'll catch a real RD event.
6463 */
6464 fd_cant_recv(afd);
Emeric Brun3854e012017-05-17 20:42:48 +02006465 }
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02006466 tasklet_free(ctx->wait_event.tasklet);
Olivier Houchard66ab4982019-02-26 18:37:15 +01006467 pool_free(ssl_sock_ctx_pool, ctx);
Olivier Houchard2be5a4c2019-03-08 18:54:43 +01006468 _HA_ATOMIC_ADD(&jobs, 1);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006469 return;
6470 }
Emeric Brun3854e012017-05-17 20:42:48 +02006471 /* Else we can remove the fds from the fdtab
6472 * and call SSL_free.
6473 * note: we do a fd_remove and not a delete
6474 * because the fd is owned by the engine.
6475 * the engine is responsible to close
6476 */
6477 for (i=0 ; i < num_all_fds ; i++)
6478 fd_remove(all_fd[i]);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006479 }
6480#endif
Olivier Houchard66ab4982019-02-26 18:37:15 +01006481 SSL_free(ctx->ssl);
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02006482 tasklet_free(ctx->wait_event.tasklet);
Olivier Houchard66ab4982019-02-26 18:37:15 +01006483 pool_free(ssl_sock_ctx_pool, ctx);
Olivier Houchard2be5a4c2019-03-08 18:54:43 +01006484 _HA_ATOMIC_SUB(&sslconns, 1);
Emeric Brun46591952012-05-18 15:47:34 +02006485 }
Emeric Brun46591952012-05-18 15:47:34 +02006486}
6487
6488/* This function tries to perform a clean shutdown on an SSL connection, and in
6489 * any case, flags the connection as reusable if no handshake was in progress.
6490 */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006491static void ssl_sock_shutw(struct connection *conn, void *xprt_ctx, int clean)
Emeric Brun46591952012-05-18 15:47:34 +02006492{
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006493 struct ssl_sock_ctx *ctx = xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006494
Emeric Brun46591952012-05-18 15:47:34 +02006495 if (conn->flags & CO_FL_HANDSHAKE)
6496 return;
Emmanuel Hocdet405ff312017-01-08 14:07:39 +01006497 if (!clean)
6498 /* don't sent notify on SSL_shutdown */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006499 SSL_set_quiet_shutdown(ctx->ssl, 1);
Emeric Brun46591952012-05-18 15:47:34 +02006500 /* no handshake was in progress, try a clean ssl shutdown */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006501 if (SSL_shutdown(ctx->ssl) <= 0) {
Emeric Brun644cde02012-12-14 11:21:13 +01006502 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02006503 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01006504 ERR_clear_error();
6505 }
Emeric Brun46591952012-05-18 15:47:34 +02006506}
6507
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01006508/* used for ppv2 pkey alog (can be used for logging) */
Willy Tarreau83061a82018-07-13 11:56:34 +02006509int ssl_sock_get_pkey_algo(struct connection *conn, struct buffer *out)
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01006510{
Christopher Faulet82004142019-09-10 10:12:03 +02006511 struct ssl_sock_ctx *ctx;
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01006512 struct pkey_info *pkinfo;
6513 int bits = 0;
6514 int sig = TLSEXT_signature_anonymous;
6515 int len = -1;
6516
6517 if (!ssl_sock_is_ssl(conn))
6518 return 0;
Christopher Faulet82004142019-09-10 10:12:03 +02006519 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006520 pkinfo = SSL_CTX_get_ex_data(SSL_get_SSL_CTX(ctx->ssl), ssl_pkey_info_index);
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01006521 if (pkinfo) {
6522 sig = pkinfo->sig;
6523 bits = pkinfo->bits;
6524 } else {
6525 /* multicert and generated cert have no pkey info */
6526 X509 *crt;
6527 EVP_PKEY *pkey;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006528 crt = SSL_get_certificate(ctx->ssl);
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01006529 if (!crt)
6530 return 0;
6531 pkey = X509_get_pubkey(crt);
6532 if (pkey) {
6533 bits = EVP_PKEY_bits(pkey);
6534 switch(EVP_PKEY_base_id(pkey)) {
6535 case EVP_PKEY_RSA:
6536 sig = TLSEXT_signature_rsa;
6537 break;
6538 case EVP_PKEY_EC:
6539 sig = TLSEXT_signature_ecdsa;
6540 break;
6541 case EVP_PKEY_DSA:
6542 sig = TLSEXT_signature_dsa;
6543 break;
6544 }
6545 EVP_PKEY_free(pkey);
6546 }
6547 }
6548
6549 switch(sig) {
6550 case TLSEXT_signature_rsa:
6551 len = chunk_printf(out, "RSA%d", bits);
6552 break;
6553 case TLSEXT_signature_ecdsa:
6554 len = chunk_printf(out, "EC%d", bits);
6555 break;
6556 case TLSEXT_signature_dsa:
6557 len = chunk_printf(out, "DSA%d", bits);
6558 break;
6559 default:
6560 return 0;
6561 }
6562 if (len < 0)
6563 return 0;
6564 return 1;
6565}
6566
Emmanuel Hocdet283e0042017-11-02 14:05:23 +01006567/* used for ppv2 cert signature (can be used for logging) */
6568const char *ssl_sock_get_cert_sig(struct connection *conn)
6569{
Christopher Faulet82004142019-09-10 10:12:03 +02006570 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006571
Emmanuel Hocdet283e0042017-11-02 14:05:23 +01006572 __OPENSSL_110_CONST__ ASN1_OBJECT *algorithm;
6573 X509 *crt;
6574
6575 if (!ssl_sock_is_ssl(conn))
6576 return NULL;
Christopher Faulet82004142019-09-10 10:12:03 +02006577 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006578 crt = SSL_get_certificate(ctx->ssl);
Emmanuel Hocdet283e0042017-11-02 14:05:23 +01006579 if (!crt)
6580 return NULL;
6581 X509_ALGOR_get0(&algorithm, NULL, NULL, X509_get0_tbs_sigalg(crt));
6582 return OBJ_nid2sn(OBJ_obj2nid(algorithm));
6583}
6584
Emmanuel Hocdet253c3b72018-02-01 18:29:59 +01006585/* used for ppv2 authority */
6586const char *ssl_sock_get_sni(struct connection *conn)
6587{
6588#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Christopher Faulet82004142019-09-10 10:12:03 +02006589 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006590
Emmanuel Hocdet253c3b72018-02-01 18:29:59 +01006591 if (!ssl_sock_is_ssl(conn))
6592 return NULL;
Christopher Faulet82004142019-09-10 10:12:03 +02006593 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006594 return SSL_get_servername(ctx->ssl, TLSEXT_NAMETYPE_host_name);
Emmanuel Hocdet253c3b72018-02-01 18:29:59 +01006595#else
Olivier Houchard66ab4982019-02-26 18:37:15 +01006596 return NULL;
Emmanuel Hocdet253c3b72018-02-01 18:29:59 +01006597#endif
6598}
6599
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02006600/* used for logging/ppv2, may be changed for a sample fetch later */
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02006601const char *ssl_sock_get_cipher_name(struct connection *conn)
6602{
Christopher Faulet82004142019-09-10 10:12:03 +02006603 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006604
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02006605 if (!ssl_sock_is_ssl(conn))
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02006606 return NULL;
Christopher Faulet82004142019-09-10 10:12:03 +02006607 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006608 return SSL_get_cipher_name(ctx->ssl);
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02006609}
6610
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02006611/* used for logging/ppv2, may be changed for a sample fetch later */
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02006612const char *ssl_sock_get_proto_version(struct connection *conn)
6613{
Christopher Faulet82004142019-09-10 10:12:03 +02006614 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006615
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02006616 if (!ssl_sock_is_ssl(conn))
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02006617 return NULL;
Christopher Faulet82004142019-09-10 10:12:03 +02006618 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006619 return SSL_get_version(ctx->ssl);
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02006620}
6621
Willy Tarreau8d598402012-10-22 17:58:39 +02006622/* Extract a serial from a cert, and copy it to a chunk.
6623 * Returns 1 if serial is found and copied, 0 if no serial found and
6624 * -1 if output is not large enough.
6625 */
6626static int
Willy Tarreau83061a82018-07-13 11:56:34 +02006627ssl_sock_get_serial(X509 *crt, struct buffer *out)
Willy Tarreau8d598402012-10-22 17:58:39 +02006628{
6629 ASN1_INTEGER *serial;
6630
6631 serial = X509_get_serialNumber(crt);
6632 if (!serial)
6633 return 0;
6634
6635 if (out->size < serial->length)
6636 return -1;
6637
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006638 memcpy(out->area, serial->data, serial->length);
6639 out->data = serial->length;
Willy Tarreau8d598402012-10-22 17:58:39 +02006640 return 1;
6641}
6642
Emeric Brun43e79582014-10-29 19:03:26 +01006643/* Extract a cert to der, and copy it to a chunk.
Joseph Herlant017b3da2018-11-15 09:07:59 -08006644 * Returns 1 if the cert is found and copied, 0 on der conversion failure
6645 * and -1 if the output is not large enough.
Emeric Brun43e79582014-10-29 19:03:26 +01006646 */
6647static int
Willy Tarreau83061a82018-07-13 11:56:34 +02006648ssl_sock_crt2der(X509 *crt, struct buffer *out)
Emeric Brun43e79582014-10-29 19:03:26 +01006649{
6650 int len;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006651 unsigned char *p = (unsigned char *) out->area;;
Emeric Brun43e79582014-10-29 19:03:26 +01006652
6653 len =i2d_X509(crt, NULL);
6654 if (len <= 0)
6655 return 1;
6656
6657 if (out->size < len)
6658 return -1;
6659
6660 i2d_X509(crt,&p);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006661 out->data = len;
Emeric Brun43e79582014-10-29 19:03:26 +01006662 return 1;
6663}
6664
Emeric Brunce5ad802012-10-22 14:11:22 +02006665
Willy Tarreau83061a82018-07-13 11:56:34 +02006666/* Copy Date in ASN1_UTCTIME format in struct buffer out.
Emeric Brunce5ad802012-10-22 14:11:22 +02006667 * Returns 1 if serial is found and copied, 0 if no valid time found
6668 * and -1 if output is not large enough.
6669 */
6670static int
Willy Tarreau83061a82018-07-13 11:56:34 +02006671ssl_sock_get_time(ASN1_TIME *tm, struct buffer *out)
Emeric Brunce5ad802012-10-22 14:11:22 +02006672{
6673 if (tm->type == V_ASN1_GENERALIZEDTIME) {
6674 ASN1_GENERALIZEDTIME *gentm = (ASN1_GENERALIZEDTIME *)tm;
6675
6676 if (gentm->length < 12)
6677 return 0;
6678 if (gentm->data[0] != 0x32 || gentm->data[1] != 0x30)
6679 return 0;
6680 if (out->size < gentm->length-2)
6681 return -1;
6682
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006683 memcpy(out->area, gentm->data+2, gentm->length-2);
6684 out->data = gentm->length-2;
Emeric Brunce5ad802012-10-22 14:11:22 +02006685 return 1;
6686 }
6687 else if (tm->type == V_ASN1_UTCTIME) {
6688 ASN1_UTCTIME *utctm = (ASN1_UTCTIME *)tm;
6689
6690 if (utctm->length < 10)
6691 return 0;
6692 if (utctm->data[0] >= 0x35)
6693 return 0;
6694 if (out->size < utctm->length)
6695 return -1;
6696
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006697 memcpy(out->area, utctm->data, utctm->length);
6698 out->data = utctm->length;
Emeric Brunce5ad802012-10-22 14:11:22 +02006699 return 1;
6700 }
6701
6702 return 0;
6703}
6704
Emeric Brun87855892012-10-17 17:39:35 +02006705/* Extract an entry from a X509_NAME and copy its value to an output chunk.
6706 * Returns 1 if entry found, 0 if entry not found, or -1 if output not large enough.
6707 */
6708static int
Willy Tarreau83061a82018-07-13 11:56:34 +02006709ssl_sock_get_dn_entry(X509_NAME *a, const struct buffer *entry, int pos,
6710 struct buffer *out)
Emeric Brun87855892012-10-17 17:39:35 +02006711{
6712 X509_NAME_ENTRY *ne;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006713 ASN1_OBJECT *obj;
6714 ASN1_STRING *data;
6715 const unsigned char *data_ptr;
6716 int data_len;
Emeric Brun87855892012-10-17 17:39:35 +02006717 int i, j, n;
6718 int cur = 0;
6719 const char *s;
6720 char tmp[128];
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006721 int name_count;
6722
6723 name_count = X509_NAME_entry_count(a);
Emeric Brun87855892012-10-17 17:39:35 +02006724
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006725 out->data = 0;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006726 for (i = 0; i < name_count; i++) {
Emeric Brun87855892012-10-17 17:39:35 +02006727 if (pos < 0)
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006728 j = (name_count-1) - i;
Emeric Brun87855892012-10-17 17:39:35 +02006729 else
6730 j = i;
6731
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006732 ne = X509_NAME_get_entry(a, j);
6733 obj = X509_NAME_ENTRY_get_object(ne);
6734 data = X509_NAME_ENTRY_get_data(ne);
6735 data_ptr = ASN1_STRING_get0_data(data);
6736 data_len = ASN1_STRING_length(data);
6737 n = OBJ_obj2nid(obj);
Emeric Brun87855892012-10-17 17:39:35 +02006738 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006739 i2t_ASN1_OBJECT(tmp, sizeof(tmp), obj);
Emeric Brun87855892012-10-17 17:39:35 +02006740 s = tmp;
6741 }
6742
6743 if (chunk_strcasecmp(entry, s) != 0)
6744 continue;
6745
6746 if (pos < 0)
6747 cur--;
6748 else
6749 cur++;
6750
6751 if (cur != pos)
6752 continue;
6753
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006754 if (data_len > out->size)
Emeric Brun87855892012-10-17 17:39:35 +02006755 return -1;
6756
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006757 memcpy(out->area, data_ptr, data_len);
6758 out->data = data_len;
Emeric Brun87855892012-10-17 17:39:35 +02006759 return 1;
6760 }
6761
6762 return 0;
6763
6764}
6765
6766/* Extract and format full DN from a X509_NAME and copy result into a chunk
6767 * Returns 1 if dn entries exits, 0 if no dn entry found or -1 if output is not large enough.
6768 */
6769static int
Willy Tarreau83061a82018-07-13 11:56:34 +02006770ssl_sock_get_dn_oneline(X509_NAME *a, struct buffer *out)
Emeric Brun87855892012-10-17 17:39:35 +02006771{
6772 X509_NAME_ENTRY *ne;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006773 ASN1_OBJECT *obj;
6774 ASN1_STRING *data;
6775 const unsigned char *data_ptr;
6776 int data_len;
Emeric Brun87855892012-10-17 17:39:35 +02006777 int i, n, ln;
6778 int l = 0;
6779 const char *s;
6780 char *p;
6781 char tmp[128];
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006782 int name_count;
6783
6784
6785 name_count = X509_NAME_entry_count(a);
Emeric Brun87855892012-10-17 17:39:35 +02006786
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006787 out->data = 0;
6788 p = out->area;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006789 for (i = 0; i < name_count; i++) {
6790 ne = X509_NAME_get_entry(a, i);
6791 obj = X509_NAME_ENTRY_get_object(ne);
6792 data = X509_NAME_ENTRY_get_data(ne);
6793 data_ptr = ASN1_STRING_get0_data(data);
6794 data_len = ASN1_STRING_length(data);
6795 n = OBJ_obj2nid(obj);
Emeric Brun87855892012-10-17 17:39:35 +02006796 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006797 i2t_ASN1_OBJECT(tmp, sizeof(tmp), obj);
Emeric Brun87855892012-10-17 17:39:35 +02006798 s = tmp;
6799 }
6800 ln = strlen(s);
6801
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006802 l += 1 + ln + 1 + data_len;
Emeric Brun87855892012-10-17 17:39:35 +02006803 if (l > out->size)
6804 return -1;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006805 out->data = l;
Emeric Brun87855892012-10-17 17:39:35 +02006806
6807 *(p++)='/';
6808 memcpy(p, s, ln);
6809 p += ln;
6810 *(p++)='=';
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006811 memcpy(p, data_ptr, data_len);
6812 p += data_len;
Emeric Brun87855892012-10-17 17:39:35 +02006813 }
6814
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006815 if (!out->data)
Emeric Brun87855892012-10-17 17:39:35 +02006816 return 0;
6817
6818 return 1;
6819}
6820
Olivier Houchardab28a322018-12-21 19:45:40 +01006821void ssl_sock_set_alpn(struct connection *conn, const unsigned char *alpn, int len)
6822{
6823#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Christopher Faulet82004142019-09-10 10:12:03 +02006824 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006825
Olivier Houcharde488ea82019-06-28 14:10:33 +02006826 if (!ssl_sock_is_ssl(conn))
6827 return;
Christopher Faulet82004142019-09-10 10:12:03 +02006828 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006829 SSL_set_alpn_protos(ctx->ssl, alpn, len);
Olivier Houchardab28a322018-12-21 19:45:40 +01006830#endif
6831}
6832
Willy Tarreau119a4082016-12-22 21:58:38 +01006833/* Sets advertised SNI for outgoing connections. Please set <hostname> to NULL
6834 * to disable SNI.
6835 */
Willy Tarreau63076412015-07-10 11:33:32 +02006836void ssl_sock_set_servername(struct connection *conn, const char *hostname)
6837{
6838#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Christopher Faulet82004142019-09-10 10:12:03 +02006839 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006840
Willy Tarreau119a4082016-12-22 21:58:38 +01006841 char *prev_name;
6842
Willy Tarreau63076412015-07-10 11:33:32 +02006843 if (!ssl_sock_is_ssl(conn))
6844 return;
Christopher Faulet82004142019-09-10 10:12:03 +02006845 ctx = conn->xprt_ctx;
Willy Tarreau63076412015-07-10 11:33:32 +02006846
Willy Tarreau119a4082016-12-22 21:58:38 +01006847 /* if the SNI changes, we must destroy the reusable context so that a
6848 * new connection will present a new SNI. As an optimization we could
6849 * later imagine having a small cache of ssl_ctx to hold a few SNI per
6850 * server.
6851 */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006852 prev_name = (char *)SSL_get_servername(ctx->ssl, TLSEXT_NAMETYPE_host_name);
Willy Tarreau119a4082016-12-22 21:58:38 +01006853 if ((!prev_name && hostname) ||
6854 (prev_name && (!hostname || strcmp(hostname, prev_name) != 0)))
Olivier Houchard66ab4982019-02-26 18:37:15 +01006855 SSL_set_session(ctx->ssl, NULL);
Willy Tarreau119a4082016-12-22 21:58:38 +01006856
Olivier Houchard66ab4982019-02-26 18:37:15 +01006857 SSL_set_tlsext_host_name(ctx->ssl, hostname);
Willy Tarreau63076412015-07-10 11:33:32 +02006858#endif
6859}
6860
Emeric Brun0abf8362014-06-24 18:26:41 +02006861/* Extract peer certificate's common name into the chunk dest
6862 * Returns
6863 * the len of the extracted common name
6864 * or 0 if no CN found in DN
6865 * or -1 on error case (i.e. no peer certificate)
6866 */
Willy Tarreau83061a82018-07-13 11:56:34 +02006867int ssl_sock_get_remote_common_name(struct connection *conn,
6868 struct buffer *dest)
David Safb76832014-05-08 23:42:08 -04006869{
Christopher Faulet82004142019-09-10 10:12:03 +02006870 struct ssl_sock_ctx *ctx;
David Safb76832014-05-08 23:42:08 -04006871 X509 *crt = NULL;
6872 X509_NAME *name;
David Safb76832014-05-08 23:42:08 -04006873 const char find_cn[] = "CN";
Willy Tarreau83061a82018-07-13 11:56:34 +02006874 const struct buffer find_cn_chunk = {
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006875 .area = (char *)&find_cn,
6876 .data = sizeof(find_cn)-1
David Safb76832014-05-08 23:42:08 -04006877 };
Emeric Brun0abf8362014-06-24 18:26:41 +02006878 int result = -1;
David Safb76832014-05-08 23:42:08 -04006879
6880 if (!ssl_sock_is_ssl(conn))
Emeric Brun0abf8362014-06-24 18:26:41 +02006881 goto out;
Christopher Faulet82004142019-09-10 10:12:03 +02006882 ctx = conn->xprt_ctx;
David Safb76832014-05-08 23:42:08 -04006883
6884 /* SSL_get_peer_certificate, it increase X509 * ref count */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006885 crt = SSL_get_peer_certificate(ctx->ssl);
David Safb76832014-05-08 23:42:08 -04006886 if (!crt)
6887 goto out;
6888
6889 name = X509_get_subject_name(crt);
6890 if (!name)
6891 goto out;
David Safb76832014-05-08 23:42:08 -04006892
Emeric Brun0abf8362014-06-24 18:26:41 +02006893 result = ssl_sock_get_dn_entry(name, &find_cn_chunk, 1, dest);
6894out:
David Safb76832014-05-08 23:42:08 -04006895 if (crt)
6896 X509_free(crt);
6897
6898 return result;
6899}
6900
Dave McCowan328fb582014-07-30 10:39:13 -04006901/* returns 1 if client passed a certificate for this session, 0 if not */
6902int ssl_sock_get_cert_used_sess(struct connection *conn)
6903{
Christopher Faulet82004142019-09-10 10:12:03 +02006904 struct ssl_sock_ctx *ctx;
Dave McCowan328fb582014-07-30 10:39:13 -04006905 X509 *crt = NULL;
6906
6907 if (!ssl_sock_is_ssl(conn))
6908 return 0;
Christopher Faulet82004142019-09-10 10:12:03 +02006909 ctx = conn->xprt_ctx;
Dave McCowan328fb582014-07-30 10:39:13 -04006910
6911 /* SSL_get_peer_certificate, it increase X509 * ref count */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006912 crt = SSL_get_peer_certificate(ctx->ssl);
Dave McCowan328fb582014-07-30 10:39:13 -04006913 if (!crt)
6914 return 0;
6915
6916 X509_free(crt);
6917 return 1;
6918}
6919
6920/* returns 1 if client passed a certificate for this connection, 0 if not */
6921int ssl_sock_get_cert_used_conn(struct connection *conn)
David Safb76832014-05-08 23:42:08 -04006922{
Christopher Faulet82004142019-09-10 10:12:03 +02006923 struct ssl_sock_ctx *ctx;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006924
David Safb76832014-05-08 23:42:08 -04006925 if (!ssl_sock_is_ssl(conn))
6926 return 0;
Christopher Faulet82004142019-09-10 10:12:03 +02006927 ctx = conn->xprt_ctx;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006928 return SSL_SOCK_ST_FL_VERIFY_DONE & ctx->xprt_st ? 1 : 0;
David Safb76832014-05-08 23:42:08 -04006929}
6930
6931/* returns result from SSL verify */
6932unsigned int ssl_sock_get_verify_result(struct connection *conn)
6933{
Christopher Faulet82004142019-09-10 10:12:03 +02006934 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006935
David Safb76832014-05-08 23:42:08 -04006936 if (!ssl_sock_is_ssl(conn))
6937 return (unsigned int)X509_V_ERR_APPLICATION_VERIFICATION;
Christopher Faulet82004142019-09-10 10:12:03 +02006938 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006939 return (unsigned int)SSL_get_verify_result(ctx->ssl);
David Safb76832014-05-08 23:42:08 -04006940}
6941
Willy Tarreau8743f7e2016-12-04 18:44:29 +01006942/* Returns the application layer protocol name in <str> and <len> when known.
6943 * Zero is returned if the protocol name was not found, otherwise non-zero is
6944 * returned. The string is allocated in the SSL context and doesn't have to be
6945 * freed by the caller. NPN is also checked if available since older versions
6946 * of openssl (1.0.1) which are more common in field only support this one.
6947 */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006948static int ssl_sock_get_alpn(const struct connection *conn, void *xprt_ctx, const char **str, int *len)
Willy Tarreau8743f7e2016-12-04 18:44:29 +01006949{
Olivier Houchard66ab4982019-02-26 18:37:15 +01006950#if defined(TLSEXT_TYPE_application_layer_protocol_negotiation) || \
6951 defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006952 struct ssl_sock_ctx *ctx = xprt_ctx;
6953 if (!ctx)
Willy Tarreau8743f7e2016-12-04 18:44:29 +01006954 return 0;
6955
6956 *str = NULL;
6957
6958#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Olivier Houchard66ab4982019-02-26 18:37:15 +01006959 SSL_get0_alpn_selected(ctx->ssl, (const unsigned char **)str, (unsigned *)len);
Willy Tarreau8743f7e2016-12-04 18:44:29 +01006960 if (*str)
6961 return 1;
6962#endif
Bernard Spil13c53f82018-02-15 13:34:58 +01006963#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006964 SSL_get0_next_proto_negotiated(ctx->ssl, (const unsigned char **)str, (unsigned *)len);
Willy Tarreau8743f7e2016-12-04 18:44:29 +01006965 if (*str)
6966 return 1;
6967#endif
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006968#endif
Willy Tarreau8743f7e2016-12-04 18:44:29 +01006969 return 0;
6970}
6971
Willy Tarreau7875d092012-09-10 08:20:03 +02006972/***** Below are some sample fetching functions for ACL/patterns *****/
6973
Olivier Houchardccaa7de2017-10-02 11:51:03 +02006974static int
6975smp_fetch_ssl_fc_has_early(const struct arg *args, struct sample *smp, const char *kw, void *private)
6976{
6977 struct connection *conn;
6978
6979 conn = objt_conn(smp->sess->origin);
6980 if (!conn || conn->xprt != &ssl_sock)
6981 return 0;
6982
6983 smp->flags = 0;
6984 smp->data.type = SMP_T_BOOL;
Emmanuel Hocdetc9858012019-08-07 14:44:49 +02006985#ifdef OPENSSL_IS_BORINGSSL
6986 {
6987 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
6988 smp->data.u.sint = (SSL_in_early_data(ctx->ssl) &&
6989 SSL_early_data_accepted(ctx->ssl));
6990 }
6991#else
Olivier Houchard25ae45a2017-11-29 19:51:19 +01006992 smp->data.u.sint = ((conn->flags & CO_FL_EARLY_DATA) &&
6993 (conn->flags & (CO_FL_EARLY_SSL_HS | CO_FL_HANDSHAKE))) ? 1 : 0;
Emmanuel Hocdetc9858012019-08-07 14:44:49 +02006994#endif
Olivier Houchardccaa7de2017-10-02 11:51:03 +02006995 return 1;
6996}
6997
Emeric Brune64aef12012-09-21 13:15:06 +02006998/* boolean, returns true if client cert was present */
6999static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007000smp_fetch_ssl_fc_has_crt(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brune64aef12012-09-21 13:15:06 +02007001{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007002 struct connection *conn;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007003 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007004
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007005 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007006 if (!conn || conn->xprt != &ssl_sock)
Emeric Brune64aef12012-09-21 13:15:06 +02007007 return 0;
7008
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007009 ctx = conn->xprt_ctx;
7010
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007011 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brune64aef12012-09-21 13:15:06 +02007012 smp->flags |= SMP_F_MAY_CHANGE;
7013 return 0;
7014 }
7015
7016 smp->flags = 0;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007017 smp->data.type = SMP_T_BOOL;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007018 smp->data.u.sint = SSL_SOCK_ST_FL_VERIFY_DONE & ctx->xprt_st ? 1 : 0;
Emeric Brune64aef12012-09-21 13:15:06 +02007019
7020 return 1;
7021}
7022
Emeric Brun43e79582014-10-29 19:03:26 +01007023/* binary, returns a certificate in a binary chunk (der/raw).
7024 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7025 * should be use.
7026 */
7027static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007028smp_fetch_ssl_x_der(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun43e79582014-10-29 19:03:26 +01007029{
7030 int cert_peer = (kw[4] == 'c') ? 1 : 0;
7031 X509 *crt = NULL;
7032 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02007033 struct buffer *smp_trash;
Emeric Brun43e79582014-10-29 19:03:26 +01007034 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007035 struct ssl_sock_ctx *ctx;
Emeric Brun43e79582014-10-29 19:03:26 +01007036
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007037 conn = objt_conn(smp->sess->origin);
Emeric Brun43e79582014-10-29 19:03:26 +01007038 if (!conn || conn->xprt != &ssl_sock)
7039 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007040 ctx = conn->xprt_ctx;
Emeric Brun43e79582014-10-29 19:03:26 +01007041
7042 if (!(conn->flags & CO_FL_CONNECTED)) {
7043 smp->flags |= SMP_F_MAY_CHANGE;
7044 return 0;
7045 }
7046
7047 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007048 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brun43e79582014-10-29 19:03:26 +01007049 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007050 crt = SSL_get_certificate(ctx->ssl);
Emeric Brun43e79582014-10-29 19:03:26 +01007051
7052 if (!crt)
7053 goto out;
7054
7055 smp_trash = get_trash_chunk();
7056 if (ssl_sock_crt2der(crt, smp_trash) <= 0)
7057 goto out;
7058
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007059 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007060 smp->data.type = SMP_T_BIN;
Emeric Brun43e79582014-10-29 19:03:26 +01007061 ret = 1;
7062out:
7063 /* SSL_get_peer_certificate, it increase X509 * ref count */
7064 if (cert_peer && crt)
7065 X509_free(crt);
7066 return ret;
7067}
7068
Emeric Brunba841a12014-04-30 17:05:08 +02007069/* binary, returns serial of certificate in a binary chunk.
7070 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7071 * should be use.
7072 */
Willy Tarreau8d598402012-10-22 17:58:39 +02007073static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007074smp_fetch_ssl_x_serial(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau8d598402012-10-22 17:58:39 +02007075{
Emeric Brunba841a12014-04-30 17:05:08 +02007076 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Willy Tarreau8d598402012-10-22 17:58:39 +02007077 X509 *crt = NULL;
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;
Willy Tarreaub363a1f2013-10-01 10:45:07 +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)
Willy Tarreau8d598402012-10-22 17:58:39 +02007085 return 0;
7086
Olivier Houchard66ab4982019-02-26 18:37:15 +01007087 ctx = conn->xprt_ctx;
7088
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007089 if (!(conn->flags & CO_FL_CONNECTED)) {
Willy Tarreau8d598402012-10-22 17:58:39 +02007090 smp->flags |= SMP_F_MAY_CHANGE;
7091 return 0;
7092 }
7093
Emeric Brunba841a12014-04-30 17:05:08 +02007094 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007095 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007096 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007097 crt = SSL_get_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007098
Willy Tarreau8d598402012-10-22 17:58:39 +02007099 if (!crt)
7100 goto out;
7101
Willy Tarreau47ca5452012-12-23 20:22:19 +01007102 smp_trash = get_trash_chunk();
Willy Tarreau8d598402012-10-22 17:58:39 +02007103 if (ssl_sock_get_serial(crt, smp_trash) <= 0)
7104 goto out;
7105
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007106 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007107 smp->data.type = SMP_T_BIN;
Willy Tarreau8d598402012-10-22 17:58:39 +02007108 ret = 1;
7109out:
Emeric Brunba841a12014-04-30 17:05:08 +02007110 /* SSL_get_peer_certificate, it increase X509 * ref count */
7111 if (cert_peer && crt)
Willy Tarreau8d598402012-10-22 17:58:39 +02007112 X509_free(crt);
7113 return ret;
7114}
Emeric Brune64aef12012-09-21 13:15:06 +02007115
Emeric Brunba841a12014-04-30 17:05:08 +02007116/* binary, returns the client certificate's SHA-1 fingerprint (SHA-1 hash of DER-encoded certificate) in a binary chunk.
7117 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7118 * should be use.
7119 */
James Votha051b4a2013-05-14 20:37:59 +02007120static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007121smp_fetch_ssl_x_sha1(const struct arg *args, struct sample *smp, const char *kw, void *private)
James Votha051b4a2013-05-14 20:37:59 +02007122{
Emeric Brunba841a12014-04-30 17:05:08 +02007123 int cert_peer = (kw[4] == 'c') ? 1 : 0;
James Votha051b4a2013-05-14 20:37:59 +02007124 X509 *crt = NULL;
7125 const EVP_MD *digest;
7126 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02007127 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007128 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007129 struct ssl_sock_ctx *ctx;
James Votha051b4a2013-05-14 20:37:59 +02007130
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007131 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007132 if (!conn || conn->xprt != &ssl_sock)
7133 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007134 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007135
7136 if (!(conn->flags & CO_FL_CONNECTED)) {
James Votha051b4a2013-05-14 20:37:59 +02007137 smp->flags |= SMP_F_MAY_CHANGE;
7138 return 0;
7139 }
7140
Emeric Brunba841a12014-04-30 17:05:08 +02007141 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007142 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007143 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007144 crt = SSL_get_certificate(ctx->ssl);
James Votha051b4a2013-05-14 20:37:59 +02007145 if (!crt)
7146 goto out;
7147
7148 smp_trash = get_trash_chunk();
7149 digest = EVP_sha1();
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007150 X509_digest(crt, digest, (unsigned char *) smp_trash->area,
7151 (unsigned int *)&smp_trash->data);
James Votha051b4a2013-05-14 20:37:59 +02007152
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007153 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007154 smp->data.type = SMP_T_BIN;
James Votha051b4a2013-05-14 20:37:59 +02007155 ret = 1;
7156out:
Emeric Brunba841a12014-04-30 17:05:08 +02007157 /* SSL_get_peer_certificate, it increase X509 * ref count */
7158 if (cert_peer && crt)
James Votha051b4a2013-05-14 20:37:59 +02007159 X509_free(crt);
7160 return ret;
7161}
7162
Emeric Brunba841a12014-04-30 17:05:08 +02007163/* string, returns certificate's notafter date in ASN1_UTCTIME format.
7164 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7165 * should be use.
7166 */
Emeric Brunce5ad802012-10-22 14:11:22 +02007167static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007168smp_fetch_ssl_x_notafter(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunce5ad802012-10-22 14:11:22 +02007169{
Emeric Brunba841a12014-04-30 17:05:08 +02007170 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brunce5ad802012-10-22 14:11:22 +02007171 X509 *crt = NULL;
7172 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02007173 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007174 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007175 struct ssl_sock_ctx *ctx;
Emeric Brunce5ad802012-10-22 14:11:22 +02007176
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007177 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007178 if (!conn || conn->xprt != &ssl_sock)
7179 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007180 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007181
7182 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02007183 smp->flags |= SMP_F_MAY_CHANGE;
7184 return 0;
7185 }
7186
Emeric Brunba841a12014-04-30 17:05:08 +02007187 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007188 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007189 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007190 crt = SSL_get_certificate(ctx->ssl);
Emeric Brunce5ad802012-10-22 14:11:22 +02007191 if (!crt)
7192 goto out;
7193
Willy Tarreau47ca5452012-12-23 20:22:19 +01007194 smp_trash = get_trash_chunk();
Rosen Penev68185952018-12-14 08:47:02 -08007195 if (ssl_sock_get_time(X509_getm_notAfter(crt), smp_trash) <= 0)
Emeric Brunce5ad802012-10-22 14:11:22 +02007196 goto out;
7197
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007198 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007199 smp->data.type = SMP_T_STR;
Emeric Brunce5ad802012-10-22 14:11:22 +02007200 ret = 1;
7201out:
Emeric Brunba841a12014-04-30 17:05:08 +02007202 /* SSL_get_peer_certificate, it increase X509 * ref count */
7203 if (cert_peer && crt)
Emeric Brunce5ad802012-10-22 14:11:22 +02007204 X509_free(crt);
7205 return ret;
7206}
7207
Emeric Brunba841a12014-04-30 17:05:08 +02007208/* string, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. of certificate's issuer
7209 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7210 * should be use.
7211 */
Emeric Brun87855892012-10-17 17:39:35 +02007212static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007213smp_fetch_ssl_x_i_dn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun87855892012-10-17 17:39:35 +02007214{
Emeric Brunba841a12014-04-30 17:05:08 +02007215 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun87855892012-10-17 17:39:35 +02007216 X509 *crt = NULL;
7217 X509_NAME *name;
7218 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02007219 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007220 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007221 struct ssl_sock_ctx *ctx;
Emeric Brun87855892012-10-17 17:39:35 +02007222
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007223 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007224 if (!conn || conn->xprt != &ssl_sock)
7225 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007226 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007227
7228 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02007229 smp->flags |= SMP_F_MAY_CHANGE;
7230 return 0;
7231 }
7232
Emeric Brunba841a12014-04-30 17:05:08 +02007233 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007234 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007235 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007236 crt = SSL_get_certificate(ctx->ssl);
Emeric Brun87855892012-10-17 17:39:35 +02007237 if (!crt)
7238 goto out;
7239
7240 name = X509_get_issuer_name(crt);
7241 if (!name)
7242 goto out;
7243
Willy Tarreau47ca5452012-12-23 20:22:19 +01007244 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02007245 if (args && args[0].type == ARGT_STR) {
7246 int pos = 1;
7247
7248 if (args[1].type == ARGT_SINT)
7249 pos = args[1].data.sint;
Emeric Brun87855892012-10-17 17:39:35 +02007250
7251 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
7252 goto out;
7253 }
7254 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
7255 goto out;
7256
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007257 smp->data.type = SMP_T_STR;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007258 smp->data.u.str = *smp_trash;
Emeric Brun87855892012-10-17 17:39:35 +02007259 ret = 1;
7260out:
Emeric Brunba841a12014-04-30 17:05:08 +02007261 /* SSL_get_peer_certificate, it increase X509 * ref count */
7262 if (cert_peer && crt)
Emeric Brun87855892012-10-17 17:39:35 +02007263 X509_free(crt);
7264 return ret;
7265}
7266
Emeric Brunba841a12014-04-30 17:05:08 +02007267/* string, returns notbefore date in ASN1_UTCTIME format.
7268 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7269 * should be use.
7270 */
Emeric Brunce5ad802012-10-22 14:11:22 +02007271static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007272smp_fetch_ssl_x_notbefore(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunce5ad802012-10-22 14:11:22 +02007273{
Emeric Brunba841a12014-04-30 17:05:08 +02007274 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brunce5ad802012-10-22 14:11:22 +02007275 X509 *crt = NULL;
7276 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02007277 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007278 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007279 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007280
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007281 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007282 if (!conn || conn->xprt != &ssl_sock)
Emeric Brunce5ad802012-10-22 14:11:22 +02007283 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007284 ctx = conn->xprt_ctx;
Emeric Brunce5ad802012-10-22 14:11:22 +02007285
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007286 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02007287 smp->flags |= SMP_F_MAY_CHANGE;
7288 return 0;
7289 }
7290
Emeric Brunba841a12014-04-30 17:05:08 +02007291 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007292 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007293 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007294 crt = SSL_get_certificate(ctx->ssl);
Emeric Brunce5ad802012-10-22 14:11:22 +02007295 if (!crt)
7296 goto out;
7297
Willy Tarreau47ca5452012-12-23 20:22:19 +01007298 smp_trash = get_trash_chunk();
Rosen Penev68185952018-12-14 08:47:02 -08007299 if (ssl_sock_get_time(X509_getm_notBefore(crt), smp_trash) <= 0)
Emeric Brunce5ad802012-10-22 14:11:22 +02007300 goto out;
7301
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007302 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007303 smp->data.type = SMP_T_STR;
Emeric Brunce5ad802012-10-22 14:11:22 +02007304 ret = 1;
7305out:
Emeric Brunba841a12014-04-30 17:05:08 +02007306 /* SSL_get_peer_certificate, it increase X509 * ref count */
7307 if (cert_peer && crt)
Emeric Brunce5ad802012-10-22 14:11:22 +02007308 X509_free(crt);
7309 return ret;
7310}
7311
Emeric Brunba841a12014-04-30 17:05:08 +02007312/* string, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. of certificate's subject
7313 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7314 * should be use.
7315 */
Emeric Brun87855892012-10-17 17:39:35 +02007316static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007317smp_fetch_ssl_x_s_dn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun87855892012-10-17 17:39:35 +02007318{
Emeric Brunba841a12014-04-30 17:05:08 +02007319 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun87855892012-10-17 17:39:35 +02007320 X509 *crt = NULL;
7321 X509_NAME *name;
7322 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02007323 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007324 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007325 struct ssl_sock_ctx *ctx;
Emeric Brun87855892012-10-17 17:39:35 +02007326
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007327 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007328 if (!conn || conn->xprt != &ssl_sock)
7329 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007330 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007331
7332 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02007333 smp->flags |= SMP_F_MAY_CHANGE;
7334 return 0;
7335 }
7336
Emeric Brunba841a12014-04-30 17:05:08 +02007337 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007338 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007339 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007340 crt = SSL_get_certificate(ctx->ssl);
Emeric Brun87855892012-10-17 17:39:35 +02007341 if (!crt)
7342 goto out;
7343
7344 name = X509_get_subject_name(crt);
7345 if (!name)
7346 goto out;
7347
Willy Tarreau47ca5452012-12-23 20:22:19 +01007348 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02007349 if (args && args[0].type == ARGT_STR) {
7350 int pos = 1;
7351
7352 if (args[1].type == ARGT_SINT)
7353 pos = args[1].data.sint;
Emeric Brun87855892012-10-17 17:39:35 +02007354
7355 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
7356 goto out;
7357 }
7358 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
7359 goto out;
7360
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007361 smp->data.type = SMP_T_STR;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007362 smp->data.u.str = *smp_trash;
Emeric Brun87855892012-10-17 17:39:35 +02007363 ret = 1;
7364out:
Emeric Brunba841a12014-04-30 17:05:08 +02007365 /* SSL_get_peer_certificate, it increase X509 * ref count */
7366 if (cert_peer && crt)
Emeric Brun87855892012-10-17 17:39:35 +02007367 X509_free(crt);
7368 return ret;
7369}
Emeric Brun9143d372012-12-20 15:44:16 +01007370
7371/* integer, returns true if current session use a client certificate */
7372static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007373smp_fetch_ssl_c_used(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun9143d372012-12-20 15:44:16 +01007374{
7375 X509 *crt;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007376 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007377 struct ssl_sock_ctx *ctx;
Emeric Brun9143d372012-12-20 15:44:16 +01007378
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007379 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007380 if (!conn || conn->xprt != &ssl_sock)
7381 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007382 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007383
7384 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun9143d372012-12-20 15:44:16 +01007385 smp->flags |= SMP_F_MAY_CHANGE;
7386 return 0;
7387 }
7388
7389 /* SSL_get_peer_certificate returns a ptr on allocated X509 struct */
Olivier Houchard66ab4982019-02-26 18:37:15 +01007390 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brun9143d372012-12-20 15:44:16 +01007391 if (crt) {
7392 X509_free(crt);
7393 }
7394
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007395 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007396 smp->data.u.sint = (crt != NULL);
Emeric Brun9143d372012-12-20 15:44:16 +01007397 return 1;
7398}
7399
Emeric Brunba841a12014-04-30 17:05:08 +02007400/* integer, returns the certificate version
7401 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7402 * should be use.
7403 */
Emeric Bruna7359fd2012-10-17 15:03:11 +02007404static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007405smp_fetch_ssl_x_version(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Bruna7359fd2012-10-17 15:03:11 +02007406{
Emeric Brunba841a12014-04-30 17:05:08 +02007407 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Bruna7359fd2012-10-17 15:03:11 +02007408 X509 *crt;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007409 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007410 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007411
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007412 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007413 if (!conn || conn->xprt != &ssl_sock)
Emeric Bruna7359fd2012-10-17 15:03:11 +02007414 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007415 ctx = conn->xprt_ctx;
Emeric Bruna7359fd2012-10-17 15:03:11 +02007416
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007417 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Bruna7359fd2012-10-17 15:03:11 +02007418 smp->flags |= SMP_F_MAY_CHANGE;
7419 return 0;
7420 }
7421
Emeric Brunba841a12014-04-30 17:05:08 +02007422 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007423 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007424 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007425 crt = SSL_get_certificate(ctx->ssl);
Emeric Bruna7359fd2012-10-17 15:03:11 +02007426 if (!crt)
7427 return 0;
7428
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007429 smp->data.u.sint = (unsigned int)(1 + X509_get_version(crt));
Emeric Brunba841a12014-04-30 17:05:08 +02007430 /* SSL_get_peer_certificate increase X509 * ref count */
7431 if (cert_peer)
7432 X509_free(crt);
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007433 smp->data.type = SMP_T_SINT;
Emeric Bruna7359fd2012-10-17 15:03:11 +02007434
7435 return 1;
7436}
7437
Emeric Brunba841a12014-04-30 17:05:08 +02007438/* string, returns the certificate's signature algorithm.
7439 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7440 * should be use.
7441 */
Emeric Brun7f56e742012-10-19 18:15:40 +02007442static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007443smp_fetch_ssl_x_sig_alg(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun7f56e742012-10-19 18:15:40 +02007444{
Emeric Brunba841a12014-04-30 17:05:08 +02007445 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun7f56e742012-10-19 18:15:40 +02007446 X509 *crt;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007447 __OPENSSL_110_CONST__ ASN1_OBJECT *algorithm;
Emeric Brun7f56e742012-10-19 18:15:40 +02007448 int nid;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007449 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007450 struct ssl_sock_ctx *ctx;
Emeric Brun7f56e742012-10-19 18:15:40 +02007451
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007452 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007453 if (!conn || conn->xprt != &ssl_sock)
7454 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007455 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007456
7457 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun7f56e742012-10-19 18:15:40 +02007458 smp->flags |= SMP_F_MAY_CHANGE;
7459 return 0;
7460 }
7461
Emeric Brunba841a12014-04-30 17:05:08 +02007462 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007463 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007464 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007465 crt = SSL_get_certificate(ctx->ssl);
Emeric Brun7f56e742012-10-19 18:15:40 +02007466 if (!crt)
7467 return 0;
7468
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007469 X509_ALGOR_get0(&algorithm, NULL, NULL, X509_get0_tbs_sigalg(crt));
7470 nid = OBJ_obj2nid(algorithm);
Emeric Brun7f56e742012-10-19 18:15:40 +02007471
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007472 smp->data.u.str.area = (char *)OBJ_nid2sn(nid);
7473 if (!smp->data.u.str.area) {
Emeric Brunba841a12014-04-30 17:05:08 +02007474 /* SSL_get_peer_certificate increase X509 * ref count */
7475 if (cert_peer)
7476 X509_free(crt);
Emeric Brun7f56e742012-10-19 18:15:40 +02007477 return 0;
Emeric Brun9bf3ba22013-10-07 14:31:44 +02007478 }
Emeric Brun7f56e742012-10-19 18:15:40 +02007479
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007480 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01007481 smp->flags |= SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007482 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brunba841a12014-04-30 17:05:08 +02007483 /* SSL_get_peer_certificate increase X509 * ref count */
7484 if (cert_peer)
7485 X509_free(crt);
Emeric Brun7f56e742012-10-19 18:15:40 +02007486
7487 return 1;
7488}
7489
Emeric Brunba841a12014-04-30 17:05:08 +02007490/* string, returns the certificate's key algorithm.
7491 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7492 * should be use.
7493 */
Emeric Brun521a0112012-10-22 12:22:55 +02007494static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007495smp_fetch_ssl_x_key_alg(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun521a0112012-10-22 12:22:55 +02007496{
Emeric Brunba841a12014-04-30 17:05:08 +02007497 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun521a0112012-10-22 12:22:55 +02007498 X509 *crt;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007499 ASN1_OBJECT *algorithm;
Emeric Brun521a0112012-10-22 12:22:55 +02007500 int nid;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007501 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007502 struct ssl_sock_ctx *ctx;
Emeric Brun521a0112012-10-22 12:22:55 +02007503
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007504 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007505 if (!conn || conn->xprt != &ssl_sock)
7506 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007507 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007508
7509 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun521a0112012-10-22 12:22:55 +02007510 smp->flags |= SMP_F_MAY_CHANGE;
7511 return 0;
7512 }
7513
Emeric Brunba841a12014-04-30 17:05:08 +02007514 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007515 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007516 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007517 crt = SSL_get_certificate(ctx->ssl);
Emeric Brun521a0112012-10-22 12:22:55 +02007518 if (!crt)
7519 return 0;
7520
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007521 X509_PUBKEY_get0_param(&algorithm, NULL, NULL, NULL, X509_get_X509_PUBKEY(crt));
7522 nid = OBJ_obj2nid(algorithm);
Emeric Brun521a0112012-10-22 12:22:55 +02007523
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007524 smp->data.u.str.area = (char *)OBJ_nid2sn(nid);
7525 if (!smp->data.u.str.area) {
Emeric Brunba841a12014-04-30 17:05:08 +02007526 /* SSL_get_peer_certificate increase X509 * ref count */
7527 if (cert_peer)
7528 X509_free(crt);
Emeric Brun521a0112012-10-22 12:22:55 +02007529 return 0;
Emeric Brun9bf3ba22013-10-07 14:31:44 +02007530 }
Emeric Brun521a0112012-10-22 12:22:55 +02007531
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007532 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01007533 smp->flags |= SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007534 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brunba841a12014-04-30 17:05:08 +02007535 if (cert_peer)
7536 X509_free(crt);
Emeric Brun521a0112012-10-22 12:22:55 +02007537
7538 return 1;
7539}
7540
Emeric Brun645ae792014-04-30 14:21:06 +02007541/* boolean, returns true if front conn. transport layer is SSL.
7542 * This function is also usable on backend conn if the fetch keyword 5th
7543 * char is 'b'.
7544 */
Willy Tarreau7875d092012-09-10 08:20:03 +02007545static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007546smp_fetch_ssl_fc(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02007547{
Emeric Bruneb8def92018-02-19 15:59:48 +01007548 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7549 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007550
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007551 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007552 smp->data.u.sint = (conn && conn->xprt == &ssl_sock);
Willy Tarreau7875d092012-09-10 08:20:03 +02007553 return 1;
7554}
7555
Emeric Brun2525b6b2012-10-18 15:59:43 +02007556/* boolean, returns true if client present a SNI */
Willy Tarreau7875d092012-09-10 08:20:03 +02007557static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007558smp_fetch_ssl_fc_has_sni(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02007559{
7560#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007561 struct connection *conn = objt_conn(smp->sess->origin);
Olivier Houchard66ab4982019-02-26 18:37:15 +01007562 struct ssl_sock_ctx *ctx = conn ? conn->xprt_ctx : NULL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007563
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007564 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007565 smp->data.u.sint = (conn && conn->xprt == &ssl_sock) &&
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007566 conn->xprt_ctx &&
Olivier Houchard66ab4982019-02-26 18:37:15 +01007567 SSL_get_servername(ctx->ssl, TLSEXT_NAMETYPE_host_name) != NULL;
Willy Tarreau7875d092012-09-10 08:20:03 +02007568 return 1;
7569#else
7570 return 0;
7571#endif
7572}
7573
Emeric Brun74f7ffa2018-02-19 16:14:12 +01007574/* boolean, returns true if client session has been resumed.
7575 * This function is also usable on backend conn if the fetch keyword 5th
7576 * char is 'b'.
7577 */
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02007578static int
7579smp_fetch_ssl_fc_is_resumed(const struct arg *args, struct sample *smp, const char *kw, void *private)
7580{
Emeric Brun74f7ffa2018-02-19 16:14:12 +01007581 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7582 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007583 struct ssl_sock_ctx *ctx = conn ? conn->xprt_ctx : NULL;
Emeric Brun74f7ffa2018-02-19 16:14:12 +01007584
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02007585
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007586 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007587 smp->data.u.sint = (conn && conn->xprt == &ssl_sock) &&
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02007588 conn->xprt_ctx &&
Olivier Houchard66ab4982019-02-26 18:37:15 +01007589 SSL_session_reused(ctx->ssl);
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02007590 return 1;
7591}
7592
Emeric Brun645ae792014-04-30 14:21:06 +02007593/* string, returns the used cipher if front conn. transport layer is SSL.
7594 * This function is also usable on backend conn if the fetch keyword 5th
7595 * char is 'b'.
7596 */
Emeric Brun589fcad2012-10-16 14:13:26 +02007597static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007598smp_fetch_ssl_fc_cipher(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02007599{
Emeric Bruneb8def92018-02-19 15:59:48 +01007600 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7601 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007602 struct ssl_sock_ctx *ctx;
Emeric Brun589fcad2012-10-16 14:13:26 +02007603
Willy Tarreaube508f12016-03-10 11:47:01 +01007604 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007605 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02007606 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007607 ctx = conn->xprt_ctx;
Emeric Brun589fcad2012-10-16 14:13:26 +02007608
Olivier Houchard66ab4982019-02-26 18:37:15 +01007609 smp->data.u.str.area = (char *)SSL_get_cipher_name(ctx->ssl);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007610 if (!smp->data.u.str.area)
Emeric Brun589fcad2012-10-16 14:13:26 +02007611 return 0;
7612
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007613 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01007614 smp->flags |= SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007615 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brun589fcad2012-10-16 14:13:26 +02007616
7617 return 1;
7618}
7619
Emeric Brun645ae792014-04-30 14:21:06 +02007620/* integer, returns the algoritm's keysize if front conn. transport layer
7621 * is SSL.
7622 * This function is also usable on backend conn if the fetch keyword 5th
7623 * char is 'b'.
7624 */
Emeric Brun589fcad2012-10-16 14:13:26 +02007625static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007626smp_fetch_ssl_fc_alg_keysize(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02007627{
Emeric Bruneb8def92018-02-19 15:59:48 +01007628 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7629 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007630 struct ssl_sock_ctx *ctx;
Willy Tarreaue237fe12016-03-10 17:05:28 +01007631 int sint;
Willy Tarreaube508f12016-03-10 11:47:01 +01007632
Emeric Brun589fcad2012-10-16 14:13:26 +02007633 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007634 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02007635 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007636 ctx = conn->xprt_ctx;
Emeric Brun589fcad2012-10-16 14:13:26 +02007637
Olivier Houchard66ab4982019-02-26 18:37:15 +01007638 if (!SSL_get_cipher_bits(ctx->ssl, &sint))
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007639 return 0;
7640
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007641 smp->data.u.sint = sint;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007642 smp->data.type = SMP_T_SINT;
Emeric Brun589fcad2012-10-16 14:13:26 +02007643
7644 return 1;
7645}
7646
Emeric Brun645ae792014-04-30 14:21:06 +02007647/* integer, returns the used keysize if front conn. transport layer is SSL.
7648 * This function is also usable on backend conn if the fetch keyword 5th
7649 * char is 'b'.
7650 */
Emeric Brun589fcad2012-10-16 14:13:26 +02007651static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007652smp_fetch_ssl_fc_use_keysize(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02007653{
Emeric Bruneb8def92018-02-19 15:59:48 +01007654 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7655 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007656 struct ssl_sock_ctx *ctx;
Willy Tarreaube508f12016-03-10 11:47:01 +01007657
Emeric Brun589fcad2012-10-16 14:13:26 +02007658 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007659 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7660 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007661 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007662
Olivier Houchard66ab4982019-02-26 18:37:15 +01007663 smp->data.u.sint = (unsigned int)SSL_get_cipher_bits(ctx->ssl, NULL);
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007664 if (!smp->data.u.sint)
Emeric Brun589fcad2012-10-16 14:13:26 +02007665 return 0;
7666
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007667 smp->data.type = SMP_T_SINT;
Emeric Brun589fcad2012-10-16 14:13:26 +02007668
7669 return 1;
7670}
7671
Bernard Spil13c53f82018-02-15 13:34:58 +01007672#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Willy Tarreau7875d092012-09-10 08:20:03 +02007673static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007674smp_fetch_ssl_fc_npn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreaua33c6542012-10-15 13:19:06 +02007675{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007676 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007677 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007678
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01007679 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007680 smp->data.type = SMP_T_STR;
Willy Tarreaua33c6542012-10-15 13:19:06 +02007681
Olivier Houchard6b77f492018-11-22 18:18:29 +01007682 conn = (kw[4] != 'b' ) ? objt_conn(smp->sess->origin) :
7683 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007684 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7685 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007686 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007687
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007688 smp->data.u.str.area = NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007689 SSL_get0_next_proto_negotiated(ctx->ssl,
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007690 (const unsigned char **)&smp->data.u.str.area,
7691 (unsigned *)&smp->data.u.str.data);
Willy Tarreaua33c6542012-10-15 13:19:06 +02007692
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007693 if (!smp->data.u.str.area)
Willy Tarreaua33c6542012-10-15 13:19:06 +02007694 return 0;
7695
7696 return 1;
Willy Tarreaua33c6542012-10-15 13:19:06 +02007697}
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02007698#endif
Willy Tarreaua33c6542012-10-15 13:19:06 +02007699
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01007700#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02007701static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007702smp_fetch_ssl_fc_alpn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreauab861d32013-04-02 02:30:41 +02007703{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007704 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007705 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007706
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01007707 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007708 smp->data.type = SMP_T_STR;
Willy Tarreauab861d32013-04-02 02:30:41 +02007709
Olivier Houchard6b77f492018-11-22 18:18:29 +01007710 conn = (kw[4] != 'b' ) ? objt_conn(smp->sess->origin) :
7711 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
7712
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007713 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Willy Tarreauab861d32013-04-02 02:30:41 +02007714 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007715 ctx = conn->xprt_ctx;
Willy Tarreauab861d32013-04-02 02:30:41 +02007716
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007717 smp->data.u.str.area = NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007718 SSL_get0_alpn_selected(ctx->ssl,
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007719 (const unsigned char **)&smp->data.u.str.area,
7720 (unsigned *)&smp->data.u.str.data);
Willy Tarreauab861d32013-04-02 02:30:41 +02007721
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007722 if (!smp->data.u.str.area)
Willy Tarreauab861d32013-04-02 02:30:41 +02007723 return 0;
7724
7725 return 1;
7726}
7727#endif
7728
Emeric Brun645ae792014-04-30 14:21:06 +02007729/* string, returns the used protocol if front conn. transport layer is SSL.
7730 * This function is also usable on backend conn if the fetch keyword 5th
7731 * char is 'b'.
7732 */
Willy Tarreaua33c6542012-10-15 13:19:06 +02007733static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007734smp_fetch_ssl_fc_protocol(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02007735{
Emeric Bruneb8def92018-02-19 15:59:48 +01007736 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7737 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007738 struct ssl_sock_ctx *ctx;
Willy Tarreaube508f12016-03-10 11:47:01 +01007739
Emeric Brun589fcad2012-10-16 14:13:26 +02007740 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007741 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7742 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007743 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007744
Olivier Houchard66ab4982019-02-26 18:37:15 +01007745 smp->data.u.str.area = (char *)SSL_get_version(ctx->ssl);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007746 if (!smp->data.u.str.area)
Emeric Brun589fcad2012-10-16 14:13:26 +02007747 return 0;
7748
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007749 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01007750 smp->flags = SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007751 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brun589fcad2012-10-16 14:13:26 +02007752
7753 return 1;
7754}
7755
Willy Tarreau87b09662015-04-03 00:22:06 +02007756/* binary, returns the SSL stream id if front conn. transport layer is SSL.
Emeric Brun645ae792014-04-30 14:21:06 +02007757 * This function is also usable on backend conn if the fetch keyword 5th
7758 * char is 'b'.
7759 */
Willy Tarreau9a1ab082019-05-09 13:26:41 +02007760#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
Emeric Brun589fcad2012-10-16 14:13:26 +02007761static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007762smp_fetch_ssl_fc_session_id(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunfe68f682012-10-16 14:59:28 +02007763{
Emeric Bruneb8def92018-02-19 15:59:48 +01007764 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7765 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaue237fe12016-03-10 17:05:28 +01007766 SSL_SESSION *ssl_sess;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007767 struct ssl_sock_ctx *ctx;
Willy Tarreaube508f12016-03-10 11:47:01 +01007768
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01007769 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007770 smp->data.type = SMP_T_BIN;
Emeric Brunfe68f682012-10-16 14:59:28 +02007771
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007772 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7773 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007774 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007775
Olivier Houchard66ab4982019-02-26 18:37:15 +01007776 ssl_sess = SSL_get_session(ctx->ssl);
Willy Tarreau192252e2015-04-04 01:47:55 +02007777 if (!ssl_sess)
Emeric Brunfe68f682012-10-16 14:59:28 +02007778 return 0;
7779
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007780 smp->data.u.str.area = (char *)SSL_SESSION_get_id(ssl_sess,
7781 (unsigned int *)&smp->data.u.str.data);
7782 if (!smp->data.u.str.area || !smp->data.u.str.data)
Emeric Brunfe68f682012-10-16 14:59:28 +02007783 return 0;
7784
7785 return 1;
Emeric Brunfe68f682012-10-16 14:59:28 +02007786}
Patrick Hemmer41966772018-04-28 19:15:48 -04007787#endif
7788
Emeric Brunfe68f682012-10-16 14:59:28 +02007789
Emmanuel Hocdet839af572019-05-14 16:27:35 +02007790#if HA_OPENSSL_VERSION_NUMBER >= 0x10100000L
Patrick Hemmere0275472018-04-28 19:15:51 -04007791static int
Patrick Hemmer65674662019-06-04 08:13:03 -04007792smp_fetch_ssl_fc_random(const struct arg *args, struct sample *smp, const char *kw, void *private)
7793{
7794 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7795 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
7796 struct buffer *data;
7797 struct ssl_sock_ctx *ctx;
7798
7799 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7800 return 0;
7801 ctx = conn->xprt_ctx;
7802
7803 data = get_trash_chunk();
7804 if (kw[7] == 'c')
7805 data->data = SSL_get_client_random(ctx->ssl,
7806 (unsigned char *) data->area,
7807 data->size);
7808 else
7809 data->data = SSL_get_server_random(ctx->ssl,
7810 (unsigned char *) data->area,
7811 data->size);
7812 if (!data->data)
7813 return 0;
7814
7815 smp->flags = 0;
7816 smp->data.type = SMP_T_BIN;
7817 smp->data.u.str = *data;
7818
7819 return 1;
7820}
7821
7822static int
Patrick Hemmere0275472018-04-28 19:15:51 -04007823smp_fetch_ssl_fc_session_key(const struct arg *args, struct sample *smp, const char *kw, void *private)
7824{
7825 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7826 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
7827 SSL_SESSION *ssl_sess;
Willy Tarreau83061a82018-07-13 11:56:34 +02007828 struct buffer *data;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007829 struct ssl_sock_ctx *ctx;
Patrick Hemmere0275472018-04-28 19:15:51 -04007830
7831 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7832 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007833 ctx = conn->xprt_ctx;
Patrick Hemmere0275472018-04-28 19:15:51 -04007834
Olivier Houchard66ab4982019-02-26 18:37:15 +01007835 ssl_sess = SSL_get_session(ctx->ssl);
Patrick Hemmere0275472018-04-28 19:15:51 -04007836 if (!ssl_sess)
7837 return 0;
7838
7839 data = get_trash_chunk();
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007840 data->data = SSL_SESSION_get_master_key(ssl_sess,
7841 (unsigned char *) data->area,
7842 data->size);
7843 if (!data->data)
Patrick Hemmere0275472018-04-28 19:15:51 -04007844 return 0;
7845
7846 smp->flags = 0;
7847 smp->data.type = SMP_T_BIN;
7848 smp->data.u.str = *data;
7849
7850 return 1;
7851}
7852#endif
7853
Patrick Hemmer41966772018-04-28 19:15:48 -04007854#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emeric Brunfe68f682012-10-16 14:59:28 +02007855static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007856smp_fetch_ssl_fc_sni(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02007857{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007858 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007859 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007860
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01007861 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007862 smp->data.type = SMP_T_STR;
Willy Tarreau7875d092012-09-10 08:20:03 +02007863
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007864 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007865 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7866 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007867 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007868
Olivier Houchard66ab4982019-02-26 18:37:15 +01007869 smp->data.u.str.area = (char *)SSL_get_servername(ctx->ssl, TLSEXT_NAMETYPE_host_name);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007870 if (!smp->data.u.str.area)
Willy Tarreau3e394c92012-09-14 23:56:58 +02007871 return 0;
7872
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007873 smp->data.u.str.data = strlen(smp->data.u.str.area);
Willy Tarreau7875d092012-09-10 08:20:03 +02007874 return 1;
Willy Tarreau7875d092012-09-10 08:20:03 +02007875}
Patrick Hemmer41966772018-04-28 19:15:48 -04007876#endif
Willy Tarreau7875d092012-09-10 08:20:03 +02007877
David Sc1ad52e2014-04-08 18:48:47 -04007878static int
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007879smp_fetch_ssl_fc_cl_bin(const struct arg *args, struct sample *smp, const char *kw, void *private)
7880{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007881 struct connection *conn;
7882 struct ssl_capture *capture;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007883 struct ssl_sock_ctx *ctx;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007884
7885 conn = objt_conn(smp->sess->origin);
7886 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7887 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007888 ctx = conn->xprt_ctx;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007889
Olivier Houchard66ab4982019-02-26 18:37:15 +01007890 capture = SSL_get_ex_data(ctx->ssl, ssl_capture_ptr_index);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007891 if (!capture)
7892 return 0;
7893
7894 smp->flags = SMP_F_CONST;
7895 smp->data.type = SMP_T_BIN;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007896 smp->data.u.str.area = capture->ciphersuite;
7897 smp->data.u.str.data = capture->ciphersuite_len;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007898 return 1;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007899}
7900
7901static int
7902smp_fetch_ssl_fc_cl_hex(const struct arg *args, struct sample *smp, const char *kw, void *private)
7903{
Willy Tarreau83061a82018-07-13 11:56:34 +02007904 struct buffer *data;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007905
7906 if (!smp_fetch_ssl_fc_cl_bin(args, smp, kw, private))
7907 return 0;
7908
7909 data = get_trash_chunk();
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007910 dump_binary(data, smp->data.u.str.area, smp->data.u.str.data);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007911 smp->data.type = SMP_T_BIN;
7912 smp->data.u.str = *data;
7913 return 1;
7914}
7915
7916static int
7917smp_fetch_ssl_fc_cl_xxh64(const struct arg *args, struct sample *smp, const char *kw, void *private)
7918{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007919 struct connection *conn;
7920 struct ssl_capture *capture;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007921 struct ssl_sock_ctx *ctx;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007922
7923 conn = objt_conn(smp->sess->origin);
7924 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7925 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007926 ctx = conn->xprt_ctx;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007927
Olivier Houchard66ab4982019-02-26 18:37:15 +01007928 capture = SSL_get_ex_data(ctx->ssl, ssl_capture_ptr_index);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007929 if (!capture)
7930 return 0;
7931
7932 smp->data.type = SMP_T_SINT;
7933 smp->data.u.sint = capture->xxh64;
7934 return 1;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007935}
7936
7937static int
7938smp_fetch_ssl_fc_cl_str(const struct arg *args, struct sample *smp, const char *kw, void *private)
7939{
Willy Tarreau5db847a2019-05-09 14:13:35 +02007940#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL)
Willy Tarreau83061a82018-07-13 11:56:34 +02007941 struct buffer *data;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007942 int i;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007943
7944 if (!smp_fetch_ssl_fc_cl_bin(args, smp, kw, private))
7945 return 0;
7946
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007947 data = get_trash_chunk();
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007948 for (i = 0; i + 1 < smp->data.u.str.data; i += 2) {
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02007949 const char *str;
7950 const SSL_CIPHER *cipher;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007951 const unsigned char *bin = (const unsigned char *) smp->data.u.str.area + i;
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02007952 uint16_t id = (bin[0] << 8) | bin[1];
7953#if defined(OPENSSL_IS_BORINGSSL)
7954 cipher = SSL_get_cipher_by_value(id);
7955#else
Willy Tarreaub7290772018-10-15 11:01:59 +02007956 struct connection *conn = __objt_conn(smp->sess->origin);
Olivier Houchard66ab4982019-02-26 18:37:15 +01007957 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
7958 cipher = SSL_CIPHER_find(ctx->ssl, bin);
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02007959#endif
7960 str = SSL_CIPHER_get_name(cipher);
7961 if (!str || strcmp(str, "(NONE)") == 0)
7962 chunk_appendf(data, "%sUNKNOWN(%04x)", i == 0 ? "" : ",", id);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007963 else
7964 chunk_appendf(data, "%s%s", i == 0 ? "" : ",", str);
7965 }
7966 smp->data.type = SMP_T_STR;
7967 smp->data.u.str = *data;
7968 return 1;
7969#else
7970 return smp_fetch_ssl_fc_cl_xxh64(args, smp, kw, private);
7971#endif
7972}
7973
Willy Tarreau9a1ab082019-05-09 13:26:41 +02007974#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007975static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007976smp_fetch_ssl_fc_unique_id(const struct arg *args, struct sample *smp, const char *kw, void *private)
David Sc1ad52e2014-04-08 18:48:47 -04007977{
Emeric Bruneb8def92018-02-19 15:59:48 +01007978 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7979 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
David Sc1ad52e2014-04-08 18:48:47 -04007980 int finished_len;
Willy Tarreau83061a82018-07-13 11:56:34 +02007981 struct buffer *finished_trash;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007982 struct ssl_sock_ctx *ctx;
David Sc1ad52e2014-04-08 18:48:47 -04007983
7984 smp->flags = 0;
David Sc1ad52e2014-04-08 18:48:47 -04007985 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7986 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007987 ctx = conn->xprt_ctx;
David Sc1ad52e2014-04-08 18:48:47 -04007988
7989 if (!(conn->flags & CO_FL_CONNECTED)) {
7990 smp->flags |= SMP_F_MAY_CHANGE;
7991 return 0;
7992 }
7993
7994 finished_trash = get_trash_chunk();
Olivier Houchard66ab4982019-02-26 18:37:15 +01007995 if (!SSL_session_reused(ctx->ssl))
7996 finished_len = SSL_get_peer_finished(ctx->ssl,
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007997 finished_trash->area,
7998 finished_trash->size);
David Sc1ad52e2014-04-08 18:48:47 -04007999 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01008000 finished_len = SSL_get_finished(ctx->ssl,
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008001 finished_trash->area,
8002 finished_trash->size);
David Sc1ad52e2014-04-08 18:48:47 -04008003
8004 if (!finished_len)
8005 return 0;
8006
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008007 finished_trash->data = finished_len;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02008008 smp->data.u.str = *finished_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008009 smp->data.type = SMP_T_BIN;
David Sc1ad52e2014-04-08 18:48:47 -04008010
8011 return 1;
David Sc1ad52e2014-04-08 18:48:47 -04008012}
Patrick Hemmer41966772018-04-28 19:15:48 -04008013#endif
David Sc1ad52e2014-04-08 18:48:47 -04008014
Emeric Brun2525b6b2012-10-18 15:59:43 +02008015/* integer, returns the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02008016static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008017smp_fetch_ssl_c_ca_err(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunf282a812012-09-21 15:27:54 +02008018{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008019 struct connection *conn;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008020 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008021
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02008022 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008023 if (!conn || conn->xprt != &ssl_sock)
8024 return 0;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008025 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008026
8027 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02008028 smp->flags = SMP_F_MAY_CHANGE;
8029 return 0;
8030 }
8031
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008032 smp->data.type = SMP_T_SINT;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008033 smp->data.u.sint = (unsigned long long int)SSL_SOCK_ST_TO_CA_ERROR(ctx->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02008034 smp->flags = 0;
8035
8036 return 1;
8037}
8038
Emeric Brun2525b6b2012-10-18 15:59:43 +02008039/* integer, returns the depth of the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02008040static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008041smp_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 +02008042{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008043 struct connection *conn;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008044 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008045
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02008046 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008047 if (!conn || conn->xprt != &ssl_sock)
Emeric Brunf282a812012-09-21 15:27:54 +02008048 return 0;
8049
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008050 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02008051 smp->flags = SMP_F_MAY_CHANGE;
8052 return 0;
8053 }
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008054 ctx = conn->xprt_ctx;
Emeric Brunf282a812012-09-21 15:27:54 +02008055
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008056 smp->data.type = SMP_T_SINT;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008057 smp->data.u.sint = (long long int)SSL_SOCK_ST_TO_CAEDEPTH(ctx->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02008058 smp->flags = 0;
8059
8060 return 1;
8061}
8062
Emeric Brun2525b6b2012-10-18 15:59:43 +02008063/* integer, returns the first verify error on client certificate */
Emeric Brunf282a812012-09-21 15:27:54 +02008064static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008065smp_fetch_ssl_c_err(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunf282a812012-09-21 15:27:54 +02008066{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008067 struct connection *conn;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008068 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008069
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02008070 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008071 if (!conn || conn->xprt != &ssl_sock)
8072 return 0;
8073
8074 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02008075 smp->flags = SMP_F_MAY_CHANGE;
8076 return 0;
8077 }
8078
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008079 ctx = conn->xprt_ctx;
8080
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008081 smp->data.type = SMP_T_SINT;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008082 smp->data.u.sint = (long long int)SSL_SOCK_ST_TO_CRTERROR(ctx->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02008083 smp->flags = 0;
8084
8085 return 1;
8086}
8087
Emeric Brun2525b6b2012-10-18 15:59:43 +02008088/* integer, returns the verify result on client cert */
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02008089static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008090smp_fetch_ssl_c_verify(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02008091{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008092 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008093 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008094
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02008095 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008096 if (!conn || conn->xprt != &ssl_sock)
8097 return 0;
8098
8099 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02008100 smp->flags = SMP_F_MAY_CHANGE;
8101 return 0;
8102 }
8103
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008104 if (!conn->xprt_ctx)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02008105 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008106 ctx = conn->xprt_ctx;
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02008107
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008108 smp->data.type = SMP_T_SINT;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008109 smp->data.u.sint = (long long int)SSL_get_verify_result(ctx->ssl);
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02008110 smp->flags = 0;
8111
8112 return 1;
8113}
8114
Emeric Brunfb510ea2012-10-05 12:00:26 +02008115/* parse the "ca-file" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008116static 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 +02008117{
8118 if (!*args[cur_arg + 1]) {
8119 if (err)
8120 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
8121 return ERR_ALERT | ERR_FATAL;
8122 }
8123
Willy Tarreauef934602016-12-22 23:12:01 +01008124 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
8125 memprintf(&conf->ca_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02008126 else
8127 memprintf(&conf->ca_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02008128
Emeric Brund94b3fe2012-09-20 18:23:56 +02008129 return 0;
8130}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008131static int bind_parse_ca_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8132{
8133 return ssl_bind_parse_ca_file(args, cur_arg, px, &conf->ssl_conf, err);
8134}
Emeric Brund94b3fe2012-09-20 18:23:56 +02008135
Christopher Faulet31af49d2015-06-09 17:29:50 +02008136/* parse the "ca-sign-file" bind keyword */
8137static int bind_parse_ca_sign_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8138{
8139 if (!*args[cur_arg + 1]) {
8140 if (err)
8141 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
8142 return ERR_ALERT | ERR_FATAL;
8143 }
8144
Willy Tarreauef934602016-12-22 23:12:01 +01008145 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
8146 memprintf(&conf->ca_sign_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Christopher Faulet31af49d2015-06-09 17:29:50 +02008147 else
8148 memprintf(&conf->ca_sign_file, "%s", args[cur_arg + 1]);
8149
8150 return 0;
8151}
8152
Bertrand Jacquinff13c062016-11-13 16:37:11 +00008153/* parse the "ca-sign-pass" bind keyword */
Christopher Faulet31af49d2015-06-09 17:29:50 +02008154static int bind_parse_ca_sign_pass(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8155{
8156 if (!*args[cur_arg + 1]) {
8157 if (err)
8158 memprintf(err, "'%s' : missing CAkey password", args[cur_arg]);
8159 return ERR_ALERT | ERR_FATAL;
8160 }
8161 memprintf(&conf->ca_sign_pass, "%s", args[cur_arg + 1]);
8162 return 0;
8163}
8164
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008165/* parse the "ciphers" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008166static 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 +02008167{
8168 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02008169 memprintf(err, "'%s' : missing cipher suite", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008170 return ERR_ALERT | ERR_FATAL;
8171 }
8172
Emeric Brun76d88952012-10-05 15:47:31 +02008173 free(conf->ciphers);
Willy Tarreau4348fad2012-09-20 16:48:07 +02008174 conf->ciphers = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008175 return 0;
8176}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008177static int bind_parse_ciphers(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8178{
8179 return ssl_bind_parse_ciphers(args, cur_arg, px, &conf->ssl_conf, err);
8180}
Dirkjan Bussink415150f2018-09-14 11:14:21 +02008181
Emmanuel Hocdet839af572019-05-14 16:27:35 +02008182#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02008183/* parse the "ciphersuites" bind keyword */
8184static int ssl_bind_parse_ciphersuites(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
8185{
8186 if (!*args[cur_arg + 1]) {
8187 memprintf(err, "'%s' : missing cipher suite", args[cur_arg]);
8188 return ERR_ALERT | ERR_FATAL;
8189 }
8190
8191 free(conf->ciphersuites);
8192 conf->ciphersuites = strdup(args[cur_arg + 1]);
8193 return 0;
8194}
8195static int bind_parse_ciphersuites(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8196{
8197 return ssl_bind_parse_ciphersuites(args, cur_arg, px, &conf->ssl_conf, err);
8198}
8199#endif
8200
Willy Tarreaubbc91962019-10-16 16:42:19 +02008201/* parse the "crt" bind keyword. Returns a set of ERR_* flags possibly with an error in <err>. */
Willy Tarreau4348fad2012-09-20 16:48:07 +02008202static 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 +02008203{
Willy Tarreau38011032013-08-13 16:59:39 +02008204 char path[MAXPATHLEN];
Willy Tarreaub75d6922014-04-14 18:05:41 +02008205
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008206 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02008207 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008208 return ERR_ALERT | ERR_FATAL;
8209 }
8210
Willy Tarreauef934602016-12-22 23:12:01 +01008211 if ((*args[cur_arg + 1] != '/' ) && global_ssl.crt_base) {
8212 if ((strlen(global_ssl.crt_base) + 1 + strlen(args[cur_arg + 1]) + 1) > MAXPATHLEN) {
Emeric Brunc8e8d122012-10-02 18:42:10 +02008213 memprintf(err, "'%s' : path too long", args[cur_arg]);
8214 return ERR_ALERT | ERR_FATAL;
8215 }
Willy Tarreauef934602016-12-22 23:12:01 +01008216 snprintf(path, sizeof(path), "%s/%s", global_ssl.crt_base, args[cur_arg + 1]);
Willy Tarreaubbc91962019-10-16 16:42:19 +02008217 return ssl_sock_load_cert(path, conf, err);
Emeric Brunc8e8d122012-10-02 18:42:10 +02008218 }
8219
Willy Tarreaubbc91962019-10-16 16:42:19 +02008220 return ssl_sock_load_cert(args[cur_arg + 1], conf, err);
Emeric Brund94b3fe2012-09-20 18:23:56 +02008221}
8222
Willy Tarreaubbc91962019-10-16 16:42:19 +02008223/* 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 +01008224static int bind_parse_crt_list(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8225{
Willy Tarreaubbc91962019-10-16 16:42:19 +02008226 int err_code;
8227
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01008228 if (!*args[cur_arg + 1]) {
8229 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
8230 return ERR_ALERT | ERR_FATAL;
8231 }
8232
Willy Tarreaubbc91962019-10-16 16:42:19 +02008233 err_code = ssl_sock_load_cert_list_file(args[cur_arg + 1], conf, px, err);
8234 if (err_code)
Willy Tarreauad1731d2013-04-02 17:35:58 +02008235 memprintf(err, "'%s' : %s", args[cur_arg], *err);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01008236
Willy Tarreaubbc91962019-10-16 16:42:19 +02008237 return err_code;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01008238}
8239
Emeric Brunfb510ea2012-10-05 12:00:26 +02008240/* parse the "crl-file" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008241static 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 +02008242{
Emeric Brun051cdab2012-10-02 19:25:50 +02008243#ifndef X509_V_FLAG_CRL_CHECK
8244 if (err)
8245 memprintf(err, "'%s' : library does not support CRL verify", args[cur_arg]);
8246 return ERR_ALERT | ERR_FATAL;
8247#else
Emeric Brund94b3fe2012-09-20 18:23:56 +02008248 if (!*args[cur_arg + 1]) {
8249 if (err)
8250 memprintf(err, "'%s' : missing CRLfile path", args[cur_arg]);
8251 return ERR_ALERT | ERR_FATAL;
8252 }
Emeric Brun2b58d042012-09-20 17:10:03 +02008253
Willy Tarreauef934602016-12-22 23:12:01 +01008254 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
8255 memprintf(&conf->crl_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02008256 else
8257 memprintf(&conf->crl_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02008258
Emeric Brun2b58d042012-09-20 17:10:03 +02008259 return 0;
Emeric Brun051cdab2012-10-02 19:25:50 +02008260#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02008261}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008262static int bind_parse_crl_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8263{
8264 return ssl_bind_parse_crl_file(args, cur_arg, px, &conf->ssl_conf, err);
8265}
Emeric Brun2b58d042012-09-20 17:10:03 +02008266
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01008267/* parse the "curves" bind keyword keyword */
8268static int ssl_bind_parse_curves(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
8269{
Willy Tarreau9a1ab082019-05-09 13:26:41 +02008270#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01008271 if (!*args[cur_arg + 1]) {
8272 if (err)
8273 memprintf(err, "'%s' : missing curve suite", args[cur_arg]);
8274 return ERR_ALERT | ERR_FATAL;
8275 }
8276 conf->curves = strdup(args[cur_arg + 1]);
8277 return 0;
8278#else
8279 if (err)
8280 memprintf(err, "'%s' : library does not support curve suite", args[cur_arg]);
8281 return ERR_ALERT | ERR_FATAL;
8282#endif
8283}
8284static int bind_parse_curves(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8285{
8286 return ssl_bind_parse_curves(args, cur_arg, px, &conf->ssl_conf, err);
8287}
8288
Bertrand Jacquinff13c062016-11-13 16:37:11 +00008289/* parse the "ecdhe" bind keyword keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008290static 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 +02008291{
Willy Tarreau9a1ab082019-05-09 13:26:41 +02008292#if HA_OPENSSL_VERSION_NUMBER < 0x0090800fL
Emeric Brun2b58d042012-09-20 17:10:03 +02008293 if (err)
8294 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (too old)", args[cur_arg]);
8295 return ERR_ALERT | ERR_FATAL;
8296#elif defined(OPENSSL_NO_ECDH)
8297 if (err)
8298 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (disabled via OPENSSL_NO_ECDH)", args[cur_arg]);
8299 return ERR_ALERT | ERR_FATAL;
8300#else
8301 if (!*args[cur_arg + 1]) {
8302 if (err)
8303 memprintf(err, "'%s' : missing named curve", args[cur_arg]);
8304 return ERR_ALERT | ERR_FATAL;
8305 }
8306
8307 conf->ecdhe = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008308
8309 return 0;
Emeric Brun2b58d042012-09-20 17:10:03 +02008310#endif
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008311}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008312static int bind_parse_ecdhe(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8313{
8314 return ssl_bind_parse_ecdhe(args, cur_arg, px, &conf->ssl_conf, err);
8315}
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008316
Bertrand Jacquinff13c062016-11-13 16:37:11 +00008317/* parse the "crt-ignore-err" and "ca-ignore-err" bind keywords */
Emeric Brun81c00f02012-09-21 14:31:21 +02008318static int bind_parse_ignore_err(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8319{
8320 int code;
8321 char *p = args[cur_arg + 1];
8322 unsigned long long *ignerr = &conf->crt_ignerr;
8323
8324 if (!*p) {
8325 if (err)
8326 memprintf(err, "'%s' : missing error IDs list", args[cur_arg]);
8327 return ERR_ALERT | ERR_FATAL;
8328 }
8329
8330 if (strcmp(args[cur_arg], "ca-ignore-err") == 0)
8331 ignerr = &conf->ca_ignerr;
8332
8333 if (strcmp(p, "all") == 0) {
8334 *ignerr = ~0ULL;
8335 return 0;
8336 }
8337
8338 while (p) {
8339 code = atoi(p);
8340 if ((code <= 0) || (code > 63)) {
8341 if (err)
8342 memprintf(err, "'%s' : ID '%d' out of range (1..63) in error IDs list '%s'",
8343 args[cur_arg], code, args[cur_arg + 1]);
8344 return ERR_ALERT | ERR_FATAL;
8345 }
8346 *ignerr |= 1ULL << code;
8347 p = strchr(p, ',');
8348 if (p)
8349 p++;
8350 }
8351
Emeric Brun2cb7ae52012-10-05 14:14:21 +02008352 return 0;
8353}
8354
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008355/* parse tls_method_options "no-xxx" and "force-xxx" */
8356static int parse_tls_method_options(char *arg, struct tls_version_filter *methods, char **err)
Emeric Brun2cb7ae52012-10-05 14:14:21 +02008357{
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008358 uint16_t v;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008359 char *p;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008360 p = strchr(arg, '-');
8361 if (!p)
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008362 goto fail;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008363 p++;
8364 if (!strcmp(p, "sslv3"))
8365 v = CONF_SSLV3;
8366 else if (!strcmp(p, "tlsv10"))
8367 v = CONF_TLSV10;
8368 else if (!strcmp(p, "tlsv11"))
8369 v = CONF_TLSV11;
8370 else if (!strcmp(p, "tlsv12"))
8371 v = CONF_TLSV12;
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +02008372 else if (!strcmp(p, "tlsv13"))
8373 v = CONF_TLSV13;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008374 else
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008375 goto fail;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008376 if (!strncmp(arg, "no-", 3))
8377 methods->flags |= methodVersions[v].flag;
8378 else if (!strncmp(arg, "force-", 6))
8379 methods->min = methods->max = v;
8380 else
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008381 goto fail;
Emeric Brun2d0c4822012-10-02 13:45:20 +02008382 return 0;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008383 fail:
8384 if (err)
8385 memprintf(err, "'%s' : option not implemented", arg);
8386 return ERR_ALERT | ERR_FATAL;
Emeric Brun2d0c4822012-10-02 13:45:20 +02008387}
8388
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008389static 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 +02008390{
Emmanuel Hocdet43664762017-08-09 18:26:20 +02008391 return parse_tls_method_options(args[cur_arg], &conf->ssl_conf.ssl_methods, err);
Emeric Brun2cb7ae52012-10-05 14:14:21 +02008392}
8393
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008394static 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 +02008395{
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008396 return parse_tls_method_options(args[*cur_arg], &newsrv->ssl_ctx.methods, err);
8397}
8398
8399/* parse tls_method min/max: "ssl-min-ver" and "ssl-max-ver" */
8400static int parse_tls_method_minmax(char **args, int cur_arg, struct tls_version_filter *methods, char **err)
8401{
8402 uint16_t i, v = 0;
8403 char *argv = args[cur_arg + 1];
8404 if (!*argv) {
8405 if (err)
8406 memprintf(err, "'%s' : missing the ssl/tls version", args[cur_arg]);
8407 return ERR_ALERT | ERR_FATAL;
8408 }
8409 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
8410 if (!strcmp(argv, methodVersions[i].name))
8411 v = i;
8412 if (!v) {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008413 if (err)
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008414 memprintf(err, "'%s' : unknown ssl/tls version", args[cur_arg + 1]);
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008415 return ERR_ALERT | ERR_FATAL;
8416 }
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008417 if (!strcmp("ssl-min-ver", args[cur_arg]))
8418 methods->min = v;
8419 else if (!strcmp("ssl-max-ver", args[cur_arg]))
8420 methods->max = v;
8421 else {
8422 if (err)
8423 memprintf(err, "'%s' : option not implemented", args[cur_arg]);
8424 return ERR_ALERT | ERR_FATAL;
8425 }
Emeric Brun2cb7ae52012-10-05 14:14:21 +02008426 return 0;
Emeric Brun2cb7ae52012-10-05 14:14:21 +02008427}
Emeric Brun2cb7ae52012-10-05 14:14:21 +02008428
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02008429static int ssl_bind_parse_tls_method_minmax(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
8430{
Willy Tarreau9a1ab082019-05-09 13:26:41 +02008431#if (HA_OPENSSL_VERSION_NUMBER < 0x10101000L) && !defined(OPENSSL_IS_BORINGSSL)
Christopher Faulet767a84b2017-11-24 16:50:31 +01008432 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 +02008433#endif
8434 return parse_tls_method_minmax(args, cur_arg, &conf->ssl_methods, err);
8435}
8436
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008437static int bind_parse_tls_method_minmax(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8438{
Emmanuel Hocdet43664762017-08-09 18:26:20 +02008439 return parse_tls_method_minmax(args, cur_arg, &conf->ssl_conf.ssl_methods, err);
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008440}
8441
8442static int srv_parse_tls_method_minmax(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8443{
8444 return parse_tls_method_minmax(args, *cur_arg, &newsrv->ssl_ctx.methods, err);
8445}
8446
Emeric Brun2d0c4822012-10-02 13:45:20 +02008447/* parse the "no-tls-tickets" bind keyword */
Emmanuel Hocdet4608ed92017-01-20 13:06:27 +01008448static 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 +02008449{
Emeric Brun89675492012-10-05 13:48:26 +02008450 conf->ssl_options |= BC_SSL_O_NO_TLS_TICKETS;
Emeric Brun81c00f02012-09-21 14:31:21 +02008451 return 0;
8452}
Emeric Brun2d0c4822012-10-02 13:45:20 +02008453
Olivier Houchardc2aae742017-09-22 18:26:28 +02008454/* parse the "allow-0rtt" bind keyword */
8455static int ssl_bind_parse_allow_0rtt(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
8456{
8457 conf->early_data = 1;
8458 return 0;
8459}
8460
8461static int bind_parse_allow_0rtt(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8462{
Olivier Houchard9679ac92017-10-27 14:58:08 +02008463 conf->ssl_conf.early_data = 1;
Olivier Houchardc2aae742017-09-22 18:26:28 +02008464 return 0;
8465}
8466
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02008467/* parse the "npn" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008468static 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 +02008469{
Bernard Spil13c53f82018-02-15 13:34:58 +01008470#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02008471 char *p1, *p2;
8472
8473 if (!*args[cur_arg + 1]) {
8474 memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[cur_arg]);
8475 return ERR_ALERT | ERR_FATAL;
8476 }
8477
8478 free(conf->npn_str);
8479
Willy Tarreau3724da12016-02-12 17:11:12 +01008480 /* the NPN string is built as a suite of (<len> <name>)*,
8481 * so we reuse each comma to store the next <len> and need
8482 * one more for the end of the string.
8483 */
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02008484 conf->npn_len = strlen(args[cur_arg + 1]) + 1;
Willy Tarreau3724da12016-02-12 17:11:12 +01008485 conf->npn_str = calloc(1, conf->npn_len + 1);
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02008486 memcpy(conf->npn_str + 1, args[cur_arg + 1], conf->npn_len);
8487
8488 /* replace commas with the name length */
8489 p1 = conf->npn_str;
8490 p2 = p1 + 1;
8491 while (1) {
8492 p2 = memchr(p1 + 1, ',', conf->npn_str + conf->npn_len - (p1 + 1));
8493 if (!p2)
8494 p2 = p1 + 1 + strlen(p1 + 1);
8495
8496 if (p2 - (p1 + 1) > 255) {
8497 *p2 = '\0';
8498 memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
8499 return ERR_ALERT | ERR_FATAL;
8500 }
8501
8502 *p1 = p2 - (p1 + 1);
8503 p1 = p2;
8504
8505 if (!*p2)
8506 break;
8507
8508 *(p2++) = '\0';
8509 }
8510 return 0;
8511#else
8512 if (err)
8513 memprintf(err, "'%s' : library does not support TLS NPN extension", args[cur_arg]);
8514 return ERR_ALERT | ERR_FATAL;
8515#endif
8516}
8517
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008518static int bind_parse_npn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8519{
8520 return ssl_bind_parse_npn(args, cur_arg, px, &conf->ssl_conf, err);
8521}
8522
Willy Tarreauab861d32013-04-02 02:30:41 +02008523/* parse the "alpn" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008524static 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 +02008525{
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01008526#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02008527 char *p1, *p2;
8528
8529 if (!*args[cur_arg + 1]) {
8530 memprintf(err, "'%s' : missing the comma-delimited ALPN protocol suite", args[cur_arg]);
8531 return ERR_ALERT | ERR_FATAL;
8532 }
8533
8534 free(conf->alpn_str);
8535
Marcoen Hirschbergbef60912016-02-12 17:05:24 +01008536 /* the ALPN string is built as a suite of (<len> <name>)*,
8537 * so we reuse each comma to store the next <len> and need
8538 * one more for the end of the string.
8539 */
Willy Tarreauab861d32013-04-02 02:30:41 +02008540 conf->alpn_len = strlen(args[cur_arg + 1]) + 1;
Marcoen Hirschbergbef60912016-02-12 17:05:24 +01008541 conf->alpn_str = calloc(1, conf->alpn_len + 1);
Willy Tarreauab861d32013-04-02 02:30:41 +02008542 memcpy(conf->alpn_str + 1, args[cur_arg + 1], conf->alpn_len);
8543
8544 /* replace commas with the name length */
8545 p1 = conf->alpn_str;
8546 p2 = p1 + 1;
8547 while (1) {
8548 p2 = memchr(p1 + 1, ',', conf->alpn_str + conf->alpn_len - (p1 + 1));
8549 if (!p2)
8550 p2 = p1 + 1 + strlen(p1 + 1);
8551
8552 if (p2 - (p1 + 1) > 255) {
8553 *p2 = '\0';
8554 memprintf(err, "'%s' : ALPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
8555 return ERR_ALERT | ERR_FATAL;
8556 }
8557
8558 *p1 = p2 - (p1 + 1);
8559 p1 = p2;
8560
8561 if (!*p2)
8562 break;
8563
8564 *(p2++) = '\0';
8565 }
8566 return 0;
8567#else
8568 if (err)
8569 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[cur_arg]);
8570 return ERR_ALERT | ERR_FATAL;
8571#endif
8572}
8573
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008574static int bind_parse_alpn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8575{
8576 return ssl_bind_parse_alpn(args, cur_arg, px, &conf->ssl_conf, err);
8577}
8578
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008579/* parse the "ssl" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02008580static 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 +02008581{
Willy Tarreau71a8c7c2016-12-21 22:04:54 +01008582 conf->xprt = &ssl_sock;
Willy Tarreau4348fad2012-09-20 16:48:07 +02008583 conf->is_ssl = 1;
Emeric Brun76d88952012-10-05 15:47:31 +02008584
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008585 if (global_ssl.listen_default_ciphers && !conf->ssl_conf.ciphers)
8586 conf->ssl_conf.ciphers = strdup(global_ssl.listen_default_ciphers);
Emmanuel Hocdet839af572019-05-14 16:27:35 +02008587#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02008588 if (global_ssl.listen_default_ciphersuites && !conf->ssl_conf.ciphersuites)
8589 conf->ssl_conf.ciphersuites = strdup(global_ssl.listen_default_ciphersuites);
8590#endif
Emmanuel Hocdet4608ed92017-01-20 13:06:27 +01008591 conf->ssl_options |= global_ssl.listen_default_ssloptions;
Emmanuel Hocdet43664762017-08-09 18:26:20 +02008592 conf->ssl_conf.ssl_methods.flags |= global_ssl.listen_default_sslmethods.flags;
8593 if (!conf->ssl_conf.ssl_methods.min)
8594 conf->ssl_conf.ssl_methods.min = global_ssl.listen_default_sslmethods.min;
8595 if (!conf->ssl_conf.ssl_methods.max)
8596 conf->ssl_conf.ssl_methods.max = global_ssl.listen_default_sslmethods.max;
Emeric Brun76d88952012-10-05 15:47:31 +02008597
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008598 return 0;
8599}
8600
Lukas Tribus53ae85c2017-05-04 15:45:40 +00008601/* parse the "prefer-client-ciphers" bind keyword */
8602static int bind_parse_pcc(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8603{
8604 conf->ssl_options |= BC_SSL_O_PREF_CLIE_CIPH;
8605 return 0;
8606}
8607
Christopher Faulet31af49d2015-06-09 17:29:50 +02008608/* parse the "generate-certificates" bind keyword */
8609static int bind_parse_generate_certs(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8610{
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01008611#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Christopher Faulet31af49d2015-06-09 17:29:50 +02008612 conf->generate_certs = 1;
8613#else
8614 memprintf(err, "%sthis version of openssl cannot generate SSL certificates.\n",
8615 err && *err ? *err : "");
8616#endif
8617 return 0;
8618}
8619
Emmanuel Hocdet65623372013-01-24 17:17:15 +01008620/* parse the "strict-sni" bind keyword */
8621static int bind_parse_strict_sni(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8622{
8623 conf->strict_sni = 1;
8624 return 0;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008625}
8626
8627/* parse the "tls-ticket-keys" bind keyword */
8628static int bind_parse_tls_ticket_keys(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8629{
8630#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
Christopher Faulete566f3d2019-10-21 09:55:49 +02008631 FILE *f = NULL;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008632 int i = 0;
8633 char thisline[LINESIZE];
Christopher Faulete566f3d2019-10-21 09:55:49 +02008634 struct tls_keys_ref *keys_ref = NULL;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008635
8636 if (!*args[cur_arg + 1]) {
8637 if (err)
8638 memprintf(err, "'%s' : missing TLS ticket keys file path", args[cur_arg]);
Christopher Faulete566f3d2019-10-21 09:55:49 +02008639 goto fail;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008640 }
8641
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02008642 keys_ref = tlskeys_ref_lookup(args[cur_arg + 1]);
Willy Tarreau17b4aa12018-07-17 10:05:32 +02008643 if (keys_ref) {
8644 keys_ref->refcount++;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02008645 conf->keys_ref = keys_ref;
8646 return 0;
8647 }
8648
Christopher Faulete566f3d2019-10-21 09:55:49 +02008649 keys_ref = calloc(1, sizeof(*keys_ref));
Emeric Brun09852f72019-01-10 10:51:13 +01008650 if (!keys_ref) {
8651 if (err)
8652 memprintf(err, "'%s' : allocation error", args[cur_arg+1]);
Christopher Faulete566f3d2019-10-21 09:55:49 +02008653 goto fail;
Emeric Brun09852f72019-01-10 10:51:13 +01008654 }
8655
Emeric Brun9e754772019-01-10 17:51:55 +01008656 keys_ref->tlskeys = malloc(TLS_TICKETS_NO * sizeof(union tls_sess_key));
Emeric Brun09852f72019-01-10 10:51:13 +01008657 if (!keys_ref->tlskeys) {
Emeric Brun09852f72019-01-10 10:51:13 +01008658 if (err)
8659 memprintf(err, "'%s' : allocation error", args[cur_arg+1]);
Christopher Faulete566f3d2019-10-21 09:55:49 +02008660 goto fail;
Emeric Brun09852f72019-01-10 10:51:13 +01008661 }
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008662
8663 if ((f = fopen(args[cur_arg + 1], "r")) == NULL) {
8664 if (err)
8665 memprintf(err, "'%s' : unable to load ssl tickets keys file", args[cur_arg+1]);
Christopher Faulete566f3d2019-10-21 09:55:49 +02008666 goto fail;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008667 }
8668
Nenad Merdanovic146defa2015-05-09 08:46:00 +02008669 keys_ref->filename = strdup(args[cur_arg + 1]);
Emeric Brun09852f72019-01-10 10:51:13 +01008670 if (!keys_ref->filename) {
Emeric Brun09852f72019-01-10 10:51:13 +01008671 if (err)
8672 memprintf(err, "'%s' : allocation error", args[cur_arg+1]);
Christopher Faulete566f3d2019-10-21 09:55:49 +02008673 goto fail;
Emeric Brun09852f72019-01-10 10:51:13 +01008674 }
Nenad Merdanovic146defa2015-05-09 08:46:00 +02008675
Emeric Brun9e754772019-01-10 17:51:55 +01008676 keys_ref->key_size_bits = 0;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008677 while (fgets(thisline, sizeof(thisline), f) != NULL) {
8678 int len = strlen(thisline);
Emeric Brun9e754772019-01-10 17:51:55 +01008679 int dec_size;
8680
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008681 /* Strip newline characters from the end */
8682 if(thisline[len - 1] == '\n')
8683 thisline[--len] = 0;
8684
8685 if(thisline[len - 1] == '\r')
8686 thisline[--len] = 0;
8687
Emeric Brun9e754772019-01-10 17:51:55 +01008688 dec_size = base64dec(thisline, len, (char *) (keys_ref->tlskeys + i % TLS_TICKETS_NO), sizeof(union tls_sess_key));
8689 if (dec_size < 0) {
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008690 if (err)
8691 memprintf(err, "'%s' : unable to decode base64 key on line %d", args[cur_arg+1], i + 1);
Christopher Faulete566f3d2019-10-21 09:55:49 +02008692 goto fail;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008693 }
Emeric Brun9e754772019-01-10 17:51:55 +01008694 else if (!keys_ref->key_size_bits && (dec_size == sizeof(struct tls_sess_key_128))) {
8695 keys_ref->key_size_bits = 128;
8696 }
8697 else if (!keys_ref->key_size_bits && (dec_size == sizeof(struct tls_sess_key_256))) {
8698 keys_ref->key_size_bits = 256;
8699 }
8700 else if (((dec_size != sizeof(struct tls_sess_key_128)) && (dec_size != sizeof(struct tls_sess_key_256)))
8701 || ((dec_size == sizeof(struct tls_sess_key_128) && (keys_ref->key_size_bits != 128)))
8702 || ((dec_size == sizeof(struct tls_sess_key_256) && (keys_ref->key_size_bits != 256)))) {
Emeric Brun9e754772019-01-10 17:51:55 +01008703 if (err)
8704 memprintf(err, "'%s' : wrong sized key on line %d", args[cur_arg+1], i + 1);
Christopher Faulete566f3d2019-10-21 09:55:49 +02008705 goto fail;
Emeric Brun9e754772019-01-10 17:51:55 +01008706 }
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008707 i++;
8708 }
8709
8710 if (i < TLS_TICKETS_NO) {
8711 if (err)
8712 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 +02008713 goto fail;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008714 }
8715
8716 fclose(f);
8717
8718 /* Use penultimate key for encryption, handle when TLS_TICKETS_NO = 1 */
Nenad Merdanovic17891152016-03-25 22:16:57 +01008719 i -= 2;
8720 keys_ref->tls_ticket_enc_index = i < 0 ? 0 : i % TLS_TICKETS_NO;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02008721 keys_ref->unique_id = -1;
Willy Tarreau17b4aa12018-07-17 10:05:32 +02008722 keys_ref->refcount = 1;
Christopher Faulet16f45c82018-02-16 11:23:49 +01008723 HA_RWLOCK_INIT(&keys_ref->lock);
Nenad Merdanovic146defa2015-05-09 08:46:00 +02008724 conf->keys_ref = keys_ref;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008725
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02008726 LIST_ADD(&tlskeys_reference, &keys_ref->list);
8727
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008728 return 0;
Christopher Faulete566f3d2019-10-21 09:55:49 +02008729
8730 fail:
8731 if (f)
8732 fclose(f);
8733 if (keys_ref) {
8734 free(keys_ref->filename);
8735 free(keys_ref->tlskeys);
8736 free(keys_ref);
8737 }
8738 return ERR_ALERT | ERR_FATAL;
8739
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008740#else
8741 if (err)
8742 memprintf(err, "'%s' : TLS ticket callback extension not supported", args[cur_arg]);
8743 return ERR_ALERT | ERR_FATAL;
8744#endif /* SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB */
Emmanuel Hocdet65623372013-01-24 17:17:15 +01008745}
8746
Emeric Brund94b3fe2012-09-20 18:23:56 +02008747/* parse the "verify" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008748static 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 +02008749{
8750 if (!*args[cur_arg + 1]) {
8751 if (err)
8752 memprintf(err, "'%s' : missing verify method", args[cur_arg]);
8753 return ERR_ALERT | ERR_FATAL;
8754 }
8755
8756 if (strcmp(args[cur_arg + 1], "none") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01008757 conf->verify = SSL_SOCK_VERIFY_NONE;
Emeric Brund94b3fe2012-09-20 18:23:56 +02008758 else if (strcmp(args[cur_arg + 1], "optional") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01008759 conf->verify = SSL_SOCK_VERIFY_OPTIONAL;
Emeric Brund94b3fe2012-09-20 18:23:56 +02008760 else if (strcmp(args[cur_arg + 1], "required") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01008761 conf->verify = SSL_SOCK_VERIFY_REQUIRED;
Emeric Brund94b3fe2012-09-20 18:23:56 +02008762 else {
8763 if (err)
8764 memprintf(err, "'%s' : unknown verify method '%s', only 'none', 'optional', and 'required' are supported\n",
8765 args[cur_arg], args[cur_arg + 1]);
8766 return ERR_ALERT | ERR_FATAL;
8767 }
8768
8769 return 0;
8770}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008771static int bind_parse_verify(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8772{
8773 return ssl_bind_parse_verify(args, cur_arg, px, &conf->ssl_conf, err);
8774}
Emeric Brund94b3fe2012-09-20 18:23:56 +02008775
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02008776/* parse the "no-ca-names" bind keyword */
8777static int ssl_bind_parse_no_ca_names(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
8778{
8779 conf->no_ca_names = 1;
8780 return 0;
8781}
8782static int bind_parse_no_ca_names(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8783{
8784 return ssl_bind_parse_no_ca_names(args, cur_arg, px, &conf->ssl_conf, err);
8785}
8786
Willy Tarreau92faadf2012-10-10 23:04:25 +02008787/************** "server" keywords ****************/
8788
Olivier Houchardc7566002018-11-20 23:33:50 +01008789/* parse the "npn" bind keyword */
8790static int srv_parse_npn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8791{
8792#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
8793 char *p1, *p2;
8794
8795 if (!*args[*cur_arg + 1]) {
8796 memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[*cur_arg]);
8797 return ERR_ALERT | ERR_FATAL;
8798 }
8799
8800 free(newsrv->ssl_ctx.npn_str);
8801
8802 /* the NPN string is built as a suite of (<len> <name>)*,
8803 * so we reuse each comma to store the next <len> and need
8804 * one more for the end of the string.
8805 */
8806 newsrv->ssl_ctx.npn_len = strlen(args[*cur_arg + 1]) + 1;
8807 newsrv->ssl_ctx.npn_str = calloc(1, newsrv->ssl_ctx.npn_len + 1);
8808 memcpy(newsrv->ssl_ctx.npn_str + 1, args[*cur_arg + 1],
8809 newsrv->ssl_ctx.npn_len);
8810
8811 /* replace commas with the name length */
8812 p1 = newsrv->ssl_ctx.npn_str;
8813 p2 = p1 + 1;
8814 while (1) {
8815 p2 = memchr(p1 + 1, ',', newsrv->ssl_ctx.npn_str +
8816 newsrv->ssl_ctx.npn_len - (p1 + 1));
8817 if (!p2)
8818 p2 = p1 + 1 + strlen(p1 + 1);
8819
8820 if (p2 - (p1 + 1) > 255) {
8821 *p2 = '\0';
8822 memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[*cur_arg], p1 + 1);
8823 return ERR_ALERT | ERR_FATAL;
8824 }
8825
8826 *p1 = p2 - (p1 + 1);
8827 p1 = p2;
8828
8829 if (!*p2)
8830 break;
8831
8832 *(p2++) = '\0';
8833 }
8834 return 0;
8835#else
8836 if (err)
8837 memprintf(err, "'%s' : library does not support TLS NPN extension", args[*cur_arg]);
8838 return ERR_ALERT | ERR_FATAL;
8839#endif
8840}
8841
Olivier Houchard92150142018-12-21 19:47:01 +01008842/* parse the "alpn" or the "check-alpn" server keyword */
Olivier Houchardc7566002018-11-20 23:33:50 +01008843static int srv_parse_alpn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8844{
8845#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
8846 char *p1, *p2;
Olivier Houchard92150142018-12-21 19:47:01 +01008847 char **alpn_str;
8848 int *alpn_len;
Olivier Houchardc7566002018-11-20 23:33:50 +01008849
Olivier Houchard92150142018-12-21 19:47:01 +01008850 if (*args[*cur_arg] == 'c') {
8851 alpn_str = &newsrv->check.alpn_str;
8852 alpn_len = &newsrv->check.alpn_len;
8853 } else {
8854 alpn_str = &newsrv->ssl_ctx.alpn_str;
8855 alpn_len = &newsrv->ssl_ctx.alpn_len;
8856
8857 }
Olivier Houchardc7566002018-11-20 23:33:50 +01008858 if (!*args[*cur_arg + 1]) {
8859 memprintf(err, "'%s' : missing the comma-delimited ALPN protocol suite", args[*cur_arg]);
8860 return ERR_ALERT | ERR_FATAL;
8861 }
8862
Olivier Houchard92150142018-12-21 19:47:01 +01008863 free(*alpn_str);
Olivier Houchardc7566002018-11-20 23:33:50 +01008864
8865 /* the ALPN string is built as a suite of (<len> <name>)*,
8866 * so we reuse each comma to store the next <len> and need
8867 * one more for the end of the string.
8868 */
Olivier Houchard92150142018-12-21 19:47:01 +01008869 *alpn_len = strlen(args[*cur_arg + 1]) + 1;
8870 *alpn_str = calloc(1, *alpn_len + 1);
8871 memcpy(*alpn_str + 1, args[*cur_arg + 1], *alpn_len);
Olivier Houchardc7566002018-11-20 23:33:50 +01008872
8873 /* replace commas with the name length */
Olivier Houchard92150142018-12-21 19:47:01 +01008874 p1 = *alpn_str;
Olivier Houchardc7566002018-11-20 23:33:50 +01008875 p2 = p1 + 1;
8876 while (1) {
Olivier Houchard92150142018-12-21 19:47:01 +01008877 p2 = memchr(p1 + 1, ',', *alpn_str + *alpn_len - (p1 + 1));
Olivier Houchardc7566002018-11-20 23:33:50 +01008878 if (!p2)
8879 p2 = p1 + 1 + strlen(p1 + 1);
8880
8881 if (p2 - (p1 + 1) > 255) {
8882 *p2 = '\0';
8883 memprintf(err, "'%s' : ALPN protocol name too long : '%s'", args[*cur_arg], p1 + 1);
8884 return ERR_ALERT | ERR_FATAL;
8885 }
8886
8887 *p1 = p2 - (p1 + 1);
8888 p1 = p2;
8889
8890 if (!*p2)
8891 break;
8892
8893 *(p2++) = '\0';
8894 }
8895 return 0;
8896#else
8897 if (err)
8898 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[*cur_arg]);
8899 return ERR_ALERT | ERR_FATAL;
8900#endif
8901}
8902
Emeric Brunef42d922012-10-11 16:11:36 +02008903/* parse the "ca-file" server keyword */
8904static int srv_parse_ca_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8905{
8906 if (!*args[*cur_arg + 1]) {
8907 if (err)
8908 memprintf(err, "'%s' : missing CAfile path", args[*cur_arg]);
8909 return ERR_ALERT | ERR_FATAL;
8910 }
8911
Willy Tarreauef934602016-12-22 23:12:01 +01008912 if ((*args[*cur_arg + 1] != '/') && global_ssl.ca_base)
8913 memprintf(&newsrv->ssl_ctx.ca_file, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02008914 else
8915 memprintf(&newsrv->ssl_ctx.ca_file, "%s", args[*cur_arg + 1]);
8916
8917 return 0;
8918}
8919
Olivier Houchard9130a962017-10-17 17:33:43 +02008920/* parse the "check-sni" server keyword */
8921static int srv_parse_check_sni(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8922{
8923 if (!*args[*cur_arg + 1]) {
8924 if (err)
8925 memprintf(err, "'%s' : missing SNI", args[*cur_arg]);
8926 return ERR_ALERT | ERR_FATAL;
8927 }
8928
8929 newsrv->check.sni = strdup(args[*cur_arg + 1]);
8930 if (!newsrv->check.sni) {
8931 memprintf(err, "'%s' : failed to allocate memory", args[*cur_arg]);
8932 return ERR_ALERT | ERR_FATAL;
8933 }
8934 return 0;
8935
8936}
8937
Willy Tarreau92faadf2012-10-10 23:04:25 +02008938/* parse the "check-ssl" server keyword */
8939static int srv_parse_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8940{
8941 newsrv->check.use_ssl = 1;
Willy Tarreauef934602016-12-22 23:12:01 +01008942 if (global_ssl.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
8943 newsrv->ssl_ctx.ciphers = strdup(global_ssl.connect_default_ciphers);
Emmanuel Hocdet839af572019-05-14 16:27:35 +02008944#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02008945 if (global_ssl.connect_default_ciphersuites && !newsrv->ssl_ctx.ciphersuites)
8946 newsrv->ssl_ctx.ciphersuites = strdup(global_ssl.connect_default_ciphersuites);
8947#endif
Willy Tarreauef934602016-12-22 23:12:01 +01008948 newsrv->ssl_ctx.options |= global_ssl.connect_default_ssloptions;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008949 newsrv->ssl_ctx.methods.flags |= global_ssl.connect_default_sslmethods.flags;
8950 if (!newsrv->ssl_ctx.methods.min)
8951 newsrv->ssl_ctx.methods.min = global_ssl.connect_default_sslmethods.min;
8952 if (!newsrv->ssl_ctx.methods.max)
8953 newsrv->ssl_ctx.methods.max = global_ssl.connect_default_sslmethods.max;
8954
Willy Tarreau92faadf2012-10-10 23:04:25 +02008955 return 0;
8956}
8957
8958/* parse the "ciphers" server keyword */
8959static int srv_parse_ciphers(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8960{
8961 if (!*args[*cur_arg + 1]) {
8962 memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
8963 return ERR_ALERT | ERR_FATAL;
8964 }
8965
8966 free(newsrv->ssl_ctx.ciphers);
8967 newsrv->ssl_ctx.ciphers = strdup(args[*cur_arg + 1]);
8968 return 0;
8969}
Dirkjan Bussink415150f2018-09-14 11:14:21 +02008970
Emmanuel Hocdet839af572019-05-14 16:27:35 +02008971#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02008972/* parse the "ciphersuites" server keyword */
8973static int srv_parse_ciphersuites(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8974{
8975 if (!*args[*cur_arg + 1]) {
8976 memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
8977 return ERR_ALERT | ERR_FATAL;
8978 }
8979
8980 free(newsrv->ssl_ctx.ciphersuites);
8981 newsrv->ssl_ctx.ciphersuites = strdup(args[*cur_arg + 1]);
8982 return 0;
8983}
8984#endif
Willy Tarreau92faadf2012-10-10 23:04:25 +02008985
Emeric Brunef42d922012-10-11 16:11:36 +02008986/* parse the "crl-file" server keyword */
8987static int srv_parse_crl_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8988{
8989#ifndef X509_V_FLAG_CRL_CHECK
8990 if (err)
8991 memprintf(err, "'%s' : library does not support CRL verify", args[*cur_arg]);
8992 return ERR_ALERT | ERR_FATAL;
8993#else
8994 if (!*args[*cur_arg + 1]) {
8995 if (err)
8996 memprintf(err, "'%s' : missing CRLfile path", args[*cur_arg]);
8997 return ERR_ALERT | ERR_FATAL;
8998 }
8999
Willy Tarreauef934602016-12-22 23:12:01 +01009000 if ((*args[*cur_arg + 1] != '/') && global_ssl.ca_base)
9001 memprintf(&newsrv->ssl_ctx.crl_file, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02009002 else
9003 memprintf(&newsrv->ssl_ctx.crl_file, "%s", args[*cur_arg + 1]);
9004
9005 return 0;
9006#endif
9007}
9008
Emeric Bruna7aa3092012-10-26 12:58:00 +02009009/* parse the "crt" server keyword */
9010static int srv_parse_crt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9011{
9012 if (!*args[*cur_arg + 1]) {
9013 if (err)
9014 memprintf(err, "'%s' : missing certificate file path", args[*cur_arg]);
9015 return ERR_ALERT | ERR_FATAL;
9016 }
9017
Willy Tarreauef934602016-12-22 23:12:01 +01009018 if ((*args[*cur_arg + 1] != '/') && global_ssl.crt_base)
Christopher Fauletff3a41e2017-11-23 09:13:32 +01009019 memprintf(&newsrv->ssl_ctx.client_crt, "%s/%s", global_ssl.crt_base, args[*cur_arg + 1]);
Emeric Bruna7aa3092012-10-26 12:58:00 +02009020 else
9021 memprintf(&newsrv->ssl_ctx.client_crt, "%s", args[*cur_arg + 1]);
9022
9023 return 0;
9024}
Emeric Brunef42d922012-10-11 16:11:36 +02009025
Frédéric Lécaille340ae602017-03-13 10:38:04 +01009026/* parse the "no-check-ssl" server keyword */
9027static int srv_parse_no_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9028{
9029 newsrv->check.use_ssl = 0;
9030 free(newsrv->ssl_ctx.ciphers);
9031 newsrv->ssl_ctx.ciphers = NULL;
9032 newsrv->ssl_ctx.options &= ~global_ssl.connect_default_ssloptions;
9033 return 0;
9034}
9035
Frédéric Lécaillee892c4c2017-03-13 12:08:01 +01009036/* parse the "no-send-proxy-v2-ssl" server keyword */
9037static int srv_parse_no_send_proxy_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9038{
9039 newsrv->pp_opts &= ~SRV_PP_V2;
9040 newsrv->pp_opts &= ~SRV_PP_V2_SSL;
9041 return 0;
9042}
9043
9044/* parse the "no-send-proxy-v2-ssl-cn" server keyword */
9045static int srv_parse_no_send_proxy_cn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9046{
9047 newsrv->pp_opts &= ~SRV_PP_V2;
9048 newsrv->pp_opts &= ~SRV_PP_V2_SSL;
9049 newsrv->pp_opts &= ~SRV_PP_V2_SSL_CN;
9050 return 0;
9051}
9052
Frédéric Lécaillee381d762017-03-13 11:54:17 +01009053/* parse the "no-ssl" server keyword */
9054static int srv_parse_no_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9055{
9056 newsrv->use_ssl = 0;
9057 free(newsrv->ssl_ctx.ciphers);
9058 newsrv->ssl_ctx.ciphers = NULL;
9059 return 0;
9060}
9061
Olivier Houchard522eea72017-11-03 16:27:47 +01009062/* parse the "allow-0rtt" server keyword */
9063static int srv_parse_allow_0rtt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9064{
9065 newsrv->ssl_ctx.options |= SRV_SSL_O_EARLY_DATA;
9066 return 0;
9067}
9068
Willy Tarreau2a3fb1c2015-02-05 16:47:07 +01009069/* parse the "no-ssl-reuse" server keyword */
9070static int srv_parse_no_ssl_reuse(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9071{
9072 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_REUSE;
9073 return 0;
9074}
9075
Emeric Brunf9c5c472012-10-11 15:28:34 +02009076/* parse the "no-tls-tickets" server keyword */
9077static int srv_parse_no_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9078{
9079 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLS_TICKETS;
9080 return 0;
9081}
David Safb76832014-05-08 23:42:08 -04009082/* parse the "send-proxy-v2-ssl" server keyword */
9083static int srv_parse_send_proxy_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9084{
9085 newsrv->pp_opts |= SRV_PP_V2;
9086 newsrv->pp_opts |= SRV_PP_V2_SSL;
9087 return 0;
9088}
9089
9090/* parse the "send-proxy-v2-ssl-cn" server keyword */
9091static int srv_parse_send_proxy_cn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9092{
9093 newsrv->pp_opts |= SRV_PP_V2;
9094 newsrv->pp_opts |= SRV_PP_V2_SSL;
9095 newsrv->pp_opts |= SRV_PP_V2_SSL_CN;
9096 return 0;
9097}
Emeric Brunf9c5c472012-10-11 15:28:34 +02009098
Willy Tarreau732eac42015-07-09 11:40:25 +02009099/* parse the "sni" server keyword */
9100static int srv_parse_sni(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9101{
9102#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
9103 memprintf(err, "'%s' : the current SSL library doesn't support the SNI TLS extension", args[*cur_arg]);
9104 return ERR_ALERT | ERR_FATAL;
9105#else
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01009106 char *arg;
Willy Tarreau732eac42015-07-09 11:40:25 +02009107
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01009108 arg = args[*cur_arg + 1];
9109 if (!*arg) {
Willy Tarreau732eac42015-07-09 11:40:25 +02009110 memprintf(err, "'%s' : missing sni expression", args[*cur_arg]);
9111 return ERR_ALERT | ERR_FATAL;
9112 }
9113
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01009114 free(newsrv->sni_expr);
9115 newsrv->sni_expr = strdup(arg);
Willy Tarreau732eac42015-07-09 11:40:25 +02009116
Willy Tarreau732eac42015-07-09 11:40:25 +02009117 return 0;
9118#endif
9119}
9120
Willy Tarreau92faadf2012-10-10 23:04:25 +02009121/* parse the "ssl" server keyword */
9122static int srv_parse_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9123{
9124 newsrv->use_ssl = 1;
Willy Tarreauef934602016-12-22 23:12:01 +01009125 if (global_ssl.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
9126 newsrv->ssl_ctx.ciphers = strdup(global_ssl.connect_default_ciphers);
Emmanuel Hocdet839af572019-05-14 16:27:35 +02009127#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009128 if (global_ssl.connect_default_ciphersuites && !newsrv->ssl_ctx.ciphersuites)
9129 newsrv->ssl_ctx.ciphersuites = strdup(global_ssl.connect_default_ciphersuites);
9130#endif
Willy Tarreau92faadf2012-10-10 23:04:25 +02009131 return 0;
9132}
9133
Frédéric Lécaille2cfcdbe2017-03-13 11:32:20 +01009134/* parse the "ssl-reuse" server keyword */
9135static int srv_parse_ssl_reuse(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9136{
9137 newsrv->ssl_ctx.options &= ~SRV_SSL_O_NO_REUSE;
9138 return 0;
9139}
9140
Frédéric Lécaille2cfcdbe2017-03-13 11:32:20 +01009141/* parse the "tls-tickets" server keyword */
9142static int srv_parse_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9143{
9144 newsrv->ssl_ctx.options &= ~SRV_SSL_O_NO_TLS_TICKETS;
9145 return 0;
9146}
9147
Emeric Brunef42d922012-10-11 16:11:36 +02009148/* parse the "verify" server keyword */
9149static int srv_parse_verify(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9150{
9151 if (!*args[*cur_arg + 1]) {
9152 if (err)
9153 memprintf(err, "'%s' : missing verify method", args[*cur_arg]);
9154 return ERR_ALERT | ERR_FATAL;
9155 }
9156
9157 if (strcmp(args[*cur_arg + 1], "none") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01009158 newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_NONE;
Emeric Brunef42d922012-10-11 16:11:36 +02009159 else if (strcmp(args[*cur_arg + 1], "required") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01009160 newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_REQUIRED;
Emeric Brunef42d922012-10-11 16:11:36 +02009161 else {
9162 if (err)
9163 memprintf(err, "'%s' : unknown verify method '%s', only 'none' and 'required' are supported\n",
9164 args[*cur_arg], args[*cur_arg + 1]);
9165 return ERR_ALERT | ERR_FATAL;
9166 }
9167
Evan Broderbe554312013-06-27 00:05:25 -07009168 return 0;
9169}
9170
9171/* parse the "verifyhost" server keyword */
9172static int srv_parse_verifyhost(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9173{
9174 if (!*args[*cur_arg + 1]) {
9175 if (err)
9176 memprintf(err, "'%s' : missing hostname to verify against", args[*cur_arg]);
9177 return ERR_ALERT | ERR_FATAL;
9178 }
9179
Frédéric Lécaille273f3212017-03-13 15:52:01 +01009180 free(newsrv->ssl_ctx.verify_host);
Evan Broderbe554312013-06-27 00:05:25 -07009181 newsrv->ssl_ctx.verify_host = strdup(args[*cur_arg + 1]);
9182
Emeric Brunef42d922012-10-11 16:11:36 +02009183 return 0;
9184}
9185
Emeric Brun2c86cbf2014-10-30 15:56:50 +01009186/* parse the "ssl-default-bind-options" keyword in global section */
9187static int ssl_parse_default_bind_options(char **args, int section_type, struct proxy *curpx,
9188 struct proxy *defpx, const char *file, int line,
9189 char **err) {
9190 int i = 1;
9191
9192 if (*(args[i]) == 0) {
9193 memprintf(err, "global statement '%s' expects an option as an argument.", args[0]);
9194 return -1;
9195 }
9196 while (*(args[i])) {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02009197 if (!strcmp(args[i], "no-tls-tickets"))
Willy Tarreauef934602016-12-22 23:12:01 +01009198 global_ssl.listen_default_ssloptions |= BC_SSL_O_NO_TLS_TICKETS;
Lukas Tribus53ae85c2017-05-04 15:45:40 +00009199 else if (!strcmp(args[i], "prefer-client-ciphers"))
9200 global_ssl.listen_default_ssloptions |= BC_SSL_O_PREF_CLIE_CIPH;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02009201 else if (!strcmp(args[i], "ssl-min-ver") || !strcmp(args[i], "ssl-max-ver")) {
9202 if (!parse_tls_method_minmax(args, i, &global_ssl.listen_default_sslmethods, err))
9203 i++;
9204 else {
9205 memprintf(err, "%s on global statement '%s'.", *err, args[0]);
9206 return -1;
9207 }
9208 }
9209 else if (parse_tls_method_options(args[i], &global_ssl.listen_default_sslmethods, err)) {
Emeric Brun2c86cbf2014-10-30 15:56:50 +01009210 memprintf(err, "unknown option '%s' on global statement '%s'.", args[i], args[0]);
9211 return -1;
9212 }
9213 i++;
9214 }
9215 return 0;
9216}
9217
9218/* parse the "ssl-default-server-options" keyword in global section */
9219static int ssl_parse_default_server_options(char **args, int section_type, struct proxy *curpx,
9220 struct proxy *defpx, const char *file, int line,
9221 char **err) {
9222 int i = 1;
9223
9224 if (*(args[i]) == 0) {
9225 memprintf(err, "global statement '%s' expects an option as an argument.", args[0]);
9226 return -1;
9227 }
9228 while (*(args[i])) {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02009229 if (!strcmp(args[i], "no-tls-tickets"))
Willy Tarreauef934602016-12-22 23:12:01 +01009230 global_ssl.connect_default_ssloptions |= SRV_SSL_O_NO_TLS_TICKETS;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02009231 else if (!strcmp(args[i], "ssl-min-ver") || !strcmp(args[i], "ssl-max-ver")) {
9232 if (!parse_tls_method_minmax(args, i, &global_ssl.connect_default_sslmethods, err))
9233 i++;
9234 else {
9235 memprintf(err, "%s on global statement '%s'.", *err, args[0]);
9236 return -1;
9237 }
9238 }
9239 else if (parse_tls_method_options(args[i], &global_ssl.connect_default_sslmethods, err)) {
Emeric Brun2c86cbf2014-10-30 15:56:50 +01009240 memprintf(err, "unknown option '%s' on global statement '%s'.", args[i], args[0]);
9241 return -1;
9242 }
9243 i++;
9244 }
9245 return 0;
9246}
9247
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01009248/* parse the "ca-base" / "crt-base" keywords in global section.
9249 * Returns <0 on alert, >0 on warning, 0 on success.
9250 */
9251static int ssl_parse_global_ca_crt_base(char **args, int section_type, struct proxy *curpx,
9252 struct proxy *defpx, const char *file, int line,
9253 char **err)
9254{
9255 char **target;
9256
Willy Tarreauef934602016-12-22 23:12:01 +01009257 target = (args[0][1] == 'a') ? &global_ssl.ca_base : &global_ssl.crt_base;
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01009258
9259 if (too_many_args(1, args, err, NULL))
9260 return -1;
9261
9262 if (*target) {
9263 memprintf(err, "'%s' already specified.", args[0]);
9264 return -1;
9265 }
9266
9267 if (*(args[1]) == 0) {
9268 memprintf(err, "global statement '%s' expects a directory path as an argument.", args[0]);
9269 return -1;
9270 }
9271 *target = strdup(args[1]);
9272 return 0;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00009273}
9274
9275/* parse the "ssl-mode-async" keyword in global section.
9276 * Returns <0 on alert, >0 on warning, 0 on success.
9277 */
9278static int ssl_parse_global_ssl_async(char **args, int section_type, struct proxy *curpx,
9279 struct proxy *defpx, const char *file, int line,
9280 char **err)
9281{
Willy Tarreau5db847a2019-05-09 14:13:35 +02009282#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00009283 global_ssl.async = 1;
Emeric Brunece0c332017-12-06 13:51:49 +01009284 global.ssl_used_async_engines = nb_engines;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00009285 return 0;
9286#else
9287 memprintf(err, "'%s': openssl library does not support async mode", args[0]);
9288 return -1;
9289#endif
9290}
9291
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02009292#ifndef OPENSSL_NO_ENGINE
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00009293static int ssl_check_async_engine_count(void) {
9294 int err_code = 0;
9295
Emeric Brun3854e012017-05-17 20:42:48 +02009296 if (global_ssl.async && (openssl_engines_initialized > 32)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01009297 ha_alert("ssl-mode-async only supports a maximum of 32 engines.\n");
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00009298 err_code = ERR_ABORT;
9299 }
9300 return err_code;
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01009301}
9302
Grant Zhang872f9c22017-01-21 01:10:18 +00009303/* parse the "ssl-engine" keyword in global section.
9304 * Returns <0 on alert, >0 on warning, 0 on success.
9305 */
9306static int ssl_parse_global_ssl_engine(char **args, int section_type, struct proxy *curpx,
9307 struct proxy *defpx, const char *file, int line,
9308 char **err)
9309{
9310 char *algo;
9311 int ret = -1;
9312
9313 if (*(args[1]) == 0) {
9314 memprintf(err, "global statement '%s' expects a valid engine name as an argument.", args[0]);
9315 return ret;
9316 }
9317
9318 if (*(args[2]) == 0) {
9319 /* if no list of algorithms is given, it defaults to ALL */
9320 algo = strdup("ALL");
9321 goto add_engine;
9322 }
9323
9324 /* otherwise the expected format is ssl-engine <engine_name> algo <list of algo> */
9325 if (strcmp(args[2], "algo") != 0) {
9326 memprintf(err, "global statement '%s' expects to have algo keyword.", args[0]);
9327 return ret;
9328 }
9329
9330 if (*(args[3]) == 0) {
9331 memprintf(err, "global statement '%s' expects algorithm names as an argument.", args[0]);
9332 return ret;
9333 }
9334 algo = strdup(args[3]);
9335
9336add_engine:
9337 if (ssl_init_single_engine(args[1], algo)==0) {
9338 openssl_engines_initialized++;
9339 ret = 0;
9340 }
9341 free(algo);
9342 return ret;
9343}
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02009344#endif
Grant Zhang872f9c22017-01-21 01:10:18 +00009345
Willy Tarreauf22e9682016-12-21 23:23:19 +01009346/* parse the "ssl-default-bind-ciphers" / "ssl-default-server-ciphers" keywords
9347 * in global section. Returns <0 on alert, >0 on warning, 0 on success.
9348 */
9349static int ssl_parse_global_ciphers(char **args, int section_type, struct proxy *curpx,
9350 struct proxy *defpx, const char *file, int line,
9351 char **err)
9352{
9353 char **target;
9354
Willy Tarreauef934602016-12-22 23:12:01 +01009355 target = (args[0][12] == 'b') ? &global_ssl.listen_default_ciphers : &global_ssl.connect_default_ciphers;
Willy Tarreauf22e9682016-12-21 23:23:19 +01009356
9357 if (too_many_args(1, args, err, NULL))
9358 return -1;
9359
9360 if (*(args[1]) == 0) {
9361 memprintf(err, "global statement '%s' expects a cipher suite as an argument.", args[0]);
9362 return -1;
9363 }
9364
9365 free(*target);
9366 *target = strdup(args[1]);
9367 return 0;
9368}
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009369
Emmanuel Hocdet839af572019-05-14 16:27:35 +02009370#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009371/* parse the "ssl-default-bind-ciphersuites" / "ssl-default-server-ciphersuites" keywords
9372 * in global section. Returns <0 on alert, >0 on warning, 0 on success.
9373 */
9374static int ssl_parse_global_ciphersuites(char **args, int section_type, struct proxy *curpx,
9375 struct proxy *defpx, const char *file, int line,
9376 char **err)
9377{
9378 char **target;
9379
9380 target = (args[0][12] == 'b') ? &global_ssl.listen_default_ciphersuites : &global_ssl.connect_default_ciphersuites;
9381
9382 if (too_many_args(1, args, err, NULL))
9383 return -1;
9384
9385 if (*(args[1]) == 0) {
9386 memprintf(err, "global statement '%s' expects a cipher suite as an argument.", args[0]);
9387 return -1;
9388 }
9389
9390 free(*target);
9391 *target = strdup(args[1]);
9392 return 0;
9393}
9394#endif
Willy Tarreauf22e9682016-12-21 23:23:19 +01009395
Willy Tarreau9ceda382016-12-21 23:13:03 +01009396/* parse various global tune.ssl settings consisting in positive integers.
9397 * Returns <0 on alert, >0 on warning, 0 on success.
9398 */
9399static int ssl_parse_global_int(char **args, int section_type, struct proxy *curpx,
9400 struct proxy *defpx, const char *file, int line,
9401 char **err)
9402{
9403 int *target;
9404
9405 if (strcmp(args[0], "tune.ssl.cachesize") == 0)
9406 target = &global.tune.sslcachesize;
9407 else if (strcmp(args[0], "tune.ssl.maxrecord") == 0)
Willy Tarreauef934602016-12-22 23:12:01 +01009408 target = (int *)&global_ssl.max_record;
Willy Tarreau9ceda382016-12-21 23:13:03 +01009409 else if (strcmp(args[0], "tune.ssl.ssl-ctx-cache-size") == 0)
Willy Tarreauef934602016-12-22 23:12:01 +01009410 target = &global_ssl.ctx_cache;
Willy Tarreau0bea58d2016-12-21 23:17:25 +01009411 else if (strcmp(args[0], "maxsslconn") == 0)
9412 target = &global.maxsslconn;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01009413 else if (strcmp(args[0], "tune.ssl.capture-cipherlist-size") == 0)
9414 target = &global_ssl.capture_cipherlist;
Willy Tarreau9ceda382016-12-21 23:13:03 +01009415 else {
9416 memprintf(err, "'%s' keyword not unhandled (please report this bug).", args[0]);
9417 return -1;
9418 }
9419
9420 if (too_many_args(1, args, err, NULL))
9421 return -1;
9422
9423 if (*(args[1]) == 0) {
9424 memprintf(err, "'%s' expects an integer argument.", args[0]);
9425 return -1;
9426 }
9427
9428 *target = atoi(args[1]);
9429 if (*target < 0) {
9430 memprintf(err, "'%s' expects a positive numeric value.", args[0]);
9431 return -1;
9432 }
9433 return 0;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01009434}
9435
9436static int ssl_parse_global_capture_cipherlist(char **args, int section_type, struct proxy *curpx,
9437 struct proxy *defpx, const char *file, int line,
9438 char **err)
9439{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01009440 int ret;
9441
9442 ret = ssl_parse_global_int(args, section_type, curpx, defpx, file, line, err);
9443 if (ret != 0)
9444 return ret;
9445
Willy Tarreaubafbe012017-11-24 17:34:44 +01009446 if (pool_head_ssl_capture) {
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01009447 memprintf(err, "'%s' is already configured.", args[0]);
9448 return -1;
9449 }
9450
Willy Tarreaubafbe012017-11-24 17:34:44 +01009451 pool_head_ssl_capture = create_pool("ssl-capture", sizeof(struct ssl_capture) + global_ssl.capture_cipherlist, MEM_F_SHARED);
9452 if (!pool_head_ssl_capture) {
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01009453 memprintf(err, "Out of memory error.");
9454 return -1;
9455 }
9456 return 0;
Willy Tarreau9ceda382016-12-21 23:13:03 +01009457}
9458
9459/* parse "ssl.force-private-cache".
9460 * Returns <0 on alert, >0 on warning, 0 on success.
9461 */
9462static int ssl_parse_global_private_cache(char **args, int section_type, struct proxy *curpx,
9463 struct proxy *defpx, const char *file, int line,
9464 char **err)
9465{
9466 if (too_many_args(0, args, err, NULL))
9467 return -1;
9468
Willy Tarreauef934602016-12-22 23:12:01 +01009469 global_ssl.private_cache = 1;
Willy Tarreau9ceda382016-12-21 23:13:03 +01009470 return 0;
9471}
9472
9473/* parse "ssl.lifetime".
9474 * Returns <0 on alert, >0 on warning, 0 on success.
9475 */
9476static int ssl_parse_global_lifetime(char **args, int section_type, struct proxy *curpx,
9477 struct proxy *defpx, const char *file, int line,
9478 char **err)
9479{
9480 const char *res;
9481
9482 if (too_many_args(1, args, err, NULL))
9483 return -1;
9484
9485 if (*(args[1]) == 0) {
9486 memprintf(err, "'%s' expects ssl sessions <lifetime> in seconds as argument.", args[0]);
9487 return -1;
9488 }
9489
Willy Tarreauef934602016-12-22 23:12:01 +01009490 res = parse_time_err(args[1], &global_ssl.life_time, TIME_UNIT_S);
Willy Tarreau9faebe32019-06-07 19:00:37 +02009491 if (res == PARSE_TIME_OVER) {
9492 memprintf(err, "timer overflow in argument '%s' to <%s> (maximum value is 2147483647 s or ~68 years).",
9493 args[1], args[0]);
9494 return -1;
9495 }
9496 else if (res == PARSE_TIME_UNDER) {
9497 memprintf(err, "timer underflow in argument '%s' to <%s> (minimum non-null value is 1 s).",
9498 args[1], args[0]);
9499 return -1;
9500 }
9501 else if (res) {
Willy Tarreau9ceda382016-12-21 23:13:03 +01009502 memprintf(err, "unexpected character '%c' in argument to <%s>.", *res, args[0]);
9503 return -1;
9504 }
9505 return 0;
9506}
9507
9508#ifndef OPENSSL_NO_DH
Willy Tarreau14e36a12016-12-21 23:28:13 +01009509/* parse "ssl-dh-param-file".
9510 * Returns <0 on alert, >0 on warning, 0 on success.
9511 */
9512static int ssl_parse_global_dh_param_file(char **args, int section_type, struct proxy *curpx,
9513 struct proxy *defpx, const char *file, int line,
9514 char **err)
9515{
9516 if (too_many_args(1, args, err, NULL))
9517 return -1;
9518
9519 if (*(args[1]) == 0) {
9520 memprintf(err, "'%s' expects a file path as an argument.", args[0]);
9521 return -1;
9522 }
9523
9524 if (ssl_sock_load_global_dh_param_from_file(args[1])) {
9525 memprintf(err, "'%s': unable to load DH parameters from file <%s>.", args[0], args[1]);
9526 return -1;
9527 }
9528 return 0;
9529}
9530
Willy Tarreau9ceda382016-12-21 23:13:03 +01009531/* parse "ssl.default-dh-param".
9532 * Returns <0 on alert, >0 on warning, 0 on success.
9533 */
9534static int ssl_parse_global_default_dh(char **args, int section_type, struct proxy *curpx,
9535 struct proxy *defpx, const char *file, int line,
9536 char **err)
9537{
9538 if (too_many_args(1, args, err, NULL))
9539 return -1;
9540
9541 if (*(args[1]) == 0) {
9542 memprintf(err, "'%s' expects an integer argument.", args[0]);
9543 return -1;
9544 }
9545
Willy Tarreauef934602016-12-22 23:12:01 +01009546 global_ssl.default_dh_param = atoi(args[1]);
9547 if (global_ssl.default_dh_param < 1024) {
Willy Tarreau9ceda382016-12-21 23:13:03 +01009548 memprintf(err, "'%s' expects a value >= 1024.", args[0]);
9549 return -1;
9550 }
9551 return 0;
9552}
9553#endif
9554
9555
William Lallemand32af2032016-10-29 18:09:35 +02009556/* This function is used with TLS ticket keys management. It permits to browse
9557 * each reference. The variable <getnext> must contain the current node,
9558 * <end> point to the root node.
9559 */
9560#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
9561static inline
9562struct tls_keys_ref *tlskeys_list_get_next(struct tls_keys_ref *getnext, struct list *end)
9563{
9564 struct tls_keys_ref *ref = getnext;
9565
9566 while (1) {
9567
9568 /* Get next list entry. */
9569 ref = LIST_NEXT(&ref->list, struct tls_keys_ref *, list);
9570
9571 /* If the entry is the last of the list, return NULL. */
9572 if (&ref->list == end)
9573 return NULL;
9574
9575 return ref;
9576 }
9577}
9578
9579static inline
9580struct tls_keys_ref *tlskeys_ref_lookup_ref(const char *reference)
9581{
9582 int id;
9583 char *error;
9584
9585 /* If the reference starts by a '#', this is numeric id. */
9586 if (reference[0] == '#') {
9587 /* Try to convert the numeric id. If the conversion fails, the lookup fails. */
9588 id = strtol(reference + 1, &error, 10);
9589 if (*error != '\0')
9590 return NULL;
9591
9592 /* Perform the unique id lookup. */
9593 return tlskeys_ref_lookupid(id);
9594 }
9595
9596 /* Perform the string lookup. */
9597 return tlskeys_ref_lookup(reference);
9598}
9599#endif
9600
9601
9602#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
9603
9604static int cli_io_handler_tlskeys_files(struct appctx *appctx);
9605
9606static inline int cli_io_handler_tlskeys_entries(struct appctx *appctx) {
9607 return cli_io_handler_tlskeys_files(appctx);
9608}
9609
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009610/* dumps all tls keys. Relies on cli.i0 (non-null = only list file names), cli.i1
9611 * (next index to be dumped), and cli.p0 (next key reference).
9612 */
William Lallemand32af2032016-10-29 18:09:35 +02009613static int cli_io_handler_tlskeys_files(struct appctx *appctx) {
9614
9615 struct stream_interface *si = appctx->owner;
9616
9617 switch (appctx->st2) {
9618 case STAT_ST_INIT:
9619 /* Display the column headers. If the message cannot be sent,
Joseph Herlant017b3da2018-11-15 09:07:59 -08009620 * quit the function with returning 0. The function is called
William Lallemand32af2032016-10-29 18:09:35 +02009621 * later and restart at the state "STAT_ST_INIT".
9622 */
9623 chunk_reset(&trash);
9624
9625 if (appctx->io_handler == cli_io_handler_tlskeys_entries)
9626 chunk_appendf(&trash, "# id secret\n");
9627 else
9628 chunk_appendf(&trash, "# id (file)\n");
9629
Willy Tarreau06d80a92017-10-19 14:32:15 +02009630 if (ci_putchk(si_ic(si), &trash) == -1) {
Willy Tarreaudb398432018-11-15 11:08:52 +01009631 si_rx_room_blk(si);
William Lallemand32af2032016-10-29 18:09:35 +02009632 return 0;
9633 }
9634
William Lallemand32af2032016-10-29 18:09:35 +02009635 /* Now, we start the browsing of the references lists.
9636 * Note that the following call to LIST_ELEM return bad pointer. The only
9637 * available field of this pointer is <list>. It is used with the function
9638 * tlskeys_list_get_next() for retruning the first available entry
9639 */
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009640 if (appctx->ctx.cli.p0 == NULL) {
9641 appctx->ctx.cli.p0 = LIST_ELEM(&tlskeys_reference, struct tls_keys_ref *, list);
9642 appctx->ctx.cli.p0 = tlskeys_list_get_next(appctx->ctx.cli.p0, &tlskeys_reference);
William Lallemand32af2032016-10-29 18:09:35 +02009643 }
9644
9645 appctx->st2 = STAT_ST_LIST;
9646 /* fall through */
9647
9648 case STAT_ST_LIST:
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009649 while (appctx->ctx.cli.p0) {
9650 struct tls_keys_ref *ref = appctx->ctx.cli.p0;
William Lallemand32af2032016-10-29 18:09:35 +02009651
9652 chunk_reset(&trash);
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009653 if (appctx->io_handler == cli_io_handler_tlskeys_entries && appctx->ctx.cli.i1 == 0)
William Lallemand32af2032016-10-29 18:09:35 +02009654 chunk_appendf(&trash, "# ");
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009655
9656 if (appctx->ctx.cli.i1 == 0)
9657 chunk_appendf(&trash, "%d (%s)\n", ref->unique_id, ref->filename);
9658
William Lallemand32af2032016-10-29 18:09:35 +02009659 if (appctx->io_handler == cli_io_handler_tlskeys_entries) {
Christopher Faulet16f45c82018-02-16 11:23:49 +01009660 int head;
9661
9662 HA_RWLOCK_RDLOCK(TLSKEYS_REF_LOCK, &ref->lock);
9663 head = ref->tls_ticket_enc_index;
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009664 while (appctx->ctx.cli.i1 < TLS_TICKETS_NO) {
Willy Tarreau83061a82018-07-13 11:56:34 +02009665 struct buffer *t2 = get_trash_chunk();
William Lallemand32af2032016-10-29 18:09:35 +02009666
9667 chunk_reset(t2);
9668 /* should never fail here because we dump only a key in the t2 buffer */
Emeric Brun9e754772019-01-10 17:51:55 +01009669 if (ref->key_size_bits == 128) {
9670 t2->data = a2base64((char *)(ref->tlskeys + (head + 2 + appctx->ctx.cli.i1) % TLS_TICKETS_NO),
9671 sizeof(struct tls_sess_key_128),
9672 t2->area, t2->size);
9673 chunk_appendf(&trash, "%d.%d %s\n", ref->unique_id, appctx->ctx.cli.i1,
9674 t2->area);
9675 }
9676 else if (ref->key_size_bits == 256) {
9677 t2->data = a2base64((char *)(ref->tlskeys + (head + 2 + appctx->ctx.cli.i1) % TLS_TICKETS_NO),
9678 sizeof(struct tls_sess_key_256),
9679 t2->area, t2->size);
9680 chunk_appendf(&trash, "%d.%d %s\n", ref->unique_id, appctx->ctx.cli.i1,
9681 t2->area);
9682 }
9683 else {
9684 /* This case should never happen */
9685 chunk_appendf(&trash, "%d.%d <unknown>\n", ref->unique_id, appctx->ctx.cli.i1);
9686 }
William Lallemand32af2032016-10-29 18:09:35 +02009687
Willy Tarreau06d80a92017-10-19 14:32:15 +02009688 if (ci_putchk(si_ic(si), &trash) == -1) {
William Lallemand32af2032016-10-29 18:09:35 +02009689 /* let's try again later from this stream. We add ourselves into
9690 * this stream's users so that it can remove us upon termination.
9691 */
Christopher Faulet16f45c82018-02-16 11:23:49 +01009692 HA_RWLOCK_RDUNLOCK(TLSKEYS_REF_LOCK, &ref->lock);
Willy Tarreaudb398432018-11-15 11:08:52 +01009693 si_rx_room_blk(si);
William Lallemand32af2032016-10-29 18:09:35 +02009694 return 0;
9695 }
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009696 appctx->ctx.cli.i1++;
William Lallemand32af2032016-10-29 18:09:35 +02009697 }
Christopher Faulet16f45c82018-02-16 11:23:49 +01009698 HA_RWLOCK_RDUNLOCK(TLSKEYS_REF_LOCK, &ref->lock);
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009699 appctx->ctx.cli.i1 = 0;
William Lallemand32af2032016-10-29 18:09:35 +02009700 }
Willy Tarreau06d80a92017-10-19 14:32:15 +02009701 if (ci_putchk(si_ic(si), &trash) == -1) {
William Lallemand32af2032016-10-29 18:09:35 +02009702 /* let's try again later from this stream. We add ourselves into
9703 * this stream's users so that it can remove us upon termination.
9704 */
Willy Tarreaudb398432018-11-15 11:08:52 +01009705 si_rx_room_blk(si);
William Lallemand32af2032016-10-29 18:09:35 +02009706 return 0;
9707 }
9708
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009709 if (appctx->ctx.cli.i0 == 0) /* don't display everything if not necessary */
William Lallemand32af2032016-10-29 18:09:35 +02009710 break;
9711
9712 /* get next list entry and check the end of the list */
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009713 appctx->ctx.cli.p0 = tlskeys_list_get_next(appctx->ctx.cli.p0, &tlskeys_reference);
William Lallemand32af2032016-10-29 18:09:35 +02009714 }
9715
9716 appctx->st2 = STAT_ST_FIN;
9717 /* fall through */
9718
9719 default:
9720 appctx->st2 = STAT_ST_FIN;
9721 return 1;
9722 }
9723 return 0;
9724}
9725
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009726/* sets cli.i0 to non-zero if only file lists should be dumped */
Aurélien Nephtaliabbf6072018-04-18 13:26:46 +02009727static int cli_parse_show_tlskeys(char **args, char *payload, struct appctx *appctx, void *private)
William Lallemand32af2032016-10-29 18:09:35 +02009728{
William Lallemand32af2032016-10-29 18:09:35 +02009729 /* no parameter, shows only file list */
9730 if (!*args[2]) {
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009731 appctx->ctx.cli.i0 = 1;
William Lallemand32af2032016-10-29 18:09:35 +02009732 appctx->io_handler = cli_io_handler_tlskeys_files;
Willy Tarreau3067bfa2016-12-05 14:50:15 +01009733 return 0;
William Lallemand32af2032016-10-29 18:09:35 +02009734 }
9735
9736 if (args[2][0] == '*') {
9737 /* list every TLS ticket keys */
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009738 appctx->ctx.cli.i0 = 1;
William Lallemand32af2032016-10-29 18:09:35 +02009739 } else {
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009740 appctx->ctx.cli.p0 = tlskeys_ref_lookup_ref(args[2]);
Willy Tarreau9d008692019-08-09 11:21:01 +02009741 if (!appctx->ctx.cli.p0)
9742 return cli_err(appctx, "'show tls-keys' unable to locate referenced filename\n");
William Lallemand32af2032016-10-29 18:09:35 +02009743 }
William Lallemand32af2032016-10-29 18:09:35 +02009744 appctx->io_handler = cli_io_handler_tlskeys_entries;
Willy Tarreau3067bfa2016-12-05 14:50:15 +01009745 return 0;
William Lallemand32af2032016-10-29 18:09:35 +02009746}
9747
Aurélien Nephtaliabbf6072018-04-18 13:26:46 +02009748static int cli_parse_set_tlskeys(char **args, char *payload, struct appctx *appctx, void *private)
William Lallemand32af2032016-10-29 18:09:35 +02009749{
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009750 struct tls_keys_ref *ref;
Willy Tarreau1c913e42018-08-22 05:26:57 +02009751 int ret;
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009752
William Lallemand32af2032016-10-29 18:09:35 +02009753 /* Expect two parameters: the filename and the new new TLS key in encoding */
Willy Tarreau9d008692019-08-09 11:21:01 +02009754 if (!*args[3] || !*args[4])
9755 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 +02009756
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009757 ref = tlskeys_ref_lookup_ref(args[3]);
Willy Tarreau9d008692019-08-09 11:21:01 +02009758 if (!ref)
9759 return cli_err(appctx, "'set ssl tls-key' unable to locate referenced filename\n");
William Lallemand32af2032016-10-29 18:09:35 +02009760
Willy Tarreau1c913e42018-08-22 05:26:57 +02009761 ret = base64dec(args[4], strlen(args[4]), trash.area, trash.size);
Willy Tarreau9d008692019-08-09 11:21:01 +02009762 if (ret < 0)
9763 return cli_err(appctx, "'set ssl tls-key' received invalid base64 encoded TLS key.\n");
Emeric Brun9e754772019-01-10 17:51:55 +01009764
Willy Tarreau1c913e42018-08-22 05:26:57 +02009765 trash.data = ret;
Willy Tarreau9d008692019-08-09 11:21:01 +02009766 if (ssl_sock_update_tlskey_ref(ref, &trash) < 0)
9767 return cli_err(appctx, "'set ssl tls-key' received a key of wrong size.\n");
William Lallemand32af2032016-10-29 18:09:35 +02009768
Willy Tarreau9d008692019-08-09 11:21:01 +02009769 return cli_msg(appctx, LOG_INFO, "TLS ticket key updated!\n");
William Lallemand32af2032016-10-29 18:09:35 +02009770}
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01009771#endif
William Lallemand32af2032016-10-29 18:09:35 +02009772
William Lallemand150bfa82019-09-19 17:12:49 +02009773static int cli_parse_set_cert(char **args, char *payload, struct appctx *appctx, void *private)
9774{
9775 struct ckch_store *ckchs = NULL;
9776 struct cert_key_and_chain *ckch;
9777 struct list tmp_ckchi_list;
William Lallemand150bfa82019-09-19 17:12:49 +02009778 char *err = NULL;
William Lallemand963b2e72019-10-14 11:38:36 +02009779 int i;
William Lallemand150bfa82019-09-19 17:12:49 +02009780 int found = 0;
William Lallemand849eed62019-10-17 16:23:50 +02009781 int bundle = -1; /* TRUE if >= 0 (ckch index) */
Emeric Brunf69ed1d2019-10-17 11:56:56 +02009782 int errcode = 0;
William Lallemand150bfa82019-09-19 17:12:49 +02009783
9784 if (!*args[3] || !payload)
9785 return cli_err(appctx, "'set ssl cert expects a filename and a certificat as a payload\n");
9786
9787 /* The operations on the CKCH architecture are locked so we can
9788 * manipulate ckch_store and ckch_inst */
9789 if (HA_SPIN_TRYLOCK(CKCH_LOCK, &ckch_lock))
9790 return cli_err(appctx, "Can't update the certificate!\nOperations on certificates are currently locked!\n");
9791
9792 LIST_INIT(&tmp_ckchi_list);
9793
William Lallemand150bfa82019-09-19 17:12:49 +02009794 /* do 2 iterations, first one with a non-bundle entry, second one with a bundle entry */
9795 for (i = 0; i < 2; i++) {
9796
9797 if ((ckchs = ckchs_lookup(args[3])) != NULL) {
9798 struct ckch_inst *ckchi, *ckchis;
9799
9800 /* only the bundle name is in the tree and you should never update a bundle name, only a filename */
9801 if (bundle < 0 && ckchs->multi) {
9802 memprintf(&err, "%s%s is a multi-cert bundle. Try updating %s.{dsa,rsa,ecdsa}\n",
9803 err ? err : "", args[3], args[3]);
Emeric Brunf69ed1d2019-10-17 11:56:56 +02009804 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemand150bfa82019-09-19 17:12:49 +02009805 goto end;
9806 }
9807
William Lallemand849eed62019-10-17 16:23:50 +02009808 /* If we want a bundle but this is not a bundle */
9809 if (bundle >= 0 && ckchs->multi == 0)
9810 continue;
9811
William Lallemand150bfa82019-09-19 17:12:49 +02009812 if (bundle < 0)
9813 ckch = ckchs->ckch;
9814 else
9815 ckch = &ckchs->ckch[bundle];
9816
9817 if (ckchs->filters) {
9818 memprintf(&err, "%sCertificates used in crt-list with filters are not supported!\n",
9819 err ? err : "");
Emeric Brunf69ed1d2019-10-17 11:56:56 +02009820 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemand150bfa82019-09-19 17:12:49 +02009821 goto end;
9822 }
9823
9824 found = 1;
9825
William Lallemand96a9c972019-10-17 11:56:17 +02009826 if (ssl_sock_load_pem_into_ckch(args[3], payload, ckch, &err) != 0) {
Emeric Brunf69ed1d2019-10-17 11:56:56 +02009827 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemand150bfa82019-09-19 17:12:49 +02009828 goto end;
9829 }
9830
9831 /* walk through ckch_inst and creates new ckch_inst using the updated ckch */
9832 list_for_each_entry(ckchi, &ckchs->ckch_inst, by_ckchs) {
9833 struct ckch_inst *new_inst;
9834
9835 if (ckchs->multi)
Emeric Brun054563d2019-10-17 13:16:58 +02009836 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 +02009837 else
Emeric Brun054563d2019-10-17 13:16:58 +02009838 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 +02009839
Emeric Brun054563d2019-10-17 13:16:58 +02009840 if (errcode & ERR_CODE)
William Lallemand150bfa82019-09-19 17:12:49 +02009841 goto end;
William Lallemand150bfa82019-09-19 17:12:49 +02009842
9843 /* link temporary the new ckch_inst */
9844 LIST_ADDQ(&tmp_ckchi_list, &new_inst->by_ckchs);
9845 }
9846
9847 /* once every allocation is done, delete the old sni_ctx & the old ckch_insts */
9848 list_for_each_entry_safe(ckchi, ckchis, &ckchs->ckch_inst, by_ckchs) {
9849 struct sni_ctx *sc0, *sc0s;
9850
William Lallemand02010472019-10-18 11:02:19 +02009851 HA_RWLOCK_WRLOCK(SNI_LOCK, &ckchi->bind_conf->sni_lock);
William Lallemand150bfa82019-09-19 17:12:49 +02009852 list_for_each_entry_safe(sc0, sc0s, &ckchi->sni_ctx, by_ckch_inst) {
9853 ebmb_delete(&sc0->name);
9854 LIST_DEL(&sc0->by_ckch_inst);
9855 free(sc0);
9856 }
William Lallemand02010472019-10-18 11:02:19 +02009857 HA_RWLOCK_WRUNLOCK(SNI_LOCK, &ckchi->bind_conf->sni_lock);
William Lallemand150bfa82019-09-19 17:12:49 +02009858 LIST_DEL(&ckchi->by_ckchs);
9859 free(ckchi);
9860 ckchi = NULL;
9861 }
9862 /* insert every new ckch instance in the actual list and insert the sni_ctx in the trees */
9863 list_for_each_entry_safe(ckchi, ckchis, &tmp_ckchi_list, by_ckchs) {
9864 LIST_DEL(&ckchi->by_ckchs);
9865 LIST_ADD(&ckchs->ckch_inst, &ckchi->by_ckchs);
William Lallemand02010472019-10-18 11:02:19 +02009866 HA_RWLOCK_WRLOCK(SNI_LOCK, &ckchi->bind_conf->sni_lock);
William Lallemand150bfa82019-09-19 17:12:49 +02009867 ssl_sock_load_cert_sni(ckchi, ckchi->bind_conf);
William Lallemand02010472019-10-18 11:02:19 +02009868 HA_RWLOCK_WRUNLOCK(SNI_LOCK, &ckchi->bind_conf->sni_lock);
William Lallemand150bfa82019-09-19 17:12:49 +02009869 }
9870 }
William Lallemand963b2e72019-10-14 11:38:36 +02009871#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
9872 {
9873 char *end = NULL;
9874 int j;
William Lallemand150bfa82019-09-19 17:12:49 +02009875
William Lallemand963b2e72019-10-14 11:38:36 +02009876 /* check if it was also used as a bundle by removing the
9877 * .dsa/.rsa/.ecdsa at the end of the filename */
9878 if (bundle >= 0)
William Lallemand150bfa82019-09-19 17:12:49 +02009879 break;
William Lallemand963b2e72019-10-14 11:38:36 +02009880 end = strrchr(args[3], '.');
9881 for (j = 0; *end && j < SSL_SOCK_NUM_KEYTYPES; j++) {
9882 if (!strcmp(end + 1, SSL_SOCK_KEYTYPE_NAMES[j])) {
9883 bundle = j; /* keep the type of certificate so we insert it at the right place */
9884 *end = '\0'; /* it's a bundle let's end the string*/
9885 break;
9886 }
William Lallemand150bfa82019-09-19 17:12:49 +02009887 }
9888 }
William Lallemand963b2e72019-10-14 11:38:36 +02009889#else
9890 /* bundles are not supported here, so we don't need to lookup again */
9891 break;
9892#endif
William Lallemand150bfa82019-09-19 17:12:49 +02009893 }
9894
9895 if (!found) {
William Lallemand150bfa82019-09-19 17:12:49 +02009896 memprintf(&err, "%sCan't replace a certificate name which is not referenced by the configuration!\n",
9897 err ? err : "");
Emeric Brunf69ed1d2019-10-17 11:56:56 +02009898 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemand150bfa82019-09-19 17:12:49 +02009899 }
9900
9901end:
9902
9903 HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
9904
Emeric Brunf69ed1d2019-10-17 11:56:56 +02009905 if (errcode & ERR_CODE) {
William Lallemand150bfa82019-09-19 17:12:49 +02009906 struct ckch_inst *ckchi, *ckchis;
9907 /* if the allocation failed, we need to free everything from the temporary list */
9908 list_for_each_entry_safe(ckchi, ckchis, &tmp_ckchi_list, by_ckchs) {
9909 struct sni_ctx *sc0, *sc0s;
9910
9911 list_for_each_entry_safe(sc0, sc0s, &ckchi->sni_ctx, by_ckch_inst) {
9912 if (sc0->order == 0) /* we only free if it's the first inserted */
9913 SSL_CTX_free(sc0->ctx);
9914 LIST_DEL(&sc0->by_ckch_inst);
9915 free(sc0);
9916 }
9917 LIST_DEL(&ckchi->by_ckchs);
9918 free(ckchi);
9919 }
9920 return cli_dynerr(appctx, memprintf(&err, "%sCan't update the certificate!\n", err ? err : ""));
Emeric Brunf69ed1d2019-10-17 11:56:56 +02009921 }
9922 else if (errcode & ERR_WARN) {
9923 return cli_dynmsg(appctx, LOG_WARNING, memprintf(&err, "%sCertificate updated!\n", err ? err : ""));
9924 }
9925 else {
William Lallemand150bfa82019-09-19 17:12:49 +02009926 return cli_dynmsg(appctx, LOG_INFO, memprintf(&err, "Certificate updated!"));
9927 }
9928}
9929
Aurélien Nephtaliabbf6072018-04-18 13:26:46 +02009930static int cli_parse_set_ocspresponse(char **args, char *payload, struct appctx *appctx, void *private)
William Lallemand32af2032016-10-29 18:09:35 +02009931{
9932#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
9933 char *err = NULL;
Willy Tarreau1c913e42018-08-22 05:26:57 +02009934 int i, j, ret;
Aurélien Nephtali1e0867c2018-04-18 14:04:58 +02009935
9936 if (!payload)
9937 payload = args[3];
William Lallemand32af2032016-10-29 18:09:35 +02009938
9939 /* Expect one parameter: the new response in base64 encoding */
Willy Tarreau9d008692019-08-09 11:21:01 +02009940 if (!*payload)
9941 return cli_err(appctx, "'set ssl ocsp-response' expects response in base64 encoding.\n");
Aurélien Nephtali1e0867c2018-04-18 14:04:58 +02009942
9943 /* remove \r and \n from the payload */
9944 for (i = 0, j = 0; payload[i]; i++) {
9945 if (payload[i] == '\r' || payload[i] == '\n')
9946 continue;
9947 payload[j++] = payload[i];
9948 }
9949 payload[j] = 0;
William Lallemand32af2032016-10-29 18:09:35 +02009950
Willy Tarreau1c913e42018-08-22 05:26:57 +02009951 ret = base64dec(payload, j, trash.area, trash.size);
Willy Tarreau9d008692019-08-09 11:21:01 +02009952 if (ret < 0)
9953 return cli_err(appctx, "'set ssl ocsp-response' received invalid base64 encoded response.\n");
William Lallemand32af2032016-10-29 18:09:35 +02009954
Willy Tarreau1c913e42018-08-22 05:26:57 +02009955 trash.data = ret;
William Lallemand32af2032016-10-29 18:09:35 +02009956 if (ssl_sock_update_ocsp_response(&trash, &err)) {
Willy Tarreau9d008692019-08-09 11:21:01 +02009957 if (err)
9958 return cli_dynerr(appctx, memprintf(&err, "%s.\n", err));
9959 else
9960 return cli_err(appctx, "Failed to update OCSP response.\n");
William Lallemand32af2032016-10-29 18:09:35 +02009961 }
Willy Tarreau9d008692019-08-09 11:21:01 +02009962
9963 return cli_msg(appctx, LOG_INFO, "OCSP Response updated!\n");
William Lallemand32af2032016-10-29 18:09:35 +02009964#else
Willy Tarreau9d008692019-08-09 11:21:01 +02009965 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 +02009966#endif
9967
Nenad Merdanovicc31499d2019-03-23 11:00:32 +01009968}
9969
Willy Tarreau86a394e2019-05-09 14:15:32 +02009970#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000100fL)
Nenad Merdanovicc31499d2019-03-23 11:00:32 +01009971static inline int sample_conv_var2smp_str(const struct arg *arg, struct sample *smp)
9972{
9973 switch (arg->type) {
9974 case ARGT_STR:
9975 smp->data.type = SMP_T_STR;
9976 smp->data.u.str = arg->data.str;
9977 return 1;
9978 case ARGT_VAR:
9979 if (!vars_get_by_desc(&arg->data.var, smp))
9980 return 0;
9981 if (!sample_casts[smp->data.type][SMP_T_STR])
9982 return 0;
9983 if (!sample_casts[smp->data.type][SMP_T_STR](smp))
9984 return 0;
9985 return 1;
9986 default:
9987 return 0;
9988 }
9989}
9990
9991static int check_aes_gcm(struct arg *args, struct sample_conv *conv,
9992 const char *file, int line, char **err)
9993{
9994 switch(args[0].data.sint) {
9995 case 128:
9996 case 192:
9997 case 256:
9998 break;
9999 default:
10000 memprintf(err, "key size must be 128, 192 or 256 (bits).");
10001 return 0;
10002 }
10003 /* Try to decode a variable. */
10004 vars_check_arg(&args[1], NULL);
10005 vars_check_arg(&args[2], NULL);
10006 vars_check_arg(&args[3], NULL);
10007 return 1;
10008}
10009
10010/* Arguements: AES size in bits, nonce, key, tag. The last three arguments are base64 encoded */
10011static int sample_conv_aes_gcm_dec(const struct arg *arg_p, struct sample *smp, void *private)
10012{
10013 struct sample nonce, key, aead_tag;
10014 struct buffer *smp_trash, *smp_trash_alloc;
10015 EVP_CIPHER_CTX *ctx;
10016 int dec_size, ret;
10017
10018 smp_set_owner(&nonce, smp->px, smp->sess, smp->strm, smp->opt);
10019 if (!sample_conv_var2smp_str(&arg_p[1], &nonce))
10020 return 0;
10021
10022 smp_set_owner(&key, smp->px, smp->sess, smp->strm, smp->opt);
10023 if (!sample_conv_var2smp_str(&arg_p[2], &key))
10024 return 0;
10025
10026 smp_set_owner(&aead_tag, smp->px, smp->sess, smp->strm, smp->opt);
10027 if (!sample_conv_var2smp_str(&arg_p[3], &aead_tag))
10028 return 0;
10029
10030 smp_trash = get_trash_chunk();
10031 smp_trash_alloc = alloc_trash_chunk();
10032 if (!smp_trash_alloc)
10033 return 0;
10034
10035 ctx = EVP_CIPHER_CTX_new();
10036
10037 if (!ctx)
10038 goto err;
10039
10040 dec_size = base64dec(nonce.data.u.str.area, nonce.data.u.str.data, smp_trash->area, smp_trash->size);
10041 if (dec_size < 0)
10042 goto err;
10043 smp_trash->data = dec_size;
10044
10045 /* Set cipher type and mode */
10046 switch(arg_p[0].data.sint) {
10047 case 128:
10048 EVP_DecryptInit_ex(ctx, EVP_aes_128_gcm(), NULL, NULL, NULL);
10049 break;
10050 case 192:
10051 EVP_DecryptInit_ex(ctx, EVP_aes_192_gcm(), NULL, NULL, NULL);
10052 break;
10053 case 256:
10054 EVP_DecryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL);
10055 break;
10056 }
10057
10058 EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, smp_trash->data, NULL);
10059
10060 /* Initialise IV */
10061 if(!EVP_DecryptInit_ex(ctx, NULL, NULL, NULL, (unsigned char *) smp_trash->area))
10062 goto err;
10063
10064 dec_size = base64dec(key.data.u.str.area, key.data.u.str.data, smp_trash->area, smp_trash->size);
10065 if (dec_size < 0)
10066 goto err;
10067 smp_trash->data = dec_size;
10068
10069 /* Initialise key */
10070 if (!EVP_DecryptInit_ex(ctx, NULL, NULL, (unsigned char *) smp_trash->area, NULL))
10071 goto err;
10072
10073 if (!EVP_DecryptUpdate(ctx, (unsigned char *) smp_trash->area, (int *) &smp_trash->data,
10074 (unsigned char *) smp->data.u.str.area, (int) smp->data.u.str.data))
10075 goto err;
10076
10077 dec_size = base64dec(aead_tag.data.u.str.area, aead_tag.data.u.str.data, smp_trash_alloc->area, smp_trash_alloc->size);
10078 if (dec_size < 0)
10079 goto err;
10080 smp_trash_alloc->data = dec_size;
10081 dec_size = smp_trash->data;
10082
10083 EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, smp_trash_alloc->data, (void *) smp_trash_alloc->area);
10084 ret = EVP_DecryptFinal_ex(ctx, (unsigned char *) smp_trash->area + smp_trash->data, (int *) &smp_trash->data);
10085
10086 if (ret <= 0)
10087 goto err;
10088
10089 smp->data.u.str.data = dec_size + smp_trash->data;
10090 smp->data.u.str.area = smp_trash->area;
10091 smp->data.type = SMP_T_BIN;
10092 smp->flags &= ~SMP_F_CONST;
10093 free_trash_chunk(smp_trash_alloc);
10094 return 1;
10095
10096err:
10097 free_trash_chunk(smp_trash_alloc);
10098 return 0;
William Lallemand32af2032016-10-29 18:09:35 +020010099}
Nenad Merdanovicc31499d2019-03-23 11:00:32 +010010100# endif
William Lallemand32af2032016-10-29 18:09:35 +020010101
10102/* register cli keywords */
10103static struct cli_kw_list cli_kws = {{ },{
10104#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
10105 { { "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 +020010106 { { "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 +020010107#endif
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +010010108 { { "set", "ssl", "ocsp-response", NULL }, NULL, cli_parse_set_ocspresponse, NULL },
William Lallemand150bfa82019-09-19 17:12:49 +020010109 { { "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 +020010110 { { NULL }, NULL, NULL, NULL }
10111}};
10112
Willy Tarreau0108d902018-11-25 19:14:37 +010010113INITCALL1(STG_REGISTER, cli_register_kw, &cli_kws);
William Lallemand32af2032016-10-29 18:09:35 +020010114
Willy Tarreau7875d092012-09-10 08:20:03 +020010115/* Note: must not be declared <const> as its list will be overwritten.
10116 * Please take care of keeping this list alphabetically sorted.
10117 */
Willy Tarreaudc13c112013-06-21 23:16:39 +020010118static struct sample_fetch_kw_list sample_fetch_keywords = {ILH, {
Emeric Brun645ae792014-04-30 14:21:06 +020010119 { "ssl_bc", smp_fetch_ssl_fc, 0, NULL, SMP_T_BOOL, SMP_USE_L5SRV },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +020010120 { "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 +010010121#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Jérôme Magnine064a802018-12-03 22:21:04 +010010122 { "ssl_bc_alpn", smp_fetch_ssl_fc_alpn, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
Olivier Houchard6b77f492018-11-22 18:18:29 +010010123#endif
Emeric Brun645ae792014-04-30 14:21:06 +020010124 { "ssl_bc_cipher", smp_fetch_ssl_fc_cipher, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
Olivier Houchard6b77f492018-11-22 18:18:29 +010010125#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
10126 { "ssl_bc_npn", smp_fetch_ssl_fc_npn, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
10127#endif
Emeric Brun74f7ffa2018-02-19 16:14:12 +010010128 { "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 +020010129 { "ssl_bc_protocol", smp_fetch_ssl_fc_protocol, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
Emeric Brunb73a9b02014-04-30 18:49:19 +020010130 { "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 +020010131 { "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 +020010132#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
Emeric Brun645ae792014-04-30 14:21:06 +020010133 { "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 -040010134#endif
Emmanuel Hocdet839af572019-05-14 16:27:35 +020010135#if HA_OPENSSL_VERSION_NUMBER >= 0x10100000L
Patrick Hemmer65674662019-06-04 08:13:03 -040010136 { "ssl_bc_client_random", smp_fetch_ssl_fc_random, 0, NULL, SMP_T_BIN, SMP_USE_L5SRV },
10137 { "ssl_bc_server_random", smp_fetch_ssl_fc_random, 0, NULL, SMP_T_BIN, SMP_USE_L5SRV },
Patrick Hemmere0275472018-04-28 19:15:51 -040010138 { "ssl_bc_session_key", smp_fetch_ssl_fc_session_key, 0, NULL, SMP_T_BIN, SMP_USE_L5SRV },
10139#endif
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +020010140 { "ssl_c_ca_err", smp_fetch_ssl_c_ca_err, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
10141 { "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 +010010142 { "ssl_c_der", smp_fetch_ssl_x_der, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +020010143 { "ssl_c_err", smp_fetch_ssl_c_err, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Emeric Brunba841a12014-04-30 17:05:08 +020010144 { "ssl_c_i_dn", smp_fetch_ssl_x_i_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
10145 { "ssl_c_key_alg", smp_fetch_ssl_x_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
10146 { "ssl_c_notafter", smp_fetch_ssl_x_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
10147 { "ssl_c_notbefore", smp_fetch_ssl_x_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
10148 { "ssl_c_sig_alg", smp_fetch_ssl_x_sig_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
10149 { "ssl_c_s_dn", smp_fetch_ssl_x_s_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
10150 { "ssl_c_serial", smp_fetch_ssl_x_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
10151 { "ssl_c_sha1", smp_fetch_ssl_x_sha1, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +010010152 { "ssl_c_used", smp_fetch_ssl_c_used, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +020010153 { "ssl_c_verify", smp_fetch_ssl_c_verify, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
10154 { "ssl_c_version", smp_fetch_ssl_x_version, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Emeric Brun43e79582014-10-29 19:03:26 +010010155 { "ssl_f_der", smp_fetch_ssl_x_der, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Emeric Brunba841a12014-04-30 17:05:08 +020010156 { "ssl_f_i_dn", smp_fetch_ssl_x_i_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
10157 { "ssl_f_key_alg", smp_fetch_ssl_x_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
10158 { "ssl_f_notafter", smp_fetch_ssl_x_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
10159 { "ssl_f_notbefore", smp_fetch_ssl_x_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
10160 { "ssl_f_sig_alg", smp_fetch_ssl_x_sig_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
10161 { "ssl_f_s_dn", smp_fetch_ssl_x_s_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
10162 { "ssl_f_serial", smp_fetch_ssl_x_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Emeric Brun55f4fa82014-04-30 17:11:25 +020010163 { "ssl_f_sha1", smp_fetch_ssl_x_sha1, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +020010164 { "ssl_f_version", smp_fetch_ssl_x_version, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +010010165 { "ssl_fc", smp_fetch_ssl_fc, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +020010166 { "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 +010010167 { "ssl_fc_cipher", smp_fetch_ssl_fc_cipher, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +010010168 { "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 +020010169 { "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 +010010170 { "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 +020010171 { "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 +010010172#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +010010173 { "ssl_fc_npn", smp_fetch_ssl_fc_npn, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreaua33c6542012-10-15 13:19:06 +020010174#endif
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +010010175#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +010010176 { "ssl_fc_alpn", smp_fetch_ssl_fc_alpn, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreauab861d32013-04-02 02:30:41 +020010177#endif
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +010010178 { "ssl_fc_protocol", smp_fetch_ssl_fc_protocol, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreau9a1ab082019-05-09 13:26:41 +020010179#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
Emeric Brunb73a9b02014-04-30 18:49:19 +020010180 { "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 -040010181#endif
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +020010182 { "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 +020010183#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +010010184 { "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 -040010185#endif
Emmanuel Hocdet839af572019-05-14 16:27:35 +020010186#if HA_OPENSSL_VERSION_NUMBER >= 0x10100000L
Patrick Hemmer65674662019-06-04 08:13:03 -040010187 { "ssl_fc_client_random", smp_fetch_ssl_fc_random, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
10188 { "ssl_fc_server_random", smp_fetch_ssl_fc_random, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Patrick Hemmere0275472018-04-28 19:15:51 -040010189 { "ssl_fc_session_key", smp_fetch_ssl_fc_session_key, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
10190#endif
Patrick Hemmer41966772018-04-28 19:15:48 -040010191#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +010010192 { "ssl_fc_sni", smp_fetch_ssl_fc_sni, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Patrick Hemmer41966772018-04-28 19:15:48 -040010193#endif
Thierry FOURNIER5bf77322017-02-25 12:45:22 +010010194 { "ssl_fc_cipherlist_bin", smp_fetch_ssl_fc_cl_bin, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
10195 { "ssl_fc_cipherlist_hex", smp_fetch_ssl_fc_cl_hex, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
10196 { "ssl_fc_cipherlist_str", smp_fetch_ssl_fc_cl_str, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
10197 { "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 +020010198 { NULL, NULL, 0, 0, 0 },
10199}};
10200
Willy Tarreau0108d902018-11-25 19:14:37 +010010201INITCALL1(STG_REGISTER, sample_register_fetches, &sample_fetch_keywords);
10202
Willy Tarreau7875d092012-09-10 08:20:03 +020010203/* Note: must not be declared <const> as its list will be overwritten.
10204 * Please take care of keeping this list alphabetically sorted.
10205 */
Willy Tarreaudc13c112013-06-21 23:16:39 +020010206static struct acl_kw_list acl_kws = {ILH, {
Thierry FOURNIERc5a4e982014-03-05 16:07:08 +010010207 { "ssl_fc_sni_end", "ssl_fc_sni", PAT_MATCH_END },
10208 { "ssl_fc_sni_reg", "ssl_fc_sni", PAT_MATCH_REG },
Willy Tarreau8ed669b2013-01-11 15:49:37 +010010209 { /* END */ },
Willy Tarreau7875d092012-09-10 08:20:03 +020010210}};
10211
Willy Tarreau0108d902018-11-25 19:14:37 +010010212INITCALL1(STG_REGISTER, acl_register_keywords, &acl_kws);
10213
Willy Tarreau79eeafa2012-09-14 07:53:05 +020010214/* Note: must not be declared <const> as its list will be overwritten.
10215 * Please take care of keeping this list alphabetically sorted, doing so helps
10216 * all code contributors.
10217 * Optional keywords are also declared with a NULL ->parse() function so that
10218 * the config parser can report an appropriate error when a known keyword was
10219 * not enabled.
10220 */
Emmanuel Hocdet98263292016-12-29 18:26:15 +010010221static struct ssl_bind_kw ssl_bind_kws[] = {
Olivier Houchardc2aae742017-09-22 18:26:28 +020010222 { "allow-0rtt", ssl_bind_parse_allow_0rtt, 0 }, /* allow 0-RTT */
Emmanuel Hocdet98263292016-12-29 18:26:15 +010010223 { "alpn", ssl_bind_parse_alpn, 1 }, /* set ALPN supported protocols */
10224 { "ca-file", ssl_bind_parse_ca_file, 1 }, /* set CAfile to process verify on client cert */
10225 { "ciphers", ssl_bind_parse_ciphers, 1 }, /* set SSL cipher suite */
Emmanuel Hocdet839af572019-05-14 16:27:35 +020010226#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +020010227 { "ciphersuites", ssl_bind_parse_ciphersuites, 1 }, /* set TLS 1.3 cipher suite */
10228#endif
Emmanuel Hocdet98263292016-12-29 18:26:15 +010010229 { "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 +010010230 { "curves", ssl_bind_parse_curves, 1 }, /* set SSL curve suite */
Emmanuel Hocdet98263292016-12-29 18:26:15 +010010231 { "ecdhe", ssl_bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +020010232 { "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 +010010233 { "npn", ssl_bind_parse_npn, 1 }, /* set NPN supported protocols */
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +020010234 { "ssl-min-ver", ssl_bind_parse_tls_method_minmax,1 }, /* minimum version */
10235 { "ssl-max-ver", ssl_bind_parse_tls_method_minmax,1 }, /* maximum version */
Emmanuel Hocdet98263292016-12-29 18:26:15 +010010236 { "verify", ssl_bind_parse_verify, 1 }, /* set SSL verify method */
10237 { NULL, NULL, 0 },
10238};
10239
Willy Tarreau0108d902018-11-25 19:14:37 +010010240/* no initcall for ssl_bind_kws, these ones are parsed in the parser loop */
10241
Willy Tarreau51fb7652012-09-18 18:24:39 +020010242static struct bind_kw_list bind_kws = { "SSL", { }, {
Olivier Houchardc2aae742017-09-22 18:26:28 +020010243 { "allow-0rtt", bind_parse_allow_0rtt, 0 }, /* Allow 0RTT */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +020010244 { "alpn", bind_parse_alpn, 1 }, /* set ALPN supported protocols */
10245 { "ca-file", bind_parse_ca_file, 1 }, /* set CAfile to process verify on client cert */
10246 { "ca-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ignore on verify depth > 0 */
10247 { "ca-sign-file", bind_parse_ca_sign_file, 1 }, /* set CAFile used to generate and sign server certs */
10248 { "ca-sign-pass", bind_parse_ca_sign_pass, 1 }, /* set CAKey passphrase */
10249 { "ciphers", bind_parse_ciphers, 1 }, /* set SSL cipher suite */
Emmanuel Hocdet839af572019-05-14 16:27:35 +020010250#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +020010251 { "ciphersuites", bind_parse_ciphersuites, 1 }, /* set TLS 1.3 cipher suite */
10252#endif
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +020010253 { "crl-file", bind_parse_crl_file, 1 }, /* set certificat revocation list file use on client cert verify */
10254 { "crt", bind_parse_crt, 1 }, /* load SSL certificates from this location */
10255 { "crt-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ingore on verify depth == 0 */
10256 { "crt-list", bind_parse_crt_list, 1 }, /* load a list of crt from this location */
10257 { "curves", bind_parse_curves, 1 }, /* set SSL curve suite */
10258 { "ecdhe", bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
10259 { "force-sslv3", bind_parse_tls_method_options, 0 }, /* force SSLv3 */
10260 { "force-tlsv10", bind_parse_tls_method_options, 0 }, /* force TLSv10 */
10261 { "force-tlsv11", bind_parse_tls_method_options, 0 }, /* force TLSv11 */
10262 { "force-tlsv12", bind_parse_tls_method_options, 0 }, /* force TLSv12 */
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +020010263 { "force-tlsv13", bind_parse_tls_method_options, 0 }, /* force TLSv13 */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +020010264 { "generate-certificates", bind_parse_generate_certs, 0 }, /* enable the server certificates generation */
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +020010265 { "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 +020010266 { "no-sslv3", bind_parse_tls_method_options, 0 }, /* disable SSLv3 */
10267 { "no-tlsv10", bind_parse_tls_method_options, 0 }, /* disable TLSv10 */
10268 { "no-tlsv11", bind_parse_tls_method_options, 0 }, /* disable TLSv11 */
10269 { "no-tlsv12", bind_parse_tls_method_options, 0 }, /* disable TLSv12 */
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +020010270 { "no-tlsv13", bind_parse_tls_method_options, 0 }, /* disable TLSv13 */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +020010271 { "no-tls-tickets", bind_parse_no_tls_tickets, 0 }, /* disable session resumption tickets */
10272 { "ssl", bind_parse_ssl, 0 }, /* enable SSL processing */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +020010273 { "ssl-min-ver", bind_parse_tls_method_minmax, 1 }, /* minimum version */
10274 { "ssl-max-ver", bind_parse_tls_method_minmax, 1 }, /* maximum version */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +020010275 { "strict-sni", bind_parse_strict_sni, 0 }, /* refuse negotiation if sni doesn't match a certificate */
10276 { "tls-ticket-keys", bind_parse_tls_ticket_keys, 1 }, /* set file to load TLS ticket keys from */
10277 { "verify", bind_parse_verify, 1 }, /* set SSL verify method */
10278 { "npn", bind_parse_npn, 1 }, /* set NPN supported protocols */
10279 { "prefer-client-ciphers", bind_parse_pcc, 0 }, /* prefer client ciphers */
Willy Tarreau79eeafa2012-09-14 07:53:05 +020010280 { NULL, NULL, 0 },
10281}};
Emeric Brun46591952012-05-18 15:47:34 +020010282
Willy Tarreau0108d902018-11-25 19:14:37 +010010283INITCALL1(STG_REGISTER, bind_register_keywords, &bind_kws);
10284
Willy Tarreau92faadf2012-10-10 23:04:25 +020010285/* Note: must not be declared <const> as its list will be overwritten.
10286 * Please take care of keeping this list alphabetically sorted, doing so helps
10287 * all code contributors.
10288 * Optional keywords are also declared with a NULL ->parse() function so that
10289 * the config parser can report an appropriate error when a known keyword was
10290 * not enabled.
10291 */
10292static struct srv_kw_list srv_kws = { "SSL", { }, {
Olivier Houchard522eea72017-11-03 16:27:47 +010010293 { "allow-0rtt", srv_parse_allow_0rtt, 0, 1 }, /* Allow using early data on this server */
Olivier Houchardc7566002018-11-20 23:33:50 +010010294 { "alpn", srv_parse_alpn, 1, 1 }, /* Set ALPN supported protocols */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +020010295 { "ca-file", srv_parse_ca_file, 1, 1 }, /* set CAfile to process verify server cert */
Olivier Houchard92150142018-12-21 19:47:01 +010010296 { "check-alpn", srv_parse_alpn, 1, 1 }, /* Set ALPN used for checks */
Olivier Houchard9130a962017-10-17 17:33:43 +020010297 { "check-sni", srv_parse_check_sni, 1, 1 }, /* set SNI */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +020010298 { "check-ssl", srv_parse_check_ssl, 0, 1 }, /* enable SSL for health checks */
10299 { "ciphers", srv_parse_ciphers, 1, 1 }, /* select the cipher suite */
Emmanuel Hocdet839af572019-05-14 16:27:35 +020010300#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +020010301 { "ciphersuites", srv_parse_ciphersuites, 1, 1 }, /* select the cipher suite */
10302#endif
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +020010303 { "crl-file", srv_parse_crl_file, 1, 1 }, /* set certificate revocation list file use on server cert verify */
10304 { "crt", srv_parse_crt, 1, 1 }, /* set client certificate */
10305 { "force-sslv3", srv_parse_tls_method_options, 0, 1 }, /* force SSLv3 */
10306 { "force-tlsv10", srv_parse_tls_method_options, 0, 1 }, /* force TLSv10 */
10307 { "force-tlsv11", srv_parse_tls_method_options, 0, 1 }, /* force TLSv11 */
10308 { "force-tlsv12", srv_parse_tls_method_options, 0, 1 }, /* force TLSv12 */
10309 { "force-tlsv13", srv_parse_tls_method_options, 0, 1 }, /* force TLSv13 */
10310 { "no-check-ssl", srv_parse_no_check_ssl, 0, 1 }, /* disable SSL for health checks */
10311 { "no-send-proxy-v2-ssl", srv_parse_no_send_proxy_ssl, 0, 1 }, /* do not send PROXY protocol header v2 with SSL info */
10312 { "no-send-proxy-v2-ssl-cn", srv_parse_no_send_proxy_cn, 0, 1 }, /* do not send PROXY protocol header v2 with CN */
10313 { "no-ssl", srv_parse_no_ssl, 0, 1 }, /* disable SSL processing */
10314 { "no-ssl-reuse", srv_parse_no_ssl_reuse, 0, 1 }, /* disable session reuse */
10315 { "no-sslv3", srv_parse_tls_method_options, 0, 0 }, /* disable SSLv3 */
10316 { "no-tlsv10", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv10 */
10317 { "no-tlsv11", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv11 */
10318 { "no-tlsv12", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv12 */
10319 { "no-tlsv13", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv13 */
10320 { "no-tls-tickets", srv_parse_no_tls_tickets, 0, 1 }, /* disable session resumption tickets */
Olivier Houchardc7566002018-11-20 23:33:50 +010010321 { "npn", srv_parse_npn, 1, 1 }, /* Set NPN supported protocols */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +020010322 { "send-proxy-v2-ssl", srv_parse_send_proxy_ssl, 0, 1 }, /* send PROXY protocol header v2 with SSL info */
10323 { "send-proxy-v2-ssl-cn", srv_parse_send_proxy_cn, 0, 1 }, /* send PROXY protocol header v2 with CN */
10324 { "sni", srv_parse_sni, 1, 1 }, /* send SNI extension */
10325 { "ssl", srv_parse_ssl, 0, 1 }, /* enable SSL processing */
10326 { "ssl-min-ver", srv_parse_tls_method_minmax, 1, 1 }, /* minimum version */
10327 { "ssl-max-ver", srv_parse_tls_method_minmax, 1, 1 }, /* maximum version */
10328 { "ssl-reuse", srv_parse_ssl_reuse, 0, 1 }, /* enable session reuse */
10329 { "tls-tickets", srv_parse_tls_tickets, 0, 1 }, /* enable session resumption tickets */
10330 { "verify", srv_parse_verify, 1, 1 }, /* set SSL verify method */
10331 { "verifyhost", srv_parse_verifyhost, 1, 1 }, /* require that SSL cert verifies for hostname */
Willy Tarreau92faadf2012-10-10 23:04:25 +020010332 { NULL, NULL, 0, 0 },
10333}};
10334
Willy Tarreau0108d902018-11-25 19:14:37 +010010335INITCALL1(STG_REGISTER, srv_register_keywords, &srv_kws);
10336
Emeric Brun2c86cbf2014-10-30 15:56:50 +010010337static struct cfg_kw_list cfg_kws = {ILH, {
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +010010338 { CFG_GLOBAL, "ca-base", ssl_parse_global_ca_crt_base },
10339 { CFG_GLOBAL, "crt-base", ssl_parse_global_ca_crt_base },
Willy Tarreau0bea58d2016-12-21 23:17:25 +010010340 { CFG_GLOBAL, "maxsslconn", ssl_parse_global_int },
Emeric Brun2c86cbf2014-10-30 15:56:50 +010010341 { CFG_GLOBAL, "ssl-default-bind-options", ssl_parse_default_bind_options },
10342 { CFG_GLOBAL, "ssl-default-server-options", ssl_parse_default_server_options },
Willy Tarreau14e36a12016-12-21 23:28:13 +010010343#ifndef OPENSSL_NO_DH
10344 { CFG_GLOBAL, "ssl-dh-param-file", ssl_parse_global_dh_param_file },
10345#endif
Grant Zhangfa6c7ee2017-01-14 01:42:15 +000010346 { CFG_GLOBAL, "ssl-mode-async", ssl_parse_global_ssl_async },
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020010347#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +000010348 { CFG_GLOBAL, "ssl-engine", ssl_parse_global_ssl_engine },
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020010349#endif
Willy Tarreau9ceda382016-12-21 23:13:03 +010010350 { CFG_GLOBAL, "tune.ssl.cachesize", ssl_parse_global_int },
10351#ifndef OPENSSL_NO_DH
10352 { CFG_GLOBAL, "tune.ssl.default-dh-param", ssl_parse_global_default_dh },
10353#endif
10354 { CFG_GLOBAL, "tune.ssl.force-private-cache", ssl_parse_global_private_cache },
10355 { CFG_GLOBAL, "tune.ssl.lifetime", ssl_parse_global_lifetime },
10356 { CFG_GLOBAL, "tune.ssl.maxrecord", ssl_parse_global_int },
10357 { CFG_GLOBAL, "tune.ssl.ssl-ctx-cache-size", ssl_parse_global_int },
Thierry FOURNIER5bf77322017-02-25 12:45:22 +010010358 { CFG_GLOBAL, "tune.ssl.capture-cipherlist-size", ssl_parse_global_capture_cipherlist },
Willy Tarreauf22e9682016-12-21 23:23:19 +010010359 { CFG_GLOBAL, "ssl-default-bind-ciphers", ssl_parse_global_ciphers },
10360 { CFG_GLOBAL, "ssl-default-server-ciphers", ssl_parse_global_ciphers },
Emmanuel Hocdet839af572019-05-14 16:27:35 +020010361#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +020010362 { CFG_GLOBAL, "ssl-default-bind-ciphersuites", ssl_parse_global_ciphersuites },
10363 { CFG_GLOBAL, "ssl-default-server-ciphersuites", ssl_parse_global_ciphersuites },
10364#endif
Emeric Brun2c86cbf2014-10-30 15:56:50 +010010365 { 0, NULL, NULL },
10366}};
10367
Willy Tarreau0108d902018-11-25 19:14:37 +010010368INITCALL1(STG_REGISTER, cfg_register_keywords, &cfg_kws);
10369
Nenad Merdanovicc31499d2019-03-23 11:00:32 +010010370/* Note: must not be declared <const> as its list will be overwritten */
10371static struct sample_conv_kw_list conv_kws = {ILH, {
Willy Tarreau86a394e2019-05-09 14:15:32 +020010372#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000100fL)
Nenad Merdanovicc31499d2019-03-23 11:00:32 +010010373 { "aes_gcm_dec", sample_conv_aes_gcm_dec, ARG4(4,SINT,STR,STR,STR), check_aes_gcm, SMP_T_BIN, SMP_T_BIN },
10374#endif
10375 { NULL, NULL, 0, 0, 0 },
10376}};
10377
10378INITCALL1(STG_REGISTER, sample_register_convs, &conv_kws);
10379
Willy Tarreauf7bc57c2012-10-03 00:19:48 +020010380/* transport-layer operations for SSL sockets */
Willy Tarreaud9f5cca2016-12-22 21:08:52 +010010381static struct xprt_ops ssl_sock = {
Emeric Brun46591952012-05-18 15:47:34 +020010382 .snd_buf = ssl_sock_from_buf,
10383 .rcv_buf = ssl_sock_to_buf,
Olivier Houcharddf357842019-03-21 16:30:07 +010010384 .subscribe = ssl_subscribe,
10385 .unsubscribe = ssl_unsubscribe,
Olivier Houchard5149b592019-05-23 17:47:36 +020010386 .remove_xprt = ssl_remove_xprt,
Olivier Houchard2e055482019-05-27 19:50:12 +020010387 .add_xprt = ssl_add_xprt,
Emeric Brun46591952012-05-18 15:47:34 +020010388 .rcv_pipe = NULL,
10389 .snd_pipe = NULL,
10390 .shutr = NULL,
10391 .shutw = ssl_sock_shutw,
10392 .close = ssl_sock_close,
10393 .init = ssl_sock_init,
Willy Tarreau55d37912016-12-21 23:38:39 +010010394 .prepare_bind_conf = ssl_sock_prepare_bind_conf,
Willy Tarreau795cdab2016-12-22 17:30:54 +010010395 .destroy_bind_conf = ssl_sock_destroy_bind_conf,
Willy Tarreau17d45382016-12-22 21:16:08 +010010396 .prepare_srv = ssl_sock_prepare_srv_ctx,
10397 .destroy_srv = ssl_sock_free_srv_ctx,
Willy Tarreau8743f7e2016-12-04 18:44:29 +010010398 .get_alpn = ssl_sock_get_alpn,
Willy Tarreau8e0bb0a2016-11-24 16:58:12 +010010399 .name = "SSL",
Emeric Brun46591952012-05-18 15:47:34 +020010400};
10401
Olivier Houchardccaa7de2017-10-02 11:51:03 +020010402enum act_return ssl_action_wait_for_hs(struct act_rule *rule, struct proxy *px,
10403 struct session *sess, struct stream *s, int flags)
10404{
10405 struct connection *conn;
Olivier Houchard6fa63d92017-11-27 18:41:32 +010010406 struct conn_stream *cs;
Olivier Houchardccaa7de2017-10-02 11:51:03 +020010407
10408 conn = objt_conn(sess->origin);
Olivier Houchard6fa63d92017-11-27 18:41:32 +010010409 cs = objt_cs(s->si[0].end);
Olivier Houchardccaa7de2017-10-02 11:51:03 +020010410
Olivier Houchard6fa63d92017-11-27 18:41:32 +010010411 if (conn && cs) {
Olivier Houchardccaa7de2017-10-02 11:51:03 +020010412 if (conn->flags & (CO_FL_EARLY_SSL_HS | CO_FL_SSL_WAIT_HS)) {
Olivier Houchard6fa63d92017-11-27 18:41:32 +010010413 cs->flags |= CS_FL_WAIT_FOR_HS;
Olivier Houchardccaa7de2017-10-02 11:51:03 +020010414 s->req.flags |= CF_READ_NULL;
10415 return ACT_RET_YIELD;
10416 }
10417 }
10418 return (ACT_RET_CONT);
10419}
10420
10421static enum act_parse_ret ssl_parse_wait_for_hs(const char **args, int *orig_arg, struct proxy *px, struct act_rule *rule, char **err)
10422{
10423 rule->action_ptr = ssl_action_wait_for_hs;
10424
10425 return ACT_RET_PRS_OK;
10426}
10427
10428static struct action_kw_list http_req_actions = {ILH, {
10429 { "wait-for-handshake", ssl_parse_wait_for_hs },
10430 { /* END */ }
10431}};
10432
Willy Tarreau0108d902018-11-25 19:14:37 +010010433INITCALL1(STG_REGISTER, http_req_keywords_register, &http_req_actions);
10434
Willy Tarreau5db847a2019-05-09 14:13:35 +020010435#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +010010436
10437static void ssl_sock_sctl_free_func(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, long argl, void *argp)
10438{
10439 if (ptr) {
10440 chunk_destroy(ptr);
10441 free(ptr);
10442 }
10443}
10444
10445#endif
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +010010446static void ssl_sock_capture_free_func(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, long argl, void *argp)
10447{
Willy Tarreaubafbe012017-11-24 17:34:44 +010010448 pool_free(pool_head_ssl_capture, ptr);
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +010010449}
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +010010450
Emeric Brun46591952012-05-18 15:47:34 +020010451__attribute__((constructor))
Willy Tarreau92faadf2012-10-10 23:04:25 +020010452static void __ssl_sock_init(void)
10453{
Ilya Shipitsin0590f442019-05-25 19:30:50 +050010454#if (!defined(OPENSSL_NO_COMP) && !defined(SSL_OP_NO_COMPRESSION))
Emeric Brun46591952012-05-18 15:47:34 +020010455 STACK_OF(SSL_COMP)* cm;
Ilya Shipitsine242f3d2019-05-25 03:38:14 +050010456 int n;
Ilya Shipitsin0590f442019-05-25 19:30:50 +050010457#endif
Emeric Brun46591952012-05-18 15:47:34 +020010458
Willy Tarreauef934602016-12-22 23:12:01 +010010459 if (global_ssl.listen_default_ciphers)
10460 global_ssl.listen_default_ciphers = strdup(global_ssl.listen_default_ciphers);
10461 if (global_ssl.connect_default_ciphers)
10462 global_ssl.connect_default_ciphers = strdup(global_ssl.connect_default_ciphers);
Emmanuel Hocdet839af572019-05-14 16:27:35 +020010463#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +020010464 if (global_ssl.listen_default_ciphersuites)
10465 global_ssl.listen_default_ciphersuites = strdup(global_ssl.listen_default_ciphersuites);
10466 if (global_ssl.connect_default_ciphersuites)
10467 global_ssl.connect_default_ciphersuites = strdup(global_ssl.connect_default_ciphersuites);
10468#endif
Willy Tarreau610f04b2014-02-13 11:36:41 +010010469
Willy Tarreau13e14102016-12-22 20:25:26 +010010470 xprt_register(XPRT_SSL, &ssl_sock);
Willy Tarreau9a1ab082019-05-09 13:26:41 +020010471#if HA_OPENSSL_VERSION_NUMBER < 0x10100000L
Emeric Brun46591952012-05-18 15:47:34 +020010472 SSL_library_init();
Rosen Penev68185952018-12-14 08:47:02 -080010473#endif
Ilya Shipitsin0590f442019-05-25 19:30:50 +050010474#if (!defined(OPENSSL_NO_COMP) && !defined(SSL_OP_NO_COMPRESSION))
Emeric Brun46591952012-05-18 15:47:34 +020010475 cm = SSL_COMP_get_compression_methods();
Ilya Shipitsine242f3d2019-05-25 03:38:14 +050010476 n = sk_SSL_COMP_num(cm);
10477 while (n--) {
10478 (void) sk_SSL_COMP_pop(cm);
10479 }
Ilya Shipitsin0590f442019-05-25 19:30:50 +050010480#endif
Ilya Shipitsine242f3d2019-05-25 03:38:14 +050010481
Willy Tarreau5db847a2019-05-09 14:13:35 +020010482#if defined(USE_THREAD) && (HA_OPENSSL_VERSION_NUMBER < 0x10100000L)
Emeric Brun821bb9b2017-06-15 16:37:39 +020010483 ssl_locking_init();
10484#endif
Willy Tarreau5db847a2019-05-09 14:13:35 +020010485#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +010010486 sctl_ex_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, ssl_sock_sctl_free_func);
10487#endif
Thierry FOURNIER28962c92018-06-17 21:37:05 +020010488 ssl_app_data_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL);
Thierry FOURNIER16ff0502018-06-17 21:33:01 +020010489 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 +010010490 ssl_pkey_info_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, NULL);
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020010491#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +000010492 ENGINE_load_builtin_engines();
Grant Zhangfa6c7ee2017-01-14 01:42:15 +000010493 hap_register_post_check(ssl_check_async_engine_count);
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020010494#endif
Willy Tarreaud1c57502016-12-22 22:46:15 +010010495#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
10496 hap_register_post_check(tlskeys_finalize_config);
10497#endif
Willy Tarreau80713382018-11-26 10:19:54 +010010498
10499 global.ssl_session_max_cost = SSL_SESSION_MAX_COST;
10500 global.ssl_handshake_max_cost = SSL_HANDSHAKE_MAX_COST;
10501
10502#ifndef OPENSSL_NO_DH
10503 ssl_dh_ptr_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, NULL);
10504 hap_register_post_deinit(ssl_free_dh);
10505#endif
10506#ifndef OPENSSL_NO_ENGINE
10507 hap_register_post_deinit(ssl_free_engines);
10508#endif
10509 /* Load SSL string for the verbose & debug mode. */
10510 ERR_load_SSL_strings();
Olivier Houcharda8955d52019-04-07 22:00:38 +020010511 ha_meth = BIO_meth_new(0x666, "ha methods");
10512 BIO_meth_set_write(ha_meth, ha_ssl_write);
10513 BIO_meth_set_read(ha_meth, ha_ssl_read);
10514 BIO_meth_set_ctrl(ha_meth, ha_ssl_ctrl);
10515 BIO_meth_set_create(ha_meth, ha_ssl_new);
10516 BIO_meth_set_destroy(ha_meth, ha_ssl_free);
10517 BIO_meth_set_puts(ha_meth, ha_ssl_puts);
10518 BIO_meth_set_gets(ha_meth, ha_ssl_gets);
William Lallemand150bfa82019-09-19 17:12:49 +020010519
10520 HA_SPIN_INIT(&ckch_lock);
Willy Tarreau80713382018-11-26 10:19:54 +010010521}
Willy Tarreaud92aa5c2015-01-15 21:34:39 +010010522
Willy Tarreau80713382018-11-26 10:19:54 +010010523/* Compute and register the version string */
10524static void ssl_register_build_options()
10525{
10526 char *ptr = NULL;
10527 int i;
10528
Willy Tarreauc2c0b612016-12-21 19:23:20 +010010529 memprintf(&ptr, "Built with OpenSSL version : "
10530#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet50e25e12017-03-24 15:20:03 +010010531 "BoringSSL");
Willy Tarreauc2c0b612016-12-21 19:23:20 +010010532#else /* OPENSSL_IS_BORINGSSL */
10533 OPENSSL_VERSION_TEXT
10534 "\nRunning on OpenSSL version : %s%s",
Rosen Penev68185952018-12-14 08:47:02 -080010535 OpenSSL_version(OPENSSL_VERSION),
Willy Tarreau1d158ab2019-05-09 13:41:45 +020010536 ((OPENSSL_VERSION_NUMBER ^ OpenSSL_version_num()) >> 8) ? " (VERSIONS DIFFER!)" : "");
Willy Tarreauc2c0b612016-12-21 19:23:20 +010010537#endif
10538 memprintf(&ptr, "%s\nOpenSSL library supports TLS extensions : "
Willy Tarreau9a1ab082019-05-09 13:26:41 +020010539#if HA_OPENSSL_VERSION_NUMBER < 0x00907000L
Willy Tarreauc2c0b612016-12-21 19:23:20 +010010540 "no (library version too old)"
10541#elif defined(OPENSSL_NO_TLSEXT)
10542 "no (disabled via OPENSSL_NO_TLSEXT)"
10543#else
10544 "yes"
10545#endif
10546 "", ptr);
10547
10548 memprintf(&ptr, "%s\nOpenSSL library supports SNI : "
10549#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
10550 "yes"
10551#else
10552#ifdef OPENSSL_NO_TLSEXT
10553 "no (because of OPENSSL_NO_TLSEXT)"
10554#else
10555 "no (version might be too old, 0.9.8f min needed)"
10556#endif
10557#endif
10558 "", ptr);
10559
Emmanuel Hocdetf80bc242017-07-12 14:25:38 +020010560 memprintf(&ptr, "%s\nOpenSSL library supports :", ptr);
10561 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
10562 if (methodVersions[i].option)
10563 memprintf(&ptr, "%s %s", ptr, methodVersions[i].name);
Emmanuel Hocdet50e25e12017-03-24 15:20:03 +010010564
Willy Tarreauc2c0b612016-12-21 19:23:20 +010010565 hap_register_build_opts(ptr, 1);
Willy Tarreau80713382018-11-26 10:19:54 +010010566}
Willy Tarreauc2c0b612016-12-21 19:23:20 +010010567
Willy Tarreau80713382018-11-26 10:19:54 +010010568INITCALL0(STG_REGISTER, ssl_register_build_options);
Remi Gacogne4f902b82015-05-28 16:23:00 +020010569
Emeric Brun46591952012-05-18 15:47:34 +020010570
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020010571#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +000010572void ssl_free_engines(void) {
10573 struct ssl_engine_list *wl, *wlb;
10574 /* free up engine list */
10575 list_for_each_entry_safe(wl, wlb, &openssl_engines, list) {
10576 ENGINE_finish(wl->e);
10577 ENGINE_free(wl->e);
10578 LIST_DEL(&wl->list);
10579 free(wl);
10580 }
10581}
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020010582#endif
Christopher Faulet31af49d2015-06-09 17:29:50 +020010583
Remi Gacogned3a23c32015-05-28 16:39:47 +020010584#ifndef OPENSSL_NO_DH
Grant Zhang872f9c22017-01-21 01:10:18 +000010585void ssl_free_dh(void) {
10586 if (local_dh_1024) {
10587 DH_free(local_dh_1024);
10588 local_dh_1024 = NULL;
10589 }
10590 if (local_dh_2048) {
10591 DH_free(local_dh_2048);
10592 local_dh_2048 = NULL;
10593 }
10594 if (local_dh_4096) {
10595 DH_free(local_dh_4096);
10596 local_dh_4096 = NULL;
10597 }
Remi Gacogne47783ef2015-05-29 15:53:22 +020010598 if (global_dh) {
10599 DH_free(global_dh);
10600 global_dh = NULL;
10601 }
Grant Zhang872f9c22017-01-21 01:10:18 +000010602}
10603#endif
10604
10605__attribute__((destructor))
10606static void __ssl_sock_deinit(void)
10607{
10608#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Emeric Brun821bb9b2017-06-15 16:37:39 +020010609 if (ssl_ctx_lru_tree) {
10610 lru64_destroy(ssl_ctx_lru_tree);
Christopher Faulet2a944ee2017-11-07 10:42:54 +010010611 HA_RWLOCK_DESTROY(&ssl_ctx_lru_rwlock);
Emeric Brun821bb9b2017-06-15 16:37:39 +020010612 }
Remi Gacogned3a23c32015-05-28 16:39:47 +020010613#endif
10614
Willy Tarreau5db847a2019-05-09 14:13:35 +020010615#if (HA_OPENSSL_VERSION_NUMBER < 0x10100000L)
Remi Gacogned3a23c32015-05-28 16:39:47 +020010616 ERR_remove_state(0);
10617 ERR_free_strings();
10618
10619 EVP_cleanup();
Rosen Penev68185952018-12-14 08:47:02 -080010620#endif
Remi Gacogned3a23c32015-05-28 16:39:47 +020010621
Willy Tarreau5db847a2019-05-09 14:13:35 +020010622#if (HA_OPENSSL_VERSION_NUMBER >= 0x00907000L) && (HA_OPENSSL_VERSION_NUMBER < 0x10100000L)
Remi Gacogned3a23c32015-05-28 16:39:47 +020010623 CRYPTO_cleanup_all_ex_data();
10624#endif
Olivier Houcharda8955d52019-04-07 22:00:38 +020010625 BIO_meth_free(ha_meth);
Remi Gacogned3a23c32015-05-28 16:39:47 +020010626}
10627
10628
Emeric Brun46591952012-05-18 15:47:34 +020010629/*
10630 * Local variables:
10631 * c-indent-level: 8
10632 * c-basic-offset: 8
10633 * End:
10634 */