blob: cfc68e5ebf3ad2b0a4ed85e4303599e8c706a194 [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
William Lallemand455af502019-10-17 18:04:45 +02002934 if (ckch->dh)
2935 DH_free(ckch->dh);
2936 ckch->dh = NULL;
2937
2938 if (ckch->sctl) {
2939 free(ckch->sctl->area);
2940 ckch->sctl->area = NULL;
2941 free(ckch->sctl);
2942 ckch->sctl = NULL;
2943 }
2944
2945 if (ckch->ocsp_response) {
2946 free(ckch->ocsp_response->area);
2947 ckch->ocsp_response->area = NULL;
2948 free(ckch->ocsp_response);
2949 ckch->ocsp_response = NULL;
2950 }
yanbzhu488a4d22015-12-01 15:16:07 -05002951}
2952
William Lallemand8d0f8932019-10-17 18:03:58 +02002953/*
2954 *
2955 * This function copy a cert_key_and_chain in memory
2956 *
2957 * It's used to try to apply changes on a ckch before committing them, because
2958 * most of the time it's not possible to revert those changes
2959 *
2960 * Return a the dst or NULL
2961 */
2962static struct cert_key_and_chain *ssl_sock_copy_cert_key_and_chain(struct cert_key_and_chain *src,
2963 struct cert_key_and_chain *dst)
2964{
2965 if (src->cert) {
2966 dst->cert = src->cert;
2967 X509_up_ref(src->cert);
2968 }
2969
2970 if (src->key) {
2971 dst->key = src->key;
2972 EVP_PKEY_up_ref(src->key);
2973 }
2974
2975 if (src->chain) {
2976 dst->chain = X509_chain_up_ref(src->chain);
2977 }
2978
2979 if (src->dh) {
2980 DH_up_ref(src->dh);
2981 dst->dh = src->dh;
2982 }
2983
2984 if (src->sctl) {
2985 struct buffer *sctl;
2986
2987 sctl = calloc(1, sizeof(*sctl));
2988 if (!chunk_dup(sctl, src->sctl)) {
2989 free(sctl);
2990 sctl = NULL;
2991 goto error;
2992 }
2993 dst->sctl = sctl;
2994 }
2995
2996 if (src->ocsp_response) {
2997 struct buffer *ocsp_response;
2998
2999 ocsp_response = calloc(1, sizeof(*ocsp_response));
3000 if (!chunk_dup(ocsp_response, src->ocsp_response)) {
3001 free(ocsp_response);
3002 ocsp_response = NULL;
3003 goto error;
3004 }
3005 dst->ocsp_response = ocsp_response;
3006 }
3007
3008 if (src->ocsp_issuer) {
3009 X509_up_ref(src->ocsp_issuer);
3010 dst->ocsp_issuer = src->ocsp_issuer;
3011 }
3012
3013 return dst;
3014
3015error:
3016
3017 /* free everything */
3018 ssl_sock_free_cert_key_and_chain_contents(dst);
3019
3020 return NULL;
3021}
3022
3023
yanbzhu488a4d22015-12-01 15:16:07 -05003024/* checks if a key and cert exists in the ckch
3025 */
William Lallemand1633e392019-09-30 12:58:13 +02003026#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
yanbzhu488a4d22015-12-01 15:16:07 -05003027static int ssl_sock_is_ckch_valid(struct cert_key_and_chain *ckch)
3028{
3029 return (ckch->cert != NULL && ckch->key != NULL);
3030}
William Lallemand1633e392019-09-30 12:58:13 +02003031#endif
yanbzhu488a4d22015-12-01 15:16:07 -05003032
William Lallemandf9568fc2019-10-16 18:27:58 +02003033/*
3034 * return 0 on success or != 0 on failure
3035 */
3036static int ssl_sock_load_issuer_file_into_ckch(const char *path, char *buf, struct cert_key_and_chain *ckch, char **err)
3037{
3038 int ret = 1;
3039 BIO *in = NULL;
3040 X509 *issuer;
3041
3042 if (buf) {
3043 /* reading from a buffer */
3044 in = BIO_new_mem_buf(buf, -1);
3045 if (in == NULL) {
3046 memprintf(err, "%sCan't allocate memory\n", err && *err ? *err : "");
3047 goto end;
3048 }
3049
3050 } else {
3051 /* reading from a file */
3052 in = BIO_new(BIO_s_file());
3053 if (in == NULL)
3054 goto end;
3055
3056 if (BIO_read_filename(in, path) <= 0)
3057 goto end;
3058 }
3059
3060 issuer = PEM_read_bio_X509_AUX(in, NULL, NULL, NULL);
3061 if (!issuer) {
3062 memprintf(err, "%s'%s' cannot be read or parsed'.\n",
3063 *err ? *err : "", path);
3064 goto end;
3065 }
3066 ret = 0;
3067 ckch->ocsp_issuer = issuer;
3068
3069end:
3070
3071 ERR_clear_error();
3072 if (in)
3073 BIO_free(in);
3074
3075 return ret;
3076}
3077
William Lallemand96a9c972019-10-17 11:56:17 +02003078
3079/*
3080 * Try to load a PEM file from a <path> or a buffer <buf>
3081 * The PEM must contain at least a Private Key and a Certificate,
3082 * It could contain a DH and a certificate chain.
yanbzhu488a4d22015-12-01 15:16:07 -05003083 *
William Lallemand96a9c972019-10-17 11:56:17 +02003084 * If it failed you should not attempt to use the ckch but free it.
3085 *
3086 * Return 0 on success or != 0 on failure
yanbzhu488a4d22015-12-01 15:16:07 -05003087 */
William Lallemand96a9c972019-10-17 11:56:17 +02003088static 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 -05003089{
William Lallemandf11365b2019-09-19 14:25:58 +02003090 BIO *in = NULL;
yanbzhu488a4d22015-12-01 15:16:07 -05003091 int ret = 1;
William Lallemand96a9c972019-10-17 11:56:17 +02003092 X509 *ca = NULL;
3093 X509 *cert = NULL;
3094 EVP_PKEY *key = NULL;
3095 DH *dh;
3096
3097 if (buf) {
3098 /* reading from a buffer */
3099 in = BIO_new_mem_buf(buf, -1);
3100 if (in == NULL) {
3101 memprintf(err, "%sCan't allocate memory\n", err && *err ? *err : "");
3102 goto end;
3103 }
yanbzhu488a4d22015-12-01 15:16:07 -05003104
William Lallemand96a9c972019-10-17 11:56:17 +02003105 } else {
3106 /* reading from a file */
William Lallemandf11365b2019-09-19 14:25:58 +02003107 in = BIO_new(BIO_s_file());
3108 if (in == NULL)
3109 goto end;
yanbzhu488a4d22015-12-01 15:16:07 -05003110
William Lallemandf11365b2019-09-19 14:25:58 +02003111 if (BIO_read_filename(in, path) <= 0)
3112 goto end;
William Lallemandf11365b2019-09-19 14:25:58 +02003113 }
yanbzhu488a4d22015-12-01 15:16:07 -05003114
yanbzhu488a4d22015-12-01 15:16:07 -05003115 /* Read Private Key */
William Lallemand96a9c972019-10-17 11:56:17 +02003116 key = PEM_read_bio_PrivateKey(in, NULL, NULL, NULL);
3117 if (key == NULL) {
yanbzhu488a4d22015-12-01 15:16:07 -05003118 memprintf(err, "%sunable to load private key from file '%s'.\n",
William Lallemand96a9c972019-10-17 11:56:17 +02003119 err && *err ? *err : "", path);
yanbzhu488a4d22015-12-01 15:16:07 -05003120 goto end;
3121 }
3122
Emmanuel Hocdet54227d82019-07-30 17:04:01 +02003123#ifndef OPENSSL_NO_DH
William Lallemandfa892222019-07-23 16:06:08 +02003124 /* Seek back to beginning of file */
3125 if (BIO_reset(in) == -1) {
3126 memprintf(err, "%san error occurred while reading the file '%s'.\n",
3127 err && *err ? *err : "", path);
3128 goto end;
3129 }
3130
William Lallemand96a9c972019-10-17 11:56:17 +02003131 dh = PEM_read_bio_DHparams(in, NULL, NULL, NULL);
3132 /* no need to return an error there, dh is not mandatory */
3133
3134 if (dh) {
3135 if (ckch->dh)
3136 DH_free(ckch->dh);
3137 ckch->dh = dh;
3138 }
3139
Emmanuel Hocdet54227d82019-07-30 17:04:01 +02003140#endif
William Lallemandfa892222019-07-23 16:06:08 +02003141
Willy Tarreaubb137a82016-04-06 19:02:38 +02003142 /* Seek back to beginning of file */
Thierry FOURNIER / OZON.IOd44ea3f2016-10-14 00:49:21 +02003143 if (BIO_reset(in) == -1) {
3144 memprintf(err, "%san error occurred while reading the file '%s'.\n",
3145 err && *err ? *err : "", path);
3146 goto end;
3147 }
Willy Tarreaubb137a82016-04-06 19:02:38 +02003148
3149 /* Read Certificate */
William Lallemand96a9c972019-10-17 11:56:17 +02003150 cert = PEM_read_bio_X509_AUX(in, NULL, NULL, NULL);
3151 if (cert == NULL) {
Willy Tarreaubb137a82016-04-06 19:02:38 +02003152 memprintf(err, "%sunable to load certificate from file '%s'.\n",
William Lallemand96a9c972019-10-17 11:56:17 +02003153 err && *err ? *err : "", path);
Willy Tarreaubb137a82016-04-06 19:02:38 +02003154 goto end;
3155 }
3156
William Lallemand96a9c972019-10-17 11:56:17 +02003157 if (!X509_check_private_key(cert, key)) {
Emmanuel Hocdet03e09f32019-07-30 14:21:25 +02003158 memprintf(err, "%sinconsistencies between private key and certificate loaded from PEM file '%s'.\n",
William Lallemand96a9c972019-10-17 11:56:17 +02003159 err && *err ? *err : "", path);
Emmanuel Hocdet03e09f32019-07-30 14:21:25 +02003160 goto end;
3161 }
3162
William Lallemand96a9c972019-10-17 11:56:17 +02003163 /* Key and Cert are good, we can use them in the ckch */
3164 if (ckch->key) /* free the previous key */
3165 EVP_PKEY_free(ckch->key);
3166 ckch->key = key;
3167
3168 if (ckch->cert) /* free the previous cert */
3169 X509_free(ckch->cert);
3170 ckch->cert = cert;
3171
3172 /* Look for a Certificate Chain */
3173 ca = PEM_read_bio_X509(in, NULL, NULL, NULL);
3174 if (ca) {
3175 /* there is a chain a in the PEM, clean the previous one in the CKCH */
3176 if (ckch->chain) /* free the previous chain */
3177 sk_X509_pop_free(ckch->chain, X509_free);
3178 ckch->chain = sk_X509_new_null();
3179 if (!sk_X509_push(ckch->chain, ca)) {
3180 X509_free(ca);
3181 goto end;
3182 }
3183 }
3184 /* look for other crt in the chain */
Emmanuel Hocdet9246f8b2018-11-30 16:00:21 +01003185 while ((ca = PEM_read_bio_X509(in, NULL, NULL, NULL)))
3186 if (!sk_X509_push(ckch->chain, ca)) {
3187 X509_free(ca);
3188 goto end;
3189 }
yanbzhu488a4d22015-12-01 15:16:07 -05003190
yanbzhu488a4d22015-12-01 15:16:07 -05003191 ret = ERR_get_error();
3192 if (ret && (ERR_GET_LIB(ret) != ERR_LIB_PEM && ERR_GET_REASON(ret) != PEM_R_NO_START_LINE)) {
3193 memprintf(err, "%sunable to load certificate chain from file '%s'.\n",
William Lallemand96a9c972019-10-17 11:56:17 +02003194 err && *err ? *err : "", path);
yanbzhu488a4d22015-12-01 15:16:07 -05003195 goto end;
William Lallemand246c0242019-10-11 08:59:13 +02003196 }
3197
3198 ret = 0;
3199
William Lallemand96a9c972019-10-17 11:56:17 +02003200end:
William Lallemand246c0242019-10-11 08:59:13 +02003201
3202 ERR_clear_error();
William Lallemand96a9c972019-10-17 11:56:17 +02003203 if (in)
William Lallemand246c0242019-10-11 08:59:13 +02003204 BIO_free(in);
William Lallemand96a9c972019-10-17 11:56:17 +02003205 if (ret != 0) {
3206 if (key)
3207 EVP_PKEY_free(key);
3208 if (cert)
3209 X509_free(cert);
yanbzhu488a4d22015-12-01 15:16:07 -05003210 }
William Lallemanda17f4112019-10-10 15:16:44 +02003211
William Lallemand96a9c972019-10-17 11:56:17 +02003212 return ret;
3213}
3214
3215/*
3216 * Try to load in a ckch every files related to a ckch.
3217 * (PEM, sctl, ocsp, issuer etc.)
3218 *
3219 * This function is only used to load files during the configuration parsing,
3220 * it is not used with the CLI.
3221 *
3222 * This allows us to carry the contents of the file without having to read the
3223 * file multiple times. The caller must call
3224 * ssl_sock_free_cert_key_and_chain_contents.
3225 *
3226 * returns:
3227 * 0 on Success
3228 * 1 on SSL Failure
3229 */
3230static int ssl_sock_load_files_into_ckch(const char *path, struct cert_key_and_chain *ckch, char **err)
3231{
3232 int ret = 1;
3233
3234 /* try to load the PEM */
3235 if (ssl_sock_load_pem_into_ckch(path, NULL, ckch , err) != 0) {
3236 goto end;
3237 }
3238
William Lallemanda17f4112019-10-10 15:16:44 +02003239#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
3240 /* try to load the sctl file */
3241 {
3242 char fp[MAXPATHLEN+1];
3243 struct stat st;
3244
3245 snprintf(fp, MAXPATHLEN+1, "%s.sctl", path);
3246 if (stat(fp, &st) == 0) {
William Lallemand0dfae6c2019-10-16 18:06:58 +02003247 if (ssl_sock_load_sctl_from_file(fp, NULL, ckch, err)) {
William Lallemanda17f4112019-10-10 15:16:44 +02003248 memprintf(err, "%s '%s.sctl' is present but cannot be read or parsed'.\n",
3249 *err ? *err : "", fp);
3250 ret = 1;
3251 goto end;
3252 }
3253 }
3254 }
3255#endif
yanbzhu488a4d22015-12-01 15:16:07 -05003256
William Lallemand246c0242019-10-11 08:59:13 +02003257 /* try to load an ocsp response file */
3258 {
3259 char fp[MAXPATHLEN+1];
3260 struct stat st;
3261
3262 snprintf(fp, MAXPATHLEN+1, "%s.ocsp", path);
3263 if (stat(fp, &st) == 0) {
William Lallemand3b5f3602019-10-16 18:05:05 +02003264 if (ssl_sock_load_ocsp_response_from_file(fp, NULL, ckch, err)) {
William Lallemand246c0242019-10-11 08:59:13 +02003265 ret = 1;
3266 goto end;
3267 }
3268 }
3269 }
3270
3271 if (ckch->ocsp_response) {
3272 X509 *issuer;
3273 int i;
3274
3275 /* check if one of the certificate of the chain is the issuer */
3276 for (i = 0; i < sk_X509_num(ckch->chain); i++) {
3277 issuer = sk_X509_value(ckch->chain, i);
3278 if (X509_check_issued(issuer, ckch->cert) == X509_V_OK) {
3279 ckch->ocsp_issuer = issuer;
3280 break;
3281 } else
3282 issuer = NULL;
3283 }
3284
3285 /* if no issuer was found, try to load an issuer from the .issuer */
3286 if (!issuer) {
3287 struct stat st;
3288 char fp[MAXPATHLEN+1];
3289
3290 snprintf(fp, MAXPATHLEN+1, "%s.issuer", path);
3291 if (stat(fp, &st) == 0) {
William Lallemandf9568fc2019-10-16 18:27:58 +02003292 if (ssl_sock_load_issuer_file_into_ckch(fp, NULL, ckch, err)) {
William Lallemand246c0242019-10-11 08:59:13 +02003293 ret = 1;
3294 goto end;
3295 }
3296
3297 if (X509_check_issued(ckch->ocsp_issuer, ckch->cert) != X509_V_OK) {
William Lallemand786188f2019-10-15 10:05:37 +02003298 memprintf(err, "%s '%s' is not an issuer'.\n",
William Lallemand246c0242019-10-11 08:59:13 +02003299 *err ? *err : "", fp);
3300 ret = 1;
3301 goto end;
3302 }
3303 } else {
3304 memprintf(err, "%sNo issuer found, cannot use the OCSP response'.\n",
3305 *err ? *err : "");
3306 ret = 1;
3307 goto end;
3308 }
3309 }
3310 }
3311
yanbzhu488a4d22015-12-01 15:16:07 -05003312 ret = 0;
3313
3314end:
3315
3316 ERR_clear_error();
yanbzhu488a4d22015-12-01 15:16:07 -05003317
3318 /* Something went wrong in one of the reads */
3319 if (ret != 0)
3320 ssl_sock_free_cert_key_and_chain_contents(ckch);
3321
3322 return ret;
3323}
3324
3325/* Loads the info in ckch into ctx
Emeric Bruna96b5822019-10-17 13:25:14 +02003326 * Returns a bitfield containing the flags:
3327 * ERR_FATAL in any fatal error case
3328 * ERR_ALERT if the reason of the error is available in err
3329 * ERR_WARN if a warning is available into err
3330 * The value 0 means there is no error nor warning and
3331 * the operation succeed.
yanbzhu488a4d22015-12-01 15:16:07 -05003332 */
3333static int ssl_sock_put_ckch_into_ctx(const char *path, const struct cert_key_and_chain *ckch, SSL_CTX *ctx, char **err)
3334{
Emeric Bruna96b5822019-10-17 13:25:14 +02003335 int errcode = 0;
3336
yanbzhu488a4d22015-12-01 15:16:07 -05003337 if (SSL_CTX_use_PrivateKey(ctx, ckch->key) <= 0) {
3338 memprintf(err, "%sunable to load SSL private key into SSL Context '%s'.\n",
3339 err && *err ? *err : "", path);
Emeric Bruna96b5822019-10-17 13:25:14 +02003340 errcode |= ERR_ALERT | ERR_FATAL;
3341 return errcode;
yanbzhu488a4d22015-12-01 15:16:07 -05003342 }
3343
3344 if (!SSL_CTX_use_certificate(ctx, ckch->cert)) {
3345 memprintf(err, "%sunable to load SSL certificate into SSL Context '%s'.\n",
3346 err && *err ? *err : "", path);
Emeric Bruna96b5822019-10-17 13:25:14 +02003347 errcode |= ERR_ALERT | ERR_FATAL;
3348 goto end;
yanbzhu488a4d22015-12-01 15:16:07 -05003349 }
3350
yanbzhu488a4d22015-12-01 15:16:07 -05003351 /* Load all certs in the ckch into the ctx_chain for the ssl_ctx */
Emmanuel Hocdet1c65fdd2018-12-03 18:07:44 +01003352#ifdef SSL_CTX_set1_chain
Emmanuel Hocdet9246f8b2018-11-30 16:00:21 +01003353 if (!SSL_CTX_set1_chain(ctx, ckch->chain)) {
3354 memprintf(err, "%sunable to load chain certificate into SSL Context '%s'. Make sure you are linking against Openssl >= 1.0.2.\n",
3355 err && *err ? *err : "", path);
Emeric Bruna96b5822019-10-17 13:25:14 +02003356 errcode |= ERR_ALERT | ERR_FATAL;
3357 goto end;
yanbzhu488a4d22015-12-01 15:16:07 -05003358 }
Emmanuel Hocdet1c65fdd2018-12-03 18:07:44 +01003359#else
3360 { /* legacy compat (< openssl 1.0.2) */
3361 X509 *ca;
3362 while ((ca = sk_X509_shift(ckch->chain)))
3363 if (!SSL_CTX_add_extra_chain_cert(ctx, ca)) {
3364 memprintf(err, "%sunable to load chain certificate into SSL Context '%s'.\n",
3365 err && *err ? *err : "", path);
3366 X509_free(ca);
Emeric Bruna96b5822019-10-17 13:25:14 +02003367 errcode |= ERR_ALERT | ERR_FATAL;
3368 goto end;
Emmanuel Hocdet1c65fdd2018-12-03 18:07:44 +01003369 }
3370 }
3371#endif
yanbzhu488a4d22015-12-01 15:16:07 -05003372
William Lallemandfa892222019-07-23 16:06:08 +02003373#ifndef OPENSSL_NO_DH
3374 /* store a NULL pointer to indicate we have not yet loaded
3375 a custom DH param file */
3376 if (ssl_dh_ptr_index >= 0) {
3377 SSL_CTX_set_ex_data(ctx, ssl_dh_ptr_index, NULL);
3378 }
3379
Emeric Brun7a883362019-10-17 13:27:40 +02003380 errcode |= ssl_sock_load_dh_params(ctx, ckch, path, err);
3381 if (errcode & ERR_CODE) {
William Lallemandfa892222019-07-23 16:06:08 +02003382 memprintf(err, "%sunable to load DH parameters from file '%s'.\n",
3383 err && *err ? *err : "", path);
Emeric Bruna96b5822019-10-17 13:25:14 +02003384 goto end;
William Lallemandfa892222019-07-23 16:06:08 +02003385 }
3386#endif
3387
William Lallemanda17f4112019-10-10 15:16:44 +02003388#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
3389 if (sctl_ex_index >= 0 && ckch->sctl) {
3390 if (ssl_sock_load_sctl(ctx, ckch->sctl) < 0) {
3391 memprintf(err, "%s '%s.sctl' is present but cannot be read or parsed'.\n",
3392 *err ? *err : "", path);
Emeric Bruna96b5822019-10-17 13:25:14 +02003393 errcode |= ERR_ALERT | ERR_FATAL;
3394 goto end;
William Lallemanda17f4112019-10-10 15:16:44 +02003395 }
3396 }
3397#endif
3398
William Lallemand4a660132019-10-14 14:51:41 +02003399#if ((defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP) || defined OPENSSL_IS_BORINGSSL)
William Lallemand246c0242019-10-11 08:59:13 +02003400 /* Load OCSP Info into context */
3401 if (ckch->ocsp_response) {
3402 if (ssl_sock_load_ocsp(ctx, ckch) < 0) {
3403 if (err)
3404 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",
3405 *err ? *err : "", path);
Emeric Bruna96b5822019-10-17 13:25:14 +02003406 errcode |= ERR_ALERT | ERR_FATAL;
3407 goto end;
William Lallemand246c0242019-10-11 08:59:13 +02003408 }
3409 }
William Lallemand246c0242019-10-11 08:59:13 +02003410#endif
3411
Emeric Bruna96b5822019-10-17 13:25:14 +02003412 end:
3413 return errcode;
yanbzhu488a4d22015-12-01 15:16:07 -05003414}
3415
William Lallemandc4ecddf2019-07-31 16:50:08 +02003416#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
yanbzhu08ce6ab2015-12-02 13:01:29 -05003417
William Lallemand28a8fce2019-10-04 17:36:55 +02003418static int ssl_sock_populate_sni_keytypes_hplr(const char *str, struct eb_root *sni_keytypes, int key_index)
yanbzhu08ce6ab2015-12-02 13:01:29 -05003419{
3420 struct sni_keytype *s_kt = NULL;
3421 struct ebmb_node *node;
3422 int i;
3423
3424 for (i = 0; i < trash.size; i++) {
3425 if (!str[i])
3426 break;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02003427 trash.area[i] = tolower(str[i]);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003428 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +02003429 trash.area[i] = 0;
3430 node = ebst_lookup(sni_keytypes, trash.area);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003431 if (!node) {
3432 /* CN not found in tree */
3433 s_kt = malloc(sizeof(struct sni_keytype) + i + 1);
3434 /* Using memcpy here instead of strncpy.
3435 * strncpy will cause sig_abrt errors under certain versions of gcc with -O2
3436 * See: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=60792
3437 */
William Lallemand28a8fce2019-10-04 17:36:55 +02003438 if (!s_kt)
3439 return -1;
3440
Willy Tarreau843b7cb2018-07-13 10:54:26 +02003441 memcpy(s_kt->name.key, trash.area, i+1);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003442 s_kt->keytypes = 0;
3443 ebst_insert(sni_keytypes, &s_kt->name);
3444 } else {
3445 /* CN found in tree */
3446 s_kt = container_of(node, struct sni_keytype, name);
3447 }
3448
3449 /* Mark that this CN has the keytype of key_index via keytypes mask */
3450 s_kt->keytypes |= 1<<key_index;
3451
William Lallemand28a8fce2019-10-04 17:36:55 +02003452 return 0;
3453
yanbzhu08ce6ab2015-12-02 13:01:29 -05003454}
3455
William Lallemandc4ecddf2019-07-31 16:50:08 +02003456#endif
3457
William Lallemand36b84632019-07-18 19:28:17 +02003458/*
William Lallemande3af8fb2019-10-08 11:36:53 +02003459 * lookup a path into the ckchs tree.
William Lallemand6af03992019-07-23 15:00:54 +02003460 */
William Lallemande3af8fb2019-10-08 11:36:53 +02003461static inline struct ckch_store *ckchs_lookup(char *path)
William Lallemand6af03992019-07-23 15:00:54 +02003462{
3463 struct ebmb_node *eb;
3464
William Lallemande3af8fb2019-10-08 11:36:53 +02003465 eb = ebst_lookup(&ckchs_tree, path);
William Lallemand6af03992019-07-23 15:00:54 +02003466 if (!eb)
3467 return NULL;
3468
William Lallemande3af8fb2019-10-08 11:36:53 +02003469 return ebmb_entry(eb, struct ckch_store, node);
William Lallemand6af03992019-07-23 15:00:54 +02003470}
3471
3472/*
William Lallemande3af8fb2019-10-08 11:36:53 +02003473 * This function allocate a ckch_store and populate it with certificates from files.
William Lallemand36b84632019-07-18 19:28:17 +02003474 */
William Lallemande3af8fb2019-10-08 11:36:53 +02003475static struct ckch_store *ckchs_load_cert_file(char *path, int multi, char **err)
William Lallemand36b84632019-07-18 19:28:17 +02003476{
William Lallemande3af8fb2019-10-08 11:36:53 +02003477 struct ckch_store *ckchs;
William Lallemand36b84632019-07-18 19:28:17 +02003478
William Lallemande3af8fb2019-10-08 11:36:53 +02003479 ckchs = calloc(1, sizeof(*ckchs) + strlen(path) + 1);
3480 if (!ckchs) {
William Lallemand36b84632019-07-18 19:28:17 +02003481 memprintf(err, "%sunable to allocate memory.\n", err && *err ? *err : "");
3482 goto end;
3483 }
William Lallemande3af8fb2019-10-08 11:36:53 +02003484 ckchs->ckch = calloc(1, sizeof(*ckchs->ckch) * (multi ? SSL_SOCK_NUM_KEYTYPES : 1));
William Lallemand36b84632019-07-18 19:28:17 +02003485
William Lallemande3af8fb2019-10-08 11:36:53 +02003486 if (!ckchs->ckch) {
William Lallemand36b84632019-07-18 19:28:17 +02003487 memprintf(err, "%sunable to allocate memory.\n", err && *err ? *err : "");
3488 goto end;
3489 }
3490
William Lallemand9117de92019-10-04 00:29:42 +02003491 LIST_INIT(&ckchs->ckch_inst);
3492
William Lallemand36b84632019-07-18 19:28:17 +02003493 if (!multi) {
3494
William Lallemand96a9c972019-10-17 11:56:17 +02003495 if (ssl_sock_load_files_into_ckch(path, ckchs->ckch, err) == 1)
William Lallemand36b84632019-07-18 19:28:17 +02003496 goto end;
3497
William Lallemande3af8fb2019-10-08 11:36:53 +02003498 /* insert into the ckchs tree */
3499 memcpy(ckchs->path, path, strlen(path) + 1);
3500 ebst_insert(&ckchs_tree, &ckchs->node);
William Lallemand36b84632019-07-18 19:28:17 +02003501 } else {
3502 int found = 0;
William Lallemandc4ecddf2019-07-31 16:50:08 +02003503#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
3504 char fp[MAXPATHLEN+1] = {0};
3505 int n = 0;
William Lallemand36b84632019-07-18 19:28:17 +02003506
3507 /* Load all possible certs and keys */
3508 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
3509 struct stat buf;
3510 snprintf(fp, sizeof(fp), "%s.%s", path, SSL_SOCK_KEYTYPE_NAMES[n]);
3511 if (stat(fp, &buf) == 0) {
William Lallemand96a9c972019-10-17 11:56:17 +02003512 if (ssl_sock_load_files_into_ckch(fp, &ckchs->ckch[n], err) == 1)
William Lallemand36b84632019-07-18 19:28:17 +02003513 goto end;
3514 found = 1;
William Lallemande3af8fb2019-10-08 11:36:53 +02003515 ckchs->multi = 1;
William Lallemand36b84632019-07-18 19:28:17 +02003516 }
3517 }
William Lallemandc4ecddf2019-07-31 16:50:08 +02003518#endif
William Lallemand36b84632019-07-18 19:28:17 +02003519
3520 if (!found) {
William Lallemand6e5f2ce2019-08-01 14:43:20 +02003521 memprintf(err, "%sDidn't find any certificate for bundle '%s'.\n", err && *err ? *err : "", path);
William Lallemand36b84632019-07-18 19:28:17 +02003522 goto end;
3523 }
William Lallemande3af8fb2019-10-08 11:36:53 +02003524 /* insert into the ckchs tree */
3525 memcpy(ckchs->path, path, strlen(path) + 1);
3526 ebst_insert(&ckchs_tree, &ckchs->node);
William Lallemand36b84632019-07-18 19:28:17 +02003527 }
William Lallemande3af8fb2019-10-08 11:36:53 +02003528 return ckchs;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003529
William Lallemand36b84632019-07-18 19:28:17 +02003530end:
William Lallemande3af8fb2019-10-08 11:36:53 +02003531 if (ckchs) {
3532 free(ckchs->ckch);
3533 ebmb_delete(&ckchs->node);
William Lallemand6af03992019-07-23 15:00:54 +02003534 }
3535
William Lallemande3af8fb2019-10-08 11:36:53 +02003536 free(ckchs);
William Lallemand36b84632019-07-18 19:28:17 +02003537
3538 return NULL;
3539}
3540
William Lallemandc4ecddf2019-07-31 16:50:08 +02003541#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
3542
William Lallemand36b84632019-07-18 19:28:17 +02003543/*
William Lallemande3af8fb2019-10-08 11:36:53 +02003544 * Take a ckch_store which contains a multi-certificate bundle.
William Lallemand36b84632019-07-18 19:28:17 +02003545 * Group these certificates into a set of SSL_CTX*
yanbzhu08ce6ab2015-12-02 13:01:29 -05003546 * based on shared and unique CN and SAN entries. Add these SSL_CTX* to the SNI tree.
3547 *
Joseph Herlant017b3da2018-11-15 09:07:59 -08003548 * This will allow the user to explicitly group multiple cert/keys for a single purpose
yanbzhu08ce6ab2015-12-02 13:01:29 -05003549 *
Emeric Brun054563d2019-10-17 13:16:58 +02003550 * Returns a bitfield containing the flags:
3551 * ERR_FATAL in any fatal error case
3552 * ERR_ALERT if the reason of the error is available in err
3553 * ERR_WARN if a warning is available into err
William Lallemand36b84632019-07-18 19:28:17 +02003554 *
yanbzhu08ce6ab2015-12-02 13:01:29 -05003555 */
Emeric Brun054563d2019-10-17 13:16:58 +02003556static int ckch_inst_new_load_multi_store(const char *path, struct ckch_store *ckchs,
3557 struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
3558 char **sni_filter, int fcount, struct ckch_inst **ckchi, char **err)
yanbzhu08ce6ab2015-12-02 13:01:29 -05003559{
William Lallemand36b84632019-07-18 19:28:17 +02003560 int i = 0, n = 0;
3561 struct cert_key_and_chain *certs_and_keys;
William Lallemand4b989f22019-10-04 18:36:55 +02003562 struct eb_root sni_keytypes_map = EB_ROOT;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003563 struct ebmb_node *node;
3564 struct ebmb_node *next;
3565 /* Array of SSL_CTX pointers corresponding to each possible combo
3566 * of keytypes
3567 */
3568 struct key_combo_ctx key_combos[SSL_SOCK_POSSIBLE_KT_COMBOS] = { {0} };
Emeric Brun054563d2019-10-17 13:16:58 +02003569 int errcode = 0;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003570 X509_NAME *xname = NULL;
3571 char *str = NULL;
3572#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
3573 STACK_OF(GENERAL_NAME) *names = NULL;
3574#endif
William Lallemand614ca0d2019-10-07 13:52:11 +02003575 struct ckch_inst *ckch_inst;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003576
Emeric Brun054563d2019-10-17 13:16:58 +02003577 *ckchi = NULL;
3578
William Lallemande3af8fb2019-10-08 11:36:53 +02003579 if (!ckchs || !ckchs->ckch || !ckchs->multi) {
William Lallemand36b84632019-07-18 19:28:17 +02003580 memprintf(err, "%sunable to load SSL certificate file '%s' file does not exist.\n",
3581 err && *err ? *err : "", path);
Emeric Brun054563d2019-10-17 13:16:58 +02003582 return ERR_ALERT | ERR_FATAL;
William Lallemand614ca0d2019-10-07 13:52:11 +02003583 }
3584
3585 ckch_inst = ckch_inst_new();
3586 if (!ckch_inst) {
3587 memprintf(err, "%sunable to allocate SSL context for cert '%s'.\n",
3588 err && *err ? *err : "", path);
Emeric Brun054563d2019-10-17 13:16:58 +02003589 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemand614ca0d2019-10-07 13:52:11 +02003590 goto end;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003591 }
3592
William Lallemande3af8fb2019-10-08 11:36:53 +02003593 certs_and_keys = ckchs->ckch;
William Lallemand36b84632019-07-18 19:28:17 +02003594
William Lallemand150bfa82019-09-19 17:12:49 +02003595 /* at least one of the instances is using filters during the config
3596 * parsing, that's ok to inherit this during loading on CLI */
3597 ckchs->filters = !!fcount;
3598
yanbzhu08ce6ab2015-12-02 13:01:29 -05003599 /* Process each ckch and update keytypes for each CN/SAN
3600 * for example, if CN/SAN www.a.com is associated with
3601 * certs with keytype 0 and 2, then at the end of the loop,
3602 * www.a.com will have:
3603 * keyindex = 0 | 1 | 4 = 5
3604 */
3605 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
William Lallemand28a8fce2019-10-04 17:36:55 +02003606 int ret;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003607
3608 if (!ssl_sock_is_ckch_valid(&certs_and_keys[n]))
3609 continue;
3610
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003611 if (fcount) {
William Lallemand28a8fce2019-10-04 17:36:55 +02003612 for (i = 0; i < fcount; i++) {
3613 ret = ssl_sock_populate_sni_keytypes_hplr(sni_filter[i], &sni_keytypes_map, n);
3614 if (ret < 0) {
3615 memprintf(err, "%sunable to allocate SSL context.\n",
3616 err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02003617 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemand28a8fce2019-10-04 17:36:55 +02003618 goto end;
3619 }
3620 }
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003621 } else {
3622 /* A lot of the following code is OpenSSL boilerplate for processing CN's and SAN's,
3623 * so the line that contains logic is marked via comments
3624 */
3625 xname = X509_get_subject_name(certs_and_keys[n].cert);
3626 i = -1;
3627 while ((i = X509_NAME_get_index_by_NID(xname, NID_commonName, i)) != -1) {
3628 X509_NAME_ENTRY *entry = X509_NAME_get_entry(xname, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003629 ASN1_STRING *value;
3630 value = X509_NAME_ENTRY_get_data(entry);
3631 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003632 /* Important line is here */
William Lallemand28a8fce2019-10-04 17:36:55 +02003633 ret = ssl_sock_populate_sni_keytypes_hplr(str, &sni_keytypes_map, n);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003634
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003635 OPENSSL_free(str);
3636 str = NULL;
William Lallemand28a8fce2019-10-04 17:36:55 +02003637 if (ret < 0) {
3638 memprintf(err, "%sunable to allocate SSL context.\n",
3639 err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02003640 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemand28a8fce2019-10-04 17:36:55 +02003641 goto end;
3642 }
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003643 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003644 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003645
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003646 /* Do the above logic for each SAN */
yanbzhu08ce6ab2015-12-02 13:01:29 -05003647#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003648 names = X509_get_ext_d2i(certs_and_keys[n].cert, NID_subject_alt_name, NULL, NULL);
3649 if (names) {
3650 for (i = 0; i < sk_GENERAL_NAME_num(names); i++) {
3651 GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003652
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003653 if (name->type == GEN_DNS) {
3654 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
3655 /* Important line is here */
William Lallemand28a8fce2019-10-04 17:36:55 +02003656 ret = ssl_sock_populate_sni_keytypes_hplr(str, &sni_keytypes_map, n);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003657
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003658 OPENSSL_free(str);
3659 str = NULL;
William Lallemand28a8fce2019-10-04 17:36:55 +02003660 if (ret < 0) {
3661 memprintf(err, "%sunable to allocate SSL context.\n",
3662 err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02003663 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemand28a8fce2019-10-04 17:36:55 +02003664 goto end;
3665 }
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003666 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003667 }
3668 }
3669 }
3670 }
3671#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
3672 }
3673
3674 /* If no files found, return error */
3675 if (eb_is_empty(&sni_keytypes_map)) {
3676 memprintf(err, "%sunable to load SSL certificate file '%s' file does not exist.\n",
3677 err && *err ? *err : "", path);
Emeric Brun054563d2019-10-17 13:16:58 +02003678 errcode |= ERR_ALERT | ERR_FATAL;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003679 goto end;
3680 }
3681
3682 /* We now have a map of CN/SAN to keytypes that are loaded in
3683 * Iterate through the map to create the SSL_CTX's (if needed)
3684 * and add each CTX to the SNI tree
3685 *
3686 * Some math here:
Joseph Herlant017b3da2018-11-15 09:07:59 -08003687 * There are 2^n - 1 possible combinations, each unique
yanbzhu08ce6ab2015-12-02 13:01:29 -05003688 * combination is denoted by the key in the map. Each key
3689 * has a value between 1 and 2^n - 1. Conveniently, the array
3690 * of SSL_CTX* is sized 2^n. So, we can simply use the i'th
3691 * entry in the array to correspond to the unique combo (key)
3692 * associated with i. This unique key combo (i) will be associated
3693 * with combos[i-1]
3694 */
3695
3696 node = ebmb_first(&sni_keytypes_map);
3697 while (node) {
3698 SSL_CTX *cur_ctx;
Bertrand Jacquin33423092016-11-13 16:37:13 +00003699 char cur_file[MAXPATHLEN+1];
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003700 const struct pkey_info kinfo = { .sig = TLSEXT_signature_anonymous, .bits = 0 };
yanbzhu08ce6ab2015-12-02 13:01:29 -05003701
3702 str = (char *)container_of(node, struct sni_keytype, name)->name.key;
3703 i = container_of(node, struct sni_keytype, name)->keytypes;
3704 cur_ctx = key_combos[i-1].ctx;
3705
3706 if (cur_ctx == NULL) {
3707 /* need to create SSL_CTX */
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003708 cur_ctx = SSL_CTX_new(SSLv23_server_method());
yanbzhu08ce6ab2015-12-02 13:01:29 -05003709 if (cur_ctx == NULL) {
3710 memprintf(err, "%sunable to allocate SSL context.\n",
3711 err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02003712 errcode |= ERR_ALERT | ERR_FATAL;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003713 goto end;
3714 }
3715
yanbzhube2774d2015-12-10 15:07:30 -05003716 /* Load all required certs/keys/chains/OCSPs info into SSL_CTX */
yanbzhu08ce6ab2015-12-02 13:01:29 -05003717 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
3718 if (i & (1<<n)) {
3719 /* Key combo contains ckch[n] */
Bertrand Jacquin33423092016-11-13 16:37:13 +00003720 snprintf(cur_file, MAXPATHLEN+1, "%s.%s", path, SSL_SOCK_KEYTYPE_NAMES[n]);
Emeric Bruna96b5822019-10-17 13:25:14 +02003721 errcode |= ssl_sock_put_ckch_into_ctx(cur_file, &certs_and_keys[n], cur_ctx, err);
3722 if (errcode & ERR_CODE)
yanbzhu08ce6ab2015-12-02 13:01:29 -05003723 goto end;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003724 }
3725 }
3726
yanbzhu08ce6ab2015-12-02 13:01:29 -05003727 /* Update key_combos */
3728 key_combos[i-1].ctx = cur_ctx;
3729 }
3730
3731 /* Update SNI Tree */
William Lallemand9117de92019-10-04 00:29:42 +02003732
William Lallemand1d29c742019-10-04 00:53:29 +02003733 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 +02003734 kinfo, str, key_combos[i-1].order);
3735 if (key_combos[i-1].order < 0) {
3736 memprintf(err, "%sunable to create a sni context.\n", err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02003737 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemandfe49bb32019-10-03 23:46:33 +02003738 goto end;
3739 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003740 node = ebmb_next(node);
3741 }
3742
3743
3744 /* Mark a default context if none exists, using the ctx that has the most shared keys */
3745 if (!bind_conf->default_ctx) {
3746 for (i = SSL_SOCK_POSSIBLE_KT_COMBOS - 1; i >= 0; i--) {
3747 if (key_combos[i].ctx) {
3748 bind_conf->default_ctx = key_combos[i].ctx;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003749 bind_conf->default_ssl_conf = ssl_conf;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003750 break;
3751 }
3752 }
3753 }
3754
William Lallemand614ca0d2019-10-07 13:52:11 +02003755 ckch_inst->bind_conf = bind_conf;
William Lallemand150bfa82019-09-19 17:12:49 +02003756 ckch_inst->ssl_conf = ssl_conf;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003757end:
3758
3759 if (names)
3760 sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
3761
yanbzhu08ce6ab2015-12-02 13:01:29 -05003762 node = ebmb_first(&sni_keytypes_map);
3763 while (node) {
3764 next = ebmb_next(node);
3765 ebmb_delete(node);
William Lallemand8ed5b962019-10-04 17:24:39 +02003766 free(ebmb_entry(node, struct sni_keytype, name));
yanbzhu08ce6ab2015-12-02 13:01:29 -05003767 node = next;
3768 }
3769
Emeric Brun054563d2019-10-17 13:16:58 +02003770 if (errcode & ERR_CODE && ckch_inst) {
William Lallemand0c6d12f2019-10-04 18:38:51 +02003771 struct sni_ctx *sc0, *sc0b;
3772
3773 /* free the SSL_CTX in case of error */
3774 for (i = 0; i < SSL_SOCK_POSSIBLE_KT_COMBOS; i++) {
3775 if (key_combos[i].ctx)
3776 SSL_CTX_free(key_combos[i].ctx);
3777 }
3778
3779 /* free the sni_ctx in case of error */
3780 list_for_each_entry_safe(sc0, sc0b, &ckch_inst->sni_ctx, by_ckch_inst) {
3781
3782 ebmb_delete(&sc0->name);
3783 LIST_DEL(&sc0->by_ckch_inst);
3784 free(sc0);
3785 }
William Lallemand614ca0d2019-10-07 13:52:11 +02003786 free(ckch_inst);
3787 ckch_inst = NULL;
William Lallemand0c6d12f2019-10-04 18:38:51 +02003788 }
3789
Emeric Brun054563d2019-10-17 13:16:58 +02003790 *ckchi = ckch_inst;
3791 return errcode;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003792}
3793#else
3794/* This is a dummy, that just logs an error and returns error */
Emeric Brun054563d2019-10-17 13:16:58 +02003795static int ckch_inst_new_load_multi_store(const char *path, struct ckch_store *ckchs,
3796 struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
3797 char **sni_filter, int fcount, struct ckch_inst **ckchi, char **err)
yanbzhu08ce6ab2015-12-02 13:01:29 -05003798{
3799 memprintf(err, "%sunable to stat SSL certificate from file '%s' : %s.\n",
3800 err && *err ? *err : "", path, strerror(errno));
Emeric Brun054563d2019-10-17 13:16:58 +02003801 return ERR_ALERT | ERR_FATAL;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003802}
3803
Willy Tarreau9a1ab082019-05-09 13:26:41 +02003804#endif /* #if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL: Support for loading multiple certs into a single SSL_CTX */
yanbzhu488a4d22015-12-01 15:16:07 -05003805
William Lallemand614ca0d2019-10-07 13:52:11 +02003806/*
3807 * This function allocate a ckch_inst and create its snis
Emeric Brun054563d2019-10-17 13:16:58 +02003808 *
3809 * Returns a bitfield containing the flags:
3810 * ERR_FATAL in any fatal error case
3811 * ERR_ALERT if the reason of the error is available in err
3812 * ERR_WARN if a warning is available into err
William Lallemand614ca0d2019-10-07 13:52:11 +02003813 */
Emeric Brun054563d2019-10-17 13:16:58 +02003814static int ckch_inst_new_load_store(const char *path, struct ckch_store *ckchs, struct bind_conf *bind_conf,
3815 struct ssl_bind_conf *ssl_conf, char **sni_filter, int fcount, struct ckch_inst **ckchi, char **err)
Emeric Brunfc0421f2012-09-07 17:30:07 +02003816{
William Lallemandc9402072019-05-15 15:33:54 +02003817 SSL_CTX *ctx;
William Lallemandc9402072019-05-15 15:33:54 +02003818 int i;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003819 int order = 0;
3820 X509_NAME *xname;
3821 char *str;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003822 EVP_PKEY *pkey;
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003823 struct pkey_info kinfo = { .sig = TLSEXT_signature_anonymous, .bits = 0 };
Emeric Brunfc0421f2012-09-07 17:30:07 +02003824#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
3825 STACK_OF(GENERAL_NAME) *names;
3826#endif
William Lallemand36b84632019-07-18 19:28:17 +02003827 struct cert_key_and_chain *ckch;
William Lallemand614ca0d2019-10-07 13:52:11 +02003828 struct ckch_inst *ckch_inst = NULL;
Emeric Brun054563d2019-10-17 13:16:58 +02003829 int errcode = 0;
3830
3831 *ckchi = NULL;
William Lallemanda59191b2019-05-15 16:08:56 +02003832
William Lallemande3af8fb2019-10-08 11:36:53 +02003833 if (!ckchs || !ckchs->ckch)
Emeric Brun054563d2019-10-17 13:16:58 +02003834 return ERR_FATAL;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003835
William Lallemande3af8fb2019-10-08 11:36:53 +02003836 ckch = ckchs->ckch;
William Lallemand36b84632019-07-18 19:28:17 +02003837
William Lallemand150bfa82019-09-19 17:12:49 +02003838 /* at least one of the instances is using filters during the config
3839 * parsing, that's ok to inherit this during loading on CLI */
3840 ckchs->filters = !!fcount;
3841
William Lallemandc9402072019-05-15 15:33:54 +02003842 ctx = SSL_CTX_new(SSLv23_server_method());
3843 if (!ctx) {
3844 memprintf(err, "%sunable to allocate SSL context for cert '%s'.\n",
3845 err && *err ? *err : "", path);
Emeric Brun054563d2019-10-17 13:16:58 +02003846 errcode |= ERR_ALERT | ERR_FATAL;
3847 goto error;
William Lallemandc9402072019-05-15 15:33:54 +02003848 }
3849
Emeric Bruna96b5822019-10-17 13:25:14 +02003850 errcode |= ssl_sock_put_ckch_into_ctx(path, ckch, ctx, err);
3851 if (errcode & ERR_CODE)
William Lallemand614ca0d2019-10-07 13:52:11 +02003852 goto error;
William Lallemand614ca0d2019-10-07 13:52:11 +02003853
3854 ckch_inst = ckch_inst_new();
3855 if (!ckch_inst) {
3856 memprintf(err, "%sunable to allocate SSL context for cert '%s'.\n",
3857 err && *err ? *err : "", path);
Emeric Brun054563d2019-10-17 13:16:58 +02003858 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemandd9199372019-10-04 15:37:05 +02003859 goto error;
William Lallemandc9402072019-05-15 15:33:54 +02003860 }
3861
William Lallemand36b84632019-07-18 19:28:17 +02003862 pkey = X509_get_pubkey(ckch->cert);
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003863 if (pkey) {
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003864 kinfo.bits = EVP_PKEY_bits(pkey);
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003865 switch(EVP_PKEY_base_id(pkey)) {
3866 case EVP_PKEY_RSA:
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003867 kinfo.sig = TLSEXT_signature_rsa;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003868 break;
3869 case EVP_PKEY_EC:
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003870 kinfo.sig = TLSEXT_signature_ecdsa;
3871 break;
3872 case EVP_PKEY_DSA:
3873 kinfo.sig = TLSEXT_signature_dsa;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003874 break;
3875 }
3876 EVP_PKEY_free(pkey);
3877 }
3878
Emeric Brun50bcecc2013-04-22 13:05:23 +02003879 if (fcount) {
William Lallemandfe49bb32019-10-03 23:46:33 +02003880 while (fcount--) {
William Lallemand1d29c742019-10-04 00:53:29 +02003881 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 +02003882 if (order < 0) {
3883 memprintf(err, "%sunable to create a sni context.\n", err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02003884 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemandd9199372019-10-04 15:37:05 +02003885 goto error;
William Lallemandfe49bb32019-10-03 23:46:33 +02003886 }
3887 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003888 }
3889 else {
Emeric Brunfc0421f2012-09-07 17:30:07 +02003890#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
William Lallemand36b84632019-07-18 19:28:17 +02003891 names = X509_get_ext_d2i(ckch->cert, NID_subject_alt_name, NULL, NULL);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003892 if (names) {
3893 for (i = 0; i < sk_GENERAL_NAME_num(names); i++) {
3894 GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i);
3895 if (name->type == GEN_DNS) {
3896 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
William Lallemand1d29c742019-10-04 00:53:29 +02003897 order = ckch_inst_add_cert_sni(ctx, ckch_inst, bind_conf, ssl_conf, kinfo, str, order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003898 OPENSSL_free(str);
William Lallemandfe49bb32019-10-03 23:46:33 +02003899 if (order < 0) {
3900 memprintf(err, "%sunable to create a sni context.\n", err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02003901 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemandd9199372019-10-04 15:37:05 +02003902 goto error;
William Lallemandfe49bb32019-10-03 23:46:33 +02003903 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003904 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003905 }
3906 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003907 sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003908 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003909#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
William Lallemand36b84632019-07-18 19:28:17 +02003910 xname = X509_get_subject_name(ckch->cert);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003911 i = -1;
3912 while ((i = X509_NAME_get_index_by_NID(xname, NID_commonName, i)) != -1) {
3913 X509_NAME_ENTRY *entry = X509_NAME_get_entry(xname, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003914 ASN1_STRING *value;
3915
3916 value = X509_NAME_ENTRY_get_data(entry);
3917 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
William Lallemand1d29c742019-10-04 00:53:29 +02003918 order = ckch_inst_add_cert_sni(ctx, ckch_inst, bind_conf, ssl_conf, kinfo, str, order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003919 OPENSSL_free(str);
William Lallemandfe49bb32019-10-03 23:46:33 +02003920 if (order < 0) {
3921 memprintf(err, "%sunable to create a sni context.\n", err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02003922 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemandd9199372019-10-04 15:37:05 +02003923 goto error;
William Lallemandfe49bb32019-10-03 23:46:33 +02003924 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003925 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003926 }
3927 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003928 /* we must not free the SSL_CTX anymore below, since it's already in
3929 * the tree, so it will be discovered and cleaned in time.
3930 */
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02003931
Emeric Brunfc0421f2012-09-07 17:30:07 +02003932#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
Willy Tarreau2a65ff02012-09-13 17:54:29 +02003933 if (bind_conf->default_ctx) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02003934 memprintf(err, "%sthis version of openssl cannot load multiple SSL certificates.\n",
3935 err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02003936 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemandd9199372019-10-04 15:37:05 +02003937 goto error;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003938 }
3939#endif
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003940 if (!bind_conf->default_ctx) {
Willy Tarreau2a65ff02012-09-13 17:54:29 +02003941 bind_conf->default_ctx = ctx;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003942 bind_conf->default_ssl_conf = ssl_conf;
3943 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003944
William Lallemand9117de92019-10-04 00:29:42 +02003945 /* everything succeed, the ckch instance can be used */
3946 ckch_inst->bind_conf = bind_conf;
William Lallemand150bfa82019-09-19 17:12:49 +02003947 ckch_inst->ssl_conf = ssl_conf;
William Lallemand9117de92019-10-04 00:29:42 +02003948
Emeric Brun054563d2019-10-17 13:16:58 +02003949 *ckchi = ckch_inst;
3950 return errcode;
William Lallemandd9199372019-10-04 15:37:05 +02003951
3952error:
3953 /* free the allocated sni_ctxs */
William Lallemand614ca0d2019-10-07 13:52:11 +02003954 if (ckch_inst) {
William Lallemandd9199372019-10-04 15:37:05 +02003955 struct sni_ctx *sc0, *sc0b;
3956
3957 list_for_each_entry_safe(sc0, sc0b, &ckch_inst->sni_ctx, by_ckch_inst) {
3958
3959 ebmb_delete(&sc0->name);
3960 LIST_DEL(&sc0->by_ckch_inst);
3961 free(sc0);
3962 }
William Lallemand614ca0d2019-10-07 13:52:11 +02003963 free(ckch_inst);
3964 ckch_inst = NULL;
William Lallemandd9199372019-10-04 15:37:05 +02003965 }
3966 /* We only created 1 SSL_CTX so we can free it there */
3967 SSL_CTX_free(ctx);
3968
Emeric Brun054563d2019-10-17 13:16:58 +02003969 return errcode;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003970}
3971
Willy Tarreau8c5414a2019-10-16 17:06:25 +02003972/* Returns a set of ERR_* flags possibly with an error in <err>. */
William Lallemand614ca0d2019-10-07 13:52:11 +02003973static int ssl_sock_load_ckchs(const char *path, struct ckch_store *ckchs,
3974 struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
3975 char **sni_filter, int fcount, char **err)
3976{
3977 struct ckch_inst *ckch_inst = NULL;
Emeric Brun054563d2019-10-17 13:16:58 +02003978 int errcode = 0;
William Lallemand614ca0d2019-10-07 13:52:11 +02003979
3980 /* we found the ckchs in the tree, we can use it directly */
3981 if (ckchs->multi)
Emeric Brun054563d2019-10-17 13:16:58 +02003982 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 +02003983 else
Emeric Brun054563d2019-10-17 13:16:58 +02003984 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 +02003985
Emeric Brun054563d2019-10-17 13:16:58 +02003986 if (errcode & ERR_CODE)
3987 return errcode;
William Lallemand614ca0d2019-10-07 13:52:11 +02003988
3989 ssl_sock_load_cert_sni(ckch_inst, bind_conf);
3990
3991 /* succeed, add the instance to the ckch_store's list of instance */
3992 LIST_ADDQ(&ckchs->ckch_inst, &ckch_inst->by_ckchs);
Emeric Brun054563d2019-10-17 13:16:58 +02003993 return errcode;
William Lallemand614ca0d2019-10-07 13:52:11 +02003994}
3995
3996
Willy Tarreaubbc91962019-10-16 16:42:19 +02003997/* Returns a set of ERR_* flags possibly with an error in <err>. */
Willy Tarreau03209342016-12-22 17:08:28 +01003998int ssl_sock_load_cert(char *path, struct bind_conf *bind_conf, char **err)
Emeric Brunfc0421f2012-09-07 17:30:07 +02003999{
Cyril Bonté3180f7b2015-01-25 00:16:08 +01004000 struct dirent **de_list;
4001 int i, n;
Emeric Brunfc0421f2012-09-07 17:30:07 +02004002 DIR *dir;
4003 struct stat buf;
Willy Tarreauee2663b2012-12-06 11:36:59 +01004004 char *end;
4005 char fp[MAXPATHLEN+1];
Emeric Brunfc0421f2012-09-07 17:30:07 +02004006 int cfgerr = 0;
William Lallemande3af8fb2019-10-08 11:36:53 +02004007 struct ckch_store *ckchs;
Willy Tarreau9a1ab082019-05-09 13:26:41 +02004008#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
yanbzhu63ea8462015-12-09 13:35:14 -05004009 int is_bundle;
4010 int j;
4011#endif
William Lallemande3af8fb2019-10-08 11:36:53 +02004012 if ((ckchs = ckchs_lookup(path))) {
William Lallemande3af8fb2019-10-08 11:36:53 +02004013 /* we found the ckchs in the tree, we can use it directly */
Willy Tarreau8c5414a2019-10-16 17:06:25 +02004014 return ssl_sock_load_ckchs(path, ckchs, bind_conf, NULL, NULL, 0, err);
William Lallemand6af03992019-07-23 15:00:54 +02004015 }
4016
yanbzhu08ce6ab2015-12-02 13:01:29 -05004017 if (stat(path, &buf) == 0) {
4018 dir = opendir(path);
William Lallemand36b84632019-07-18 19:28:17 +02004019 if (!dir) {
William Lallemande3af8fb2019-10-08 11:36:53 +02004020 ckchs = ckchs_load_cert_file(path, 0, err);
4021 if (!ckchs)
Willy Tarreaubbc91962019-10-16 16:42:19 +02004022 return ERR_ALERT | ERR_FATAL;
4023
Willy Tarreau8c5414a2019-10-16 17:06:25 +02004024 return ssl_sock_load_ckchs(path, ckchs, bind_conf, NULL, NULL, 0, err);
William Lallemand36b84632019-07-18 19:28:17 +02004025 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004026
yanbzhu08ce6ab2015-12-02 13:01:29 -05004027 /* strip trailing slashes, including first one */
4028 for (end = path + strlen(path) - 1; end >= path && *end == '/'; end--)
4029 *end = 0;
Emeric Brunfc0421f2012-09-07 17:30:07 +02004030
yanbzhu08ce6ab2015-12-02 13:01:29 -05004031 n = scandir(path, &de_list, 0, alphasort);
4032 if (n < 0) {
4033 memprintf(err, "%sunable to scan directory '%s' : %s.\n",
4034 err && *err ? *err : "", path, strerror(errno));
Willy Tarreaubbc91962019-10-16 16:42:19 +02004035 cfgerr |= ERR_ALERT | ERR_FATAL;
yanbzhu08ce6ab2015-12-02 13:01:29 -05004036 }
4037 else {
4038 for (i = 0; i < n; i++) {
4039 struct dirent *de = de_list[i];
Emeric Brun2aab7222014-06-18 18:15:09 +02004040
yanbzhu08ce6ab2015-12-02 13:01:29 -05004041 end = strrchr(de->d_name, '.');
4042 if (end && (!strcmp(end, ".issuer") || !strcmp(end, ".ocsp") || !strcmp(end, ".sctl")))
4043 goto ignore_entry;
Cyril Bonté3180f7b2015-01-25 00:16:08 +01004044
yanbzhu08ce6ab2015-12-02 13:01:29 -05004045 snprintf(fp, sizeof(fp), "%s/%s", path, de->d_name);
4046 if (stat(fp, &buf) != 0) {
4047 memprintf(err, "%sunable to stat SSL certificate from file '%s' : %s.\n",
4048 err && *err ? *err : "", fp, strerror(errno));
Willy Tarreaubbc91962019-10-16 16:42:19 +02004049 cfgerr |= ERR_ALERT | ERR_FATAL;
yanbzhu08ce6ab2015-12-02 13:01:29 -05004050 goto ignore_entry;
4051 }
4052 if (!S_ISREG(buf.st_mode))
4053 goto ignore_entry;
yanbzhu63ea8462015-12-09 13:35:14 -05004054
Willy Tarreau9a1ab082019-05-09 13:26:41 +02004055#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
yanbzhu63ea8462015-12-09 13:35:14 -05004056 is_bundle = 0;
4057 /* Check if current entry in directory is part of a multi-cert bundle */
4058
4059 if (end) {
4060 for (j = 0; j < SSL_SOCK_NUM_KEYTYPES; j++) {
4061 if (!strcmp(end + 1, SSL_SOCK_KEYTYPE_NAMES[j])) {
4062 is_bundle = 1;
4063 break;
4064 }
4065 }
4066
4067 if (is_bundle) {
4068 char dp[MAXPATHLEN+1] = {0}; /* this will be the filename w/o the keytype */
4069 int dp_len;
4070
4071 dp_len = end - de->d_name;
4072 snprintf(dp, dp_len + 1, "%s", de->d_name);
4073
4074 /* increment i and free de until we get to a non-bundle cert
4075 * Note here that we look at de_list[i + 1] before freeing de
4076 * this is important since ignore_entry will free de
4077 */
4078 while (i + 1 < n && !strncmp(de_list[i + 1]->d_name, dp, dp_len)) {
4079 free(de);
4080 i++;
4081 de = de_list[i];
4082 }
4083
4084 snprintf(fp, sizeof(fp), "%s/%s", path, dp);
William Lallemande3af8fb2019-10-08 11:36:53 +02004085 if ((ckchs = ckchs_lookup(fp)) == NULL)
4086 ckchs = ckchs_load_cert_file(fp, 1, err);
4087 if (!ckchs)
Willy Tarreaubbc91962019-10-16 16:42:19 +02004088 cfgerr |= ERR_ALERT | ERR_FATAL;
Willy Tarreau8c5414a2019-10-16 17:06:25 +02004089 else
4090 cfgerr |= ssl_sock_load_ckchs(path, ckchs, bind_conf, NULL, NULL, 0, err);
yanbzhu63ea8462015-12-09 13:35:14 -05004091 /* Successfully processed the bundle */
4092 goto ignore_entry;
4093 }
4094 }
4095
4096#endif
William Lallemande3af8fb2019-10-08 11:36:53 +02004097 if ((ckchs = ckchs_lookup(fp)) == NULL)
4098 ckchs = ckchs_load_cert_file(fp, 0, err);
4099 if (!ckchs)
Willy Tarreaubbc91962019-10-16 16:42:19 +02004100 cfgerr |= ERR_ALERT | ERR_FATAL;
William Lallemand614ca0d2019-10-07 13:52:11 +02004101 else
Willy Tarreau8c5414a2019-10-16 17:06:25 +02004102 cfgerr |= ssl_sock_load_ckchs(path, ckchs, bind_conf, NULL, NULL, 0, err);
William Lallemand36b84632019-07-18 19:28:17 +02004103
yanbzhu08ce6ab2015-12-02 13:01:29 -05004104ignore_entry:
4105 free(de);
Cyril Bonté3180f7b2015-01-25 00:16:08 +01004106 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05004107 free(de_list);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004108 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05004109 closedir(dir);
4110 return cfgerr;
Emeric Brunfc0421f2012-09-07 17:30:07 +02004111 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05004112
William Lallemande3af8fb2019-10-08 11:36:53 +02004113 ckchs = ckchs_load_cert_file(path, 1, err);
4114 if (!ckchs)
Willy Tarreaubbc91962019-10-16 16:42:19 +02004115 return ERR_ALERT | ERR_FATAL;
4116
Willy Tarreau8c5414a2019-10-16 17:06:25 +02004117 cfgerr |= ssl_sock_load_ckchs(path, ckchs, bind_conf, NULL, NULL, 0, err);
yanbzhu08ce6ab2015-12-02 13:01:29 -05004118
Emeric Brunfc0421f2012-09-07 17:30:07 +02004119 return cfgerr;
4120}
4121
Thierry Fournier383085f2013-01-24 14:15:43 +01004122/* Make sure openssl opens /dev/urandom before the chroot. The work is only
4123 * done once. Zero is returned if the operation fails. No error is returned
4124 * if the random is said as not implemented, because we expect that openssl
4125 * will use another method once needed.
4126 */
4127static int ssl_initialize_random()
4128{
4129 unsigned char random;
4130 static int random_initialized = 0;
4131
4132 if (!random_initialized && RAND_bytes(&random, 1) != 0)
4133 random_initialized = 1;
4134
4135 return random_initialized;
4136}
4137
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004138/* release ssl bind conf */
4139void ssl_sock_free_ssl_conf(struct ssl_bind_conf *conf)
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004140{
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004141 if (conf) {
Bernard Spil13c53f82018-02-15 13:34:58 +01004142#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004143 free(conf->npn_str);
4144 conf->npn_str = NULL;
4145#endif
4146#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
4147 free(conf->alpn_str);
4148 conf->alpn_str = NULL;
4149#endif
4150 free(conf->ca_file);
4151 conf->ca_file = NULL;
4152 free(conf->crl_file);
4153 conf->crl_file = NULL;
4154 free(conf->ciphers);
4155 conf->ciphers = NULL;
Emmanuel Hocdet839af572019-05-14 16:27:35 +02004156#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02004157 free(conf->ciphersuites);
4158 conf->ciphersuites = NULL;
4159#endif
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004160 free(conf->curves);
4161 conf->curves = NULL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004162 free(conf->ecdhe);
4163 conf->ecdhe = NULL;
4164 }
4165}
4166
Willy Tarreaubbc91962019-10-16 16:42:19 +02004167/* Returns a set of ERR_* flags possibly with an error in <err>. */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004168int ssl_sock_load_cert_list_file(char *file, struct bind_conf *bind_conf, struct proxy *curproxy, char **err)
4169{
4170 char thisline[CRT_LINESIZE];
4171 char path[MAXPATHLEN+1];
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004172 FILE *f;
yanbzhu1b04e5b2015-12-02 13:54:14 -05004173 struct stat buf;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004174 int linenum = 0;
4175 int cfgerr = 0;
William Lallemande3af8fb2019-10-08 11:36:53 +02004176 struct ckch_store *ckchs;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004177
Willy Tarreauad1731d2013-04-02 17:35:58 +02004178 if ((f = fopen(file, "r")) == NULL) {
4179 memprintf(err, "cannot open file '%s' : %s", file, strerror(errno));
Willy Tarreaubbc91962019-10-16 16:42:19 +02004180 return ERR_ALERT | ERR_FATAL;
Willy Tarreauad1731d2013-04-02 17:35:58 +02004181 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004182
4183 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004184 int arg, newarg, cur_arg, i, ssl_b = 0, ssl_e = 0;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004185 char *end;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004186 char *args[MAX_CRT_ARGS + 1];
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004187 char *line = thisline;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004188 char *crt_path;
4189 struct ssl_bind_conf *ssl_conf = NULL;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004190
4191 linenum++;
4192 end = line + strlen(line);
4193 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
4194 /* Check if we reached the limit and the last char is not \n.
4195 * Watch out for the last line without the terminating '\n'!
4196 */
Willy Tarreauad1731d2013-04-02 17:35:58 +02004197 memprintf(err, "line %d too long in file '%s', limit is %d characters",
4198 linenum, file, (int)sizeof(thisline)-1);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004199 cfgerr |= ERR_ALERT | ERR_FATAL;
Willy Tarreauad1731d2013-04-02 17:35:58 +02004200 break;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004201 }
4202
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004203 arg = 0;
Emeric Brun50bcecc2013-04-22 13:05:23 +02004204 newarg = 1;
4205 while (*line) {
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004206 if (*line == '#' || *line == '\n' || *line == '\r') {
4207 /* end of string, end of loop */
4208 *line = 0;
4209 break;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004210 } else if (isspace(*line)) {
Emeric Brun50bcecc2013-04-22 13:05:23 +02004211 newarg = 1;
4212 *line = 0;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004213 } else if (*line == '[') {
4214 if (ssl_b) {
4215 memprintf(err, "too many '[' on line %d in file '%s'.", linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004216 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004217 break;
4218 }
4219 if (!arg) {
4220 memprintf(err, "file must start with a cert on line %d in file '%s'", linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004221 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004222 break;
4223 }
4224 ssl_b = arg;
4225 newarg = 1;
4226 *line = 0;
4227 } else if (*line == ']') {
4228 if (ssl_e) {
4229 memprintf(err, "too many ']' on line %d in file '%s'.", linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004230 cfgerr |= ERR_ALERT | ERR_FATAL;
Emeric Brun50bcecc2013-04-22 13:05:23 +02004231 break;
4232 }
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004233 if (!ssl_b) {
4234 memprintf(err, "missing '[' in line %d in file '%s'.", linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004235 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004236 break;
4237 }
4238 ssl_e = arg;
4239 newarg = 1;
4240 *line = 0;
4241 } else if (newarg) {
4242 if (arg == MAX_CRT_ARGS) {
4243 memprintf(err, "too many args on line %d in file '%s'.", linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004244 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004245 break;
4246 }
Emeric Brun50bcecc2013-04-22 13:05:23 +02004247 newarg = 0;
4248 args[arg++] = line;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004249 }
Emeric Brun50bcecc2013-04-22 13:05:23 +02004250 line++;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004251 }
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02004252 if (cfgerr)
4253 break;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004254 args[arg++] = line;
Willy Tarreauad1731d2013-04-02 17:35:58 +02004255
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004256 /* empty line */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004257 if (!*args[0])
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004258 continue;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004259
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004260 crt_path = args[0];
4261 if (*crt_path != '/' && global_ssl.crt_base) {
4262 if ((strlen(global_ssl.crt_base) + 1 + strlen(crt_path)) > MAXPATHLEN) {
4263 memprintf(err, "'%s' : path too long on line %d in file '%s'",
4264 crt_path, linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004265 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004266 break;
4267 }
4268 snprintf(path, sizeof(path), "%s/%s", global_ssl.crt_base, crt_path);
4269 crt_path = path;
4270 }
4271
4272 ssl_conf = calloc(1, sizeof *ssl_conf);
4273 cur_arg = ssl_b ? ssl_b : 1;
4274 while (cur_arg < ssl_e) {
4275 newarg = 0;
4276 for (i = 0; ssl_bind_kws[i].kw != NULL; i++) {
4277 if (strcmp(ssl_bind_kws[i].kw, args[cur_arg]) == 0) {
4278 newarg = 1;
Willy Tarreaubbc91962019-10-16 16:42:19 +02004279 cfgerr |= ssl_bind_kws[i].parse(args, cur_arg, curproxy, ssl_conf, err);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004280 if (cur_arg + 1 + ssl_bind_kws[i].skip > ssl_e) {
4281 memprintf(err, "ssl args out of '[]' for %s on line %d in file '%s'",
4282 args[cur_arg], linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004283 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004284 }
4285 cur_arg += 1 + ssl_bind_kws[i].skip;
4286 break;
4287 }
4288 }
4289 if (!cfgerr && !newarg) {
4290 memprintf(err, "unknown ssl keyword %s on line %d in file '%s'.",
4291 args[cur_arg], linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004292 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004293 break;
4294 }
4295 }
Willy Tarreaubbc91962019-10-16 16:42:19 +02004296
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004297 if (cfgerr) {
4298 ssl_sock_free_ssl_conf(ssl_conf);
4299 free(ssl_conf);
4300 ssl_conf = NULL;
4301 break;
4302 }
4303
William Lallemande3af8fb2019-10-08 11:36:53 +02004304 if ((ckchs = ckchs_lookup(crt_path)) == NULL) {
William Lallemandeed4bf22019-10-10 11:38:13 +02004305 if (stat(crt_path, &buf) == 0)
William Lallemande3af8fb2019-10-08 11:36:53 +02004306 ckchs = ckchs_load_cert_file(crt_path, 0, err);
Emmanuel Hocdet1503e052019-07-31 18:30:33 +02004307 else
William Lallemande3af8fb2019-10-08 11:36:53 +02004308 ckchs = ckchs_load_cert_file(crt_path, 1, err);
yanbzhu1b04e5b2015-12-02 13:54:14 -05004309 }
4310
Willy Tarreau8c5414a2019-10-16 17:06:25 +02004311 if (!ckchs)
Willy Tarreaubbc91962019-10-16 16:42:19 +02004312 cfgerr |= ERR_ALERT | ERR_FATAL;
Willy Tarreau8c5414a2019-10-16 17:06:25 +02004313 else
4314 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 +02004315
Willy Tarreauad1731d2013-04-02 17:35:58 +02004316 if (cfgerr) {
4317 memprintf(err, "error processing line %d in file '%s' : %s", linenum, file, *err);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004318 break;
Willy Tarreauad1731d2013-04-02 17:35:58 +02004319 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004320 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004321 fclose(f);
4322 return cfgerr;
4323}
4324
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004325/* Create an initial CTX used to start the SSL connection before switchctx */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004326static int
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004327ssl_sock_initial_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02004328{
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004329 SSL_CTX *ctx = NULL;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004330 long options =
Emeric Brunfc0421f2012-09-07 17:30:07 +02004331 SSL_OP_ALL | /* all known workarounds for bugs */
4332 SSL_OP_NO_SSLv2 |
4333 SSL_OP_NO_COMPRESSION |
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02004334 SSL_OP_SINGLE_DH_USE |
Emeric Brun2b58d042012-09-20 17:10:03 +02004335 SSL_OP_SINGLE_ECDH_USE |
Emeric Brun3c4bc6e2012-10-04 18:44:19 +02004336 SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION |
Lukas Tribus926594f2018-05-18 17:55:57 +02004337 SSL_OP_PRIORITIZE_CHACHA |
Emeric Brun3c4bc6e2012-10-04 18:44:19 +02004338 SSL_OP_CIPHER_SERVER_PREFERENCE;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004339 long mode =
Emeric Brunfc0421f2012-09-07 17:30:07 +02004340 SSL_MODE_ENABLE_PARTIAL_WRITE |
4341 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
Willy Tarreau396a1862014-11-13 14:06:52 +01004342 SSL_MODE_RELEASE_BUFFERS |
4343 SSL_MODE_SMALL_BUFFERS;
Emmanuel Hocdet43664762017-08-09 18:26:20 +02004344 struct tls_version_filter *conf_ssl_methods = &bind_conf->ssl_conf.ssl_methods;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004345 int i, min, max, hole;
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004346 int flags = MC_SSL_O_ALL;
4347 int cfgerr = 0;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004348
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004349 ctx = SSL_CTX_new(SSLv23_server_method());
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004350 bind_conf->initial_ctx = ctx;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004351
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004352 if (conf_ssl_methods->flags && (conf_ssl_methods->min || conf_ssl_methods->max))
Christopher Faulet767a84b2017-11-24 16:50:31 +01004353 ha_warning("Proxy '%s': no-sslv3/no-tlsv1x are ignored for bind '%s' at [%s:%d]. "
4354 "Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
4355 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004356 else
4357 flags = conf_ssl_methods->flags;
4358
Emmanuel Hocdetbd695fe2017-05-15 15:53:41 +02004359 min = conf_ssl_methods->min;
4360 max = conf_ssl_methods->max;
4361 /* start with TLSv10 to remove SSLv3 per default */
4362 if (!min && (!max || max >= CONF_TLSV10))
4363 min = CONF_TLSV10;
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004364 /* Real min and max should be determinate with configuration and openssl's capabilities */
Emmanuel Hocdetbd695fe2017-05-15 15:53:41 +02004365 if (min)
4366 flags |= (methodVersions[min].flag - 1);
4367 if (max)
4368 flags |= ~((methodVersions[max].flag << 1) - 1);
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004369 /* find min, max and holes */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004370 min = max = CONF_TLSV_NONE;
4371 hole = 0;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004372 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004373 /* version is in openssl && version not disable in configuration */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004374 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004375 if (min) {
4376 if (hole) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004377 ha_warning("Proxy '%s': SSL/TLS versions range not contiguous for bind '%s' at [%s:%d]. "
4378 "Hole find for %s. Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
4379 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line,
4380 methodVersions[hole].name);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004381 hole = 0;
4382 }
4383 max = i;
4384 }
4385 else {
4386 min = max = i;
4387 }
4388 }
4389 else {
4390 if (min)
4391 hole = i;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004392 }
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004393 if (!min) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004394 ha_alert("Proxy '%s': all SSL/TLS versions are disabled for bind '%s' at [%s:%d].\n",
4395 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004396 cfgerr += 1;
4397 }
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02004398 /* save real min/max in bind_conf */
4399 conf_ssl_methods->min = min;
4400 conf_ssl_methods->max = max;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004401
Willy Tarreau9a1ab082019-05-09 13:26:41 +02004402#if (HA_OPENSSL_VERSION_NUMBER < 0x1010000fL)
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004403 /* Keep force-xxx implementation as it is in older haproxy. It's a
Joseph Herlant017b3da2018-11-15 09:07:59 -08004404 precautionary measure to avoid any surprise with older openssl version. */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004405 if (min == max)
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004406 methodVersions[min].ctx_set_version(ctx, SET_SERVER);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004407 else
4408 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
4409 if (flags & methodVersions[i].flag)
4410 options |= methodVersions[i].option;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004411#else /* openssl >= 1.1.0 */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004412 /* set the max_version is required to cap TLS version or activate new TLS (v1.3) */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004413 methodVersions[min].ctx_set_version(ctx, SET_MIN);
4414 methodVersions[max].ctx_set_version(ctx, SET_MAX);
Emeric Brunfa5c5c82017-04-28 16:19:51 +02004415#endif
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004416
4417 if (bind_conf->ssl_options & BC_SSL_O_NO_TLS_TICKETS)
4418 options |= SSL_OP_NO_TICKET;
4419 if (bind_conf->ssl_options & BC_SSL_O_PREF_CLIE_CIPH)
4420 options &= ~SSL_OP_CIPHER_SERVER_PREFERENCE;
Dirkjan Bussink526894f2019-01-21 09:35:03 -08004421
4422#ifdef SSL_OP_NO_RENEGOTIATION
4423 options |= SSL_OP_NO_RENEGOTIATION;
4424#endif
4425
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004426 SSL_CTX_set_options(ctx, options);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004427
Willy Tarreau5db847a2019-05-09 14:13:35 +02004428#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004429 if (global_ssl.async)
4430 mode |= SSL_MODE_ASYNC;
4431#endif
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004432 SSL_CTX_set_mode(ctx, mode);
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004433 if (global_ssl.life_time)
4434 SSL_CTX_set_timeout(ctx, global_ssl.life_time);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004435
4436#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
4437#ifdef OPENSSL_IS_BORINGSSL
4438 SSL_CTX_set_select_certificate_cb(ctx, ssl_sock_switchctx_cbk);
4439 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_err_cbk);
Willy Tarreau5db847a2019-05-09 14:13:35 +02004440#elif (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Olivier Houchard51088ce2019-01-02 18:46:41 +01004441 if (bind_conf->ssl_conf.early_data) {
4442 SSL_CTX_set_options(ctx, SSL_OP_NO_ANTI_REPLAY);
4443 SSL_CTX_set_max_early_data(ctx, global.tune.bufsize - global.tune.maxrewrite);
4444 }
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02004445 SSL_CTX_set_client_hello_cb(ctx, ssl_sock_switchctx_cbk, NULL);
4446 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_err_cbk);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004447#else
4448 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_cbk);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004449#endif
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02004450 SSL_CTX_set_tlsext_servername_arg(ctx, bind_conf);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004451#endif
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004452 return cfgerr;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004453}
4454
William Lallemand4f45bb92017-10-30 20:08:51 +01004455
4456static inline void sh_ssl_sess_free_blocks(struct shared_block *first, struct shared_block *block)
4457{
4458 if (first == block) {
4459 struct sh_ssl_sess_hdr *sh_ssl_sess = (struct sh_ssl_sess_hdr *)first->data;
4460 if (first->len > 0)
4461 sh_ssl_sess_tree_delete(sh_ssl_sess);
4462 }
4463}
4464
4465/* return first block from sh_ssl_sess */
4466static inline struct shared_block *sh_ssl_sess_first_block(struct sh_ssl_sess_hdr *sh_ssl_sess)
4467{
4468 return (struct shared_block *)((unsigned char *)sh_ssl_sess - ((struct shared_block *)NULL)->data);
4469
4470}
4471
4472/* store a session into the cache
4473 * s_id : session id padded with zero to SSL_MAX_SSL_SESSION_ID_LENGTH
4474 * data: asn1 encoded session
4475 * data_len: asn1 encoded session length
4476 * Returns 1 id session was stored (else 0)
4477 */
4478static int sh_ssl_sess_store(unsigned char *s_id, unsigned char *data, int data_len)
4479{
4480 struct shared_block *first;
4481 struct sh_ssl_sess_hdr *sh_ssl_sess, *oldsh_ssl_sess;
4482
Frédéric Lécaille0bec8072018-10-22 17:55:57 +02004483 first = shctx_row_reserve_hot(ssl_shctx, NULL, data_len + sizeof(struct sh_ssl_sess_hdr));
William Lallemand4f45bb92017-10-30 20:08:51 +01004484 if (!first) {
4485 /* Could not retrieve enough free blocks to store that session */
4486 return 0;
4487 }
4488
4489 /* STORE the key in the first elem */
4490 sh_ssl_sess = (struct sh_ssl_sess_hdr *)first->data;
4491 memcpy(sh_ssl_sess->key_data, s_id, SSL_MAX_SSL_SESSION_ID_LENGTH);
4492 first->len = sizeof(struct sh_ssl_sess_hdr);
4493
4494 /* it returns the already existing node
4495 or current node if none, never returns null */
4496 oldsh_ssl_sess = sh_ssl_sess_tree_insert(sh_ssl_sess);
4497 if (oldsh_ssl_sess != sh_ssl_sess) {
4498 /* NOTE: Row couldn't be in use because we lock read & write function */
4499 /* release the reserved row */
4500 shctx_row_dec_hot(ssl_shctx, first);
4501 /* replace the previous session already in the tree */
4502 sh_ssl_sess = oldsh_ssl_sess;
4503 /* ignore the previous session data, only use the header */
4504 first = sh_ssl_sess_first_block(sh_ssl_sess);
4505 shctx_row_inc_hot(ssl_shctx, first);
4506 first->len = sizeof(struct sh_ssl_sess_hdr);
4507 }
4508
Frédéric Lécaille0bec8072018-10-22 17:55:57 +02004509 if (shctx_row_data_append(ssl_shctx, first, NULL, data, data_len) < 0) {
William Lallemand99b90af2018-01-03 19:15:51 +01004510 shctx_row_dec_hot(ssl_shctx, first);
William Lallemand4f45bb92017-10-30 20:08:51 +01004511 return 0;
William Lallemand99b90af2018-01-03 19:15:51 +01004512 }
4513
4514 shctx_row_dec_hot(ssl_shctx, first);
William Lallemand4f45bb92017-10-30 20:08:51 +01004515
4516 return 1;
4517}
William Lallemanded0b5ad2017-10-30 19:36:36 +01004518
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004519/* SSL callback used when a new session is created while connecting to a server */
4520static int ssl_sess_new_srv_cb(SSL *ssl, SSL_SESSION *sess)
4521{
Thierry FOURNIER28962c92018-06-17 21:37:05 +02004522 struct connection *conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Olivier Houcharde6060c52017-11-16 17:42:52 +01004523 struct server *s;
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004524
Willy Tarreau07d94e42018-09-20 10:57:52 +02004525 s = __objt_server(conn->target);
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004526
Olivier Houcharde6060c52017-11-16 17:42:52 +01004527 if (!(s->ssl_ctx.options & SRV_SSL_O_NO_REUSE)) {
4528 int len;
4529 unsigned char *ptr;
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004530
Olivier Houcharde6060c52017-11-16 17:42:52 +01004531 len = i2d_SSL_SESSION(sess, NULL);
4532 if (s->ssl_ctx.reused_sess[tid].ptr && s->ssl_ctx.reused_sess[tid].allocated_size >= len) {
4533 ptr = s->ssl_ctx.reused_sess[tid].ptr;
4534 } else {
4535 free(s->ssl_ctx.reused_sess[tid].ptr);
4536 ptr = s->ssl_ctx.reused_sess[tid].ptr = malloc(len);
4537 s->ssl_ctx.reused_sess[tid].allocated_size = len;
4538 }
4539 if (s->ssl_ctx.reused_sess[tid].ptr) {
4540 s->ssl_ctx.reused_sess[tid].size = i2d_SSL_SESSION(sess,
4541 &ptr);
4542 }
4543 } else {
4544 free(s->ssl_ctx.reused_sess[tid].ptr);
4545 s->ssl_ctx.reused_sess[tid].ptr = NULL;
4546 }
4547
4548 return 0;
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004549}
4550
Olivier Houcharde6060c52017-11-16 17:42:52 +01004551
William Lallemanded0b5ad2017-10-30 19:36:36 +01004552/* SSL callback used on new session creation */
William Lallemand4f45bb92017-10-30 20:08:51 +01004553int sh_ssl_sess_new_cb(SSL *ssl, SSL_SESSION *sess)
William Lallemanded0b5ad2017-10-30 19:36:36 +01004554{
4555 unsigned char encsess[SHSESS_MAX_DATA_LEN]; /* encoded session */
4556 unsigned char encid[SSL_MAX_SSL_SESSION_ID_LENGTH]; /* encoded id */
4557 unsigned char *p;
4558 int data_len;
Emeric Bruneb469652019-10-08 18:27:37 +02004559 unsigned int sid_length;
William Lallemanded0b5ad2017-10-30 19:36:36 +01004560 const unsigned char *sid_data;
William Lallemanded0b5ad2017-10-30 19:36:36 +01004561
4562 /* Session id is already stored in to key and session id is known
4563 * so we dont store it to keep size.
Emeric Bruneb469652019-10-08 18:27:37 +02004564 * note: SSL_SESSION_set1_id is using
4565 * a memcpy so we need to use a different pointer
4566 * than sid_data or sid_ctx_data to avoid valgrind
4567 * complaining.
William Lallemanded0b5ad2017-10-30 19:36:36 +01004568 */
4569
4570 sid_data = SSL_SESSION_get_id(sess, &sid_length);
Emeric Bruneb469652019-10-08 18:27:37 +02004571
4572 /* copy value in an other buffer */
4573 memcpy(encid, sid_data, sid_length);
4574
4575 /* pad with 0 */
4576 if (sid_length < SSL_MAX_SSL_SESSION_ID_LENGTH)
4577 memset(encid + sid_length, 0, SSL_MAX_SSL_SESSION_ID_LENGTH-sid_length);
4578
4579 /* force length to zero to avoid ASN1 encoding */
4580 SSL_SESSION_set1_id(sess, encid, 0);
4581
4582 /* force length to zero to avoid ASN1 encoding */
4583 SSL_SESSION_set1_id_context(sess, (const unsigned char *)SHCTX_APPNAME, 0);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004584
4585 /* check if buffer is large enough for the ASN1 encoded session */
4586 data_len = i2d_SSL_SESSION(sess, NULL);
4587 if (data_len > SHSESS_MAX_DATA_LEN)
4588 goto err;
4589
4590 p = encsess;
4591
4592 /* process ASN1 session encoding before the lock */
4593 i2d_SSL_SESSION(sess, &p);
4594
William Lallemanded0b5ad2017-10-30 19:36:36 +01004595
William Lallemanda3c77cf2017-10-30 23:44:40 +01004596 shctx_lock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004597 /* store to cache */
William Lallemand4f45bb92017-10-30 20:08:51 +01004598 sh_ssl_sess_store(encid, encsess, data_len);
William Lallemanda3c77cf2017-10-30 23:44:40 +01004599 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004600err:
4601 /* reset original length values */
Emeric Bruneb469652019-10-08 18:27:37 +02004602 SSL_SESSION_set1_id(sess, encid, sid_length);
4603 SSL_SESSION_set1_id_context(sess, (const unsigned char *)SHCTX_APPNAME, strlen(SHCTX_APPNAME));
William Lallemanded0b5ad2017-10-30 19:36:36 +01004604
4605 return 0; /* do not increment session reference count */
4606}
4607
4608/* SSL callback used on lookup an existing session cause none found in internal cache */
William Lallemand4f45bb92017-10-30 20:08:51 +01004609SSL_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 +01004610{
William Lallemand4f45bb92017-10-30 20:08:51 +01004611 struct sh_ssl_sess_hdr *sh_ssl_sess;
William Lallemanded0b5ad2017-10-30 19:36:36 +01004612 unsigned char data[SHSESS_MAX_DATA_LEN], *p;
4613 unsigned char tmpkey[SSL_MAX_SSL_SESSION_ID_LENGTH];
William Lallemanded0b5ad2017-10-30 19:36:36 +01004614 SSL_SESSION *sess;
William Lallemand4f45bb92017-10-30 20:08:51 +01004615 struct shared_block *first;
William Lallemanded0b5ad2017-10-30 19:36:36 +01004616
4617 global.shctx_lookups++;
4618
4619 /* allow the session to be freed automatically by openssl */
4620 *do_copy = 0;
4621
4622 /* tree key is zeros padded sessionid */
4623 if (key_len < SSL_MAX_SSL_SESSION_ID_LENGTH) {
4624 memcpy(tmpkey, key, key_len);
4625 memset(tmpkey + key_len, 0, SSL_MAX_SSL_SESSION_ID_LENGTH - key_len);
4626 key = tmpkey;
4627 }
4628
4629 /* lock cache */
William Lallemanda3c77cf2017-10-30 23:44:40 +01004630 shctx_lock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004631
4632 /* lookup for session */
William Lallemand4f45bb92017-10-30 20:08:51 +01004633 sh_ssl_sess = sh_ssl_sess_tree_lookup(key);
4634 if (!sh_ssl_sess) {
William Lallemanded0b5ad2017-10-30 19:36:36 +01004635 /* no session found: unlock cache and exit */
William Lallemanda3c77cf2017-10-30 23:44:40 +01004636 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004637 global.shctx_misses++;
4638 return NULL;
4639 }
4640
William Lallemand4f45bb92017-10-30 20:08:51 +01004641 /* sh_ssl_sess (shared_block->data) is at the end of shared_block */
4642 first = sh_ssl_sess_first_block(sh_ssl_sess);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004643
William Lallemand4f45bb92017-10-30 20:08:51 +01004644 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 +01004645
William Lallemanda3c77cf2017-10-30 23:44:40 +01004646 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004647
4648 /* decode ASN1 session */
4649 p = data;
William Lallemand4f45bb92017-10-30 20:08:51 +01004650 sess = d2i_SSL_SESSION(NULL, (const unsigned char **)&p, first->len-sizeof(struct sh_ssl_sess_hdr));
William Lallemanded0b5ad2017-10-30 19:36:36 +01004651 /* Reset session id and session id contenxt */
4652 if (sess) {
4653 SSL_SESSION_set1_id(sess, key, key_len);
4654 SSL_SESSION_set1_id_context(sess, (const unsigned char *)SHCTX_APPNAME, strlen(SHCTX_APPNAME));
4655 }
4656
4657 return sess;
4658}
4659
William Lallemand4f45bb92017-10-30 20:08:51 +01004660
William Lallemanded0b5ad2017-10-30 19:36:36 +01004661/* SSL callback used to signal session is no more used in internal cache */
William Lallemand4f45bb92017-10-30 20:08:51 +01004662void sh_ssl_sess_remove_cb(SSL_CTX *ctx, SSL_SESSION *sess)
William Lallemanded0b5ad2017-10-30 19:36:36 +01004663{
William Lallemand4f45bb92017-10-30 20:08:51 +01004664 struct sh_ssl_sess_hdr *sh_ssl_sess;
William Lallemanded0b5ad2017-10-30 19:36:36 +01004665 unsigned char tmpkey[SSL_MAX_SSL_SESSION_ID_LENGTH];
4666 unsigned int sid_length;
4667 const unsigned char *sid_data;
4668 (void)ctx;
4669
4670 sid_data = SSL_SESSION_get_id(sess, &sid_length);
4671 /* tree key is zeros padded sessionid */
4672 if (sid_length < SSL_MAX_SSL_SESSION_ID_LENGTH) {
4673 memcpy(tmpkey, sid_data, sid_length);
4674 memset(tmpkey+sid_length, 0, SSL_MAX_SSL_SESSION_ID_LENGTH - sid_length);
4675 sid_data = tmpkey;
4676 }
4677
William Lallemanda3c77cf2017-10-30 23:44:40 +01004678 shctx_lock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004679
4680 /* lookup for session */
William Lallemand4f45bb92017-10-30 20:08:51 +01004681 sh_ssl_sess = sh_ssl_sess_tree_lookup(sid_data);
4682 if (sh_ssl_sess) {
William Lallemanded0b5ad2017-10-30 19:36:36 +01004683 /* free session */
William Lallemand4f45bb92017-10-30 20:08:51 +01004684 sh_ssl_sess_tree_delete(sh_ssl_sess);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004685 }
4686
4687 /* unlock cache */
William Lallemanda3c77cf2017-10-30 23:44:40 +01004688 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004689}
4690
4691/* Set session cache mode to server and disable openssl internal cache.
4692 * Set shared cache callbacks on an ssl context.
4693 * Shared context MUST be firstly initialized */
William Lallemand4f45bb92017-10-30 20:08:51 +01004694void ssl_set_shctx(SSL_CTX *ctx)
William Lallemanded0b5ad2017-10-30 19:36:36 +01004695{
4696 SSL_CTX_set_session_id_context(ctx, (const unsigned char *)SHCTX_APPNAME, strlen(SHCTX_APPNAME));
4697
4698 if (!ssl_shctx) {
4699 SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF);
4700 return;
4701 }
4702
4703 SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_SERVER |
4704 SSL_SESS_CACHE_NO_INTERNAL |
4705 SSL_SESS_CACHE_NO_AUTO_CLEAR);
4706
4707 /* Set callbacks */
William Lallemand4f45bb92017-10-30 20:08:51 +01004708 SSL_CTX_sess_set_new_cb(ctx, sh_ssl_sess_new_cb);
4709 SSL_CTX_sess_set_get_cb(ctx, sh_ssl_sess_get_cb);
4710 SSL_CTX_sess_set_remove_cb(ctx, sh_ssl_sess_remove_cb);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004711}
4712
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004713int ssl_sock_prepare_ctx(struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf, SSL_CTX *ctx)
4714{
4715 struct proxy *curproxy = bind_conf->frontend;
4716 int cfgerr = 0;
4717 int verify = SSL_VERIFY_NONE;
Willy Tarreau5d4cafb2018-01-04 18:55:19 +01004718 struct ssl_bind_conf __maybe_unused *ssl_conf_cur;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004719 const char *conf_ciphers;
Emmanuel Hocdet839af572019-05-14 16:27:35 +02004720#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02004721 const char *conf_ciphersuites;
4722#endif
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004723 const char *conf_curves = NULL;
Emeric Brunfc0421f2012-09-07 17:30:07 +02004724
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02004725 if (ssl_conf) {
4726 struct tls_version_filter *conf_ssl_methods = &ssl_conf->ssl_methods;
4727 int i, min, max;
4728 int flags = MC_SSL_O_ALL;
4729
4730 /* Real min and max should be determinate with configuration and openssl's capabilities */
Emmanuel Hocdet43664762017-08-09 18:26:20 +02004731 min = conf_ssl_methods->min ? conf_ssl_methods->min : bind_conf->ssl_conf.ssl_methods.min;
4732 max = conf_ssl_methods->max ? conf_ssl_methods->max : bind_conf->ssl_conf.ssl_methods.max;
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02004733 if (min)
4734 flags |= (methodVersions[min].flag - 1);
4735 if (max)
4736 flags |= ~((methodVersions[max].flag << 1) - 1);
4737 min = max = CONF_TLSV_NONE;
4738 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
4739 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
4740 if (min)
4741 max = i;
4742 else
4743 min = max = i;
4744 }
4745 /* save real min/max */
4746 conf_ssl_methods->min = min;
4747 conf_ssl_methods->max = max;
4748 if (!min) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004749 ha_alert("Proxy '%s': all SSL/TLS versions are disabled for bind '%s' at [%s:%d].\n",
4750 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02004751 cfgerr += 1;
4752 }
4753 }
4754
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004755 switch ((ssl_conf && ssl_conf->verify) ? ssl_conf->verify : bind_conf->ssl_conf.verify) {
Emeric Brun850efd52014-01-29 12:24:34 +01004756 case SSL_SOCK_VERIFY_NONE:
4757 verify = SSL_VERIFY_NONE;
4758 break;
4759 case SSL_SOCK_VERIFY_OPTIONAL:
4760 verify = SSL_VERIFY_PEER;
4761 break;
4762 case SSL_SOCK_VERIFY_REQUIRED:
4763 verify = SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
4764 break;
4765 }
4766 SSL_CTX_set_verify(ctx, verify, ssl_sock_bind_verifycbk);
4767 if (verify & SSL_VERIFY_PEER) {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004768 char *ca_file = (ssl_conf && ssl_conf->ca_file) ? ssl_conf->ca_file : bind_conf->ssl_conf.ca_file;
4769 char *crl_file = (ssl_conf && ssl_conf->crl_file) ? ssl_conf->crl_file : bind_conf->ssl_conf.crl_file;
4770 if (ca_file) {
Emeric Brund94b3fe2012-09-20 18:23:56 +02004771 /* load CAfile to verify */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004772 if (!SSL_CTX_load_verify_locations(ctx, ca_file, NULL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004773 ha_alert("Proxy '%s': unable to load CA file '%s' for bind '%s' at [%s:%d].\n",
4774 curproxy->id, ca_file, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brund94b3fe2012-09-20 18:23:56 +02004775 cfgerr++;
4776 }
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02004777 if (!((ssl_conf && ssl_conf->no_ca_names) || bind_conf->ssl_conf.no_ca_names)) {
4778 /* set CA names for client cert request, function returns void */
4779 SSL_CTX_set_client_CA_list(ctx, SSL_load_client_CA_file(ca_file));
4780 }
Emeric Brund94b3fe2012-09-20 18:23:56 +02004781 }
Emeric Brun850efd52014-01-29 12:24:34 +01004782 else {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004783 ha_alert("Proxy '%s': verify is enabled but no CA file specified for bind '%s' at [%s:%d].\n",
4784 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brun850efd52014-01-29 12:24:34 +01004785 cfgerr++;
4786 }
Emeric Brun051cdab2012-10-02 19:25:50 +02004787#ifdef X509_V_FLAG_CRL_CHECK
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004788 if (crl_file) {
Emeric Brund94b3fe2012-09-20 18:23:56 +02004789 X509_STORE *store = SSL_CTX_get_cert_store(ctx);
4790
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004791 if (!store || !X509_STORE_load_locations(store, crl_file, NULL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004792 ha_alert("Proxy '%s': unable to configure CRL file '%s' for bind '%s' at [%s:%d].\n",
4793 curproxy->id, crl_file, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brund94b3fe2012-09-20 18:23:56 +02004794 cfgerr++;
4795 }
Emeric Brun561e5742012-10-02 15:20:55 +02004796 else {
4797 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
4798 }
Emeric Brund94b3fe2012-09-20 18:23:56 +02004799 }
Emeric Brun051cdab2012-10-02 19:25:50 +02004800#endif
Emeric Brun644cde02012-12-14 11:21:13 +01004801 ERR_clear_error();
Emeric Brund94b3fe2012-09-20 18:23:56 +02004802 }
Nenad Merdanovic05552d42015-02-27 19:56:49 +01004803#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
Nenad Merdanovic146defa2015-05-09 08:46:00 +02004804 if(bind_conf->keys_ref) {
Nenad Merdanovic05552d42015-02-27 19:56:49 +01004805 if (!SSL_CTX_set_tlsext_ticket_key_cb(ctx, ssl_tlsext_ticket_key_cb)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004806 ha_alert("Proxy '%s': unable to set callback for TLS ticket validation for bind '%s' at [%s:%d].\n",
4807 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Nenad Merdanovic05552d42015-02-27 19:56:49 +01004808 cfgerr++;
4809 }
4810 }
4811#endif
4812
William Lallemand4f45bb92017-10-30 20:08:51 +01004813 ssl_set_shctx(ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004814 conf_ciphers = (ssl_conf && ssl_conf->ciphers) ? ssl_conf->ciphers : bind_conf->ssl_conf.ciphers;
4815 if (conf_ciphers &&
4816 !SSL_CTX_set_cipher_list(ctx, conf_ciphers)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004817 ha_alert("Proxy '%s': unable to set SSL cipher list to '%s' for bind '%s' at [%s:%d].\n",
4818 curproxy->id, conf_ciphers, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004819 cfgerr++;
4820 }
4821
Emmanuel Hocdet839af572019-05-14 16:27:35 +02004822#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02004823 conf_ciphersuites = (ssl_conf && ssl_conf->ciphersuites) ? ssl_conf->ciphersuites : bind_conf->ssl_conf.ciphersuites;
4824 if (conf_ciphersuites &&
4825 !SSL_CTX_set_ciphersuites(ctx, conf_ciphersuites)) {
4826 ha_alert("Proxy '%s': unable to set TLS 1.3 cipher suites to '%s' for bind '%s' at [%s:%d].\n",
4827 curproxy->id, conf_ciphersuites, bind_conf->arg, bind_conf->file, bind_conf->line);
4828 cfgerr++;
4829 }
4830#endif
4831
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01004832#ifndef OPENSSL_NO_DH
Remi Gacogne47783ef2015-05-29 15:53:22 +02004833 /* If tune.ssl.default-dh-param has not been set,
4834 neither has ssl-default-dh-file and no static DH
4835 params were in the certificate file. */
Willy Tarreauef934602016-12-22 23:12:01 +01004836 if (global_ssl.default_dh_param == 0 &&
Remi Gacogne47783ef2015-05-29 15:53:22 +02004837 global_dh == NULL &&
Remi Gacogne4f902b82015-05-28 16:23:00 +02004838 (ssl_dh_ptr_index == -1 ||
4839 SSL_CTX_get_ex_data(ctx, ssl_dh_ptr_index) == NULL)) {
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01004840 STACK_OF(SSL_CIPHER) * ciphers = NULL;
4841 const SSL_CIPHER * cipher = NULL;
4842 char cipher_description[128];
4843 /* The description of ciphers using an Ephemeral Diffie Hellman key exchange
4844 contains " Kx=DH " or " Kx=DH(". Beware of " Kx=DH/",
4845 which is not ephemeral DH. */
4846 const char dhe_description[] = " Kx=DH ";
4847 const char dhe_export_description[] = " Kx=DH(";
4848 int idx = 0;
4849 int dhe_found = 0;
4850 SSL *ssl = NULL;
Lukas Tribus90132722014-08-18 00:56:33 +02004851
Remi Gacogne23d5d372014-10-10 17:04:26 +02004852 ssl = SSL_new(ctx);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004853
Remi Gacogne23d5d372014-10-10 17:04:26 +02004854 if (ssl) {
4855 ciphers = SSL_get_ciphers(ssl);
4856
4857 if (ciphers) {
4858 for (idx = 0; idx < sk_SSL_CIPHER_num(ciphers); idx++) {
4859 cipher = sk_SSL_CIPHER_value(ciphers, idx);
4860 if (SSL_CIPHER_description(cipher, cipher_description, sizeof (cipher_description)) == cipher_description) {
4861 if (strstr(cipher_description, dhe_description) != NULL ||
4862 strstr(cipher_description, dhe_export_description) != NULL) {
4863 dhe_found = 1;
4864 break;
4865 }
Remi Gacognec1eab8c2014-06-12 18:20:11 +02004866 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004867 }
4868 }
Remi Gacogne23d5d372014-10-10 17:04:26 +02004869 SSL_free(ssl);
4870 ssl = NULL;
Lukas Tribus90132722014-08-18 00:56:33 +02004871 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004872
Lukas Tribus90132722014-08-18 00:56:33 +02004873 if (dhe_found) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004874 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 +02004875 }
4876
Willy Tarreauef934602016-12-22 23:12:01 +01004877 global_ssl.default_dh_param = 1024;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004878 }
Remi Gacogne8de54152014-07-15 11:36:40 +02004879
Willy Tarreauef934602016-12-22 23:12:01 +01004880 if (global_ssl.default_dh_param >= 1024) {
Remi Gacogne8de54152014-07-15 11:36:40 +02004881 if (local_dh_1024 == NULL) {
4882 local_dh_1024 = ssl_get_dh_1024();
4883 }
Willy Tarreauef934602016-12-22 23:12:01 +01004884 if (global_ssl.default_dh_param >= 2048) {
Remi Gacogne8de54152014-07-15 11:36:40 +02004885 if (local_dh_2048 == NULL) {
4886 local_dh_2048 = ssl_get_dh_2048();
4887 }
Willy Tarreauef934602016-12-22 23:12:01 +01004888 if (global_ssl.default_dh_param >= 4096) {
Remi Gacogne8de54152014-07-15 11:36:40 +02004889 if (local_dh_4096 == NULL) {
4890 local_dh_4096 = ssl_get_dh_4096();
4891 }
Remi Gacogne8de54152014-07-15 11:36:40 +02004892 }
4893 }
4894 }
4895#endif /* OPENSSL_NO_DH */
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004896
Emeric Brunfc0421f2012-09-07 17:30:07 +02004897 SSL_CTX_set_info_callback(ctx, ssl_sock_infocbk);
Willy Tarreau9a1ab082019-05-09 13:26:41 +02004898#if HA_OPENSSL_VERSION_NUMBER >= 0x00907000L
Emeric Brun29f037d2014-04-25 19:05:36 +02004899 SSL_CTX_set_msg_callback(ctx, ssl_sock_msgcbk);
Willy Tarreau5cbe4ef2014-05-08 22:45:11 +02004900#endif
Emeric Brun29f037d2014-04-25 19:05:36 +02004901
Bernard Spil13c53f82018-02-15 13:34:58 +01004902#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004903 ssl_conf_cur = NULL;
4904 if (ssl_conf && ssl_conf->npn_str)
4905 ssl_conf_cur = ssl_conf;
4906 else if (bind_conf->ssl_conf.npn_str)
4907 ssl_conf_cur = &bind_conf->ssl_conf;
4908 if (ssl_conf_cur)
4909 SSL_CTX_set_next_protos_advertised_cb(ctx, ssl_sock_advertise_npn_protos, ssl_conf_cur);
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02004910#endif
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01004911#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004912 ssl_conf_cur = NULL;
4913 if (ssl_conf && ssl_conf->alpn_str)
4914 ssl_conf_cur = ssl_conf;
4915 else if (bind_conf->ssl_conf.alpn_str)
4916 ssl_conf_cur = &bind_conf->ssl_conf;
4917 if (ssl_conf_cur)
4918 SSL_CTX_set_alpn_select_cb(ctx, ssl_sock_advertise_alpn_protos, ssl_conf_cur);
Willy Tarreauab861d32013-04-02 02:30:41 +02004919#endif
Willy Tarreau9a1ab082019-05-09 13:26:41 +02004920#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004921 conf_curves = (ssl_conf && ssl_conf->curves) ? ssl_conf->curves : bind_conf->ssl_conf.curves;
4922 if (conf_curves) {
4923 if (!SSL_CTX_set1_curves_list(ctx, conf_curves)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004924 ha_alert("Proxy '%s': unable to set SSL curves list to '%s' for bind '%s' at [%s:%d].\n",
4925 curproxy->id, conf_curves, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004926 cfgerr++;
4927 }
Emmanuel Hocdeta52bb152017-03-20 11:11:49 +01004928#if defined(SSL_CTX_set_ecdh_auto)
4929 (void)SSL_CTX_set_ecdh_auto(ctx, 1);
4930#endif
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004931 }
4932#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02004933#if defined(SSL_CTX_set_tmp_ecdh) && !defined(OPENSSL_NO_ECDH)
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004934 if (!conf_curves) {
Emeric Brun2b58d042012-09-20 17:10:03 +02004935 int i;
4936 EC_KEY *ecdh;
Willy Tarreau9a1ab082019-05-09 13:26:41 +02004937#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004938 const char *ecdhe = (ssl_conf && ssl_conf->ecdhe) ? ssl_conf->ecdhe :
Olivier Houchardc2aae742017-09-22 18:26:28 +02004939 (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe :
4940 NULL);
4941
4942 if (ecdhe == NULL) {
Emeric Bruna9363eb2019-10-17 14:53:03 +02004943 SSL_CTX_set_ecdh_auto(ctx, 1);
Olivier Houchardc2aae742017-09-22 18:26:28 +02004944 return cfgerr;
4945 }
4946#else
4947 const char *ecdhe = (ssl_conf && ssl_conf->ecdhe) ? ssl_conf->ecdhe :
4948 (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe :
4949 ECDHE_DEFAULT_CURVE);
4950#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02004951
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004952 i = OBJ_sn2nid(ecdhe);
Emeric Brun2b58d042012-09-20 17:10:03 +02004953 if (!i || ((ecdh = EC_KEY_new_by_curve_name(i)) == NULL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004954 ha_alert("Proxy '%s': unable to set elliptic named curve to '%s' for bind '%s' at [%s:%d].\n",
4955 curproxy->id, ecdhe, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brun2b58d042012-09-20 17:10:03 +02004956 cfgerr++;
4957 }
4958 else {
4959 SSL_CTX_set_tmp_ecdh(ctx, ecdh);
4960 EC_KEY_free(ecdh);
4961 }
4962 }
4963#endif
4964
Emeric Brunfc0421f2012-09-07 17:30:07 +02004965 return cfgerr;
4966}
4967
Evan Broderbe554312013-06-27 00:05:25 -07004968static int ssl_sock_srv_hostcheck(const char *pattern, const char *hostname)
4969{
4970 const char *pattern_wildcard, *pattern_left_label_end, *hostname_left_label_end;
4971 size_t prefixlen, suffixlen;
4972
4973 /* Trivial case */
4974 if (strcmp(pattern, hostname) == 0)
4975 return 1;
4976
Evan Broderbe554312013-06-27 00:05:25 -07004977 /* The rest of this logic is based on RFC 6125, section 6.4.3
4978 * (http://tools.ietf.org/html/rfc6125#section-6.4.3) */
4979
Emeric Bruna848dae2013-10-08 11:27:28 +02004980 pattern_wildcard = NULL;
4981 pattern_left_label_end = pattern;
4982 while (*pattern_left_label_end != '.') {
4983 switch (*pattern_left_label_end) {
4984 case 0:
4985 /* End of label not found */
4986 return 0;
4987 case '*':
4988 /* If there is more than one wildcards */
4989 if (pattern_wildcard)
4990 return 0;
4991 pattern_wildcard = pattern_left_label_end;
4992 break;
4993 }
4994 pattern_left_label_end++;
4995 }
4996
4997 /* If it's not trivial and there is no wildcard, it can't
4998 * match */
4999 if (!pattern_wildcard)
Evan Broderbe554312013-06-27 00:05:25 -07005000 return 0;
5001
5002 /* Make sure all labels match except the leftmost */
5003 hostname_left_label_end = strchr(hostname, '.');
5004 if (!hostname_left_label_end
5005 || strcmp(pattern_left_label_end, hostname_left_label_end) != 0)
5006 return 0;
5007
5008 /* Make sure the leftmost label of the hostname is long enough
5009 * that the wildcard can match */
Emeric Brun369da852013-10-08 11:39:35 +02005010 if (hostname_left_label_end - hostname < (pattern_left_label_end - pattern) - 1)
Evan Broderbe554312013-06-27 00:05:25 -07005011 return 0;
5012
5013 /* Finally compare the string on either side of the
5014 * wildcard */
5015 prefixlen = pattern_wildcard - pattern;
5016 suffixlen = pattern_left_label_end - (pattern_wildcard + 1);
Emeric Bruna848dae2013-10-08 11:27:28 +02005017 if ((prefixlen && (memcmp(pattern, hostname, prefixlen) != 0))
5018 || (suffixlen && (memcmp(pattern_wildcard + 1, hostname_left_label_end - suffixlen, suffixlen) != 0)))
Evan Broderbe554312013-06-27 00:05:25 -07005019 return 0;
5020
5021 return 1;
5022}
5023
5024static int ssl_sock_srv_verifycbk(int ok, X509_STORE_CTX *ctx)
5025{
5026 SSL *ssl;
5027 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01005028 struct ssl_sock_ctx *ssl_ctx;
Willy Tarreau2ab88672017-07-05 18:23:03 +02005029 const char *servername;
Willy Tarreau71d058c2017-07-26 20:09:56 +02005030 const char *sni;
Evan Broderbe554312013-06-27 00:05:25 -07005031
5032 int depth;
5033 X509 *cert;
5034 STACK_OF(GENERAL_NAME) *alt_names;
5035 int i;
5036 X509_NAME *cert_subject;
5037 char *str;
5038
5039 if (ok == 0)
5040 return ok;
5041
5042 ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
Thierry FOURNIER28962c92018-06-17 21:37:05 +02005043 conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Olivier Houchard66ab4982019-02-26 18:37:15 +01005044 ssl_ctx = conn->xprt_ctx;
Evan Broderbe554312013-06-27 00:05:25 -07005045
Willy Tarreauad92a9a2017-07-28 11:38:41 +02005046 /* We're checking if the provided hostnames match the desired one. The
5047 * desired hostname comes from the SNI we presented if any, or if not
5048 * provided then it may have been explicitly stated using a "verifyhost"
5049 * directive. If neither is set, we don't care about the name so the
5050 * verification is OK.
Willy Tarreau2ab88672017-07-05 18:23:03 +02005051 */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005052 servername = SSL_get_servername(ssl_ctx->ssl, TLSEXT_NAMETYPE_host_name);
Willy Tarreau71d058c2017-07-26 20:09:56 +02005053 sni = servername;
Willy Tarreau2ab88672017-07-05 18:23:03 +02005054 if (!servername) {
Willy Tarreau07d94e42018-09-20 10:57:52 +02005055 servername = __objt_server(conn->target)->ssl_ctx.verify_host;
Willy Tarreau2ab88672017-07-05 18:23:03 +02005056 if (!servername)
5057 return ok;
5058 }
Evan Broderbe554312013-06-27 00:05:25 -07005059
5060 /* We only need to verify the CN on the actual server cert,
5061 * not the indirect CAs */
5062 depth = X509_STORE_CTX_get_error_depth(ctx);
5063 if (depth != 0)
5064 return ok;
5065
5066 /* At this point, the cert is *not* OK unless we can find a
5067 * hostname match */
5068 ok = 0;
5069
5070 cert = X509_STORE_CTX_get_current_cert(ctx);
5071 /* It seems like this might happen if verify peer isn't set */
5072 if (!cert)
5073 return ok;
5074
5075 alt_names = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
5076 if (alt_names) {
5077 for (i = 0; !ok && i < sk_GENERAL_NAME_num(alt_names); i++) {
5078 GENERAL_NAME *name = sk_GENERAL_NAME_value(alt_names, i);
5079 if (name->type == GEN_DNS) {
Willy Tarreau9a1ab082019-05-09 13:26:41 +02005080#if HA_OPENSSL_VERSION_NUMBER < 0x00907000L
Emeric Bruna33410c2013-09-17 15:47:48 +02005081 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.ia5) >= 0) {
5082#else
Evan Broderbe554312013-06-27 00:05:25 -07005083 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
Emeric Bruna33410c2013-09-17 15:47:48 +02005084#endif
Evan Broderbe554312013-06-27 00:05:25 -07005085 ok = ssl_sock_srv_hostcheck(str, servername);
5086 OPENSSL_free(str);
5087 }
5088 }
5089 }
Emeric Brun4ad50a42013-09-17 15:19:54 +02005090 sk_GENERAL_NAME_pop_free(alt_names, GENERAL_NAME_free);
Evan Broderbe554312013-06-27 00:05:25 -07005091 }
5092
5093 cert_subject = X509_get_subject_name(cert);
5094 i = -1;
5095 while (!ok && (i = X509_NAME_get_index_by_NID(cert_subject, NID_commonName, i)) != -1) {
5096 X509_NAME_ENTRY *entry = X509_NAME_get_entry(cert_subject, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005097 ASN1_STRING *value;
5098 value = X509_NAME_ENTRY_get_data(entry);
5099 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
Evan Broderbe554312013-06-27 00:05:25 -07005100 ok = ssl_sock_srv_hostcheck(str, servername);
5101 OPENSSL_free(str);
5102 }
5103 }
5104
Willy Tarreau71d058c2017-07-26 20:09:56 +02005105 /* report the mismatch and indicate if SNI was used or not */
5106 if (!ok && !conn->err_code)
5107 conn->err_code = sni ? CO_ER_SSL_MISMATCH_SNI : CO_ER_SSL_MISMATCH;
Evan Broderbe554312013-06-27 00:05:25 -07005108 return ok;
5109}
5110
Emeric Brun94324a42012-10-11 14:00:19 +02005111/* prepare ssl context from servers options. Returns an error count */
Willy Tarreau03209342016-12-22 17:08:28 +01005112int ssl_sock_prepare_srv_ctx(struct server *srv)
Emeric Brun94324a42012-10-11 14:00:19 +02005113{
Willy Tarreau03209342016-12-22 17:08:28 +01005114 struct proxy *curproxy = srv->proxy;
Emeric Brun94324a42012-10-11 14:00:19 +02005115 int cfgerr = 0;
Remi Gacogneaf5c3da2014-05-19 10:29:58 +02005116 long options =
Emeric Brun94324a42012-10-11 14:00:19 +02005117 SSL_OP_ALL | /* all known workarounds for bugs */
5118 SSL_OP_NO_SSLv2 |
5119 SSL_OP_NO_COMPRESSION;
Remi Gacogneaf5c3da2014-05-19 10:29:58 +02005120 long mode =
Emeric Brun94324a42012-10-11 14:00:19 +02005121 SSL_MODE_ENABLE_PARTIAL_WRITE |
5122 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
Willy Tarreau396a1862014-11-13 14:06:52 +01005123 SSL_MODE_RELEASE_BUFFERS |
5124 SSL_MODE_SMALL_BUFFERS;
Emeric Brun850efd52014-01-29 12:24:34 +01005125 int verify = SSL_VERIFY_NONE;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01005126 SSL_CTX *ctx = NULL;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005127 struct tls_version_filter *conf_ssl_methods = &srv->ssl_ctx.methods;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005128 int i, min, max, hole;
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005129 int flags = MC_SSL_O_ALL;
Emeric Brun94324a42012-10-11 14:00:19 +02005130
Thierry Fournier383085f2013-01-24 14:15:43 +01005131 /* Make sure openssl opens /dev/urandom before the chroot */
5132 if (!ssl_initialize_random()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005133 ha_alert("OpenSSL random data generator initialization failed.\n");
Thierry Fournier383085f2013-01-24 14:15:43 +01005134 cfgerr++;
5135 }
5136
Willy Tarreaufce03112015-01-15 21:32:40 +01005137 /* Automatic memory computations need to know we use SSL there */
5138 global.ssl_used_backend = 1;
5139
5140 /* Initiate SSL context for current server */
Emeric Brun821bb9b2017-06-15 16:37:39 +02005141 if (!srv->ssl_ctx.reused_sess) {
Olivier Houcharde6060c52017-11-16 17:42:52 +01005142 if ((srv->ssl_ctx.reused_sess = calloc(1, global.nbthread*sizeof(*srv->ssl_ctx.reused_sess))) == NULL) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005143 ha_alert("Proxy '%s', server '%s' [%s:%d] out of memory.\n",
5144 curproxy->id, srv->id,
5145 srv->conf.file, srv->conf.line);
Emeric Brun821bb9b2017-06-15 16:37:39 +02005146 cfgerr++;
5147 return cfgerr;
5148 }
5149 }
Emeric Brun94324a42012-10-11 14:00:19 +02005150 if (srv->use_ssl)
5151 srv->xprt = &ssl_sock;
5152 if (srv->check.use_ssl)
Cyril Bonté9ce13112014-11-15 22:41:27 +01005153 srv->check.xprt = &ssl_sock;
Emeric Brun94324a42012-10-11 14:00:19 +02005154
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005155 ctx = SSL_CTX_new(SSLv23_client_method());
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01005156 if (!ctx) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005157 ha_alert("config : %s '%s', server '%s': unable to allocate ssl context.\n",
5158 proxy_type_str(curproxy), curproxy->id,
5159 srv->id);
Emeric Brun94324a42012-10-11 14:00:19 +02005160 cfgerr++;
5161 return cfgerr;
5162 }
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005163
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005164 if (conf_ssl_methods->flags && (conf_ssl_methods->min || conf_ssl_methods->max))
Christopher Faulet767a84b2017-11-24 16:50:31 +01005165 ha_warning("config : %s '%s': no-sslv3/no-tlsv1x are ignored for server '%s'. "
5166 "Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
5167 proxy_type_str(curproxy), curproxy->id, srv->id);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005168 else
5169 flags = conf_ssl_methods->flags;
5170
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005171 /* Real min and max should be determinate with configuration and openssl's capabilities */
5172 if (conf_ssl_methods->min)
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005173 flags |= (methodVersions[conf_ssl_methods->min].flag - 1);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005174 if (conf_ssl_methods->max)
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005175 flags |= ~((methodVersions[conf_ssl_methods->max].flag << 1) - 1);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005176
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02005177 /* find min, max and holes */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005178 min = max = CONF_TLSV_NONE;
5179 hole = 0;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005180 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005181 /* version is in openssl && version not disable in configuration */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005182 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005183 if (min) {
5184 if (hole) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005185 ha_warning("config : %s '%s': SSL/TLS versions range not contiguous for server '%s'. "
5186 "Hole find for %s. Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
5187 proxy_type_str(curproxy), curproxy->id, srv->id,
5188 methodVersions[hole].name);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005189 hole = 0;
5190 }
5191 max = i;
5192 }
5193 else {
5194 min = max = i;
5195 }
5196 }
5197 else {
5198 if (min)
5199 hole = i;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005200 }
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005201 if (!min) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005202 ha_alert("config : %s '%s': all SSL/TLS versions are disabled for server '%s'.\n",
5203 proxy_type_str(curproxy), curproxy->id, srv->id);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005204 cfgerr += 1;
5205 }
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005206
Willy Tarreau9a1ab082019-05-09 13:26:41 +02005207#if (HA_OPENSSL_VERSION_NUMBER < 0x1010000fL)
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005208 /* Keep force-xxx implementation as it is in older haproxy. It's a
Joseph Herlant017b3da2018-11-15 09:07:59 -08005209 precautionary measure to avoid any surprise with older openssl version. */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005210 if (min == max)
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02005211 methodVersions[min].ctx_set_version(ctx, SET_CLIENT);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005212 else
5213 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
5214 if (flags & methodVersions[i].flag)
5215 options |= methodVersions[i].option;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005216#else /* openssl >= 1.1.0 */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005217 /* set the max_version is required to cap TLS version or activate new TLS (v1.3) */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02005218 methodVersions[min].ctx_set_version(ctx, SET_MIN);
5219 methodVersions[max].ctx_set_version(ctx, SET_MAX);
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005220#endif
5221
5222 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLS_TICKETS)
5223 options |= SSL_OP_NO_TICKET;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01005224 SSL_CTX_set_options(ctx, options);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005225
Willy Tarreau5db847a2019-05-09 14:13:35 +02005226#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005227 if (global_ssl.async)
5228 mode |= SSL_MODE_ASYNC;
5229#endif
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01005230 SSL_CTX_set_mode(ctx, mode);
5231 srv->ssl_ctx.ctx = ctx;
5232
Emeric Bruna7aa3092012-10-26 12:58:00 +02005233 if (srv->ssl_ctx.client_crt) {
5234 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 +01005235 ha_alert("config : %s '%s', server '%s': unable to load SSL private key from PEM file '%s'.\n",
5236 proxy_type_str(curproxy), curproxy->id,
5237 srv->id, srv->ssl_ctx.client_crt);
Emeric Bruna7aa3092012-10-26 12:58:00 +02005238 cfgerr++;
5239 }
5240 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 +01005241 ha_alert("config : %s '%s', server '%s': unable to load ssl certificate from PEM file '%s'.\n",
5242 proxy_type_str(curproxy), curproxy->id,
5243 srv->id, srv->ssl_ctx.client_crt);
Emeric Bruna7aa3092012-10-26 12:58:00 +02005244 cfgerr++;
5245 }
5246 else if (SSL_CTX_check_private_key(srv->ssl_ctx.ctx) <= 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005247 ha_alert("config : %s '%s', server '%s': inconsistencies between private key and certificate loaded from PEM file '%s'.\n",
5248 proxy_type_str(curproxy), curproxy->id,
5249 srv->id, srv->ssl_ctx.client_crt);
Emeric Bruna7aa3092012-10-26 12:58:00 +02005250 cfgerr++;
5251 }
5252 }
Emeric Brun94324a42012-10-11 14:00:19 +02005253
Emeric Brun850efd52014-01-29 12:24:34 +01005254 if (global.ssl_server_verify == SSL_SERVER_VERIFY_REQUIRED)
5255 verify = SSL_VERIFY_PEER;
Emeric Brun850efd52014-01-29 12:24:34 +01005256 switch (srv->ssl_ctx.verify) {
5257 case SSL_SOCK_VERIFY_NONE:
5258 verify = SSL_VERIFY_NONE;
5259 break;
5260 case SSL_SOCK_VERIFY_REQUIRED:
5261 verify = SSL_VERIFY_PEER;
5262 break;
5263 }
Evan Broderbe554312013-06-27 00:05:25 -07005264 SSL_CTX_set_verify(srv->ssl_ctx.ctx,
Emeric Brun850efd52014-01-29 12:24:34 +01005265 verify,
Willy Tarreau2ab88672017-07-05 18:23:03 +02005266 (srv->ssl_ctx.verify_host || (verify & SSL_VERIFY_PEER)) ? ssl_sock_srv_verifycbk : NULL);
Emeric Brun850efd52014-01-29 12:24:34 +01005267 if (verify & SSL_VERIFY_PEER) {
Emeric Brunef42d922012-10-11 16:11:36 +02005268 if (srv->ssl_ctx.ca_file) {
5269 /* load CAfile to verify */
5270 if (!SSL_CTX_load_verify_locations(srv->ssl_ctx.ctx, srv->ssl_ctx.ca_file, NULL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005271 ha_alert("Proxy '%s', server '%s' [%s:%d] unable to load CA file '%s'.\n",
5272 curproxy->id, srv->id,
5273 srv->conf.file, srv->conf.line, srv->ssl_ctx.ca_file);
Emeric Brunef42d922012-10-11 16:11:36 +02005274 cfgerr++;
5275 }
5276 }
Emeric Brun850efd52014-01-29 12:24:34 +01005277 else {
5278 if (global.ssl_server_verify == SSL_SERVER_VERIFY_REQUIRED)
Christopher Faulet767a84b2017-11-24 16:50:31 +01005279 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",
5280 curproxy->id, srv->id,
5281 srv->conf.file, srv->conf.line);
Emeric Brun850efd52014-01-29 12:24:34 +01005282 else
Christopher Faulet767a84b2017-11-24 16:50:31 +01005283 ha_alert("Proxy '%s', server '%s' [%s:%d] verify is enabled but no CA file specified.\n",
5284 curproxy->id, srv->id,
5285 srv->conf.file, srv->conf.line);
Emeric Brun850efd52014-01-29 12:24:34 +01005286 cfgerr++;
5287 }
Emeric Brunef42d922012-10-11 16:11:36 +02005288#ifdef X509_V_FLAG_CRL_CHECK
5289 if (srv->ssl_ctx.crl_file) {
5290 X509_STORE *store = SSL_CTX_get_cert_store(srv->ssl_ctx.ctx);
5291
5292 if (!store || !X509_STORE_load_locations(store, srv->ssl_ctx.crl_file, NULL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005293 ha_alert("Proxy '%s', server '%s' [%s:%d] unable to configure CRL file '%s'.\n",
5294 curproxy->id, srv->id,
5295 srv->conf.file, srv->conf.line, srv->ssl_ctx.crl_file);
Emeric Brunef42d922012-10-11 16:11:36 +02005296 cfgerr++;
5297 }
5298 else {
5299 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
5300 }
5301 }
5302#endif
5303 }
5304
Olivier Houchardbd84ac82017-11-03 13:43:35 +01005305 SSL_CTX_set_session_cache_mode(srv->ssl_ctx.ctx, SSL_SESS_CACHE_CLIENT |
5306 SSL_SESS_CACHE_NO_INTERNAL_STORE);
5307 SSL_CTX_sess_set_new_cb(srv->ssl_ctx.ctx, ssl_sess_new_srv_cb);
Emeric Brun94324a42012-10-11 14:00:19 +02005308 if (srv->ssl_ctx.ciphers &&
5309 !SSL_CTX_set_cipher_list(srv->ssl_ctx.ctx, srv->ssl_ctx.ciphers)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005310 ha_alert("Proxy '%s', server '%s' [%s:%d] : unable to set SSL cipher list to '%s'.\n",
5311 curproxy->id, srv->id,
5312 srv->conf.file, srv->conf.line, srv->ssl_ctx.ciphers);
Emeric Brun94324a42012-10-11 14:00:19 +02005313 cfgerr++;
5314 }
Dirkjan Bussink415150f2018-09-14 11:14:21 +02005315
Emmanuel Hocdet839af572019-05-14 16:27:35 +02005316#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02005317 if (srv->ssl_ctx.ciphersuites &&
Pierre Cheynierbc34cd12019-03-21 16:15:47 +00005318 !SSL_CTX_set_ciphersuites(srv->ssl_ctx.ctx, srv->ssl_ctx.ciphersuites)) {
Dirkjan Bussink415150f2018-09-14 11:14:21 +02005319 ha_alert("Proxy '%s', server '%s' [%s:%d] : unable to set TLS 1.3 cipher suites to '%s'.\n",
5320 curproxy->id, srv->id,
5321 srv->conf.file, srv->conf.line, srv->ssl_ctx.ciphersuites);
5322 cfgerr++;
5323 }
5324#endif
Olivier Houchardc7566002018-11-20 23:33:50 +01005325#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
5326 if (srv->ssl_ctx.npn_str)
5327 SSL_CTX_set_next_proto_select_cb(ctx, ssl_sock_srv_select_protos, srv);
5328#endif
5329#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
5330 if (srv->ssl_ctx.alpn_str)
5331 SSL_CTX_set_alpn_protos(ctx, (unsigned char *)srv->ssl_ctx.alpn_str, srv->ssl_ctx.alpn_len);
5332#endif
5333
Emeric Brun94324a42012-10-11 14:00:19 +02005334
5335 return cfgerr;
5336}
5337
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005338/* Walks down the two trees in bind_conf and prepares all certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +02005339 * be NULL, in which case nothing is done. Returns the number of errors
5340 * encountered.
5341 */
Willy Tarreau03209342016-12-22 17:08:28 +01005342int ssl_sock_prepare_all_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02005343{
5344 struct ebmb_node *node;
5345 struct sni_ctx *sni;
5346 int err = 0;
5347
Willy Tarreaufce03112015-01-15 21:32:40 +01005348 /* Automatic memory computations need to know we use SSL there */
5349 global.ssl_used_frontend = 1;
5350
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01005351 /* Make sure openssl opens /dev/urandom before the chroot */
5352 if (!ssl_initialize_random()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005353 ha_alert("OpenSSL random data generator initialization failed.\n");
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01005354 err++;
5355 }
5356 /* Create initial_ctx used to start the ssl connection before do switchctx */
5357 if (!bind_conf->initial_ctx) {
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005358 err += ssl_sock_initial_ctx(bind_conf);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01005359 /* It should not be necessary to call this function, but it's
5360 necessary first to check and move all initialisation related
5361 to initial_ctx in ssl_sock_initial_ctx. */
5362 err += ssl_sock_prepare_ctx(bind_conf, NULL, bind_conf->initial_ctx);
5363 }
Emeric Brun0bed9942014-10-30 19:25:24 +01005364 if (bind_conf->default_ctx)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005365 err += ssl_sock_prepare_ctx(bind_conf, bind_conf->default_ssl_conf, bind_conf->default_ctx);
Emeric Brun0bed9942014-10-30 19:25:24 +01005366
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005367 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02005368 while (node) {
5369 sni = ebmb_entry(node, struct sni_ctx, name);
Emeric Brun0bed9942014-10-30 19:25:24 +01005370 if (!sni->order && sni->ctx != bind_conf->default_ctx)
5371 /* only initialize the CTX on its first occurrence and
5372 if it is not the default_ctx */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005373 err += ssl_sock_prepare_ctx(bind_conf, sni->conf, sni->ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02005374 node = ebmb_next(node);
5375 }
5376
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005377 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02005378 while (node) {
5379 sni = ebmb_entry(node, struct sni_ctx, name);
Emeric Brun0bed9942014-10-30 19:25:24 +01005380 if (!sni->order && sni->ctx != bind_conf->default_ctx)
5381 /* only initialize the CTX on its first occurrence and
5382 if it is not the default_ctx */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005383 err += ssl_sock_prepare_ctx(bind_conf, sni->conf, sni->ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02005384 node = ebmb_next(node);
5385 }
5386 return err;
5387}
5388
Willy Tarreau55d37912016-12-21 23:38:39 +01005389/* Prepares all the contexts for a bind_conf and allocates the shared SSL
5390 * context if needed. Returns < 0 on error, 0 on success. The warnings and
5391 * alerts are directly emitted since the rest of the stack does it below.
5392 */
5393int ssl_sock_prepare_bind_conf(struct bind_conf *bind_conf)
5394{
5395 struct proxy *px = bind_conf->frontend;
5396 int alloc_ctx;
5397 int err;
5398
5399 if (!bind_conf->is_ssl) {
5400 if (bind_conf->default_ctx) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005401 ha_warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
5402 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreau55d37912016-12-21 23:38:39 +01005403 }
5404 return 0;
5405 }
5406 if (!bind_conf->default_ctx) {
Emmanuel Hocdetaa0d6372017-08-09 11:24:25 +02005407 if (bind_conf->strict_sni && !bind_conf->generate_certs) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005408 ha_warning("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d], ssl connections will fail (use 'crt').\n",
5409 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetaa0d6372017-08-09 11:24:25 +02005410 }
5411 else {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005412 ha_alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
5413 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetaa0d6372017-08-09 11:24:25 +02005414 return -1;
5415 }
Willy Tarreau55d37912016-12-21 23:38:39 +01005416 }
William Lallemandc61c0b32017-12-04 18:46:39 +01005417 if (!ssl_shctx && global.tune.sslcachesize) {
William Lallemandc3cd35f2017-11-28 11:04:43 +01005418 alloc_ctx = shctx_init(&ssl_shctx, global.tune.sslcachesize,
Frédéric Lécailleb7838af2018-10-22 16:21:39 +02005419 sizeof(struct sh_ssl_sess_hdr) + SHSESS_BLOCK_MIN_SIZE, -1,
William Lallemandc3cd35f2017-11-28 11:04:43 +01005420 sizeof(*sh_ssl_sess_tree),
5421 ((global.nbthread > 1) || (!global_ssl.private_cache && (global.nbproc > 1))) ? 1 : 0);
Frédéric Lécaille4c8aa112018-10-25 20:22:46 +02005422 if (alloc_ctx <= 0) {
William Lallemandc3cd35f2017-11-28 11:04:43 +01005423 if (alloc_ctx == SHCTX_E_INIT_LOCK)
5424 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");
5425 else
5426 ha_alert("Unable to allocate SSL session cache.\n");
5427 return -1;
5428 }
5429 /* free block callback */
5430 ssl_shctx->free_block = sh_ssl_sess_free_blocks;
5431 /* init the root tree within the extra space */
5432 sh_ssl_sess_tree = (void *)ssl_shctx + sizeof(struct shared_context);
5433 *sh_ssl_sess_tree = EB_ROOT_UNIQUE;
Willy Tarreau55d37912016-12-21 23:38:39 +01005434 }
Willy Tarreau55d37912016-12-21 23:38:39 +01005435 err = 0;
5436 /* initialize all certificate contexts */
5437 err += ssl_sock_prepare_all_ctx(bind_conf);
5438
5439 /* initialize CA variables if the certificates generation is enabled */
5440 err += ssl_sock_load_ca(bind_conf);
5441
5442 return -err;
5443}
Christopher Faulet77fe80c2015-07-29 13:02:40 +02005444
5445/* release ssl context allocated for servers. */
5446void ssl_sock_free_srv_ctx(struct server *srv)
5447{
Olivier Houchardc7566002018-11-20 23:33:50 +01005448#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
5449 if (srv->ssl_ctx.alpn_str)
5450 free(srv->ssl_ctx.alpn_str);
5451#endif
Lukas Tribusda95fd92018-11-25 13:21:27 +01005452#ifdef OPENSSL_NPN_NEGOTIATED
Olivier Houchardc7566002018-11-20 23:33:50 +01005453 if (srv->ssl_ctx.npn_str)
5454 free(srv->ssl_ctx.npn_str);
Lukas Tribus7706b852018-11-26 22:57:17 +01005455#endif
Christopher Faulet77fe80c2015-07-29 13:02:40 +02005456 if (srv->ssl_ctx.ctx)
5457 SSL_CTX_free(srv->ssl_ctx.ctx);
5458}
5459
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005460/* Walks down the two trees in bind_conf and frees all the certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +02005461 * be NULL, in which case nothing is done. The default_ctx is nullified too.
5462 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005463void ssl_sock_free_all_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02005464{
5465 struct ebmb_node *node, *back;
5466 struct sni_ctx *sni;
5467
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005468 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02005469 while (node) {
5470 sni = ebmb_entry(node, struct sni_ctx, name);
5471 back = ebmb_next(node);
5472 ebmb_delete(node);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005473 if (!sni->order) { /* only free the CTX on its first occurrence */
Emeric Brunfc0421f2012-09-07 17:30:07 +02005474 SSL_CTX_free(sni->ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005475 ssl_sock_free_ssl_conf(sni->conf);
5476 free(sni->conf);
5477 sni->conf = NULL;
5478 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02005479 free(sni);
5480 node = back;
5481 }
5482
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005483 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02005484 while (node) {
5485 sni = ebmb_entry(node, struct sni_ctx, name);
5486 back = ebmb_next(node);
5487 ebmb_delete(node);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005488 if (!sni->order) { /* only free the CTX on its first occurrence */
Emeric Brunfc0421f2012-09-07 17:30:07 +02005489 SSL_CTX_free(sni->ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005490 ssl_sock_free_ssl_conf(sni->conf);
5491 free(sni->conf);
5492 sni->conf = NULL;
5493 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02005494 free(sni);
5495 node = back;
5496 }
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01005497 SSL_CTX_free(bind_conf->initial_ctx);
5498 bind_conf->initial_ctx = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005499 bind_conf->default_ctx = NULL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005500 bind_conf->default_ssl_conf = NULL;
Emeric Brune1f38db2012-09-03 20:36:47 +02005501}
5502
Willy Tarreau795cdab2016-12-22 17:30:54 +01005503/* Destroys all the contexts for a bind_conf. This is used during deinit(). */
5504void ssl_sock_destroy_bind_conf(struct bind_conf *bind_conf)
5505{
5506 ssl_sock_free_ca(bind_conf);
5507 ssl_sock_free_all_ctx(bind_conf);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005508 ssl_sock_free_ssl_conf(&bind_conf->ssl_conf);
Willy Tarreau795cdab2016-12-22 17:30:54 +01005509 free(bind_conf->ca_sign_file);
5510 free(bind_conf->ca_sign_pass);
Willy Tarreau17b4aa12018-07-17 10:05:32 +02005511 if (bind_conf->keys_ref && !--bind_conf->keys_ref->refcount) {
Willy Tarreau795cdab2016-12-22 17:30:54 +01005512 free(bind_conf->keys_ref->filename);
5513 free(bind_conf->keys_ref->tlskeys);
5514 LIST_DEL(&bind_conf->keys_ref->list);
5515 free(bind_conf->keys_ref);
5516 }
5517 bind_conf->keys_ref = NULL;
Willy Tarreau795cdab2016-12-22 17:30:54 +01005518 bind_conf->ca_sign_pass = NULL;
5519 bind_conf->ca_sign_file = NULL;
Willy Tarreau795cdab2016-12-22 17:30:54 +01005520}
5521
Christopher Faulet31af49d2015-06-09 17:29:50 +02005522/* Load CA cert file and private key used to generate certificates */
5523int
Willy Tarreau03209342016-12-22 17:08:28 +01005524ssl_sock_load_ca(struct bind_conf *bind_conf)
Christopher Faulet31af49d2015-06-09 17:29:50 +02005525{
Willy Tarreau03209342016-12-22 17:08:28 +01005526 struct proxy *px = bind_conf->frontend;
Christopher Faulet31af49d2015-06-09 17:29:50 +02005527 FILE *fp;
5528 X509 *cacert = NULL;
5529 EVP_PKEY *capkey = NULL;
5530 int err = 0;
5531
Christopher Fauletf8bb0ce2017-09-15 09:52:49 +02005532 if (!bind_conf->generate_certs)
Christopher Faulet31af49d2015-06-09 17:29:50 +02005533 return err;
5534
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005535#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Emeric Brun821bb9b2017-06-15 16:37:39 +02005536 if (global_ssl.ctx_cache) {
Willy Tarreauef934602016-12-22 23:12:01 +01005537 ssl_ctx_lru_tree = lru64_new(global_ssl.ctx_cache);
Emeric Brun821bb9b2017-06-15 16:37:39 +02005538 }
Christopher Fauletd2cab922015-07-28 16:03:47 +02005539 ssl_ctx_lru_seed = (unsigned int)time(NULL);
Emeric Brun821bb9b2017-06-15 16:37:39 +02005540 ssl_ctx_serial = now_ms;
Willy Tarreaua84c2672015-10-09 12:10:13 +02005541#endif
Christopher Fauletd2cab922015-07-28 16:03:47 +02005542
Christopher Faulet31af49d2015-06-09 17:29:50 +02005543 if (!bind_conf->ca_sign_file) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005544 ha_alert("Proxy '%s': cannot enable certificate generation, "
5545 "no CA certificate File configured at [%s:%d].\n",
5546 px->id, bind_conf->file, bind_conf->line);
Christopher Faulet31af49d2015-06-09 17:29:50 +02005547 goto load_error;
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005548 }
Christopher Faulet31af49d2015-06-09 17:29:50 +02005549
5550 /* read in the CA certificate */
5551 if (!(fp = fopen(bind_conf->ca_sign_file, "r"))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005552 ha_alert("Proxy '%s': Failed to read CA certificate file '%s' at [%s:%d].\n",
5553 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Faulet31af49d2015-06-09 17:29:50 +02005554 goto load_error;
5555 }
5556 if (!(cacert = PEM_read_X509(fp, NULL, NULL, NULL))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005557 ha_alert("Proxy '%s': Failed to read CA certificate file '%s' at [%s:%d].\n",
5558 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005559 goto read_error;
Christopher Faulet31af49d2015-06-09 17:29:50 +02005560 }
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005561 rewind(fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02005562 if (!(capkey = PEM_read_PrivateKey(fp, NULL, NULL, bind_conf->ca_sign_pass))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005563 ha_alert("Proxy '%s': Failed to read CA private key file '%s' at [%s:%d].\n",
5564 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005565 goto read_error;
Christopher Faulet31af49d2015-06-09 17:29:50 +02005566 }
Christopher Faulet31af49d2015-06-09 17:29:50 +02005567
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005568 fclose (fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02005569 bind_conf->ca_sign_cert = cacert;
5570 bind_conf->ca_sign_pkey = capkey;
5571 return err;
5572
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005573 read_error:
5574 fclose (fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02005575 if (capkey) EVP_PKEY_free(capkey);
5576 if (cacert) X509_free(cacert);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005577 load_error:
5578 bind_conf->generate_certs = 0;
5579 err++;
Christopher Faulet31af49d2015-06-09 17:29:50 +02005580 return err;
5581}
5582
5583/* Release CA cert and private key used to generate certificated */
5584void
5585ssl_sock_free_ca(struct bind_conf *bind_conf)
5586{
Christopher Faulet31af49d2015-06-09 17:29:50 +02005587 if (bind_conf->ca_sign_pkey)
5588 EVP_PKEY_free(bind_conf->ca_sign_pkey);
5589 if (bind_conf->ca_sign_cert)
5590 X509_free(bind_conf->ca_sign_cert);
Willy Tarreau94ff03a2016-12-22 17:57:46 +01005591 bind_conf->ca_sign_pkey = NULL;
5592 bind_conf->ca_sign_cert = NULL;
Christopher Faulet31af49d2015-06-09 17:29:50 +02005593}
5594
Emeric Brun46591952012-05-18 15:47:34 +02005595/*
5596 * This function is called if SSL * context is not yet allocated. The function
5597 * is designed to be called before any other data-layer operation and sets the
5598 * handshake flag on the connection. It is safe to call it multiple times.
5599 * It returns 0 on success and -1 in error case.
5600 */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005601static int ssl_sock_init(struct connection *conn, void **xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02005602{
Olivier Houchard66ab4982019-02-26 18:37:15 +01005603 struct ssl_sock_ctx *ctx;
Emeric Brun46591952012-05-18 15:47:34 +02005604 /* already initialized */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005605 if (*xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02005606 return 0;
5607
Willy Tarreau3c728722014-01-23 13:50:42 +01005608 if (!conn_ctrl_ready(conn))
Willy Tarreauf79c8172013-10-21 16:30:56 +02005609 return 0;
5610
Olivier Houchard66ab4982019-02-26 18:37:15 +01005611 ctx = pool_alloc(ssl_sock_ctx_pool);
5612 if (!ctx) {
5613 conn->err_code = CO_ER_SSL_NO_MEM;
5614 return -1;
5615 }
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02005616 ctx->wait_event.tasklet = tasklet_new();
5617 if (!ctx->wait_event.tasklet) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02005618 conn->err_code = CO_ER_SSL_NO_MEM;
5619 pool_free(ssl_sock_ctx_pool, ctx);
5620 return -1;
5621 }
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02005622 ctx->wait_event.tasklet->process = ssl_sock_io_cb;
5623 ctx->wait_event.tasklet->context = ctx;
Olivier Houchardea8dd942019-05-20 14:02:16 +02005624 ctx->wait_event.events = 0;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01005625 ctx->sent_early_data = 0;
5626 ctx->tmp_early_data = -1;
Olivier Houcharda8955d52019-04-07 22:00:38 +02005627 ctx->conn = conn;
Olivier Houchard81284e62019-06-06 13:21:23 +02005628 ctx->send_wait = NULL;
5629 ctx->recv_wait = NULL;
Emeric Brun5762a0d2019-09-06 15:36:02 +02005630 ctx->xprt_st = 0;
5631 ctx->xprt_ctx = NULL;
Olivier Houcharda8955d52019-04-07 22:00:38 +02005632
5633 /* Only work with sockets for now, this should be adapted when we'll
5634 * add QUIC support.
5635 */
5636 ctx->xprt = xprt_get(XPRT_RAW);
Olivier Houchard19afb272019-05-23 18:24:07 +02005637 if (ctx->xprt->init) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02005638 if (ctx->xprt->init(conn, &ctx->xprt_ctx) != 0)
5639 goto err;
Olivier Houchard19afb272019-05-23 18:24:07 +02005640 }
Olivier Houchard66ab4982019-02-26 18:37:15 +01005641
Willy Tarreau20879a02012-12-03 16:32:10 +01005642 if (global.maxsslconn && sslconns >= global.maxsslconn) {
5643 conn->err_code = CO_ER_SSL_TOO_MANY;
Olivier Houchardea8dd942019-05-20 14:02:16 +02005644 goto err;
Willy Tarreau20879a02012-12-03 16:32:10 +01005645 }
Willy Tarreau403edff2012-09-06 11:58:37 +02005646
Emeric Brun46591952012-05-18 15:47:34 +02005647 /* If it is in client mode initiate SSL session
5648 in connect state otherwise accept state */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01005649 if (objt_server(conn->target)) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005650 int may_retry = 1;
5651
5652 retry_connect:
Emeric Brun46591952012-05-18 15:47:34 +02005653 /* Alloc a new SSL session ctx */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005654 ctx->ssl = SSL_new(__objt_server(conn->target)->ssl_ctx.ctx);
5655 if (!ctx->ssl) {
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_connect;
5659 }
Willy Tarreau20879a02012-12-03 16:32:10 +01005660 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01005661 goto err;
Willy Tarreau20879a02012-12-03 16:32:10 +01005662 }
Olivier Houcharda8955d52019-04-07 22:00:38 +02005663 ctx->bio = BIO_new(ha_meth);
5664 if (!ctx->bio) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005665 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005666 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005667 goto retry_connect;
5668 }
Emeric Brun55476152014-11-12 17:35:37 +01005669 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01005670 goto err;
Emeric Brun55476152014-11-12 17:35:37 +01005671 }
Olivier Houcharda8955d52019-04-07 22:00:38 +02005672 BIO_set_data(ctx->bio, ctx);
Olivier Houcharda8955d52019-04-07 22:00:38 +02005673 SSL_set_bio(ctx->ssl, ctx->bio, ctx->bio);
Emeric Brun46591952012-05-18 15:47:34 +02005674
Evan Broderbe554312013-06-27 00:05:25 -07005675 /* set connection pointer */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005676 if (!SSL_set_ex_data(ctx->ssl, ssl_app_data_index, conn)) {
5677 SSL_free(ctx->ssl);
5678 ctx->ssl = NULL;
Emeric Brun55476152014-11-12 17:35:37 +01005679 conn->xprt_ctx = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005680 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005681 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005682 goto retry_connect;
5683 }
Emeric Brun55476152014-11-12 17:35:37 +01005684 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01005685 goto err;
Emeric Brun55476152014-11-12 17:35:37 +01005686 }
5687
Olivier Houchard66ab4982019-02-26 18:37:15 +01005688 SSL_set_connect_state(ctx->ssl);
Willy Tarreau07d94e42018-09-20 10:57:52 +02005689 if (__objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr) {
5690 const unsigned char *ptr = __objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr;
5691 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 +01005692 if (sess && !SSL_set_session(ctx->ssl, sess)) {
Olivier Houcharde6060c52017-11-16 17:42:52 +01005693 SSL_SESSION_free(sess);
Willy Tarreau07d94e42018-09-20 10:57:52 +02005694 free(__objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr);
5695 __objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr = NULL;
Olivier Houcharde6060c52017-11-16 17:42:52 +01005696 } else if (sess) {
5697 SSL_SESSION_free(sess);
Emeric Brun55476152014-11-12 17:35:37 +01005698 }
5699 }
Evan Broderbe554312013-06-27 00:05:25 -07005700
Emeric Brun46591952012-05-18 15:47:34 +02005701 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +02005702 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Willy Tarreau403edff2012-09-06 11:58:37 +02005703
Olivier Houchard2be5a4c2019-03-08 18:54:43 +01005704 _HA_ATOMIC_ADD(&sslconns, 1);
5705 _HA_ATOMIC_ADD(&totalsslconns, 1);
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005706 *xprt_ctx = ctx;
Olivier Houchardea8dd942019-05-20 14:02:16 +02005707 /* Start the handshake */
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02005708 tasklet_wakeup(ctx->wait_event.tasklet);
Olivier Houchardea8dd942019-05-20 14:02:16 +02005709 if (conn->flags & CO_FL_ERROR)
5710 goto err;
Emeric Brun46591952012-05-18 15:47:34 +02005711 return 0;
5712 }
Willy Tarreau3fdb3662012-11-12 00:42:33 +01005713 else if (objt_listener(conn->target)) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005714 int may_retry = 1;
5715
5716 retry_accept:
Emeric Brun46591952012-05-18 15:47:34 +02005717 /* Alloc a new SSL session ctx */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005718 ctx->ssl = SSL_new(__objt_listener(conn->target)->bind_conf->initial_ctx);
5719 if (!ctx->ssl) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005720 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005721 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005722 goto retry_accept;
5723 }
Willy Tarreau20879a02012-12-03 16:32:10 +01005724 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01005725 goto err;
Willy Tarreau20879a02012-12-03 16:32:10 +01005726 }
Emeric Brun46591952012-05-18 15:47:34 +02005727
Olivier Houcharda8955d52019-04-07 22:00:38 +02005728 ctx->bio = BIO_new(ha_meth);
5729 if (!ctx->bio) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005730 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005731 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005732 goto retry_accept;
5733 }
Emeric Brun55476152014-11-12 17:35:37 +01005734 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01005735 goto err;
Emeric Brun55476152014-11-12 17:35:37 +01005736 }
Olivier Houcharda8955d52019-04-07 22:00:38 +02005737 BIO_set_data(ctx->bio, ctx);
Olivier Houcharda8955d52019-04-07 22:00:38 +02005738 SSL_set_bio(ctx->ssl, ctx->bio, ctx->bio);
Emeric Brun46591952012-05-18 15:47:34 +02005739
Emeric Brune1f38db2012-09-03 20:36:47 +02005740 /* set connection pointer */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005741 if (!SSL_set_ex_data(ctx->ssl, ssl_app_data_index, conn)) {
5742 SSL_free(ctx->ssl);
5743 ctx->ssl = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005744 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005745 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005746 goto retry_accept;
5747 }
Emeric Brun55476152014-11-12 17:35:37 +01005748 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01005749 goto err;
Emeric Brun55476152014-11-12 17:35:37 +01005750 }
5751
Olivier Houchard66ab4982019-02-26 18:37:15 +01005752 SSL_set_accept_state(ctx->ssl);
Emeric Brune1f38db2012-09-03 20:36:47 +02005753
Emeric Brun46591952012-05-18 15:47:34 +02005754 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +02005755 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Emmanuel Hocdetf967c312019-08-05 18:04:16 +02005756#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Olivier Houchardc2aae742017-09-22 18:26:28 +02005757 conn->flags |= CO_FL_EARLY_SSL_HS;
5758#endif
Willy Tarreau403edff2012-09-06 11:58:37 +02005759
Olivier Houchard2be5a4c2019-03-08 18:54:43 +01005760 _HA_ATOMIC_ADD(&sslconns, 1);
5761 _HA_ATOMIC_ADD(&totalsslconns, 1);
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005762 *xprt_ctx = ctx;
Olivier Houchardea8dd942019-05-20 14:02:16 +02005763 /* Start the handshake */
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02005764 tasklet_wakeup(ctx->wait_event.tasklet);
Olivier Houchardea8dd942019-05-20 14:02:16 +02005765 if (conn->flags & CO_FL_ERROR)
5766 goto err;
Emeric Brun46591952012-05-18 15:47:34 +02005767 return 0;
5768 }
5769 /* don't know how to handle such a target */
Willy Tarreau20879a02012-12-03 16:32:10 +01005770 conn->err_code = CO_ER_SSL_NO_TARGET;
Olivier Houchard66ab4982019-02-26 18:37:15 +01005771err:
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02005772 if (ctx && ctx->wait_event.tasklet)
5773 tasklet_free(ctx->wait_event.tasklet);
Olivier Houchard66ab4982019-02-26 18:37:15 +01005774 pool_free(ssl_sock_ctx_pool, ctx);
Emeric Brun46591952012-05-18 15:47:34 +02005775 return -1;
5776}
5777
5778
5779/* This is the callback which is used when an SSL handshake is pending. It
5780 * updates the FD status if it wants some polling before being called again.
5781 * It returns 0 if it fails in a fatal way or needs to poll to go further,
5782 * otherwise it returns non-zero and removes itself from the connection's
5783 * flags (the bit is provided in <flag> by the caller).
5784 */
Olivier Houchard000694c2019-05-23 14:45:12 +02005785static int ssl_sock_handshake(struct connection *conn, unsigned int flag)
Emeric Brun46591952012-05-18 15:47:34 +02005786{
Olivier Houchard66ab4982019-02-26 18:37:15 +01005787 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
Emeric Brun46591952012-05-18 15:47:34 +02005788 int ret;
5789
Willy Tarreau3c728722014-01-23 13:50:42 +01005790 if (!conn_ctrl_ready(conn))
Willy Tarreauf79c8172013-10-21 16:30:56 +02005791 return 0;
5792
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005793 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02005794 goto out_error;
5795
Willy Tarreau5db847a2019-05-09 14:13:35 +02005796#if HA_OPENSSL_VERSION_NUMBER >= 0x10101000L
Olivier Houchardc2aae742017-09-22 18:26:28 +02005797 /*
5798 * Check if we have early data. If we do, we have to read them
5799 * before SSL_do_handshake() is called, And there's no way to
5800 * detect early data, except to try to read them
5801 */
5802 if (conn->flags & CO_FL_EARLY_SSL_HS) {
5803 size_t read_data;
5804
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01005805 ret = SSL_read_early_data(ctx->ssl, &ctx->tmp_early_data,
Olivier Houchardc2aae742017-09-22 18:26:28 +02005806 1, &read_data);
5807 if (ret == SSL_READ_EARLY_DATA_ERROR)
5808 goto check_error;
5809 if (ret == SSL_READ_EARLY_DATA_SUCCESS) {
5810 conn->flags &= ~(CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN);
5811 return 1;
5812 } else
5813 conn->flags &= ~CO_FL_EARLY_SSL_HS;
5814 }
5815#endif
Emeric Brun674b7432012-11-08 19:21:55 +01005816 /* If we use SSL_do_handshake to process a reneg initiated by
5817 * the remote peer, it sometimes returns SSL_ERROR_SSL.
5818 * Usually SSL_write and SSL_read are used and process implicitly
5819 * the reneg handshake.
5820 * Here we use SSL_peek as a workaround for reneg.
5821 */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005822 if ((conn->flags & CO_FL_CONNECTED) && SSL_renegotiate_pending(ctx->ssl)) {
Emeric Brun674b7432012-11-08 19:21:55 +01005823 char c;
5824
Olivier Houchard66ab4982019-02-26 18:37:15 +01005825 ret = SSL_peek(ctx->ssl, &c, 1);
Emeric Brun674b7432012-11-08 19:21:55 +01005826 if (ret <= 0) {
5827 /* handshake may have not been completed, let's find why */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005828 ret = SSL_get_error(ctx->ssl, ret);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005829
Emeric Brun674b7432012-11-08 19:21:55 +01005830 if (ret == SSL_ERROR_WANT_WRITE) {
5831 /* SSL handshake needs to write, L4 connection may not be ready */
Olivier Houchard03abf2d2019-05-28 10:12:02 +02005832 if (!(ctx->wait_event.events & SUB_RETRY_SEND))
Olivier Houchardea8dd942019-05-20 14:02:16 +02005833 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_SEND, &ctx->wait_event);
Emeric Brun674b7432012-11-08 19:21:55 +01005834 return 0;
5835 }
5836 else if (ret == SSL_ERROR_WANT_READ) {
5837 /* handshake may have been completed but we have
5838 * no more data to read.
5839 */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005840 if (!SSL_renegotiate_pending(ctx->ssl)) {
Emeric Brun674b7432012-11-08 19:21:55 +01005841 ret = 1;
5842 goto reneg_ok;
5843 }
5844 /* SSL handshake needs to read, L4 connection is ready */
Olivier Houchard03abf2d2019-05-28 10:12:02 +02005845 if (!(ctx->wait_event.events & SUB_RETRY_RECV))
Olivier Houchardea8dd942019-05-20 14:02:16 +02005846 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_RECV, &ctx->wait_event);
Emeric Brun674b7432012-11-08 19:21:55 +01005847 return 0;
5848 }
Willy Tarreau5db847a2019-05-09 14:13:35 +02005849#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005850 else if (ret == SSL_ERROR_WANT_ASYNC) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02005851 ssl_async_process_fds(ctx);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005852 return 0;
5853 }
5854#endif
Emeric Brun674b7432012-11-08 19:21:55 +01005855 else if (ret == SSL_ERROR_SYSCALL) {
5856 /* if errno is null, then connection was successfully established */
5857 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
5858 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Willy Tarreau20879a02012-12-03 16:32:10 +01005859 if (!conn->err_code) {
Lukas Tribus49799162019-07-08 14:29:15 +02005860#if defined(OPENSSL_IS_BORINGSSL) || defined(LIBRESSL_VERSION_NUMBER)
5861 /* do not handle empty handshakes in BoringSSL or LibreSSL */
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005862 conn->err_code = CO_ER_SSL_HANDSHAKE;
5863#else
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005864 int empty_handshake;
Willy Tarreau5db847a2019-05-09 14:13:35 +02005865#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL)
Lukas Tribus49799162019-07-08 14:29:15 +02005866 /* use SSL_get_state() in OpenSSL >= 1.1.0; SSL_state() is broken */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005867 OSSL_HANDSHAKE_STATE state = SSL_get_state((SSL *)ctx->ssl);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005868 empty_handshake = state == TLS_ST_BEFORE;
5869#else
Lukas Tribus49799162019-07-08 14:29:15 +02005870 /* access packet_length directly in OpenSSL <= 1.0.2; SSL_state() is broken */
5871 empty_handshake = !ctx->ssl->packet_length;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005872#endif
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005873 if (empty_handshake) {
Emeric Brun29f037d2014-04-25 19:05:36 +02005874 if (!errno) {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01005875 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emeric Brun29f037d2014-04-25 19:05:36 +02005876 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5877 else
5878 conn->err_code = CO_ER_SSL_EMPTY;
5879 }
5880 else {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01005881 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emeric Brun29f037d2014-04-25 19:05:36 +02005882 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5883 else
5884 conn->err_code = CO_ER_SSL_ABORT;
5885 }
5886 }
5887 else {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01005888 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emeric Brun29f037d2014-04-25 19:05:36 +02005889 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
Willy Tarreau20879a02012-12-03 16:32:10 +01005890 else
Emeric Brun29f037d2014-04-25 19:05:36 +02005891 conn->err_code = CO_ER_SSL_HANDSHAKE;
5892 }
Lukas Tribus49799162019-07-08 14:29:15 +02005893#endif /* BoringSSL or LibreSSL */
Willy Tarreau20879a02012-12-03 16:32:10 +01005894 }
Emeric Brun674b7432012-11-08 19:21:55 +01005895 goto out_error;
5896 }
5897 else {
5898 /* Fail on all other handshake errors */
5899 /* Note: OpenSSL may leave unread bytes in the socket's
5900 * buffer, causing an RST to be emitted upon close() on
5901 * TCP sockets. We first try to drain possibly pending
5902 * data to avoid this as much as possible.
5903 */
Willy Tarreaud85c4852015-03-13 00:40:28 +01005904 conn_sock_drain(conn);
Willy Tarreau20879a02012-12-03 16:32:10 +01005905 if (!conn->err_code)
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01005906 conn->err_code = (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT) ?
Willy Tarreauf51c6982014-04-25 20:02:39 +02005907 CO_ER_SSL_KILLED_HB : CO_ER_SSL_HANDSHAKE;
Emeric Brun674b7432012-11-08 19:21:55 +01005908 goto out_error;
5909 }
5910 }
5911 /* read some data: consider handshake completed */
5912 goto reneg_ok;
5913 }
Olivier Houchard66ab4982019-02-26 18:37:15 +01005914 ret = SSL_do_handshake(ctx->ssl);
Olivier Houchardc2aae742017-09-22 18:26:28 +02005915check_error:
Emeric Brun46591952012-05-18 15:47:34 +02005916 if (ret != 1) {
5917 /* handshake did not complete, let's find why */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005918 ret = SSL_get_error(ctx->ssl, ret);
Emeric Brun46591952012-05-18 15:47:34 +02005919
5920 if (ret == SSL_ERROR_WANT_WRITE) {
5921 /* SSL handshake needs to write, L4 connection may not be ready */
Olivier Houchard03abf2d2019-05-28 10:12:02 +02005922 if (!(ctx->wait_event.events & SUB_RETRY_SEND))
Olivier Houchardea8dd942019-05-20 14:02:16 +02005923 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_SEND, &ctx->wait_event);
Emeric Brun46591952012-05-18 15:47:34 +02005924 return 0;
5925 }
5926 else if (ret == SSL_ERROR_WANT_READ) {
5927 /* SSL handshake needs to read, L4 connection is ready */
Olivier Houchardea8dd942019-05-20 14:02:16 +02005928 if (!(ctx->wait_event.events & SUB_RETRY_RECV))
Olivier Houchardea8dd942019-05-20 14:02:16 +02005929 ctx->xprt->subscribe(conn, ctx->xprt_ctx,
5930 SUB_RETRY_RECV, &ctx->wait_event);
Emeric Brun46591952012-05-18 15:47:34 +02005931 return 0;
5932 }
Willy Tarreau5db847a2019-05-09 14:13:35 +02005933#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005934 else if (ret == SSL_ERROR_WANT_ASYNC) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02005935 ssl_async_process_fds(ctx);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005936 return 0;
5937 }
5938#endif
Willy Tarreau89230192012-09-28 20:22:13 +02005939 else if (ret == SSL_ERROR_SYSCALL) {
5940 /* if errno is null, then connection was successfully established */
5941 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
5942 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005943 if (!conn->err_code) {
Lukas Tribus49799162019-07-08 14:29:15 +02005944#if defined(OPENSSL_IS_BORINGSSL) || defined(LIBRESSL_VERSION_NUMBER)
5945 /* do not handle empty handshakes in BoringSSL or LibreSSL */
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005946 conn->err_code = CO_ER_SSL_HANDSHAKE;
5947#else
5948 int empty_handshake;
Willy Tarreau5db847a2019-05-09 14:13:35 +02005949#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL)
Lukas Tribus49799162019-07-08 14:29:15 +02005950 /* use SSL_get_state() in OpenSSL >= 1.1.0; SSL_state() is broken */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005951 OSSL_HANDSHAKE_STATE state = SSL_get_state(ctx->ssl);
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005952 empty_handshake = state == TLS_ST_BEFORE;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005953#else
Lukas Tribus49799162019-07-08 14:29:15 +02005954 /* access packet_length directly in OpenSSL <= 1.0.2; SSL_state() is broken */
5955 empty_handshake = !ctx->ssl->packet_length;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005956#endif
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005957 if (empty_handshake) {
5958 if (!errno) {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01005959 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005960 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5961 else
5962 conn->err_code = CO_ER_SSL_EMPTY;
5963 }
5964 else {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01005965 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005966 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5967 else
5968 conn->err_code = CO_ER_SSL_ABORT;
5969 }
Emeric Brun29f037d2014-04-25 19:05:36 +02005970 }
5971 else {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01005972 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emeric Brun29f037d2014-04-25 19:05:36 +02005973 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5974 else
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005975 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun29f037d2014-04-25 19:05:36 +02005976 }
Lukas Tribus49799162019-07-08 14:29:15 +02005977#endif /* BoringSSL or LibreSSL */
Emeric Brun29f037d2014-04-25 19:05:36 +02005978 }
Willy Tarreau89230192012-09-28 20:22:13 +02005979 goto out_error;
5980 }
Emeric Brun46591952012-05-18 15:47:34 +02005981 else {
5982 /* Fail on all other handshake errors */
Willy Tarreau566dc552012-10-19 20:52:18 +02005983 /* Note: OpenSSL may leave unread bytes in the socket's
5984 * buffer, causing an RST to be emitted upon close() on
5985 * TCP sockets. We first try to drain possibly pending
5986 * data to avoid this as much as possible.
5987 */
Willy Tarreaud85c4852015-03-13 00:40:28 +01005988 conn_sock_drain(conn);
Willy Tarreau20879a02012-12-03 16:32:10 +01005989 if (!conn->err_code)
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01005990 conn->err_code = (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT) ?
Willy Tarreauf51c6982014-04-25 20:02:39 +02005991 CO_ER_SSL_KILLED_HB : CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02005992 goto out_error;
5993 }
5994 }
Willy Tarreau5db847a2019-05-09 14:13:35 +02005995#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Olivier Houchard522eea72017-11-03 16:27:47 +01005996 else {
5997 /*
5998 * If the server refused the early data, we have to send a
5999 * 425 to the client, as we no longer have the data to sent
6000 * them again.
6001 */
6002 if ((conn->flags & CO_FL_EARLY_DATA) && (objt_server(conn->target))) {
Olivier Houchard66ab4982019-02-26 18:37:15 +01006003 if (SSL_get_early_data_status(ctx->ssl) == SSL_EARLY_DATA_REJECTED) {
Olivier Houchard522eea72017-11-03 16:27:47 +01006004 conn->err_code = CO_ER_SSL_EARLY_FAILED;
6005 goto out_error;
6006 }
6007 }
6008 }
6009#endif
6010
Emeric Brun46591952012-05-18 15:47:34 +02006011
Emeric Brun674b7432012-11-08 19:21:55 +01006012reneg_ok:
Emeric Brunb5e42a82017-06-06 12:35:14 +00006013
Willy Tarreau5db847a2019-05-09 14:13:35 +02006014#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00006015 /* ASYNC engine API doesn't support moving read/write
6016 * buffers. So we disable ASYNC mode right after
6017 * the handshake to avoid buffer oveflows.
6018 */
6019 if (global_ssl.async)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006020 SSL_clear_mode(ctx->ssl, SSL_MODE_ASYNC);
Emeric Brunb5e42a82017-06-06 12:35:14 +00006021#endif
Emeric Brun46591952012-05-18 15:47:34 +02006022 /* Handshake succeeded */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006023 if (!SSL_session_reused(ctx->ssl)) {
Willy Tarreau0c9c2722014-05-28 12:28:58 +02006024 if (objt_server(conn->target)) {
6025 update_freq_ctr(&global.ssl_be_keys_per_sec, 1);
6026 if (global.ssl_be_keys_per_sec.curr_ctr > global.ssl_be_keys_max)
6027 global.ssl_be_keys_max = global.ssl_be_keys_per_sec.curr_ctr;
Emeric Brun46591952012-05-18 15:47:34 +02006028 }
Willy Tarreau0c9c2722014-05-28 12:28:58 +02006029 else {
6030 update_freq_ctr(&global.ssl_fe_keys_per_sec, 1);
6031 if (global.ssl_fe_keys_per_sec.curr_ctr > global.ssl_fe_keys_max)
6032 global.ssl_fe_keys_max = global.ssl_fe_keys_per_sec.curr_ctr;
6033 }
Emeric Brun46591952012-05-18 15:47:34 +02006034 }
6035
6036 /* The connection is now established at both layers, it's time to leave */
6037 conn->flags &= ~(flag | CO_FL_WAIT_L4_CONN | CO_FL_WAIT_L6_CONN);
6038 return 1;
6039
6040 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01006041 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02006042 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01006043 ERR_clear_error();
6044
Emeric Brun9fa89732012-10-04 17:09:56 +02006045 /* free resumed session if exists */
Willy Tarreau07d94e42018-09-20 10:57:52 +02006046 if (objt_server(conn->target) && __objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr) {
6047 free(__objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr);
6048 __objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr = NULL;
Emeric Brun9fa89732012-10-04 17:09:56 +02006049 }
6050
Emeric Brun46591952012-05-18 15:47:34 +02006051 /* Fail on all other handshake errors */
6052 conn->flags |= CO_FL_ERROR;
Willy Tarreau20879a02012-12-03 16:32:10 +01006053 if (!conn->err_code)
6054 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02006055 return 0;
6056}
6057
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006058static int ssl_subscribe(struct connection *conn, void *xprt_ctx, int event_type, void *param)
Olivier Houcharddf357842019-03-21 16:30:07 +01006059{
Olivier Houchardea8dd942019-05-20 14:02:16 +02006060 struct wait_event *sw;
6061 struct ssl_sock_ctx *ctx = xprt_ctx;
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006062
Olivier Houchard0ff28652019-06-24 18:57:39 +02006063 if (!ctx)
6064 return -1;
6065
Olivier Houchardea8dd942019-05-20 14:02:16 +02006066 if (event_type & SUB_RETRY_RECV) {
6067 sw = param;
6068 BUG_ON(ctx->recv_wait != NULL || (sw->events & SUB_RETRY_RECV));
6069 sw->events |= SUB_RETRY_RECV;
6070 ctx->recv_wait = sw;
6071 if (!(conn->flags & CO_FL_SSL_WAIT_HS) &&
6072 !(ctx->wait_event.events & SUB_RETRY_RECV))
6073 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_RECV, &ctx->wait_event);
6074 event_type &= ~SUB_RETRY_RECV;
6075 }
6076 if (event_type & SUB_RETRY_SEND) {
6077sw = param;
6078 BUG_ON(ctx->send_wait != NULL || (sw->events & SUB_RETRY_SEND));
6079 sw->events |= SUB_RETRY_SEND;
6080 ctx->send_wait = sw;
6081 if (!(conn->flags & CO_FL_SSL_WAIT_HS) &&
6082 !(ctx->wait_event.events & SUB_RETRY_SEND))
6083 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_SEND, &ctx->wait_event);
6084 event_type &= ~SUB_RETRY_SEND;
6085
6086 }
6087 if (event_type != 0)
6088 return -1;
6089 return 0;
Olivier Houcharddf357842019-03-21 16:30:07 +01006090}
6091
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006092static int ssl_unsubscribe(struct connection *conn, void *xprt_ctx, int event_type, void *param)
Olivier Houcharddf357842019-03-21 16:30:07 +01006093{
Olivier Houchardea8dd942019-05-20 14:02:16 +02006094 struct wait_event *sw;
6095 struct ssl_sock_ctx *ctx = xprt_ctx;
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006096
Olivier Houchardea8dd942019-05-20 14:02:16 +02006097 if (event_type & SUB_RETRY_RECV) {
6098 sw = param;
6099 BUG_ON(ctx->recv_wait != sw);
6100 ctx->recv_wait = NULL;
6101 sw->events &= ~SUB_RETRY_RECV;
6102 /* If we subscribed, and we're not doing the handshake,
6103 * then we subscribed because the upper layer asked for it,
6104 * as the upper layer is no longer interested, we can
6105 * unsubscribe too.
6106 */
6107 if (!(ctx->conn->flags & CO_FL_SSL_WAIT_HS) &&
6108 (ctx->wait_event.events & SUB_RETRY_RECV))
6109 conn_unsubscribe(conn, ctx->xprt_ctx, SUB_RETRY_RECV,
6110 &ctx->wait_event);
6111 }
6112 if (event_type & SUB_RETRY_SEND) {
6113 sw = param;
6114 BUG_ON(ctx->send_wait != sw);
6115 ctx->send_wait = NULL;
6116 sw->events &= ~SUB_RETRY_SEND;
6117 if (!(ctx->conn->flags & CO_FL_SSL_WAIT_HS) &&
6118 (ctx->wait_event.events & SUB_RETRY_SEND))
6119 conn_unsubscribe(conn, ctx->xprt_ctx, SUB_RETRY_SEND,
6120 &ctx->wait_event);
6121
6122 }
6123
6124 return 0;
Olivier Houcharddf357842019-03-21 16:30:07 +01006125}
6126
Olivier Houchard2e055482019-05-27 19:50:12 +02006127/* Use the provided XPRT as an underlying XPRT, and provide the old one.
6128 * Returns 0 on success, and non-zero on failure.
6129 */
6130static 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)
6131{
6132 struct ssl_sock_ctx *ctx = xprt_ctx;
6133
6134 if (oldxprt_ops != NULL)
6135 *oldxprt_ops = ctx->xprt;
6136 if (oldxprt_ctx != NULL)
6137 *oldxprt_ctx = ctx->xprt_ctx;
6138 ctx->xprt = toadd_ops;
6139 ctx->xprt_ctx = toadd_ctx;
6140 return 0;
6141}
6142
Olivier Houchard5149b592019-05-23 17:47:36 +02006143/* Remove the specified xprt. If if it our underlying XPRT, remove it and
6144 * return 0, otherwise just call the remove_xprt method from the underlying
6145 * XPRT.
6146 */
6147static int ssl_remove_xprt(struct connection *conn, void *xprt_ctx, void *toremove_ctx, const struct xprt_ops *newops, void *newctx)
6148{
6149 struct ssl_sock_ctx *ctx = xprt_ctx;
6150
6151 if (ctx->xprt_ctx == toremove_ctx) {
6152 ctx->xprt_ctx = newctx;
6153 ctx->xprt = newops;
6154 return 0;
6155 }
6156 return (ctx->xprt->remove_xprt(conn, ctx->xprt_ctx, toremove_ctx, newops, newctx));
6157}
6158
Olivier Houchardea8dd942019-05-20 14:02:16 +02006159static struct task *ssl_sock_io_cb(struct task *t, void *context, unsigned short state)
6160{
6161 struct ssl_sock_ctx *ctx = context;
6162
6163 /* First if we're doing an handshake, try that */
6164 if (ctx->conn->flags & CO_FL_SSL_WAIT_HS)
6165 ssl_sock_handshake(ctx->conn, CO_FL_SSL_WAIT_HS);
6166 /* If we had an error, or the handshake is done and I/O is available,
6167 * let the upper layer know.
6168 * If no mux was set up yet, and nobody subscribed, then call
6169 * xprt_done_cb() ourself if it's set, or destroy the connection,
6170 * we can't be sure conn_fd_handler() will be called again.
6171 */
6172 if ((ctx->conn->flags & CO_FL_ERROR) ||
6173 !(ctx->conn->flags & CO_FL_SSL_WAIT_HS)) {
6174 int ret = 0;
6175 int woke = 0;
6176
6177 /* On error, wake any waiter */
6178 if (ctx->recv_wait) {
6179 ctx->recv_wait->events &= ~SUB_RETRY_RECV;
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02006180 tasklet_wakeup(ctx->recv_wait->tasklet);
Olivier Houchardea8dd942019-05-20 14:02:16 +02006181 ctx->recv_wait = NULL;
6182 woke = 1;
6183 }
6184 if (ctx->send_wait) {
6185 ctx->send_wait->events &= ~SUB_RETRY_SEND;
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02006186 tasklet_wakeup(ctx->send_wait->tasklet);
Olivier Houchardea8dd942019-05-20 14:02:16 +02006187 ctx->send_wait = NULL;
6188 woke = 1;
6189 }
6190 /* If we're the first xprt for the connection, let the
6191 * upper layers know. If xprt_done_cb() is set, call it,
6192 * otherwise, we should have a mux, so call its wake
6193 * method if we didn't woke a tasklet already.
6194 */
6195 if (ctx->conn->xprt_ctx == ctx) {
6196 if (ctx->conn->xprt_done_cb)
6197 ret = ctx->conn->xprt_done_cb(ctx->conn);
6198 if (ret >= 0 && !woke && ctx->conn->mux && ctx->conn->mux->wake)
6199 ctx->conn->mux->wake(ctx->conn);
6200 return NULL;
6201 }
6202 }
6203 return NULL;
6204}
6205
Emeric Brun46591952012-05-18 15:47:34 +02006206/* Receive up to <count> bytes from connection <conn>'s socket and store them
Willy Tarreauabf08d92014-01-14 11:31:27 +01006207 * into buffer <buf>. Only one call to recv() is performed, unless the
Emeric Brun46591952012-05-18 15:47:34 +02006208 * buffer wraps, in which case a second call may be performed. The connection's
6209 * flags are updated with whatever special event is detected (error, read0,
6210 * empty). The caller is responsible for taking care of those events and
6211 * avoiding the call if inappropriate. The function does not call the
6212 * connection's polling update function, so the caller is responsible for this.
6213 */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006214static 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 +02006215{
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006216 struct ssl_sock_ctx *ctx = xprt_ctx;
Willy Tarreaubfc4d772018-07-18 11:22:03 +02006217 ssize_t ret;
6218 size_t try, done = 0;
Emeric Brun46591952012-05-18 15:47:34 +02006219
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02006220 conn_refresh_polling_flags(conn);
6221
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006222 if (!ctx)
Emeric Brun46591952012-05-18 15:47:34 +02006223 goto out_error;
6224
6225 if (conn->flags & CO_FL_HANDSHAKE)
6226 /* a handshake was requested */
6227 return 0;
6228
Emeric Brun46591952012-05-18 15:47:34 +02006229 /* read the largest possible block. For this, we perform only one call
6230 * to recv() unless the buffer wraps and we exactly fill the first hunk,
6231 * in which case we accept to do it once again. A new attempt is made on
6232 * EINTR too.
6233 */
Willy Tarreau00b0fb92014-01-17 11:09:40 +01006234 while (count > 0) {
Olivier Houchardc2aae742017-09-22 18:26:28 +02006235 int need_out = 0;
6236
Willy Tarreau591d4452018-06-15 17:21:00 +02006237 try = b_contig_space(buf);
6238 if (!try)
6239 break;
6240
Willy Tarreauabf08d92014-01-14 11:31:27 +01006241 if (try > count)
6242 try = count;
Willy Tarreau591d4452018-06-15 17:21:00 +02006243
Olivier Houchardc2aae742017-09-22 18:26:28 +02006244 if (((conn->flags & (CO_FL_EARLY_SSL_HS | CO_FL_EARLY_DATA)) == CO_FL_EARLY_SSL_HS) &&
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006245 ctx->tmp_early_data != -1) {
6246 *b_tail(buf) = ctx->tmp_early_data;
Olivier Houchardc2aae742017-09-22 18:26:28 +02006247 done++;
6248 try--;
6249 count--;
Olivier Houchardacd14032018-06-28 18:17:23 +02006250 b_add(buf, 1);
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006251 ctx->tmp_early_data = -1;
Olivier Houchardc2aae742017-09-22 18:26:28 +02006252 continue;
6253 }
Willy Tarreauabf08d92014-01-14 11:31:27 +01006254
Willy Tarreau5db847a2019-05-09 14:13:35 +02006255#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Olivier Houchardc2aae742017-09-22 18:26:28 +02006256 if (conn->flags & CO_FL_EARLY_SSL_HS) {
6257 size_t read_length;
6258
Olivier Houchard66ab4982019-02-26 18:37:15 +01006259 ret = SSL_read_early_data(ctx->ssl,
Willy Tarreau8f9c72d2018-06-07 18:46:28 +02006260 b_tail(buf), try, &read_length);
Olivier Houchard522eea72017-11-03 16:27:47 +01006261 if (ret == SSL_READ_EARLY_DATA_SUCCESS &&
6262 read_length > 0)
Olivier Houchardc2aae742017-09-22 18:26:28 +02006263 conn->flags |= CO_FL_EARLY_DATA;
6264 if (ret == SSL_READ_EARLY_DATA_SUCCESS ||
6265 ret == SSL_READ_EARLY_DATA_FINISH) {
6266 if (ret == SSL_READ_EARLY_DATA_FINISH) {
6267 /*
6268 * We're done reading the early data,
6269 * let's make the handshake
6270 */
6271 conn->flags &= ~CO_FL_EARLY_SSL_HS;
6272 conn->flags |= CO_FL_SSL_WAIT_HS;
6273 need_out = 1;
Olivier Houchard965e84e2019-06-15 20:59:30 +02006274 /* Now initiate the handshake */
6275 tasklet_wakeup(ctx->wait_event.tasklet);
Olivier Houchardc2aae742017-09-22 18:26:28 +02006276 if (read_length == 0)
6277 break;
6278 }
6279 ret = read_length;
6280 }
6281 } else
6282#endif
Olivier Houchard66ab4982019-02-26 18:37:15 +01006283 ret = SSL_read(ctx->ssl, b_tail(buf), try);
Emmanuel Hocdetf967c312019-08-05 18:04:16 +02006284
Emeric Brune1f38db2012-09-03 20:36:47 +02006285 if (conn->flags & CO_FL_ERROR) {
6286 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01006287 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02006288 }
Emeric Brun46591952012-05-18 15:47:34 +02006289 if (ret > 0) {
Olivier Houchardacd14032018-06-28 18:17:23 +02006290 b_add(buf, ret);
Emeric Brun46591952012-05-18 15:47:34 +02006291 done += ret;
Emeric Brun46591952012-05-18 15:47:34 +02006292 count -= ret;
Emeric Brun46591952012-05-18 15:47:34 +02006293 }
Emeric Brun46591952012-05-18 15:47:34 +02006294 else {
Olivier Houchard66ab4982019-02-26 18:37:15 +01006295 ret = SSL_get_error(ctx->ssl, ret);
Emeric Brun46591952012-05-18 15:47:34 +02006296 if (ret == SSL_ERROR_WANT_WRITE) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01006297 /* handshake is running, and it needs to enable write */
Emeric Brun46591952012-05-18 15:47:34 +02006298 conn->flags |= CO_FL_SSL_WAIT_HS;
Olivier Houchardea8dd942019-05-20 14:02:16 +02006299 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_SEND, &ctx->wait_event);
Willy Tarreau5db847a2019-05-09 14:13:35 +02006300#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00006301 /* Async mode can be re-enabled, because we're leaving data state.*/
6302 if (global_ssl.async)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006303 SSL_set_mode(ctx->ssl, SSL_MODE_ASYNC);
Emeric Brunb5e42a82017-06-06 12:35:14 +00006304#endif
Emeric Brun46591952012-05-18 15:47:34 +02006305 break;
6306 }
6307 else if (ret == SSL_ERROR_WANT_READ) {
Olivier Houchard66ab4982019-02-26 18:37:15 +01006308 if (SSL_renegotiate_pending(ctx->ssl)) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02006309 ctx->xprt->subscribe(conn, ctx->xprt_ctx,
6310 SUB_RETRY_RECV,
6311 &ctx->wait_event);
Emeric Brun282a76a2012-11-08 18:02:56 +01006312 /* handshake is running, and it may need to re-enable read */
6313 conn->flags |= CO_FL_SSL_WAIT_HS;
Willy Tarreau5db847a2019-05-09 14:13:35 +02006314#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00006315 /* Async mode can be re-enabled, because we're leaving data state.*/
6316 if (global_ssl.async)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006317 SSL_set_mode(ctx->ssl, SSL_MODE_ASYNC);
Emeric Brunb5e42a82017-06-06 12:35:14 +00006318#endif
Emeric Brun282a76a2012-11-08 18:02:56 +01006319 break;
6320 }
Emeric Brun46591952012-05-18 15:47:34 +02006321 break;
Olivier Houchardc2aae742017-09-22 18:26:28 +02006322 } else if (ret == SSL_ERROR_ZERO_RETURN)
6323 goto read0;
Christopher Faulet4ac77a92018-02-19 14:25:15 +01006324 /* For SSL_ERROR_SYSCALL, make sure to clear the error
6325 * stack before shutting down the connection for
6326 * reading. */
Olivier Houchard7e2e5052018-02-13 15:17:23 +01006327 if (ret == SSL_ERROR_SYSCALL && (!errno || errno == EAGAIN))
6328 goto clear_ssl_error;
Emeric Brun46591952012-05-18 15:47:34 +02006329 /* otherwise it's a real error */
6330 goto out_error;
6331 }
Olivier Houchardc2aae742017-09-22 18:26:28 +02006332 if (need_out)
6333 break;
Emeric Brun46591952012-05-18 15:47:34 +02006334 }
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02006335 leave:
Emeric Brun46591952012-05-18 15:47:34 +02006336 return done;
6337
Christopher Faulet4ac77a92018-02-19 14:25:15 +01006338 clear_ssl_error:
6339 /* Clear openssl global errors stack */
6340 ssl_sock_dump_errors(conn);
6341 ERR_clear_error();
Emeric Brun46591952012-05-18 15:47:34 +02006342 read0:
6343 conn_sock_read0(conn);
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02006344 goto leave;
Christopher Faulet4ac77a92018-02-19 14:25:15 +01006345
Emeric Brun46591952012-05-18 15:47:34 +02006346 out_error:
Olivier Houchard7e2e5052018-02-13 15:17:23 +01006347 conn->flags |= CO_FL_ERROR;
Emeric Brun644cde02012-12-14 11:21:13 +01006348 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02006349 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01006350 ERR_clear_error();
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02006351 goto leave;
Emeric Brun46591952012-05-18 15:47:34 +02006352}
6353
6354
Willy Tarreau787db9a2018-06-14 18:31:46 +02006355/* Send up to <count> pending bytes from buffer <buf> to connection <conn>'s
6356 * socket. <flags> may contain some CO_SFL_* flags to hint the system about
6357 * other pending data for example, but this flag is ignored at the moment.
Emeric Brun46591952012-05-18 15:47:34 +02006358 * Only one call to send() is performed, unless the buffer wraps, in which case
6359 * a second call may be performed. The connection's flags are updated with
6360 * whatever special event is detected (error, empty). The caller is responsible
6361 * for taking care of those events and avoiding the call if inappropriate. The
6362 * function does not call the connection's polling update function, so the caller
Willy Tarreau787db9a2018-06-14 18:31:46 +02006363 * is responsible for this. The buffer's output is not adjusted, it's up to the
6364 * caller to take care of this. It's up to the caller to update the buffer's
6365 * contents based on the return value.
Emeric Brun46591952012-05-18 15:47:34 +02006366 */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006367static 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 +02006368{
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006369 struct ssl_sock_ctx *ctx = xprt_ctx;
Willy Tarreau787db9a2018-06-14 18:31:46 +02006370 ssize_t ret;
6371 size_t try, done;
Emeric Brun46591952012-05-18 15:47:34 +02006372
6373 done = 0;
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02006374 conn_refresh_polling_flags(conn);
Emeric Brun46591952012-05-18 15:47:34 +02006375
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006376 if (!ctx)
Emeric Brun46591952012-05-18 15:47:34 +02006377 goto out_error;
6378
Olivier Houchard010941f2019-05-03 20:56:19 +02006379 if (conn->flags & (CO_FL_HANDSHAKE | CO_FL_EARLY_SSL_HS))
Emeric Brun46591952012-05-18 15:47:34 +02006380 /* a handshake was requested */
6381 return 0;
6382
6383 /* send the largest possible block. For this we perform only one call
6384 * to send() unless the buffer wraps and we exactly fill the first hunk,
6385 * in which case we accept to do it once again.
6386 */
Willy Tarreau787db9a2018-06-14 18:31:46 +02006387 while (count) {
Willy Tarreau5db847a2019-05-09 14:13:35 +02006388#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Olivier Houchardc2aae742017-09-22 18:26:28 +02006389 size_t written_data;
6390#endif
6391
Willy Tarreau787db9a2018-06-14 18:31:46 +02006392 try = b_contig_data(buf, done);
6393 if (try > count)
6394 try = count;
Willy Tarreaubfd59462013-02-21 07:46:09 +01006395
Willy Tarreau7bed9452014-02-02 02:00:24 +01006396 if (!(flags & CO_SFL_STREAMER) &&
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006397 !(ctx->xprt_st & SSL_SOCK_SEND_UNLIMITED) &&
Willy Tarreauef934602016-12-22 23:12:01 +01006398 global_ssl.max_record && try > global_ssl.max_record) {
6399 try = global_ssl.max_record;
Willy Tarreau518cedd2014-02-17 15:43:01 +01006400 }
6401 else {
6402 /* we need to keep the information about the fact that
6403 * we're not limiting the upcoming send(), because if it
6404 * fails, we'll have to retry with at least as many data.
6405 */
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006406 ctx->xprt_st |= SSL_SOCK_SEND_UNLIMITED;
Willy Tarreau518cedd2014-02-17 15:43:01 +01006407 }
Willy Tarreaubfd59462013-02-21 07:46:09 +01006408
Willy Tarreau5db847a2019-05-09 14:13:35 +02006409#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Olivier Houchard010941f2019-05-03 20:56:19 +02006410 if (!SSL_is_init_finished(ctx->ssl) && conn_is_back(conn)) {
Olivier Houchardc2aae742017-09-22 18:26:28 +02006411 unsigned int max_early;
6412
Olivier Houchard522eea72017-11-03 16:27:47 +01006413 if (objt_listener(conn->target))
Olivier Houchard66ab4982019-02-26 18:37:15 +01006414 max_early = SSL_get_max_early_data(ctx->ssl);
Olivier Houchard522eea72017-11-03 16:27:47 +01006415 else {
Olivier Houchard66ab4982019-02-26 18:37:15 +01006416 if (SSL_get0_session(ctx->ssl))
6417 max_early = SSL_SESSION_get_max_early_data(SSL_get0_session(ctx->ssl));
Olivier Houchard522eea72017-11-03 16:27:47 +01006418 else
6419 max_early = 0;
6420 }
6421
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006422 if (try + ctx->sent_early_data > max_early) {
6423 try -= (try + ctx->sent_early_data) - max_early;
Olivier Houchard522eea72017-11-03 16:27:47 +01006424 if (try <= 0) {
Olivier Houchard010941f2019-05-03 20:56:19 +02006425 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Olivier Houchard965e84e2019-06-15 20:59:30 +02006426 tasklet_wakeup(ctx->wait_event.tasklet);
Olivier Houchardc2aae742017-09-22 18:26:28 +02006427 break;
Olivier Houchard522eea72017-11-03 16:27:47 +01006428 }
Olivier Houchardc2aae742017-09-22 18:26:28 +02006429 }
Olivier Houchard66ab4982019-02-26 18:37:15 +01006430 ret = SSL_write_early_data(ctx->ssl, b_peek(buf, done), try, &written_data);
Olivier Houchardc2aae742017-09-22 18:26:28 +02006431 if (ret == 1) {
6432 ret = written_data;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006433 ctx->sent_early_data += ret;
Olivier Houchard965e84e2019-06-15 20:59:30 +02006434 if (objt_server(conn->target)) {
Olivier Houchard522eea72017-11-03 16:27:47 +01006435 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN | CO_FL_EARLY_DATA;
Olivier Houchard965e84e2019-06-15 20:59:30 +02006436 /* Initiate the handshake, now */
6437 tasklet_wakeup(ctx->wait_event.tasklet);
6438 }
Olivier Houchard522eea72017-11-03 16:27:47 +01006439
Olivier Houchardc2aae742017-09-22 18:26:28 +02006440 }
6441
6442 } else
6443#endif
Olivier Houchard66ab4982019-02-26 18:37:15 +01006444 ret = SSL_write(ctx->ssl, b_peek(buf, done), try);
Willy Tarreau518cedd2014-02-17 15:43:01 +01006445
Emeric Brune1f38db2012-09-03 20:36:47 +02006446 if (conn->flags & CO_FL_ERROR) {
6447 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01006448 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02006449 }
Emeric Brun46591952012-05-18 15:47:34 +02006450 if (ret > 0) {
Olivier Houchardf24502b2019-01-17 19:09:11 +01006451 /* A send succeeded, so we can consier ourself connected */
6452 conn->flags |= CO_FL_CONNECTED;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006453 ctx->xprt_st &= ~SSL_SOCK_SEND_UNLIMITED;
Willy Tarreau787db9a2018-06-14 18:31:46 +02006454 count -= ret;
Emeric Brun46591952012-05-18 15:47:34 +02006455 done += ret;
Emeric Brun46591952012-05-18 15:47:34 +02006456 }
6457 else {
Olivier Houchard66ab4982019-02-26 18:37:15 +01006458 ret = SSL_get_error(ctx->ssl, ret);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006459
Emeric Brun46591952012-05-18 15:47:34 +02006460 if (ret == SSL_ERROR_WANT_WRITE) {
Olivier Houchard66ab4982019-02-26 18:37:15 +01006461 if (SSL_renegotiate_pending(ctx->ssl)) {
Emeric Brun282a76a2012-11-08 18:02:56 +01006462 /* handshake is running, and it may need to re-enable write */
6463 conn->flags |= CO_FL_SSL_WAIT_HS;
Olivier Houchardea8dd942019-05-20 14:02:16 +02006464 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_SEND, &ctx->wait_event);
Willy Tarreau5db847a2019-05-09 14:13:35 +02006465#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00006466 /* Async mode can be re-enabled, because we're leaving data state.*/
6467 if (global_ssl.async)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006468 SSL_set_mode(ctx->ssl, SSL_MODE_ASYNC);
Emeric Brunb5e42a82017-06-06 12:35:14 +00006469#endif
Emeric Brun282a76a2012-11-08 18:02:56 +01006470 break;
6471 }
Olivier Houchardea8dd942019-05-20 14:02:16 +02006472
Emeric Brun46591952012-05-18 15:47:34 +02006473 break;
6474 }
6475 else if (ret == SSL_ERROR_WANT_READ) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01006476 /* handshake is running, and it needs to enable read */
Emeric Brun46591952012-05-18 15:47:34 +02006477 conn->flags |= CO_FL_SSL_WAIT_HS;
Olivier Houchardea8dd942019-05-20 14:02:16 +02006478 ctx->xprt->subscribe(conn, ctx->xprt_ctx,
6479 SUB_RETRY_RECV,
6480 &ctx->wait_event);
Willy Tarreau5db847a2019-05-09 14:13:35 +02006481#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00006482 /* Async mode can be re-enabled, because we're leaving data state.*/
6483 if (global_ssl.async)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006484 SSL_set_mode(ctx->ssl, SSL_MODE_ASYNC);
Emeric Brunb5e42a82017-06-06 12:35:14 +00006485#endif
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006486 break;
6487 }
Emeric Brun46591952012-05-18 15:47:34 +02006488 goto out_error;
6489 }
6490 }
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02006491 leave:
Emeric Brun46591952012-05-18 15:47:34 +02006492 return done;
6493
6494 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01006495 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02006496 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01006497 ERR_clear_error();
6498
Emeric Brun46591952012-05-18 15:47:34 +02006499 conn->flags |= CO_FL_ERROR;
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02006500 goto leave;
Emeric Brun46591952012-05-18 15:47:34 +02006501}
6502
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006503static void ssl_sock_close(struct connection *conn, void *xprt_ctx) {
Emeric Brun46591952012-05-18 15:47:34 +02006504
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006505 struct ssl_sock_ctx *ctx = xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006506
Olivier Houchardea8dd942019-05-20 14:02:16 +02006507
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006508 if (ctx) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02006509 if (ctx->wait_event.events != 0)
6510 ctx->xprt->unsubscribe(ctx->conn, ctx->xprt_ctx,
6511 ctx->wait_event.events,
6512 &ctx->wait_event);
6513 if (ctx->send_wait) {
6514 ctx->send_wait->events &= ~SUB_RETRY_SEND;
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02006515 tasklet_wakeup(ctx->send_wait->tasklet);
Olivier Houchardea8dd942019-05-20 14:02:16 +02006516 }
6517 if (ctx->recv_wait) {
6518 ctx->recv_wait->events &= ~SUB_RETRY_RECV;
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02006519 tasklet_wakeup(ctx->recv_wait->tasklet);
Olivier Houchardea8dd942019-05-20 14:02:16 +02006520 }
Olivier Houchard692c1d02019-05-23 18:41:47 +02006521 if (ctx->xprt->close)
6522 ctx->xprt->close(conn, ctx->xprt_ctx);
Willy Tarreau5db847a2019-05-09 14:13:35 +02006523#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brun3854e012017-05-17 20:42:48 +02006524 if (global_ssl.async) {
6525 OSSL_ASYNC_FD all_fd[32], afd;
6526 size_t num_all_fds = 0;
6527 int i;
6528
Olivier Houchard66ab4982019-02-26 18:37:15 +01006529 SSL_get_all_async_fds(ctx->ssl, NULL, &num_all_fds);
Emeric Brun3854e012017-05-17 20:42:48 +02006530 if (num_all_fds > 32) {
6531 send_log(NULL, LOG_EMERG, "haproxy: openssl returns too many async fds. It seems a bug. Process may crash\n");
6532 return;
6533 }
6534
Olivier Houchard66ab4982019-02-26 18:37:15 +01006535 SSL_get_all_async_fds(ctx->ssl, all_fd, &num_all_fds);
Emeric Brun3854e012017-05-17 20:42:48 +02006536
6537 /* If an async job is pending, we must try to
6538 to catch the end using polling before calling
6539 SSL_free */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006540 if (num_all_fds && SSL_waiting_for_async(ctx->ssl)) {
Emeric Brun3854e012017-05-17 20:42:48 +02006541 for (i=0 ; i < num_all_fds ; i++) {
6542 /* switch on an handler designed to
6543 * handle the SSL_free
6544 */
6545 afd = all_fd[i];
6546 fdtab[afd].iocb = ssl_async_fd_free;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006547 fdtab[afd].owner = ctx->ssl;
Emeric Brun3854e012017-05-17 20:42:48 +02006548 fd_want_recv(afd);
Emeric Brunce9e01c2017-05-31 10:02:53 +00006549 /* To ensure that the fd cache won't be used
6550 * and we'll catch a real RD event.
6551 */
6552 fd_cant_recv(afd);
Emeric Brun3854e012017-05-17 20:42:48 +02006553 }
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02006554 tasklet_free(ctx->wait_event.tasklet);
Olivier Houchard66ab4982019-02-26 18:37:15 +01006555 pool_free(ssl_sock_ctx_pool, ctx);
Olivier Houchard2be5a4c2019-03-08 18:54:43 +01006556 _HA_ATOMIC_ADD(&jobs, 1);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006557 return;
6558 }
Emeric Brun3854e012017-05-17 20:42:48 +02006559 /* Else we can remove the fds from the fdtab
6560 * and call SSL_free.
6561 * note: we do a fd_remove and not a delete
6562 * because the fd is owned by the engine.
6563 * the engine is responsible to close
6564 */
6565 for (i=0 ; i < num_all_fds ; i++)
6566 fd_remove(all_fd[i]);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006567 }
6568#endif
Olivier Houchard66ab4982019-02-26 18:37:15 +01006569 SSL_free(ctx->ssl);
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02006570 tasklet_free(ctx->wait_event.tasklet);
Olivier Houchard66ab4982019-02-26 18:37:15 +01006571 pool_free(ssl_sock_ctx_pool, ctx);
Olivier Houchard2be5a4c2019-03-08 18:54:43 +01006572 _HA_ATOMIC_SUB(&sslconns, 1);
Emeric Brun46591952012-05-18 15:47:34 +02006573 }
Emeric Brun46591952012-05-18 15:47:34 +02006574}
6575
6576/* This function tries to perform a clean shutdown on an SSL connection, and in
6577 * any case, flags the connection as reusable if no handshake was in progress.
6578 */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006579static void ssl_sock_shutw(struct connection *conn, void *xprt_ctx, int clean)
Emeric Brun46591952012-05-18 15:47:34 +02006580{
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006581 struct ssl_sock_ctx *ctx = xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006582
Emeric Brun46591952012-05-18 15:47:34 +02006583 if (conn->flags & CO_FL_HANDSHAKE)
6584 return;
Emmanuel Hocdet405ff312017-01-08 14:07:39 +01006585 if (!clean)
6586 /* don't sent notify on SSL_shutdown */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006587 SSL_set_quiet_shutdown(ctx->ssl, 1);
Emeric Brun46591952012-05-18 15:47:34 +02006588 /* no handshake was in progress, try a clean ssl shutdown */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006589 if (SSL_shutdown(ctx->ssl) <= 0) {
Emeric Brun644cde02012-12-14 11:21:13 +01006590 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02006591 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01006592 ERR_clear_error();
6593 }
Emeric Brun46591952012-05-18 15:47:34 +02006594}
6595
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01006596/* used for ppv2 pkey alog (can be used for logging) */
Willy Tarreau83061a82018-07-13 11:56:34 +02006597int ssl_sock_get_pkey_algo(struct connection *conn, struct buffer *out)
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01006598{
Christopher Faulet82004142019-09-10 10:12:03 +02006599 struct ssl_sock_ctx *ctx;
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01006600 struct pkey_info *pkinfo;
6601 int bits = 0;
6602 int sig = TLSEXT_signature_anonymous;
6603 int len = -1;
6604
6605 if (!ssl_sock_is_ssl(conn))
6606 return 0;
Christopher Faulet82004142019-09-10 10:12:03 +02006607 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006608 pkinfo = SSL_CTX_get_ex_data(SSL_get_SSL_CTX(ctx->ssl), ssl_pkey_info_index);
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01006609 if (pkinfo) {
6610 sig = pkinfo->sig;
6611 bits = pkinfo->bits;
6612 } else {
6613 /* multicert and generated cert have no pkey info */
6614 X509 *crt;
6615 EVP_PKEY *pkey;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006616 crt = SSL_get_certificate(ctx->ssl);
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01006617 if (!crt)
6618 return 0;
6619 pkey = X509_get_pubkey(crt);
6620 if (pkey) {
6621 bits = EVP_PKEY_bits(pkey);
6622 switch(EVP_PKEY_base_id(pkey)) {
6623 case EVP_PKEY_RSA:
6624 sig = TLSEXT_signature_rsa;
6625 break;
6626 case EVP_PKEY_EC:
6627 sig = TLSEXT_signature_ecdsa;
6628 break;
6629 case EVP_PKEY_DSA:
6630 sig = TLSEXT_signature_dsa;
6631 break;
6632 }
6633 EVP_PKEY_free(pkey);
6634 }
6635 }
6636
6637 switch(sig) {
6638 case TLSEXT_signature_rsa:
6639 len = chunk_printf(out, "RSA%d", bits);
6640 break;
6641 case TLSEXT_signature_ecdsa:
6642 len = chunk_printf(out, "EC%d", bits);
6643 break;
6644 case TLSEXT_signature_dsa:
6645 len = chunk_printf(out, "DSA%d", bits);
6646 break;
6647 default:
6648 return 0;
6649 }
6650 if (len < 0)
6651 return 0;
6652 return 1;
6653}
6654
Emmanuel Hocdet283e0042017-11-02 14:05:23 +01006655/* used for ppv2 cert signature (can be used for logging) */
6656const char *ssl_sock_get_cert_sig(struct connection *conn)
6657{
Christopher Faulet82004142019-09-10 10:12:03 +02006658 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006659
Emmanuel Hocdet283e0042017-11-02 14:05:23 +01006660 __OPENSSL_110_CONST__ ASN1_OBJECT *algorithm;
6661 X509 *crt;
6662
6663 if (!ssl_sock_is_ssl(conn))
6664 return NULL;
Christopher Faulet82004142019-09-10 10:12:03 +02006665 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006666 crt = SSL_get_certificate(ctx->ssl);
Emmanuel Hocdet283e0042017-11-02 14:05:23 +01006667 if (!crt)
6668 return NULL;
6669 X509_ALGOR_get0(&algorithm, NULL, NULL, X509_get0_tbs_sigalg(crt));
6670 return OBJ_nid2sn(OBJ_obj2nid(algorithm));
6671}
6672
Emmanuel Hocdet253c3b72018-02-01 18:29:59 +01006673/* used for ppv2 authority */
6674const char *ssl_sock_get_sni(struct connection *conn)
6675{
6676#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Christopher Faulet82004142019-09-10 10:12:03 +02006677 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006678
Emmanuel Hocdet253c3b72018-02-01 18:29:59 +01006679 if (!ssl_sock_is_ssl(conn))
6680 return NULL;
Christopher Faulet82004142019-09-10 10:12:03 +02006681 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006682 return SSL_get_servername(ctx->ssl, TLSEXT_NAMETYPE_host_name);
Emmanuel Hocdet253c3b72018-02-01 18:29:59 +01006683#else
Olivier Houchard66ab4982019-02-26 18:37:15 +01006684 return NULL;
Emmanuel Hocdet253c3b72018-02-01 18:29:59 +01006685#endif
6686}
6687
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02006688/* used for logging/ppv2, may be changed for a sample fetch later */
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02006689const char *ssl_sock_get_cipher_name(struct connection *conn)
6690{
Christopher Faulet82004142019-09-10 10:12:03 +02006691 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006692
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02006693 if (!ssl_sock_is_ssl(conn))
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02006694 return NULL;
Christopher Faulet82004142019-09-10 10:12:03 +02006695 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006696 return SSL_get_cipher_name(ctx->ssl);
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02006697}
6698
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02006699/* used for logging/ppv2, may be changed for a sample fetch later */
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02006700const char *ssl_sock_get_proto_version(struct connection *conn)
6701{
Christopher Faulet82004142019-09-10 10:12:03 +02006702 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006703
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02006704 if (!ssl_sock_is_ssl(conn))
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02006705 return NULL;
Christopher Faulet82004142019-09-10 10:12:03 +02006706 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006707 return SSL_get_version(ctx->ssl);
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02006708}
6709
Willy Tarreau8d598402012-10-22 17:58:39 +02006710/* Extract a serial from a cert, and copy it to a chunk.
6711 * Returns 1 if serial is found and copied, 0 if no serial found and
6712 * -1 if output is not large enough.
6713 */
6714static int
Willy Tarreau83061a82018-07-13 11:56:34 +02006715ssl_sock_get_serial(X509 *crt, struct buffer *out)
Willy Tarreau8d598402012-10-22 17:58:39 +02006716{
6717 ASN1_INTEGER *serial;
6718
6719 serial = X509_get_serialNumber(crt);
6720 if (!serial)
6721 return 0;
6722
6723 if (out->size < serial->length)
6724 return -1;
6725
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006726 memcpy(out->area, serial->data, serial->length);
6727 out->data = serial->length;
Willy Tarreau8d598402012-10-22 17:58:39 +02006728 return 1;
6729}
6730
Emeric Brun43e79582014-10-29 19:03:26 +01006731/* Extract a cert to der, and copy it to a chunk.
Joseph Herlant017b3da2018-11-15 09:07:59 -08006732 * Returns 1 if the cert is found and copied, 0 on der conversion failure
6733 * and -1 if the output is not large enough.
Emeric Brun43e79582014-10-29 19:03:26 +01006734 */
6735static int
Willy Tarreau83061a82018-07-13 11:56:34 +02006736ssl_sock_crt2der(X509 *crt, struct buffer *out)
Emeric Brun43e79582014-10-29 19:03:26 +01006737{
6738 int len;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006739 unsigned char *p = (unsigned char *) out->area;;
Emeric Brun43e79582014-10-29 19:03:26 +01006740
6741 len =i2d_X509(crt, NULL);
6742 if (len <= 0)
6743 return 1;
6744
6745 if (out->size < len)
6746 return -1;
6747
6748 i2d_X509(crt,&p);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006749 out->data = len;
Emeric Brun43e79582014-10-29 19:03:26 +01006750 return 1;
6751}
6752
Emeric Brunce5ad802012-10-22 14:11:22 +02006753
Willy Tarreau83061a82018-07-13 11:56:34 +02006754/* Copy Date in ASN1_UTCTIME format in struct buffer out.
Emeric Brunce5ad802012-10-22 14:11:22 +02006755 * Returns 1 if serial is found and copied, 0 if no valid time found
6756 * and -1 if output is not large enough.
6757 */
6758static int
Willy Tarreau83061a82018-07-13 11:56:34 +02006759ssl_sock_get_time(ASN1_TIME *tm, struct buffer *out)
Emeric Brunce5ad802012-10-22 14:11:22 +02006760{
6761 if (tm->type == V_ASN1_GENERALIZEDTIME) {
6762 ASN1_GENERALIZEDTIME *gentm = (ASN1_GENERALIZEDTIME *)tm;
6763
6764 if (gentm->length < 12)
6765 return 0;
6766 if (gentm->data[0] != 0x32 || gentm->data[1] != 0x30)
6767 return 0;
6768 if (out->size < gentm->length-2)
6769 return -1;
6770
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006771 memcpy(out->area, gentm->data+2, gentm->length-2);
6772 out->data = gentm->length-2;
Emeric Brunce5ad802012-10-22 14:11:22 +02006773 return 1;
6774 }
6775 else if (tm->type == V_ASN1_UTCTIME) {
6776 ASN1_UTCTIME *utctm = (ASN1_UTCTIME *)tm;
6777
6778 if (utctm->length < 10)
6779 return 0;
6780 if (utctm->data[0] >= 0x35)
6781 return 0;
6782 if (out->size < utctm->length)
6783 return -1;
6784
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006785 memcpy(out->area, utctm->data, utctm->length);
6786 out->data = utctm->length;
Emeric Brunce5ad802012-10-22 14:11:22 +02006787 return 1;
6788 }
6789
6790 return 0;
6791}
6792
Emeric Brun87855892012-10-17 17:39:35 +02006793/* Extract an entry from a X509_NAME and copy its value to an output chunk.
6794 * Returns 1 if entry found, 0 if entry not found, or -1 if output not large enough.
6795 */
6796static int
Willy Tarreau83061a82018-07-13 11:56:34 +02006797ssl_sock_get_dn_entry(X509_NAME *a, const struct buffer *entry, int pos,
6798 struct buffer *out)
Emeric Brun87855892012-10-17 17:39:35 +02006799{
6800 X509_NAME_ENTRY *ne;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006801 ASN1_OBJECT *obj;
6802 ASN1_STRING *data;
6803 const unsigned char *data_ptr;
6804 int data_len;
Emeric Brun87855892012-10-17 17:39:35 +02006805 int i, j, n;
6806 int cur = 0;
6807 const char *s;
6808 char tmp[128];
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006809 int name_count;
6810
6811 name_count = X509_NAME_entry_count(a);
Emeric Brun87855892012-10-17 17:39:35 +02006812
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006813 out->data = 0;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006814 for (i = 0; i < name_count; i++) {
Emeric Brun87855892012-10-17 17:39:35 +02006815 if (pos < 0)
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006816 j = (name_count-1) - i;
Emeric Brun87855892012-10-17 17:39:35 +02006817 else
6818 j = i;
6819
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006820 ne = X509_NAME_get_entry(a, j);
6821 obj = X509_NAME_ENTRY_get_object(ne);
6822 data = X509_NAME_ENTRY_get_data(ne);
6823 data_ptr = ASN1_STRING_get0_data(data);
6824 data_len = ASN1_STRING_length(data);
6825 n = OBJ_obj2nid(obj);
Emeric Brun87855892012-10-17 17:39:35 +02006826 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006827 i2t_ASN1_OBJECT(tmp, sizeof(tmp), obj);
Emeric Brun87855892012-10-17 17:39:35 +02006828 s = tmp;
6829 }
6830
6831 if (chunk_strcasecmp(entry, s) != 0)
6832 continue;
6833
6834 if (pos < 0)
6835 cur--;
6836 else
6837 cur++;
6838
6839 if (cur != pos)
6840 continue;
6841
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006842 if (data_len > out->size)
Emeric Brun87855892012-10-17 17:39:35 +02006843 return -1;
6844
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006845 memcpy(out->area, data_ptr, data_len);
6846 out->data = data_len;
Emeric Brun87855892012-10-17 17:39:35 +02006847 return 1;
6848 }
6849
6850 return 0;
6851
6852}
6853
6854/* Extract and format full DN from a X509_NAME and copy result into a chunk
6855 * Returns 1 if dn entries exits, 0 if no dn entry found or -1 if output is not large enough.
6856 */
6857static int
Willy Tarreau83061a82018-07-13 11:56:34 +02006858ssl_sock_get_dn_oneline(X509_NAME *a, struct buffer *out)
Emeric Brun87855892012-10-17 17:39:35 +02006859{
6860 X509_NAME_ENTRY *ne;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006861 ASN1_OBJECT *obj;
6862 ASN1_STRING *data;
6863 const unsigned char *data_ptr;
6864 int data_len;
Emeric Brun87855892012-10-17 17:39:35 +02006865 int i, n, ln;
6866 int l = 0;
6867 const char *s;
6868 char *p;
6869 char tmp[128];
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006870 int name_count;
6871
6872
6873 name_count = X509_NAME_entry_count(a);
Emeric Brun87855892012-10-17 17:39:35 +02006874
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006875 out->data = 0;
6876 p = out->area;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006877 for (i = 0; i < name_count; i++) {
6878 ne = X509_NAME_get_entry(a, i);
6879 obj = X509_NAME_ENTRY_get_object(ne);
6880 data = X509_NAME_ENTRY_get_data(ne);
6881 data_ptr = ASN1_STRING_get0_data(data);
6882 data_len = ASN1_STRING_length(data);
6883 n = OBJ_obj2nid(obj);
Emeric Brun87855892012-10-17 17:39:35 +02006884 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006885 i2t_ASN1_OBJECT(tmp, sizeof(tmp), obj);
Emeric Brun87855892012-10-17 17:39:35 +02006886 s = tmp;
6887 }
6888 ln = strlen(s);
6889
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006890 l += 1 + ln + 1 + data_len;
Emeric Brun87855892012-10-17 17:39:35 +02006891 if (l > out->size)
6892 return -1;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006893 out->data = l;
Emeric Brun87855892012-10-17 17:39:35 +02006894
6895 *(p++)='/';
6896 memcpy(p, s, ln);
6897 p += ln;
6898 *(p++)='=';
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006899 memcpy(p, data_ptr, data_len);
6900 p += data_len;
Emeric Brun87855892012-10-17 17:39:35 +02006901 }
6902
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006903 if (!out->data)
Emeric Brun87855892012-10-17 17:39:35 +02006904 return 0;
6905
6906 return 1;
6907}
6908
Olivier Houchardab28a322018-12-21 19:45:40 +01006909void ssl_sock_set_alpn(struct connection *conn, const unsigned char *alpn, int len)
6910{
6911#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Christopher Faulet82004142019-09-10 10:12:03 +02006912 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006913
Olivier Houcharde488ea82019-06-28 14:10:33 +02006914 if (!ssl_sock_is_ssl(conn))
6915 return;
Christopher Faulet82004142019-09-10 10:12:03 +02006916 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006917 SSL_set_alpn_protos(ctx->ssl, alpn, len);
Olivier Houchardab28a322018-12-21 19:45:40 +01006918#endif
6919}
6920
Willy Tarreau119a4082016-12-22 21:58:38 +01006921/* Sets advertised SNI for outgoing connections. Please set <hostname> to NULL
6922 * to disable SNI.
6923 */
Willy Tarreau63076412015-07-10 11:33:32 +02006924void ssl_sock_set_servername(struct connection *conn, const char *hostname)
6925{
6926#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Christopher Faulet82004142019-09-10 10:12:03 +02006927 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006928
Willy Tarreau119a4082016-12-22 21:58:38 +01006929 char *prev_name;
6930
Willy Tarreau63076412015-07-10 11:33:32 +02006931 if (!ssl_sock_is_ssl(conn))
6932 return;
Christopher Faulet82004142019-09-10 10:12:03 +02006933 ctx = conn->xprt_ctx;
Willy Tarreau63076412015-07-10 11:33:32 +02006934
Willy Tarreau119a4082016-12-22 21:58:38 +01006935 /* if the SNI changes, we must destroy the reusable context so that a
6936 * new connection will present a new SNI. As an optimization we could
6937 * later imagine having a small cache of ssl_ctx to hold a few SNI per
6938 * server.
6939 */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006940 prev_name = (char *)SSL_get_servername(ctx->ssl, TLSEXT_NAMETYPE_host_name);
Willy Tarreau119a4082016-12-22 21:58:38 +01006941 if ((!prev_name && hostname) ||
6942 (prev_name && (!hostname || strcmp(hostname, prev_name) != 0)))
Olivier Houchard66ab4982019-02-26 18:37:15 +01006943 SSL_set_session(ctx->ssl, NULL);
Willy Tarreau119a4082016-12-22 21:58:38 +01006944
Olivier Houchard66ab4982019-02-26 18:37:15 +01006945 SSL_set_tlsext_host_name(ctx->ssl, hostname);
Willy Tarreau63076412015-07-10 11:33:32 +02006946#endif
6947}
6948
Emeric Brun0abf8362014-06-24 18:26:41 +02006949/* Extract peer certificate's common name into the chunk dest
6950 * Returns
6951 * the len of the extracted common name
6952 * or 0 if no CN found in DN
6953 * or -1 on error case (i.e. no peer certificate)
6954 */
Willy Tarreau83061a82018-07-13 11:56:34 +02006955int ssl_sock_get_remote_common_name(struct connection *conn,
6956 struct buffer *dest)
David Safb76832014-05-08 23:42:08 -04006957{
Christopher Faulet82004142019-09-10 10:12:03 +02006958 struct ssl_sock_ctx *ctx;
David Safb76832014-05-08 23:42:08 -04006959 X509 *crt = NULL;
6960 X509_NAME *name;
David Safb76832014-05-08 23:42:08 -04006961 const char find_cn[] = "CN";
Willy Tarreau83061a82018-07-13 11:56:34 +02006962 const struct buffer find_cn_chunk = {
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006963 .area = (char *)&find_cn,
6964 .data = sizeof(find_cn)-1
David Safb76832014-05-08 23:42:08 -04006965 };
Emeric Brun0abf8362014-06-24 18:26:41 +02006966 int result = -1;
David Safb76832014-05-08 23:42:08 -04006967
6968 if (!ssl_sock_is_ssl(conn))
Emeric Brun0abf8362014-06-24 18:26:41 +02006969 goto out;
Christopher Faulet82004142019-09-10 10:12:03 +02006970 ctx = conn->xprt_ctx;
David Safb76832014-05-08 23:42:08 -04006971
6972 /* SSL_get_peer_certificate, it increase X509 * ref count */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006973 crt = SSL_get_peer_certificate(ctx->ssl);
David Safb76832014-05-08 23:42:08 -04006974 if (!crt)
6975 goto out;
6976
6977 name = X509_get_subject_name(crt);
6978 if (!name)
6979 goto out;
David Safb76832014-05-08 23:42:08 -04006980
Emeric Brun0abf8362014-06-24 18:26:41 +02006981 result = ssl_sock_get_dn_entry(name, &find_cn_chunk, 1, dest);
6982out:
David Safb76832014-05-08 23:42:08 -04006983 if (crt)
6984 X509_free(crt);
6985
6986 return result;
6987}
6988
Dave McCowan328fb582014-07-30 10:39:13 -04006989/* returns 1 if client passed a certificate for this session, 0 if not */
6990int ssl_sock_get_cert_used_sess(struct connection *conn)
6991{
Christopher Faulet82004142019-09-10 10:12:03 +02006992 struct ssl_sock_ctx *ctx;
Dave McCowan328fb582014-07-30 10:39:13 -04006993 X509 *crt = NULL;
6994
6995 if (!ssl_sock_is_ssl(conn))
6996 return 0;
Christopher Faulet82004142019-09-10 10:12:03 +02006997 ctx = conn->xprt_ctx;
Dave McCowan328fb582014-07-30 10:39:13 -04006998
6999 /* SSL_get_peer_certificate, it increase X509 * ref count */
Olivier Houchard66ab4982019-02-26 18:37:15 +01007000 crt = SSL_get_peer_certificate(ctx->ssl);
Dave McCowan328fb582014-07-30 10:39:13 -04007001 if (!crt)
7002 return 0;
7003
7004 X509_free(crt);
7005 return 1;
7006}
7007
7008/* returns 1 if client passed a certificate for this connection, 0 if not */
7009int ssl_sock_get_cert_used_conn(struct connection *conn)
David Safb76832014-05-08 23:42:08 -04007010{
Christopher Faulet82004142019-09-10 10:12:03 +02007011 struct ssl_sock_ctx *ctx;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007012
David Safb76832014-05-08 23:42:08 -04007013 if (!ssl_sock_is_ssl(conn))
7014 return 0;
Christopher Faulet82004142019-09-10 10:12:03 +02007015 ctx = conn->xprt_ctx;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007016 return SSL_SOCK_ST_FL_VERIFY_DONE & ctx->xprt_st ? 1 : 0;
David Safb76832014-05-08 23:42:08 -04007017}
7018
7019/* returns result from SSL verify */
7020unsigned int ssl_sock_get_verify_result(struct connection *conn)
7021{
Christopher Faulet82004142019-09-10 10:12:03 +02007022 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007023
David Safb76832014-05-08 23:42:08 -04007024 if (!ssl_sock_is_ssl(conn))
7025 return (unsigned int)X509_V_ERR_APPLICATION_VERIFICATION;
Christopher Faulet82004142019-09-10 10:12:03 +02007026 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007027 return (unsigned int)SSL_get_verify_result(ctx->ssl);
David Safb76832014-05-08 23:42:08 -04007028}
7029
Willy Tarreau8743f7e2016-12-04 18:44:29 +01007030/* Returns the application layer protocol name in <str> and <len> when known.
7031 * Zero is returned if the protocol name was not found, otherwise non-zero is
7032 * returned. The string is allocated in the SSL context and doesn't have to be
7033 * freed by the caller. NPN is also checked if available since older versions
7034 * of openssl (1.0.1) which are more common in field only support this one.
7035 */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01007036static int ssl_sock_get_alpn(const struct connection *conn, void *xprt_ctx, const char **str, int *len)
Willy Tarreau8743f7e2016-12-04 18:44:29 +01007037{
Olivier Houchard66ab4982019-02-26 18:37:15 +01007038#if defined(TLSEXT_TYPE_application_layer_protocol_negotiation) || \
7039 defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Olivier Houcharde179d0e2019-03-21 18:27:17 +01007040 struct ssl_sock_ctx *ctx = xprt_ctx;
7041 if (!ctx)
Willy Tarreau8743f7e2016-12-04 18:44:29 +01007042 return 0;
7043
7044 *str = NULL;
7045
7046#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Olivier Houchard66ab4982019-02-26 18:37:15 +01007047 SSL_get0_alpn_selected(ctx->ssl, (const unsigned char **)str, (unsigned *)len);
Willy Tarreau8743f7e2016-12-04 18:44:29 +01007048 if (*str)
7049 return 1;
7050#endif
Bernard Spil13c53f82018-02-15 13:34:58 +01007051#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007052 SSL_get0_next_proto_negotiated(ctx->ssl, (const unsigned char **)str, (unsigned *)len);
Willy Tarreau8743f7e2016-12-04 18:44:29 +01007053 if (*str)
7054 return 1;
7055#endif
Olivier Houcharde179d0e2019-03-21 18:27:17 +01007056#endif
Willy Tarreau8743f7e2016-12-04 18:44:29 +01007057 return 0;
7058}
7059
Willy Tarreau7875d092012-09-10 08:20:03 +02007060/***** Below are some sample fetching functions for ACL/patterns *****/
7061
Olivier Houchardccaa7de2017-10-02 11:51:03 +02007062static int
7063smp_fetch_ssl_fc_has_early(const struct arg *args, struct sample *smp, const char *kw, void *private)
7064{
7065 struct connection *conn;
7066
7067 conn = objt_conn(smp->sess->origin);
7068 if (!conn || conn->xprt != &ssl_sock)
7069 return 0;
7070
7071 smp->flags = 0;
7072 smp->data.type = SMP_T_BOOL;
Emmanuel Hocdetc9858012019-08-07 14:44:49 +02007073#ifdef OPENSSL_IS_BORINGSSL
7074 {
7075 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
7076 smp->data.u.sint = (SSL_in_early_data(ctx->ssl) &&
7077 SSL_early_data_accepted(ctx->ssl));
7078 }
7079#else
Olivier Houchard25ae45a2017-11-29 19:51:19 +01007080 smp->data.u.sint = ((conn->flags & CO_FL_EARLY_DATA) &&
7081 (conn->flags & (CO_FL_EARLY_SSL_HS | CO_FL_HANDSHAKE))) ? 1 : 0;
Emmanuel Hocdetc9858012019-08-07 14:44:49 +02007082#endif
Olivier Houchardccaa7de2017-10-02 11:51:03 +02007083 return 1;
7084}
7085
Emeric Brune64aef12012-09-21 13:15:06 +02007086/* boolean, returns true if client cert was present */
7087static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007088smp_fetch_ssl_fc_has_crt(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brune64aef12012-09-21 13:15:06 +02007089{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007090 struct connection *conn;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007091 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007092
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007093 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007094 if (!conn || conn->xprt != &ssl_sock)
Emeric Brune64aef12012-09-21 13:15:06 +02007095 return 0;
7096
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007097 ctx = conn->xprt_ctx;
7098
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007099 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brune64aef12012-09-21 13:15:06 +02007100 smp->flags |= SMP_F_MAY_CHANGE;
7101 return 0;
7102 }
7103
7104 smp->flags = 0;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007105 smp->data.type = SMP_T_BOOL;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007106 smp->data.u.sint = SSL_SOCK_ST_FL_VERIFY_DONE & ctx->xprt_st ? 1 : 0;
Emeric Brune64aef12012-09-21 13:15:06 +02007107
7108 return 1;
7109}
7110
Emeric Brun43e79582014-10-29 19:03:26 +01007111/* binary, returns a certificate in a binary chunk (der/raw).
7112 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7113 * should be use.
7114 */
7115static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007116smp_fetch_ssl_x_der(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun43e79582014-10-29 19:03:26 +01007117{
7118 int cert_peer = (kw[4] == 'c') ? 1 : 0;
7119 X509 *crt = NULL;
7120 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02007121 struct buffer *smp_trash;
Emeric Brun43e79582014-10-29 19:03:26 +01007122 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007123 struct ssl_sock_ctx *ctx;
Emeric Brun43e79582014-10-29 19:03:26 +01007124
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007125 conn = objt_conn(smp->sess->origin);
Emeric Brun43e79582014-10-29 19:03:26 +01007126 if (!conn || conn->xprt != &ssl_sock)
7127 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007128 ctx = conn->xprt_ctx;
Emeric Brun43e79582014-10-29 19:03:26 +01007129
7130 if (!(conn->flags & CO_FL_CONNECTED)) {
7131 smp->flags |= SMP_F_MAY_CHANGE;
7132 return 0;
7133 }
7134
7135 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007136 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brun43e79582014-10-29 19:03:26 +01007137 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007138 crt = SSL_get_certificate(ctx->ssl);
Emeric Brun43e79582014-10-29 19:03:26 +01007139
7140 if (!crt)
7141 goto out;
7142
7143 smp_trash = get_trash_chunk();
7144 if (ssl_sock_crt2der(crt, smp_trash) <= 0)
7145 goto out;
7146
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007147 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007148 smp->data.type = SMP_T_BIN;
Emeric Brun43e79582014-10-29 19:03:26 +01007149 ret = 1;
7150out:
7151 /* SSL_get_peer_certificate, it increase X509 * ref count */
7152 if (cert_peer && crt)
7153 X509_free(crt);
7154 return ret;
7155}
7156
Emeric Brunba841a12014-04-30 17:05:08 +02007157/* binary, returns serial of certificate in a binary chunk.
7158 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7159 * should be use.
7160 */
Willy Tarreau8d598402012-10-22 17:58:39 +02007161static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007162smp_fetch_ssl_x_serial(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau8d598402012-10-22 17:58:39 +02007163{
Emeric Brunba841a12014-04-30 17:05:08 +02007164 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Willy Tarreau8d598402012-10-22 17:58:39 +02007165 X509 *crt = NULL;
7166 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02007167 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007168 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007169 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007170
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007171 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007172 if (!conn || conn->xprt != &ssl_sock)
Willy Tarreau8d598402012-10-22 17:58:39 +02007173 return 0;
7174
Olivier Houchard66ab4982019-02-26 18:37:15 +01007175 ctx = conn->xprt_ctx;
7176
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007177 if (!(conn->flags & CO_FL_CONNECTED)) {
Willy Tarreau8d598402012-10-22 17:58:39 +02007178 smp->flags |= SMP_F_MAY_CHANGE;
7179 return 0;
7180 }
7181
Emeric Brunba841a12014-04-30 17:05:08 +02007182 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007183 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007184 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007185 crt = SSL_get_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007186
Willy Tarreau8d598402012-10-22 17:58:39 +02007187 if (!crt)
7188 goto out;
7189
Willy Tarreau47ca5452012-12-23 20:22:19 +01007190 smp_trash = get_trash_chunk();
Willy Tarreau8d598402012-10-22 17:58:39 +02007191 if (ssl_sock_get_serial(crt, smp_trash) <= 0)
7192 goto out;
7193
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007194 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007195 smp->data.type = SMP_T_BIN;
Willy Tarreau8d598402012-10-22 17:58:39 +02007196 ret = 1;
7197out:
Emeric Brunba841a12014-04-30 17:05:08 +02007198 /* SSL_get_peer_certificate, it increase X509 * ref count */
7199 if (cert_peer && crt)
Willy Tarreau8d598402012-10-22 17:58:39 +02007200 X509_free(crt);
7201 return ret;
7202}
Emeric Brune64aef12012-09-21 13:15:06 +02007203
Emeric Brunba841a12014-04-30 17:05:08 +02007204/* binary, returns the client certificate's SHA-1 fingerprint (SHA-1 hash of DER-encoded certificate) in a binary chunk.
7205 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7206 * should be use.
7207 */
James Votha051b4a2013-05-14 20:37:59 +02007208static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007209smp_fetch_ssl_x_sha1(const struct arg *args, struct sample *smp, const char *kw, void *private)
James Votha051b4a2013-05-14 20:37:59 +02007210{
Emeric Brunba841a12014-04-30 17:05:08 +02007211 int cert_peer = (kw[4] == 'c') ? 1 : 0;
James Votha051b4a2013-05-14 20:37:59 +02007212 X509 *crt = NULL;
7213 const EVP_MD *digest;
7214 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02007215 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007216 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007217 struct ssl_sock_ctx *ctx;
James Votha051b4a2013-05-14 20:37:59 +02007218
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007219 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007220 if (!conn || conn->xprt != &ssl_sock)
7221 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007222 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007223
7224 if (!(conn->flags & CO_FL_CONNECTED)) {
James Votha051b4a2013-05-14 20:37:59 +02007225 smp->flags |= SMP_F_MAY_CHANGE;
7226 return 0;
7227 }
7228
Emeric Brunba841a12014-04-30 17:05:08 +02007229 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007230 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007231 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007232 crt = SSL_get_certificate(ctx->ssl);
James Votha051b4a2013-05-14 20:37:59 +02007233 if (!crt)
7234 goto out;
7235
7236 smp_trash = get_trash_chunk();
7237 digest = EVP_sha1();
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007238 X509_digest(crt, digest, (unsigned char *) smp_trash->area,
7239 (unsigned int *)&smp_trash->data);
James Votha051b4a2013-05-14 20:37:59 +02007240
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007241 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007242 smp->data.type = SMP_T_BIN;
James Votha051b4a2013-05-14 20:37:59 +02007243 ret = 1;
7244out:
Emeric Brunba841a12014-04-30 17:05:08 +02007245 /* SSL_get_peer_certificate, it increase X509 * ref count */
7246 if (cert_peer && crt)
James Votha051b4a2013-05-14 20:37:59 +02007247 X509_free(crt);
7248 return ret;
7249}
7250
Emeric Brunba841a12014-04-30 17:05:08 +02007251/* string, returns certificate's notafter date in ASN1_UTCTIME format.
7252 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7253 * should be use.
7254 */
Emeric Brunce5ad802012-10-22 14:11:22 +02007255static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007256smp_fetch_ssl_x_notafter(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunce5ad802012-10-22 14:11:22 +02007257{
Emeric Brunba841a12014-04-30 17:05:08 +02007258 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brunce5ad802012-10-22 14:11:22 +02007259 X509 *crt = NULL;
7260 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02007261 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007262 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007263 struct ssl_sock_ctx *ctx;
Emeric Brunce5ad802012-10-22 14:11:22 +02007264
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007265 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007266 if (!conn || conn->xprt != &ssl_sock)
7267 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007268 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007269
7270 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02007271 smp->flags |= SMP_F_MAY_CHANGE;
7272 return 0;
7273 }
7274
Emeric Brunba841a12014-04-30 17:05:08 +02007275 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007276 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007277 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007278 crt = SSL_get_certificate(ctx->ssl);
Emeric Brunce5ad802012-10-22 14:11:22 +02007279 if (!crt)
7280 goto out;
7281
Willy Tarreau47ca5452012-12-23 20:22:19 +01007282 smp_trash = get_trash_chunk();
Rosen Penev68185952018-12-14 08:47:02 -08007283 if (ssl_sock_get_time(X509_getm_notAfter(crt), smp_trash) <= 0)
Emeric Brunce5ad802012-10-22 14:11:22 +02007284 goto out;
7285
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007286 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007287 smp->data.type = SMP_T_STR;
Emeric Brunce5ad802012-10-22 14:11:22 +02007288 ret = 1;
7289out:
Emeric Brunba841a12014-04-30 17:05:08 +02007290 /* SSL_get_peer_certificate, it increase X509 * ref count */
7291 if (cert_peer && crt)
Emeric Brunce5ad802012-10-22 14:11:22 +02007292 X509_free(crt);
7293 return ret;
7294}
7295
Emeric Brunba841a12014-04-30 17:05:08 +02007296/* string, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. of certificate's issuer
7297 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7298 * should be use.
7299 */
Emeric Brun87855892012-10-17 17:39:35 +02007300static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007301smp_fetch_ssl_x_i_dn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun87855892012-10-17 17:39:35 +02007302{
Emeric Brunba841a12014-04-30 17:05:08 +02007303 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun87855892012-10-17 17:39:35 +02007304 X509 *crt = NULL;
7305 X509_NAME *name;
7306 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02007307 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007308 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007309 struct ssl_sock_ctx *ctx;
Emeric Brun87855892012-10-17 17:39:35 +02007310
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007311 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007312 if (!conn || conn->xprt != &ssl_sock)
7313 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007314 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007315
7316 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02007317 smp->flags |= SMP_F_MAY_CHANGE;
7318 return 0;
7319 }
7320
Emeric Brunba841a12014-04-30 17:05:08 +02007321 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007322 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007323 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007324 crt = SSL_get_certificate(ctx->ssl);
Emeric Brun87855892012-10-17 17:39:35 +02007325 if (!crt)
7326 goto out;
7327
7328 name = X509_get_issuer_name(crt);
7329 if (!name)
7330 goto out;
7331
Willy Tarreau47ca5452012-12-23 20:22:19 +01007332 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02007333 if (args && args[0].type == ARGT_STR) {
7334 int pos = 1;
7335
7336 if (args[1].type == ARGT_SINT)
7337 pos = args[1].data.sint;
Emeric Brun87855892012-10-17 17:39:35 +02007338
7339 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
7340 goto out;
7341 }
7342 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
7343 goto out;
7344
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007345 smp->data.type = SMP_T_STR;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007346 smp->data.u.str = *smp_trash;
Emeric Brun87855892012-10-17 17:39:35 +02007347 ret = 1;
7348out:
Emeric Brunba841a12014-04-30 17:05:08 +02007349 /* SSL_get_peer_certificate, it increase X509 * ref count */
7350 if (cert_peer && crt)
Emeric Brun87855892012-10-17 17:39:35 +02007351 X509_free(crt);
7352 return ret;
7353}
7354
Emeric Brunba841a12014-04-30 17:05:08 +02007355/* string, returns notbefore date in ASN1_UTCTIME format.
7356 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7357 * should be use.
7358 */
Emeric Brunce5ad802012-10-22 14:11:22 +02007359static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007360smp_fetch_ssl_x_notbefore(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunce5ad802012-10-22 14:11:22 +02007361{
Emeric Brunba841a12014-04-30 17:05:08 +02007362 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brunce5ad802012-10-22 14:11:22 +02007363 X509 *crt = NULL;
7364 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02007365 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007366 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007367 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007368
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007369 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007370 if (!conn || conn->xprt != &ssl_sock)
Emeric Brunce5ad802012-10-22 14:11:22 +02007371 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007372 ctx = conn->xprt_ctx;
Emeric Brunce5ad802012-10-22 14:11:22 +02007373
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007374 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02007375 smp->flags |= SMP_F_MAY_CHANGE;
7376 return 0;
7377 }
7378
Emeric Brunba841a12014-04-30 17:05:08 +02007379 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007380 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007381 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007382 crt = SSL_get_certificate(ctx->ssl);
Emeric Brunce5ad802012-10-22 14:11:22 +02007383 if (!crt)
7384 goto out;
7385
Willy Tarreau47ca5452012-12-23 20:22:19 +01007386 smp_trash = get_trash_chunk();
Rosen Penev68185952018-12-14 08:47:02 -08007387 if (ssl_sock_get_time(X509_getm_notBefore(crt), smp_trash) <= 0)
Emeric Brunce5ad802012-10-22 14:11:22 +02007388 goto out;
7389
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007390 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007391 smp->data.type = SMP_T_STR;
Emeric Brunce5ad802012-10-22 14:11:22 +02007392 ret = 1;
7393out:
Emeric Brunba841a12014-04-30 17:05:08 +02007394 /* SSL_get_peer_certificate, it increase X509 * ref count */
7395 if (cert_peer && crt)
Emeric Brunce5ad802012-10-22 14:11:22 +02007396 X509_free(crt);
7397 return ret;
7398}
7399
Emeric Brunba841a12014-04-30 17:05:08 +02007400/* string, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. of certificate's subject
7401 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7402 * should be use.
7403 */
Emeric Brun87855892012-10-17 17:39:35 +02007404static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007405smp_fetch_ssl_x_s_dn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun87855892012-10-17 17:39:35 +02007406{
Emeric Brunba841a12014-04-30 17:05:08 +02007407 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun87855892012-10-17 17:39:35 +02007408 X509 *crt = NULL;
7409 X509_NAME *name;
7410 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02007411 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007412 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007413 struct ssl_sock_ctx *ctx;
Emeric Brun87855892012-10-17 17:39:35 +02007414
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007415 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007416 if (!conn || conn->xprt != &ssl_sock)
7417 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007418 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007419
7420 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02007421 smp->flags |= SMP_F_MAY_CHANGE;
7422 return 0;
7423 }
7424
Emeric Brunba841a12014-04-30 17:05:08 +02007425 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007426 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007427 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007428 crt = SSL_get_certificate(ctx->ssl);
Emeric Brun87855892012-10-17 17:39:35 +02007429 if (!crt)
7430 goto out;
7431
7432 name = X509_get_subject_name(crt);
7433 if (!name)
7434 goto out;
7435
Willy Tarreau47ca5452012-12-23 20:22:19 +01007436 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02007437 if (args && args[0].type == ARGT_STR) {
7438 int pos = 1;
7439
7440 if (args[1].type == ARGT_SINT)
7441 pos = args[1].data.sint;
Emeric Brun87855892012-10-17 17:39:35 +02007442
7443 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
7444 goto out;
7445 }
7446 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
7447 goto out;
7448
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007449 smp->data.type = SMP_T_STR;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007450 smp->data.u.str = *smp_trash;
Emeric Brun87855892012-10-17 17:39:35 +02007451 ret = 1;
7452out:
Emeric Brunba841a12014-04-30 17:05:08 +02007453 /* SSL_get_peer_certificate, it increase X509 * ref count */
7454 if (cert_peer && crt)
Emeric Brun87855892012-10-17 17:39:35 +02007455 X509_free(crt);
7456 return ret;
7457}
Emeric Brun9143d372012-12-20 15:44:16 +01007458
7459/* integer, returns true if current session use a client certificate */
7460static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007461smp_fetch_ssl_c_used(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun9143d372012-12-20 15:44:16 +01007462{
7463 X509 *crt;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007464 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007465 struct ssl_sock_ctx *ctx;
Emeric Brun9143d372012-12-20 15:44:16 +01007466
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007467 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007468 if (!conn || conn->xprt != &ssl_sock)
7469 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007470 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007471
7472 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun9143d372012-12-20 15:44:16 +01007473 smp->flags |= SMP_F_MAY_CHANGE;
7474 return 0;
7475 }
7476
7477 /* SSL_get_peer_certificate returns a ptr on allocated X509 struct */
Olivier Houchard66ab4982019-02-26 18:37:15 +01007478 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brun9143d372012-12-20 15:44:16 +01007479 if (crt) {
7480 X509_free(crt);
7481 }
7482
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007483 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007484 smp->data.u.sint = (crt != NULL);
Emeric Brun9143d372012-12-20 15:44:16 +01007485 return 1;
7486}
7487
Emeric Brunba841a12014-04-30 17:05:08 +02007488/* integer, returns the certificate version
7489 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7490 * should be use.
7491 */
Emeric Bruna7359fd2012-10-17 15:03:11 +02007492static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007493smp_fetch_ssl_x_version(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Bruna7359fd2012-10-17 15:03:11 +02007494{
Emeric Brunba841a12014-04-30 17:05:08 +02007495 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Bruna7359fd2012-10-17 15:03:11 +02007496 X509 *crt;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007497 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007498 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007499
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007500 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007501 if (!conn || conn->xprt != &ssl_sock)
Emeric Bruna7359fd2012-10-17 15:03:11 +02007502 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007503 ctx = conn->xprt_ctx;
Emeric Bruna7359fd2012-10-17 15:03:11 +02007504
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007505 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Bruna7359fd2012-10-17 15:03:11 +02007506 smp->flags |= SMP_F_MAY_CHANGE;
7507 return 0;
7508 }
7509
Emeric Brunba841a12014-04-30 17:05:08 +02007510 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007511 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007512 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007513 crt = SSL_get_certificate(ctx->ssl);
Emeric Bruna7359fd2012-10-17 15:03:11 +02007514 if (!crt)
7515 return 0;
7516
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007517 smp->data.u.sint = (unsigned int)(1 + X509_get_version(crt));
Emeric Brunba841a12014-04-30 17:05:08 +02007518 /* SSL_get_peer_certificate increase X509 * ref count */
7519 if (cert_peer)
7520 X509_free(crt);
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007521 smp->data.type = SMP_T_SINT;
Emeric Bruna7359fd2012-10-17 15:03:11 +02007522
7523 return 1;
7524}
7525
Emeric Brunba841a12014-04-30 17:05:08 +02007526/* string, returns the certificate's signature algorithm.
7527 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7528 * should be use.
7529 */
Emeric Brun7f56e742012-10-19 18:15:40 +02007530static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007531smp_fetch_ssl_x_sig_alg(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun7f56e742012-10-19 18:15:40 +02007532{
Emeric Brunba841a12014-04-30 17:05:08 +02007533 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun7f56e742012-10-19 18:15:40 +02007534 X509 *crt;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007535 __OPENSSL_110_CONST__ ASN1_OBJECT *algorithm;
Emeric Brun7f56e742012-10-19 18:15:40 +02007536 int nid;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007537 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007538 struct ssl_sock_ctx *ctx;
Emeric Brun7f56e742012-10-19 18:15:40 +02007539
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007540 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007541 if (!conn || conn->xprt != &ssl_sock)
7542 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007543 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007544
7545 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun7f56e742012-10-19 18:15:40 +02007546 smp->flags |= SMP_F_MAY_CHANGE;
7547 return 0;
7548 }
7549
Emeric Brunba841a12014-04-30 17:05:08 +02007550 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007551 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007552 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007553 crt = SSL_get_certificate(ctx->ssl);
Emeric Brun7f56e742012-10-19 18:15:40 +02007554 if (!crt)
7555 return 0;
7556
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007557 X509_ALGOR_get0(&algorithm, NULL, NULL, X509_get0_tbs_sigalg(crt));
7558 nid = OBJ_obj2nid(algorithm);
Emeric Brun7f56e742012-10-19 18:15:40 +02007559
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007560 smp->data.u.str.area = (char *)OBJ_nid2sn(nid);
7561 if (!smp->data.u.str.area) {
Emeric Brunba841a12014-04-30 17:05:08 +02007562 /* SSL_get_peer_certificate increase X509 * ref count */
7563 if (cert_peer)
7564 X509_free(crt);
Emeric Brun7f56e742012-10-19 18:15:40 +02007565 return 0;
Emeric Brun9bf3ba22013-10-07 14:31:44 +02007566 }
Emeric Brun7f56e742012-10-19 18:15:40 +02007567
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007568 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01007569 smp->flags |= SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007570 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brunba841a12014-04-30 17:05:08 +02007571 /* SSL_get_peer_certificate increase X509 * ref count */
7572 if (cert_peer)
7573 X509_free(crt);
Emeric Brun7f56e742012-10-19 18:15:40 +02007574
7575 return 1;
7576}
7577
Emeric Brunba841a12014-04-30 17:05:08 +02007578/* string, returns the certificate's key algorithm.
7579 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7580 * should be use.
7581 */
Emeric Brun521a0112012-10-22 12:22:55 +02007582static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007583smp_fetch_ssl_x_key_alg(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun521a0112012-10-22 12:22:55 +02007584{
Emeric Brunba841a12014-04-30 17:05:08 +02007585 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun521a0112012-10-22 12:22:55 +02007586 X509 *crt;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007587 ASN1_OBJECT *algorithm;
Emeric Brun521a0112012-10-22 12:22:55 +02007588 int nid;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007589 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007590 struct ssl_sock_ctx *ctx;
Emeric Brun521a0112012-10-22 12:22:55 +02007591
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007592 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007593 if (!conn || conn->xprt != &ssl_sock)
7594 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007595 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007596
7597 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun521a0112012-10-22 12:22:55 +02007598 smp->flags |= SMP_F_MAY_CHANGE;
7599 return 0;
7600 }
7601
Emeric Brunba841a12014-04-30 17:05:08 +02007602 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007603 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007604 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007605 crt = SSL_get_certificate(ctx->ssl);
Emeric Brun521a0112012-10-22 12:22:55 +02007606 if (!crt)
7607 return 0;
7608
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007609 X509_PUBKEY_get0_param(&algorithm, NULL, NULL, NULL, X509_get_X509_PUBKEY(crt));
7610 nid = OBJ_obj2nid(algorithm);
Emeric Brun521a0112012-10-22 12:22:55 +02007611
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007612 smp->data.u.str.area = (char *)OBJ_nid2sn(nid);
7613 if (!smp->data.u.str.area) {
Emeric Brunba841a12014-04-30 17:05:08 +02007614 /* SSL_get_peer_certificate increase X509 * ref count */
7615 if (cert_peer)
7616 X509_free(crt);
Emeric Brun521a0112012-10-22 12:22:55 +02007617 return 0;
Emeric Brun9bf3ba22013-10-07 14:31:44 +02007618 }
Emeric Brun521a0112012-10-22 12:22:55 +02007619
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007620 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01007621 smp->flags |= SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007622 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brunba841a12014-04-30 17:05:08 +02007623 if (cert_peer)
7624 X509_free(crt);
Emeric Brun521a0112012-10-22 12:22:55 +02007625
7626 return 1;
7627}
7628
Emeric Brun645ae792014-04-30 14:21:06 +02007629/* boolean, returns true if front conn. transport layer is SSL.
7630 * This function is also usable on backend conn if the fetch keyword 5th
7631 * char is 'b'.
7632 */
Willy Tarreau7875d092012-09-10 08:20:03 +02007633static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007634smp_fetch_ssl_fc(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02007635{
Emeric Bruneb8def92018-02-19 15:59:48 +01007636 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7637 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007638
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007639 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007640 smp->data.u.sint = (conn && conn->xprt == &ssl_sock);
Willy Tarreau7875d092012-09-10 08:20:03 +02007641 return 1;
7642}
7643
Emeric Brun2525b6b2012-10-18 15:59:43 +02007644/* boolean, returns true if client present a SNI */
Willy Tarreau7875d092012-09-10 08:20:03 +02007645static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007646smp_fetch_ssl_fc_has_sni(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02007647{
7648#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007649 struct connection *conn = objt_conn(smp->sess->origin);
Olivier Houchard66ab4982019-02-26 18:37:15 +01007650 struct ssl_sock_ctx *ctx = conn ? conn->xprt_ctx : NULL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007651
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007652 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007653 smp->data.u.sint = (conn && conn->xprt == &ssl_sock) &&
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007654 conn->xprt_ctx &&
Olivier Houchard66ab4982019-02-26 18:37:15 +01007655 SSL_get_servername(ctx->ssl, TLSEXT_NAMETYPE_host_name) != NULL;
Willy Tarreau7875d092012-09-10 08:20:03 +02007656 return 1;
7657#else
7658 return 0;
7659#endif
7660}
7661
Emeric Brun74f7ffa2018-02-19 16:14:12 +01007662/* boolean, returns true if client session has been resumed.
7663 * This function is also usable on backend conn if the fetch keyword 5th
7664 * char is 'b'.
7665 */
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02007666static int
7667smp_fetch_ssl_fc_is_resumed(const struct arg *args, struct sample *smp, const char *kw, void *private)
7668{
Emeric Brun74f7ffa2018-02-19 16:14:12 +01007669 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7670 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007671 struct ssl_sock_ctx *ctx = conn ? conn->xprt_ctx : NULL;
Emeric Brun74f7ffa2018-02-19 16:14:12 +01007672
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02007673
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007674 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007675 smp->data.u.sint = (conn && conn->xprt == &ssl_sock) &&
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02007676 conn->xprt_ctx &&
Olivier Houchard66ab4982019-02-26 18:37:15 +01007677 SSL_session_reused(ctx->ssl);
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02007678 return 1;
7679}
7680
Emeric Brun645ae792014-04-30 14:21:06 +02007681/* string, returns the used cipher if front conn. transport layer is SSL.
7682 * This function is also usable on backend conn if the fetch keyword 5th
7683 * char is 'b'.
7684 */
Emeric Brun589fcad2012-10-16 14:13:26 +02007685static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007686smp_fetch_ssl_fc_cipher(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02007687{
Emeric Bruneb8def92018-02-19 15:59:48 +01007688 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7689 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007690 struct ssl_sock_ctx *ctx;
Emeric Brun589fcad2012-10-16 14:13:26 +02007691
Willy Tarreaube508f12016-03-10 11:47:01 +01007692 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007693 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02007694 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007695 ctx = conn->xprt_ctx;
Emeric Brun589fcad2012-10-16 14:13:26 +02007696
Olivier Houchard66ab4982019-02-26 18:37:15 +01007697 smp->data.u.str.area = (char *)SSL_get_cipher_name(ctx->ssl);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007698 if (!smp->data.u.str.area)
Emeric Brun589fcad2012-10-16 14:13:26 +02007699 return 0;
7700
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007701 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01007702 smp->flags |= SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007703 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brun589fcad2012-10-16 14:13:26 +02007704
7705 return 1;
7706}
7707
Emeric Brun645ae792014-04-30 14:21:06 +02007708/* integer, returns the algoritm's keysize if front conn. transport layer
7709 * is SSL.
7710 * This function is also usable on backend conn if the fetch keyword 5th
7711 * char is 'b'.
7712 */
Emeric Brun589fcad2012-10-16 14:13:26 +02007713static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007714smp_fetch_ssl_fc_alg_keysize(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02007715{
Emeric Bruneb8def92018-02-19 15:59:48 +01007716 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7717 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007718 struct ssl_sock_ctx *ctx;
Willy Tarreaue237fe12016-03-10 17:05:28 +01007719 int sint;
Willy Tarreaube508f12016-03-10 11:47:01 +01007720
Emeric Brun589fcad2012-10-16 14:13:26 +02007721 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007722 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02007723 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007724 ctx = conn->xprt_ctx;
Emeric Brun589fcad2012-10-16 14:13:26 +02007725
Olivier Houchard66ab4982019-02-26 18:37:15 +01007726 if (!SSL_get_cipher_bits(ctx->ssl, &sint))
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007727 return 0;
7728
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007729 smp->data.u.sint = sint;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007730 smp->data.type = SMP_T_SINT;
Emeric Brun589fcad2012-10-16 14:13:26 +02007731
7732 return 1;
7733}
7734
Emeric Brun645ae792014-04-30 14:21:06 +02007735/* integer, returns the used keysize if front conn. transport layer is SSL.
7736 * This function is also usable on backend conn if the fetch keyword 5th
7737 * char is 'b'.
7738 */
Emeric Brun589fcad2012-10-16 14:13:26 +02007739static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007740smp_fetch_ssl_fc_use_keysize(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02007741{
Emeric Bruneb8def92018-02-19 15:59:48 +01007742 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7743 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007744 struct ssl_sock_ctx *ctx;
Willy Tarreaube508f12016-03-10 11:47:01 +01007745
Emeric Brun589fcad2012-10-16 14:13:26 +02007746 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007747 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7748 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007749 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007750
Olivier Houchard66ab4982019-02-26 18:37:15 +01007751 smp->data.u.sint = (unsigned int)SSL_get_cipher_bits(ctx->ssl, NULL);
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007752 if (!smp->data.u.sint)
Emeric Brun589fcad2012-10-16 14:13:26 +02007753 return 0;
7754
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007755 smp->data.type = SMP_T_SINT;
Emeric Brun589fcad2012-10-16 14:13:26 +02007756
7757 return 1;
7758}
7759
Bernard Spil13c53f82018-02-15 13:34:58 +01007760#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Willy Tarreau7875d092012-09-10 08:20:03 +02007761static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007762smp_fetch_ssl_fc_npn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreaua33c6542012-10-15 13:19:06 +02007763{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007764 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007765 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007766
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01007767 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007768 smp->data.type = SMP_T_STR;
Willy Tarreaua33c6542012-10-15 13:19:06 +02007769
Olivier Houchard6b77f492018-11-22 18:18:29 +01007770 conn = (kw[4] != 'b' ) ? objt_conn(smp->sess->origin) :
7771 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
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
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007776 smp->data.u.str.area = NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007777 SSL_get0_next_proto_negotiated(ctx->ssl,
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007778 (const unsigned char **)&smp->data.u.str.area,
7779 (unsigned *)&smp->data.u.str.data);
Willy Tarreaua33c6542012-10-15 13:19:06 +02007780
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007781 if (!smp->data.u.str.area)
Willy Tarreaua33c6542012-10-15 13:19:06 +02007782 return 0;
7783
7784 return 1;
Willy Tarreaua33c6542012-10-15 13:19:06 +02007785}
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02007786#endif
Willy Tarreaua33c6542012-10-15 13:19:06 +02007787
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01007788#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02007789static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007790smp_fetch_ssl_fc_alpn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreauab861d32013-04-02 02:30:41 +02007791{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007792 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007793 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007794
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01007795 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007796 smp->data.type = SMP_T_STR;
Willy Tarreauab861d32013-04-02 02:30:41 +02007797
Olivier Houchard6b77f492018-11-22 18:18:29 +01007798 conn = (kw[4] != 'b' ) ? objt_conn(smp->sess->origin) :
7799 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
7800
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007801 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Willy Tarreauab861d32013-04-02 02:30:41 +02007802 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007803 ctx = conn->xprt_ctx;
Willy Tarreauab861d32013-04-02 02:30:41 +02007804
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007805 smp->data.u.str.area = NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007806 SSL_get0_alpn_selected(ctx->ssl,
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007807 (const unsigned char **)&smp->data.u.str.area,
7808 (unsigned *)&smp->data.u.str.data);
Willy Tarreauab861d32013-04-02 02:30:41 +02007809
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007810 if (!smp->data.u.str.area)
Willy Tarreauab861d32013-04-02 02:30:41 +02007811 return 0;
7812
7813 return 1;
7814}
7815#endif
7816
Emeric Brun645ae792014-04-30 14:21:06 +02007817/* string, returns the used protocol if front conn. transport layer is SSL.
7818 * This function is also usable on backend conn if the fetch keyword 5th
7819 * char is 'b'.
7820 */
Willy Tarreaua33c6542012-10-15 13:19:06 +02007821static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007822smp_fetch_ssl_fc_protocol(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02007823{
Emeric Bruneb8def92018-02-19 15:59:48 +01007824 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7825 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007826 struct ssl_sock_ctx *ctx;
Willy Tarreaube508f12016-03-10 11:47:01 +01007827
Emeric Brun589fcad2012-10-16 14:13:26 +02007828 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007829 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7830 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007831 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007832
Olivier Houchard66ab4982019-02-26 18:37:15 +01007833 smp->data.u.str.area = (char *)SSL_get_version(ctx->ssl);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007834 if (!smp->data.u.str.area)
Emeric Brun589fcad2012-10-16 14:13:26 +02007835 return 0;
7836
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007837 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01007838 smp->flags = SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007839 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brun589fcad2012-10-16 14:13:26 +02007840
7841 return 1;
7842}
7843
Willy Tarreau87b09662015-04-03 00:22:06 +02007844/* binary, returns the SSL stream id if front conn. transport layer is SSL.
Emeric Brun645ae792014-04-30 14:21:06 +02007845 * This function is also usable on backend conn if the fetch keyword 5th
7846 * char is 'b'.
7847 */
Willy Tarreau9a1ab082019-05-09 13:26:41 +02007848#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
Emeric Brun589fcad2012-10-16 14:13:26 +02007849static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007850smp_fetch_ssl_fc_session_id(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunfe68f682012-10-16 14:59:28 +02007851{
Emeric Bruneb8def92018-02-19 15:59:48 +01007852 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7853 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaue237fe12016-03-10 17:05:28 +01007854 SSL_SESSION *ssl_sess;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007855 struct ssl_sock_ctx *ctx;
Willy Tarreaube508f12016-03-10 11:47:01 +01007856
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01007857 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007858 smp->data.type = SMP_T_BIN;
Emeric Brunfe68f682012-10-16 14:59:28 +02007859
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007860 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7861 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007862 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007863
Olivier Houchard66ab4982019-02-26 18:37:15 +01007864 ssl_sess = SSL_get_session(ctx->ssl);
Willy Tarreau192252e2015-04-04 01:47:55 +02007865 if (!ssl_sess)
Emeric Brunfe68f682012-10-16 14:59:28 +02007866 return 0;
7867
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007868 smp->data.u.str.area = (char *)SSL_SESSION_get_id(ssl_sess,
7869 (unsigned int *)&smp->data.u.str.data);
7870 if (!smp->data.u.str.area || !smp->data.u.str.data)
Emeric Brunfe68f682012-10-16 14:59:28 +02007871 return 0;
7872
7873 return 1;
Emeric Brunfe68f682012-10-16 14:59:28 +02007874}
Patrick Hemmer41966772018-04-28 19:15:48 -04007875#endif
7876
Emeric Brunfe68f682012-10-16 14:59:28 +02007877
Emmanuel Hocdet839af572019-05-14 16:27:35 +02007878#if HA_OPENSSL_VERSION_NUMBER >= 0x10100000L
Patrick Hemmere0275472018-04-28 19:15:51 -04007879static int
Patrick Hemmer65674662019-06-04 08:13:03 -04007880smp_fetch_ssl_fc_random(const struct arg *args, struct sample *smp, const char *kw, void *private)
7881{
7882 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7883 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
7884 struct buffer *data;
7885 struct ssl_sock_ctx *ctx;
7886
7887 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7888 return 0;
7889 ctx = conn->xprt_ctx;
7890
7891 data = get_trash_chunk();
7892 if (kw[7] == 'c')
7893 data->data = SSL_get_client_random(ctx->ssl,
7894 (unsigned char *) data->area,
7895 data->size);
7896 else
7897 data->data = SSL_get_server_random(ctx->ssl,
7898 (unsigned char *) data->area,
7899 data->size);
7900 if (!data->data)
7901 return 0;
7902
7903 smp->flags = 0;
7904 smp->data.type = SMP_T_BIN;
7905 smp->data.u.str = *data;
7906
7907 return 1;
7908}
7909
7910static int
Patrick Hemmere0275472018-04-28 19:15:51 -04007911smp_fetch_ssl_fc_session_key(const struct arg *args, struct sample *smp, const char *kw, void *private)
7912{
7913 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7914 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
7915 SSL_SESSION *ssl_sess;
Willy Tarreau83061a82018-07-13 11:56:34 +02007916 struct buffer *data;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007917 struct ssl_sock_ctx *ctx;
Patrick Hemmere0275472018-04-28 19:15:51 -04007918
7919 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7920 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007921 ctx = conn->xprt_ctx;
Patrick Hemmere0275472018-04-28 19:15:51 -04007922
Olivier Houchard66ab4982019-02-26 18:37:15 +01007923 ssl_sess = SSL_get_session(ctx->ssl);
Patrick Hemmere0275472018-04-28 19:15:51 -04007924 if (!ssl_sess)
7925 return 0;
7926
7927 data = get_trash_chunk();
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007928 data->data = SSL_SESSION_get_master_key(ssl_sess,
7929 (unsigned char *) data->area,
7930 data->size);
7931 if (!data->data)
Patrick Hemmere0275472018-04-28 19:15:51 -04007932 return 0;
7933
7934 smp->flags = 0;
7935 smp->data.type = SMP_T_BIN;
7936 smp->data.u.str = *data;
7937
7938 return 1;
7939}
7940#endif
7941
Patrick Hemmer41966772018-04-28 19:15:48 -04007942#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emeric Brunfe68f682012-10-16 14:59:28 +02007943static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007944smp_fetch_ssl_fc_sni(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02007945{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007946 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007947 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007948
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01007949 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007950 smp->data.type = SMP_T_STR;
Willy Tarreau7875d092012-09-10 08:20:03 +02007951
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007952 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007953 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7954 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007955 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007956
Olivier Houchard66ab4982019-02-26 18:37:15 +01007957 smp->data.u.str.area = (char *)SSL_get_servername(ctx->ssl, TLSEXT_NAMETYPE_host_name);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007958 if (!smp->data.u.str.area)
Willy Tarreau3e394c92012-09-14 23:56:58 +02007959 return 0;
7960
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007961 smp->data.u.str.data = strlen(smp->data.u.str.area);
Willy Tarreau7875d092012-09-10 08:20:03 +02007962 return 1;
Willy Tarreau7875d092012-09-10 08:20:03 +02007963}
Patrick Hemmer41966772018-04-28 19:15:48 -04007964#endif
Willy Tarreau7875d092012-09-10 08:20:03 +02007965
David Sc1ad52e2014-04-08 18:48:47 -04007966static int
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007967smp_fetch_ssl_fc_cl_bin(const struct arg *args, struct sample *smp, const char *kw, void *private)
7968{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007969 struct connection *conn;
7970 struct ssl_capture *capture;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007971 struct ssl_sock_ctx *ctx;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007972
7973 conn = objt_conn(smp->sess->origin);
7974 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7975 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007976 ctx = conn->xprt_ctx;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007977
Olivier Houchard66ab4982019-02-26 18:37:15 +01007978 capture = SSL_get_ex_data(ctx->ssl, ssl_capture_ptr_index);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007979 if (!capture)
7980 return 0;
7981
7982 smp->flags = SMP_F_CONST;
7983 smp->data.type = SMP_T_BIN;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007984 smp->data.u.str.area = capture->ciphersuite;
7985 smp->data.u.str.data = capture->ciphersuite_len;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007986 return 1;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007987}
7988
7989static int
7990smp_fetch_ssl_fc_cl_hex(const struct arg *args, struct sample *smp, const char *kw, void *private)
7991{
Willy Tarreau83061a82018-07-13 11:56:34 +02007992 struct buffer *data;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007993
7994 if (!smp_fetch_ssl_fc_cl_bin(args, smp, kw, private))
7995 return 0;
7996
7997 data = get_trash_chunk();
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007998 dump_binary(data, smp->data.u.str.area, smp->data.u.str.data);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007999 smp->data.type = SMP_T_BIN;
8000 smp->data.u.str = *data;
8001 return 1;
8002}
8003
8004static int
8005smp_fetch_ssl_fc_cl_xxh64(const struct arg *args, struct sample *smp, const char *kw, void *private)
8006{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008007 struct connection *conn;
8008 struct ssl_capture *capture;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008009 struct ssl_sock_ctx *ctx;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008010
8011 conn = objt_conn(smp->sess->origin);
8012 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8013 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008014 ctx = conn->xprt_ctx;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008015
Olivier Houchard66ab4982019-02-26 18:37:15 +01008016 capture = SSL_get_ex_data(ctx->ssl, ssl_capture_ptr_index);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008017 if (!capture)
8018 return 0;
8019
8020 smp->data.type = SMP_T_SINT;
8021 smp->data.u.sint = capture->xxh64;
8022 return 1;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008023}
8024
8025static int
8026smp_fetch_ssl_fc_cl_str(const struct arg *args, struct sample *smp, const char *kw, void *private)
8027{
Willy Tarreau5db847a2019-05-09 14:13:35 +02008028#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL)
Willy Tarreau83061a82018-07-13 11:56:34 +02008029 struct buffer *data;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008030 int i;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008031
8032 if (!smp_fetch_ssl_fc_cl_bin(args, smp, kw, private))
8033 return 0;
8034
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008035 data = get_trash_chunk();
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008036 for (i = 0; i + 1 < smp->data.u.str.data; i += 2) {
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02008037 const char *str;
8038 const SSL_CIPHER *cipher;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008039 const unsigned char *bin = (const unsigned char *) smp->data.u.str.area + i;
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02008040 uint16_t id = (bin[0] << 8) | bin[1];
8041#if defined(OPENSSL_IS_BORINGSSL)
8042 cipher = SSL_get_cipher_by_value(id);
8043#else
Willy Tarreaub7290772018-10-15 11:01:59 +02008044 struct connection *conn = __objt_conn(smp->sess->origin);
Olivier Houchard66ab4982019-02-26 18:37:15 +01008045 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
8046 cipher = SSL_CIPHER_find(ctx->ssl, bin);
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02008047#endif
8048 str = SSL_CIPHER_get_name(cipher);
8049 if (!str || strcmp(str, "(NONE)") == 0)
8050 chunk_appendf(data, "%sUNKNOWN(%04x)", i == 0 ? "" : ",", id);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008051 else
8052 chunk_appendf(data, "%s%s", i == 0 ? "" : ",", str);
8053 }
8054 smp->data.type = SMP_T_STR;
8055 smp->data.u.str = *data;
8056 return 1;
8057#else
8058 return smp_fetch_ssl_fc_cl_xxh64(args, smp, kw, private);
8059#endif
8060}
8061
Willy Tarreau9a1ab082019-05-09 13:26:41 +02008062#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008063static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008064smp_fetch_ssl_fc_unique_id(const struct arg *args, struct sample *smp, const char *kw, void *private)
David Sc1ad52e2014-04-08 18:48:47 -04008065{
Emeric Bruneb8def92018-02-19 15:59:48 +01008066 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
8067 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
David Sc1ad52e2014-04-08 18:48:47 -04008068 int finished_len;
Willy Tarreau83061a82018-07-13 11:56:34 +02008069 struct buffer *finished_trash;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008070 struct ssl_sock_ctx *ctx;
David Sc1ad52e2014-04-08 18:48:47 -04008071
8072 smp->flags = 0;
David Sc1ad52e2014-04-08 18:48:47 -04008073 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8074 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008075 ctx = conn->xprt_ctx;
David Sc1ad52e2014-04-08 18:48:47 -04008076
8077 if (!(conn->flags & CO_FL_CONNECTED)) {
8078 smp->flags |= SMP_F_MAY_CHANGE;
8079 return 0;
8080 }
8081
8082 finished_trash = get_trash_chunk();
Olivier Houchard66ab4982019-02-26 18:37:15 +01008083 if (!SSL_session_reused(ctx->ssl))
8084 finished_len = SSL_get_peer_finished(ctx->ssl,
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008085 finished_trash->area,
8086 finished_trash->size);
David Sc1ad52e2014-04-08 18:48:47 -04008087 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01008088 finished_len = SSL_get_finished(ctx->ssl,
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008089 finished_trash->area,
8090 finished_trash->size);
David Sc1ad52e2014-04-08 18:48:47 -04008091
8092 if (!finished_len)
8093 return 0;
8094
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008095 finished_trash->data = finished_len;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02008096 smp->data.u.str = *finished_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008097 smp->data.type = SMP_T_BIN;
David Sc1ad52e2014-04-08 18:48:47 -04008098
8099 return 1;
David Sc1ad52e2014-04-08 18:48:47 -04008100}
Patrick Hemmer41966772018-04-28 19:15:48 -04008101#endif
David Sc1ad52e2014-04-08 18:48:47 -04008102
Emeric Brun2525b6b2012-10-18 15:59:43 +02008103/* integer, returns the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02008104static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008105smp_fetch_ssl_c_ca_err(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunf282a812012-09-21 15:27:54 +02008106{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008107 struct connection *conn;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008108 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008109
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02008110 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008111 if (!conn || conn->xprt != &ssl_sock)
8112 return 0;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008113 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008114
8115 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02008116 smp->flags = SMP_F_MAY_CHANGE;
8117 return 0;
8118 }
8119
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008120 smp->data.type = SMP_T_SINT;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008121 smp->data.u.sint = (unsigned long long int)SSL_SOCK_ST_TO_CA_ERROR(ctx->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02008122 smp->flags = 0;
8123
8124 return 1;
8125}
8126
Emeric Brun2525b6b2012-10-18 15:59:43 +02008127/* integer, returns the depth of the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02008128static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008129smp_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 +02008130{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008131 struct connection *conn;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008132 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008133
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02008134 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008135 if (!conn || conn->xprt != &ssl_sock)
Emeric Brunf282a812012-09-21 15:27:54 +02008136 return 0;
8137
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008138 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02008139 smp->flags = SMP_F_MAY_CHANGE;
8140 return 0;
8141 }
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008142 ctx = conn->xprt_ctx;
Emeric Brunf282a812012-09-21 15:27:54 +02008143
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008144 smp->data.type = SMP_T_SINT;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008145 smp->data.u.sint = (long long int)SSL_SOCK_ST_TO_CAEDEPTH(ctx->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02008146 smp->flags = 0;
8147
8148 return 1;
8149}
8150
Emeric Brun2525b6b2012-10-18 15:59:43 +02008151/* integer, returns the first verify error on client certificate */
Emeric Brunf282a812012-09-21 15:27:54 +02008152static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008153smp_fetch_ssl_c_err(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunf282a812012-09-21 15:27:54 +02008154{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008155 struct connection *conn;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008156 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008157
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02008158 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008159 if (!conn || conn->xprt != &ssl_sock)
8160 return 0;
8161
8162 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02008163 smp->flags = SMP_F_MAY_CHANGE;
8164 return 0;
8165 }
8166
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008167 ctx = conn->xprt_ctx;
8168
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008169 smp->data.type = SMP_T_SINT;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008170 smp->data.u.sint = (long long int)SSL_SOCK_ST_TO_CRTERROR(ctx->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02008171 smp->flags = 0;
8172
8173 return 1;
8174}
8175
Emeric Brun2525b6b2012-10-18 15:59:43 +02008176/* integer, returns the verify result on client cert */
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02008177static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008178smp_fetch_ssl_c_verify(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02008179{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008180 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008181 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008182
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02008183 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008184 if (!conn || conn->xprt != &ssl_sock)
8185 return 0;
8186
8187 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02008188 smp->flags = SMP_F_MAY_CHANGE;
8189 return 0;
8190 }
8191
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008192 if (!conn->xprt_ctx)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02008193 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008194 ctx = conn->xprt_ctx;
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02008195
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008196 smp->data.type = SMP_T_SINT;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008197 smp->data.u.sint = (long long int)SSL_get_verify_result(ctx->ssl);
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02008198 smp->flags = 0;
8199
8200 return 1;
8201}
8202
Emeric Brunfb510ea2012-10-05 12:00:26 +02008203/* parse the "ca-file" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008204static 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 +02008205{
8206 if (!*args[cur_arg + 1]) {
8207 if (err)
8208 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
8209 return ERR_ALERT | ERR_FATAL;
8210 }
8211
Willy Tarreauef934602016-12-22 23:12:01 +01008212 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
8213 memprintf(&conf->ca_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02008214 else
8215 memprintf(&conf->ca_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02008216
Emeric Brund94b3fe2012-09-20 18:23:56 +02008217 return 0;
8218}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008219static int bind_parse_ca_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8220{
8221 return ssl_bind_parse_ca_file(args, cur_arg, px, &conf->ssl_conf, err);
8222}
Emeric Brund94b3fe2012-09-20 18:23:56 +02008223
Christopher Faulet31af49d2015-06-09 17:29:50 +02008224/* parse the "ca-sign-file" bind keyword */
8225static int bind_parse_ca_sign_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8226{
8227 if (!*args[cur_arg + 1]) {
8228 if (err)
8229 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
8230 return ERR_ALERT | ERR_FATAL;
8231 }
8232
Willy Tarreauef934602016-12-22 23:12:01 +01008233 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
8234 memprintf(&conf->ca_sign_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Christopher Faulet31af49d2015-06-09 17:29:50 +02008235 else
8236 memprintf(&conf->ca_sign_file, "%s", args[cur_arg + 1]);
8237
8238 return 0;
8239}
8240
Bertrand Jacquinff13c062016-11-13 16:37:11 +00008241/* parse the "ca-sign-pass" bind keyword */
Christopher Faulet31af49d2015-06-09 17:29:50 +02008242static int bind_parse_ca_sign_pass(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8243{
8244 if (!*args[cur_arg + 1]) {
8245 if (err)
8246 memprintf(err, "'%s' : missing CAkey password", args[cur_arg]);
8247 return ERR_ALERT | ERR_FATAL;
8248 }
8249 memprintf(&conf->ca_sign_pass, "%s", args[cur_arg + 1]);
8250 return 0;
8251}
8252
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008253/* parse the "ciphers" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008254static 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 +02008255{
8256 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02008257 memprintf(err, "'%s' : missing cipher suite", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008258 return ERR_ALERT | ERR_FATAL;
8259 }
8260
Emeric Brun76d88952012-10-05 15:47:31 +02008261 free(conf->ciphers);
Willy Tarreau4348fad2012-09-20 16:48:07 +02008262 conf->ciphers = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008263 return 0;
8264}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008265static int bind_parse_ciphers(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8266{
8267 return ssl_bind_parse_ciphers(args, cur_arg, px, &conf->ssl_conf, err);
8268}
Dirkjan Bussink415150f2018-09-14 11:14:21 +02008269
Emmanuel Hocdet839af572019-05-14 16:27:35 +02008270#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02008271/* parse the "ciphersuites" bind keyword */
8272static int ssl_bind_parse_ciphersuites(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
8273{
8274 if (!*args[cur_arg + 1]) {
8275 memprintf(err, "'%s' : missing cipher suite", args[cur_arg]);
8276 return ERR_ALERT | ERR_FATAL;
8277 }
8278
8279 free(conf->ciphersuites);
8280 conf->ciphersuites = strdup(args[cur_arg + 1]);
8281 return 0;
8282}
8283static int bind_parse_ciphersuites(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8284{
8285 return ssl_bind_parse_ciphersuites(args, cur_arg, px, &conf->ssl_conf, err);
8286}
8287#endif
8288
Willy Tarreaubbc91962019-10-16 16:42:19 +02008289/* parse the "crt" bind keyword. Returns a set of ERR_* flags possibly with an error in <err>. */
Willy Tarreau4348fad2012-09-20 16:48:07 +02008290static 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 +02008291{
Willy Tarreau38011032013-08-13 16:59:39 +02008292 char path[MAXPATHLEN];
Willy Tarreaub75d6922014-04-14 18:05:41 +02008293
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008294 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02008295 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008296 return ERR_ALERT | ERR_FATAL;
8297 }
8298
Willy Tarreauef934602016-12-22 23:12:01 +01008299 if ((*args[cur_arg + 1] != '/' ) && global_ssl.crt_base) {
8300 if ((strlen(global_ssl.crt_base) + 1 + strlen(args[cur_arg + 1]) + 1) > MAXPATHLEN) {
Emeric Brunc8e8d122012-10-02 18:42:10 +02008301 memprintf(err, "'%s' : path too long", args[cur_arg]);
8302 return ERR_ALERT | ERR_FATAL;
8303 }
Willy Tarreauef934602016-12-22 23:12:01 +01008304 snprintf(path, sizeof(path), "%s/%s", global_ssl.crt_base, args[cur_arg + 1]);
Willy Tarreaubbc91962019-10-16 16:42:19 +02008305 return ssl_sock_load_cert(path, conf, err);
Emeric Brunc8e8d122012-10-02 18:42:10 +02008306 }
8307
Willy Tarreaubbc91962019-10-16 16:42:19 +02008308 return ssl_sock_load_cert(args[cur_arg + 1], conf, err);
Emeric Brund94b3fe2012-09-20 18:23:56 +02008309}
8310
Willy Tarreaubbc91962019-10-16 16:42:19 +02008311/* 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 +01008312static int bind_parse_crt_list(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8313{
Willy Tarreaubbc91962019-10-16 16:42:19 +02008314 int err_code;
8315
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01008316 if (!*args[cur_arg + 1]) {
8317 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
8318 return ERR_ALERT | ERR_FATAL;
8319 }
8320
Willy Tarreaubbc91962019-10-16 16:42:19 +02008321 err_code = ssl_sock_load_cert_list_file(args[cur_arg + 1], conf, px, err);
8322 if (err_code)
Willy Tarreauad1731d2013-04-02 17:35:58 +02008323 memprintf(err, "'%s' : %s", args[cur_arg], *err);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01008324
Willy Tarreaubbc91962019-10-16 16:42:19 +02008325 return err_code;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01008326}
8327
Emeric Brunfb510ea2012-10-05 12:00:26 +02008328/* parse the "crl-file" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008329static 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 +02008330{
Emeric Brun051cdab2012-10-02 19:25:50 +02008331#ifndef X509_V_FLAG_CRL_CHECK
8332 if (err)
8333 memprintf(err, "'%s' : library does not support CRL verify", args[cur_arg]);
8334 return ERR_ALERT | ERR_FATAL;
8335#else
Emeric Brund94b3fe2012-09-20 18:23:56 +02008336 if (!*args[cur_arg + 1]) {
8337 if (err)
8338 memprintf(err, "'%s' : missing CRLfile path", args[cur_arg]);
8339 return ERR_ALERT | ERR_FATAL;
8340 }
Emeric Brun2b58d042012-09-20 17:10:03 +02008341
Willy Tarreauef934602016-12-22 23:12:01 +01008342 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
8343 memprintf(&conf->crl_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02008344 else
8345 memprintf(&conf->crl_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02008346
Emeric Brun2b58d042012-09-20 17:10:03 +02008347 return 0;
Emeric Brun051cdab2012-10-02 19:25:50 +02008348#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02008349}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008350static int bind_parse_crl_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8351{
8352 return ssl_bind_parse_crl_file(args, cur_arg, px, &conf->ssl_conf, err);
8353}
Emeric Brun2b58d042012-09-20 17:10:03 +02008354
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01008355/* parse the "curves" bind keyword keyword */
8356static int ssl_bind_parse_curves(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
8357{
Willy Tarreau9a1ab082019-05-09 13:26:41 +02008358#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01008359 if (!*args[cur_arg + 1]) {
8360 if (err)
8361 memprintf(err, "'%s' : missing curve suite", args[cur_arg]);
8362 return ERR_ALERT | ERR_FATAL;
8363 }
8364 conf->curves = strdup(args[cur_arg + 1]);
8365 return 0;
8366#else
8367 if (err)
8368 memprintf(err, "'%s' : library does not support curve suite", args[cur_arg]);
8369 return ERR_ALERT | ERR_FATAL;
8370#endif
8371}
8372static int bind_parse_curves(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8373{
8374 return ssl_bind_parse_curves(args, cur_arg, px, &conf->ssl_conf, err);
8375}
8376
Bertrand Jacquinff13c062016-11-13 16:37:11 +00008377/* parse the "ecdhe" bind keyword keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008378static 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 +02008379{
Willy Tarreau9a1ab082019-05-09 13:26:41 +02008380#if HA_OPENSSL_VERSION_NUMBER < 0x0090800fL
Emeric Brun2b58d042012-09-20 17:10:03 +02008381 if (err)
8382 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (too old)", args[cur_arg]);
8383 return ERR_ALERT | ERR_FATAL;
8384#elif defined(OPENSSL_NO_ECDH)
8385 if (err)
8386 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (disabled via OPENSSL_NO_ECDH)", args[cur_arg]);
8387 return ERR_ALERT | ERR_FATAL;
8388#else
8389 if (!*args[cur_arg + 1]) {
8390 if (err)
8391 memprintf(err, "'%s' : missing named curve", args[cur_arg]);
8392 return ERR_ALERT | ERR_FATAL;
8393 }
8394
8395 conf->ecdhe = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008396
8397 return 0;
Emeric Brun2b58d042012-09-20 17:10:03 +02008398#endif
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008399}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008400static int bind_parse_ecdhe(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8401{
8402 return ssl_bind_parse_ecdhe(args, cur_arg, px, &conf->ssl_conf, err);
8403}
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008404
Bertrand Jacquinff13c062016-11-13 16:37:11 +00008405/* parse the "crt-ignore-err" and "ca-ignore-err" bind keywords */
Emeric Brun81c00f02012-09-21 14:31:21 +02008406static int bind_parse_ignore_err(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8407{
8408 int code;
8409 char *p = args[cur_arg + 1];
8410 unsigned long long *ignerr = &conf->crt_ignerr;
8411
8412 if (!*p) {
8413 if (err)
8414 memprintf(err, "'%s' : missing error IDs list", args[cur_arg]);
8415 return ERR_ALERT | ERR_FATAL;
8416 }
8417
8418 if (strcmp(args[cur_arg], "ca-ignore-err") == 0)
8419 ignerr = &conf->ca_ignerr;
8420
8421 if (strcmp(p, "all") == 0) {
8422 *ignerr = ~0ULL;
8423 return 0;
8424 }
8425
8426 while (p) {
8427 code = atoi(p);
8428 if ((code <= 0) || (code > 63)) {
8429 if (err)
8430 memprintf(err, "'%s' : ID '%d' out of range (1..63) in error IDs list '%s'",
8431 args[cur_arg], code, args[cur_arg + 1]);
8432 return ERR_ALERT | ERR_FATAL;
8433 }
8434 *ignerr |= 1ULL << code;
8435 p = strchr(p, ',');
8436 if (p)
8437 p++;
8438 }
8439
Emeric Brun2cb7ae52012-10-05 14:14:21 +02008440 return 0;
8441}
8442
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008443/* parse tls_method_options "no-xxx" and "force-xxx" */
8444static int parse_tls_method_options(char *arg, struct tls_version_filter *methods, char **err)
Emeric Brun2cb7ae52012-10-05 14:14:21 +02008445{
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008446 uint16_t v;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008447 char *p;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008448 p = strchr(arg, '-');
8449 if (!p)
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008450 goto fail;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008451 p++;
8452 if (!strcmp(p, "sslv3"))
8453 v = CONF_SSLV3;
8454 else if (!strcmp(p, "tlsv10"))
8455 v = CONF_TLSV10;
8456 else if (!strcmp(p, "tlsv11"))
8457 v = CONF_TLSV11;
8458 else if (!strcmp(p, "tlsv12"))
8459 v = CONF_TLSV12;
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +02008460 else if (!strcmp(p, "tlsv13"))
8461 v = CONF_TLSV13;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008462 else
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008463 goto fail;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008464 if (!strncmp(arg, "no-", 3))
8465 methods->flags |= methodVersions[v].flag;
8466 else if (!strncmp(arg, "force-", 6))
8467 methods->min = methods->max = v;
8468 else
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008469 goto fail;
Emeric Brun2d0c4822012-10-02 13:45:20 +02008470 return 0;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008471 fail:
8472 if (err)
8473 memprintf(err, "'%s' : option not implemented", arg);
8474 return ERR_ALERT | ERR_FATAL;
Emeric Brun2d0c4822012-10-02 13:45:20 +02008475}
8476
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008477static 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 +02008478{
Emmanuel Hocdet43664762017-08-09 18:26:20 +02008479 return parse_tls_method_options(args[cur_arg], &conf->ssl_conf.ssl_methods, err);
Emeric Brun2cb7ae52012-10-05 14:14:21 +02008480}
8481
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008482static 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 +02008483{
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008484 return parse_tls_method_options(args[*cur_arg], &newsrv->ssl_ctx.methods, err);
8485}
8486
8487/* parse tls_method min/max: "ssl-min-ver" and "ssl-max-ver" */
8488static int parse_tls_method_minmax(char **args, int cur_arg, struct tls_version_filter *methods, char **err)
8489{
8490 uint16_t i, v = 0;
8491 char *argv = args[cur_arg + 1];
8492 if (!*argv) {
8493 if (err)
8494 memprintf(err, "'%s' : missing the ssl/tls version", args[cur_arg]);
8495 return ERR_ALERT | ERR_FATAL;
8496 }
8497 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
8498 if (!strcmp(argv, methodVersions[i].name))
8499 v = i;
8500 if (!v) {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008501 if (err)
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008502 memprintf(err, "'%s' : unknown ssl/tls version", args[cur_arg + 1]);
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008503 return ERR_ALERT | ERR_FATAL;
8504 }
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008505 if (!strcmp("ssl-min-ver", args[cur_arg]))
8506 methods->min = v;
8507 else if (!strcmp("ssl-max-ver", args[cur_arg]))
8508 methods->max = v;
8509 else {
8510 if (err)
8511 memprintf(err, "'%s' : option not implemented", args[cur_arg]);
8512 return ERR_ALERT | ERR_FATAL;
8513 }
Emeric Brun2cb7ae52012-10-05 14:14:21 +02008514 return 0;
Emeric Brun2cb7ae52012-10-05 14:14:21 +02008515}
Emeric Brun2cb7ae52012-10-05 14:14:21 +02008516
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02008517static int ssl_bind_parse_tls_method_minmax(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
8518{
Willy Tarreau9a1ab082019-05-09 13:26:41 +02008519#if (HA_OPENSSL_VERSION_NUMBER < 0x10101000L) && !defined(OPENSSL_IS_BORINGSSL)
Christopher Faulet767a84b2017-11-24 16:50:31 +01008520 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 +02008521#endif
8522 return parse_tls_method_minmax(args, cur_arg, &conf->ssl_methods, err);
8523}
8524
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008525static int bind_parse_tls_method_minmax(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8526{
Emmanuel Hocdet43664762017-08-09 18:26:20 +02008527 return parse_tls_method_minmax(args, cur_arg, &conf->ssl_conf.ssl_methods, err);
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008528}
8529
8530static int srv_parse_tls_method_minmax(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8531{
8532 return parse_tls_method_minmax(args, *cur_arg, &newsrv->ssl_ctx.methods, err);
8533}
8534
Emeric Brun2d0c4822012-10-02 13:45:20 +02008535/* parse the "no-tls-tickets" bind keyword */
Emmanuel Hocdet4608ed92017-01-20 13:06:27 +01008536static 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 +02008537{
Emeric Brun89675492012-10-05 13:48:26 +02008538 conf->ssl_options |= BC_SSL_O_NO_TLS_TICKETS;
Emeric Brun81c00f02012-09-21 14:31:21 +02008539 return 0;
8540}
Emeric Brun2d0c4822012-10-02 13:45:20 +02008541
Olivier Houchardc2aae742017-09-22 18:26:28 +02008542/* parse the "allow-0rtt" bind keyword */
8543static int ssl_bind_parse_allow_0rtt(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
8544{
8545 conf->early_data = 1;
8546 return 0;
8547}
8548
8549static int bind_parse_allow_0rtt(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8550{
Olivier Houchard9679ac92017-10-27 14:58:08 +02008551 conf->ssl_conf.early_data = 1;
Olivier Houchardc2aae742017-09-22 18:26:28 +02008552 return 0;
8553}
8554
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02008555/* parse the "npn" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008556static 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 +02008557{
Bernard Spil13c53f82018-02-15 13:34:58 +01008558#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02008559 char *p1, *p2;
8560
8561 if (!*args[cur_arg + 1]) {
8562 memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[cur_arg]);
8563 return ERR_ALERT | ERR_FATAL;
8564 }
8565
8566 free(conf->npn_str);
8567
Willy Tarreau3724da12016-02-12 17:11:12 +01008568 /* the NPN string is built as a suite of (<len> <name>)*,
8569 * so we reuse each comma to store the next <len> and need
8570 * one more for the end of the string.
8571 */
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02008572 conf->npn_len = strlen(args[cur_arg + 1]) + 1;
Willy Tarreau3724da12016-02-12 17:11:12 +01008573 conf->npn_str = calloc(1, conf->npn_len + 1);
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02008574 memcpy(conf->npn_str + 1, args[cur_arg + 1], conf->npn_len);
8575
8576 /* replace commas with the name length */
8577 p1 = conf->npn_str;
8578 p2 = p1 + 1;
8579 while (1) {
8580 p2 = memchr(p1 + 1, ',', conf->npn_str + conf->npn_len - (p1 + 1));
8581 if (!p2)
8582 p2 = p1 + 1 + strlen(p1 + 1);
8583
8584 if (p2 - (p1 + 1) > 255) {
8585 *p2 = '\0';
8586 memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
8587 return ERR_ALERT | ERR_FATAL;
8588 }
8589
8590 *p1 = p2 - (p1 + 1);
8591 p1 = p2;
8592
8593 if (!*p2)
8594 break;
8595
8596 *(p2++) = '\0';
8597 }
8598 return 0;
8599#else
8600 if (err)
8601 memprintf(err, "'%s' : library does not support TLS NPN extension", args[cur_arg]);
8602 return ERR_ALERT | ERR_FATAL;
8603#endif
8604}
8605
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008606static int bind_parse_npn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8607{
8608 return ssl_bind_parse_npn(args, cur_arg, px, &conf->ssl_conf, err);
8609}
8610
Willy Tarreauab861d32013-04-02 02:30:41 +02008611/* parse the "alpn" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008612static 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 +02008613{
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01008614#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02008615 char *p1, *p2;
8616
8617 if (!*args[cur_arg + 1]) {
8618 memprintf(err, "'%s' : missing the comma-delimited ALPN protocol suite", args[cur_arg]);
8619 return ERR_ALERT | ERR_FATAL;
8620 }
8621
8622 free(conf->alpn_str);
8623
Marcoen Hirschbergbef60912016-02-12 17:05:24 +01008624 /* the ALPN string is built as a suite of (<len> <name>)*,
8625 * so we reuse each comma to store the next <len> and need
8626 * one more for the end of the string.
8627 */
Willy Tarreauab861d32013-04-02 02:30:41 +02008628 conf->alpn_len = strlen(args[cur_arg + 1]) + 1;
Marcoen Hirschbergbef60912016-02-12 17:05:24 +01008629 conf->alpn_str = calloc(1, conf->alpn_len + 1);
Willy Tarreauab861d32013-04-02 02:30:41 +02008630 memcpy(conf->alpn_str + 1, args[cur_arg + 1], conf->alpn_len);
8631
8632 /* replace commas with the name length */
8633 p1 = conf->alpn_str;
8634 p2 = p1 + 1;
8635 while (1) {
8636 p2 = memchr(p1 + 1, ',', conf->alpn_str + conf->alpn_len - (p1 + 1));
8637 if (!p2)
8638 p2 = p1 + 1 + strlen(p1 + 1);
8639
8640 if (p2 - (p1 + 1) > 255) {
8641 *p2 = '\0';
8642 memprintf(err, "'%s' : ALPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
8643 return ERR_ALERT | ERR_FATAL;
8644 }
8645
8646 *p1 = p2 - (p1 + 1);
8647 p1 = p2;
8648
8649 if (!*p2)
8650 break;
8651
8652 *(p2++) = '\0';
8653 }
8654 return 0;
8655#else
8656 if (err)
8657 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[cur_arg]);
8658 return ERR_ALERT | ERR_FATAL;
8659#endif
8660}
8661
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008662static int bind_parse_alpn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8663{
8664 return ssl_bind_parse_alpn(args, cur_arg, px, &conf->ssl_conf, err);
8665}
8666
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008667/* parse the "ssl" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02008668static 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 +02008669{
Willy Tarreau71a8c7c2016-12-21 22:04:54 +01008670 conf->xprt = &ssl_sock;
Willy Tarreau4348fad2012-09-20 16:48:07 +02008671 conf->is_ssl = 1;
Emeric Brun76d88952012-10-05 15:47:31 +02008672
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008673 if (global_ssl.listen_default_ciphers && !conf->ssl_conf.ciphers)
8674 conf->ssl_conf.ciphers = strdup(global_ssl.listen_default_ciphers);
Emmanuel Hocdet839af572019-05-14 16:27:35 +02008675#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02008676 if (global_ssl.listen_default_ciphersuites && !conf->ssl_conf.ciphersuites)
8677 conf->ssl_conf.ciphersuites = strdup(global_ssl.listen_default_ciphersuites);
8678#endif
Emmanuel Hocdet4608ed92017-01-20 13:06:27 +01008679 conf->ssl_options |= global_ssl.listen_default_ssloptions;
Emmanuel Hocdet43664762017-08-09 18:26:20 +02008680 conf->ssl_conf.ssl_methods.flags |= global_ssl.listen_default_sslmethods.flags;
8681 if (!conf->ssl_conf.ssl_methods.min)
8682 conf->ssl_conf.ssl_methods.min = global_ssl.listen_default_sslmethods.min;
8683 if (!conf->ssl_conf.ssl_methods.max)
8684 conf->ssl_conf.ssl_methods.max = global_ssl.listen_default_sslmethods.max;
Emeric Brun76d88952012-10-05 15:47:31 +02008685
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008686 return 0;
8687}
8688
Lukas Tribus53ae85c2017-05-04 15:45:40 +00008689/* parse the "prefer-client-ciphers" bind keyword */
8690static int bind_parse_pcc(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8691{
8692 conf->ssl_options |= BC_SSL_O_PREF_CLIE_CIPH;
8693 return 0;
8694}
8695
Christopher Faulet31af49d2015-06-09 17:29:50 +02008696/* parse the "generate-certificates" bind keyword */
8697static int bind_parse_generate_certs(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8698{
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01008699#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Christopher Faulet31af49d2015-06-09 17:29:50 +02008700 conf->generate_certs = 1;
8701#else
8702 memprintf(err, "%sthis version of openssl cannot generate SSL certificates.\n",
8703 err && *err ? *err : "");
8704#endif
8705 return 0;
8706}
8707
Emmanuel Hocdet65623372013-01-24 17:17:15 +01008708/* parse the "strict-sni" bind keyword */
8709static int bind_parse_strict_sni(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8710{
8711 conf->strict_sni = 1;
8712 return 0;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008713}
8714
8715/* parse the "tls-ticket-keys" bind keyword */
8716static int bind_parse_tls_ticket_keys(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8717{
8718#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
Christopher Faulete566f3d2019-10-21 09:55:49 +02008719 FILE *f = NULL;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008720 int i = 0;
8721 char thisline[LINESIZE];
Christopher Faulete566f3d2019-10-21 09:55:49 +02008722 struct tls_keys_ref *keys_ref = NULL;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008723
8724 if (!*args[cur_arg + 1]) {
8725 if (err)
8726 memprintf(err, "'%s' : missing TLS ticket keys file path", args[cur_arg]);
Christopher Faulete566f3d2019-10-21 09:55:49 +02008727 goto fail;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008728 }
8729
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02008730 keys_ref = tlskeys_ref_lookup(args[cur_arg + 1]);
Willy Tarreau17b4aa12018-07-17 10:05:32 +02008731 if (keys_ref) {
8732 keys_ref->refcount++;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02008733 conf->keys_ref = keys_ref;
8734 return 0;
8735 }
8736
Christopher Faulete566f3d2019-10-21 09:55:49 +02008737 keys_ref = calloc(1, sizeof(*keys_ref));
Emeric Brun09852f72019-01-10 10:51:13 +01008738 if (!keys_ref) {
8739 if (err)
8740 memprintf(err, "'%s' : allocation error", args[cur_arg+1]);
Christopher Faulete566f3d2019-10-21 09:55:49 +02008741 goto fail;
Emeric Brun09852f72019-01-10 10:51:13 +01008742 }
8743
Emeric Brun9e754772019-01-10 17:51:55 +01008744 keys_ref->tlskeys = malloc(TLS_TICKETS_NO * sizeof(union tls_sess_key));
Emeric Brun09852f72019-01-10 10:51:13 +01008745 if (!keys_ref->tlskeys) {
Emeric Brun09852f72019-01-10 10:51:13 +01008746 if (err)
8747 memprintf(err, "'%s' : allocation error", args[cur_arg+1]);
Christopher Faulete566f3d2019-10-21 09:55:49 +02008748 goto fail;
Emeric Brun09852f72019-01-10 10:51:13 +01008749 }
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008750
8751 if ((f = fopen(args[cur_arg + 1], "r")) == NULL) {
8752 if (err)
8753 memprintf(err, "'%s' : unable to load ssl tickets keys file", args[cur_arg+1]);
Christopher Faulete566f3d2019-10-21 09:55:49 +02008754 goto fail;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008755 }
8756
Nenad Merdanovic146defa2015-05-09 08:46:00 +02008757 keys_ref->filename = strdup(args[cur_arg + 1]);
Emeric Brun09852f72019-01-10 10:51:13 +01008758 if (!keys_ref->filename) {
Emeric Brun09852f72019-01-10 10:51:13 +01008759 if (err)
8760 memprintf(err, "'%s' : allocation error", args[cur_arg+1]);
Christopher Faulete566f3d2019-10-21 09:55:49 +02008761 goto fail;
Emeric Brun09852f72019-01-10 10:51:13 +01008762 }
Nenad Merdanovic146defa2015-05-09 08:46:00 +02008763
Emeric Brun9e754772019-01-10 17:51:55 +01008764 keys_ref->key_size_bits = 0;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008765 while (fgets(thisline, sizeof(thisline), f) != NULL) {
8766 int len = strlen(thisline);
Emeric Brun9e754772019-01-10 17:51:55 +01008767 int dec_size;
8768
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008769 /* Strip newline characters from the end */
8770 if(thisline[len - 1] == '\n')
8771 thisline[--len] = 0;
8772
8773 if(thisline[len - 1] == '\r')
8774 thisline[--len] = 0;
8775
Emeric Brun9e754772019-01-10 17:51:55 +01008776 dec_size = base64dec(thisline, len, (char *) (keys_ref->tlskeys + i % TLS_TICKETS_NO), sizeof(union tls_sess_key));
8777 if (dec_size < 0) {
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008778 if (err)
8779 memprintf(err, "'%s' : unable to decode base64 key on line %d", args[cur_arg+1], i + 1);
Christopher Faulete566f3d2019-10-21 09:55:49 +02008780 goto fail;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008781 }
Emeric Brun9e754772019-01-10 17:51:55 +01008782 else if (!keys_ref->key_size_bits && (dec_size == sizeof(struct tls_sess_key_128))) {
8783 keys_ref->key_size_bits = 128;
8784 }
8785 else if (!keys_ref->key_size_bits && (dec_size == sizeof(struct tls_sess_key_256))) {
8786 keys_ref->key_size_bits = 256;
8787 }
8788 else if (((dec_size != sizeof(struct tls_sess_key_128)) && (dec_size != sizeof(struct tls_sess_key_256)))
8789 || ((dec_size == sizeof(struct tls_sess_key_128) && (keys_ref->key_size_bits != 128)))
8790 || ((dec_size == sizeof(struct tls_sess_key_256) && (keys_ref->key_size_bits != 256)))) {
Emeric Brun9e754772019-01-10 17:51:55 +01008791 if (err)
8792 memprintf(err, "'%s' : wrong sized key on line %d", args[cur_arg+1], i + 1);
Christopher Faulete566f3d2019-10-21 09:55:49 +02008793 goto fail;
Emeric Brun9e754772019-01-10 17:51:55 +01008794 }
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008795 i++;
8796 }
8797
8798 if (i < TLS_TICKETS_NO) {
8799 if (err)
8800 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 +02008801 goto fail;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008802 }
8803
8804 fclose(f);
8805
8806 /* Use penultimate key for encryption, handle when TLS_TICKETS_NO = 1 */
Nenad Merdanovic17891152016-03-25 22:16:57 +01008807 i -= 2;
8808 keys_ref->tls_ticket_enc_index = i < 0 ? 0 : i % TLS_TICKETS_NO;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02008809 keys_ref->unique_id = -1;
Willy Tarreau17b4aa12018-07-17 10:05:32 +02008810 keys_ref->refcount = 1;
Christopher Faulet16f45c82018-02-16 11:23:49 +01008811 HA_RWLOCK_INIT(&keys_ref->lock);
Nenad Merdanovic146defa2015-05-09 08:46:00 +02008812 conf->keys_ref = keys_ref;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008813
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02008814 LIST_ADD(&tlskeys_reference, &keys_ref->list);
8815
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008816 return 0;
Christopher Faulete566f3d2019-10-21 09:55:49 +02008817
8818 fail:
8819 if (f)
8820 fclose(f);
8821 if (keys_ref) {
8822 free(keys_ref->filename);
8823 free(keys_ref->tlskeys);
8824 free(keys_ref);
8825 }
8826 return ERR_ALERT | ERR_FATAL;
8827
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008828#else
8829 if (err)
8830 memprintf(err, "'%s' : TLS ticket callback extension not supported", args[cur_arg]);
8831 return ERR_ALERT | ERR_FATAL;
8832#endif /* SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB */
Emmanuel Hocdet65623372013-01-24 17:17:15 +01008833}
8834
Emeric Brund94b3fe2012-09-20 18:23:56 +02008835/* parse the "verify" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008836static 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 +02008837{
8838 if (!*args[cur_arg + 1]) {
8839 if (err)
8840 memprintf(err, "'%s' : missing verify method", args[cur_arg]);
8841 return ERR_ALERT | ERR_FATAL;
8842 }
8843
8844 if (strcmp(args[cur_arg + 1], "none") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01008845 conf->verify = SSL_SOCK_VERIFY_NONE;
Emeric Brund94b3fe2012-09-20 18:23:56 +02008846 else if (strcmp(args[cur_arg + 1], "optional") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01008847 conf->verify = SSL_SOCK_VERIFY_OPTIONAL;
Emeric Brund94b3fe2012-09-20 18:23:56 +02008848 else if (strcmp(args[cur_arg + 1], "required") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01008849 conf->verify = SSL_SOCK_VERIFY_REQUIRED;
Emeric Brund94b3fe2012-09-20 18:23:56 +02008850 else {
8851 if (err)
8852 memprintf(err, "'%s' : unknown verify method '%s', only 'none', 'optional', and 'required' are supported\n",
8853 args[cur_arg], args[cur_arg + 1]);
8854 return ERR_ALERT | ERR_FATAL;
8855 }
8856
8857 return 0;
8858}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008859static int bind_parse_verify(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8860{
8861 return ssl_bind_parse_verify(args, cur_arg, px, &conf->ssl_conf, err);
8862}
Emeric Brund94b3fe2012-09-20 18:23:56 +02008863
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02008864/* parse the "no-ca-names" bind keyword */
8865static int ssl_bind_parse_no_ca_names(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
8866{
8867 conf->no_ca_names = 1;
8868 return 0;
8869}
8870static int bind_parse_no_ca_names(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8871{
8872 return ssl_bind_parse_no_ca_names(args, cur_arg, px, &conf->ssl_conf, err);
8873}
8874
Willy Tarreau92faadf2012-10-10 23:04:25 +02008875/************** "server" keywords ****************/
8876
Olivier Houchardc7566002018-11-20 23:33:50 +01008877/* parse the "npn" bind keyword */
8878static int srv_parse_npn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8879{
8880#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
8881 char *p1, *p2;
8882
8883 if (!*args[*cur_arg + 1]) {
8884 memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[*cur_arg]);
8885 return ERR_ALERT | ERR_FATAL;
8886 }
8887
8888 free(newsrv->ssl_ctx.npn_str);
8889
8890 /* the NPN string is built as a suite of (<len> <name>)*,
8891 * so we reuse each comma to store the next <len> and need
8892 * one more for the end of the string.
8893 */
8894 newsrv->ssl_ctx.npn_len = strlen(args[*cur_arg + 1]) + 1;
8895 newsrv->ssl_ctx.npn_str = calloc(1, newsrv->ssl_ctx.npn_len + 1);
8896 memcpy(newsrv->ssl_ctx.npn_str + 1, args[*cur_arg + 1],
8897 newsrv->ssl_ctx.npn_len);
8898
8899 /* replace commas with the name length */
8900 p1 = newsrv->ssl_ctx.npn_str;
8901 p2 = p1 + 1;
8902 while (1) {
8903 p2 = memchr(p1 + 1, ',', newsrv->ssl_ctx.npn_str +
8904 newsrv->ssl_ctx.npn_len - (p1 + 1));
8905 if (!p2)
8906 p2 = p1 + 1 + strlen(p1 + 1);
8907
8908 if (p2 - (p1 + 1) > 255) {
8909 *p2 = '\0';
8910 memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[*cur_arg], p1 + 1);
8911 return ERR_ALERT | ERR_FATAL;
8912 }
8913
8914 *p1 = p2 - (p1 + 1);
8915 p1 = p2;
8916
8917 if (!*p2)
8918 break;
8919
8920 *(p2++) = '\0';
8921 }
8922 return 0;
8923#else
8924 if (err)
8925 memprintf(err, "'%s' : library does not support TLS NPN extension", args[*cur_arg]);
8926 return ERR_ALERT | ERR_FATAL;
8927#endif
8928}
8929
Olivier Houchard92150142018-12-21 19:47:01 +01008930/* parse the "alpn" or the "check-alpn" server keyword */
Olivier Houchardc7566002018-11-20 23:33:50 +01008931static int srv_parse_alpn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8932{
8933#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
8934 char *p1, *p2;
Olivier Houchard92150142018-12-21 19:47:01 +01008935 char **alpn_str;
8936 int *alpn_len;
Olivier Houchardc7566002018-11-20 23:33:50 +01008937
Olivier Houchard92150142018-12-21 19:47:01 +01008938 if (*args[*cur_arg] == 'c') {
8939 alpn_str = &newsrv->check.alpn_str;
8940 alpn_len = &newsrv->check.alpn_len;
8941 } else {
8942 alpn_str = &newsrv->ssl_ctx.alpn_str;
8943 alpn_len = &newsrv->ssl_ctx.alpn_len;
8944
8945 }
Olivier Houchardc7566002018-11-20 23:33:50 +01008946 if (!*args[*cur_arg + 1]) {
8947 memprintf(err, "'%s' : missing the comma-delimited ALPN protocol suite", args[*cur_arg]);
8948 return ERR_ALERT | ERR_FATAL;
8949 }
8950
Olivier Houchard92150142018-12-21 19:47:01 +01008951 free(*alpn_str);
Olivier Houchardc7566002018-11-20 23:33:50 +01008952
8953 /* the ALPN string is built as a suite of (<len> <name>)*,
8954 * so we reuse each comma to store the next <len> and need
8955 * one more for the end of the string.
8956 */
Olivier Houchard92150142018-12-21 19:47:01 +01008957 *alpn_len = strlen(args[*cur_arg + 1]) + 1;
8958 *alpn_str = calloc(1, *alpn_len + 1);
8959 memcpy(*alpn_str + 1, args[*cur_arg + 1], *alpn_len);
Olivier Houchardc7566002018-11-20 23:33:50 +01008960
8961 /* replace commas with the name length */
Olivier Houchard92150142018-12-21 19:47:01 +01008962 p1 = *alpn_str;
Olivier Houchardc7566002018-11-20 23:33:50 +01008963 p2 = p1 + 1;
8964 while (1) {
Olivier Houchard92150142018-12-21 19:47:01 +01008965 p2 = memchr(p1 + 1, ',', *alpn_str + *alpn_len - (p1 + 1));
Olivier Houchardc7566002018-11-20 23:33:50 +01008966 if (!p2)
8967 p2 = p1 + 1 + strlen(p1 + 1);
8968
8969 if (p2 - (p1 + 1) > 255) {
8970 *p2 = '\0';
8971 memprintf(err, "'%s' : ALPN protocol name too long : '%s'", args[*cur_arg], p1 + 1);
8972 return ERR_ALERT | ERR_FATAL;
8973 }
8974
8975 *p1 = p2 - (p1 + 1);
8976 p1 = p2;
8977
8978 if (!*p2)
8979 break;
8980
8981 *(p2++) = '\0';
8982 }
8983 return 0;
8984#else
8985 if (err)
8986 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[*cur_arg]);
8987 return ERR_ALERT | ERR_FATAL;
8988#endif
8989}
8990
Emeric Brunef42d922012-10-11 16:11:36 +02008991/* parse the "ca-file" server keyword */
8992static int srv_parse_ca_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8993{
8994 if (!*args[*cur_arg + 1]) {
8995 if (err)
8996 memprintf(err, "'%s' : missing CAfile 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.ca_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.ca_file, "%s", args[*cur_arg + 1]);
9004
9005 return 0;
9006}
9007
Olivier Houchard9130a962017-10-17 17:33:43 +02009008/* parse the "check-sni" server keyword */
9009static int srv_parse_check_sni(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9010{
9011 if (!*args[*cur_arg + 1]) {
9012 if (err)
9013 memprintf(err, "'%s' : missing SNI", args[*cur_arg]);
9014 return ERR_ALERT | ERR_FATAL;
9015 }
9016
9017 newsrv->check.sni = strdup(args[*cur_arg + 1]);
9018 if (!newsrv->check.sni) {
9019 memprintf(err, "'%s' : failed to allocate memory", args[*cur_arg]);
9020 return ERR_ALERT | ERR_FATAL;
9021 }
9022 return 0;
9023
9024}
9025
Willy Tarreau92faadf2012-10-10 23:04:25 +02009026/* parse the "check-ssl" server keyword */
9027static int srv_parse_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9028{
9029 newsrv->check.use_ssl = 1;
Willy Tarreauef934602016-12-22 23:12:01 +01009030 if (global_ssl.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
9031 newsrv->ssl_ctx.ciphers = strdup(global_ssl.connect_default_ciphers);
Emmanuel Hocdet839af572019-05-14 16:27:35 +02009032#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009033 if (global_ssl.connect_default_ciphersuites && !newsrv->ssl_ctx.ciphersuites)
9034 newsrv->ssl_ctx.ciphersuites = strdup(global_ssl.connect_default_ciphersuites);
9035#endif
Willy Tarreauef934602016-12-22 23:12:01 +01009036 newsrv->ssl_ctx.options |= global_ssl.connect_default_ssloptions;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02009037 newsrv->ssl_ctx.methods.flags |= global_ssl.connect_default_sslmethods.flags;
9038 if (!newsrv->ssl_ctx.methods.min)
9039 newsrv->ssl_ctx.methods.min = global_ssl.connect_default_sslmethods.min;
9040 if (!newsrv->ssl_ctx.methods.max)
9041 newsrv->ssl_ctx.methods.max = global_ssl.connect_default_sslmethods.max;
9042
Willy Tarreau92faadf2012-10-10 23:04:25 +02009043 return 0;
9044}
9045
9046/* parse the "ciphers" server keyword */
9047static int srv_parse_ciphers(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9048{
9049 if (!*args[*cur_arg + 1]) {
9050 memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
9051 return ERR_ALERT | ERR_FATAL;
9052 }
9053
9054 free(newsrv->ssl_ctx.ciphers);
9055 newsrv->ssl_ctx.ciphers = strdup(args[*cur_arg + 1]);
9056 return 0;
9057}
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009058
Emmanuel Hocdet839af572019-05-14 16:27:35 +02009059#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009060/* parse the "ciphersuites" server keyword */
9061static int srv_parse_ciphersuites(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9062{
9063 if (!*args[*cur_arg + 1]) {
9064 memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
9065 return ERR_ALERT | ERR_FATAL;
9066 }
9067
9068 free(newsrv->ssl_ctx.ciphersuites);
9069 newsrv->ssl_ctx.ciphersuites = strdup(args[*cur_arg + 1]);
9070 return 0;
9071}
9072#endif
Willy Tarreau92faadf2012-10-10 23:04:25 +02009073
Emeric Brunef42d922012-10-11 16:11:36 +02009074/* parse the "crl-file" server keyword */
9075static int srv_parse_crl_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9076{
9077#ifndef X509_V_FLAG_CRL_CHECK
9078 if (err)
9079 memprintf(err, "'%s' : library does not support CRL verify", args[*cur_arg]);
9080 return ERR_ALERT | ERR_FATAL;
9081#else
9082 if (!*args[*cur_arg + 1]) {
9083 if (err)
9084 memprintf(err, "'%s' : missing CRLfile path", args[*cur_arg]);
9085 return ERR_ALERT | ERR_FATAL;
9086 }
9087
Willy Tarreauef934602016-12-22 23:12:01 +01009088 if ((*args[*cur_arg + 1] != '/') && global_ssl.ca_base)
9089 memprintf(&newsrv->ssl_ctx.crl_file, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02009090 else
9091 memprintf(&newsrv->ssl_ctx.crl_file, "%s", args[*cur_arg + 1]);
9092
9093 return 0;
9094#endif
9095}
9096
Emeric Bruna7aa3092012-10-26 12:58:00 +02009097/* parse the "crt" server keyword */
9098static int srv_parse_crt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9099{
9100 if (!*args[*cur_arg + 1]) {
9101 if (err)
9102 memprintf(err, "'%s' : missing certificate file path", args[*cur_arg]);
9103 return ERR_ALERT | ERR_FATAL;
9104 }
9105
Willy Tarreauef934602016-12-22 23:12:01 +01009106 if ((*args[*cur_arg + 1] != '/') && global_ssl.crt_base)
Christopher Fauletff3a41e2017-11-23 09:13:32 +01009107 memprintf(&newsrv->ssl_ctx.client_crt, "%s/%s", global_ssl.crt_base, args[*cur_arg + 1]);
Emeric Bruna7aa3092012-10-26 12:58:00 +02009108 else
9109 memprintf(&newsrv->ssl_ctx.client_crt, "%s", args[*cur_arg + 1]);
9110
9111 return 0;
9112}
Emeric Brunef42d922012-10-11 16:11:36 +02009113
Frédéric Lécaille340ae602017-03-13 10:38:04 +01009114/* parse the "no-check-ssl" server keyword */
9115static int srv_parse_no_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9116{
9117 newsrv->check.use_ssl = 0;
9118 free(newsrv->ssl_ctx.ciphers);
9119 newsrv->ssl_ctx.ciphers = NULL;
9120 newsrv->ssl_ctx.options &= ~global_ssl.connect_default_ssloptions;
9121 return 0;
9122}
9123
Frédéric Lécaillee892c4c2017-03-13 12:08:01 +01009124/* parse the "no-send-proxy-v2-ssl" server keyword */
9125static int srv_parse_no_send_proxy_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9126{
9127 newsrv->pp_opts &= ~SRV_PP_V2;
9128 newsrv->pp_opts &= ~SRV_PP_V2_SSL;
9129 return 0;
9130}
9131
9132/* parse the "no-send-proxy-v2-ssl-cn" server keyword */
9133static int srv_parse_no_send_proxy_cn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9134{
9135 newsrv->pp_opts &= ~SRV_PP_V2;
9136 newsrv->pp_opts &= ~SRV_PP_V2_SSL;
9137 newsrv->pp_opts &= ~SRV_PP_V2_SSL_CN;
9138 return 0;
9139}
9140
Frédéric Lécaillee381d762017-03-13 11:54:17 +01009141/* parse the "no-ssl" server keyword */
9142static int srv_parse_no_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9143{
9144 newsrv->use_ssl = 0;
9145 free(newsrv->ssl_ctx.ciphers);
9146 newsrv->ssl_ctx.ciphers = NULL;
9147 return 0;
9148}
9149
Olivier Houchard522eea72017-11-03 16:27:47 +01009150/* parse the "allow-0rtt" server keyword */
9151static int srv_parse_allow_0rtt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9152{
9153 newsrv->ssl_ctx.options |= SRV_SSL_O_EARLY_DATA;
9154 return 0;
9155}
9156
Willy Tarreau2a3fb1c2015-02-05 16:47:07 +01009157/* parse the "no-ssl-reuse" server keyword */
9158static int srv_parse_no_ssl_reuse(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9159{
9160 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_REUSE;
9161 return 0;
9162}
9163
Emeric Brunf9c5c472012-10-11 15:28:34 +02009164/* parse the "no-tls-tickets" server keyword */
9165static int srv_parse_no_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9166{
9167 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLS_TICKETS;
9168 return 0;
9169}
David Safb76832014-05-08 23:42:08 -04009170/* parse the "send-proxy-v2-ssl" server keyword */
9171static int srv_parse_send_proxy_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9172{
9173 newsrv->pp_opts |= SRV_PP_V2;
9174 newsrv->pp_opts |= SRV_PP_V2_SSL;
9175 return 0;
9176}
9177
9178/* parse the "send-proxy-v2-ssl-cn" server keyword */
9179static int srv_parse_send_proxy_cn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9180{
9181 newsrv->pp_opts |= SRV_PP_V2;
9182 newsrv->pp_opts |= SRV_PP_V2_SSL;
9183 newsrv->pp_opts |= SRV_PP_V2_SSL_CN;
9184 return 0;
9185}
Emeric Brunf9c5c472012-10-11 15:28:34 +02009186
Willy Tarreau732eac42015-07-09 11:40:25 +02009187/* parse the "sni" server keyword */
9188static int srv_parse_sni(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9189{
9190#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
9191 memprintf(err, "'%s' : the current SSL library doesn't support the SNI TLS extension", args[*cur_arg]);
9192 return ERR_ALERT | ERR_FATAL;
9193#else
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01009194 char *arg;
Willy Tarreau732eac42015-07-09 11:40:25 +02009195
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01009196 arg = args[*cur_arg + 1];
9197 if (!*arg) {
Willy Tarreau732eac42015-07-09 11:40:25 +02009198 memprintf(err, "'%s' : missing sni expression", args[*cur_arg]);
9199 return ERR_ALERT | ERR_FATAL;
9200 }
9201
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01009202 free(newsrv->sni_expr);
9203 newsrv->sni_expr = strdup(arg);
Willy Tarreau732eac42015-07-09 11:40:25 +02009204
Willy Tarreau732eac42015-07-09 11:40:25 +02009205 return 0;
9206#endif
9207}
9208
Willy Tarreau92faadf2012-10-10 23:04:25 +02009209/* parse the "ssl" server keyword */
9210static int srv_parse_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9211{
9212 newsrv->use_ssl = 1;
Willy Tarreauef934602016-12-22 23:12:01 +01009213 if (global_ssl.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
9214 newsrv->ssl_ctx.ciphers = strdup(global_ssl.connect_default_ciphers);
Emmanuel Hocdet839af572019-05-14 16:27:35 +02009215#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009216 if (global_ssl.connect_default_ciphersuites && !newsrv->ssl_ctx.ciphersuites)
9217 newsrv->ssl_ctx.ciphersuites = strdup(global_ssl.connect_default_ciphersuites);
9218#endif
Willy Tarreau92faadf2012-10-10 23:04:25 +02009219 return 0;
9220}
9221
Frédéric Lécaille2cfcdbe2017-03-13 11:32:20 +01009222/* parse the "ssl-reuse" server keyword */
9223static int srv_parse_ssl_reuse(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9224{
9225 newsrv->ssl_ctx.options &= ~SRV_SSL_O_NO_REUSE;
9226 return 0;
9227}
9228
Frédéric Lécaille2cfcdbe2017-03-13 11:32:20 +01009229/* parse the "tls-tickets" server keyword */
9230static int srv_parse_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9231{
9232 newsrv->ssl_ctx.options &= ~SRV_SSL_O_NO_TLS_TICKETS;
9233 return 0;
9234}
9235
Emeric Brunef42d922012-10-11 16:11:36 +02009236/* parse the "verify" server keyword */
9237static int srv_parse_verify(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9238{
9239 if (!*args[*cur_arg + 1]) {
9240 if (err)
9241 memprintf(err, "'%s' : missing verify method", args[*cur_arg]);
9242 return ERR_ALERT | ERR_FATAL;
9243 }
9244
9245 if (strcmp(args[*cur_arg + 1], "none") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01009246 newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_NONE;
Emeric Brunef42d922012-10-11 16:11:36 +02009247 else if (strcmp(args[*cur_arg + 1], "required") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01009248 newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_REQUIRED;
Emeric Brunef42d922012-10-11 16:11:36 +02009249 else {
9250 if (err)
9251 memprintf(err, "'%s' : unknown verify method '%s', only 'none' and 'required' are supported\n",
9252 args[*cur_arg], args[*cur_arg + 1]);
9253 return ERR_ALERT | ERR_FATAL;
9254 }
9255
Evan Broderbe554312013-06-27 00:05:25 -07009256 return 0;
9257}
9258
9259/* parse the "verifyhost" server keyword */
9260static int srv_parse_verifyhost(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9261{
9262 if (!*args[*cur_arg + 1]) {
9263 if (err)
9264 memprintf(err, "'%s' : missing hostname to verify against", args[*cur_arg]);
9265 return ERR_ALERT | ERR_FATAL;
9266 }
9267
Frédéric Lécaille273f3212017-03-13 15:52:01 +01009268 free(newsrv->ssl_ctx.verify_host);
Evan Broderbe554312013-06-27 00:05:25 -07009269 newsrv->ssl_ctx.verify_host = strdup(args[*cur_arg + 1]);
9270
Emeric Brunef42d922012-10-11 16:11:36 +02009271 return 0;
9272}
9273
Emeric Brun2c86cbf2014-10-30 15:56:50 +01009274/* parse the "ssl-default-bind-options" keyword in global section */
9275static int ssl_parse_default_bind_options(char **args, int section_type, struct proxy *curpx,
9276 struct proxy *defpx, const char *file, int line,
9277 char **err) {
9278 int i = 1;
9279
9280 if (*(args[i]) == 0) {
9281 memprintf(err, "global statement '%s' expects an option as an argument.", args[0]);
9282 return -1;
9283 }
9284 while (*(args[i])) {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02009285 if (!strcmp(args[i], "no-tls-tickets"))
Willy Tarreauef934602016-12-22 23:12:01 +01009286 global_ssl.listen_default_ssloptions |= BC_SSL_O_NO_TLS_TICKETS;
Lukas Tribus53ae85c2017-05-04 15:45:40 +00009287 else if (!strcmp(args[i], "prefer-client-ciphers"))
9288 global_ssl.listen_default_ssloptions |= BC_SSL_O_PREF_CLIE_CIPH;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02009289 else if (!strcmp(args[i], "ssl-min-ver") || !strcmp(args[i], "ssl-max-ver")) {
9290 if (!parse_tls_method_minmax(args, i, &global_ssl.listen_default_sslmethods, err))
9291 i++;
9292 else {
9293 memprintf(err, "%s on global statement '%s'.", *err, args[0]);
9294 return -1;
9295 }
9296 }
9297 else if (parse_tls_method_options(args[i], &global_ssl.listen_default_sslmethods, err)) {
Emeric Brun2c86cbf2014-10-30 15:56:50 +01009298 memprintf(err, "unknown option '%s' on global statement '%s'.", args[i], args[0]);
9299 return -1;
9300 }
9301 i++;
9302 }
9303 return 0;
9304}
9305
9306/* parse the "ssl-default-server-options" keyword in global section */
9307static int ssl_parse_default_server_options(char **args, int section_type, struct proxy *curpx,
9308 struct proxy *defpx, const char *file, int line,
9309 char **err) {
9310 int i = 1;
9311
9312 if (*(args[i]) == 0) {
9313 memprintf(err, "global statement '%s' expects an option as an argument.", args[0]);
9314 return -1;
9315 }
9316 while (*(args[i])) {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02009317 if (!strcmp(args[i], "no-tls-tickets"))
Willy Tarreauef934602016-12-22 23:12:01 +01009318 global_ssl.connect_default_ssloptions |= SRV_SSL_O_NO_TLS_TICKETS;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02009319 else if (!strcmp(args[i], "ssl-min-ver") || !strcmp(args[i], "ssl-max-ver")) {
9320 if (!parse_tls_method_minmax(args, i, &global_ssl.connect_default_sslmethods, err))
9321 i++;
9322 else {
9323 memprintf(err, "%s on global statement '%s'.", *err, args[0]);
9324 return -1;
9325 }
9326 }
9327 else if (parse_tls_method_options(args[i], &global_ssl.connect_default_sslmethods, err)) {
Emeric Brun2c86cbf2014-10-30 15:56:50 +01009328 memprintf(err, "unknown option '%s' on global statement '%s'.", args[i], args[0]);
9329 return -1;
9330 }
9331 i++;
9332 }
9333 return 0;
9334}
9335
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01009336/* parse the "ca-base" / "crt-base" keywords in global section.
9337 * Returns <0 on alert, >0 on warning, 0 on success.
9338 */
9339static int ssl_parse_global_ca_crt_base(char **args, int section_type, struct proxy *curpx,
9340 struct proxy *defpx, const char *file, int line,
9341 char **err)
9342{
9343 char **target;
9344
Willy Tarreauef934602016-12-22 23:12:01 +01009345 target = (args[0][1] == 'a') ? &global_ssl.ca_base : &global_ssl.crt_base;
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01009346
9347 if (too_many_args(1, args, err, NULL))
9348 return -1;
9349
9350 if (*target) {
9351 memprintf(err, "'%s' already specified.", args[0]);
9352 return -1;
9353 }
9354
9355 if (*(args[1]) == 0) {
9356 memprintf(err, "global statement '%s' expects a directory path as an argument.", args[0]);
9357 return -1;
9358 }
9359 *target = strdup(args[1]);
9360 return 0;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00009361}
9362
9363/* parse the "ssl-mode-async" keyword in global section.
9364 * Returns <0 on alert, >0 on warning, 0 on success.
9365 */
9366static int ssl_parse_global_ssl_async(char **args, int section_type, struct proxy *curpx,
9367 struct proxy *defpx, const char *file, int line,
9368 char **err)
9369{
Willy Tarreau5db847a2019-05-09 14:13:35 +02009370#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00009371 global_ssl.async = 1;
Emeric Brunece0c332017-12-06 13:51:49 +01009372 global.ssl_used_async_engines = nb_engines;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00009373 return 0;
9374#else
9375 memprintf(err, "'%s': openssl library does not support async mode", args[0]);
9376 return -1;
9377#endif
9378}
9379
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02009380#ifndef OPENSSL_NO_ENGINE
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00009381static int ssl_check_async_engine_count(void) {
9382 int err_code = 0;
9383
Emeric Brun3854e012017-05-17 20:42:48 +02009384 if (global_ssl.async && (openssl_engines_initialized > 32)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01009385 ha_alert("ssl-mode-async only supports a maximum of 32 engines.\n");
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00009386 err_code = ERR_ABORT;
9387 }
9388 return err_code;
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01009389}
9390
Grant Zhang872f9c22017-01-21 01:10:18 +00009391/* parse the "ssl-engine" keyword in global section.
9392 * Returns <0 on alert, >0 on warning, 0 on success.
9393 */
9394static int ssl_parse_global_ssl_engine(char **args, int section_type, struct proxy *curpx,
9395 struct proxy *defpx, const char *file, int line,
9396 char **err)
9397{
9398 char *algo;
9399 int ret = -1;
9400
9401 if (*(args[1]) == 0) {
9402 memprintf(err, "global statement '%s' expects a valid engine name as an argument.", args[0]);
9403 return ret;
9404 }
9405
9406 if (*(args[2]) == 0) {
9407 /* if no list of algorithms is given, it defaults to ALL */
9408 algo = strdup("ALL");
9409 goto add_engine;
9410 }
9411
9412 /* otherwise the expected format is ssl-engine <engine_name> algo <list of algo> */
9413 if (strcmp(args[2], "algo") != 0) {
9414 memprintf(err, "global statement '%s' expects to have algo keyword.", args[0]);
9415 return ret;
9416 }
9417
9418 if (*(args[3]) == 0) {
9419 memprintf(err, "global statement '%s' expects algorithm names as an argument.", args[0]);
9420 return ret;
9421 }
9422 algo = strdup(args[3]);
9423
9424add_engine:
9425 if (ssl_init_single_engine(args[1], algo)==0) {
9426 openssl_engines_initialized++;
9427 ret = 0;
9428 }
9429 free(algo);
9430 return ret;
9431}
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02009432#endif
Grant Zhang872f9c22017-01-21 01:10:18 +00009433
Willy Tarreauf22e9682016-12-21 23:23:19 +01009434/* parse the "ssl-default-bind-ciphers" / "ssl-default-server-ciphers" keywords
9435 * in global section. Returns <0 on alert, >0 on warning, 0 on success.
9436 */
9437static int ssl_parse_global_ciphers(char **args, int section_type, struct proxy *curpx,
9438 struct proxy *defpx, const char *file, int line,
9439 char **err)
9440{
9441 char **target;
9442
Willy Tarreauef934602016-12-22 23:12:01 +01009443 target = (args[0][12] == 'b') ? &global_ssl.listen_default_ciphers : &global_ssl.connect_default_ciphers;
Willy Tarreauf22e9682016-12-21 23:23:19 +01009444
9445 if (too_many_args(1, args, err, NULL))
9446 return -1;
9447
9448 if (*(args[1]) == 0) {
9449 memprintf(err, "global statement '%s' expects a cipher suite as an argument.", args[0]);
9450 return -1;
9451 }
9452
9453 free(*target);
9454 *target = strdup(args[1]);
9455 return 0;
9456}
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009457
Emmanuel Hocdet839af572019-05-14 16:27:35 +02009458#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009459/* parse the "ssl-default-bind-ciphersuites" / "ssl-default-server-ciphersuites" keywords
9460 * in global section. Returns <0 on alert, >0 on warning, 0 on success.
9461 */
9462static int ssl_parse_global_ciphersuites(char **args, int section_type, struct proxy *curpx,
9463 struct proxy *defpx, const char *file, int line,
9464 char **err)
9465{
9466 char **target;
9467
9468 target = (args[0][12] == 'b') ? &global_ssl.listen_default_ciphersuites : &global_ssl.connect_default_ciphersuites;
9469
9470 if (too_many_args(1, args, err, NULL))
9471 return -1;
9472
9473 if (*(args[1]) == 0) {
9474 memprintf(err, "global statement '%s' expects a cipher suite as an argument.", args[0]);
9475 return -1;
9476 }
9477
9478 free(*target);
9479 *target = strdup(args[1]);
9480 return 0;
9481}
9482#endif
Willy Tarreauf22e9682016-12-21 23:23:19 +01009483
Willy Tarreau9ceda382016-12-21 23:13:03 +01009484/* parse various global tune.ssl settings consisting in positive integers.
9485 * Returns <0 on alert, >0 on warning, 0 on success.
9486 */
9487static int ssl_parse_global_int(char **args, int section_type, struct proxy *curpx,
9488 struct proxy *defpx, const char *file, int line,
9489 char **err)
9490{
9491 int *target;
9492
9493 if (strcmp(args[0], "tune.ssl.cachesize") == 0)
9494 target = &global.tune.sslcachesize;
9495 else if (strcmp(args[0], "tune.ssl.maxrecord") == 0)
Willy Tarreauef934602016-12-22 23:12:01 +01009496 target = (int *)&global_ssl.max_record;
Willy Tarreau9ceda382016-12-21 23:13:03 +01009497 else if (strcmp(args[0], "tune.ssl.ssl-ctx-cache-size") == 0)
Willy Tarreauef934602016-12-22 23:12:01 +01009498 target = &global_ssl.ctx_cache;
Willy Tarreau0bea58d2016-12-21 23:17:25 +01009499 else if (strcmp(args[0], "maxsslconn") == 0)
9500 target = &global.maxsslconn;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01009501 else if (strcmp(args[0], "tune.ssl.capture-cipherlist-size") == 0)
9502 target = &global_ssl.capture_cipherlist;
Willy Tarreau9ceda382016-12-21 23:13:03 +01009503 else {
9504 memprintf(err, "'%s' keyword not unhandled (please report this bug).", args[0]);
9505 return -1;
9506 }
9507
9508 if (too_many_args(1, args, err, NULL))
9509 return -1;
9510
9511 if (*(args[1]) == 0) {
9512 memprintf(err, "'%s' expects an integer argument.", args[0]);
9513 return -1;
9514 }
9515
9516 *target = atoi(args[1]);
9517 if (*target < 0) {
9518 memprintf(err, "'%s' expects a positive numeric value.", args[0]);
9519 return -1;
9520 }
9521 return 0;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01009522}
9523
9524static int ssl_parse_global_capture_cipherlist(char **args, int section_type, struct proxy *curpx,
9525 struct proxy *defpx, const char *file, int line,
9526 char **err)
9527{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01009528 int ret;
9529
9530 ret = ssl_parse_global_int(args, section_type, curpx, defpx, file, line, err);
9531 if (ret != 0)
9532 return ret;
9533
Willy Tarreaubafbe012017-11-24 17:34:44 +01009534 if (pool_head_ssl_capture) {
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01009535 memprintf(err, "'%s' is already configured.", args[0]);
9536 return -1;
9537 }
9538
Willy Tarreaubafbe012017-11-24 17:34:44 +01009539 pool_head_ssl_capture = create_pool("ssl-capture", sizeof(struct ssl_capture) + global_ssl.capture_cipherlist, MEM_F_SHARED);
9540 if (!pool_head_ssl_capture) {
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01009541 memprintf(err, "Out of memory error.");
9542 return -1;
9543 }
9544 return 0;
Willy Tarreau9ceda382016-12-21 23:13:03 +01009545}
9546
9547/* parse "ssl.force-private-cache".
9548 * Returns <0 on alert, >0 on warning, 0 on success.
9549 */
9550static int ssl_parse_global_private_cache(char **args, int section_type, struct proxy *curpx,
9551 struct proxy *defpx, const char *file, int line,
9552 char **err)
9553{
9554 if (too_many_args(0, args, err, NULL))
9555 return -1;
9556
Willy Tarreauef934602016-12-22 23:12:01 +01009557 global_ssl.private_cache = 1;
Willy Tarreau9ceda382016-12-21 23:13:03 +01009558 return 0;
9559}
9560
9561/* parse "ssl.lifetime".
9562 * Returns <0 on alert, >0 on warning, 0 on success.
9563 */
9564static int ssl_parse_global_lifetime(char **args, int section_type, struct proxy *curpx,
9565 struct proxy *defpx, const char *file, int line,
9566 char **err)
9567{
9568 const char *res;
9569
9570 if (too_many_args(1, args, err, NULL))
9571 return -1;
9572
9573 if (*(args[1]) == 0) {
9574 memprintf(err, "'%s' expects ssl sessions <lifetime> in seconds as argument.", args[0]);
9575 return -1;
9576 }
9577
Willy Tarreauef934602016-12-22 23:12:01 +01009578 res = parse_time_err(args[1], &global_ssl.life_time, TIME_UNIT_S);
Willy Tarreau9faebe32019-06-07 19:00:37 +02009579 if (res == PARSE_TIME_OVER) {
9580 memprintf(err, "timer overflow in argument '%s' to <%s> (maximum value is 2147483647 s or ~68 years).",
9581 args[1], args[0]);
9582 return -1;
9583 }
9584 else if (res == PARSE_TIME_UNDER) {
9585 memprintf(err, "timer underflow in argument '%s' to <%s> (minimum non-null value is 1 s).",
9586 args[1], args[0]);
9587 return -1;
9588 }
9589 else if (res) {
Willy Tarreau9ceda382016-12-21 23:13:03 +01009590 memprintf(err, "unexpected character '%c' in argument to <%s>.", *res, args[0]);
9591 return -1;
9592 }
9593 return 0;
9594}
9595
9596#ifndef OPENSSL_NO_DH
Willy Tarreau14e36a12016-12-21 23:28:13 +01009597/* parse "ssl-dh-param-file".
9598 * Returns <0 on alert, >0 on warning, 0 on success.
9599 */
9600static int ssl_parse_global_dh_param_file(char **args, int section_type, struct proxy *curpx,
9601 struct proxy *defpx, const char *file, int line,
9602 char **err)
9603{
9604 if (too_many_args(1, args, err, NULL))
9605 return -1;
9606
9607 if (*(args[1]) == 0) {
9608 memprintf(err, "'%s' expects a file path as an argument.", args[0]);
9609 return -1;
9610 }
9611
9612 if (ssl_sock_load_global_dh_param_from_file(args[1])) {
9613 memprintf(err, "'%s': unable to load DH parameters from file <%s>.", args[0], args[1]);
9614 return -1;
9615 }
9616 return 0;
9617}
9618
Willy Tarreau9ceda382016-12-21 23:13:03 +01009619/* parse "ssl.default-dh-param".
9620 * Returns <0 on alert, >0 on warning, 0 on success.
9621 */
9622static int ssl_parse_global_default_dh(char **args, int section_type, struct proxy *curpx,
9623 struct proxy *defpx, const char *file, int line,
9624 char **err)
9625{
9626 if (too_many_args(1, args, err, NULL))
9627 return -1;
9628
9629 if (*(args[1]) == 0) {
9630 memprintf(err, "'%s' expects an integer argument.", args[0]);
9631 return -1;
9632 }
9633
Willy Tarreauef934602016-12-22 23:12:01 +01009634 global_ssl.default_dh_param = atoi(args[1]);
9635 if (global_ssl.default_dh_param < 1024) {
Willy Tarreau9ceda382016-12-21 23:13:03 +01009636 memprintf(err, "'%s' expects a value >= 1024.", args[0]);
9637 return -1;
9638 }
9639 return 0;
9640}
9641#endif
9642
9643
William Lallemand32af2032016-10-29 18:09:35 +02009644/* This function is used with TLS ticket keys management. It permits to browse
9645 * each reference. The variable <getnext> must contain the current node,
9646 * <end> point to the root node.
9647 */
9648#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
9649static inline
9650struct tls_keys_ref *tlskeys_list_get_next(struct tls_keys_ref *getnext, struct list *end)
9651{
9652 struct tls_keys_ref *ref = getnext;
9653
9654 while (1) {
9655
9656 /* Get next list entry. */
9657 ref = LIST_NEXT(&ref->list, struct tls_keys_ref *, list);
9658
9659 /* If the entry is the last of the list, return NULL. */
9660 if (&ref->list == end)
9661 return NULL;
9662
9663 return ref;
9664 }
9665}
9666
9667static inline
9668struct tls_keys_ref *tlskeys_ref_lookup_ref(const char *reference)
9669{
9670 int id;
9671 char *error;
9672
9673 /* If the reference starts by a '#', this is numeric id. */
9674 if (reference[0] == '#') {
9675 /* Try to convert the numeric id. If the conversion fails, the lookup fails. */
9676 id = strtol(reference + 1, &error, 10);
9677 if (*error != '\0')
9678 return NULL;
9679
9680 /* Perform the unique id lookup. */
9681 return tlskeys_ref_lookupid(id);
9682 }
9683
9684 /* Perform the string lookup. */
9685 return tlskeys_ref_lookup(reference);
9686}
9687#endif
9688
9689
9690#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
9691
9692static int cli_io_handler_tlskeys_files(struct appctx *appctx);
9693
9694static inline int cli_io_handler_tlskeys_entries(struct appctx *appctx) {
9695 return cli_io_handler_tlskeys_files(appctx);
9696}
9697
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009698/* dumps all tls keys. Relies on cli.i0 (non-null = only list file names), cli.i1
9699 * (next index to be dumped), and cli.p0 (next key reference).
9700 */
William Lallemand32af2032016-10-29 18:09:35 +02009701static int cli_io_handler_tlskeys_files(struct appctx *appctx) {
9702
9703 struct stream_interface *si = appctx->owner;
9704
9705 switch (appctx->st2) {
9706 case STAT_ST_INIT:
9707 /* Display the column headers. If the message cannot be sent,
Joseph Herlant017b3da2018-11-15 09:07:59 -08009708 * quit the function with returning 0. The function is called
William Lallemand32af2032016-10-29 18:09:35 +02009709 * later and restart at the state "STAT_ST_INIT".
9710 */
9711 chunk_reset(&trash);
9712
9713 if (appctx->io_handler == cli_io_handler_tlskeys_entries)
9714 chunk_appendf(&trash, "# id secret\n");
9715 else
9716 chunk_appendf(&trash, "# id (file)\n");
9717
Willy Tarreau06d80a92017-10-19 14:32:15 +02009718 if (ci_putchk(si_ic(si), &trash) == -1) {
Willy Tarreaudb398432018-11-15 11:08:52 +01009719 si_rx_room_blk(si);
William Lallemand32af2032016-10-29 18:09:35 +02009720 return 0;
9721 }
9722
William Lallemand32af2032016-10-29 18:09:35 +02009723 /* Now, we start the browsing of the references lists.
9724 * Note that the following call to LIST_ELEM return bad pointer. The only
9725 * available field of this pointer is <list>. It is used with the function
9726 * tlskeys_list_get_next() for retruning the first available entry
9727 */
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009728 if (appctx->ctx.cli.p0 == NULL) {
9729 appctx->ctx.cli.p0 = LIST_ELEM(&tlskeys_reference, struct tls_keys_ref *, list);
9730 appctx->ctx.cli.p0 = tlskeys_list_get_next(appctx->ctx.cli.p0, &tlskeys_reference);
William Lallemand32af2032016-10-29 18:09:35 +02009731 }
9732
9733 appctx->st2 = STAT_ST_LIST;
9734 /* fall through */
9735
9736 case STAT_ST_LIST:
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009737 while (appctx->ctx.cli.p0) {
9738 struct tls_keys_ref *ref = appctx->ctx.cli.p0;
William Lallemand32af2032016-10-29 18:09:35 +02009739
9740 chunk_reset(&trash);
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009741 if (appctx->io_handler == cli_io_handler_tlskeys_entries && appctx->ctx.cli.i1 == 0)
William Lallemand32af2032016-10-29 18:09:35 +02009742 chunk_appendf(&trash, "# ");
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009743
9744 if (appctx->ctx.cli.i1 == 0)
9745 chunk_appendf(&trash, "%d (%s)\n", ref->unique_id, ref->filename);
9746
William Lallemand32af2032016-10-29 18:09:35 +02009747 if (appctx->io_handler == cli_io_handler_tlskeys_entries) {
Christopher Faulet16f45c82018-02-16 11:23:49 +01009748 int head;
9749
9750 HA_RWLOCK_RDLOCK(TLSKEYS_REF_LOCK, &ref->lock);
9751 head = ref->tls_ticket_enc_index;
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009752 while (appctx->ctx.cli.i1 < TLS_TICKETS_NO) {
Willy Tarreau83061a82018-07-13 11:56:34 +02009753 struct buffer *t2 = get_trash_chunk();
William Lallemand32af2032016-10-29 18:09:35 +02009754
9755 chunk_reset(t2);
9756 /* should never fail here because we dump only a key in the t2 buffer */
Emeric Brun9e754772019-01-10 17:51:55 +01009757 if (ref->key_size_bits == 128) {
9758 t2->data = a2base64((char *)(ref->tlskeys + (head + 2 + appctx->ctx.cli.i1) % TLS_TICKETS_NO),
9759 sizeof(struct tls_sess_key_128),
9760 t2->area, t2->size);
9761 chunk_appendf(&trash, "%d.%d %s\n", ref->unique_id, appctx->ctx.cli.i1,
9762 t2->area);
9763 }
9764 else if (ref->key_size_bits == 256) {
9765 t2->data = a2base64((char *)(ref->tlskeys + (head + 2 + appctx->ctx.cli.i1) % TLS_TICKETS_NO),
9766 sizeof(struct tls_sess_key_256),
9767 t2->area, t2->size);
9768 chunk_appendf(&trash, "%d.%d %s\n", ref->unique_id, appctx->ctx.cli.i1,
9769 t2->area);
9770 }
9771 else {
9772 /* This case should never happen */
9773 chunk_appendf(&trash, "%d.%d <unknown>\n", ref->unique_id, appctx->ctx.cli.i1);
9774 }
William Lallemand32af2032016-10-29 18:09:35 +02009775
Willy Tarreau06d80a92017-10-19 14:32:15 +02009776 if (ci_putchk(si_ic(si), &trash) == -1) {
William Lallemand32af2032016-10-29 18:09:35 +02009777 /* let's try again later from this stream. We add ourselves into
9778 * this stream's users so that it can remove us upon termination.
9779 */
Christopher Faulet16f45c82018-02-16 11:23:49 +01009780 HA_RWLOCK_RDUNLOCK(TLSKEYS_REF_LOCK, &ref->lock);
Willy Tarreaudb398432018-11-15 11:08:52 +01009781 si_rx_room_blk(si);
William Lallemand32af2032016-10-29 18:09:35 +02009782 return 0;
9783 }
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009784 appctx->ctx.cli.i1++;
William Lallemand32af2032016-10-29 18:09:35 +02009785 }
Christopher Faulet16f45c82018-02-16 11:23:49 +01009786 HA_RWLOCK_RDUNLOCK(TLSKEYS_REF_LOCK, &ref->lock);
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009787 appctx->ctx.cli.i1 = 0;
William Lallemand32af2032016-10-29 18:09:35 +02009788 }
Willy Tarreau06d80a92017-10-19 14:32:15 +02009789 if (ci_putchk(si_ic(si), &trash) == -1) {
William Lallemand32af2032016-10-29 18:09:35 +02009790 /* let's try again later from this stream. We add ourselves into
9791 * this stream's users so that it can remove us upon termination.
9792 */
Willy Tarreaudb398432018-11-15 11:08:52 +01009793 si_rx_room_blk(si);
William Lallemand32af2032016-10-29 18:09:35 +02009794 return 0;
9795 }
9796
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009797 if (appctx->ctx.cli.i0 == 0) /* don't display everything if not necessary */
William Lallemand32af2032016-10-29 18:09:35 +02009798 break;
9799
9800 /* get next list entry and check the end of the list */
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009801 appctx->ctx.cli.p0 = tlskeys_list_get_next(appctx->ctx.cli.p0, &tlskeys_reference);
William Lallemand32af2032016-10-29 18:09:35 +02009802 }
9803
9804 appctx->st2 = STAT_ST_FIN;
9805 /* fall through */
9806
9807 default:
9808 appctx->st2 = STAT_ST_FIN;
9809 return 1;
9810 }
9811 return 0;
9812}
9813
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009814/* sets cli.i0 to non-zero if only file lists should be dumped */
Aurélien Nephtaliabbf6072018-04-18 13:26:46 +02009815static int cli_parse_show_tlskeys(char **args, char *payload, struct appctx *appctx, void *private)
William Lallemand32af2032016-10-29 18:09:35 +02009816{
William Lallemand32af2032016-10-29 18:09:35 +02009817 /* no parameter, shows only file list */
9818 if (!*args[2]) {
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009819 appctx->ctx.cli.i0 = 1;
William Lallemand32af2032016-10-29 18:09:35 +02009820 appctx->io_handler = cli_io_handler_tlskeys_files;
Willy Tarreau3067bfa2016-12-05 14:50:15 +01009821 return 0;
William Lallemand32af2032016-10-29 18:09:35 +02009822 }
9823
9824 if (args[2][0] == '*') {
9825 /* list every TLS ticket keys */
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009826 appctx->ctx.cli.i0 = 1;
William Lallemand32af2032016-10-29 18:09:35 +02009827 } else {
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009828 appctx->ctx.cli.p0 = tlskeys_ref_lookup_ref(args[2]);
Willy Tarreau9d008692019-08-09 11:21:01 +02009829 if (!appctx->ctx.cli.p0)
9830 return cli_err(appctx, "'show tls-keys' unable to locate referenced filename\n");
William Lallemand32af2032016-10-29 18:09:35 +02009831 }
William Lallemand32af2032016-10-29 18:09:35 +02009832 appctx->io_handler = cli_io_handler_tlskeys_entries;
Willy Tarreau3067bfa2016-12-05 14:50:15 +01009833 return 0;
William Lallemand32af2032016-10-29 18:09:35 +02009834}
9835
Aurélien Nephtaliabbf6072018-04-18 13:26:46 +02009836static int cli_parse_set_tlskeys(char **args, char *payload, struct appctx *appctx, void *private)
William Lallemand32af2032016-10-29 18:09:35 +02009837{
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009838 struct tls_keys_ref *ref;
Willy Tarreau1c913e42018-08-22 05:26:57 +02009839 int ret;
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009840
William Lallemand32af2032016-10-29 18:09:35 +02009841 /* Expect two parameters: the filename and the new new TLS key in encoding */
Willy Tarreau9d008692019-08-09 11:21:01 +02009842 if (!*args[3] || !*args[4])
9843 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 +02009844
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009845 ref = tlskeys_ref_lookup_ref(args[3]);
Willy Tarreau9d008692019-08-09 11:21:01 +02009846 if (!ref)
9847 return cli_err(appctx, "'set ssl tls-key' unable to locate referenced filename\n");
William Lallemand32af2032016-10-29 18:09:35 +02009848
Willy Tarreau1c913e42018-08-22 05:26:57 +02009849 ret = base64dec(args[4], strlen(args[4]), trash.area, trash.size);
Willy Tarreau9d008692019-08-09 11:21:01 +02009850 if (ret < 0)
9851 return cli_err(appctx, "'set ssl tls-key' received invalid base64 encoded TLS key.\n");
Emeric Brun9e754772019-01-10 17:51:55 +01009852
Willy Tarreau1c913e42018-08-22 05:26:57 +02009853 trash.data = ret;
Willy Tarreau9d008692019-08-09 11:21:01 +02009854 if (ssl_sock_update_tlskey_ref(ref, &trash) < 0)
9855 return cli_err(appctx, "'set ssl tls-key' received a key of wrong size.\n");
William Lallemand32af2032016-10-29 18:09:35 +02009856
Willy Tarreau9d008692019-08-09 11:21:01 +02009857 return cli_msg(appctx, LOG_INFO, "TLS ticket key updated!\n");
William Lallemand32af2032016-10-29 18:09:35 +02009858}
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01009859#endif
William Lallemand32af2032016-10-29 18:09:35 +02009860
William Lallemand44b35322019-10-17 16:28:40 +02009861
9862/* Type of SSL payloads that can be updated over the CLI */
9863
9864enum {
9865 CERT_TYPE_PEM = 0,
9866 CERT_TYPE_OCSP,
9867 CERT_TYPE_ISSUER,
9868 CERT_TYPE_SCTL,
9869 CERT_TYPE_MAX,
9870};
9871
9872struct {
9873 const char *ext;
9874 int type;
9875 int (*load)(const char *path, char *payload, struct cert_key_and_chain *ckch, char **err);
9876 /* add a parsing callback */
9877} cert_exts[CERT_TYPE_MAX] = {
9878 [CERT_TYPE_PEM] = { "", CERT_TYPE_PEM, &ssl_sock_load_pem_into_ckch }, /* default mode, no extensions */
9879 [CERT_TYPE_OCSP] = { "ocsp", CERT_TYPE_OCSP, &ssl_sock_load_ocsp_response_from_file },
9880 [CERT_TYPE_SCTL] = { "sctl", CERT_TYPE_SCTL, &ssl_sock_load_sctl_from_file },
9881 [CERT_TYPE_ISSUER] = { "issuer", CERT_TYPE_ISSUER, &ssl_sock_load_issuer_file_into_ckch },
9882};
9883
William Lallemand150bfa82019-09-19 17:12:49 +02009884static int cli_parse_set_cert(char **args, char *payload, struct appctx *appctx, void *private)
9885{
9886 struct ckch_store *ckchs = NULL;
9887 struct cert_key_and_chain *ckch;
9888 struct list tmp_ckchi_list;
William Lallemand44b35322019-10-17 16:28:40 +02009889 char *tmpfp = NULL;
William Lallemand150bfa82019-09-19 17:12:49 +02009890 char *err = NULL;
William Lallemand963b2e72019-10-14 11:38:36 +02009891 int i;
William Lallemand150bfa82019-09-19 17:12:49 +02009892 int found = 0;
William Lallemand849eed62019-10-17 16:23:50 +02009893 int bundle = -1; /* TRUE if >= 0 (ckch index) */
Emeric Brunf69ed1d2019-10-17 11:56:56 +02009894 int errcode = 0;
William Lallemand44b35322019-10-17 16:28:40 +02009895 char *end;
9896 int type = CERT_TYPE_PEM;
William Lallemand150bfa82019-09-19 17:12:49 +02009897
9898 if (!*args[3] || !payload)
9899 return cli_err(appctx, "'set ssl cert expects a filename and a certificat as a payload\n");
9900
William Lallemand44b35322019-10-17 16:28:40 +02009901 tmpfp = strdup(args[3]);
9902 if (!tmpfp)
9903 return cli_err(appctx, "Can't allocate memory\n");
9904
William Lallemand150bfa82019-09-19 17:12:49 +02009905 /* The operations on the CKCH architecture are locked so we can
9906 * manipulate ckch_store and ckch_inst */
9907 if (HA_SPIN_TRYLOCK(CKCH_LOCK, &ckch_lock))
9908 return cli_err(appctx, "Can't update the certificate!\nOperations on certificates are currently locked!\n");
9909
9910 LIST_INIT(&tmp_ckchi_list);
9911
William Lallemand44b35322019-10-17 16:28:40 +02009912 /* check which type of file we want to update */
9913 for (i = 0; i < CERT_TYPE_MAX; i++) {
9914 end = strrchr(tmpfp, '.');
9915 if (end && *cert_exts[i].ext && (!strcmp(end + 1, cert_exts[i].ext))) {
9916 *end = '\0';
9917 type = cert_exts[i].type;
9918 break;
9919 }
9920 }
9921
William Lallemand150bfa82019-09-19 17:12:49 +02009922 /* do 2 iterations, first one with a non-bundle entry, second one with a bundle entry */
9923 for (i = 0; i < 2; i++) {
9924
William Lallemand44b35322019-10-17 16:28:40 +02009925 if ((ckchs = ckchs_lookup(tmpfp)) != NULL) {
William Lallemand150bfa82019-09-19 17:12:49 +02009926 struct ckch_inst *ckchi, *ckchis;
9927
9928 /* only the bundle name is in the tree and you should never update a bundle name, only a filename */
9929 if (bundle < 0 && ckchs->multi) {
9930 memprintf(&err, "%s%s is a multi-cert bundle. Try updating %s.{dsa,rsa,ecdsa}\n",
9931 err ? err : "", args[3], args[3]);
Emeric Brunf69ed1d2019-10-17 11:56:56 +02009932 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemand150bfa82019-09-19 17:12:49 +02009933 goto end;
9934 }
9935
William Lallemand849eed62019-10-17 16:23:50 +02009936 /* If we want a bundle but this is not a bundle */
9937 if (bundle >= 0 && ckchs->multi == 0)
9938 continue;
9939
William Lallemand150bfa82019-09-19 17:12:49 +02009940 if (bundle < 0)
9941 ckch = ckchs->ckch;
9942 else
9943 ckch = &ckchs->ckch[bundle];
9944
9945 if (ckchs->filters) {
9946 memprintf(&err, "%sCertificates used in crt-list with filters are not supported!\n",
9947 err ? err : "");
Emeric Brunf69ed1d2019-10-17 11:56:56 +02009948 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemand150bfa82019-09-19 17:12:49 +02009949 goto end;
9950 }
9951
9952 found = 1;
9953
William Lallemand44b35322019-10-17 16:28:40 +02009954 if (cert_exts[type].load(tmpfp, payload, ckch, &err) != 0) {
Emeric Brunf69ed1d2019-10-17 11:56:56 +02009955 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemand150bfa82019-09-19 17:12:49 +02009956 goto end;
9957 }
9958
9959 /* walk through ckch_inst and creates new ckch_inst using the updated ckch */
9960 list_for_each_entry(ckchi, &ckchs->ckch_inst, by_ckchs) {
9961 struct ckch_inst *new_inst;
9962
9963 if (ckchs->multi)
Emeric Brun054563d2019-10-17 13:16:58 +02009964 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 +02009965 else
Emeric Brun054563d2019-10-17 13:16:58 +02009966 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 +02009967
Emeric Brun054563d2019-10-17 13:16:58 +02009968 if (errcode & ERR_CODE)
William Lallemand150bfa82019-09-19 17:12:49 +02009969 goto end;
William Lallemand150bfa82019-09-19 17:12:49 +02009970
9971 /* link temporary the new ckch_inst */
9972 LIST_ADDQ(&tmp_ckchi_list, &new_inst->by_ckchs);
9973 }
9974
9975 /* once every allocation is done, delete the old sni_ctx & the old ckch_insts */
9976 list_for_each_entry_safe(ckchi, ckchis, &ckchs->ckch_inst, by_ckchs) {
9977 struct sni_ctx *sc0, *sc0s;
9978
William Lallemand02010472019-10-18 11:02:19 +02009979 HA_RWLOCK_WRLOCK(SNI_LOCK, &ckchi->bind_conf->sni_lock);
William Lallemand150bfa82019-09-19 17:12:49 +02009980 list_for_each_entry_safe(sc0, sc0s, &ckchi->sni_ctx, by_ckch_inst) {
9981 ebmb_delete(&sc0->name);
9982 LIST_DEL(&sc0->by_ckch_inst);
9983 free(sc0);
9984 }
William Lallemand02010472019-10-18 11:02:19 +02009985 HA_RWLOCK_WRUNLOCK(SNI_LOCK, &ckchi->bind_conf->sni_lock);
William Lallemand150bfa82019-09-19 17:12:49 +02009986 LIST_DEL(&ckchi->by_ckchs);
9987 free(ckchi);
9988 ckchi = NULL;
9989 }
9990 /* insert every new ckch instance in the actual list and insert the sni_ctx in the trees */
9991 list_for_each_entry_safe(ckchi, ckchis, &tmp_ckchi_list, by_ckchs) {
9992 LIST_DEL(&ckchi->by_ckchs);
9993 LIST_ADD(&ckchs->ckch_inst, &ckchi->by_ckchs);
William Lallemand02010472019-10-18 11:02:19 +02009994 HA_RWLOCK_WRLOCK(SNI_LOCK, &ckchi->bind_conf->sni_lock);
William Lallemand150bfa82019-09-19 17:12:49 +02009995 ssl_sock_load_cert_sni(ckchi, ckchi->bind_conf);
William Lallemand02010472019-10-18 11:02:19 +02009996 HA_RWLOCK_WRUNLOCK(SNI_LOCK, &ckchi->bind_conf->sni_lock);
William Lallemand150bfa82019-09-19 17:12:49 +02009997 }
9998 }
William Lallemand963b2e72019-10-14 11:38:36 +02009999#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
10000 {
10001 char *end = NULL;
10002 int j;
William Lallemand150bfa82019-09-19 17:12:49 +020010003
William Lallemand963b2e72019-10-14 11:38:36 +020010004 /* check if it was also used as a bundle by removing the
10005 * .dsa/.rsa/.ecdsa at the end of the filename */
10006 if (bundle >= 0)
William Lallemand150bfa82019-09-19 17:12:49 +020010007 break;
William Lallemand44b35322019-10-17 16:28:40 +020010008 end = strrchr(tmpfp, '.');
William Lallemand963b2e72019-10-14 11:38:36 +020010009 for (j = 0; *end && j < SSL_SOCK_NUM_KEYTYPES; j++) {
10010 if (!strcmp(end + 1, SSL_SOCK_KEYTYPE_NAMES[j])) {
10011 bundle = j; /* keep the type of certificate so we insert it at the right place */
10012 *end = '\0'; /* it's a bundle let's end the string*/
10013 break;
10014 }
William Lallemand150bfa82019-09-19 17:12:49 +020010015 }
10016 }
William Lallemand963b2e72019-10-14 11:38:36 +020010017#else
10018 /* bundles are not supported here, so we don't need to lookup again */
10019 break;
10020#endif
William Lallemand150bfa82019-09-19 17:12:49 +020010021 }
10022
10023 if (!found) {
William Lallemand150bfa82019-09-19 17:12:49 +020010024 memprintf(&err, "%sCan't replace a certificate name which is not referenced by the configuration!\n",
10025 err ? err : "");
Emeric Brunf69ed1d2019-10-17 11:56:56 +020010026 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemand150bfa82019-09-19 17:12:49 +020010027 }
10028
10029end:
10030
10031 HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
William Lallemand44b35322019-10-17 16:28:40 +020010032 free(tmpfp);
William Lallemand150bfa82019-09-19 17:12:49 +020010033
Emeric Brunf69ed1d2019-10-17 11:56:56 +020010034 if (errcode & ERR_CODE) {
William Lallemand150bfa82019-09-19 17:12:49 +020010035 struct ckch_inst *ckchi, *ckchis;
10036 /* if the allocation failed, we need to free everything from the temporary list */
10037 list_for_each_entry_safe(ckchi, ckchis, &tmp_ckchi_list, by_ckchs) {
10038 struct sni_ctx *sc0, *sc0s;
10039
10040 list_for_each_entry_safe(sc0, sc0s, &ckchi->sni_ctx, by_ckch_inst) {
10041 if (sc0->order == 0) /* we only free if it's the first inserted */
10042 SSL_CTX_free(sc0->ctx);
10043 LIST_DEL(&sc0->by_ckch_inst);
10044 free(sc0);
10045 }
10046 LIST_DEL(&ckchi->by_ckchs);
10047 free(ckchi);
10048 }
William Lallemand44b35322019-10-17 16:28:40 +020010049 return cli_dynerr(appctx, memprintf(&err, "%sCan't update %s!\n", err ? err : "", args[3]));
Emeric Brunf69ed1d2019-10-17 11:56:56 +020010050 }
10051 else if (errcode & ERR_WARN) {
William Lallemand44b35322019-10-17 16:28:40 +020010052 return cli_dynmsg(appctx, LOG_WARNING, memprintf(&err, "%s%s updated!\n", err ? err : "", args[3]));
Emeric Brunf69ed1d2019-10-17 11:56:56 +020010053 }
10054 else {
William Lallemand44b35322019-10-17 16:28:40 +020010055 return cli_dynmsg(appctx, LOG_INFO, memprintf(&err, "%s updated!", args[3]));
William Lallemand150bfa82019-09-19 17:12:49 +020010056 }
10057}
10058
Aurélien Nephtaliabbf6072018-04-18 13:26:46 +020010059static int cli_parse_set_ocspresponse(char **args, char *payload, struct appctx *appctx, void *private)
William Lallemand32af2032016-10-29 18:09:35 +020010060{
10061#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
10062 char *err = NULL;
Willy Tarreau1c913e42018-08-22 05:26:57 +020010063 int i, j, ret;
Aurélien Nephtali1e0867c2018-04-18 14:04:58 +020010064
10065 if (!payload)
10066 payload = args[3];
William Lallemand32af2032016-10-29 18:09:35 +020010067
10068 /* Expect one parameter: the new response in base64 encoding */
Willy Tarreau9d008692019-08-09 11:21:01 +020010069 if (!*payload)
10070 return cli_err(appctx, "'set ssl ocsp-response' expects response in base64 encoding.\n");
Aurélien Nephtali1e0867c2018-04-18 14:04:58 +020010071
10072 /* remove \r and \n from the payload */
10073 for (i = 0, j = 0; payload[i]; i++) {
10074 if (payload[i] == '\r' || payload[i] == '\n')
10075 continue;
10076 payload[j++] = payload[i];
10077 }
10078 payload[j] = 0;
William Lallemand32af2032016-10-29 18:09:35 +020010079
Willy Tarreau1c913e42018-08-22 05:26:57 +020010080 ret = base64dec(payload, j, trash.area, trash.size);
Willy Tarreau9d008692019-08-09 11:21:01 +020010081 if (ret < 0)
10082 return cli_err(appctx, "'set ssl ocsp-response' received invalid base64 encoded response.\n");
William Lallemand32af2032016-10-29 18:09:35 +020010083
Willy Tarreau1c913e42018-08-22 05:26:57 +020010084 trash.data = ret;
William Lallemand32af2032016-10-29 18:09:35 +020010085 if (ssl_sock_update_ocsp_response(&trash, &err)) {
Willy Tarreau9d008692019-08-09 11:21:01 +020010086 if (err)
10087 return cli_dynerr(appctx, memprintf(&err, "%s.\n", err));
10088 else
10089 return cli_err(appctx, "Failed to update OCSP response.\n");
William Lallemand32af2032016-10-29 18:09:35 +020010090 }
Willy Tarreau9d008692019-08-09 11:21:01 +020010091
10092 return cli_msg(appctx, LOG_INFO, "OCSP Response updated!\n");
William Lallemand32af2032016-10-29 18:09:35 +020010093#else
Willy Tarreau9d008692019-08-09 11:21:01 +020010094 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 +020010095#endif
10096
Nenad Merdanovicc31499d2019-03-23 11:00:32 +010010097}
10098
Willy Tarreau86a394e2019-05-09 14:15:32 +020010099#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000100fL)
Nenad Merdanovicc31499d2019-03-23 11:00:32 +010010100static inline int sample_conv_var2smp_str(const struct arg *arg, struct sample *smp)
10101{
10102 switch (arg->type) {
10103 case ARGT_STR:
10104 smp->data.type = SMP_T_STR;
10105 smp->data.u.str = arg->data.str;
10106 return 1;
10107 case ARGT_VAR:
10108 if (!vars_get_by_desc(&arg->data.var, smp))
10109 return 0;
10110 if (!sample_casts[smp->data.type][SMP_T_STR])
10111 return 0;
10112 if (!sample_casts[smp->data.type][SMP_T_STR](smp))
10113 return 0;
10114 return 1;
10115 default:
10116 return 0;
10117 }
10118}
10119
10120static int check_aes_gcm(struct arg *args, struct sample_conv *conv,
10121 const char *file, int line, char **err)
10122{
10123 switch(args[0].data.sint) {
10124 case 128:
10125 case 192:
10126 case 256:
10127 break;
10128 default:
10129 memprintf(err, "key size must be 128, 192 or 256 (bits).");
10130 return 0;
10131 }
10132 /* Try to decode a variable. */
10133 vars_check_arg(&args[1], NULL);
10134 vars_check_arg(&args[2], NULL);
10135 vars_check_arg(&args[3], NULL);
10136 return 1;
10137}
10138
10139/* Arguements: AES size in bits, nonce, key, tag. The last three arguments are base64 encoded */
10140static int sample_conv_aes_gcm_dec(const struct arg *arg_p, struct sample *smp, void *private)
10141{
10142 struct sample nonce, key, aead_tag;
10143 struct buffer *smp_trash, *smp_trash_alloc;
10144 EVP_CIPHER_CTX *ctx;
10145 int dec_size, ret;
10146
10147 smp_set_owner(&nonce, smp->px, smp->sess, smp->strm, smp->opt);
10148 if (!sample_conv_var2smp_str(&arg_p[1], &nonce))
10149 return 0;
10150
10151 smp_set_owner(&key, smp->px, smp->sess, smp->strm, smp->opt);
10152 if (!sample_conv_var2smp_str(&arg_p[2], &key))
10153 return 0;
10154
10155 smp_set_owner(&aead_tag, smp->px, smp->sess, smp->strm, smp->opt);
10156 if (!sample_conv_var2smp_str(&arg_p[3], &aead_tag))
10157 return 0;
10158
10159 smp_trash = get_trash_chunk();
10160 smp_trash_alloc = alloc_trash_chunk();
10161 if (!smp_trash_alloc)
10162 return 0;
10163
10164 ctx = EVP_CIPHER_CTX_new();
10165
10166 if (!ctx)
10167 goto err;
10168
10169 dec_size = base64dec(nonce.data.u.str.area, nonce.data.u.str.data, smp_trash->area, smp_trash->size);
10170 if (dec_size < 0)
10171 goto err;
10172 smp_trash->data = dec_size;
10173
10174 /* Set cipher type and mode */
10175 switch(arg_p[0].data.sint) {
10176 case 128:
10177 EVP_DecryptInit_ex(ctx, EVP_aes_128_gcm(), NULL, NULL, NULL);
10178 break;
10179 case 192:
10180 EVP_DecryptInit_ex(ctx, EVP_aes_192_gcm(), NULL, NULL, NULL);
10181 break;
10182 case 256:
10183 EVP_DecryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL);
10184 break;
10185 }
10186
10187 EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, smp_trash->data, NULL);
10188
10189 /* Initialise IV */
10190 if(!EVP_DecryptInit_ex(ctx, NULL, NULL, NULL, (unsigned char *) smp_trash->area))
10191 goto err;
10192
10193 dec_size = base64dec(key.data.u.str.area, key.data.u.str.data, smp_trash->area, smp_trash->size);
10194 if (dec_size < 0)
10195 goto err;
10196 smp_trash->data = dec_size;
10197
10198 /* Initialise key */
10199 if (!EVP_DecryptInit_ex(ctx, NULL, NULL, (unsigned char *) smp_trash->area, NULL))
10200 goto err;
10201
10202 if (!EVP_DecryptUpdate(ctx, (unsigned char *) smp_trash->area, (int *) &smp_trash->data,
10203 (unsigned char *) smp->data.u.str.area, (int) smp->data.u.str.data))
10204 goto err;
10205
10206 dec_size = base64dec(aead_tag.data.u.str.area, aead_tag.data.u.str.data, smp_trash_alloc->area, smp_trash_alloc->size);
10207 if (dec_size < 0)
10208 goto err;
10209 smp_trash_alloc->data = dec_size;
10210 dec_size = smp_trash->data;
10211
10212 EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, smp_trash_alloc->data, (void *) smp_trash_alloc->area);
10213 ret = EVP_DecryptFinal_ex(ctx, (unsigned char *) smp_trash->area + smp_trash->data, (int *) &smp_trash->data);
10214
10215 if (ret <= 0)
10216 goto err;
10217
10218 smp->data.u.str.data = dec_size + smp_trash->data;
10219 smp->data.u.str.area = smp_trash->area;
10220 smp->data.type = SMP_T_BIN;
10221 smp->flags &= ~SMP_F_CONST;
10222 free_trash_chunk(smp_trash_alloc);
10223 return 1;
10224
10225err:
10226 free_trash_chunk(smp_trash_alloc);
10227 return 0;
William Lallemand32af2032016-10-29 18:09:35 +020010228}
Nenad Merdanovicc31499d2019-03-23 11:00:32 +010010229# endif
William Lallemand32af2032016-10-29 18:09:35 +020010230
10231/* register cli keywords */
10232static struct cli_kw_list cli_kws = {{ },{
10233#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
10234 { { "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 +020010235 { { "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 +020010236#endif
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +010010237 { { "set", "ssl", "ocsp-response", NULL }, NULL, cli_parse_set_ocspresponse, NULL },
William Lallemand150bfa82019-09-19 17:12:49 +020010238 { { "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 +020010239 { { NULL }, NULL, NULL, NULL }
10240}};
10241
Willy Tarreau0108d902018-11-25 19:14:37 +010010242INITCALL1(STG_REGISTER, cli_register_kw, &cli_kws);
William Lallemand32af2032016-10-29 18:09:35 +020010243
Willy Tarreau7875d092012-09-10 08:20:03 +020010244/* Note: must not be declared <const> as its list will be overwritten.
10245 * Please take care of keeping this list alphabetically sorted.
10246 */
Willy Tarreaudc13c112013-06-21 23:16:39 +020010247static struct sample_fetch_kw_list sample_fetch_keywords = {ILH, {
Emeric Brun645ae792014-04-30 14:21:06 +020010248 { "ssl_bc", smp_fetch_ssl_fc, 0, NULL, SMP_T_BOOL, SMP_USE_L5SRV },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +020010249 { "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 +010010250#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Jérôme Magnine064a802018-12-03 22:21:04 +010010251 { "ssl_bc_alpn", smp_fetch_ssl_fc_alpn, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
Olivier Houchard6b77f492018-11-22 18:18:29 +010010252#endif
Emeric Brun645ae792014-04-30 14:21:06 +020010253 { "ssl_bc_cipher", smp_fetch_ssl_fc_cipher, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
Olivier Houchard6b77f492018-11-22 18:18:29 +010010254#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
10255 { "ssl_bc_npn", smp_fetch_ssl_fc_npn, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
10256#endif
Emeric Brun74f7ffa2018-02-19 16:14:12 +010010257 { "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 +020010258 { "ssl_bc_protocol", smp_fetch_ssl_fc_protocol, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
Emeric Brunb73a9b02014-04-30 18:49:19 +020010259 { "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 +020010260 { "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 +020010261#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
Emeric Brun645ae792014-04-30 14:21:06 +020010262 { "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 -040010263#endif
Emmanuel Hocdet839af572019-05-14 16:27:35 +020010264#if HA_OPENSSL_VERSION_NUMBER >= 0x10100000L
Patrick Hemmer65674662019-06-04 08:13:03 -040010265 { "ssl_bc_client_random", smp_fetch_ssl_fc_random, 0, NULL, SMP_T_BIN, SMP_USE_L5SRV },
10266 { "ssl_bc_server_random", smp_fetch_ssl_fc_random, 0, NULL, SMP_T_BIN, SMP_USE_L5SRV },
Patrick Hemmere0275472018-04-28 19:15:51 -040010267 { "ssl_bc_session_key", smp_fetch_ssl_fc_session_key, 0, NULL, SMP_T_BIN, SMP_USE_L5SRV },
10268#endif
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +020010269 { "ssl_c_ca_err", smp_fetch_ssl_c_ca_err, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
10270 { "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 +010010271 { "ssl_c_der", smp_fetch_ssl_x_der, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +020010272 { "ssl_c_err", smp_fetch_ssl_c_err, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Emeric Brunba841a12014-04-30 17:05:08 +020010273 { "ssl_c_i_dn", smp_fetch_ssl_x_i_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
10274 { "ssl_c_key_alg", smp_fetch_ssl_x_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
10275 { "ssl_c_notafter", smp_fetch_ssl_x_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
10276 { "ssl_c_notbefore", smp_fetch_ssl_x_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
10277 { "ssl_c_sig_alg", smp_fetch_ssl_x_sig_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
10278 { "ssl_c_s_dn", smp_fetch_ssl_x_s_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
10279 { "ssl_c_serial", smp_fetch_ssl_x_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
10280 { "ssl_c_sha1", smp_fetch_ssl_x_sha1, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +010010281 { "ssl_c_used", smp_fetch_ssl_c_used, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +020010282 { "ssl_c_verify", smp_fetch_ssl_c_verify, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
10283 { "ssl_c_version", smp_fetch_ssl_x_version, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Emeric Brun43e79582014-10-29 19:03:26 +010010284 { "ssl_f_der", smp_fetch_ssl_x_der, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Emeric Brunba841a12014-04-30 17:05:08 +020010285 { "ssl_f_i_dn", smp_fetch_ssl_x_i_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
10286 { "ssl_f_key_alg", smp_fetch_ssl_x_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
10287 { "ssl_f_notafter", smp_fetch_ssl_x_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
10288 { "ssl_f_notbefore", smp_fetch_ssl_x_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
10289 { "ssl_f_sig_alg", smp_fetch_ssl_x_sig_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
10290 { "ssl_f_s_dn", smp_fetch_ssl_x_s_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
10291 { "ssl_f_serial", smp_fetch_ssl_x_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Emeric Brun55f4fa82014-04-30 17:11:25 +020010292 { "ssl_f_sha1", smp_fetch_ssl_x_sha1, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +020010293 { "ssl_f_version", smp_fetch_ssl_x_version, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +010010294 { "ssl_fc", smp_fetch_ssl_fc, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +020010295 { "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 +010010296 { "ssl_fc_cipher", smp_fetch_ssl_fc_cipher, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +010010297 { "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 +020010298 { "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 +010010299 { "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 +020010300 { "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 +010010301#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +010010302 { "ssl_fc_npn", smp_fetch_ssl_fc_npn, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreaua33c6542012-10-15 13:19:06 +020010303#endif
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +010010304#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +010010305 { "ssl_fc_alpn", smp_fetch_ssl_fc_alpn, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreauab861d32013-04-02 02:30:41 +020010306#endif
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +010010307 { "ssl_fc_protocol", smp_fetch_ssl_fc_protocol, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreau9a1ab082019-05-09 13:26:41 +020010308#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
Emeric Brunb73a9b02014-04-30 18:49:19 +020010309 { "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 -040010310#endif
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +020010311 { "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 +020010312#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +010010313 { "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 -040010314#endif
Emmanuel Hocdet839af572019-05-14 16:27:35 +020010315#if HA_OPENSSL_VERSION_NUMBER >= 0x10100000L
Patrick Hemmer65674662019-06-04 08:13:03 -040010316 { "ssl_fc_client_random", smp_fetch_ssl_fc_random, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
10317 { "ssl_fc_server_random", smp_fetch_ssl_fc_random, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Patrick Hemmere0275472018-04-28 19:15:51 -040010318 { "ssl_fc_session_key", smp_fetch_ssl_fc_session_key, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
10319#endif
Patrick Hemmer41966772018-04-28 19:15:48 -040010320#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +010010321 { "ssl_fc_sni", smp_fetch_ssl_fc_sni, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Patrick Hemmer41966772018-04-28 19:15:48 -040010322#endif
Thierry FOURNIER5bf77322017-02-25 12:45:22 +010010323 { "ssl_fc_cipherlist_bin", smp_fetch_ssl_fc_cl_bin, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
10324 { "ssl_fc_cipherlist_hex", smp_fetch_ssl_fc_cl_hex, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
10325 { "ssl_fc_cipherlist_str", smp_fetch_ssl_fc_cl_str, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
10326 { "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 +020010327 { NULL, NULL, 0, 0, 0 },
10328}};
10329
Willy Tarreau0108d902018-11-25 19:14:37 +010010330INITCALL1(STG_REGISTER, sample_register_fetches, &sample_fetch_keywords);
10331
Willy Tarreau7875d092012-09-10 08:20:03 +020010332/* Note: must not be declared <const> as its list will be overwritten.
10333 * Please take care of keeping this list alphabetically sorted.
10334 */
Willy Tarreaudc13c112013-06-21 23:16:39 +020010335static struct acl_kw_list acl_kws = {ILH, {
Thierry FOURNIERc5a4e982014-03-05 16:07:08 +010010336 { "ssl_fc_sni_end", "ssl_fc_sni", PAT_MATCH_END },
10337 { "ssl_fc_sni_reg", "ssl_fc_sni", PAT_MATCH_REG },
Willy Tarreau8ed669b2013-01-11 15:49:37 +010010338 { /* END */ },
Willy Tarreau7875d092012-09-10 08:20:03 +020010339}};
10340
Willy Tarreau0108d902018-11-25 19:14:37 +010010341INITCALL1(STG_REGISTER, acl_register_keywords, &acl_kws);
10342
Willy Tarreau79eeafa2012-09-14 07:53:05 +020010343/* Note: must not be declared <const> as its list will be overwritten.
10344 * Please take care of keeping this list alphabetically sorted, doing so helps
10345 * all code contributors.
10346 * Optional keywords are also declared with a NULL ->parse() function so that
10347 * the config parser can report an appropriate error when a known keyword was
10348 * not enabled.
10349 */
Emmanuel Hocdet98263292016-12-29 18:26:15 +010010350static struct ssl_bind_kw ssl_bind_kws[] = {
Olivier Houchardc2aae742017-09-22 18:26:28 +020010351 { "allow-0rtt", ssl_bind_parse_allow_0rtt, 0 }, /* allow 0-RTT */
Emmanuel Hocdet98263292016-12-29 18:26:15 +010010352 { "alpn", ssl_bind_parse_alpn, 1 }, /* set ALPN supported protocols */
10353 { "ca-file", ssl_bind_parse_ca_file, 1 }, /* set CAfile to process verify on client cert */
10354 { "ciphers", ssl_bind_parse_ciphers, 1 }, /* set SSL cipher suite */
Emmanuel Hocdet839af572019-05-14 16:27:35 +020010355#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +020010356 { "ciphersuites", ssl_bind_parse_ciphersuites, 1 }, /* set TLS 1.3 cipher suite */
10357#endif
Emmanuel Hocdet98263292016-12-29 18:26:15 +010010358 { "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 +010010359 { "curves", ssl_bind_parse_curves, 1 }, /* set SSL curve suite */
Emmanuel Hocdet98263292016-12-29 18:26:15 +010010360 { "ecdhe", ssl_bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +020010361 { "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 +010010362 { "npn", ssl_bind_parse_npn, 1 }, /* set NPN supported protocols */
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +020010363 { "ssl-min-ver", ssl_bind_parse_tls_method_minmax,1 }, /* minimum version */
10364 { "ssl-max-ver", ssl_bind_parse_tls_method_minmax,1 }, /* maximum version */
Emmanuel Hocdet98263292016-12-29 18:26:15 +010010365 { "verify", ssl_bind_parse_verify, 1 }, /* set SSL verify method */
10366 { NULL, NULL, 0 },
10367};
10368
Willy Tarreau0108d902018-11-25 19:14:37 +010010369/* no initcall for ssl_bind_kws, these ones are parsed in the parser loop */
10370
Willy Tarreau51fb7652012-09-18 18:24:39 +020010371static struct bind_kw_list bind_kws = { "SSL", { }, {
Olivier Houchardc2aae742017-09-22 18:26:28 +020010372 { "allow-0rtt", bind_parse_allow_0rtt, 0 }, /* Allow 0RTT */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +020010373 { "alpn", bind_parse_alpn, 1 }, /* set ALPN supported protocols */
10374 { "ca-file", bind_parse_ca_file, 1 }, /* set CAfile to process verify on client cert */
10375 { "ca-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ignore on verify depth > 0 */
10376 { "ca-sign-file", bind_parse_ca_sign_file, 1 }, /* set CAFile used to generate and sign server certs */
10377 { "ca-sign-pass", bind_parse_ca_sign_pass, 1 }, /* set CAKey passphrase */
10378 { "ciphers", bind_parse_ciphers, 1 }, /* set SSL cipher suite */
Emmanuel Hocdet839af572019-05-14 16:27:35 +020010379#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +020010380 { "ciphersuites", bind_parse_ciphersuites, 1 }, /* set TLS 1.3 cipher suite */
10381#endif
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +020010382 { "crl-file", bind_parse_crl_file, 1 }, /* set certificat revocation list file use on client cert verify */
10383 { "crt", bind_parse_crt, 1 }, /* load SSL certificates from this location */
10384 { "crt-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ingore on verify depth == 0 */
10385 { "crt-list", bind_parse_crt_list, 1 }, /* load a list of crt from this location */
10386 { "curves", bind_parse_curves, 1 }, /* set SSL curve suite */
10387 { "ecdhe", bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
10388 { "force-sslv3", bind_parse_tls_method_options, 0 }, /* force SSLv3 */
10389 { "force-tlsv10", bind_parse_tls_method_options, 0 }, /* force TLSv10 */
10390 { "force-tlsv11", bind_parse_tls_method_options, 0 }, /* force TLSv11 */
10391 { "force-tlsv12", bind_parse_tls_method_options, 0 }, /* force TLSv12 */
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +020010392 { "force-tlsv13", bind_parse_tls_method_options, 0 }, /* force TLSv13 */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +020010393 { "generate-certificates", bind_parse_generate_certs, 0 }, /* enable the server certificates generation */
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +020010394 { "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 +020010395 { "no-sslv3", bind_parse_tls_method_options, 0 }, /* disable SSLv3 */
10396 { "no-tlsv10", bind_parse_tls_method_options, 0 }, /* disable TLSv10 */
10397 { "no-tlsv11", bind_parse_tls_method_options, 0 }, /* disable TLSv11 */
10398 { "no-tlsv12", bind_parse_tls_method_options, 0 }, /* disable TLSv12 */
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +020010399 { "no-tlsv13", bind_parse_tls_method_options, 0 }, /* disable TLSv13 */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +020010400 { "no-tls-tickets", bind_parse_no_tls_tickets, 0 }, /* disable session resumption tickets */
10401 { "ssl", bind_parse_ssl, 0 }, /* enable SSL processing */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +020010402 { "ssl-min-ver", bind_parse_tls_method_minmax, 1 }, /* minimum version */
10403 { "ssl-max-ver", bind_parse_tls_method_minmax, 1 }, /* maximum version */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +020010404 { "strict-sni", bind_parse_strict_sni, 0 }, /* refuse negotiation if sni doesn't match a certificate */
10405 { "tls-ticket-keys", bind_parse_tls_ticket_keys, 1 }, /* set file to load TLS ticket keys from */
10406 { "verify", bind_parse_verify, 1 }, /* set SSL verify method */
10407 { "npn", bind_parse_npn, 1 }, /* set NPN supported protocols */
10408 { "prefer-client-ciphers", bind_parse_pcc, 0 }, /* prefer client ciphers */
Willy Tarreau79eeafa2012-09-14 07:53:05 +020010409 { NULL, NULL, 0 },
10410}};
Emeric Brun46591952012-05-18 15:47:34 +020010411
Willy Tarreau0108d902018-11-25 19:14:37 +010010412INITCALL1(STG_REGISTER, bind_register_keywords, &bind_kws);
10413
Willy Tarreau92faadf2012-10-10 23:04:25 +020010414/* Note: must not be declared <const> as its list will be overwritten.
10415 * Please take care of keeping this list alphabetically sorted, doing so helps
10416 * all code contributors.
10417 * Optional keywords are also declared with a NULL ->parse() function so that
10418 * the config parser can report an appropriate error when a known keyword was
10419 * not enabled.
10420 */
10421static struct srv_kw_list srv_kws = { "SSL", { }, {
Olivier Houchard522eea72017-11-03 16:27:47 +010010422 { "allow-0rtt", srv_parse_allow_0rtt, 0, 1 }, /* Allow using early data on this server */
Olivier Houchardc7566002018-11-20 23:33:50 +010010423 { "alpn", srv_parse_alpn, 1, 1 }, /* Set ALPN supported protocols */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +020010424 { "ca-file", srv_parse_ca_file, 1, 1 }, /* set CAfile to process verify server cert */
Olivier Houchard92150142018-12-21 19:47:01 +010010425 { "check-alpn", srv_parse_alpn, 1, 1 }, /* Set ALPN used for checks */
Olivier Houchard9130a962017-10-17 17:33:43 +020010426 { "check-sni", srv_parse_check_sni, 1, 1 }, /* set SNI */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +020010427 { "check-ssl", srv_parse_check_ssl, 0, 1 }, /* enable SSL for health checks */
10428 { "ciphers", srv_parse_ciphers, 1, 1 }, /* select the cipher suite */
Emmanuel Hocdet839af572019-05-14 16:27:35 +020010429#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +020010430 { "ciphersuites", srv_parse_ciphersuites, 1, 1 }, /* select the cipher suite */
10431#endif
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +020010432 { "crl-file", srv_parse_crl_file, 1, 1 }, /* set certificate revocation list file use on server cert verify */
10433 { "crt", srv_parse_crt, 1, 1 }, /* set client certificate */
10434 { "force-sslv3", srv_parse_tls_method_options, 0, 1 }, /* force SSLv3 */
10435 { "force-tlsv10", srv_parse_tls_method_options, 0, 1 }, /* force TLSv10 */
10436 { "force-tlsv11", srv_parse_tls_method_options, 0, 1 }, /* force TLSv11 */
10437 { "force-tlsv12", srv_parse_tls_method_options, 0, 1 }, /* force TLSv12 */
10438 { "force-tlsv13", srv_parse_tls_method_options, 0, 1 }, /* force TLSv13 */
10439 { "no-check-ssl", srv_parse_no_check_ssl, 0, 1 }, /* disable SSL for health checks */
10440 { "no-send-proxy-v2-ssl", srv_parse_no_send_proxy_ssl, 0, 1 }, /* do not send PROXY protocol header v2 with SSL info */
10441 { "no-send-proxy-v2-ssl-cn", srv_parse_no_send_proxy_cn, 0, 1 }, /* do not send PROXY protocol header v2 with CN */
10442 { "no-ssl", srv_parse_no_ssl, 0, 1 }, /* disable SSL processing */
10443 { "no-ssl-reuse", srv_parse_no_ssl_reuse, 0, 1 }, /* disable session reuse */
10444 { "no-sslv3", srv_parse_tls_method_options, 0, 0 }, /* disable SSLv3 */
10445 { "no-tlsv10", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv10 */
10446 { "no-tlsv11", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv11 */
10447 { "no-tlsv12", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv12 */
10448 { "no-tlsv13", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv13 */
10449 { "no-tls-tickets", srv_parse_no_tls_tickets, 0, 1 }, /* disable session resumption tickets */
Olivier Houchardc7566002018-11-20 23:33:50 +010010450 { "npn", srv_parse_npn, 1, 1 }, /* Set NPN supported protocols */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +020010451 { "send-proxy-v2-ssl", srv_parse_send_proxy_ssl, 0, 1 }, /* send PROXY protocol header v2 with SSL info */
10452 { "send-proxy-v2-ssl-cn", srv_parse_send_proxy_cn, 0, 1 }, /* send PROXY protocol header v2 with CN */
10453 { "sni", srv_parse_sni, 1, 1 }, /* send SNI extension */
10454 { "ssl", srv_parse_ssl, 0, 1 }, /* enable SSL processing */
10455 { "ssl-min-ver", srv_parse_tls_method_minmax, 1, 1 }, /* minimum version */
10456 { "ssl-max-ver", srv_parse_tls_method_minmax, 1, 1 }, /* maximum version */
10457 { "ssl-reuse", srv_parse_ssl_reuse, 0, 1 }, /* enable session reuse */
10458 { "tls-tickets", srv_parse_tls_tickets, 0, 1 }, /* enable session resumption tickets */
10459 { "verify", srv_parse_verify, 1, 1 }, /* set SSL verify method */
10460 { "verifyhost", srv_parse_verifyhost, 1, 1 }, /* require that SSL cert verifies for hostname */
Willy Tarreau92faadf2012-10-10 23:04:25 +020010461 { NULL, NULL, 0, 0 },
10462}};
10463
Willy Tarreau0108d902018-11-25 19:14:37 +010010464INITCALL1(STG_REGISTER, srv_register_keywords, &srv_kws);
10465
Emeric Brun2c86cbf2014-10-30 15:56:50 +010010466static struct cfg_kw_list cfg_kws = {ILH, {
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +010010467 { CFG_GLOBAL, "ca-base", ssl_parse_global_ca_crt_base },
10468 { CFG_GLOBAL, "crt-base", ssl_parse_global_ca_crt_base },
Willy Tarreau0bea58d2016-12-21 23:17:25 +010010469 { CFG_GLOBAL, "maxsslconn", ssl_parse_global_int },
Emeric Brun2c86cbf2014-10-30 15:56:50 +010010470 { CFG_GLOBAL, "ssl-default-bind-options", ssl_parse_default_bind_options },
10471 { CFG_GLOBAL, "ssl-default-server-options", ssl_parse_default_server_options },
Willy Tarreau14e36a12016-12-21 23:28:13 +010010472#ifndef OPENSSL_NO_DH
10473 { CFG_GLOBAL, "ssl-dh-param-file", ssl_parse_global_dh_param_file },
10474#endif
Grant Zhangfa6c7ee2017-01-14 01:42:15 +000010475 { CFG_GLOBAL, "ssl-mode-async", ssl_parse_global_ssl_async },
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020010476#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +000010477 { CFG_GLOBAL, "ssl-engine", ssl_parse_global_ssl_engine },
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020010478#endif
Willy Tarreau9ceda382016-12-21 23:13:03 +010010479 { CFG_GLOBAL, "tune.ssl.cachesize", ssl_parse_global_int },
10480#ifndef OPENSSL_NO_DH
10481 { CFG_GLOBAL, "tune.ssl.default-dh-param", ssl_parse_global_default_dh },
10482#endif
10483 { CFG_GLOBAL, "tune.ssl.force-private-cache", ssl_parse_global_private_cache },
10484 { CFG_GLOBAL, "tune.ssl.lifetime", ssl_parse_global_lifetime },
10485 { CFG_GLOBAL, "tune.ssl.maxrecord", ssl_parse_global_int },
10486 { CFG_GLOBAL, "tune.ssl.ssl-ctx-cache-size", ssl_parse_global_int },
Thierry FOURNIER5bf77322017-02-25 12:45:22 +010010487 { CFG_GLOBAL, "tune.ssl.capture-cipherlist-size", ssl_parse_global_capture_cipherlist },
Willy Tarreauf22e9682016-12-21 23:23:19 +010010488 { CFG_GLOBAL, "ssl-default-bind-ciphers", ssl_parse_global_ciphers },
10489 { CFG_GLOBAL, "ssl-default-server-ciphers", ssl_parse_global_ciphers },
Emmanuel Hocdet839af572019-05-14 16:27:35 +020010490#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +020010491 { CFG_GLOBAL, "ssl-default-bind-ciphersuites", ssl_parse_global_ciphersuites },
10492 { CFG_GLOBAL, "ssl-default-server-ciphersuites", ssl_parse_global_ciphersuites },
10493#endif
Emeric Brun2c86cbf2014-10-30 15:56:50 +010010494 { 0, NULL, NULL },
10495}};
10496
Willy Tarreau0108d902018-11-25 19:14:37 +010010497INITCALL1(STG_REGISTER, cfg_register_keywords, &cfg_kws);
10498
Nenad Merdanovicc31499d2019-03-23 11:00:32 +010010499/* Note: must not be declared <const> as its list will be overwritten */
10500static struct sample_conv_kw_list conv_kws = {ILH, {
Willy Tarreau86a394e2019-05-09 14:15:32 +020010501#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000100fL)
Nenad Merdanovicc31499d2019-03-23 11:00:32 +010010502 { "aes_gcm_dec", sample_conv_aes_gcm_dec, ARG4(4,SINT,STR,STR,STR), check_aes_gcm, SMP_T_BIN, SMP_T_BIN },
10503#endif
10504 { NULL, NULL, 0, 0, 0 },
10505}};
10506
10507INITCALL1(STG_REGISTER, sample_register_convs, &conv_kws);
10508
Willy Tarreauf7bc57c2012-10-03 00:19:48 +020010509/* transport-layer operations for SSL sockets */
Willy Tarreaud9f5cca2016-12-22 21:08:52 +010010510static struct xprt_ops ssl_sock = {
Emeric Brun46591952012-05-18 15:47:34 +020010511 .snd_buf = ssl_sock_from_buf,
10512 .rcv_buf = ssl_sock_to_buf,
Olivier Houcharddf357842019-03-21 16:30:07 +010010513 .subscribe = ssl_subscribe,
10514 .unsubscribe = ssl_unsubscribe,
Olivier Houchard5149b592019-05-23 17:47:36 +020010515 .remove_xprt = ssl_remove_xprt,
Olivier Houchard2e055482019-05-27 19:50:12 +020010516 .add_xprt = ssl_add_xprt,
Emeric Brun46591952012-05-18 15:47:34 +020010517 .rcv_pipe = NULL,
10518 .snd_pipe = NULL,
10519 .shutr = NULL,
10520 .shutw = ssl_sock_shutw,
10521 .close = ssl_sock_close,
10522 .init = ssl_sock_init,
Willy Tarreau55d37912016-12-21 23:38:39 +010010523 .prepare_bind_conf = ssl_sock_prepare_bind_conf,
Willy Tarreau795cdab2016-12-22 17:30:54 +010010524 .destroy_bind_conf = ssl_sock_destroy_bind_conf,
Willy Tarreau17d45382016-12-22 21:16:08 +010010525 .prepare_srv = ssl_sock_prepare_srv_ctx,
10526 .destroy_srv = ssl_sock_free_srv_ctx,
Willy Tarreau8743f7e2016-12-04 18:44:29 +010010527 .get_alpn = ssl_sock_get_alpn,
Willy Tarreau8e0bb0a2016-11-24 16:58:12 +010010528 .name = "SSL",
Emeric Brun46591952012-05-18 15:47:34 +020010529};
10530
Olivier Houchardccaa7de2017-10-02 11:51:03 +020010531enum act_return ssl_action_wait_for_hs(struct act_rule *rule, struct proxy *px,
10532 struct session *sess, struct stream *s, int flags)
10533{
10534 struct connection *conn;
Olivier Houchard6fa63d92017-11-27 18:41:32 +010010535 struct conn_stream *cs;
Olivier Houchardccaa7de2017-10-02 11:51:03 +020010536
10537 conn = objt_conn(sess->origin);
Olivier Houchard6fa63d92017-11-27 18:41:32 +010010538 cs = objt_cs(s->si[0].end);
Olivier Houchardccaa7de2017-10-02 11:51:03 +020010539
Olivier Houchard6fa63d92017-11-27 18:41:32 +010010540 if (conn && cs) {
Olivier Houchardccaa7de2017-10-02 11:51:03 +020010541 if (conn->flags & (CO_FL_EARLY_SSL_HS | CO_FL_SSL_WAIT_HS)) {
Olivier Houchard6fa63d92017-11-27 18:41:32 +010010542 cs->flags |= CS_FL_WAIT_FOR_HS;
Olivier Houchardccaa7de2017-10-02 11:51:03 +020010543 s->req.flags |= CF_READ_NULL;
10544 return ACT_RET_YIELD;
10545 }
10546 }
10547 return (ACT_RET_CONT);
10548}
10549
10550static enum act_parse_ret ssl_parse_wait_for_hs(const char **args, int *orig_arg, struct proxy *px, struct act_rule *rule, char **err)
10551{
10552 rule->action_ptr = ssl_action_wait_for_hs;
10553
10554 return ACT_RET_PRS_OK;
10555}
10556
10557static struct action_kw_list http_req_actions = {ILH, {
10558 { "wait-for-handshake", ssl_parse_wait_for_hs },
10559 { /* END */ }
10560}};
10561
Willy Tarreau0108d902018-11-25 19:14:37 +010010562INITCALL1(STG_REGISTER, http_req_keywords_register, &http_req_actions);
10563
Willy Tarreau5db847a2019-05-09 14:13:35 +020010564#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +010010565
10566static void ssl_sock_sctl_free_func(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, long argl, void *argp)
10567{
10568 if (ptr) {
10569 chunk_destroy(ptr);
10570 free(ptr);
10571 }
10572}
10573
10574#endif
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +010010575static void ssl_sock_capture_free_func(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, long argl, void *argp)
10576{
Willy Tarreaubafbe012017-11-24 17:34:44 +010010577 pool_free(pool_head_ssl_capture, ptr);
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +010010578}
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +010010579
Emeric Brun46591952012-05-18 15:47:34 +020010580__attribute__((constructor))
Willy Tarreau92faadf2012-10-10 23:04:25 +020010581static void __ssl_sock_init(void)
10582{
Ilya Shipitsin0590f442019-05-25 19:30:50 +050010583#if (!defined(OPENSSL_NO_COMP) && !defined(SSL_OP_NO_COMPRESSION))
Emeric Brun46591952012-05-18 15:47:34 +020010584 STACK_OF(SSL_COMP)* cm;
Ilya Shipitsine242f3d2019-05-25 03:38:14 +050010585 int n;
Ilya Shipitsin0590f442019-05-25 19:30:50 +050010586#endif
Emeric Brun46591952012-05-18 15:47:34 +020010587
Willy Tarreauef934602016-12-22 23:12:01 +010010588 if (global_ssl.listen_default_ciphers)
10589 global_ssl.listen_default_ciphers = strdup(global_ssl.listen_default_ciphers);
10590 if (global_ssl.connect_default_ciphers)
10591 global_ssl.connect_default_ciphers = strdup(global_ssl.connect_default_ciphers);
Emmanuel Hocdet839af572019-05-14 16:27:35 +020010592#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +020010593 if (global_ssl.listen_default_ciphersuites)
10594 global_ssl.listen_default_ciphersuites = strdup(global_ssl.listen_default_ciphersuites);
10595 if (global_ssl.connect_default_ciphersuites)
10596 global_ssl.connect_default_ciphersuites = strdup(global_ssl.connect_default_ciphersuites);
10597#endif
Willy Tarreau610f04b2014-02-13 11:36:41 +010010598
Willy Tarreau13e14102016-12-22 20:25:26 +010010599 xprt_register(XPRT_SSL, &ssl_sock);
Willy Tarreau9a1ab082019-05-09 13:26:41 +020010600#if HA_OPENSSL_VERSION_NUMBER < 0x10100000L
Emeric Brun46591952012-05-18 15:47:34 +020010601 SSL_library_init();
Rosen Penev68185952018-12-14 08:47:02 -080010602#endif
Ilya Shipitsin0590f442019-05-25 19:30:50 +050010603#if (!defined(OPENSSL_NO_COMP) && !defined(SSL_OP_NO_COMPRESSION))
Emeric Brun46591952012-05-18 15:47:34 +020010604 cm = SSL_COMP_get_compression_methods();
Ilya Shipitsine242f3d2019-05-25 03:38:14 +050010605 n = sk_SSL_COMP_num(cm);
10606 while (n--) {
10607 (void) sk_SSL_COMP_pop(cm);
10608 }
Ilya Shipitsin0590f442019-05-25 19:30:50 +050010609#endif
Ilya Shipitsine242f3d2019-05-25 03:38:14 +050010610
Willy Tarreau5db847a2019-05-09 14:13:35 +020010611#if defined(USE_THREAD) && (HA_OPENSSL_VERSION_NUMBER < 0x10100000L)
Emeric Brun821bb9b2017-06-15 16:37:39 +020010612 ssl_locking_init();
10613#endif
Willy Tarreau5db847a2019-05-09 14:13:35 +020010614#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +010010615 sctl_ex_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, ssl_sock_sctl_free_func);
10616#endif
Thierry FOURNIER28962c92018-06-17 21:37:05 +020010617 ssl_app_data_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL);
Thierry FOURNIER16ff0502018-06-17 21:33:01 +020010618 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 +010010619 ssl_pkey_info_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, NULL);
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020010620#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +000010621 ENGINE_load_builtin_engines();
Grant Zhangfa6c7ee2017-01-14 01:42:15 +000010622 hap_register_post_check(ssl_check_async_engine_count);
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020010623#endif
Willy Tarreaud1c57502016-12-22 22:46:15 +010010624#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
10625 hap_register_post_check(tlskeys_finalize_config);
10626#endif
Willy Tarreau80713382018-11-26 10:19:54 +010010627
10628 global.ssl_session_max_cost = SSL_SESSION_MAX_COST;
10629 global.ssl_handshake_max_cost = SSL_HANDSHAKE_MAX_COST;
10630
10631#ifndef OPENSSL_NO_DH
10632 ssl_dh_ptr_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, NULL);
10633 hap_register_post_deinit(ssl_free_dh);
10634#endif
10635#ifndef OPENSSL_NO_ENGINE
10636 hap_register_post_deinit(ssl_free_engines);
10637#endif
10638 /* Load SSL string for the verbose & debug mode. */
10639 ERR_load_SSL_strings();
Olivier Houcharda8955d52019-04-07 22:00:38 +020010640 ha_meth = BIO_meth_new(0x666, "ha methods");
10641 BIO_meth_set_write(ha_meth, ha_ssl_write);
10642 BIO_meth_set_read(ha_meth, ha_ssl_read);
10643 BIO_meth_set_ctrl(ha_meth, ha_ssl_ctrl);
10644 BIO_meth_set_create(ha_meth, ha_ssl_new);
10645 BIO_meth_set_destroy(ha_meth, ha_ssl_free);
10646 BIO_meth_set_puts(ha_meth, ha_ssl_puts);
10647 BIO_meth_set_gets(ha_meth, ha_ssl_gets);
William Lallemand150bfa82019-09-19 17:12:49 +020010648
10649 HA_SPIN_INIT(&ckch_lock);
Willy Tarreau80713382018-11-26 10:19:54 +010010650}
Willy Tarreaud92aa5c2015-01-15 21:34:39 +010010651
Willy Tarreau80713382018-11-26 10:19:54 +010010652/* Compute and register the version string */
10653static void ssl_register_build_options()
10654{
10655 char *ptr = NULL;
10656 int i;
10657
Willy Tarreauc2c0b612016-12-21 19:23:20 +010010658 memprintf(&ptr, "Built with OpenSSL version : "
10659#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet50e25e12017-03-24 15:20:03 +010010660 "BoringSSL");
Willy Tarreauc2c0b612016-12-21 19:23:20 +010010661#else /* OPENSSL_IS_BORINGSSL */
10662 OPENSSL_VERSION_TEXT
10663 "\nRunning on OpenSSL version : %s%s",
Rosen Penev68185952018-12-14 08:47:02 -080010664 OpenSSL_version(OPENSSL_VERSION),
Willy Tarreau1d158ab2019-05-09 13:41:45 +020010665 ((OPENSSL_VERSION_NUMBER ^ OpenSSL_version_num()) >> 8) ? " (VERSIONS DIFFER!)" : "");
Willy Tarreauc2c0b612016-12-21 19:23:20 +010010666#endif
10667 memprintf(&ptr, "%s\nOpenSSL library supports TLS extensions : "
Willy Tarreau9a1ab082019-05-09 13:26:41 +020010668#if HA_OPENSSL_VERSION_NUMBER < 0x00907000L
Willy Tarreauc2c0b612016-12-21 19:23:20 +010010669 "no (library version too old)"
10670#elif defined(OPENSSL_NO_TLSEXT)
10671 "no (disabled via OPENSSL_NO_TLSEXT)"
10672#else
10673 "yes"
10674#endif
10675 "", ptr);
10676
10677 memprintf(&ptr, "%s\nOpenSSL library supports SNI : "
10678#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
10679 "yes"
10680#else
10681#ifdef OPENSSL_NO_TLSEXT
10682 "no (because of OPENSSL_NO_TLSEXT)"
10683#else
10684 "no (version might be too old, 0.9.8f min needed)"
10685#endif
10686#endif
10687 "", ptr);
10688
Emmanuel Hocdetf80bc242017-07-12 14:25:38 +020010689 memprintf(&ptr, "%s\nOpenSSL library supports :", ptr);
10690 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
10691 if (methodVersions[i].option)
10692 memprintf(&ptr, "%s %s", ptr, methodVersions[i].name);
Emmanuel Hocdet50e25e12017-03-24 15:20:03 +010010693
Willy Tarreauc2c0b612016-12-21 19:23:20 +010010694 hap_register_build_opts(ptr, 1);
Willy Tarreau80713382018-11-26 10:19:54 +010010695}
Willy Tarreauc2c0b612016-12-21 19:23:20 +010010696
Willy Tarreau80713382018-11-26 10:19:54 +010010697INITCALL0(STG_REGISTER, ssl_register_build_options);
Remi Gacogne4f902b82015-05-28 16:23:00 +020010698
Emeric Brun46591952012-05-18 15:47:34 +020010699
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020010700#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +000010701void ssl_free_engines(void) {
10702 struct ssl_engine_list *wl, *wlb;
10703 /* free up engine list */
10704 list_for_each_entry_safe(wl, wlb, &openssl_engines, list) {
10705 ENGINE_finish(wl->e);
10706 ENGINE_free(wl->e);
10707 LIST_DEL(&wl->list);
10708 free(wl);
10709 }
10710}
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020010711#endif
Christopher Faulet31af49d2015-06-09 17:29:50 +020010712
Remi Gacogned3a23c32015-05-28 16:39:47 +020010713#ifndef OPENSSL_NO_DH
Grant Zhang872f9c22017-01-21 01:10:18 +000010714void ssl_free_dh(void) {
10715 if (local_dh_1024) {
10716 DH_free(local_dh_1024);
10717 local_dh_1024 = NULL;
10718 }
10719 if (local_dh_2048) {
10720 DH_free(local_dh_2048);
10721 local_dh_2048 = NULL;
10722 }
10723 if (local_dh_4096) {
10724 DH_free(local_dh_4096);
10725 local_dh_4096 = NULL;
10726 }
Remi Gacogne47783ef2015-05-29 15:53:22 +020010727 if (global_dh) {
10728 DH_free(global_dh);
10729 global_dh = NULL;
10730 }
Grant Zhang872f9c22017-01-21 01:10:18 +000010731}
10732#endif
10733
10734__attribute__((destructor))
10735static void __ssl_sock_deinit(void)
10736{
10737#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Emeric Brun821bb9b2017-06-15 16:37:39 +020010738 if (ssl_ctx_lru_tree) {
10739 lru64_destroy(ssl_ctx_lru_tree);
Christopher Faulet2a944ee2017-11-07 10:42:54 +010010740 HA_RWLOCK_DESTROY(&ssl_ctx_lru_rwlock);
Emeric Brun821bb9b2017-06-15 16:37:39 +020010741 }
Remi Gacogned3a23c32015-05-28 16:39:47 +020010742#endif
10743
Willy Tarreau5db847a2019-05-09 14:13:35 +020010744#if (HA_OPENSSL_VERSION_NUMBER < 0x10100000L)
Remi Gacogned3a23c32015-05-28 16:39:47 +020010745 ERR_remove_state(0);
10746 ERR_free_strings();
10747
10748 EVP_cleanup();
Rosen Penev68185952018-12-14 08:47:02 -080010749#endif
Remi Gacogned3a23c32015-05-28 16:39:47 +020010750
Willy Tarreau5db847a2019-05-09 14:13:35 +020010751#if (HA_OPENSSL_VERSION_NUMBER >= 0x00907000L) && (HA_OPENSSL_VERSION_NUMBER < 0x10100000L)
Remi Gacogned3a23c32015-05-28 16:39:47 +020010752 CRYPTO_cleanup_all_ex_data();
10753#endif
Olivier Houcharda8955d52019-04-07 22:00:38 +020010754 BIO_meth_free(ha_meth);
Remi Gacogned3a23c32015-05-28 16:39:47 +020010755}
10756
10757
Emeric Brun46591952012-05-18 15:47:34 +020010758/*
10759 * Local variables:
10760 * c-indent-level: 8
10761 * c-basic-offset: 8
10762 * End:
10763 */