blob: 65f070e585cef2906f5b96fc82b9c2ddd5819a04 [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>
Olivier Houchardccaa7de2017-10-02 11:51:03 +020080#include <proto/proto_http.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 */
Olivier Houchardf6715e72019-12-19 15:02:39 +0100220 struct buffer early_buf; /* buffer to store the early data received */
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +0100221 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
356
357
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;
Willy Tarreau838379a2021-03-02 19:32:39 +0100458 fprintf(stderr, "fd[%#x] OpenSSL error[0x%lx] %s: %s\n",
459 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));
Remi Tricot-Le Bretone5759bd2021-05-12 17:45:21 +0200492 if (!el)
493 goto fail_alloc;
Grant Zhang872f9c22017-01-21 01:10:18 +0000494 el->e = engine;
495 LIST_ADD(&openssl_engines, &el->list);
Emeric Brunece0c332017-12-06 13:51:49 +0100496 nb_engines++;
497 if (global_ssl.async)
498 global.ssl_used_async_engines = nb_engines;
Grant Zhang872f9c22017-01-21 01:10:18 +0000499 return 0;
500
Remi Tricot-Le Bretone5759bd2021-05-12 17:45:21 +0200501fail_alloc:
Grant Zhang872f9c22017-01-21 01:10:18 +0000502fail_set_method:
503 /* release the functional reference from ENGINE_init() */
504 ENGINE_finish(engine);
505
506fail_init:
507 /* release the structural reference from ENGINE_by_id() */
508 ENGINE_free(engine);
509
510fail_get:
511 return err_code;
512}
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +0200513#endif
Grant Zhang872f9c22017-01-21 01:10:18 +0000514
Willy Tarreau5db847a2019-05-09 14:13:35 +0200515#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brun3854e012017-05-17 20:42:48 +0200516/*
517 * openssl async fd handler
518 */
Emeric Brund0e095c2019-04-19 17:15:28 +0200519void ssl_async_fd_handler(int fd)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000520{
Olivier Houchardea8dd942019-05-20 14:02:16 +0200521 struct ssl_sock_ctx *ctx = fdtab[fd].owner;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000522
Emeric Brun3854e012017-05-17 20:42:48 +0200523 /* fd is an async enfine fd, we must stop
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000524 * to poll this fd until it is requested
525 */
Emeric Brunbbc16542017-06-02 15:54:06 +0000526 fd_stop_recv(fd);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000527 fd_cant_recv(fd);
528
529 /* crypto engine is available, let's notify the associated
530 * connection that it can pursue its processing.
531 */
Olivier Houchard03abf2d2019-05-28 10:12:02 +0200532 ssl_sock_io_cb(NULL, ctx, 0);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000533}
534
Emeric Brun3854e012017-05-17 20:42:48 +0200535/*
536 * openssl async delayed SSL_free handler
537 */
Emeric Brund0e095c2019-04-19 17:15:28 +0200538void ssl_async_fd_free(int fd)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000539{
540 SSL *ssl = fdtab[fd].owner;
Emeric Brun3854e012017-05-17 20:42:48 +0200541 OSSL_ASYNC_FD all_fd[32];
542 size_t num_all_fds = 0;
543 int i;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000544
Emeric Brun3854e012017-05-17 20:42:48 +0200545 /* We suppose that the async job for a same SSL *
546 * are serialized. So if we are awake it is
547 * because the running job has just finished
548 * and we can remove all async fds safely
549 */
550 SSL_get_all_async_fds(ssl, NULL, &num_all_fds);
551 if (num_all_fds > 32) {
552 send_log(NULL, LOG_EMERG, "haproxy: openssl returns too many async fds. It seems a bug. Process may crash\n");
553 return;
554 }
555
556 SSL_get_all_async_fds(ssl, all_fd, &num_all_fds);
557 for (i=0 ; i < num_all_fds ; i++)
558 fd_remove(all_fd[i]);
559
560 /* Now we can safely call SSL_free, no more pending job in engines */
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000561 SSL_free(ssl);
Olivier Houchard2be5a4c2019-03-08 18:54:43 +0100562 _HA_ATOMIC_SUB(&sslconns, 1);
563 _HA_ATOMIC_SUB(&jobs, 1);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000564}
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000565/*
Emeric Brun3854e012017-05-17 20:42:48 +0200566 * function used to manage a returned SSL_ERROR_WANT_ASYNC
567 * and enable/disable polling for async fds
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000568 */
Olivier Houchardea8dd942019-05-20 14:02:16 +0200569static inline void ssl_async_process_fds(struct ssl_sock_ctx *ctx)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000570{
Willy Tarreaua9786b62018-01-25 07:22:13 +0100571 OSSL_ASYNC_FD add_fd[32];
Emeric Brun3854e012017-05-17 20:42:48 +0200572 OSSL_ASYNC_FD del_fd[32];
Olivier Houchardea8dd942019-05-20 14:02:16 +0200573 SSL *ssl = ctx->ssl;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000574 size_t num_add_fds = 0;
575 size_t num_del_fds = 0;
Emeric Brun3854e012017-05-17 20:42:48 +0200576 int i;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000577
578 SSL_get_changed_async_fds(ssl, NULL, &num_add_fds, NULL,
579 &num_del_fds);
Emeric Brun3854e012017-05-17 20:42:48 +0200580 if (num_add_fds > 32 || num_del_fds > 32) {
581 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 +0000582 return;
583 }
584
Emeric Brun3854e012017-05-17 20:42:48 +0200585 SSL_get_changed_async_fds(ssl, add_fd, &num_add_fds, del_fd, &num_del_fds);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000586
Emeric Brun3854e012017-05-17 20:42:48 +0200587 /* We remove unused fds from the fdtab */
588 for (i=0 ; i < num_del_fds ; i++)
589 fd_remove(del_fd[i]);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000590
Emeric Brun3854e012017-05-17 20:42:48 +0200591 /* We add new fds to the fdtab */
592 for (i=0 ; i < num_add_fds ; i++) {
Olivier Houchardea8dd942019-05-20 14:02:16 +0200593 fd_insert(add_fd[i], ctx, ssl_async_fd_handler, tid_bit);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000594 }
595
Emeric Brun3854e012017-05-17 20:42:48 +0200596 num_add_fds = 0;
597 SSL_get_all_async_fds(ssl, NULL, &num_add_fds);
598 if (num_add_fds > 32) {
599 send_log(NULL, LOG_EMERG, "haproxy: openssl returns too many async fds. It seems a bug. Process may crash\n");
600 return;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000601 }
Emeric Brun3854e012017-05-17 20:42:48 +0200602
603 /* We activate the polling for all known async fds */
604 SSL_get_all_async_fds(ssl, add_fd, &num_add_fds);
Emeric Brunce9e01c2017-05-31 10:02:53 +0000605 for (i=0 ; i < num_add_fds ; i++) {
Emeric Brun3854e012017-05-17 20:42:48 +0200606 fd_want_recv(add_fd[i]);
Emeric Brunce9e01c2017-05-31 10:02:53 +0000607 /* To ensure that the fd cache won't be used
608 * We'll prefer to catch a real RD event
609 * because handling an EAGAIN on this fd will
610 * result in a context switch and also
611 * some engines uses a fd in blocking mode.
612 */
613 fd_cant_recv(add_fd[i]);
614 }
Emeric Brun3854e012017-05-17 20:42:48 +0200615
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000616}
617#endif
618
William Lallemandc33d83d2019-10-14 14:14:59 +0200619#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
Emeric Brun4f3c87a2014-06-20 15:46:13 +0200620/*
621 * This function returns the number of seconds elapsed
622 * since the Epoch, 1970-01-01 00:00:00 +0000 (UTC) and the
623 * date presented un ASN1_GENERALIZEDTIME.
624 *
625 * In parsing error case, it returns -1.
626 */
627static long asn1_generalizedtime_to_epoch(ASN1_GENERALIZEDTIME *d)
628{
629 long epoch;
630 char *p, *end;
631 const unsigned short month_offset[12] = {
632 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
633 };
Remi Tricot-Le Breton2f216542021-06-09 17:16:18 +0200634 unsigned long year, month;
Emeric Brun4f3c87a2014-06-20 15:46:13 +0200635
636 if (!d || (d->type != V_ASN1_GENERALIZEDTIME)) return -1;
637
638 p = (char *)d->data;
639 end = p + d->length;
640
641 if (end - p < 4) return -1;
642 year = 1000 * (p[0] - '0') + 100 * (p[1] - '0') + 10 * (p[2] - '0') + p[3] - '0';
643 p += 4;
644 if (end - p < 2) return -1;
645 month = 10 * (p[0] - '0') + p[1] - '0';
646 if (month < 1 || month > 12) return -1;
647 /* Compute the number of seconds since 1 jan 1970 and the beginning of current month
648 We consider leap years and the current month (<marsh or not) */
649 epoch = ( ((year - 1970) * 365)
650 + ((year - (month < 3)) / 4 - (year - (month < 3)) / 100 + (year - (month < 3)) / 400)
651 - ((1970 - 1) / 4 - (1970 - 1) / 100 + (1970 - 1) / 400)
652 + month_offset[month-1]
653 ) * 24 * 60 * 60;
654 p += 2;
655 if (end - p < 2) return -1;
656 /* Add the number of seconds of completed days of current month */
657 epoch += (10 * (p[0] - '0') + p[1] - '0' - 1) * 24 * 60 * 60;
658 p += 2;
659 if (end - p < 2) return -1;
660 /* Add the completed hours of the current day */
661 epoch += (10 * (p[0] - '0') + p[1] - '0') * 60 * 60;
662 p += 2;
663 if (end - p < 2) return -1;
664 /* Add the completed minutes of the current hour */
665 epoch += (10 * (p[0] - '0') + p[1] - '0') * 60;
666 p += 2;
667 if (p == end) return -1;
668 /* Test if there is available seconds */
669 if (p[0] < '0' || p[0] > '9')
670 goto nosec;
671 if (end - p < 2) return -1;
672 /* Add the seconds of the current minute */
673 epoch += 10 * (p[0] - '0') + p[1] - '0';
674 p += 2;
675 if (p == end) return -1;
676 /* Ignore seconds float part if present */
677 if (p[0] == '.') {
678 do {
679 if (++p == end) return -1;
680 } while (p[0] >= '0' && p[0] <= '9');
681 }
682
683nosec:
684 if (p[0] == 'Z') {
685 if (end - p != 1) return -1;
686 return epoch;
687 }
688 else if (p[0] == '+') {
689 if (end - p != 5) return -1;
690 /* Apply timezone offset */
Frederik Deweerdt953917a2017-10-16 07:37:31 -0700691 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 +0200692 }
693 else if (p[0] == '-') {
694 if (end - p != 5) return -1;
695 /* Apply timezone offset */
Frederik Deweerdt953917a2017-10-16 07:37:31 -0700696 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 +0200697 }
698
699 return -1;
700}
701
William Lallemandc33d83d2019-10-14 14:14:59 +0200702/*
703 * struct alignment works here such that the key.key is the same as key_data
704 * Do not change the placement of key_data
705 */
706struct certificate_ocsp {
707 struct ebmb_node key;
708 unsigned char key_data[OCSP_MAX_CERTID_ASN1_LENGTH];
709 struct buffer response;
710 long expire;
711};
712
713struct ocsp_cbk_arg {
714 int is_single;
715 int single_kt;
716 union {
717 struct certificate_ocsp *s_ocsp;
718 /*
719 * m_ocsp will have multiple entries dependent on key type
720 * Entry 0 - DSA
721 * Entry 1 - ECDSA
722 * Entry 2 - RSA
723 */
724 struct certificate_ocsp *m_ocsp[SSL_SOCK_NUM_KEYTYPES];
725 };
726};
727
Emeric Brun1d3865b2014-06-20 15:37:32 +0200728static struct eb_root cert_ocsp_tree = EB_ROOT_UNIQUE;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200729
730/* This function starts to check if the OCSP response (in DER format) contained
731 * in chunk 'ocsp_response' is valid (else exits on error).
732 * If 'cid' is not NULL, it will be compared to the OCSP certificate ID
733 * contained in the OCSP Response and exits on error if no match.
734 * If it's a valid OCSP Response:
735 * If 'ocsp' is not NULL, the chunk is copied in the OCSP response's container
736 * pointed by 'ocsp'.
737 * If 'ocsp' is NULL, the function looks up into the OCSP response's
738 * containers tree (using as index the ASN1 form of the OCSP Certificate ID extracted
739 * from the response) and exits on error if not found. Finally, If an OCSP response is
740 * already present in the container, it will be overwritten.
741 *
742 * Note: OCSP response containing more than one OCSP Single response is not
743 * considered valid.
744 *
745 * Returns 0 on success, 1 in error case.
746 */
Willy Tarreau83061a82018-07-13 11:56:34 +0200747static int ssl_sock_load_ocsp_response(struct buffer *ocsp_response,
748 struct certificate_ocsp *ocsp,
749 OCSP_CERTID *cid, char **err)
Emeric Brun4147b2e2014-06-16 18:36:30 +0200750{
751 OCSP_RESPONSE *resp;
752 OCSP_BASICRESP *bs = NULL;
753 OCSP_SINGLERESP *sr;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200754 OCSP_CERTID *id;
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200755 unsigned char *p = (unsigned char *) ocsp_response->area;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200756 int rc , count_sr;
Emeric Brun13a6b482014-06-20 15:44:34 +0200757 ASN1_GENERALIZEDTIME *revtime, *thisupd, *nextupd = NULL;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200758 int reason;
759 int ret = 1;
760
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200761 resp = d2i_OCSP_RESPONSE(NULL, (const unsigned char **)&p,
762 ocsp_response->data);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200763 if (!resp) {
764 memprintf(err, "Unable to parse OCSP response");
765 goto out;
766 }
767
768 rc = OCSP_response_status(resp);
769 if (rc != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
770 memprintf(err, "OCSP response status not successful");
771 goto out;
772 }
773
774 bs = OCSP_response_get1_basic(resp);
775 if (!bs) {
776 memprintf(err, "Failed to get basic response from OCSP Response");
777 goto out;
778 }
779
780 count_sr = OCSP_resp_count(bs);
781 if (count_sr > 1) {
782 memprintf(err, "OCSP response ignored because contains multiple single responses (%d)", count_sr);
783 goto out;
784 }
785
786 sr = OCSP_resp_get0(bs, 0);
787 if (!sr) {
788 memprintf(err, "Failed to get OCSP single response");
789 goto out;
790 }
791
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200792 id = (OCSP_CERTID*)OCSP_SINGLERESP_get0_id(sr);
793
Emeric Brun4147b2e2014-06-16 18:36:30 +0200794 rc = OCSP_single_get0_status(sr, &reason, &revtime, &thisupd, &nextupd);
Emmanuel Hocdetef607052017-10-24 14:57:16 +0200795 if (rc != V_OCSP_CERTSTATUS_GOOD && rc != V_OCSP_CERTSTATUS_REVOKED) {
Emmanuel Hocdet872085c2017-10-10 15:18:52 +0200796 memprintf(err, "OCSP single response: certificate status is unknown");
Emeric Brun4147b2e2014-06-16 18:36:30 +0200797 goto out;
798 }
799
Emeric Brun13a6b482014-06-20 15:44:34 +0200800 if (!nextupd) {
801 memprintf(err, "OCSP single response: missing nextupdate");
802 goto out;
803 }
804
Emeric Brunc8b27b62014-06-19 14:16:17 +0200805 rc = OCSP_check_validity(thisupd, nextupd, OCSP_MAX_RESPONSE_TIME_SKEW, -1);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200806 if (!rc) {
807 memprintf(err, "OCSP single response: no longer valid.");
808 goto out;
809 }
810
811 if (cid) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200812 if (OCSP_id_cmp(id, cid)) {
Emeric Brun4147b2e2014-06-16 18:36:30 +0200813 memprintf(err, "OCSP single response: Certificate ID does not match certificate and issuer");
814 goto out;
815 }
816 }
817
818 if (!ocsp) {
819 unsigned char key[OCSP_MAX_CERTID_ASN1_LENGTH];
820 unsigned char *p;
821
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200822 rc = i2d_OCSP_CERTID(id, NULL);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200823 if (!rc) {
824 memprintf(err, "OCSP single response: Unable to encode Certificate ID");
825 goto out;
826 }
827
828 if (rc > OCSP_MAX_CERTID_ASN1_LENGTH) {
829 memprintf(err, "OCSP single response: Certificate ID too long");
830 goto out;
831 }
832
833 p = key;
834 memset(key, 0, OCSP_MAX_CERTID_ASN1_LENGTH);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200835 i2d_OCSP_CERTID(id, &p);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200836 ocsp = (struct certificate_ocsp *)ebmb_lookup(&cert_ocsp_tree, key, OCSP_MAX_CERTID_ASN1_LENGTH);
837 if (!ocsp) {
838 memprintf(err, "OCSP single response: Certificate ID does not match any certificate or issuer");
839 goto out;
840 }
841 }
842
843 /* According to comments on "chunk_dup", the
844 previous chunk buffer will be freed */
845 if (!chunk_dup(&ocsp->response, ocsp_response)) {
846 memprintf(err, "OCSP response: Memory allocation error");
847 goto out;
848 }
849
Emeric Brun4f3c87a2014-06-20 15:46:13 +0200850 ocsp->expire = asn1_generalizedtime_to_epoch(nextupd) - OCSP_MAX_RESPONSE_TIME_SKEW;
Remi Tricot-Le Breton2f216542021-06-09 17:16:18 +0200851 if (ocsp->expire < 0) {
852 memprintf(err, "OCSP single response: Invalid \"Next Update\" time");
853 goto out;
854 }
Emeric Brun4f3c87a2014-06-20 15:46:13 +0200855
Emeric Brun4147b2e2014-06-16 18:36:30 +0200856 ret = 0;
857out:
Janusz Dziemidowicz8d710492017-03-08 16:59:41 +0100858 ERR_clear_error();
859
Emeric Brun4147b2e2014-06-16 18:36:30 +0200860 if (bs)
861 OCSP_BASICRESP_free(bs);
862
863 if (resp)
864 OCSP_RESPONSE_free(resp);
865
866 return ret;
867}
868/*
869 * External function use to update the OCSP response in the OCSP response's
870 * containers tree. The chunk 'ocsp_response' must contain the OCSP response
871 * to update in DER format.
872 *
873 * Returns 0 on success, 1 in error case.
874 */
Willy Tarreau83061a82018-07-13 11:56:34 +0200875int ssl_sock_update_ocsp_response(struct buffer *ocsp_response, char **err)
Emeric Brun4147b2e2014-06-16 18:36:30 +0200876{
877 return ssl_sock_load_ocsp_response(ocsp_response, NULL, NULL, err);
878}
879
880/*
881 * This function load the OCSP Resonse in DER format contained in file at
882 * path 'ocsp_path' and call 'ssl_sock_load_ocsp_response'
883 *
884 * Returns 0 on success, 1 in error case.
885 */
886static int ssl_sock_load_ocsp_response_from_file(const char *ocsp_path, struct certificate_ocsp *ocsp, OCSP_CERTID *cid, char **err)
887{
888 int fd = -1;
889 int r = 0;
890 int ret = 1;
891
892 fd = open(ocsp_path, O_RDONLY);
893 if (fd == -1) {
894 memprintf(err, "Error opening OCSP response file");
895 goto end;
896 }
897
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200898 trash.data = 0;
899 while (trash.data < trash.size) {
900 r = read(fd, trash.area + trash.data, trash.size - trash.data);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200901 if (r < 0) {
902 if (errno == EINTR)
903 continue;
904
905 memprintf(err, "Error reading OCSP response from file");
906 goto end;
907 }
908 else if (r == 0) {
909 break;
910 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200911 trash.data += r;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200912 }
913
914 close(fd);
915 fd = -1;
916
917 ret = ssl_sock_load_ocsp_response(&trash, ocsp, cid, err);
918end:
919 if (fd != -1)
920 close(fd);
921
922 return ret;
923}
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100924#endif
Emeric Brun4147b2e2014-06-16 18:36:30 +0200925
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100926#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
927static 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)
928{
Christopher Faulet16f45c82018-02-16 11:23:49 +0100929 struct tls_keys_ref *ref;
Emeric Brun9e754772019-01-10 17:51:55 +0100930 union tls_sess_key *keys;
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100931 struct connection *conn;
932 int head;
933 int i;
Christopher Faulet16f45c82018-02-16 11:23:49 +0100934 int ret = -1; /* error by default */
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100935
Thierry FOURNIER28962c92018-06-17 21:37:05 +0200936 conn = SSL_get_ex_data(s, ssl_app_data_index);
Willy Tarreau07d94e42018-09-20 10:57:52 +0200937 ref = __objt_listener(conn->target)->bind_conf->keys_ref;
Christopher Faulet16f45c82018-02-16 11:23:49 +0100938 HA_RWLOCK_RDLOCK(TLSKEYS_REF_LOCK, &ref->lock);
939
940 keys = ref->tlskeys;
941 head = ref->tls_ticket_enc_index;
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100942
943 if (enc) {
944 memcpy(key_name, keys[head].name, 16);
945
946 if(!RAND_pseudo_bytes(iv, EVP_MAX_IV_LENGTH))
Christopher Faulet16f45c82018-02-16 11:23:49 +0100947 goto end;
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100948
Emeric Brun9e754772019-01-10 17:51:55 +0100949 if (ref->key_size_bits == 128) {
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100950
Emeric Brun9e754772019-01-10 17:51:55 +0100951 if(!EVP_EncryptInit_ex(ectx, EVP_aes_128_cbc(), NULL, keys[head].key_128.aes_key, iv))
952 goto end;
953
Willy Tarreau9356dac2019-05-10 09:22:53 +0200954 HMAC_Init_ex(hctx, keys[head].key_128.hmac_key, 16, TLS_TICKET_HASH_FUNCT(), NULL);
Emeric Brun9e754772019-01-10 17:51:55 +0100955 ret = 1;
956 }
957 else if (ref->key_size_bits == 256 ) {
958
959 if(!EVP_EncryptInit_ex(ectx, EVP_aes_256_cbc(), NULL, keys[head].key_256.aes_key, iv))
960 goto end;
961
Willy Tarreau9356dac2019-05-10 09:22:53 +0200962 HMAC_Init_ex(hctx, keys[head].key_256.hmac_key, 32, TLS_TICKET_HASH_FUNCT(), NULL);
Emeric Brun9e754772019-01-10 17:51:55 +0100963 ret = 1;
964 }
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100965 } else {
966 for (i = 0; i < TLS_TICKETS_NO; i++) {
967 if (!memcmp(key_name, keys[(head + i) % TLS_TICKETS_NO].name, 16))
968 goto found;
969 }
Christopher Faulet16f45c82018-02-16 11:23:49 +0100970 ret = 0;
971 goto end;
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100972
Christopher Faulet16f45c82018-02-16 11:23:49 +0100973 found:
Emeric Brun9e754772019-01-10 17:51:55 +0100974 if (ref->key_size_bits == 128) {
Willy Tarreau9356dac2019-05-10 09:22:53 +0200975 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 +0100976 if(!EVP_DecryptInit_ex(ectx, EVP_aes_128_cbc(), NULL, keys[(head + i) % TLS_TICKETS_NO].key_128.aes_key, iv))
977 goto end;
978 /* 2 for key renewal, 1 if current key is still valid */
979 ret = i ? 2 : 1;
980 }
981 else if (ref->key_size_bits == 256) {
Willy Tarreau9356dac2019-05-10 09:22:53 +0200982 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 +0100983 if(!EVP_DecryptInit_ex(ectx, EVP_aes_256_cbc(), NULL, keys[(head + i) % TLS_TICKETS_NO].key_256.aes_key, iv))
984 goto end;
985 /* 2 for key renewal, 1 if current key is still valid */
986 ret = i ? 2 : 1;
987 }
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100988 }
Emeric Brun9e754772019-01-10 17:51:55 +0100989
Christopher Faulet16f45c82018-02-16 11:23:49 +0100990 end:
991 HA_RWLOCK_RDUNLOCK(TLSKEYS_REF_LOCK, &ref->lock);
992 return ret;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200993}
994
995struct tls_keys_ref *tlskeys_ref_lookup(const char *filename)
996{
997 struct tls_keys_ref *ref;
998
999 list_for_each_entry(ref, &tlskeys_reference, list)
1000 if (ref->filename && strcmp(filename, ref->filename) == 0)
1001 return ref;
1002 return NULL;
1003}
1004
1005struct tls_keys_ref *tlskeys_ref_lookupid(int unique_id)
1006{
1007 struct tls_keys_ref *ref;
1008
1009 list_for_each_entry(ref, &tlskeys_reference, list)
1010 if (ref->unique_id == unique_id)
1011 return ref;
1012 return NULL;
1013}
1014
Emeric Brun9e754772019-01-10 17:51:55 +01001015/* Update the key into ref: if keysize doesnt
1016 * match existing ones, this function returns -1
1017 * else it returns 0 on success.
1018 */
1019int ssl_sock_update_tlskey_ref(struct tls_keys_ref *ref,
Willy Tarreau83061a82018-07-13 11:56:34 +02001020 struct buffer *tlskey)
Christopher Faulet16f45c82018-02-16 11:23:49 +01001021{
Emeric Brun9e754772019-01-10 17:51:55 +01001022 if (ref->key_size_bits == 128) {
1023 if (tlskey->data != sizeof(struct tls_sess_key_128))
1024 return -1;
1025 }
1026 else if (ref->key_size_bits == 256) {
1027 if (tlskey->data != sizeof(struct tls_sess_key_256))
1028 return -1;
1029 }
1030 else
1031 return -1;
1032
Christopher Faulet16f45c82018-02-16 11:23:49 +01001033 HA_RWLOCK_WRLOCK(TLSKEYS_REF_LOCK, &ref->lock);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001034 memcpy((char *) (ref->tlskeys + ((ref->tls_ticket_enc_index + 2) % TLS_TICKETS_NO)),
1035 tlskey->area, tlskey->data);
Christopher Faulet16f45c82018-02-16 11:23:49 +01001036 ref->tls_ticket_enc_index = (ref->tls_ticket_enc_index + 1) % TLS_TICKETS_NO;
1037 HA_RWLOCK_WRUNLOCK(TLSKEYS_REF_LOCK, &ref->lock);
Emeric Brun9e754772019-01-10 17:51:55 +01001038
1039 return 0;
Christopher Faulet16f45c82018-02-16 11:23:49 +01001040}
1041
Willy Tarreau83061a82018-07-13 11:56:34 +02001042int ssl_sock_update_tlskey(char *filename, struct buffer *tlskey, char **err)
Christopher Faulet16f45c82018-02-16 11:23:49 +01001043{
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02001044 struct tls_keys_ref *ref = tlskeys_ref_lookup(filename);
1045
1046 if(!ref) {
1047 memprintf(err, "Unable to locate the referenced filename: %s", filename);
1048 return 1;
1049 }
Emeric Brun9e754772019-01-10 17:51:55 +01001050 if (ssl_sock_update_tlskey_ref(ref, tlskey) < 0) {
1051 memprintf(err, "Invalid key size");
1052 return 1;
1053 }
1054
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02001055 return 0;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01001056}
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02001057
1058/* This function finalize the configuration parsing. Its set all the
Willy Tarreaud1c57502016-12-22 22:46:15 +01001059 * automatic ids. It's called just after the basic checks. It returns
1060 * 0 on success otherwise ERR_*.
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02001061 */
Willy Tarreaud1c57502016-12-22 22:46:15 +01001062static int tlskeys_finalize_config(void)
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02001063{
1064 int i = 0;
1065 struct tls_keys_ref *ref, *ref2, *ref3;
1066 struct list tkr = LIST_HEAD_INIT(tkr);
1067
1068 list_for_each_entry(ref, &tlskeys_reference, list) {
1069 if (ref->unique_id == -1) {
1070 /* Look for the first free id. */
1071 while (1) {
1072 list_for_each_entry(ref2, &tlskeys_reference, list) {
1073 if (ref2->unique_id == i) {
1074 i++;
1075 break;
1076 }
1077 }
1078 if (&ref2->list == &tlskeys_reference)
1079 break;
1080 }
1081
1082 /* Uses the unique id and increment it for the next entry. */
1083 ref->unique_id = i;
1084 i++;
1085 }
1086 }
1087
1088 /* This sort the reference list by id. */
1089 list_for_each_entry_safe(ref, ref2, &tlskeys_reference, list) {
1090 LIST_DEL(&ref->list);
1091 list_for_each_entry(ref3, &tkr, list) {
1092 if (ref->unique_id < ref3->unique_id) {
1093 LIST_ADDQ(&ref3->list, &ref->list);
1094 break;
1095 }
1096 }
1097 if (&ref3->list == &tkr)
1098 LIST_ADDQ(&tkr, &ref->list);
1099 }
1100
1101 /* swap root */
1102 LIST_ADD(&tkr, &tlskeys_reference);
1103 LIST_DEL(&tkr);
Willy Tarreaud1c57502016-12-22 22:46:15 +01001104 return 0;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02001105}
Nenad Merdanovic05552d42015-02-27 19:56:49 +01001106#endif /* SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB */
1107
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01001108#ifndef OPENSSL_NO_OCSP
yanbzhube2774d2015-12-10 15:07:30 -05001109int ssl_sock_get_ocsp_arg_kt_index(int evp_keytype)
1110{
1111 switch (evp_keytype) {
1112 case EVP_PKEY_RSA:
1113 return 2;
1114 case EVP_PKEY_DSA:
1115 return 0;
1116 case EVP_PKEY_EC:
1117 return 1;
1118 }
1119
1120 return -1;
1121}
1122
Emeric Brun4147b2e2014-06-16 18:36:30 +02001123/*
1124 * Callback used to set OCSP status extension content in server hello.
1125 */
1126int ssl_sock_ocsp_stapling_cbk(SSL *ssl, void *arg)
1127{
yanbzhube2774d2015-12-10 15:07:30 -05001128 struct certificate_ocsp *ocsp;
1129 struct ocsp_cbk_arg *ocsp_arg;
1130 char *ssl_buf;
1131 EVP_PKEY *ssl_pkey;
1132 int key_type;
1133 int index;
1134
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02001135 ocsp_arg = arg;
yanbzhube2774d2015-12-10 15:07:30 -05001136
1137 ssl_pkey = SSL_get_privatekey(ssl);
1138 if (!ssl_pkey)
1139 return SSL_TLSEXT_ERR_NOACK;
1140
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001141 key_type = EVP_PKEY_base_id(ssl_pkey);
yanbzhube2774d2015-12-10 15:07:30 -05001142
1143 if (ocsp_arg->is_single && ocsp_arg->single_kt == key_type)
1144 ocsp = ocsp_arg->s_ocsp;
1145 else {
1146 /* For multiple certs per context, we have to find the correct OCSP response based on
1147 * the certificate type
1148 */
1149 index = ssl_sock_get_ocsp_arg_kt_index(key_type);
1150
1151 if (index < 0)
1152 return SSL_TLSEXT_ERR_NOACK;
1153
1154 ocsp = ocsp_arg->m_ocsp[index];
1155
1156 }
Emeric Brun4147b2e2014-06-16 18:36:30 +02001157
1158 if (!ocsp ||
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001159 !ocsp->response.area ||
1160 !ocsp->response.data ||
Emeric Brun4f3c87a2014-06-20 15:46:13 +02001161 (ocsp->expire < now.tv_sec))
Emeric Brun4147b2e2014-06-16 18:36:30 +02001162 return SSL_TLSEXT_ERR_NOACK;
1163
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001164 ssl_buf = OPENSSL_malloc(ocsp->response.data);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001165 if (!ssl_buf)
1166 return SSL_TLSEXT_ERR_NOACK;
1167
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001168 memcpy(ssl_buf, ocsp->response.area, ocsp->response.data);
1169 SSL_set_tlsext_status_ocsp_resp(ssl, ssl_buf, ocsp->response.data);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001170
1171 return SSL_TLSEXT_ERR_OK;
1172}
1173
1174/*
1175 * This function enables the handling of OCSP status extension on 'ctx' if a
1176 * file name 'cert_path' suffixed using ".ocsp" is present.
1177 * To enable OCSP status extension, the issuer's certificate is mandatory.
1178 * It should be present in the certificate's extra chain builded from file
1179 * 'cert_path'. If not found, the issuer certificate is loaded from a file
1180 * named 'cert_path' suffixed using '.issuer'.
1181 *
1182 * In addition, ".ocsp" file content is loaded as a DER format of an OCSP
1183 * response. If file is empty or content is not a valid OCSP response,
1184 * OCSP status extension is enabled but OCSP response is ignored (a warning
1185 * is displayed).
1186 *
1187 * Returns 1 if no ".ocsp" file found, 0 if OCSP status extension is
Joseph Herlant017b3da2018-11-15 09:07:59 -08001188 * successfully enabled, or -1 in other error case.
Emeric Brun4147b2e2014-06-16 18:36:30 +02001189 */
1190static int ssl_sock_load_ocsp(SSL_CTX *ctx, const char *cert_path)
1191{
1192
1193 BIO *in = NULL;
1194 X509 *x, *xi = NULL, *issuer = NULL;
1195 STACK_OF(X509) *chain = NULL;
1196 OCSP_CERTID *cid = NULL;
1197 SSL *ssl;
1198 char ocsp_path[MAXPATHLEN+1];
1199 int i, ret = -1;
1200 struct stat st;
1201 struct certificate_ocsp *ocsp = NULL, *iocsp;
1202 char *warn = NULL;
1203 unsigned char *p;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001204 pem_password_cb *passwd_cb;
1205 void *passwd_cb_userdata;
1206 void (*callback) (void);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001207
1208 snprintf(ocsp_path, MAXPATHLEN+1, "%s.ocsp", cert_path);
1209
1210 if (stat(ocsp_path, &st))
1211 return 1;
1212
1213 ssl = SSL_new(ctx);
1214 if (!ssl)
1215 goto out;
1216
1217 x = SSL_get_certificate(ssl);
1218 if (!x)
1219 goto out;
1220
1221 /* Try to lookup for issuer in certificate extra chain */
Emeric Brun4147b2e2014-06-16 18:36:30 +02001222 SSL_CTX_get_extra_chain_certs(ctx, &chain);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001223 for (i = 0; i < sk_X509_num(chain); i++) {
1224 issuer = sk_X509_value(chain, i);
1225 if (X509_check_issued(issuer, x) == X509_V_OK)
1226 break;
1227 else
1228 issuer = NULL;
1229 }
1230
1231 /* If not found try to load issuer from a suffixed file */
1232 if (!issuer) {
1233 char issuer_path[MAXPATHLEN+1];
1234
1235 in = BIO_new(BIO_s_file());
1236 if (!in)
1237 goto out;
1238
1239 snprintf(issuer_path, MAXPATHLEN+1, "%s.issuer", cert_path);
1240 if (BIO_read_filename(in, issuer_path) <= 0)
1241 goto out;
1242
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001243 passwd_cb = SSL_CTX_get_default_passwd_cb(ctx);
1244 passwd_cb_userdata = SSL_CTX_get_default_passwd_cb_userdata(ctx);
1245
1246 xi = PEM_read_bio_X509_AUX(in, NULL, passwd_cb, passwd_cb_userdata);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001247 if (!xi)
1248 goto out;
1249
1250 if (X509_check_issued(xi, x) != X509_V_OK)
1251 goto out;
1252
1253 issuer = xi;
1254 }
1255
1256 cid = OCSP_cert_to_id(0, x, issuer);
1257 if (!cid)
1258 goto out;
1259
1260 i = i2d_OCSP_CERTID(cid, NULL);
1261 if (!i || (i > OCSP_MAX_CERTID_ASN1_LENGTH))
1262 goto out;
1263
Vincent Bernat02779b62016-04-03 13:48:43 +02001264 ocsp = calloc(1, sizeof(*ocsp));
Emeric Brun4147b2e2014-06-16 18:36:30 +02001265 if (!ocsp)
1266 goto out;
1267
1268 p = ocsp->key_data;
1269 i2d_OCSP_CERTID(cid, &p);
1270
1271 iocsp = (struct certificate_ocsp *)ebmb_insert(&cert_ocsp_tree, &ocsp->key, OCSP_MAX_CERTID_ASN1_LENGTH);
1272 if (iocsp == ocsp)
1273 ocsp = NULL;
1274
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001275#ifndef SSL_CTX_get_tlsext_status_cb
1276# define SSL_CTX_get_tlsext_status_cb(ctx, cb) \
1277 *cb = (void (*) (void))ctx->tlsext_status_cb;
1278#endif
1279 SSL_CTX_get_tlsext_status_cb(ctx, &callback);
1280
1281 if (!callback) {
William Lallemanda4864492020-07-31 11:43:20 +02001282 struct ocsp_cbk_arg *cb_arg;
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001283 EVP_PKEY *pkey;
yanbzhube2774d2015-12-10 15:07:30 -05001284
William Lallemanda4864492020-07-31 11:43:20 +02001285 cb_arg = calloc(1, sizeof(*cb_arg));
1286 if (!cb_arg)
1287 goto out;
1288
yanbzhube2774d2015-12-10 15:07:30 -05001289 cb_arg->is_single = 1;
1290 cb_arg->s_ocsp = iocsp;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001291
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001292 pkey = X509_get_pubkey(x);
1293 cb_arg->single_kt = EVP_PKEY_base_id(pkey);
1294 EVP_PKEY_free(pkey);
yanbzhube2774d2015-12-10 15:07:30 -05001295
1296 SSL_CTX_set_tlsext_status_cb(ctx, ssl_sock_ocsp_stapling_cbk);
1297 SSL_CTX_set_tlsext_status_arg(ctx, cb_arg);
1298 } else {
1299 /*
1300 * If the ctx has a status CB, then we have previously set an OCSP staple for this ctx
1301 * Update that cb_arg with the new cert's staple
1302 */
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001303 struct ocsp_cbk_arg *cb_arg;
yanbzhube2774d2015-12-10 15:07:30 -05001304 struct certificate_ocsp *tmp_ocsp;
1305 int index;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001306 int key_type;
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001307 EVP_PKEY *pkey;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001308
1309#ifdef SSL_CTX_get_tlsext_status_arg
1310 SSL_CTX_ctrl(ctx, SSL_CTRL_GET_TLSEXT_STATUS_REQ_CB_ARG, 0, &cb_arg);
1311#else
1312 cb_arg = ctx->tlsext_status_arg;
1313#endif
yanbzhube2774d2015-12-10 15:07:30 -05001314
1315 /*
1316 * The following few lines will convert cb_arg from a single ocsp to multi ocsp
1317 * the order of operations below matter, take care when changing it
1318 */
1319 tmp_ocsp = cb_arg->s_ocsp;
1320 index = ssl_sock_get_ocsp_arg_kt_index(cb_arg->single_kt);
1321 cb_arg->s_ocsp = NULL;
1322 cb_arg->m_ocsp[index] = tmp_ocsp;
1323 cb_arg->is_single = 0;
1324 cb_arg->single_kt = 0;
1325
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001326 pkey = X509_get_pubkey(x);
1327 key_type = EVP_PKEY_base_id(pkey);
1328 EVP_PKEY_free(pkey);
1329
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001330 index = ssl_sock_get_ocsp_arg_kt_index(key_type);
yanbzhube2774d2015-12-10 15:07:30 -05001331 if (index >= 0 && !cb_arg->m_ocsp[index])
1332 cb_arg->m_ocsp[index] = iocsp;
1333
1334 }
Emeric Brun4147b2e2014-06-16 18:36:30 +02001335
1336 ret = 0;
1337
1338 warn = NULL;
1339 if (ssl_sock_load_ocsp_response_from_file(ocsp_path, iocsp, cid, &warn)) {
1340 memprintf(&warn, "Loading '%s': %s. Content will be ignored", ocsp_path, warn ? warn : "failure");
Christopher Faulet767a84b2017-11-24 16:50:31 +01001341 ha_warning("%s.\n", warn);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001342 }
1343
1344out:
1345 if (ssl)
1346 SSL_free(ssl);
1347
1348 if (in)
1349 BIO_free(in);
1350
1351 if (xi)
1352 X509_free(xi);
1353
1354 if (cid)
1355 OCSP_CERTID_free(cid);
1356
1357 if (ocsp)
1358 free(ocsp);
1359
1360 if (warn)
1361 free(warn);
1362
1363
1364 return ret;
1365}
1366
1367#endif
1368
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02001369#ifdef OPENSSL_IS_BORINGSSL
1370static int ssl_sock_set_ocsp_response_from_file(SSL_CTX *ctx, const char *cert_path)
1371{
1372 char ocsp_path[MAXPATHLEN+1];
1373 struct stat st;
1374 int fd = -1, r = 0;
1375
1376 snprintf(ocsp_path, MAXPATHLEN+1, "%s.ocsp", cert_path);
1377 if (stat(ocsp_path, &st))
1378 return 0;
1379
1380 fd = open(ocsp_path, O_RDONLY);
1381 if (fd == -1) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001382 ha_warning("Error opening OCSP response file %s.\n", ocsp_path);
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02001383 return -1;
1384 }
1385
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001386 trash.data = 0;
1387 while (trash.data < trash.size) {
1388 r = read(fd, trash.area + trash.data, trash.size - trash.data);
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02001389 if (r < 0) {
1390 if (errno == EINTR)
1391 continue;
Christopher Faulet767a84b2017-11-24 16:50:31 +01001392 ha_warning("Error reading OCSP response from file %s.\n", ocsp_path);
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02001393 close(fd);
1394 return -1;
1395 }
1396 else if (r == 0) {
1397 break;
1398 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001399 trash.data += r;
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02001400 }
1401 close(fd);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001402 return SSL_CTX_set_ocsp_response(ctx, (const uint8_t *) trash.area,
1403 trash.data);
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02001404}
1405#endif
1406
Willy Tarreau5db847a2019-05-09 14:13:35 +02001407#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001408
1409#define CT_EXTENSION_TYPE 18
1410
1411static int sctl_ex_index = -1;
1412
1413/*
1414 * Try to parse Signed Certificate Timestamp List structure. This function
1415 * makes only basic test if the data seems like SCTL. No signature validation
1416 * is performed.
1417 */
Willy Tarreau83061a82018-07-13 11:56:34 +02001418static int ssl_sock_parse_sctl(struct buffer *sctl)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001419{
1420 int ret = 1;
1421 int len, pos, sct_len;
1422 unsigned char *data;
1423
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001424 if (sctl->data < 2)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001425 goto out;
1426
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001427 data = (unsigned char *) sctl->area;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001428 len = (data[0] << 8) | data[1];
1429
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001430 if (len + 2 != sctl->data)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001431 goto out;
1432
1433 data = data + 2;
1434 pos = 0;
1435 while (pos < len) {
1436 if (len - pos < 2)
1437 goto out;
1438
1439 sct_len = (data[pos] << 8) | data[pos + 1];
1440 if (pos + sct_len + 2 > len)
1441 goto out;
1442
1443 pos += sct_len + 2;
1444 }
1445
1446 ret = 0;
1447
1448out:
1449 return ret;
1450}
1451
Willy Tarreau83061a82018-07-13 11:56:34 +02001452static int ssl_sock_load_sctl_from_file(const char *sctl_path,
1453 struct buffer **sctl)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001454{
1455 int fd = -1;
1456 int r = 0;
1457 int ret = 1;
1458
1459 *sctl = NULL;
1460
1461 fd = open(sctl_path, O_RDONLY);
1462 if (fd == -1)
1463 goto end;
1464
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001465 trash.data = 0;
1466 while (trash.data < trash.size) {
1467 r = read(fd, trash.area + trash.data, trash.size - trash.data);
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001468 if (r < 0) {
1469 if (errno == EINTR)
1470 continue;
1471
1472 goto end;
1473 }
1474 else if (r == 0) {
1475 break;
1476 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001477 trash.data += r;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001478 }
1479
1480 ret = ssl_sock_parse_sctl(&trash);
1481 if (ret)
1482 goto end;
1483
Vincent Bernat02779b62016-04-03 13:48:43 +02001484 *sctl = calloc(1, sizeof(**sctl));
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001485 if (!chunk_dup(*sctl, &trash)) {
1486 free(*sctl);
1487 *sctl = NULL;
1488 goto end;
1489 }
1490
1491end:
1492 if (fd != -1)
1493 close(fd);
1494
1495 return ret;
1496}
1497
1498int ssl_sock_sctl_add_cbk(SSL *ssl, unsigned ext_type, const unsigned char **out, size_t *outlen, int *al, void *add_arg)
1499{
Willy Tarreau83061a82018-07-13 11:56:34 +02001500 struct buffer *sctl = add_arg;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001501
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001502 *out = (unsigned char *) sctl->area;
1503 *outlen = sctl->data;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001504
1505 return 1;
1506}
1507
1508int ssl_sock_sctl_parse_cbk(SSL *s, unsigned int ext_type, const unsigned char *in, size_t inlen, int *al, void *parse_arg)
1509{
1510 return 1;
1511}
1512
1513static int ssl_sock_load_sctl(SSL_CTX *ctx, const char *cert_path)
1514{
1515 char sctl_path[MAXPATHLEN+1];
1516 int ret = -1;
1517 struct stat st;
Willy Tarreau83061a82018-07-13 11:56:34 +02001518 struct buffer *sctl = NULL;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001519
1520 snprintf(sctl_path, MAXPATHLEN+1, "%s.sctl", cert_path);
1521
1522 if (stat(sctl_path, &st))
1523 return 1;
1524
1525 if (ssl_sock_load_sctl_from_file(sctl_path, &sctl))
1526 goto out;
1527
1528 if (!SSL_CTX_add_server_custom_ext(ctx, CT_EXTENSION_TYPE, ssl_sock_sctl_add_cbk, NULL, sctl, ssl_sock_sctl_parse_cbk, NULL)) {
1529 free(sctl);
1530 goto out;
1531 }
1532
1533 SSL_CTX_set_ex_data(ctx, sctl_ex_index, sctl);
1534
1535 ret = 0;
1536
1537out:
1538 return ret;
1539}
1540
1541#endif
1542
Emeric Brune1f38db2012-09-03 20:36:47 +02001543void ssl_sock_infocbk(const SSL *ssl, int where, int ret)
1544{
Thierry FOURNIER28962c92018-06-17 21:37:05 +02001545 struct connection *conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001546 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
Emeric Brund8b2bb52014-01-28 15:43:53 +01001547 BIO *write_bio;
Willy Tarreau622317d2015-02-27 16:36:16 +01001548 (void)ret; /* shut gcc stupid warning */
Emeric Brune1f38db2012-09-03 20:36:47 +02001549
Dirkjan Bussink526894f2019-01-21 09:35:03 -08001550#ifndef SSL_OP_NO_RENEGOTIATION
1551 /* Please note that BoringSSL defines this macro to zero so don't
1552 * change this to #if and do not assign a default value to this macro!
1553 */
Emeric Brune1f38db2012-09-03 20:36:47 +02001554 if (where & SSL_CB_HANDSHAKE_START) {
1555 /* Disable renegotiation (CVE-2009-3555) */
Olivier Houchard90084a12017-11-23 18:21:29 +01001556 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 +02001557 conn->flags |= CO_FL_ERROR;
Willy Tarreau20879a02012-12-03 16:32:10 +01001558 conn->err_code = CO_ER_SSL_RENEG;
1559 }
Emeric Brune1f38db2012-09-03 20:36:47 +02001560 }
Dirkjan Bussink526894f2019-01-21 09:35:03 -08001561#endif
Emeric Brund8b2bb52014-01-28 15:43:53 +01001562
1563 if ((where & SSL_CB_ACCEPT_LOOP) == SSL_CB_ACCEPT_LOOP) {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001564 if (!(ctx->xprt_st & SSL_SOCK_ST_FL_16K_WBFSIZE)) {
Emeric Brund8b2bb52014-01-28 15:43:53 +01001565 /* Long certificate chains optimz
1566 If write and read bios are differents, we
1567 consider that the buffering was activated,
1568 so we rise the output buffer size from 4k
1569 to 16k */
1570 write_bio = SSL_get_wbio(ssl);
1571 if (write_bio != SSL_get_rbio(ssl)) {
1572 BIO_set_write_buffer_size(write_bio, 16384);
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001573 ctx->xprt_st |= SSL_SOCK_ST_FL_16K_WBFSIZE;
Emeric Brund8b2bb52014-01-28 15:43:53 +01001574 }
1575 }
1576 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02001577}
1578
Emeric Brune64aef12012-09-21 13:15:06 +02001579/* Callback is called for each certificate of the chain during a verify
1580 ok is set to 1 if preverify detect no error on current certificate.
1581 Returns 0 to break the handshake, 1 otherwise. */
Evan Broderbe554312013-06-27 00:05:25 -07001582int ssl_sock_bind_verifycbk(int ok, X509_STORE_CTX *x_store)
Emeric Brune64aef12012-09-21 13:15:06 +02001583{
1584 SSL *ssl;
1585 struct connection *conn;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001586 struct ssl_sock_ctx *ctx;
Emeric Brun81c00f02012-09-21 14:31:21 +02001587 int err, depth;
Emeric Brune64aef12012-09-21 13:15:06 +02001588
1589 ssl = X509_STORE_CTX_get_ex_data(x_store, SSL_get_ex_data_X509_STORE_CTX_idx());
Thierry FOURNIER28962c92018-06-17 21:37:05 +02001590 conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Emeric Brune64aef12012-09-21 13:15:06 +02001591
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001592 ctx = conn->xprt_ctx;
1593
1594 ctx->xprt_st |= SSL_SOCK_ST_FL_VERIFY_DONE;
Emeric Brune64aef12012-09-21 13:15:06 +02001595
Emeric Brun81c00f02012-09-21 14:31:21 +02001596 if (ok) /* no errors */
1597 return ok;
1598
1599 depth = X509_STORE_CTX_get_error_depth(x_store);
1600 err = X509_STORE_CTX_get_error(x_store);
1601
1602 /* check if CA error needs to be ignored */
1603 if (depth > 0) {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001604 if (!SSL_SOCK_ST_TO_CA_ERROR(ctx->xprt_st)) {
1605 ctx->xprt_st |= SSL_SOCK_CA_ERROR_TO_ST(err);
1606 ctx->xprt_st |= SSL_SOCK_CAEDEPTH_TO_ST(depth);
Emeric Brunf282a812012-09-21 15:27:54 +02001607 }
1608
Willy Tarreaua9d299f2020-02-04 14:02:02 +01001609 if (err < 64 && __objt_listener(conn->target)->bind_conf->ca_ignerr & (1ULL << err)) {
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02001610 ssl_sock_dump_errors(conn);
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001611 ERR_clear_error();
Emeric Brun81c00f02012-09-21 14:31:21 +02001612 return 1;
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001613 }
Emeric Brun81c00f02012-09-21 14:31:21 +02001614
Willy Tarreau20879a02012-12-03 16:32:10 +01001615 conn->err_code = CO_ER_SSL_CA_FAIL;
Emeric Brun81c00f02012-09-21 14:31:21 +02001616 return 0;
1617 }
1618
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001619 if (!SSL_SOCK_ST_TO_CRTERROR(ctx->xprt_st))
1620 ctx->xprt_st |= SSL_SOCK_CRTERROR_TO_ST(err);
Emeric Brunf282a812012-09-21 15:27:54 +02001621
Emeric Brun81c00f02012-09-21 14:31:21 +02001622 /* check if certificate error needs to be ignored */
Willy Tarreaua9d299f2020-02-04 14:02:02 +01001623 if (err < 64 && __objt_listener(conn->target)->bind_conf->crt_ignerr & (1ULL << err)) {
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02001624 ssl_sock_dump_errors(conn);
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001625 ERR_clear_error();
Emeric Brun81c00f02012-09-21 14:31:21 +02001626 return 1;
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001627 }
Emeric Brun81c00f02012-09-21 14:31:21 +02001628
Willy Tarreau20879a02012-12-03 16:32:10 +01001629 conn->err_code = CO_ER_SSL_CRT_FAIL;
Emeric Brun81c00f02012-09-21 14:31:21 +02001630 return 0;
Emeric Brune64aef12012-09-21 13:15:06 +02001631}
1632
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001633static inline
1634void ssl_sock_parse_clienthello(int write_p, int version, int content_type,
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001635 const void *buf, size_t len, SSL *ssl)
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001636{
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001637 struct ssl_capture *capture;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001638 unsigned char *msg;
1639 unsigned char *end;
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001640 size_t rec_len;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001641
1642 /* This function is called for "from client" and "to server"
1643 * connections. The combination of write_p == 0 and content_type == 22
Joseph Herlant017b3da2018-11-15 09:07:59 -08001644 * is only available during "from client" connection.
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001645 */
1646
1647 /* "write_p" is set to 0 is the bytes are received messages,
1648 * otherwise it is set to 1.
1649 */
1650 if (write_p != 0)
1651 return;
1652
1653 /* content_type contains the type of message received or sent
1654 * according with the SSL/TLS protocol spec. This message is
1655 * encoded with one byte. The value 256 (two bytes) is used
1656 * for designing the SSL/TLS record layer. According with the
1657 * rfc6101, the expected message (other than 256) are:
1658 * - change_cipher_spec(20)
1659 * - alert(21)
1660 * - handshake(22)
1661 * - application_data(23)
1662 * - (255)
1663 * We are interessed by the handshake and specially the client
1664 * hello.
1665 */
1666 if (content_type != 22)
1667 return;
1668
1669 /* The message length is at least 4 bytes, containing the
1670 * message type and the message length.
1671 */
1672 if (len < 4)
1673 return;
1674
1675 /* First byte of the handshake message id the type of
1676 * message. The konwn types are:
1677 * - hello_request(0)
1678 * - client_hello(1)
1679 * - server_hello(2)
1680 * - certificate(11)
1681 * - server_key_exchange (12)
1682 * - certificate_request(13)
1683 * - server_hello_done(14)
1684 * We are interested by the client hello.
1685 */
1686 msg = (unsigned char *)buf;
1687 if (msg[0] != 1)
1688 return;
1689
1690 /* Next three bytes are the length of the message. The total length
1691 * must be this decoded length + 4. If the length given as argument
1692 * is not the same, we abort the protocol dissector.
1693 */
1694 rec_len = (msg[1] << 16) + (msg[2] << 8) + msg[3];
1695 if (len < rec_len + 4)
1696 return;
1697 msg += 4;
1698 end = msg + rec_len;
1699 if (end < msg)
1700 return;
1701
1702 /* Expect 2 bytes for protocol version (1 byte for major and 1 byte
1703 * for minor, the random, composed by 4 bytes for the unix time and
Baptiste Assmann6be139f2018-11-28 15:20:25 +01001704 * 28 bytes for unix payload. So we jump 1 + 1 + 4 + 28.
1705 */
1706 msg += 1 + 1 + 4 + 28;
1707 if (msg > end)
1708 return;
1709
1710 /* Next, is session id:
1711 * if present, we have to jump by length + 1 for the size information
1712 * if not present, we have to jump by 1 only
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001713 */
Baptiste Assmann6be139f2018-11-28 15:20:25 +01001714 if (msg[0] > 0)
1715 msg += msg[0];
1716 msg += 1;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001717 if (msg > end)
1718 return;
1719
1720 /* Next two bytes are the ciphersuite length. */
1721 if (msg + 2 > end)
1722 return;
1723 rec_len = (msg[0] << 8) + msg[1];
1724 msg += 2;
1725 if (msg + rec_len > end || msg + rec_len < msg)
1726 return;
1727
Willy Tarreaubafbe012017-11-24 17:34:44 +01001728 capture = pool_alloc_dirty(pool_head_ssl_capture);
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001729 if (!capture)
1730 return;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001731 /* Compute the xxh64 of the ciphersuite. */
1732 capture->xxh64 = XXH64(msg, rec_len, 0);
1733
1734 /* Capture the ciphersuite. */
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001735 capture->ciphersuite_len = (global_ssl.capture_cipherlist < rec_len) ?
1736 global_ssl.capture_cipherlist : rec_len;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001737 memcpy(capture->ciphersuite, msg, capture->ciphersuite_len);
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001738
1739 SSL_set_ex_data(ssl, ssl_capture_ptr_index, capture);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001740}
1741
Emeric Brun29f037d2014-04-25 19:05:36 +02001742/* Callback is called for ssl protocol analyse */
1743void ssl_sock_msgcbk(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg)
1744{
Emeric Brun29f037d2014-04-25 19:05:36 +02001745#ifdef TLS1_RT_HEARTBEAT
1746 /* test heartbeat received (write_p is set to 0
1747 for a received record) */
Willy Tarreauf51c6982014-04-25 20:02:39 +02001748 if ((content_type == TLS1_RT_HEARTBEAT) && (write_p == 0)) {
Thierry FOURNIER28962c92018-06-17 21:37:05 +02001749 struct connection *conn = SSL_get_ex_data(ssl, ssl_app_data_index);
William Lallemand7e1770b2019-05-13 14:31:34 +02001750 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
Willy Tarreauf51c6982014-04-25 20:02:39 +02001751 const unsigned char *p = buf;
1752 unsigned int payload;
1753
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001754 ctx->xprt_st |= SSL_SOCK_RECV_HEARTBEAT;
Willy Tarreauf51c6982014-04-25 20:02:39 +02001755
1756 /* Check if this is a CVE-2014-0160 exploitation attempt. */
1757 if (*p != TLS1_HB_REQUEST)
1758 return;
1759
Willy Tarreauaeed6722014-04-25 23:59:58 +02001760 if (len < 1 + 2 + 16) /* 1 type + 2 size + 0 payload + 16 padding */
Willy Tarreauf51c6982014-04-25 20:02:39 +02001761 goto kill_it;
1762
1763 payload = (p[1] * 256) + p[2];
Willy Tarreau3b2fdb62014-04-25 23:44:22 +02001764 if (3 + payload + 16 <= len)
Willy Tarreauf51c6982014-04-25 20:02:39 +02001765 return; /* OK no problem */
Willy Tarreauaeed6722014-04-25 23:59:58 +02001766 kill_it:
Willy Tarreau3b2fdb62014-04-25 23:44:22 +02001767 /* We have a clear heartbleed attack (CVE-2014-0160), the
1768 * advertised payload is larger than the advertised packet
1769 * length, so we have garbage in the buffer between the
1770 * payload and the end of the buffer (p+len). We can't know
1771 * if the SSL stack is patched, and we don't know if we can
1772 * safely wipe out the area between p+3+len and payload.
1773 * So instead, we prevent the response from being sent by
1774 * setting the max_send_fragment to 0 and we report an SSL
1775 * error, which will kill this connection. It will be reported
1776 * above as SSL_ERROR_SSL while an other handshake failure with
Willy Tarreauf51c6982014-04-25 20:02:39 +02001777 * a heartbeat message will be reported as SSL_ERROR_SYSCALL.
1778 */
Willy Tarreau3b2fdb62014-04-25 23:44:22 +02001779 ssl->max_send_fragment = 0;
Willy Tarreauf51c6982014-04-25 20:02:39 +02001780 SSLerr(SSL_F_TLS1_HEARTBEAT, SSL_R_SSL_HANDSHAKE_FAILURE);
1781 return;
1782 }
Emeric Brun29f037d2014-04-25 19:05:36 +02001783#endif
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001784 if (global_ssl.capture_cipherlist > 0)
1785 ssl_sock_parse_clienthello(write_p, version, content_type, buf, len, ssl);
Emeric Brun29f037d2014-04-25 19:05:36 +02001786}
1787
Bernard Spil13c53f82018-02-15 13:34:58 +01001788#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Olivier Houchardc7566002018-11-20 23:33:50 +01001789static int ssl_sock_srv_select_protos(SSL *s, unsigned char **out, unsigned char *outlen,
1790 const unsigned char *in, unsigned int inlen,
1791 void *arg)
1792{
1793 struct server *srv = arg;
1794
1795 if (SSL_select_next_proto(out, outlen, in, inlen, (unsigned char *)srv->ssl_ctx.npn_str,
1796 srv->ssl_ctx.npn_len) == OPENSSL_NPN_NEGOTIATED)
1797 return SSL_TLSEXT_ERR_OK;
1798 return SSL_TLSEXT_ERR_NOACK;
1799}
1800#endif
1801
1802#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02001803/* This callback is used so that the server advertises the list of
1804 * negociable protocols for NPN.
1805 */
1806static int ssl_sock_advertise_npn_protos(SSL *s, const unsigned char **data,
1807 unsigned int *len, void *arg)
1808{
Emmanuel Hocdet98263292016-12-29 18:26:15 +01001809 struct ssl_bind_conf *conf = arg;
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02001810
1811 *data = (const unsigned char *)conf->npn_str;
1812 *len = conf->npn_len;
1813 return SSL_TLSEXT_ERR_OK;
1814}
1815#endif
1816
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01001817#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02001818/* This callback is used so that the server advertises the list of
1819 * negociable protocols for ALPN.
1820 */
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01001821static int ssl_sock_advertise_alpn_protos(SSL *s, const unsigned char **out,
1822 unsigned char *outlen,
1823 const unsigned char *server,
1824 unsigned int server_len, void *arg)
Willy Tarreauab861d32013-04-02 02:30:41 +02001825{
Emmanuel Hocdet98263292016-12-29 18:26:15 +01001826 struct ssl_bind_conf *conf = arg;
Willy Tarreauab861d32013-04-02 02:30:41 +02001827
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01001828 if (SSL_select_next_proto((unsigned char**) out, outlen, (const unsigned char *)conf->alpn_str,
1829 conf->alpn_len, server, server_len) != OPENSSL_NPN_NEGOTIATED) {
1830 return SSL_TLSEXT_ERR_NOACK;
1831 }
Willy Tarreauab861d32013-04-02 02:30:41 +02001832 return SSL_TLSEXT_ERR_OK;
1833}
1834#endif
1835
Willy Tarreauc8ad3be2015-06-17 15:48:26 +02001836#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01001837#ifndef SSL_NO_GENERATE_CERTIFICATES
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001838
Christopher Faulet30548802015-06-11 13:39:32 +02001839/* Create a X509 certificate with the specified servername and serial. This
1840 * function returns a SSL_CTX object or NULL if an error occurs. */
Christopher Faulet7969a332015-10-09 11:15:03 +02001841static SSL_CTX *
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001842ssl_sock_do_create_cert(const char *servername, struct bind_conf *bind_conf, SSL *ssl)
Christopher Faulet31af49d2015-06-09 17:29:50 +02001843{
Christopher Faulet7969a332015-10-09 11:15:03 +02001844 X509 *cacert = bind_conf->ca_sign_cert;
1845 EVP_PKEY *capkey = bind_conf->ca_sign_pkey;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001846 SSL_CTX *ssl_ctx = NULL;
1847 X509 *newcrt = NULL;
1848 EVP_PKEY *pkey = NULL;
Emmanuel Hocdet15969292017-08-11 10:56:00 +02001849 SSL *tmp_ssl = NULL;
Emmanuel Hocdeta9b84022018-10-01 18:41:36 +02001850 CONF *ctmp = NULL;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001851 X509_NAME *name;
1852 const EVP_MD *digest;
1853 X509V3_CTX ctx;
1854 unsigned int i;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001855 int key_type;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001856
Christopher Faulet48a83322017-07-28 16:56:09 +02001857 /* Get the private key of the default certificate and use it */
Willy Tarreau5db847a2019-05-09 14:13:35 +02001858#if (HA_OPENSSL_VERSION_NUMBER >= 0x10002000L)
Emmanuel Hocdet15969292017-08-11 10:56:00 +02001859 pkey = SSL_CTX_get0_privatekey(bind_conf->default_ctx);
1860#else
1861 tmp_ssl = SSL_new(bind_conf->default_ctx);
1862 if (tmp_ssl)
1863 pkey = SSL_get_privatekey(tmp_ssl);
1864#endif
1865 if (!pkey)
Christopher Faulet31af49d2015-06-09 17:29:50 +02001866 goto mkcert_error;
1867
1868 /* Create the certificate */
1869 if (!(newcrt = X509_new()))
1870 goto mkcert_error;
1871
1872 /* Set version number for the certificate (X509v3) and the serial
1873 * number */
1874 if (X509_set_version(newcrt, 2L) != 1)
1875 goto mkcert_error;
Olivier Houchard2be5a4c2019-03-08 18:54:43 +01001876 ASN1_INTEGER_set(X509_get_serialNumber(newcrt), _HA_ATOMIC_ADD(&ssl_ctx_serial, 1));
Christopher Faulet31af49d2015-06-09 17:29:50 +02001877
1878 /* Set duration for the certificate */
Rosen Penev68185952018-12-14 08:47:02 -08001879 if (!X509_gmtime_adj(X509_getm_notBefore(newcrt), (long)-60*60*24) ||
1880 !X509_gmtime_adj(X509_getm_notAfter(newcrt),(long)60*60*24*365))
Christopher Faulet31af49d2015-06-09 17:29:50 +02001881 goto mkcert_error;
1882
1883 /* set public key in the certificate */
1884 if (X509_set_pubkey(newcrt, pkey) != 1)
1885 goto mkcert_error;
1886
1887 /* Set issuer name from the CA */
1888 if (!(name = X509_get_subject_name(cacert)))
1889 goto mkcert_error;
1890 if (X509_set_issuer_name(newcrt, name) != 1)
1891 goto mkcert_error;
1892
1893 /* Set the subject name using the same, but the CN */
1894 name = X509_NAME_dup(name);
1895 if (X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC,
1896 (const unsigned char *)servername,
1897 -1, -1, 0) != 1) {
1898 X509_NAME_free(name);
1899 goto mkcert_error;
1900 }
1901 if (X509_set_subject_name(newcrt, name) != 1) {
1902 X509_NAME_free(name);
1903 goto mkcert_error;
1904 }
1905 X509_NAME_free(name);
1906
1907 /* Add x509v3 extensions as specified */
Emmanuel Hocdeta9b84022018-10-01 18:41:36 +02001908 ctmp = NCONF_new(NULL);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001909 X509V3_set_ctx(&ctx, cacert, newcrt, NULL, NULL, 0);
1910 for (i = 0; i < X509V3_EXT_SIZE; i++) {
1911 X509_EXTENSION *ext;
1912
Emmanuel Hocdeta9b84022018-10-01 18:41:36 +02001913 if (!(ext = X509V3_EXT_nconf(ctmp, &ctx, x509v3_ext_names[i], x509v3_ext_values[i])))
Christopher Faulet31af49d2015-06-09 17:29:50 +02001914 goto mkcert_error;
1915 if (!X509_add_ext(newcrt, ext, -1)) {
1916 X509_EXTENSION_free(ext);
1917 goto mkcert_error;
1918 }
1919 X509_EXTENSION_free(ext);
1920 }
1921
1922 /* Sign the certificate with the CA private key */
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001923
1924 key_type = EVP_PKEY_base_id(capkey);
1925
1926 if (key_type == EVP_PKEY_DSA)
1927 digest = EVP_sha1();
1928 else if (key_type == EVP_PKEY_RSA)
Christopher Faulet31af49d2015-06-09 17:29:50 +02001929 digest = EVP_sha256();
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001930 else if (key_type == EVP_PKEY_EC)
Christopher Faulet7969a332015-10-09 11:15:03 +02001931 digest = EVP_sha256();
1932 else {
Willy Tarreau9a1ab082019-05-09 13:26:41 +02001933#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000000fL) && !defined(OPENSSL_IS_BORINGSSL)
Christopher Faulet7969a332015-10-09 11:15:03 +02001934 int nid;
1935
1936 if (EVP_PKEY_get_default_digest_nid(capkey, &nid) <= 0)
1937 goto mkcert_error;
1938 if (!(digest = EVP_get_digestbynid(nid)))
1939 goto mkcert_error;
Christopher Faulete7db2162015-10-19 13:59:24 +02001940#else
1941 goto mkcert_error;
1942#endif
Christopher Faulet7969a332015-10-09 11:15:03 +02001943 }
1944
Christopher Faulet31af49d2015-06-09 17:29:50 +02001945 if (!(X509_sign(newcrt, capkey, digest)))
1946 goto mkcert_error;
1947
1948 /* Create and set the new SSL_CTX */
1949 if (!(ssl_ctx = SSL_CTX_new(SSLv23_server_method())))
1950 goto mkcert_error;
1951 if (!SSL_CTX_use_PrivateKey(ssl_ctx, pkey))
1952 goto mkcert_error;
1953 if (!SSL_CTX_use_certificate(ssl_ctx, newcrt))
1954 goto mkcert_error;
1955 if (!SSL_CTX_check_private_key(ssl_ctx))
1956 goto mkcert_error;
1957
1958 if (newcrt) X509_free(newcrt);
Christopher Faulet7969a332015-10-09 11:15:03 +02001959
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01001960#ifndef OPENSSL_NO_DH
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001961 SSL_CTX_set_tmp_dh_callback(ssl_ctx, ssl_get_tmp_dh);
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01001962#endif
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001963#if defined(SSL_CTX_set_tmp_ecdh) && !defined(OPENSSL_NO_ECDH)
1964 {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01001965 const char *ecdhe = (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe : ECDHE_DEFAULT_CURVE);
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001966 EC_KEY *ecc;
1967 int nid;
1968
1969 if ((nid = OBJ_sn2nid(ecdhe)) == NID_undef)
1970 goto end;
1971 if (!(ecc = EC_KEY_new_by_curve_name(nid)))
1972 goto end;
1973 SSL_CTX_set_tmp_ecdh(ssl_ctx, ecc);
1974 EC_KEY_free(ecc);
1975 }
1976#endif
1977 end:
Christopher Faulet31af49d2015-06-09 17:29:50 +02001978 return ssl_ctx;
1979
1980 mkcert_error:
Emmanuel Hocdeta9b84022018-10-01 18:41:36 +02001981 if (ctmp) NCONF_free(ctmp);
Emmanuel Hocdet15969292017-08-11 10:56:00 +02001982 if (tmp_ssl) SSL_free(tmp_ssl);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001983 if (ssl_ctx) SSL_CTX_free(ssl_ctx);
1984 if (newcrt) X509_free(newcrt);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001985 return NULL;
1986}
1987
Christopher Faulet7969a332015-10-09 11:15:03 +02001988SSL_CTX *
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001989ssl_sock_create_cert(struct connection *conn, const char *servername, unsigned int key)
Christopher Faulet7969a332015-10-09 11:15:03 +02001990{
Willy Tarreau07d94e42018-09-20 10:57:52 +02001991 struct bind_conf *bind_conf = __objt_listener(conn->target)->bind_conf;
Olivier Houchard66ab4982019-02-26 18:37:15 +01001992 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001993
Olivier Houchard66ab4982019-02-26 18:37:15 +01001994 return ssl_sock_do_create_cert(servername, bind_conf, ctx->ssl);
Christopher Faulet7969a332015-10-09 11:15:03 +02001995}
1996
Christopher Faulet30548802015-06-11 13:39:32 +02001997/* Do a lookup for a certificate in the LRU cache used to store generated
Emeric Brun821bb9b2017-06-15 16:37:39 +02001998 * certificates and immediately assign it to the SSL session if not null. */
Christopher Faulet30548802015-06-11 13:39:32 +02001999SSL_CTX *
Emeric Brun821bb9b2017-06-15 16:37:39 +02002000ssl_sock_assign_generated_cert(unsigned int key, struct bind_conf *bind_conf, SSL *ssl)
Christopher Faulet30548802015-06-11 13:39:32 +02002001{
2002 struct lru64 *lru = NULL;
2003
2004 if (ssl_ctx_lru_tree) {
Willy Tarreau03f4ec42018-05-17 10:56:47 +02002005 HA_RWLOCK_WRLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002006 lru = lru64_lookup(key, ssl_ctx_lru_tree, bind_conf->ca_sign_cert, 0);
Emeric Brun821bb9b2017-06-15 16:37:39 +02002007 if (lru && lru->domain) {
2008 if (ssl)
2009 SSL_set_SSL_CTX(ssl, (SSL_CTX *)lru->data);
Willy Tarreau03f4ec42018-05-17 10:56:47 +02002010 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet30548802015-06-11 13:39:32 +02002011 return (SSL_CTX *)lru->data;
Emeric Brun821bb9b2017-06-15 16:37:39 +02002012 }
Willy Tarreau03f4ec42018-05-17 10:56:47 +02002013 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet30548802015-06-11 13:39:32 +02002014 }
2015 return NULL;
2016}
2017
Emeric Brun821bb9b2017-06-15 16:37:39 +02002018/* Same as <ssl_sock_assign_generated_cert> but without SSL session. This
2019 * function is not thread-safe, it should only be used to check if a certificate
2020 * exists in the lru cache (with no warranty it will not be removed by another
2021 * thread). It is kept for backward compatibility. */
2022SSL_CTX *
2023ssl_sock_get_generated_cert(unsigned int key, struct bind_conf *bind_conf)
2024{
2025 return ssl_sock_assign_generated_cert(key, bind_conf, NULL);
2026}
2027
Christopher Fauletd2cab922015-07-28 16:03:47 +02002028/* Set a certificate int the LRU cache used to store generated
2029 * certificate. Return 0 on success, otherwise -1 */
2030int
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002031ssl_sock_set_generated_cert(SSL_CTX *ssl_ctx, unsigned int key, struct bind_conf *bind_conf)
Christopher Faulet30548802015-06-11 13:39:32 +02002032{
2033 struct lru64 *lru = NULL;
2034
2035 if (ssl_ctx_lru_tree) {
Christopher Faulet2a944ee2017-11-07 10:42:54 +01002036 HA_RWLOCK_WRLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002037 lru = lru64_get(key, ssl_ctx_lru_tree, bind_conf->ca_sign_cert, 0);
Emeric Brun821bb9b2017-06-15 16:37:39 +02002038 if (!lru) {
Christopher Faulet2a944ee2017-11-07 10:42:54 +01002039 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Fauletd2cab922015-07-28 16:03:47 +02002040 return -1;
Emeric Brun821bb9b2017-06-15 16:37:39 +02002041 }
Christopher Faulet30548802015-06-11 13:39:32 +02002042 if (lru->domain && lru->data)
2043 lru->free((SSL_CTX *)lru->data);
Christopher Faulet7969a332015-10-09 11:15:03 +02002044 lru64_commit(lru, ssl_ctx, bind_conf->ca_sign_cert, 0, (void (*)(void *))SSL_CTX_free);
Christopher Faulet2a944ee2017-11-07 10:42:54 +01002045 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Fauletd2cab922015-07-28 16:03:47 +02002046 return 0;
Christopher Faulet30548802015-06-11 13:39:32 +02002047 }
Christopher Fauletd2cab922015-07-28 16:03:47 +02002048 return -1;
Christopher Faulet30548802015-06-11 13:39:32 +02002049}
2050
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002051/* Compute the key of the certificate. */
Christopher Faulet30548802015-06-11 13:39:32 +02002052unsigned int
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002053ssl_sock_generated_cert_key(const void *data, size_t len)
Christopher Faulet30548802015-06-11 13:39:32 +02002054{
2055 return XXH32(data, len, ssl_ctx_lru_seed);
2056}
2057
Willy Tarreau2f63ef42015-10-20 15:16:01 +02002058/* Generate a cert and immediately assign it to the SSL session so that the cert's
2059 * refcount is maintained regardless of the cert's presence in the LRU cache.
2060 */
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002061static int
Christopher Faulet7969a332015-10-09 11:15:03 +02002062ssl_sock_generate_certificate(const char *servername, struct bind_conf *bind_conf, SSL *ssl)
Christopher Faulet31af49d2015-06-09 17:29:50 +02002063{
2064 X509 *cacert = bind_conf->ca_sign_cert;
Christopher Faulet31af49d2015-06-09 17:29:50 +02002065 SSL_CTX *ssl_ctx = NULL;
2066 struct lru64 *lru = NULL;
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002067 unsigned int key;
Christopher Faulet31af49d2015-06-09 17:29:50 +02002068
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002069 key = ssl_sock_generated_cert_key(servername, strlen(servername));
Christopher Faulet31af49d2015-06-09 17:29:50 +02002070 if (ssl_ctx_lru_tree) {
Christopher Faulet2a944ee2017-11-07 10:42:54 +01002071 HA_RWLOCK_WRLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002072 lru = lru64_get(key, ssl_ctx_lru_tree, cacert, 0);
Christopher Faulet31af49d2015-06-09 17:29:50 +02002073 if (lru && lru->domain)
2074 ssl_ctx = (SSL_CTX *)lru->data;
Christopher Fauletd2cab922015-07-28 16:03:47 +02002075 if (!ssl_ctx && lru) {
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002076 ssl_ctx = ssl_sock_do_create_cert(servername, bind_conf, ssl);
Christopher Faulet31af49d2015-06-09 17:29:50 +02002077 lru64_commit(lru, ssl_ctx, cacert, 0, (void (*)(void *))SSL_CTX_free);
Christopher Fauletd2cab922015-07-28 16:03:47 +02002078 }
Willy Tarreau2f63ef42015-10-20 15:16:01 +02002079 SSL_set_SSL_CTX(ssl, ssl_ctx);
Christopher Faulet2a944ee2017-11-07 10:42:54 +01002080 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002081 return 1;
Christopher Faulet31af49d2015-06-09 17:29:50 +02002082 }
Willy Tarreau2f63ef42015-10-20 15:16:01 +02002083 else {
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002084 ssl_ctx = ssl_sock_do_create_cert(servername, bind_conf, ssl);
Willy Tarreau2f63ef42015-10-20 15:16:01 +02002085 SSL_set_SSL_CTX(ssl, ssl_ctx);
2086 /* No LRU cache, this CTX will be released as soon as the session dies */
2087 SSL_CTX_free(ssl_ctx);
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002088 return 1;
Willy Tarreau2f63ef42015-10-20 15:16:01 +02002089 }
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002090 return 0;
2091}
2092static int
2093ssl_sock_generate_certificate_from_conn(struct bind_conf *bind_conf, SSL *ssl)
2094{
2095 unsigned int key;
Thierry FOURNIER28962c92018-06-17 21:37:05 +02002096 struct connection *conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002097
2098 conn_get_to_addr(conn);
2099 if (conn->flags & CO_FL_ADDR_TO_SET) {
2100 key = ssl_sock_generated_cert_key(&conn->addr.to, get_addr_len(&conn->addr.to));
Emeric Brun821bb9b2017-06-15 16:37:39 +02002101 if (ssl_sock_assign_generated_cert(key, bind_conf, ssl))
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002102 return 1;
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002103 }
2104 return 0;
Christopher Faulet31af49d2015-06-09 17:29:50 +02002105}
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002106#endif /* !defined SSL_NO_GENERATE_CERTIFICATES */
Christopher Faulet31af49d2015-06-09 17:29:50 +02002107
Willy Tarreau9a1ab082019-05-09 13:26:41 +02002108#if (HA_OPENSSL_VERSION_NUMBER < 0x1010000fL)
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002109typedef enum { SET_CLIENT, SET_SERVER } set_context_func;
2110
2111static void ctx_set_SSLv3_func(SSL_CTX *ctx, set_context_func c)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002112{
Emmanuel Hocdet23877ab2017-07-12 12:53:02 +02002113#if SSL_OP_NO_SSLv3
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002114 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, SSLv3_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002115 : SSL_CTX_set_ssl_version(ctx, SSLv3_client_method());
2116#endif
2117}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002118static void ctx_set_TLSv10_func(SSL_CTX *ctx, set_context_func c) {
2119 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, TLSv1_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002120 : SSL_CTX_set_ssl_version(ctx, TLSv1_client_method());
2121}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002122static void ctx_set_TLSv11_func(SSL_CTX *ctx, set_context_func c) {
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002123#if SSL_OP_NO_TLSv1_1
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002124 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, TLSv1_1_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002125 : SSL_CTX_set_ssl_version(ctx, TLSv1_1_client_method());
2126#endif
2127}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002128static void ctx_set_TLSv12_func(SSL_CTX *ctx, set_context_func c) {
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002129#if SSL_OP_NO_TLSv1_2
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002130 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, TLSv1_2_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002131 : SSL_CTX_set_ssl_version(ctx, TLSv1_2_client_method());
2132#endif
2133}
Bertrand Jacquina25282b2018-08-14 00:56:13 +01002134/* TLSv1.2 is the last supported version in this context. */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002135static void ctx_set_TLSv13_func(SSL_CTX *ctx, set_context_func c) {}
2136/* Unusable in this context. */
2137static void ssl_set_SSLv3_func(SSL *ssl, set_context_func c) {}
2138static void ssl_set_TLSv10_func(SSL *ssl, set_context_func c) {}
2139static void ssl_set_TLSv11_func(SSL *ssl, set_context_func c) {}
2140static void ssl_set_TLSv12_func(SSL *ssl, set_context_func c) {}
2141static void ssl_set_TLSv13_func(SSL *ssl, set_context_func c) {}
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002142#else /* openssl >= 1.1.0 */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002143typedef enum { SET_MIN, SET_MAX } set_context_func;
2144
2145static void ctx_set_SSLv3_func(SSL_CTX *ctx, set_context_func c) {
2146 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, SSL3_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002147 : SSL_CTX_set_min_proto_version(ctx, SSL3_VERSION);
2148}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002149static void ssl_set_SSLv3_func(SSL *ssl, set_context_func c) {
2150 c == SET_MAX ? SSL_set_max_proto_version(ssl, SSL3_VERSION)
2151 : SSL_set_min_proto_version(ssl, SSL3_VERSION);
2152}
2153static void ctx_set_TLSv10_func(SSL_CTX *ctx, set_context_func c) {
2154 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002155 : SSL_CTX_set_min_proto_version(ctx, TLS1_VERSION);
2156}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002157static void ssl_set_TLSv10_func(SSL *ssl, set_context_func c) {
2158 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_VERSION)
2159 : SSL_set_min_proto_version(ssl, TLS1_VERSION);
2160}
2161static void ctx_set_TLSv11_func(SSL_CTX *ctx, set_context_func c) {
2162 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_1_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002163 : SSL_CTX_set_min_proto_version(ctx, TLS1_1_VERSION);
2164}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002165static void ssl_set_TLSv11_func(SSL *ssl, set_context_func c) {
2166 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_1_VERSION)
2167 : SSL_set_min_proto_version(ssl, TLS1_1_VERSION);
2168}
2169static void ctx_set_TLSv12_func(SSL_CTX *ctx, set_context_func c) {
2170 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_2_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002171 : SSL_CTX_set_min_proto_version(ctx, TLS1_2_VERSION);
2172}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002173static void ssl_set_TLSv12_func(SSL *ssl, set_context_func c) {
2174 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_2_VERSION)
2175 : SSL_set_min_proto_version(ssl, TLS1_2_VERSION);
2176}
2177static void ctx_set_TLSv13_func(SSL_CTX *ctx, set_context_func c) {
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002178#if SSL_OP_NO_TLSv1_3
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002179 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_3_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002180 : SSL_CTX_set_min_proto_version(ctx, TLS1_3_VERSION);
2181#endif
2182}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002183static void ssl_set_TLSv13_func(SSL *ssl, set_context_func c) {
2184#if SSL_OP_NO_TLSv1_3
2185 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_3_VERSION)
2186 : SSL_set_min_proto_version(ssl, TLS1_3_VERSION);
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002187#endif
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002188}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002189#endif
2190static void ctx_set_None_func(SSL_CTX *ctx, set_context_func c) { }
2191static void ssl_set_None_func(SSL *ssl, set_context_func c) { }
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002192
2193static struct {
2194 int option;
2195 uint16_t flag;
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002196 void (*ctx_set_version)(SSL_CTX *, set_context_func);
2197 void (*ssl_set_version)(SSL *, set_context_func);
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002198 const char *name;
2199} methodVersions[] = {
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002200 {0, 0, ctx_set_None_func, ssl_set_None_func, "NONE"}, /* CONF_TLSV_NONE */
2201 {SSL_OP_NO_SSLv3, MC_SSL_O_NO_SSLV3, ctx_set_SSLv3_func, ssl_set_SSLv3_func, "SSLv3"}, /* CONF_SSLV3 */
2202 {SSL_OP_NO_TLSv1, MC_SSL_O_NO_TLSV10, ctx_set_TLSv10_func, ssl_set_TLSv10_func, "TLSv1.0"}, /* CONF_TLSV10 */
2203 {SSL_OP_NO_TLSv1_1, MC_SSL_O_NO_TLSV11, ctx_set_TLSv11_func, ssl_set_TLSv11_func, "TLSv1.1"}, /* CONF_TLSV11 */
2204 {SSL_OP_NO_TLSv1_2, MC_SSL_O_NO_TLSV12, ctx_set_TLSv12_func, ssl_set_TLSv12_func, "TLSv1.2"}, /* CONF_TLSV12 */
2205 {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 +02002206};
2207
Emmanuel Hocdet530141f2017-03-01 18:54:56 +01002208static void ssl_sock_switchctx_set(SSL *ssl, SSL_CTX *ctx)
2209{
2210 SSL_set_verify(ssl, SSL_CTX_get_verify_mode(ctx), ssl_sock_bind_verifycbk);
2211 SSL_set_client_CA_list(ssl, SSL_dup_CA_list(SSL_CTX_get_client_CA_list(ctx)));
2212 SSL_set_SSL_CTX(ssl, ctx);
2213}
2214
Willy Tarreau5db847a2019-05-09 14:13:35 +02002215#if ((HA_OPENSSL_VERSION_NUMBER >= 0x10101000L) || defined(OPENSSL_IS_BORINGSSL))
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002216
2217static int ssl_sock_switchctx_err_cbk(SSL *ssl, int *al, void *priv)
2218{
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002219 struct bind_conf *s = priv;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002220 (void)al; /* shut gcc stupid warning */
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002221
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002222 if (SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name) || s->generate_certs)
2223 return SSL_TLSEXT_ERR_OK;
2224 return SSL_TLSEXT_ERR_NOACK;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002225}
2226
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002227#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002228static int ssl_sock_switchctx_cbk(const struct ssl_early_callback_ctx *ctx)
2229{
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002230 SSL *ssl = ctx->ssl;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002231#else
2232static int ssl_sock_switchctx_cbk(SSL *ssl, int *al, void *arg)
2233{
2234#endif
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002235 struct connection *conn;
2236 struct bind_conf *s;
2237 const uint8_t *extension_data;
2238 size_t extension_len;
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002239 int has_rsa_sig = 0, has_ecdsa_sig = 0;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002240
2241 char *wildp = NULL;
2242 const uint8_t *servername;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002243 size_t servername_len;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002244 struct ebmb_node *node, *n, *node_ecdsa = NULL, *node_rsa = NULL, *node_anonymous = NULL;
Olivier Houchardc2aae742017-09-22 18:26:28 +02002245 int allow_early = 0;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002246 int i;
2247
Thierry FOURNIER28962c92018-06-17 21:37:05 +02002248 conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Willy Tarreaua8825522018-10-15 13:20:07 +02002249 s = __objt_listener(conn->target)->bind_conf;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002250
Olivier Houchard9679ac92017-10-27 14:58:08 +02002251 if (s->ssl_conf.early_data)
Olivier Houchardc2aae742017-09-22 18:26:28 +02002252 allow_early = 1;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002253#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002254 if (SSL_early_callback_ctx_extension_get(ctx, TLSEXT_TYPE_server_name,
2255 &extension_data, &extension_len)) {
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002256#else
2257 if (SSL_client_hello_get0_ext(ssl, TLSEXT_TYPE_server_name, &extension_data, &extension_len)) {
2258#endif
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002259 /*
2260 * The server_name extension was given too much extensibility when it
2261 * was written, so parsing the normal case is a bit complex.
2262 */
2263 size_t len;
2264 if (extension_len <= 2)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002265 goto abort;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002266 /* Extract the length of the supplied list of names. */
2267 len = (*extension_data++) << 8;
2268 len |= *extension_data++;
2269 if (len + 2 != extension_len)
2270 goto abort;
2271 /*
2272 * The list in practice only has a single element, so we only consider
2273 * the first one.
2274 */
2275 if (len == 0 || *extension_data++ != TLSEXT_NAMETYPE_host_name)
2276 goto abort;
2277 extension_len = len - 1;
2278 /* Now we can finally pull out the byte array with the actual hostname. */
2279 if (extension_len <= 2)
2280 goto abort;
2281 len = (*extension_data++) << 8;
2282 len |= *extension_data++;
2283 if (len == 0 || len + 2 > extension_len || len > TLSEXT_MAXLEN_host_name
2284 || memchr(extension_data, 0, len) != NULL)
2285 goto abort;
2286 servername = extension_data;
2287 servername_len = len;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002288 } else {
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002289#if (!defined SSL_NO_GENERATE_CERTIFICATES)
2290 if (s->generate_certs && ssl_sock_generate_certificate_from_conn(s, ssl)) {
Olivier Houchardc2aae742017-09-22 18:26:28 +02002291 goto allow_early;
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002292 }
2293#endif
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002294 /* without SNI extension, is the default_ctx (need SSL_TLSEXT_ERR_NOACK) */
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002295 if (!s->strict_sni) {
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002296 ssl_sock_switchctx_set(ssl, s->default_ctx);
Olivier Houchardc2aae742017-09-22 18:26:28 +02002297 goto allow_early;
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002298 }
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002299 goto abort;
2300 }
2301
2302 /* extract/check clientHello informations */
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002303#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002304 if (SSL_early_callback_ctx_extension_get(ctx, TLSEXT_TYPE_signature_algorithms, &extension_data, &extension_len)) {
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002305#else
2306 if (SSL_client_hello_get0_ext(ssl, TLSEXT_TYPE_signature_algorithms, &extension_data, &extension_len)) {
2307#endif
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002308 uint8_t sign;
2309 size_t len;
2310 if (extension_len < 2)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002311 goto abort;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002312 len = (*extension_data++) << 8;
2313 len |= *extension_data++;
2314 if (len + 2 != extension_len)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002315 goto abort;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002316 if (len % 2 != 0)
2317 goto abort;
2318 for (; len > 0; len -= 2) {
2319 extension_data++; /* hash */
2320 sign = *extension_data++;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002321 switch (sign) {
2322 case TLSEXT_signature_rsa:
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002323 has_rsa_sig = 1;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002324 break;
2325 case TLSEXT_signature_ecdsa:
2326 has_ecdsa_sig = 1;
2327 break;
2328 default:
2329 continue;
2330 }
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002331 if (has_ecdsa_sig && has_rsa_sig)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002332 break;
2333 }
2334 } else {
Bertrand Jacquina25282b2018-08-14 00:56:13 +01002335 /* without TLSEXT_TYPE_signature_algorithms extension (< TLSv1.2) */
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002336 has_rsa_sig = 1;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002337 }
2338 if (has_ecdsa_sig) { /* in very rare case: has ecdsa sign but not a ECDSA cipher */
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002339 const SSL_CIPHER *cipher;
2340 size_t len;
2341 const uint8_t *cipher_suites;
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002342 has_ecdsa_sig = 0;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002343#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002344 len = ctx->cipher_suites_len;
2345 cipher_suites = ctx->cipher_suites;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002346#else
2347 len = SSL_client_hello_get0_ciphers(ssl, &cipher_suites);
2348#endif
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002349 if (len % 2 != 0)
2350 goto abort;
2351 for (; len != 0; len -= 2, cipher_suites += 2) {
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002352#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002353 uint16_t cipher_suite = (cipher_suites[0] << 8) | cipher_suites[1];
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002354 cipher = SSL_get_cipher_by_value(cipher_suite);
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002355#else
2356 cipher = SSL_CIPHER_find(ssl, cipher_suites);
2357#endif
Emmanuel Hocdet019f9b12017-10-02 17:12:06 +02002358 if (cipher && SSL_CIPHER_get_auth_nid(cipher) == NID_auth_ecdsa) {
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002359 has_ecdsa_sig = 1;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002360 break;
2361 }
2362 }
2363 }
2364
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002365 for (i = 0; i < trash.size && i < servername_len; i++) {
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002366 trash.area[i] = tolower(servername[i]);
2367 if (!wildp && (trash.area[i] == '.'))
2368 wildp = &trash.area[i];
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002369 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002370 trash.area[i] = 0;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002371
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002372
William Lallemand6c98f492020-08-14 14:43:35 +02002373 /* Look for an ECDSA, RSA and DSA certificate, first in the single
2374 * name and if not found in the wildcard */
Emmanuel Hocdetcc957c32019-11-06 16:05:34 +01002375 for (i = 0; i < 2; i++) {
2376 if (i == 0) /* lookup in full qualified names */
2377 node = ebst_lookup(&s->sni_ctx, trash.area);
2378 else if (i == 1 && wildp) /* lookup in wildcards names */
2379 node = ebst_lookup(&s->sni_w_ctx, wildp);
2380 else
2381 break;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002382 for (n = node; n; n = ebmb_next_dup(n)) {
Emmanuel Hocdetcc957c32019-11-06 16:05:34 +01002383 /* lookup a not neg filter */
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002384 if (!container_of(n, struct sni_ctx, name)->neg) {
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002385 switch(container_of(n, struct sni_ctx, name)->kinfo.sig) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002386 case TLSEXT_signature_ecdsa:
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002387 if (!node_ecdsa)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002388 node_ecdsa = n;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002389 break;
2390 case TLSEXT_signature_rsa:
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002391 if (!node_rsa)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002392 node_rsa = n;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002393 break;
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002394 default: /* TLSEXT_signature_anonymous|dsa */
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002395 if (!node_anonymous)
2396 node_anonymous = n;
2397 break;
2398 }
2399 }
2400 }
William Lallemand6c98f492020-08-14 14:43:35 +02002401 }
2402 /* Once the certificates are found, select them depending on what is
2403 * supported in the client and by key_signature priority order: EDSA >
2404 * RSA > DSA */
2405 node = (has_ecdsa_sig && node_ecdsa) ? node_ecdsa
2406 : ((has_rsa_sig && node_rsa) ? node_rsa
2407 : (node_anonymous ? node_anonymous
2408 : (node_ecdsa ? node_ecdsa /* no ecdsa signature case (< TLSv1.2) */
2409 : node_rsa /* no rsa signature case (far far away) */
2410 )));
2411 if (node) {
2412 /* switch ctx */
2413 struct ssl_bind_conf *conf = container_of(node, struct sni_ctx, name)->conf;
2414 ssl_sock_switchctx_set(ssl, container_of(node, struct sni_ctx, name)->ctx);
2415 if (conf) {
2416 methodVersions[conf->ssl_methods.min].ssl_set_version(ssl, SET_MIN);
2417 methodVersions[conf->ssl_methods.max].ssl_set_version(ssl, SET_MAX);
2418 if (conf->early_data)
2419 allow_early = 1;
Emmanuel Hocdetcc957c32019-11-06 16:05:34 +01002420 }
William Lallemand6c98f492020-08-14 14:43:35 +02002421 goto allow_early;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002422 }
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002423#if (!defined SSL_NO_GENERATE_CERTIFICATES)
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002424 if (s->generate_certs && ssl_sock_generate_certificate(trash.area, s, ssl)) {
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002425 /* switch ctx done in ssl_sock_generate_certificate */
Olivier Houchardc2aae742017-09-22 18:26:28 +02002426 goto allow_early;
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002427 }
2428#endif
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002429 if (!s->strict_sni) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002430 /* no certificate match, is the default_ctx */
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002431 ssl_sock_switchctx_set(ssl, s->default_ctx);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002432 }
Olivier Houchardc2aae742017-09-22 18:26:28 +02002433allow_early:
2434#ifdef OPENSSL_IS_BORINGSSL
2435 if (allow_early)
2436 SSL_set_early_data_enabled(ssl, 1);
2437#else
2438 if (!allow_early)
2439 SSL_set_max_early_data(ssl, 0);
2440#endif
2441 return 1;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002442 abort:
2443 /* abort handshake (was SSL_TLSEXT_ERR_ALERT_FATAL) */
2444 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002445#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002446 return ssl_select_cert_error;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002447#else
2448 *al = SSL_AD_UNRECOGNIZED_NAME;
2449 return 0;
2450#endif
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002451}
2452
2453#else /* OPENSSL_IS_BORINGSSL */
2454
Emeric Brunfc0421f2012-09-07 17:30:07 +02002455/* Sets the SSL ctx of <ssl> to match the advertised server name. Returns a
2456 * warning when no match is found, which implies the default (first) cert
2457 * will keep being used.
2458 */
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002459static int ssl_sock_switchctx_cbk(SSL *ssl, int *al, void *priv)
Emeric Brunfc0421f2012-09-07 17:30:07 +02002460{
2461 const char *servername;
2462 const char *wildp = NULL;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002463 struct ebmb_node *node, *n;
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002464 struct bind_conf *s = priv;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002465 int i;
2466 (void)al; /* shut gcc stupid warning */
2467
2468 servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
Emmanuel Hocdet65623372013-01-24 17:17:15 +01002469 if (!servername) {
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002470#if (!defined SSL_NO_GENERATE_CERTIFICATES)
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002471 if (s->generate_certs && ssl_sock_generate_certificate_from_conn(s, ssl))
2472 return SSL_TLSEXT_ERR_OK;
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002473#endif
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002474 if (s->strict_sni)
2475 return SSL_TLSEXT_ERR_ALERT_FATAL;
2476 ssl_sock_switchctx_set(ssl, s->default_ctx);
2477 return SSL_TLSEXT_ERR_NOACK;
Emmanuel Hocdet65623372013-01-24 17:17:15 +01002478 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02002479
Willy Tarreau19d14ef2012-10-29 16:51:55 +01002480 for (i = 0; i < trash.size; i++) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02002481 if (!servername[i])
2482 break;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002483 trash.area[i] = tolower(servername[i]);
2484 if (!wildp && (trash.area[i] == '.'))
2485 wildp = &trash.area[i];
Emeric Brunfc0421f2012-09-07 17:30:07 +02002486 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002487 trash.area[i] = 0;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002488
Emmanuel Hocdet26b7b802019-11-04 15:49:46 +01002489 node = NULL;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002490 /* lookup in full qualified names */
Emmanuel Hocdet26b7b802019-11-04 15:49:46 +01002491 for (n = ebst_lookup(&s->sni_ctx, trash.area); n; n = ebmb_next_dup(n)) {
2492 /* lookup a not neg filter */
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002493 if (!container_of(n, struct sni_ctx, name)->neg) {
2494 node = n;
2495 break;
Emmanuel Hocdet65623372013-01-24 17:17:15 +01002496 }
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002497 }
2498 if (!node && wildp) {
2499 /* lookup in wildcards names */
Emmanuel Hocdet26b7b802019-11-04 15:49:46 +01002500 for (n = ebst_lookup(&s->sni_w_ctx, wildp); n; n = ebmb_next_dup(n)) {
2501 /* lookup a not neg filter */
2502 if (!container_of(n, struct sni_ctx, name)->neg) {
2503 node = n;
2504 break;
2505 }
2506 }
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002507 }
Emmanuel Hocdet26b7b802019-11-04 15:49:46 +01002508 if (!node) {
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002509#if (!defined SSL_NO_GENERATE_CERTIFICATES)
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002510 if (s->generate_certs && ssl_sock_generate_certificate(servername, s, ssl)) {
2511 /* switch ctx done in ssl_sock_generate_certificate */
Christopher Faulet31af49d2015-06-09 17:29:50 +02002512 return SSL_TLSEXT_ERR_OK;
2513 }
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002514#endif
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002515 if (s->strict_sni)
2516 return SSL_TLSEXT_ERR_ALERT_FATAL;
2517 ssl_sock_switchctx_set(ssl, s->default_ctx);
2518 return SSL_TLSEXT_ERR_OK;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002519 }
2520
2521 /* switch ctx */
Emmanuel Hocdet530141f2017-03-01 18:54:56 +01002522 ssl_sock_switchctx_set(ssl, container_of(node, struct sni_ctx, name)->ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02002523 return SSL_TLSEXT_ERR_OK;
2524}
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002525#endif /* (!) OPENSSL_IS_BORINGSSL */
Emeric Brunfc0421f2012-09-07 17:30:07 +02002526#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
2527
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002528#ifndef OPENSSL_NO_DH
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002529
2530static DH * ssl_get_dh_1024(void)
2531{
Remi Gacogned3a341a2015-05-29 16:26:17 +02002532 static unsigned char dh1024_p[]={
2533 0xFA,0xF9,0x2A,0x22,0x2A,0xA7,0x7F,0xE1,0x67,0x4E,0x53,0xF7,
2534 0x56,0x13,0xC3,0xB1,0xE3,0x29,0x6B,0x66,0x31,0x6A,0x7F,0xB3,
2535 0xC2,0x68,0x6B,0xCB,0x1D,0x57,0x39,0x1D,0x1F,0xFF,0x1C,0xC9,
2536 0xA6,0xA4,0x98,0x82,0x31,0x5D,0x25,0xFF,0x8A,0xE0,0x73,0x96,
2537 0x81,0xC8,0x83,0x79,0xC1,0x5A,0x04,0xF8,0x37,0x0D,0xA8,0x3D,
2538 0xAE,0x74,0xBC,0xDB,0xB6,0xA4,0x75,0xD9,0x71,0x8A,0xA0,0x17,
2539 0x9E,0x2D,0xC8,0xA8,0xDF,0x2C,0x5F,0x82,0x95,0xF8,0x92,0x9B,
2540 0xA7,0x33,0x5F,0x89,0x71,0xC8,0x2D,0x6B,0x18,0x86,0xC4,0x94,
2541 0x22,0xA5,0x52,0x8D,0xF6,0xF6,0xD2,0x37,0x92,0x0F,0xA5,0xCC,
2542 0xDB,0x7B,0x1D,0x3D,0xA1,0x31,0xB7,0x80,0x8F,0x0B,0x67,0x5E,
2543 0x36,0xA5,0x60,0x0C,0xF1,0x95,0x33,0x8B,
2544 };
2545 static unsigned char dh1024_g[]={
2546 0x02,
2547 };
2548
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002549 BIGNUM *p;
2550 BIGNUM *g;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002551 DH *dh = DH_new();
2552 if (dh) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002553 p = BN_bin2bn(dh1024_p, sizeof dh1024_p, NULL);
2554 g = BN_bin2bn(dh1024_g, sizeof dh1024_g, NULL);
Remi Gacogned3a341a2015-05-29 16:26:17 +02002555
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002556 if (!p || !g) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002557 DH_free(dh);
2558 dh = NULL;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002559 } else {
2560 DH_set0_pqg(dh, p, NULL, g);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002561 }
2562 }
2563 return dh;
2564}
2565
2566static DH *ssl_get_dh_2048(void)
2567{
Remi Gacogned3a341a2015-05-29 16:26:17 +02002568 static unsigned char dh2048_p[]={
2569 0xEC,0x86,0xF8,0x70,0xA0,0x33,0x16,0xEC,0x05,0x1A,0x73,0x59,
2570 0xCD,0x1F,0x8B,0xF8,0x29,0xE4,0xD2,0xCF,0x52,0xDD,0xC2,0x24,
2571 0x8D,0xB5,0x38,0x9A,0xFB,0x5C,0xA4,0xE4,0xB2,0xDA,0xCE,0x66,
2572 0x50,0x74,0xA6,0x85,0x4D,0x4B,0x1D,0x30,0xB8,0x2B,0xF3,0x10,
2573 0xE9,0xA7,0x2D,0x05,0x71,0xE7,0x81,0xDF,0x8B,0x59,0x52,0x3B,
2574 0x5F,0x43,0x0B,0x68,0xF1,0xDB,0x07,0xBE,0x08,0x6B,0x1B,0x23,
2575 0xEE,0x4D,0xCC,0x9E,0x0E,0x43,0xA0,0x1E,0xDF,0x43,0x8C,0xEC,
2576 0xBE,0xBE,0x90,0xB4,0x51,0x54,0xB9,0x2F,0x7B,0x64,0x76,0x4E,
2577 0x5D,0xD4,0x2E,0xAE,0xC2,0x9E,0xAE,0x51,0x43,0x59,0xC7,0x77,
2578 0x9C,0x50,0x3C,0x0E,0xED,0x73,0x04,0x5F,0xF1,0x4C,0x76,0x2A,
2579 0xD8,0xF8,0xCF,0xFC,0x34,0x40,0xD1,0xB4,0x42,0x61,0x84,0x66,
2580 0x42,0x39,0x04,0xF8,0x68,0xB2,0x62,0xD7,0x55,0xED,0x1B,0x74,
2581 0x75,0x91,0xE0,0xC5,0x69,0xC1,0x31,0x5C,0xDB,0x7B,0x44,0x2E,
2582 0xCE,0x84,0x58,0x0D,0x1E,0x66,0x0C,0xC8,0x44,0x9E,0xFD,0x40,
2583 0x08,0x67,0x5D,0xFB,0xA7,0x76,0x8F,0x00,0x11,0x87,0xE9,0x93,
2584 0xF9,0x7D,0xC4,0xBC,0x74,0x55,0x20,0xD4,0x4A,0x41,0x2F,0x43,
2585 0x42,0x1A,0xC1,0xF2,0x97,0x17,0x49,0x27,0x37,0x6B,0x2F,0x88,
2586 0x7E,0x1C,0xA0,0xA1,0x89,0x92,0x27,0xD9,0x56,0x5A,0x71,0xC1,
2587 0x56,0x37,0x7E,0x3A,0x9D,0x05,0xE7,0xEE,0x5D,0x8F,0x82,0x17,
2588 0xBC,0xE9,0xC2,0x93,0x30,0x82,0xF9,0xF4,0xC9,0xAE,0x49,0xDB,
2589 0xD0,0x54,0xB4,0xD9,0x75,0x4D,0xFA,0x06,0xB8,0xD6,0x38,0x41,
2590 0xB7,0x1F,0x77,0xF3,
2591 };
2592 static unsigned char dh2048_g[]={
2593 0x02,
2594 };
2595
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002596 BIGNUM *p;
2597 BIGNUM *g;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002598 DH *dh = DH_new();
2599 if (dh) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002600 p = BN_bin2bn(dh2048_p, sizeof dh2048_p, NULL);
2601 g = BN_bin2bn(dh2048_g, sizeof dh2048_g, NULL);
Remi Gacogned3a341a2015-05-29 16:26:17 +02002602
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002603 if (!p || !g) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002604 DH_free(dh);
2605 dh = NULL;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002606 } else {
2607 DH_set0_pqg(dh, p, NULL, g);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002608 }
2609 }
2610 return dh;
2611}
2612
2613static DH *ssl_get_dh_4096(void)
2614{
Remi Gacogned3a341a2015-05-29 16:26:17 +02002615 static unsigned char dh4096_p[]={
2616 0xDE,0x16,0x94,0xCD,0x99,0x58,0x07,0xF1,0xF7,0x32,0x96,0x11,
2617 0x04,0x82,0xD4,0x84,0x72,0x80,0x99,0x06,0xCA,0xF0,0xA3,0x68,
2618 0x07,0xCE,0x64,0x50,0xE7,0x74,0x45,0x20,0x80,0x5E,0x4D,0xAD,
2619 0xA5,0xB6,0xED,0xFA,0x80,0x6C,0x3B,0x35,0xC4,0x9A,0x14,0x6B,
2620 0x32,0xBB,0xFD,0x1F,0x17,0x8E,0xB7,0x1F,0xD6,0xFA,0x3F,0x7B,
2621 0xEE,0x16,0xA5,0x62,0x33,0x0D,0xED,0xBC,0x4E,0x58,0xE5,0x47,
2622 0x4D,0xE9,0xAB,0x8E,0x38,0xD3,0x6E,0x90,0x57,0xE3,0x22,0x15,
2623 0x33,0xBD,0xF6,0x43,0x45,0xB5,0x10,0x0A,0xBE,0x2C,0xB4,0x35,
2624 0xB8,0x53,0x8D,0xAD,0xFB,0xA7,0x1F,0x85,0x58,0x41,0x7A,0x79,
2625 0x20,0x68,0xB3,0xE1,0x3D,0x08,0x76,0xBF,0x86,0x0D,0x49,0xE3,
2626 0x82,0x71,0x8C,0xB4,0x8D,0x81,0x84,0xD4,0xE7,0xBE,0x91,0xDC,
2627 0x26,0x39,0x48,0x0F,0x35,0xC4,0xCA,0x65,0xE3,0x40,0x93,0x52,
2628 0x76,0x58,0x7D,0xDD,0x51,0x75,0xDC,0x69,0x61,0xBF,0x47,0x2C,
2629 0x16,0x68,0x2D,0xC9,0x29,0xD3,0xE6,0xC0,0x99,0x48,0xA0,0x9A,
2630 0xC8,0x78,0xC0,0x6D,0x81,0x67,0x12,0x61,0x3F,0x71,0xBA,0x41,
2631 0x1F,0x6C,0x89,0x44,0x03,0xBA,0x3B,0x39,0x60,0xAA,0x28,0x55,
2632 0x59,0xAE,0xB8,0xFA,0xCB,0x6F,0xA5,0x1A,0xF7,0x2B,0xDD,0x52,
2633 0x8A,0x8B,0xE2,0x71,0xA6,0x5E,0x7E,0xD8,0x2E,0x18,0xE0,0x66,
2634 0xDF,0xDD,0x22,0x21,0x99,0x52,0x73,0xA6,0x33,0x20,0x65,0x0E,
2635 0x53,0xE7,0x6B,0x9B,0xC5,0xA3,0x2F,0x97,0x65,0x76,0xD3,0x47,
2636 0x23,0x77,0x12,0xB6,0x11,0x7B,0x24,0xED,0xF1,0xEF,0xC0,0xE2,
2637 0xA3,0x7E,0x67,0x05,0x3E,0x96,0x4D,0x45,0xC2,0x18,0xD1,0x73,
2638 0x9E,0x07,0xF3,0x81,0x6E,0x52,0x63,0xF6,0x20,0x76,0xB9,0x13,
2639 0xD2,0x65,0x30,0x18,0x16,0x09,0x16,0x9E,0x8F,0xF1,0xD2,0x10,
2640 0x5A,0xD3,0xD4,0xAF,0x16,0x61,0xDA,0x55,0x2E,0x18,0x5E,0x14,
2641 0x08,0x54,0x2E,0x2A,0x25,0xA2,0x1A,0x9B,0x8B,0x32,0xA9,0xFD,
2642 0xC2,0x48,0x96,0xE1,0x80,0xCA,0xE9,0x22,0x17,0xBB,0xCE,0x3E,
2643 0x9E,0xED,0xC7,0xF1,0x1F,0xEC,0x17,0x21,0xDC,0x7B,0x82,0x48,
2644 0x8E,0xBB,0x4B,0x9D,0x5B,0x04,0x04,0xDA,0xDB,0x39,0xDF,0x01,
2645 0x40,0xC3,0xAA,0x26,0x23,0x89,0x75,0xC6,0x0B,0xD0,0xA2,0x60,
2646 0x6A,0xF1,0xCC,0x65,0x18,0x98,0x1B,0x52,0xD2,0x74,0x61,0xCC,
2647 0xBD,0x60,0xAE,0xA3,0xA0,0x66,0x6A,0x16,0x34,0x92,0x3F,0x41,
2648 0x40,0x31,0x29,0xC0,0x2C,0x63,0xB2,0x07,0x8D,0xEB,0x94,0xB8,
2649 0xE8,0x47,0x92,0x52,0x93,0x6A,0x1B,0x7E,0x1A,0x61,0xB3,0x1B,
2650 0xF0,0xD6,0x72,0x9B,0xF1,0xB0,0xAF,0xBF,0x3E,0x65,0xEF,0x23,
2651 0x1D,0x6F,0xFF,0x70,0xCD,0x8A,0x4C,0x8A,0xA0,0x72,0x9D,0xBE,
2652 0xD4,0xBB,0x24,0x47,0x4A,0x68,0xB5,0xF5,0xC6,0xD5,0x7A,0xCD,
2653 0xCA,0x06,0x41,0x07,0xAD,0xC2,0x1E,0xE6,0x54,0xA7,0xAD,0x03,
2654 0xD9,0x12,0xC1,0x9C,0x13,0xB1,0xC9,0x0A,0x43,0x8E,0x1E,0x08,
2655 0xCE,0x50,0x82,0x73,0x5F,0xA7,0x55,0x1D,0xD9,0x59,0xAC,0xB5,
2656 0xEA,0x02,0x7F,0x6C,0x5B,0x74,0x96,0x98,0x67,0x24,0xA3,0x0F,
2657 0x15,0xFC,0xA9,0x7D,0x3E,0x67,0xD1,0x70,0xF8,0x97,0xF3,0x67,
2658 0xC5,0x8C,0x88,0x44,0x08,0x02,0xC7,0x2B,
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002659 };
Remi Gacogned3a341a2015-05-29 16:26:17 +02002660 static unsigned char dh4096_g[]={
2661 0x02,
2662 };
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002663
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002664 BIGNUM *p;
2665 BIGNUM *g;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002666 DH *dh = DH_new();
2667 if (dh) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002668 p = BN_bin2bn(dh4096_p, sizeof dh4096_p, NULL);
2669 g = BN_bin2bn(dh4096_g, sizeof dh4096_g, NULL);
Remi Gacogned3a341a2015-05-29 16:26:17 +02002670
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002671 if (!p || !g) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002672 DH_free(dh);
2673 dh = NULL;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002674 } else {
2675 DH_set0_pqg(dh, p, NULL, g);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002676 }
2677 }
2678 return dh;
2679}
2680
2681/* Returns Diffie-Hellman parameters matching the private key length
Willy Tarreauef934602016-12-22 23:12:01 +01002682 but not exceeding global_ssl.default_dh_param */
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002683static DH *ssl_get_tmp_dh(SSL *ssl, int export, int keylen)
2684{
2685 DH *dh = NULL;
2686 EVP_PKEY *pkey = SSL_get_privatekey(ssl);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002687 int type;
2688
2689 type = pkey ? EVP_PKEY_base_id(pkey) : EVP_PKEY_NONE;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002690
2691 /* The keylen supplied by OpenSSL can only be 512 or 1024.
2692 See ssl3_send_server_key_exchange() in ssl/s3_srvr.c
2693 */
2694 if (type == EVP_PKEY_RSA || type == EVP_PKEY_DSA) {
2695 keylen = EVP_PKEY_bits(pkey);
2696 }
2697
Willy Tarreauef934602016-12-22 23:12:01 +01002698 if (keylen > global_ssl.default_dh_param) {
2699 keylen = global_ssl.default_dh_param;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002700 }
2701
Remi Gacogned3a341a2015-05-29 16:26:17 +02002702 if (keylen >= 4096) {
Remi Gacogne8de54152014-07-15 11:36:40 +02002703 dh = local_dh_4096;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002704 }
2705 else if (keylen >= 2048) {
Remi Gacogne8de54152014-07-15 11:36:40 +02002706 dh = local_dh_2048;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002707 }
2708 else {
Remi Gacogne8de54152014-07-15 11:36:40 +02002709 dh = local_dh_1024;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002710 }
2711
2712 return dh;
2713}
2714
Remi Gacogne47783ef2015-05-29 15:53:22 +02002715static DH * ssl_sock_get_dh_from_file(const char *filename)
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002716{
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002717 DH *dh = NULL;
Remi Gacogne47783ef2015-05-29 15:53:22 +02002718 BIO *in = BIO_new(BIO_s_file());
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002719
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002720 if (in == NULL)
2721 goto end;
2722
Remi Gacogne47783ef2015-05-29 15:53:22 +02002723 if (BIO_read_filename(in, filename) <= 0)
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002724 goto end;
2725
Remi Gacogne47783ef2015-05-29 15:53:22 +02002726 dh = PEM_read_bio_DHparams(in, NULL, NULL, NULL);
2727
2728end:
2729 if (in)
2730 BIO_free(in);
2731
Emeric Brune1b4ed42018-08-16 15:14:12 +02002732 ERR_clear_error();
2733
Remi Gacogne47783ef2015-05-29 15:53:22 +02002734 return dh;
2735}
2736
2737int ssl_sock_load_global_dh_param_from_file(const char *filename)
2738{
2739 global_dh = ssl_sock_get_dh_from_file(filename);
2740
2741 if (global_dh) {
2742 return 0;
2743 }
2744
2745 return -1;
2746}
2747
Emeric Bruncfc1afe2019-10-17 13:27:40 +02002748/* Loads Diffie-Hellman parameter from a ckchs to an SSL_CTX.
2749 * If there is no DH paramater availaible in the ckchs, the global
2750 * DH parameter is loaded into the SSL_CTX and if there is no
2751 * DH parameter available in ckchs nor in global, the default
2752 * DH parameters are applied on the SSL_CTX.
2753 * Returns a bitfield containing the flags:
2754 * ERR_FATAL in any fatal error case
2755 * ERR_ALERT if a reason of the error is availabine in err
2756 * ERR_WARN if a warning is available into err
2757 * The value 0 means there is no error nor warning and
2758 * the operation succeed.
2759 */
2760static int ssl_sock_load_dh_params(SSL_CTX *ctx, const char *file, char **err)
2761 {
2762 int ret = 0;
Remi Gacogne47783ef2015-05-29 15:53:22 +02002763 DH *dh = ssl_sock_get_dh_from_file(file);
2764
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002765 if (dh) {
Emeric Brund6de1512019-10-17 14:53:03 +02002766 if (!SSL_CTX_set_tmp_dh(ctx, dh)) {
2767 memprintf(err, "%sunable to load the DH parameter specified in '%s'",
2768 err && *err ? *err : "", file);
2769#if defined(SSL_CTX_set_dh_auto)
2770 SSL_CTX_set_dh_auto(ctx, 1);
2771 memprintf(err, "%s, SSL library will use an automatically generated DH parameter.\n",
2772 err && *err ? *err : "");
2773#else
2774 memprintf(err, "%s, DH ciphers won't be available.\n",
2775 err && *err ? *err : "");
2776#endif
2777 ret |= ERR_WARN;
2778 goto end;
2779 }
Remi Gacogne4f902b82015-05-28 16:23:00 +02002780
2781 if (ssl_dh_ptr_index >= 0) {
2782 /* store a pointer to the DH params to avoid complaining about
2783 ssl-default-dh-param not being set for this SSL_CTX */
2784 SSL_CTX_set_ex_data(ctx, ssl_dh_ptr_index, dh);
2785 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002786 }
Remi Gacogne47783ef2015-05-29 15:53:22 +02002787 else if (global_dh) {
Emeric Brund6de1512019-10-17 14:53:03 +02002788 if (!SSL_CTX_set_tmp_dh(ctx, global_dh)) {
2789 memprintf(err, "%sunable to use the global DH parameter for certificate '%s'",
2790 err && *err ? *err : "", file);
2791#if defined(SSL_CTX_set_dh_auto)
2792 SSL_CTX_set_dh_auto(ctx, 1);
2793 memprintf(err, "%s, SSL library will use an automatically generated DH parameter.\n",
2794 err && *err ? *err : "");
2795#else
2796 memprintf(err, "%s, DH ciphers won't be available.\n",
2797 err && *err ? *err : "");
2798#endif
2799 ret |= ERR_WARN;
2800 goto end;
2801 }
Remi Gacogne47783ef2015-05-29 15:53:22 +02002802 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002803 else {
Emeric Brun41fdb3c2013-04-26 11:05:44 +02002804 /* Clear openssl global errors stack */
2805 ERR_clear_error();
2806
Willy Tarreauef934602016-12-22 23:12:01 +01002807 if (global_ssl.default_dh_param <= 1024) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002808 /* we are limited to DH parameter of 1024 bits anyway */
Remi Gacognec7e12632016-07-02 16:26:10 +02002809 if (local_dh_1024 == NULL)
2810 local_dh_1024 = ssl_get_dh_1024();
2811
Emeric Bruncfc1afe2019-10-17 13:27:40 +02002812 if (local_dh_1024 == NULL) {
2813 memprintf(err, "%sunable to load default 1024 bits DH parameter for certificate '%s'.\n",
2814 err && *err ? *err : "", file);
2815 ret |= ERR_ALERT | ERR_FATAL;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002816 goto end;
Emeric Bruncfc1afe2019-10-17 13:27:40 +02002817 }
Willy Tarreau6e774b42014-04-25 21:35:23 +02002818
Emeric Brund6de1512019-10-17 14:53:03 +02002819 if (!SSL_CTX_set_tmp_dh(ctx, local_dh_1024)) {
2820 memprintf(err, "%sunable to load default 1024 bits DH parameter for certificate '%s'.\n",
2821 err && *err ? *err : "", file);
2822#if defined(SSL_CTX_set_dh_auto)
2823 SSL_CTX_set_dh_auto(ctx, 1);
2824 memprintf(err, "%s, SSL library will use an automatically generated DH parameter.\n",
2825 err && *err ? *err : "");
2826#else
2827 memprintf(err, "%s, DH ciphers won't be available.\n",
2828 err && *err ? *err : "");
2829#endif
2830 ret |= ERR_WARN;
2831 goto end;
2832 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002833 }
2834 else {
2835 SSL_CTX_set_tmp_dh_callback(ctx, ssl_get_tmp_dh);
2836 }
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002837 }
Emeric Brun644cde02012-12-14 11:21:13 +01002838
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002839end:
2840 if (dh)
2841 DH_free(dh);
2842
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002843 return ret;
2844}
2845#endif
2846
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002847static int ssl_sock_add_cert_sni(SSL_CTX *ctx, struct bind_conf *s, struct ssl_bind_conf *conf,
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002848 struct pkey_info kinfo, char *name, int order)
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002849{
2850 struct sni_ctx *sc;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002851 int wild = 0, neg = 0;
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002852 struct ebmb_node *node;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002853
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002854 if (*name == '!') {
2855 neg = 1;
2856 name++;
2857 }
2858 if (*name == '*') {
2859 wild = 1;
2860 name++;
2861 }
2862 /* !* filter is a nop */
2863 if (neg && wild)
2864 return order;
2865 if (*name) {
2866 int j, len;
2867 len = strlen(name);
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002868 for (j = 0; j < len && j < trash.size; j++)
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002869 trash.area[j] = tolower(name[j]);
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002870 if (j >= trash.size)
William Lallemand24e292c2019-10-03 23:46:33 +02002871 return -1;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002872 trash.area[j] = 0;
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002873
2874 /* Check for duplicates. */
2875 if (wild)
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002876 node = ebst_lookup(&s->sni_w_ctx, trash.area);
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002877 else
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002878 node = ebst_lookup(&s->sni_ctx, trash.area);
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002879 for (; node; node = ebmb_next_dup(node)) {
2880 sc = ebmb_entry(node, struct sni_ctx, name);
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002881 if (sc->ctx == ctx && sc->conf == conf && sc->neg == neg)
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002882 return order;
2883 }
2884
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002885 sc = malloc(sizeof(struct sni_ctx) + len + 1);
Thierry FOURNIER / OZON.IO7a3bd3b2016-10-06 10:35:29 +02002886 if (!sc)
William Lallemand24e292c2019-10-03 23:46:33 +02002887 return -1;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002888 memcpy(sc->name.key, trash.area, len + 1);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002889 sc->ctx = ctx;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01002890 sc->conf = conf;
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002891 sc->kinfo = kinfo;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002892 sc->order = order++;
2893 sc->neg = neg;
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01002894 if (kinfo.sig != TLSEXT_signature_anonymous)
2895 SSL_CTX_set_ex_data(ctx, ssl_pkey_info_index, &sc->kinfo);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002896 if (wild)
2897 ebst_insert(&s->sni_w_ctx, &sc->name);
2898 else
2899 ebst_insert(&s->sni_ctx, &sc->name);
2900 }
2901 return order;
2902}
2903
yanbzhu488a4d22015-12-01 15:16:07 -05002904
2905/* The following code is used for loading multiple crt files into
2906 * SSL_CTX's based on CN/SAN
2907 */
Willy Tarreau5db847a2019-05-09 14:13:35 +02002908#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
yanbzhu488a4d22015-12-01 15:16:07 -05002909/* This is used to preload the certifcate, private key
2910 * and Cert Chain of a file passed in via the crt
2911 * argument
2912 *
2913 * This way, we do not have to read the file multiple times
2914 */
2915struct cert_key_and_chain {
2916 X509 *cert;
2917 EVP_PKEY *key;
2918 unsigned int num_chain_certs;
2919 /* This is an array of X509 pointers */
2920 X509 **chain_certs;
2921};
2922
yanbzhu08ce6ab2015-12-02 13:01:29 -05002923#define SSL_SOCK_POSSIBLE_KT_COMBOS (1<<(SSL_SOCK_NUM_KEYTYPES))
2924
2925struct key_combo_ctx {
2926 SSL_CTX *ctx;
2927 int order;
2928};
2929
2930/* Map used for processing multiple keypairs for a single purpose
2931 *
2932 * This maps CN/SNI name to certificate type
2933 */
2934struct sni_keytype {
2935 int keytypes; /* BITMASK for keytypes */
2936 struct ebmb_node name; /* node holding the servername value */
2937};
2938
2939
yanbzhu488a4d22015-12-01 15:16:07 -05002940/* Frees the contents of a cert_key_and_chain
2941 */
2942static void ssl_sock_free_cert_key_and_chain_contents(struct cert_key_and_chain *ckch)
2943{
2944 int i;
2945
2946 if (!ckch)
2947 return;
2948
2949 /* Free the certificate and set pointer to NULL */
2950 if (ckch->cert)
2951 X509_free(ckch->cert);
2952 ckch->cert = NULL;
2953
2954 /* Free the key and set pointer to NULL */
2955 if (ckch->key)
2956 EVP_PKEY_free(ckch->key);
2957 ckch->key = NULL;
2958
2959 /* Free each certificate in the chain */
2960 for (i = 0; i < ckch->num_chain_certs; i++) {
2961 if (ckch->chain_certs[i])
2962 X509_free(ckch->chain_certs[i]);
2963 }
2964
2965 /* Free the chain obj itself and set to NULL */
2966 if (ckch->num_chain_certs > 0) {
2967 free(ckch->chain_certs);
2968 ckch->num_chain_certs = 0;
2969 ckch->chain_certs = NULL;
2970 }
2971
2972}
2973
2974/* checks if a key and cert exists in the ckch
2975 */
2976static int ssl_sock_is_ckch_valid(struct cert_key_and_chain *ckch)
2977{
2978 return (ckch->cert != NULL && ckch->key != NULL);
2979}
2980
2981
2982/* Loads the contents of a crt file (path) into a cert_key_and_chain
2983 * This allows us to carry the contents of the file without having to
2984 * read the file multiple times.
2985 *
2986 * returns:
2987 * 0 on Success
2988 * 1 on SSL Failure
2989 * 2 on file not found
2990 */
2991static int ssl_sock_load_crt_file_into_ckch(const char *path, struct cert_key_and_chain *ckch, char **err)
2992{
2993
2994 BIO *in;
2995 X509 *ca = NULL;
2996 int ret = 1;
2997
2998 ssl_sock_free_cert_key_and_chain_contents(ckch);
2999
3000 in = BIO_new(BIO_s_file());
3001 if (in == NULL)
3002 goto end;
3003
3004 if (BIO_read_filename(in, path) <= 0)
3005 goto end;
3006
yanbzhu488a4d22015-12-01 15:16:07 -05003007 /* Read Private Key */
3008 ckch->key = PEM_read_bio_PrivateKey(in, NULL, NULL, NULL);
3009 if (ckch->key == NULL) {
3010 memprintf(err, "%sunable to load private key from file '%s'.\n",
3011 err && *err ? *err : "", path);
3012 goto end;
3013 }
3014
Willy Tarreaubb137a82016-04-06 19:02:38 +02003015 /* Seek back to beginning of file */
Thierry FOURNIER / OZON.IOd44ea3f2016-10-14 00:49:21 +02003016 if (BIO_reset(in) == -1) {
3017 memprintf(err, "%san error occurred while reading the file '%s'.\n",
3018 err && *err ? *err : "", path);
3019 goto end;
3020 }
Willy Tarreaubb137a82016-04-06 19:02:38 +02003021
3022 /* Read Certificate */
3023 ckch->cert = PEM_read_bio_X509_AUX(in, NULL, NULL, NULL);
3024 if (ckch->cert == NULL) {
3025 memprintf(err, "%sunable to load certificate from file '%s'.\n",
3026 err && *err ? *err : "", path);
3027 goto end;
3028 }
3029
yanbzhu488a4d22015-12-01 15:16:07 -05003030 /* Read Certificate Chain */
3031 while ((ca = PEM_read_bio_X509(in, NULL, NULL, NULL))) {
3032 /* Grow the chain certs */
3033 ckch->num_chain_certs++;
3034 ckch->chain_certs = realloc(ckch->chain_certs, (ckch->num_chain_certs * sizeof(X509 *)));
3035
3036 /* use - 1 here since we just incremented it above */
3037 ckch->chain_certs[ckch->num_chain_certs - 1] = ca;
3038 }
3039 ret = ERR_get_error();
3040 if (ret && (ERR_GET_LIB(ret) != ERR_LIB_PEM && ERR_GET_REASON(ret) != PEM_R_NO_START_LINE)) {
3041 memprintf(err, "%sunable to load certificate chain from file '%s'.\n",
3042 err && *err ? *err : "", path);
3043 ret = 1;
3044 goto end;
3045 }
3046
3047 ret = 0;
3048
3049end:
3050
3051 ERR_clear_error();
3052 if (in)
3053 BIO_free(in);
3054
3055 /* Something went wrong in one of the reads */
3056 if (ret != 0)
3057 ssl_sock_free_cert_key_and_chain_contents(ckch);
3058
3059 return ret;
3060}
3061
3062/* Loads the info in ckch into ctx
Emeric Brun394701d2019-10-17 13:25:14 +02003063 * Returns a bitfield containing the flags:
3064 * ERR_FATAL in any fatal error case
3065 * ERR_ALERT if the reason of the error is available in err
3066 * ERR_WARN if a warning is available into err
3067 * The value 0 means there is no error nor warning and
3068 * the operation succeed.
yanbzhu488a4d22015-12-01 15:16:07 -05003069 */
3070static int ssl_sock_put_ckch_into_ctx(const char *path, const struct cert_key_and_chain *ckch, SSL_CTX *ctx, char **err)
3071{
3072 int i = 0;
Emeric Brun394701d2019-10-17 13:25:14 +02003073 int errcode = 0;
yanbzhu488a4d22015-12-01 15:16:07 -05003074
3075 if (SSL_CTX_use_PrivateKey(ctx, ckch->key) <= 0) {
3076 memprintf(err, "%sunable to load SSL private key into SSL Context '%s'.\n",
3077 err && *err ? *err : "", path);
Emeric Brun394701d2019-10-17 13:25:14 +02003078 errcode |= ERR_ALERT | ERR_FATAL;
3079 return errcode;
yanbzhu488a4d22015-12-01 15:16:07 -05003080 }
3081
3082 if (!SSL_CTX_use_certificate(ctx, ckch->cert)) {
3083 memprintf(err, "%sunable to load SSL certificate into SSL Context '%s'.\n",
3084 err && *err ? *err : "", path);
Emeric Brun394701d2019-10-17 13:25:14 +02003085 errcode |= ERR_ALERT | ERR_FATAL;
3086 goto end;
yanbzhu488a4d22015-12-01 15:16:07 -05003087 }
3088
yanbzhu488a4d22015-12-01 15:16:07 -05003089 /* Load all certs in the ckch into the ctx_chain for the ssl_ctx */
3090 for (i = 0; i < ckch->num_chain_certs; i++) {
3091 if (!SSL_CTX_add1_chain_cert(ctx, ckch->chain_certs[i])) {
yanbzhu08ce6ab2015-12-02 13:01:29 -05003092 memprintf(err, "%sunable to load chain certificate #%d into SSL Context '%s'. Make sure you are linking against Openssl >= 1.0.2.\n",
3093 err && *err ? *err : "", (i+1), path);
Emeric Brun394701d2019-10-17 13:25:14 +02003094 errcode |= ERR_ALERT | ERR_FATAL;
3095 goto end;
yanbzhu488a4d22015-12-01 15:16:07 -05003096 }
3097 }
3098
3099 if (SSL_CTX_check_private_key(ctx) <= 0) {
3100 memprintf(err, "%sinconsistencies between private key and certificate loaded from PEM file '%s'.\n",
3101 err && *err ? *err : "", path);
Emeric Brun394701d2019-10-17 13:25:14 +02003102 errcode |= ERR_ALERT | ERR_FATAL;
yanbzhu488a4d22015-12-01 15:16:07 -05003103 }
3104
Emeric Brun394701d2019-10-17 13:25:14 +02003105 end:
3106 return errcode;
yanbzhu488a4d22015-12-01 15:16:07 -05003107}
3108
yanbzhu08ce6ab2015-12-02 13:01:29 -05003109
William Lallemand4801c702019-10-04 17:36:55 +02003110static int ssl_sock_populate_sni_keytypes_hplr(const char *str, struct eb_root *sni_keytypes, int key_index)
yanbzhu08ce6ab2015-12-02 13:01:29 -05003111{
3112 struct sni_keytype *s_kt = NULL;
3113 struct ebmb_node *node;
3114 int i;
3115
3116 for (i = 0; i < trash.size; i++) {
3117 if (!str[i])
3118 break;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02003119 trash.area[i] = tolower(str[i]);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003120 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +02003121 trash.area[i] = 0;
3122 node = ebst_lookup(sni_keytypes, trash.area);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003123 if (!node) {
3124 /* CN not found in tree */
3125 s_kt = malloc(sizeof(struct sni_keytype) + i + 1);
3126 /* Using memcpy here instead of strncpy.
3127 * strncpy will cause sig_abrt errors under certain versions of gcc with -O2
3128 * See: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=60792
3129 */
William Lallemand4801c702019-10-04 17:36:55 +02003130 if (!s_kt)
3131 return -1;
3132
Willy Tarreau843b7cb2018-07-13 10:54:26 +02003133 memcpy(s_kt->name.key, trash.area, i+1);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003134 s_kt->keytypes = 0;
3135 ebst_insert(sni_keytypes, &s_kt->name);
3136 } else {
3137 /* CN found in tree */
3138 s_kt = container_of(node, struct sni_keytype, name);
3139 }
3140
3141 /* Mark that this CN has the keytype of key_index via keytypes mask */
3142 s_kt->keytypes |= 1<<key_index;
3143
William Lallemand4801c702019-10-04 17:36:55 +02003144 return 0;
3145
yanbzhu08ce6ab2015-12-02 13:01:29 -05003146}
3147
3148
3149/* Given a path that does not exist, try to check for path.rsa, path.dsa and path.ecdsa files.
3150 * If any are found, group these files into a set of SSL_CTX*
3151 * based on shared and unique CN and SAN entries. Add these SSL_CTX* to the SNI tree.
3152 *
Joseph Herlant017b3da2018-11-15 09:07:59 -08003153 * This will allow the user to explicitly group multiple cert/keys for a single purpose
yanbzhu08ce6ab2015-12-02 13:01:29 -05003154 *
Willy Tarreaub131c872019-10-16 16:42:19 +02003155 * Returns a set of ERR_* flags possibly with an error in <err>.
3156 *
yanbzhu08ce6ab2015-12-02 13:01:29 -05003157 */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003158static int ssl_sock_load_multi_cert(const char *path, struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
3159 char **sni_filter, int fcount, char **err)
yanbzhu08ce6ab2015-12-02 13:01:29 -05003160{
3161 char fp[MAXPATHLEN+1] = {0};
3162 int n = 0;
3163 int i = 0;
3164 struct cert_key_and_chain certs_and_keys[SSL_SOCK_NUM_KEYTYPES] = { {0} };
3165 struct eb_root sni_keytypes_map = { {0} };
3166 struct ebmb_node *node;
3167 struct ebmb_node *next;
3168 /* Array of SSL_CTX pointers corresponding to each possible combo
3169 * of keytypes
3170 */
3171 struct key_combo_ctx key_combos[SSL_SOCK_POSSIBLE_KT_COMBOS] = { {0} };
Willy Tarreaub131c872019-10-16 16:42:19 +02003172 int errcode = 0;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003173 X509_NAME *xname = NULL;
3174 char *str = NULL;
3175#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
3176 STACK_OF(GENERAL_NAME) *names = NULL;
3177#endif
3178
3179 /* Load all possible certs and keys */
3180 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
3181 struct stat buf;
3182
3183 snprintf(fp, sizeof(fp), "%s.%s", path, SSL_SOCK_KEYTYPE_NAMES[n]);
3184 if (stat(fp, &buf) == 0) {
3185 if (ssl_sock_load_crt_file_into_ckch(fp, &certs_and_keys[n], err) == 1) {
Willy Tarreaub131c872019-10-16 16:42:19 +02003186 errcode |= ERR_ALERT | ERR_FATAL;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003187 goto end;
3188 }
3189 }
3190 }
3191
3192 /* Process each ckch and update keytypes for each CN/SAN
3193 * for example, if CN/SAN www.a.com is associated with
3194 * certs with keytype 0 and 2, then at the end of the loop,
3195 * www.a.com will have:
3196 * keyindex = 0 | 1 | 4 = 5
3197 */
3198 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
William Lallemand4801c702019-10-04 17:36:55 +02003199 int ret;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003200
3201 if (!ssl_sock_is_ckch_valid(&certs_and_keys[n]))
3202 continue;
3203
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003204 if (fcount) {
William Lallemand4801c702019-10-04 17:36:55 +02003205 for (i = 0; i < fcount; i++) {
3206 ret = ssl_sock_populate_sni_keytypes_hplr(sni_filter[i], &sni_keytypes_map, n);
3207 if (ret < 0) {
3208 memprintf(err, "%sunable to allocate SSL context.\n",
3209 err && *err ? *err : "");
Willy Tarreaub131c872019-10-16 16:42:19 +02003210 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemand4801c702019-10-04 17:36:55 +02003211 goto end;
3212 }
3213 }
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003214 } else {
3215 /* A lot of the following code is OpenSSL boilerplate for processing CN's and SAN's,
3216 * so the line that contains logic is marked via comments
3217 */
3218 xname = X509_get_subject_name(certs_and_keys[n].cert);
3219 i = -1;
3220 while ((i = X509_NAME_get_index_by_NID(xname, NID_commonName, i)) != -1) {
3221 X509_NAME_ENTRY *entry = X509_NAME_get_entry(xname, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003222 ASN1_STRING *value;
3223 value = X509_NAME_ENTRY_get_data(entry);
3224 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003225 /* Important line is here */
William Lallemand4801c702019-10-04 17:36:55 +02003226 ret = ssl_sock_populate_sni_keytypes_hplr(str, &sni_keytypes_map, n);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003227
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003228 OPENSSL_free(str);
3229 str = NULL;
William Lallemand4801c702019-10-04 17:36:55 +02003230 if (ret < 0) {
3231 memprintf(err, "%sunable to allocate SSL context.\n",
3232 err && *err ? *err : "");
Willy Tarreaub131c872019-10-16 16:42:19 +02003233 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemand4801c702019-10-04 17:36:55 +02003234 goto end;
3235 }
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003236 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003237 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003238
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003239 /* Do the above logic for each SAN */
yanbzhu08ce6ab2015-12-02 13:01:29 -05003240#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003241 names = X509_get_ext_d2i(certs_and_keys[n].cert, NID_subject_alt_name, NULL, NULL);
3242 if (names) {
3243 for (i = 0; i < sk_GENERAL_NAME_num(names); i++) {
3244 GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003245
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003246 if (name->type == GEN_DNS) {
3247 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
3248 /* Important line is here */
William Lallemand4801c702019-10-04 17:36:55 +02003249 ret = ssl_sock_populate_sni_keytypes_hplr(str, &sni_keytypes_map, n);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003250
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003251 OPENSSL_free(str);
3252 str = NULL;
William Lallemand4801c702019-10-04 17:36:55 +02003253 if (ret < 0) {
3254 memprintf(err, "%sunable to allocate SSL context.\n",
3255 err && *err ? *err : "");
Willy Tarreaub131c872019-10-16 16:42:19 +02003256 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemand4801c702019-10-04 17:36:55 +02003257 goto end;
3258 }
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003259 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003260 }
3261 }
3262 }
3263 }
3264#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
3265 }
3266
3267 /* If no files found, return error */
3268 if (eb_is_empty(&sni_keytypes_map)) {
3269 memprintf(err, "%sunable to load SSL certificate file '%s' file does not exist.\n",
3270 err && *err ? *err : "", path);
Willy Tarreaub131c872019-10-16 16:42:19 +02003271 errcode |= ERR_ALERT | ERR_FATAL;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003272 goto end;
3273 }
3274
3275 /* We now have a map of CN/SAN to keytypes that are loaded in
3276 * Iterate through the map to create the SSL_CTX's (if needed)
3277 * and add each CTX to the SNI tree
3278 *
3279 * Some math here:
Joseph Herlant017b3da2018-11-15 09:07:59 -08003280 * There are 2^n - 1 possible combinations, each unique
yanbzhu08ce6ab2015-12-02 13:01:29 -05003281 * combination is denoted by the key in the map. Each key
3282 * has a value between 1 and 2^n - 1. Conveniently, the array
3283 * of SSL_CTX* is sized 2^n. So, we can simply use the i'th
3284 * entry in the array to correspond to the unique combo (key)
3285 * associated with i. This unique key combo (i) will be associated
3286 * with combos[i-1]
3287 */
3288
3289 node = ebmb_first(&sni_keytypes_map);
3290 while (node) {
3291 SSL_CTX *cur_ctx;
Bertrand Jacquin33423092016-11-13 16:37:13 +00003292 char cur_file[MAXPATHLEN+1];
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003293 const struct pkey_info kinfo = { .sig = TLSEXT_signature_anonymous, .bits = 0 };
yanbzhu08ce6ab2015-12-02 13:01:29 -05003294
3295 str = (char *)container_of(node, struct sni_keytype, name)->name.key;
3296 i = container_of(node, struct sni_keytype, name)->keytypes;
3297 cur_ctx = key_combos[i-1].ctx;
3298
3299 if (cur_ctx == NULL) {
3300 /* need to create SSL_CTX */
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003301 cur_ctx = SSL_CTX_new(SSLv23_server_method());
yanbzhu08ce6ab2015-12-02 13:01:29 -05003302 if (cur_ctx == NULL) {
3303 memprintf(err, "%sunable to allocate SSL context.\n",
3304 err && *err ? *err : "");
Willy Tarreaub131c872019-10-16 16:42:19 +02003305 errcode |= ERR_ALERT | ERR_FATAL;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003306 goto end;
3307 }
3308
yanbzhube2774d2015-12-10 15:07:30 -05003309 /* Load all required certs/keys/chains/OCSPs info into SSL_CTX */
yanbzhu08ce6ab2015-12-02 13:01:29 -05003310 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
3311 if (i & (1<<n)) {
3312 /* Key combo contains ckch[n] */
Bertrand Jacquin33423092016-11-13 16:37:13 +00003313 snprintf(cur_file, MAXPATHLEN+1, "%s.%s", path, SSL_SOCK_KEYTYPE_NAMES[n]);
Emeric Brun394701d2019-10-17 13:25:14 +02003314 errcode |= ssl_sock_put_ckch_into_ctx(cur_file, &certs_and_keys[n], cur_ctx, err);
3315 if (errcode & ERR_CODE) {
yanbzhu08ce6ab2015-12-02 13:01:29 -05003316 SSL_CTX_free(cur_ctx);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003317 goto end;
3318 }
yanbzhube2774d2015-12-10 15:07:30 -05003319
3320#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
3321 /* Load OCSP Info into context */
Bertrand Jacquin33423092016-11-13 16:37:13 +00003322 if (ssl_sock_load_ocsp(cur_ctx, cur_file) < 0) {
yanbzhube2774d2015-12-10 15:07:30 -05003323 if (err)
3324 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",
Bertrand Jacquin5424ee02016-11-13 16:37:14 +00003325 *err ? *err : "", cur_file);
yanbzhube2774d2015-12-10 15:07:30 -05003326 SSL_CTX_free(cur_ctx);
Willy Tarreaub131c872019-10-16 16:42:19 +02003327 errcode |= ERR_ALERT | ERR_FATAL;
yanbzhube2774d2015-12-10 15:07:30 -05003328 goto end;
3329 }
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02003330#elif (defined OPENSSL_IS_BORINGSSL)
3331 ssl_sock_set_ocsp_response_from_file(cur_ctx, cur_file);
yanbzhube2774d2015-12-10 15:07:30 -05003332#endif
yanbzhu08ce6ab2015-12-02 13:01:29 -05003333 }
3334 }
3335
3336 /* Load DH params into the ctx to support DHE keys */
3337#ifndef OPENSSL_NO_DH
3338 if (ssl_dh_ptr_index >= 0)
3339 SSL_CTX_set_ex_data(cur_ctx, ssl_dh_ptr_index, NULL);
3340
Emeric Bruncfc1afe2019-10-17 13:27:40 +02003341 errcode |= ssl_sock_load_dh_params(cur_ctx, NULL, err);
3342 if (errcode & ERR_CODE) {
yanbzhu08ce6ab2015-12-02 13:01:29 -05003343 if (err)
3344 memprintf(err, "%sunable to load DH parameters from file '%s'.\n",
3345 *err ? *err : "", path);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003346 goto end;
3347 }
3348#endif
3349
3350 /* Update key_combos */
3351 key_combos[i-1].ctx = cur_ctx;
3352 }
3353
3354 /* Update SNI Tree */
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003355 key_combos[i-1].order = ssl_sock_add_cert_sni(cur_ctx, bind_conf, ssl_conf,
William Lallemand24e292c2019-10-03 23:46:33 +02003356 kinfo, str, key_combos[i-1].order);
3357 if (key_combos[i-1].order < 0) {
3358 memprintf(err, "%sunable to create a sni context.\n", err && *err ? *err : "");
Willy Tarreaub131c872019-10-16 16:42:19 +02003359 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemand24e292c2019-10-03 23:46:33 +02003360 goto end;
3361 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003362 node = ebmb_next(node);
3363 }
3364
3365
3366 /* Mark a default context if none exists, using the ctx that has the most shared keys */
3367 if (!bind_conf->default_ctx) {
3368 for (i = SSL_SOCK_POSSIBLE_KT_COMBOS - 1; i >= 0; i--) {
3369 if (key_combos[i].ctx) {
3370 bind_conf->default_ctx = key_combos[i].ctx;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003371 bind_conf->default_ssl_conf = ssl_conf;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003372 break;
3373 }
3374 }
3375 }
3376
3377end:
3378
3379 if (names)
3380 sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
3381
3382 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++)
3383 ssl_sock_free_cert_key_and_chain_contents(&certs_and_keys[n]);
3384
3385 node = ebmb_first(&sni_keytypes_map);
3386 while (node) {
3387 next = ebmb_next(node);
3388 ebmb_delete(node);
William Lallemande92c0302019-10-04 17:24:39 +02003389 free(ebmb_entry(node, struct sni_keytype, name));
yanbzhu08ce6ab2015-12-02 13:01:29 -05003390 node = next;
3391 }
3392
Willy Tarreaub131c872019-10-16 16:42:19 +02003393 return errcode;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003394}
3395#else
3396/* This is a dummy, that just logs an error and returns error */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003397static int ssl_sock_load_multi_cert(const char *path, struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
3398 char **sni_filter, int fcount, char **err)
yanbzhu08ce6ab2015-12-02 13:01:29 -05003399{
3400 memprintf(err, "%sunable to stat SSL certificate from file '%s' : %s.\n",
3401 err && *err ? *err : "", path, strerror(errno));
3402 return 1;
3403}
3404
Willy Tarreau9a1ab082019-05-09 13:26:41 +02003405#endif /* #if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL: Support for loading multiple certs into a single SSL_CTX */
yanbzhu488a4d22015-12-01 15:16:07 -05003406
Emeric Brunfc0421f2012-09-07 17:30:07 +02003407/* Loads a certificate key and CA chain from a file. Returns 0 on error, -1 if
3408 * an early error happens and the caller must call SSL_CTX_free() by itelf.
3409 */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003410static int ssl_sock_load_cert_chain_file(SSL_CTX *ctx, const char *file, struct bind_conf *s,
3411 struct ssl_bind_conf *ssl_conf, char **sni_filter, int fcount)
Emeric Brunfc0421f2012-09-07 17:30:07 +02003412{
3413 BIO *in;
3414 X509 *x = NULL, *ca;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02003415 int i, err;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003416 int ret = -1;
3417 int order = 0;
3418 X509_NAME *xname;
3419 char *str;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003420 pem_password_cb *passwd_cb;
3421 void *passwd_cb_userdata;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003422 EVP_PKEY *pkey;
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003423 struct pkey_info kinfo = { .sig = TLSEXT_signature_anonymous, .bits = 0 };
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003424
Emeric Brunfc0421f2012-09-07 17:30:07 +02003425#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
3426 STACK_OF(GENERAL_NAME) *names;
3427#endif
3428
3429 in = BIO_new(BIO_s_file());
3430 if (in == NULL)
3431 goto end;
3432
3433 if (BIO_read_filename(in, file) <= 0)
3434 goto end;
3435
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003436
3437 passwd_cb = SSL_CTX_get_default_passwd_cb(ctx);
3438 passwd_cb_userdata = SSL_CTX_get_default_passwd_cb_userdata(ctx);
3439
3440 x = PEM_read_bio_X509_AUX(in, NULL, passwd_cb, passwd_cb_userdata);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003441 if (x == NULL)
3442 goto end;
3443
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003444 pkey = X509_get_pubkey(x);
3445 if (pkey) {
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003446 kinfo.bits = EVP_PKEY_bits(pkey);
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003447 switch(EVP_PKEY_base_id(pkey)) {
3448 case EVP_PKEY_RSA:
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003449 kinfo.sig = TLSEXT_signature_rsa;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003450 break;
3451 case EVP_PKEY_EC:
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003452 kinfo.sig = TLSEXT_signature_ecdsa;
3453 break;
3454 case EVP_PKEY_DSA:
3455 kinfo.sig = TLSEXT_signature_dsa;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003456 break;
3457 }
3458 EVP_PKEY_free(pkey);
3459 }
3460
Emeric Brun50bcecc2013-04-22 13:05:23 +02003461 if (fcount) {
William Lallemand24e292c2019-10-03 23:46:33 +02003462 while (fcount--) {
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003463 order = ssl_sock_add_cert_sni(ctx, s, ssl_conf, kinfo, sni_filter[fcount], order);
William Lallemand24e292c2019-10-03 23:46:33 +02003464 if (order < 0)
3465 goto end;
3466 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003467 }
3468 else {
Emeric Brunfc0421f2012-09-07 17:30:07 +02003469#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003470 names = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL);
3471 if (names) {
3472 for (i = 0; i < sk_GENERAL_NAME_num(names); i++) {
3473 GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i);
3474 if (name->type == GEN_DNS) {
3475 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003476 order = ssl_sock_add_cert_sni(ctx, s, ssl_conf, kinfo, str, order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003477 OPENSSL_free(str);
William Lallemand24e292c2019-10-03 23:46:33 +02003478 if (order < 0)
3479 goto end;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003480 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003481 }
3482 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003483 sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003484 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003485#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003486 xname = X509_get_subject_name(x);
3487 i = -1;
3488 while ((i = X509_NAME_get_index_by_NID(xname, NID_commonName, i)) != -1) {
3489 X509_NAME_ENTRY *entry = X509_NAME_get_entry(xname, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003490 ASN1_STRING *value;
3491
3492 value = X509_NAME_ENTRY_get_data(entry);
3493 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003494 order = ssl_sock_add_cert_sni(ctx, s, ssl_conf, kinfo, str, order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003495 OPENSSL_free(str);
William Lallemand24e292c2019-10-03 23:46:33 +02003496 if (order < 0)
3497 goto end;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003498 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003499 }
3500 }
3501
3502 ret = 0; /* the caller must not free the SSL_CTX argument anymore */
3503 if (!SSL_CTX_use_certificate(ctx, x))
3504 goto end;
3505
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003506#ifdef SSL_CTX_clear_extra_chain_certs
3507 SSL_CTX_clear_extra_chain_certs(ctx);
3508#else
Emeric Brunfc0421f2012-09-07 17:30:07 +02003509 if (ctx->extra_certs != NULL) {
3510 sk_X509_pop_free(ctx->extra_certs, X509_free);
3511 ctx->extra_certs = NULL;
3512 }
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003513#endif
Emeric Brunfc0421f2012-09-07 17:30:07 +02003514
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003515 while ((ca = PEM_read_bio_X509(in, NULL, passwd_cb, passwd_cb_userdata))) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02003516 if (!SSL_CTX_add_extra_chain_cert(ctx, ca)) {
3517 X509_free(ca);
3518 goto end;
3519 }
3520 }
3521
3522 err = ERR_get_error();
3523 if (!err || (ERR_GET_LIB(err) == ERR_LIB_PEM && ERR_GET_REASON(err) == PEM_R_NO_START_LINE)) {
3524 /* we successfully reached the last cert in the file */
3525 ret = 1;
3526 }
3527 ERR_clear_error();
3528
3529end:
3530 if (x)
3531 X509_free(x);
3532
3533 if (in)
3534 BIO_free(in);
3535
3536 return ret;
3537}
3538
Willy Tarreaub131c872019-10-16 16:42:19 +02003539/* Returns a set of ERR_* flags possibly with an error in <err>. */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003540static int ssl_sock_load_cert_file(const char *path, struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
3541 char **sni_filter, int fcount, char **err)
Emeric Brunfc0421f2012-09-07 17:30:07 +02003542{
Emeric Bruncfc1afe2019-10-17 13:27:40 +02003543 int errcode = 0;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003544 int ret;
3545 SSL_CTX *ctx;
3546
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003547 ctx = SSL_CTX_new(SSLv23_server_method());
Emeric Brunfc0421f2012-09-07 17:30:07 +02003548 if (!ctx) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02003549 memprintf(err, "%sunable to allocate SSL context for cert '%s'.\n",
3550 err && *err ? *err : "", path);
Willy Tarreaub131c872019-10-16 16:42:19 +02003551 return ERR_ALERT | ERR_FATAL;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003552 }
3553
3554 if (SSL_CTX_use_PrivateKey_file(ctx, path, SSL_FILETYPE_PEM) <= 0) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02003555 memprintf(err, "%sunable to load SSL private key from PEM file '%s'.\n",
3556 err && *err ? *err : "", path);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003557 SSL_CTX_free(ctx);
Willy Tarreaub131c872019-10-16 16:42:19 +02003558 return ERR_ALERT | ERR_FATAL;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003559 }
3560
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003561 ret = ssl_sock_load_cert_chain_file(ctx, path, bind_conf, ssl_conf, sni_filter, fcount);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003562 if (ret <= 0) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02003563 memprintf(err, "%sunable to load SSL certificate from PEM file '%s'.\n",
3564 err && *err ? *err : "", path);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003565 if (ret < 0) /* serious error, must do that ourselves */
3566 SSL_CTX_free(ctx);
Willy Tarreaub131c872019-10-16 16:42:19 +02003567 return ERR_ALERT | ERR_FATAL;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003568 }
Emeric Brun61694ab2012-10-26 13:35:33 +02003569
3570 if (SSL_CTX_check_private_key(ctx) <= 0) {
3571 memprintf(err, "%sinconsistencies between private key and certificate loaded from PEM file '%s'.\n",
3572 err && *err ? *err : "", path);
Willy Tarreaub131c872019-10-16 16:42:19 +02003573 return ERR_ALERT | ERR_FATAL;
Emeric Brun61694ab2012-10-26 13:35:33 +02003574 }
3575
Emeric Brunfc0421f2012-09-07 17:30:07 +02003576 /* we must not free the SSL_CTX anymore below, since it's already in
3577 * the tree, so it will be discovered and cleaned in time.
3578 */
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02003579#ifndef OPENSSL_NO_DH
Remi Gacogne4f902b82015-05-28 16:23:00 +02003580 /* store a NULL pointer to indicate we have not yet loaded
3581 a custom DH param file */
3582 if (ssl_dh_ptr_index >= 0) {
3583 SSL_CTX_set_ex_data(ctx, ssl_dh_ptr_index, NULL);
3584 }
3585
Emeric Bruncfc1afe2019-10-17 13:27:40 +02003586 errcode |= ssl_sock_load_dh_params(ctx, path, err);
3587 if (errcode & ERR_CODE) {
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02003588 if (err)
3589 memprintf(err, "%sunable to load DH parameters from file '%s'.\n",
3590 *err ? *err : "", path);
Emeric Bruncfc1afe2019-10-17 13:27:40 +02003591 return errcode;
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02003592 }
3593#endif
3594
Lukas Tribuse4e30f72014-12-09 16:32:51 +01003595#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
Emeric Brun4147b2e2014-06-16 18:36:30 +02003596 ret = ssl_sock_load_ocsp(ctx, path);
3597 if (ret < 0) {
3598 if (err)
3599 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",
3600 *err ? *err : "", path);
Willy Tarreaub131c872019-10-16 16:42:19 +02003601 return ERR_ALERT | ERR_FATAL;
Emeric Brun4147b2e2014-06-16 18:36:30 +02003602 }
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02003603#elif (defined OPENSSL_IS_BORINGSSL)
3604 ssl_sock_set_ocsp_response_from_file(ctx, path);
Emeric Brun4147b2e2014-06-16 18:36:30 +02003605#endif
3606
Willy Tarreau5db847a2019-05-09 14:13:35 +02003607#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01003608 if (sctl_ex_index >= 0) {
3609 ret = ssl_sock_load_sctl(ctx, path);
3610 if (ret < 0) {
3611 if (err)
3612 memprintf(err, "%s '%s.sctl' is present but cannot be read or parsed'.\n",
3613 *err ? *err : "", path);
Willy Tarreaub131c872019-10-16 16:42:19 +02003614 return ERR_ALERT | ERR_FATAL;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01003615 }
3616 }
3617#endif
3618
Emeric Brunfc0421f2012-09-07 17:30:07 +02003619#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
Willy Tarreau2a65ff02012-09-13 17:54:29 +02003620 if (bind_conf->default_ctx) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02003621 memprintf(err, "%sthis version of openssl cannot load multiple SSL certificates.\n",
3622 err && *err ? *err : "");
Willy Tarreaub131c872019-10-16 16:42:19 +02003623 return ERR_ALERT | ERR_FATAL;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003624 }
3625#endif
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003626 if (!bind_conf->default_ctx) {
Willy Tarreau2a65ff02012-09-13 17:54:29 +02003627 bind_conf->default_ctx = ctx;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003628 bind_conf->default_ssl_conf = ssl_conf;
3629 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003630
Emeric Bruncfc1afe2019-10-17 13:27:40 +02003631 return errcode;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003632}
3633
Willy Tarreaub131c872019-10-16 16:42:19 +02003634
3635/* Returns a set of ERR_* flags possibly with an error in <err>. */
Willy Tarreau03209342016-12-22 17:08:28 +01003636int ssl_sock_load_cert(char *path, struct bind_conf *bind_conf, char **err)
Emeric Brunfc0421f2012-09-07 17:30:07 +02003637{
Cyril Bonté3180f7b2015-01-25 00:16:08 +01003638 struct dirent **de_list;
3639 int i, n;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003640 DIR *dir;
3641 struct stat buf;
Willy Tarreauee2663b2012-12-06 11:36:59 +01003642 char *end;
3643 char fp[MAXPATHLEN+1];
Emeric Brunfc0421f2012-09-07 17:30:07 +02003644 int cfgerr = 0;
Willy Tarreau9a1ab082019-05-09 13:26:41 +02003645#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
yanbzhu63ea8462015-12-09 13:35:14 -05003646 int is_bundle;
3647 int j;
3648#endif
Emeric Brunfc0421f2012-09-07 17:30:07 +02003649
yanbzhu08ce6ab2015-12-02 13:01:29 -05003650 if (stat(path, &buf) == 0) {
3651 dir = opendir(path);
3652 if (!dir)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003653 return ssl_sock_load_cert_file(path, bind_conf, NULL, NULL, 0, err);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003654
yanbzhu08ce6ab2015-12-02 13:01:29 -05003655 /* strip trailing slashes, including first one */
3656 for (end = path + strlen(path) - 1; end >= path && *end == '/'; end--)
3657 *end = 0;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003658
yanbzhu08ce6ab2015-12-02 13:01:29 -05003659 n = scandir(path, &de_list, 0, alphasort);
3660 if (n < 0) {
3661 memprintf(err, "%sunable to scan directory '%s' : %s.\n",
3662 err && *err ? *err : "", path, strerror(errno));
Willy Tarreaub131c872019-10-16 16:42:19 +02003663 cfgerr |= ERR_ALERT | ERR_FATAL;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003664 }
3665 else {
3666 for (i = 0; i < n; i++) {
3667 struct dirent *de = de_list[i];
Emeric Brun2aab7222014-06-18 18:15:09 +02003668
yanbzhu08ce6ab2015-12-02 13:01:29 -05003669 end = strrchr(de->d_name, '.');
3670 if (end && (!strcmp(end, ".issuer") || !strcmp(end, ".ocsp") || !strcmp(end, ".sctl")))
3671 goto ignore_entry;
Cyril Bonté3180f7b2015-01-25 00:16:08 +01003672
yanbzhu08ce6ab2015-12-02 13:01:29 -05003673 snprintf(fp, sizeof(fp), "%s/%s", path, de->d_name);
3674 if (stat(fp, &buf) != 0) {
3675 memprintf(err, "%sunable to stat SSL certificate from file '%s' : %s.\n",
3676 err && *err ? *err : "", fp, strerror(errno));
Willy Tarreaub131c872019-10-16 16:42:19 +02003677 cfgerr |= ERR_ALERT | ERR_FATAL;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003678 goto ignore_entry;
3679 }
3680 if (!S_ISREG(buf.st_mode))
3681 goto ignore_entry;
yanbzhu63ea8462015-12-09 13:35:14 -05003682
Willy Tarreau9a1ab082019-05-09 13:26:41 +02003683#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
yanbzhu63ea8462015-12-09 13:35:14 -05003684 is_bundle = 0;
3685 /* Check if current entry in directory is part of a multi-cert bundle */
3686
3687 if (end) {
3688 for (j = 0; j < SSL_SOCK_NUM_KEYTYPES; j++) {
3689 if (!strcmp(end + 1, SSL_SOCK_KEYTYPE_NAMES[j])) {
3690 is_bundle = 1;
3691 break;
3692 }
3693 }
3694
3695 if (is_bundle) {
yanbzhu63ea8462015-12-09 13:35:14 -05003696 int dp_len;
3697
3698 dp_len = end - de->d_name;
yanbzhu63ea8462015-12-09 13:35:14 -05003699
3700 /* increment i and free de until we get to a non-bundle cert
3701 * Note here that we look at de_list[i + 1] before freeing de
Willy Tarreau5b8a8652019-10-29 10:48:50 +01003702 * this is important since ignore_entry will free de. This also
3703 * guarantees that de->d_name continues to hold the same prefix.
yanbzhu63ea8462015-12-09 13:35:14 -05003704 */
Willy Tarreau5b8a8652019-10-29 10:48:50 +01003705 while (i + 1 < n && !strncmp(de_list[i + 1]->d_name, de->d_name, dp_len)) {
yanbzhu63ea8462015-12-09 13:35:14 -05003706 free(de);
3707 i++;
3708 de = de_list[i];
3709 }
3710
Willy Tarreau5b8a8652019-10-29 10:48:50 +01003711 snprintf(fp, sizeof(fp), "%s/%.*s", path, dp_len, de->d_name);
Willy Tarreaub131c872019-10-16 16:42:19 +02003712 cfgerr |= ssl_sock_load_multi_cert(fp, bind_conf, NULL, NULL, 0, err);
yanbzhu63ea8462015-12-09 13:35:14 -05003713 /* Successfully processed the bundle */
3714 goto ignore_entry;
3715 }
3716 }
3717
3718#endif
Willy Tarreaub131c872019-10-16 16:42:19 +02003719 cfgerr |= ssl_sock_load_cert_file(fp, bind_conf, NULL, NULL, 0, err);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003720ignore_entry:
3721 free(de);
Cyril Bonté3180f7b2015-01-25 00:16:08 +01003722 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003723 free(de_list);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003724 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003725 closedir(dir);
3726 return cfgerr;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003727 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003728
Willy Tarreaub131c872019-10-16 16:42:19 +02003729 cfgerr |= ssl_sock_load_multi_cert(path, bind_conf, NULL, NULL, 0, err);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003730
Emeric Brunfc0421f2012-09-07 17:30:07 +02003731 return cfgerr;
3732}
3733
Thierry Fournier383085f2013-01-24 14:15:43 +01003734/* Make sure openssl opens /dev/urandom before the chroot. The work is only
3735 * done once. Zero is returned if the operation fails. No error is returned
3736 * if the random is said as not implemented, because we expect that openssl
3737 * will use another method once needed.
3738 */
3739static int ssl_initialize_random()
3740{
3741 unsigned char random;
3742 static int random_initialized = 0;
3743
3744 if (!random_initialized && RAND_bytes(&random, 1) != 0)
3745 random_initialized = 1;
3746
3747 return random_initialized;
3748}
3749
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003750/* release ssl bind conf */
3751void ssl_sock_free_ssl_conf(struct ssl_bind_conf *conf)
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003752{
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003753 if (conf) {
Bernard Spil13c53f82018-02-15 13:34:58 +01003754#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003755 free(conf->npn_str);
3756 conf->npn_str = NULL;
3757#endif
3758#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
3759 free(conf->alpn_str);
3760 conf->alpn_str = NULL;
3761#endif
3762 free(conf->ca_file);
3763 conf->ca_file = NULL;
3764 free(conf->crl_file);
3765 conf->crl_file = NULL;
3766 free(conf->ciphers);
3767 conf->ciphers = NULL;
Emmanuel Hocdet839af572019-05-14 16:27:35 +02003768#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02003769 free(conf->ciphersuites);
3770 conf->ciphersuites = NULL;
3771#endif
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01003772 free(conf->curves);
3773 conf->curves = NULL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003774 free(conf->ecdhe);
3775 conf->ecdhe = NULL;
3776 }
3777}
3778
Willy Tarreaub131c872019-10-16 16:42:19 +02003779/* Returns a set of ERR_* flags possibly with an error in <err>. */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003780int ssl_sock_load_cert_list_file(char *file, struct bind_conf *bind_conf, struct proxy *curproxy, char **err)
3781{
3782 char thisline[CRT_LINESIZE];
3783 char path[MAXPATHLEN+1];
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003784 FILE *f;
yanbzhu1b04e5b2015-12-02 13:54:14 -05003785 struct stat buf;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003786 int linenum = 0;
3787 int cfgerr = 0;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003788
Willy Tarreauad1731d2013-04-02 17:35:58 +02003789 if ((f = fopen(file, "r")) == NULL) {
3790 memprintf(err, "cannot open file '%s' : %s", file, strerror(errno));
Willy Tarreaub131c872019-10-16 16:42:19 +02003791 return ERR_ALERT | ERR_FATAL;
Willy Tarreauad1731d2013-04-02 17:35:58 +02003792 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003793
3794 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003795 int arg, newarg, cur_arg, i, ssl_b = 0, ssl_e = 0;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003796 char *end;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003797 char *args[MAX_CRT_ARGS + 1];
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003798 char *line = thisline;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003799 char *crt_path;
3800 struct ssl_bind_conf *ssl_conf = NULL;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003801
3802 linenum++;
3803 end = line + strlen(line);
3804 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
3805 /* Check if we reached the limit and the last char is not \n.
3806 * Watch out for the last line without the terminating '\n'!
3807 */
Willy Tarreauad1731d2013-04-02 17:35:58 +02003808 memprintf(err, "line %d too long in file '%s', limit is %d characters",
3809 linenum, file, (int)sizeof(thisline)-1);
Willy Tarreaub131c872019-10-16 16:42:19 +02003810 cfgerr |= ERR_ALERT | ERR_FATAL;
Willy Tarreauad1731d2013-04-02 17:35:58 +02003811 break;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003812 }
3813
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003814 arg = 0;
Emeric Brun50bcecc2013-04-22 13:05:23 +02003815 newarg = 1;
3816 while (*line) {
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003817 if (*line == '#' || *line == '\n' || *line == '\r') {
3818 /* end of string, end of loop */
3819 *line = 0;
3820 break;
Willy Tarreau26e4ab42020-02-25 07:51:59 +01003821 } else if (isspace((unsigned char)*line)) {
Emeric Brun50bcecc2013-04-22 13:05:23 +02003822 newarg = 1;
3823 *line = 0;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003824 } else if (*line == '[') {
3825 if (ssl_b) {
3826 memprintf(err, "too many '[' on line %d in file '%s'.", linenum, file);
Willy Tarreaub131c872019-10-16 16:42:19 +02003827 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003828 break;
3829 }
3830 if (!arg) {
3831 memprintf(err, "file must start with a cert on line %d in file '%s'", linenum, file);
Willy Tarreaub131c872019-10-16 16:42:19 +02003832 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003833 break;
3834 }
3835 ssl_b = arg;
3836 newarg = 1;
3837 *line = 0;
3838 } else if (*line == ']') {
3839 if (ssl_e) {
3840 memprintf(err, "too many ']' on line %d in file '%s'.", linenum, file);
Willy Tarreaub131c872019-10-16 16:42:19 +02003841 cfgerr |= ERR_ALERT | ERR_FATAL;
Emeric Brun50bcecc2013-04-22 13:05:23 +02003842 break;
3843 }
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003844 if (!ssl_b) {
3845 memprintf(err, "missing '[' in line %d in file '%s'.", linenum, file);
Willy Tarreaub131c872019-10-16 16:42:19 +02003846 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003847 break;
3848 }
3849 ssl_e = arg;
3850 newarg = 1;
3851 *line = 0;
3852 } else if (newarg) {
3853 if (arg == MAX_CRT_ARGS) {
3854 memprintf(err, "too many args on line %d in file '%s'.", linenum, file);
Willy Tarreaub131c872019-10-16 16:42:19 +02003855 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003856 break;
3857 }
Emeric Brun50bcecc2013-04-22 13:05:23 +02003858 newarg = 0;
3859 args[arg++] = line;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003860 }
Emeric Brun50bcecc2013-04-22 13:05:23 +02003861 line++;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003862 }
Willy Tarreaub131c872019-10-16 16:42:19 +02003863 if (cfgerr & ERR_CODE)
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02003864 break;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003865 args[arg++] = line;
Willy Tarreauad1731d2013-04-02 17:35:58 +02003866
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003867 /* empty line */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003868 if (!*args[0])
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003869 continue;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003870
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003871 crt_path = args[0];
3872 if (*crt_path != '/' && global_ssl.crt_base) {
3873 if ((strlen(global_ssl.crt_base) + 1 + strlen(crt_path)) > MAXPATHLEN) {
3874 memprintf(err, "'%s' : path too long on line %d in file '%s'",
3875 crt_path, linenum, file);
Willy Tarreaub131c872019-10-16 16:42:19 +02003876 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003877 break;
3878 }
3879 snprintf(path, sizeof(path), "%s/%s", global_ssl.crt_base, crt_path);
3880 crt_path = path;
3881 }
3882
3883 ssl_conf = calloc(1, sizeof *ssl_conf);
3884 cur_arg = ssl_b ? ssl_b : 1;
3885 while (cur_arg < ssl_e) {
3886 newarg = 0;
3887 for (i = 0; ssl_bind_kws[i].kw != NULL; i++) {
3888 if (strcmp(ssl_bind_kws[i].kw, args[cur_arg]) == 0) {
3889 newarg = 1;
Willy Tarreaub131c872019-10-16 16:42:19 +02003890 cfgerr |= ssl_bind_kws[i].parse(args, cur_arg, curproxy, ssl_conf, err);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003891 if (cur_arg + 1 + ssl_bind_kws[i].skip > ssl_e) {
3892 memprintf(err, "ssl args out of '[]' for %s on line %d in file '%s'",
3893 args[cur_arg], linenum, file);
Willy Tarreaub131c872019-10-16 16:42:19 +02003894 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003895 }
3896 cur_arg += 1 + ssl_bind_kws[i].skip;
3897 break;
3898 }
3899 }
3900 if (!cfgerr && !newarg) {
3901 memprintf(err, "unknown ssl keyword %s on line %d in file '%s'.",
3902 args[cur_arg], linenum, file);
Willy Tarreaub131c872019-10-16 16:42:19 +02003903 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003904 break;
3905 }
3906 }
Willy Tarreaub131c872019-10-16 16:42:19 +02003907
3908 if (cfgerr & ERR_CODE) {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003909 ssl_sock_free_ssl_conf(ssl_conf);
3910 free(ssl_conf);
3911 ssl_conf = NULL;
3912 break;
3913 }
3914
3915 if (stat(crt_path, &buf) == 0) {
Willy Tarreaub131c872019-10-16 16:42:19 +02003916 cfgerr |= ssl_sock_load_cert_file(crt_path, bind_conf, ssl_conf,
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003917 &args[cur_arg], arg - cur_arg - 1, err);
Willy Tarreaub131c872019-10-16 16:42:19 +02003918 } else {
3919 cfgerr |= ssl_sock_load_multi_cert(crt_path, bind_conf, ssl_conf,
3920 &args[cur_arg], arg - cur_arg - 1, err);
yanbzhu1b04e5b2015-12-02 13:54:14 -05003921 }
3922
Willy Tarreaub131c872019-10-16 16:42:19 +02003923 if (cfgerr & ERR_CODE) {
Willy Tarreauad1731d2013-04-02 17:35:58 +02003924 memprintf(err, "error processing line %d in file '%s' : %s", linenum, file, *err);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003925 break;
Willy Tarreauad1731d2013-04-02 17:35:58 +02003926 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003927 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003928 fclose(f);
3929 return cfgerr;
3930}
3931
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003932/* Create an initial CTX used to start the SSL connection before switchctx */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003933static int
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003934ssl_sock_initial_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02003935{
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01003936 SSL_CTX *ctx = NULL;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003937 long options =
Emeric Brunfc0421f2012-09-07 17:30:07 +02003938 SSL_OP_ALL | /* all known workarounds for bugs */
3939 SSL_OP_NO_SSLv2 |
3940 SSL_OP_NO_COMPRESSION |
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02003941 SSL_OP_SINGLE_DH_USE |
Emeric Brun2b58d042012-09-20 17:10:03 +02003942 SSL_OP_SINGLE_ECDH_USE |
Emeric Brun3c4bc6e2012-10-04 18:44:19 +02003943 SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION |
Lukas Tribus926594f2018-05-18 17:55:57 +02003944 SSL_OP_PRIORITIZE_CHACHA |
Emeric Brun3c4bc6e2012-10-04 18:44:19 +02003945 SSL_OP_CIPHER_SERVER_PREFERENCE;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003946 long mode =
Emeric Brunfc0421f2012-09-07 17:30:07 +02003947 SSL_MODE_ENABLE_PARTIAL_WRITE |
3948 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
Willy Tarreau396a1862014-11-13 14:06:52 +01003949 SSL_MODE_RELEASE_BUFFERS |
3950 SSL_MODE_SMALL_BUFFERS;
Emmanuel Hocdet43664762017-08-09 18:26:20 +02003951 struct tls_version_filter *conf_ssl_methods = &bind_conf->ssl_conf.ssl_methods;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003952 int i, min, max, hole;
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003953 int flags = MC_SSL_O_ALL;
3954 int cfgerr = 0;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01003955
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003956 ctx = SSL_CTX_new(SSLv23_server_method());
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003957 bind_conf->initial_ctx = ctx;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003958
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003959 if (conf_ssl_methods->flags && (conf_ssl_methods->min || conf_ssl_methods->max))
Christopher Faulet767a84b2017-11-24 16:50:31 +01003960 ha_warning("Proxy '%s': no-sslv3/no-tlsv1x are ignored for bind '%s' at [%s:%d]. "
3961 "Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
3962 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003963 else
3964 flags = conf_ssl_methods->flags;
3965
Emmanuel Hocdetbd695fe2017-05-15 15:53:41 +02003966 min = conf_ssl_methods->min;
3967 max = conf_ssl_methods->max;
3968 /* start with TLSv10 to remove SSLv3 per default */
3969 if (!min && (!max || max >= CONF_TLSV10))
3970 min = CONF_TLSV10;
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02003971 /* Real min and max should be determinate with configuration and openssl's capabilities */
Emmanuel Hocdetbd695fe2017-05-15 15:53:41 +02003972 if (min)
3973 flags |= (methodVersions[min].flag - 1);
3974 if (max)
3975 flags |= ~((methodVersions[max].flag << 1) - 1);
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02003976 /* find min, max and holes */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003977 min = max = CONF_TLSV_NONE;
3978 hole = 0;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003979 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003980 /* version is in openssl && version not disable in configuration */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003981 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003982 if (min) {
3983 if (hole) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003984 ha_warning("Proxy '%s': SSL/TLS versions range not contiguous for bind '%s' at [%s:%d]. "
3985 "Hole find for %s. Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
3986 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line,
3987 methodVersions[hole].name);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003988 hole = 0;
3989 }
3990 max = i;
3991 }
3992 else {
3993 min = max = i;
3994 }
3995 }
3996 else {
3997 if (min)
3998 hole = i;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003999 }
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004000 if (!min) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004001 ha_alert("Proxy '%s': all SSL/TLS versions are disabled for bind '%s' at [%s:%d].\n",
4002 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004003 cfgerr += 1;
4004 }
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02004005 /* save real min/max in bind_conf */
4006 conf_ssl_methods->min = min;
4007 conf_ssl_methods->max = max;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004008
Willy Tarreau9a1ab082019-05-09 13:26:41 +02004009#if (HA_OPENSSL_VERSION_NUMBER < 0x1010000fL)
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004010 /* Keep force-xxx implementation as it is in older haproxy. It's a
Joseph Herlant017b3da2018-11-15 09:07:59 -08004011 precautionary measure to avoid any surprise with older openssl version. */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004012 if (min == max)
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004013 methodVersions[min].ctx_set_version(ctx, SET_SERVER);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004014 else
William Lallemand6dbb9a12020-06-11 17:34:00 +02004015 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++) {
4016 /* clear every version flags in case SSL_CTX_new()
4017 * returns an SSL_CTX with disabled versions */
4018 SSL_CTX_clear_options(ctx, methodVersions[i].option);
4019
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004020 if (flags & methodVersions[i].flag)
4021 options |= methodVersions[i].option;
William Lallemand6dbb9a12020-06-11 17:34:00 +02004022
4023 }
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004024#else /* openssl >= 1.1.0 */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004025 /* set the max_version is required to cap TLS version or activate new TLS (v1.3) */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004026 methodVersions[min].ctx_set_version(ctx, SET_MIN);
4027 methodVersions[max].ctx_set_version(ctx, SET_MAX);
Emeric Brunfa5c5c82017-04-28 16:19:51 +02004028#endif
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004029
4030 if (bind_conf->ssl_options & BC_SSL_O_NO_TLS_TICKETS)
4031 options |= SSL_OP_NO_TICKET;
4032 if (bind_conf->ssl_options & BC_SSL_O_PREF_CLIE_CIPH)
4033 options &= ~SSL_OP_CIPHER_SERVER_PREFERENCE;
Dirkjan Bussink526894f2019-01-21 09:35:03 -08004034
4035#ifdef SSL_OP_NO_RENEGOTIATION
4036 options |= SSL_OP_NO_RENEGOTIATION;
4037#endif
4038
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004039 SSL_CTX_set_options(ctx, options);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004040
Willy Tarreau5db847a2019-05-09 14:13:35 +02004041#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004042 if (global_ssl.async)
4043 mode |= SSL_MODE_ASYNC;
4044#endif
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004045 SSL_CTX_set_mode(ctx, mode);
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004046 if (global_ssl.life_time)
4047 SSL_CTX_set_timeout(ctx, global_ssl.life_time);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004048
4049#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
4050#ifdef OPENSSL_IS_BORINGSSL
4051 SSL_CTX_set_select_certificate_cb(ctx, ssl_sock_switchctx_cbk);
4052 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_err_cbk);
Willy Tarreau5db847a2019-05-09 14:13:35 +02004053#elif (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Olivier Houcharde82c1d42019-12-17 15:39:54 +01004054 if (bind_conf->ssl_conf.early_data)
Olivier Houchard51088ce2019-01-02 18:46:41 +01004055 SSL_CTX_set_options(ctx, SSL_OP_NO_ANTI_REPLAY);
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02004056 SSL_CTX_set_client_hello_cb(ctx, ssl_sock_switchctx_cbk, NULL);
4057 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_err_cbk);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004058#else
4059 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_cbk);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004060#endif
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02004061 SSL_CTX_set_tlsext_servername_arg(ctx, bind_conf);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004062#endif
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004063 return cfgerr;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004064}
4065
William Lallemand4f45bb92017-10-30 20:08:51 +01004066
4067static inline void sh_ssl_sess_free_blocks(struct shared_block *first, struct shared_block *block)
4068{
4069 if (first == block) {
4070 struct sh_ssl_sess_hdr *sh_ssl_sess = (struct sh_ssl_sess_hdr *)first->data;
4071 if (first->len > 0)
4072 sh_ssl_sess_tree_delete(sh_ssl_sess);
4073 }
4074}
4075
4076/* return first block from sh_ssl_sess */
4077static inline struct shared_block *sh_ssl_sess_first_block(struct sh_ssl_sess_hdr *sh_ssl_sess)
4078{
4079 return (struct shared_block *)((unsigned char *)sh_ssl_sess - ((struct shared_block *)NULL)->data);
4080
4081}
4082
4083/* store a session into the cache
4084 * s_id : session id padded with zero to SSL_MAX_SSL_SESSION_ID_LENGTH
4085 * data: asn1 encoded session
4086 * data_len: asn1 encoded session length
4087 * Returns 1 id session was stored (else 0)
4088 */
4089static int sh_ssl_sess_store(unsigned char *s_id, unsigned char *data, int data_len)
4090{
4091 struct shared_block *first;
4092 struct sh_ssl_sess_hdr *sh_ssl_sess, *oldsh_ssl_sess;
4093
Frédéric Lécaille0bec8072018-10-22 17:55:57 +02004094 first = shctx_row_reserve_hot(ssl_shctx, NULL, data_len + sizeof(struct sh_ssl_sess_hdr));
William Lallemand4f45bb92017-10-30 20:08:51 +01004095 if (!first) {
4096 /* Could not retrieve enough free blocks to store that session */
4097 return 0;
4098 }
4099
4100 /* STORE the key in the first elem */
4101 sh_ssl_sess = (struct sh_ssl_sess_hdr *)first->data;
4102 memcpy(sh_ssl_sess->key_data, s_id, SSL_MAX_SSL_SESSION_ID_LENGTH);
4103 first->len = sizeof(struct sh_ssl_sess_hdr);
4104
4105 /* it returns the already existing node
4106 or current node if none, never returns null */
4107 oldsh_ssl_sess = sh_ssl_sess_tree_insert(sh_ssl_sess);
4108 if (oldsh_ssl_sess != sh_ssl_sess) {
4109 /* NOTE: Row couldn't be in use because we lock read & write function */
4110 /* release the reserved row */
4111 shctx_row_dec_hot(ssl_shctx, first);
4112 /* replace the previous session already in the tree */
4113 sh_ssl_sess = oldsh_ssl_sess;
4114 /* ignore the previous session data, only use the header */
4115 first = sh_ssl_sess_first_block(sh_ssl_sess);
4116 shctx_row_inc_hot(ssl_shctx, first);
4117 first->len = sizeof(struct sh_ssl_sess_hdr);
4118 }
4119
Frédéric Lécaille0bec8072018-10-22 17:55:57 +02004120 if (shctx_row_data_append(ssl_shctx, first, NULL, data, data_len) < 0) {
William Lallemand99b90af2018-01-03 19:15:51 +01004121 shctx_row_dec_hot(ssl_shctx, first);
William Lallemand4f45bb92017-10-30 20:08:51 +01004122 return 0;
William Lallemand99b90af2018-01-03 19:15:51 +01004123 }
4124
4125 shctx_row_dec_hot(ssl_shctx, first);
William Lallemand4f45bb92017-10-30 20:08:51 +01004126
4127 return 1;
4128}
William Lallemanded0b5ad2017-10-30 19:36:36 +01004129
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004130/* SSL callback used when a new session is created while connecting to a server */
4131static int ssl_sess_new_srv_cb(SSL *ssl, SSL_SESSION *sess)
4132{
Thierry FOURNIER28962c92018-06-17 21:37:05 +02004133 struct connection *conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Olivier Houcharde6060c52017-11-16 17:42:52 +01004134 struct server *s;
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004135
Willy Tarreau07d94e42018-09-20 10:57:52 +02004136 s = __objt_server(conn->target);
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004137
Olivier Houcharde6060c52017-11-16 17:42:52 +01004138 if (!(s->ssl_ctx.options & SRV_SSL_O_NO_REUSE)) {
4139 int len;
4140 unsigned char *ptr;
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004141
Olivier Houcharde6060c52017-11-16 17:42:52 +01004142 len = i2d_SSL_SESSION(sess, NULL);
4143 if (s->ssl_ctx.reused_sess[tid].ptr && s->ssl_ctx.reused_sess[tid].allocated_size >= len) {
4144 ptr = s->ssl_ctx.reused_sess[tid].ptr;
4145 } else {
4146 free(s->ssl_ctx.reused_sess[tid].ptr);
4147 ptr = s->ssl_ctx.reused_sess[tid].ptr = malloc(len);
4148 s->ssl_ctx.reused_sess[tid].allocated_size = len;
4149 }
4150 if (s->ssl_ctx.reused_sess[tid].ptr) {
4151 s->ssl_ctx.reused_sess[tid].size = i2d_SSL_SESSION(sess,
4152 &ptr);
4153 }
4154 } else {
4155 free(s->ssl_ctx.reused_sess[tid].ptr);
4156 s->ssl_ctx.reused_sess[tid].ptr = NULL;
4157 }
4158
4159 return 0;
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004160}
4161
Olivier Houcharde6060c52017-11-16 17:42:52 +01004162
William Lallemanded0b5ad2017-10-30 19:36:36 +01004163/* SSL callback used on new session creation */
William Lallemand4f45bb92017-10-30 20:08:51 +01004164int sh_ssl_sess_new_cb(SSL *ssl, SSL_SESSION *sess)
William Lallemanded0b5ad2017-10-30 19:36:36 +01004165{
4166 unsigned char encsess[SHSESS_MAX_DATA_LEN]; /* encoded session */
4167 unsigned char encid[SSL_MAX_SSL_SESSION_ID_LENGTH]; /* encoded id */
4168 unsigned char *p;
4169 int data_len;
Emeric Brun7b34de32019-10-08 18:27:37 +02004170 unsigned int sid_length;
William Lallemanded0b5ad2017-10-30 19:36:36 +01004171 const unsigned char *sid_data;
William Lallemanded0b5ad2017-10-30 19:36:36 +01004172
4173 /* Session id is already stored in to key and session id is known
4174 * so we dont store it to keep size.
Emeric Brun7b34de32019-10-08 18:27:37 +02004175 * note: SSL_SESSION_set1_id is using
4176 * a memcpy so we need to use a different pointer
4177 * than sid_data or sid_ctx_data to avoid valgrind
4178 * complaining.
William Lallemanded0b5ad2017-10-30 19:36:36 +01004179 */
4180
4181 sid_data = SSL_SESSION_get_id(sess, &sid_length);
Emeric Brun7b34de32019-10-08 18:27:37 +02004182
4183 /* copy value in an other buffer */
4184 memcpy(encid, sid_data, sid_length);
4185
4186 /* pad with 0 */
4187 if (sid_length < SSL_MAX_SSL_SESSION_ID_LENGTH)
4188 memset(encid + sid_length, 0, SSL_MAX_SSL_SESSION_ID_LENGTH-sid_length);
4189
4190 /* force length to zero to avoid ASN1 encoding */
4191 SSL_SESSION_set1_id(sess, encid, 0);
4192
4193 /* force length to zero to avoid ASN1 encoding */
4194 SSL_SESSION_set1_id_context(sess, (const unsigned char *)SHCTX_APPNAME, 0);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004195
4196 /* check if buffer is large enough for the ASN1 encoded session */
4197 data_len = i2d_SSL_SESSION(sess, NULL);
4198 if (data_len > SHSESS_MAX_DATA_LEN)
4199 goto err;
4200
4201 p = encsess;
4202
4203 /* process ASN1 session encoding before the lock */
4204 i2d_SSL_SESSION(sess, &p);
4205
William Lallemanded0b5ad2017-10-30 19:36:36 +01004206
William Lallemanda3c77cf2017-10-30 23:44:40 +01004207 shctx_lock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004208 /* store to cache */
William Lallemand4f45bb92017-10-30 20:08:51 +01004209 sh_ssl_sess_store(encid, encsess, data_len);
William Lallemanda3c77cf2017-10-30 23:44:40 +01004210 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004211err:
4212 /* reset original length values */
Emeric Brun7b34de32019-10-08 18:27:37 +02004213 SSL_SESSION_set1_id(sess, encid, sid_length);
4214 SSL_SESSION_set1_id_context(sess, (const unsigned char *)SHCTX_APPNAME, strlen(SHCTX_APPNAME));
William Lallemanded0b5ad2017-10-30 19:36:36 +01004215
4216 return 0; /* do not increment session reference count */
4217}
4218
4219/* SSL callback used on lookup an existing session cause none found in internal cache */
William Lallemand4f45bb92017-10-30 20:08:51 +01004220SSL_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 +01004221{
William Lallemand4f45bb92017-10-30 20:08:51 +01004222 struct sh_ssl_sess_hdr *sh_ssl_sess;
William Lallemanded0b5ad2017-10-30 19:36:36 +01004223 unsigned char data[SHSESS_MAX_DATA_LEN], *p;
4224 unsigned char tmpkey[SSL_MAX_SSL_SESSION_ID_LENGTH];
William Lallemanded0b5ad2017-10-30 19:36:36 +01004225 SSL_SESSION *sess;
William Lallemand4f45bb92017-10-30 20:08:51 +01004226 struct shared_block *first;
William Lallemanded0b5ad2017-10-30 19:36:36 +01004227
4228 global.shctx_lookups++;
4229
4230 /* allow the session to be freed automatically by openssl */
4231 *do_copy = 0;
4232
4233 /* tree key is zeros padded sessionid */
4234 if (key_len < SSL_MAX_SSL_SESSION_ID_LENGTH) {
4235 memcpy(tmpkey, key, key_len);
4236 memset(tmpkey + key_len, 0, SSL_MAX_SSL_SESSION_ID_LENGTH - key_len);
4237 key = tmpkey;
4238 }
4239
4240 /* lock cache */
William Lallemanda3c77cf2017-10-30 23:44:40 +01004241 shctx_lock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004242
4243 /* lookup for session */
William Lallemand4f45bb92017-10-30 20:08:51 +01004244 sh_ssl_sess = sh_ssl_sess_tree_lookup(key);
4245 if (!sh_ssl_sess) {
William Lallemanded0b5ad2017-10-30 19:36:36 +01004246 /* no session found: unlock cache and exit */
William Lallemanda3c77cf2017-10-30 23:44:40 +01004247 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004248 global.shctx_misses++;
4249 return NULL;
4250 }
4251
William Lallemand4f45bb92017-10-30 20:08:51 +01004252 /* sh_ssl_sess (shared_block->data) is at the end of shared_block */
4253 first = sh_ssl_sess_first_block(sh_ssl_sess);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004254
William Lallemand4f45bb92017-10-30 20:08:51 +01004255 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 +01004256
William Lallemanda3c77cf2017-10-30 23:44:40 +01004257 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004258
4259 /* decode ASN1 session */
4260 p = data;
William Lallemand4f45bb92017-10-30 20:08:51 +01004261 sess = d2i_SSL_SESSION(NULL, (const unsigned char **)&p, first->len-sizeof(struct sh_ssl_sess_hdr));
William Lallemanded0b5ad2017-10-30 19:36:36 +01004262 /* Reset session id and session id contenxt */
4263 if (sess) {
4264 SSL_SESSION_set1_id(sess, key, key_len);
4265 SSL_SESSION_set1_id_context(sess, (const unsigned char *)SHCTX_APPNAME, strlen(SHCTX_APPNAME));
4266 }
4267
4268 return sess;
4269}
4270
William Lallemand4f45bb92017-10-30 20:08:51 +01004271
William Lallemanded0b5ad2017-10-30 19:36:36 +01004272/* SSL callback used to signal session is no more used in internal cache */
William Lallemand4f45bb92017-10-30 20:08:51 +01004273void sh_ssl_sess_remove_cb(SSL_CTX *ctx, SSL_SESSION *sess)
William Lallemanded0b5ad2017-10-30 19:36:36 +01004274{
William Lallemand4f45bb92017-10-30 20:08:51 +01004275 struct sh_ssl_sess_hdr *sh_ssl_sess;
William Lallemanded0b5ad2017-10-30 19:36:36 +01004276 unsigned char tmpkey[SSL_MAX_SSL_SESSION_ID_LENGTH];
4277 unsigned int sid_length;
4278 const unsigned char *sid_data;
4279 (void)ctx;
4280
4281 sid_data = SSL_SESSION_get_id(sess, &sid_length);
4282 /* tree key is zeros padded sessionid */
4283 if (sid_length < SSL_MAX_SSL_SESSION_ID_LENGTH) {
4284 memcpy(tmpkey, sid_data, sid_length);
4285 memset(tmpkey+sid_length, 0, SSL_MAX_SSL_SESSION_ID_LENGTH - sid_length);
4286 sid_data = tmpkey;
4287 }
4288
William Lallemanda3c77cf2017-10-30 23:44:40 +01004289 shctx_lock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004290
4291 /* lookup for session */
William Lallemand4f45bb92017-10-30 20:08:51 +01004292 sh_ssl_sess = sh_ssl_sess_tree_lookup(sid_data);
4293 if (sh_ssl_sess) {
William Lallemanded0b5ad2017-10-30 19:36:36 +01004294 /* free session */
William Lallemand4f45bb92017-10-30 20:08:51 +01004295 sh_ssl_sess_tree_delete(sh_ssl_sess);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004296 }
4297
4298 /* unlock cache */
William Lallemanda3c77cf2017-10-30 23:44:40 +01004299 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004300}
4301
4302/* Set session cache mode to server and disable openssl internal cache.
4303 * Set shared cache callbacks on an ssl context.
4304 * Shared context MUST be firstly initialized */
William Lallemand4f45bb92017-10-30 20:08:51 +01004305void ssl_set_shctx(SSL_CTX *ctx)
William Lallemanded0b5ad2017-10-30 19:36:36 +01004306{
4307 SSL_CTX_set_session_id_context(ctx, (const unsigned char *)SHCTX_APPNAME, strlen(SHCTX_APPNAME));
4308
4309 if (!ssl_shctx) {
4310 SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF);
4311 return;
4312 }
4313
4314 SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_SERVER |
4315 SSL_SESS_CACHE_NO_INTERNAL |
4316 SSL_SESS_CACHE_NO_AUTO_CLEAR);
4317
4318 /* Set callbacks */
William Lallemand4f45bb92017-10-30 20:08:51 +01004319 SSL_CTX_sess_set_new_cb(ctx, sh_ssl_sess_new_cb);
4320 SSL_CTX_sess_set_get_cb(ctx, sh_ssl_sess_get_cb);
4321 SSL_CTX_sess_set_remove_cb(ctx, sh_ssl_sess_remove_cb);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004322}
4323
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004324int ssl_sock_prepare_ctx(struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf, SSL_CTX *ctx)
4325{
4326 struct proxy *curproxy = bind_conf->frontend;
4327 int cfgerr = 0;
4328 int verify = SSL_VERIFY_NONE;
Willy Tarreau5d4cafb2018-01-04 18:55:19 +01004329 struct ssl_bind_conf __maybe_unused *ssl_conf_cur;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004330 const char *conf_ciphers;
Emmanuel Hocdet839af572019-05-14 16:27:35 +02004331#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02004332 const char *conf_ciphersuites;
4333#endif
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004334 const char *conf_curves = NULL;
Emeric Brunfc0421f2012-09-07 17:30:07 +02004335
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02004336 if (ssl_conf) {
4337 struct tls_version_filter *conf_ssl_methods = &ssl_conf->ssl_methods;
4338 int i, min, max;
4339 int flags = MC_SSL_O_ALL;
4340
4341 /* Real min and max should be determinate with configuration and openssl's capabilities */
Emmanuel Hocdet43664762017-08-09 18:26:20 +02004342 min = conf_ssl_methods->min ? conf_ssl_methods->min : bind_conf->ssl_conf.ssl_methods.min;
4343 max = conf_ssl_methods->max ? conf_ssl_methods->max : bind_conf->ssl_conf.ssl_methods.max;
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02004344 if (min)
4345 flags |= (methodVersions[min].flag - 1);
4346 if (max)
4347 flags |= ~((methodVersions[max].flag << 1) - 1);
4348 min = max = CONF_TLSV_NONE;
4349 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
4350 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
4351 if (min)
4352 max = i;
4353 else
4354 min = max = i;
4355 }
4356 /* save real min/max */
4357 conf_ssl_methods->min = min;
4358 conf_ssl_methods->max = max;
4359 if (!min) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004360 ha_alert("Proxy '%s': all SSL/TLS versions are disabled for bind '%s' at [%s:%d].\n",
4361 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02004362 cfgerr += 1;
4363 }
4364 }
4365
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004366 switch ((ssl_conf && ssl_conf->verify) ? ssl_conf->verify : bind_conf->ssl_conf.verify) {
Emeric Brun850efd52014-01-29 12:24:34 +01004367 case SSL_SOCK_VERIFY_NONE:
4368 verify = SSL_VERIFY_NONE;
4369 break;
4370 case SSL_SOCK_VERIFY_OPTIONAL:
4371 verify = SSL_VERIFY_PEER;
4372 break;
4373 case SSL_SOCK_VERIFY_REQUIRED:
4374 verify = SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
4375 break;
4376 }
4377 SSL_CTX_set_verify(ctx, verify, ssl_sock_bind_verifycbk);
4378 if (verify & SSL_VERIFY_PEER) {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004379 char *ca_file = (ssl_conf && ssl_conf->ca_file) ? ssl_conf->ca_file : bind_conf->ssl_conf.ca_file;
4380 char *crl_file = (ssl_conf && ssl_conf->crl_file) ? ssl_conf->crl_file : bind_conf->ssl_conf.crl_file;
4381 if (ca_file) {
Emeric Brund94b3fe2012-09-20 18:23:56 +02004382 /* load CAfile to verify */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004383 if (!SSL_CTX_load_verify_locations(ctx, ca_file, NULL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004384 ha_alert("Proxy '%s': unable to load CA file '%s' for bind '%s' at [%s:%d].\n",
4385 curproxy->id, ca_file, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brund94b3fe2012-09-20 18:23:56 +02004386 cfgerr++;
4387 }
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02004388 if (!((ssl_conf && ssl_conf->no_ca_names) || bind_conf->ssl_conf.no_ca_names)) {
4389 /* set CA names for client cert request, function returns void */
4390 SSL_CTX_set_client_CA_list(ctx, SSL_load_client_CA_file(ca_file));
4391 }
Emeric Brund94b3fe2012-09-20 18:23:56 +02004392 }
Emeric Brun850efd52014-01-29 12:24:34 +01004393 else {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004394 ha_alert("Proxy '%s': verify is enabled but no CA file specified for bind '%s' at [%s:%d].\n",
4395 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brun850efd52014-01-29 12:24:34 +01004396 cfgerr++;
4397 }
Emeric Brun051cdab2012-10-02 19:25:50 +02004398#ifdef X509_V_FLAG_CRL_CHECK
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004399 if (crl_file) {
Emeric Brund94b3fe2012-09-20 18:23:56 +02004400 X509_STORE *store = SSL_CTX_get_cert_store(ctx);
4401
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004402 if (!store || !X509_STORE_load_locations(store, crl_file, NULL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004403 ha_alert("Proxy '%s': unable to configure CRL file '%s' for bind '%s' at [%s:%d].\n",
4404 curproxy->id, crl_file, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brund94b3fe2012-09-20 18:23:56 +02004405 cfgerr++;
4406 }
Emeric Brun561e5742012-10-02 15:20:55 +02004407 else {
4408 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
4409 }
Emeric Brund94b3fe2012-09-20 18:23:56 +02004410 }
Emeric Brun051cdab2012-10-02 19:25:50 +02004411#endif
Emeric Brun644cde02012-12-14 11:21:13 +01004412 ERR_clear_error();
Emeric Brund94b3fe2012-09-20 18:23:56 +02004413 }
Nenad Merdanovic05552d42015-02-27 19:56:49 +01004414#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
Nenad Merdanovic146defa2015-05-09 08:46:00 +02004415 if(bind_conf->keys_ref) {
Nenad Merdanovic05552d42015-02-27 19:56:49 +01004416 if (!SSL_CTX_set_tlsext_ticket_key_cb(ctx, ssl_tlsext_ticket_key_cb)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004417 ha_alert("Proxy '%s': unable to set callback for TLS ticket validation for bind '%s' at [%s:%d].\n",
4418 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Nenad Merdanovic05552d42015-02-27 19:56:49 +01004419 cfgerr++;
4420 }
4421 }
4422#endif
4423
William Lallemand4f45bb92017-10-30 20:08:51 +01004424 ssl_set_shctx(ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004425 conf_ciphers = (ssl_conf && ssl_conf->ciphers) ? ssl_conf->ciphers : bind_conf->ssl_conf.ciphers;
4426 if (conf_ciphers &&
4427 !SSL_CTX_set_cipher_list(ctx, conf_ciphers)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004428 ha_alert("Proxy '%s': unable to set SSL cipher list to '%s' for bind '%s' at [%s:%d].\n",
4429 curproxy->id, conf_ciphers, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004430 cfgerr++;
4431 }
4432
Emmanuel Hocdet839af572019-05-14 16:27:35 +02004433#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02004434 conf_ciphersuites = (ssl_conf && ssl_conf->ciphersuites) ? ssl_conf->ciphersuites : bind_conf->ssl_conf.ciphersuites;
4435 if (conf_ciphersuites &&
4436 !SSL_CTX_set_ciphersuites(ctx, conf_ciphersuites)) {
4437 ha_alert("Proxy '%s': unable to set TLS 1.3 cipher suites to '%s' for bind '%s' at [%s:%d].\n",
4438 curproxy->id, conf_ciphersuites, bind_conf->arg, bind_conf->file, bind_conf->line);
4439 cfgerr++;
4440 }
4441#endif
4442
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01004443#ifndef OPENSSL_NO_DH
Remi Gacogne47783ef2015-05-29 15:53:22 +02004444 /* If tune.ssl.default-dh-param has not been set,
4445 neither has ssl-default-dh-file and no static DH
4446 params were in the certificate file. */
Willy Tarreauef934602016-12-22 23:12:01 +01004447 if (global_ssl.default_dh_param == 0 &&
Remi Gacogne47783ef2015-05-29 15:53:22 +02004448 global_dh == NULL &&
Remi Gacogne4f902b82015-05-28 16:23:00 +02004449 (ssl_dh_ptr_index == -1 ||
4450 SSL_CTX_get_ex_data(ctx, ssl_dh_ptr_index) == NULL)) {
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01004451 STACK_OF(SSL_CIPHER) * ciphers = NULL;
4452 const SSL_CIPHER * cipher = NULL;
4453 char cipher_description[128];
4454 /* The description of ciphers using an Ephemeral Diffie Hellman key exchange
4455 contains " Kx=DH " or " Kx=DH(". Beware of " Kx=DH/",
4456 which is not ephemeral DH. */
4457 const char dhe_description[] = " Kx=DH ";
4458 const char dhe_export_description[] = " Kx=DH(";
4459 int idx = 0;
4460 int dhe_found = 0;
4461 SSL *ssl = NULL;
Lukas Tribus90132722014-08-18 00:56:33 +02004462
Remi Gacogne23d5d372014-10-10 17:04:26 +02004463 ssl = SSL_new(ctx);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004464
Remi Gacogne23d5d372014-10-10 17:04:26 +02004465 if (ssl) {
4466 ciphers = SSL_get_ciphers(ssl);
4467
4468 if (ciphers) {
4469 for (idx = 0; idx < sk_SSL_CIPHER_num(ciphers); idx++) {
4470 cipher = sk_SSL_CIPHER_value(ciphers, idx);
4471 if (SSL_CIPHER_description(cipher, cipher_description, sizeof (cipher_description)) == cipher_description) {
4472 if (strstr(cipher_description, dhe_description) != NULL ||
4473 strstr(cipher_description, dhe_export_description) != NULL) {
4474 dhe_found = 1;
4475 break;
4476 }
Remi Gacognec1eab8c2014-06-12 18:20:11 +02004477 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004478 }
4479 }
Remi Gacogne23d5d372014-10-10 17:04:26 +02004480 SSL_free(ssl);
4481 ssl = NULL;
Lukas Tribus90132722014-08-18 00:56:33 +02004482 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004483
Lukas Tribus90132722014-08-18 00:56:33 +02004484 if (dhe_found) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004485 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 +02004486 }
4487
Willy Tarreauef934602016-12-22 23:12:01 +01004488 global_ssl.default_dh_param = 1024;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004489 }
Remi Gacogne8de54152014-07-15 11:36:40 +02004490
Willy Tarreauef934602016-12-22 23:12:01 +01004491 if (global_ssl.default_dh_param >= 1024) {
Remi Gacogne8de54152014-07-15 11:36:40 +02004492 if (local_dh_1024 == NULL) {
4493 local_dh_1024 = ssl_get_dh_1024();
4494 }
Willy Tarreauef934602016-12-22 23:12:01 +01004495 if (global_ssl.default_dh_param >= 2048) {
Remi Gacogne8de54152014-07-15 11:36:40 +02004496 if (local_dh_2048 == NULL) {
4497 local_dh_2048 = ssl_get_dh_2048();
4498 }
Willy Tarreauef934602016-12-22 23:12:01 +01004499 if (global_ssl.default_dh_param >= 4096) {
Remi Gacogne8de54152014-07-15 11:36:40 +02004500 if (local_dh_4096 == NULL) {
4501 local_dh_4096 = ssl_get_dh_4096();
4502 }
Remi Gacogne8de54152014-07-15 11:36:40 +02004503 }
4504 }
4505 }
4506#endif /* OPENSSL_NO_DH */
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004507
Emeric Brunfc0421f2012-09-07 17:30:07 +02004508 SSL_CTX_set_info_callback(ctx, ssl_sock_infocbk);
Willy Tarreau9a1ab082019-05-09 13:26:41 +02004509#if HA_OPENSSL_VERSION_NUMBER >= 0x00907000L
Emeric Brun29f037d2014-04-25 19:05:36 +02004510 SSL_CTX_set_msg_callback(ctx, ssl_sock_msgcbk);
Willy Tarreau5cbe4ef2014-05-08 22:45:11 +02004511#endif
Emeric Brun29f037d2014-04-25 19:05:36 +02004512
Bernard Spil13c53f82018-02-15 13:34:58 +01004513#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004514 ssl_conf_cur = NULL;
4515 if (ssl_conf && ssl_conf->npn_str)
4516 ssl_conf_cur = ssl_conf;
4517 else if (bind_conf->ssl_conf.npn_str)
4518 ssl_conf_cur = &bind_conf->ssl_conf;
4519 if (ssl_conf_cur)
4520 SSL_CTX_set_next_protos_advertised_cb(ctx, ssl_sock_advertise_npn_protos, ssl_conf_cur);
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02004521#endif
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01004522#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004523 ssl_conf_cur = NULL;
4524 if (ssl_conf && ssl_conf->alpn_str)
4525 ssl_conf_cur = ssl_conf;
4526 else if (bind_conf->ssl_conf.alpn_str)
4527 ssl_conf_cur = &bind_conf->ssl_conf;
4528 if (ssl_conf_cur)
4529 SSL_CTX_set_alpn_select_cb(ctx, ssl_sock_advertise_alpn_protos, ssl_conf_cur);
Willy Tarreauab861d32013-04-02 02:30:41 +02004530#endif
Lukas Tribusd13e9252019-11-24 18:20:40 +01004531#if ((HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL) || defined(LIBRESSL_VERSION_NUMBER))
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004532 conf_curves = (ssl_conf && ssl_conf->curves) ? ssl_conf->curves : bind_conf->ssl_conf.curves;
4533 if (conf_curves) {
4534 if (!SSL_CTX_set1_curves_list(ctx, conf_curves)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004535 ha_alert("Proxy '%s': unable to set SSL curves list to '%s' for bind '%s' at [%s:%d].\n",
4536 curproxy->id, conf_curves, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004537 cfgerr++;
4538 }
Emmanuel Hocdeta52bb152017-03-20 11:11:49 +01004539 (void)SSL_CTX_set_ecdh_auto(ctx, 1);
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004540 }
4541#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02004542#if defined(SSL_CTX_set_tmp_ecdh) && !defined(OPENSSL_NO_ECDH)
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004543 if (!conf_curves) {
Emeric Brun2b58d042012-09-20 17:10:03 +02004544 int i;
4545 EC_KEY *ecdh;
Willy Tarreau9a1ab082019-05-09 13:26:41 +02004546#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004547 const char *ecdhe = (ssl_conf && ssl_conf->ecdhe) ? ssl_conf->ecdhe :
Olivier Houchardc2aae742017-09-22 18:26:28 +02004548 (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe :
4549 NULL);
4550
4551 if (ecdhe == NULL) {
Eric Salama27c21cd2019-11-20 11:33:40 +01004552 (void)SSL_CTX_set_ecdh_auto(ctx, 1);
Olivier Houchardc2aae742017-09-22 18:26:28 +02004553 return cfgerr;
4554 }
4555#else
4556 const char *ecdhe = (ssl_conf && ssl_conf->ecdhe) ? ssl_conf->ecdhe :
4557 (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe :
4558 ECDHE_DEFAULT_CURVE);
4559#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02004560
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004561 i = OBJ_sn2nid(ecdhe);
Emeric Brun2b58d042012-09-20 17:10:03 +02004562 if (!i || ((ecdh = EC_KEY_new_by_curve_name(i)) == NULL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004563 ha_alert("Proxy '%s': unable to set elliptic named curve to '%s' for bind '%s' at [%s:%d].\n",
4564 curproxy->id, ecdhe, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brun2b58d042012-09-20 17:10:03 +02004565 cfgerr++;
4566 }
4567 else {
4568 SSL_CTX_set_tmp_ecdh(ctx, ecdh);
4569 EC_KEY_free(ecdh);
4570 }
4571 }
4572#endif
4573
Emeric Brunfc0421f2012-09-07 17:30:07 +02004574 return cfgerr;
4575}
4576
Evan Broderbe554312013-06-27 00:05:25 -07004577static int ssl_sock_srv_hostcheck(const char *pattern, const char *hostname)
4578{
4579 const char *pattern_wildcard, *pattern_left_label_end, *hostname_left_label_end;
4580 size_t prefixlen, suffixlen;
4581
4582 /* Trivial case */
William Lallemandb00a33b2020-09-14 15:20:10 +02004583 if (strcasecmp(pattern, hostname) == 0)
Evan Broderbe554312013-06-27 00:05:25 -07004584 return 1;
4585
Evan Broderbe554312013-06-27 00:05:25 -07004586 /* The rest of this logic is based on RFC 6125, section 6.4.3
4587 * (http://tools.ietf.org/html/rfc6125#section-6.4.3) */
4588
Emeric Bruna848dae2013-10-08 11:27:28 +02004589 pattern_wildcard = NULL;
4590 pattern_left_label_end = pattern;
4591 while (*pattern_left_label_end != '.') {
4592 switch (*pattern_left_label_end) {
4593 case 0:
4594 /* End of label not found */
4595 return 0;
4596 case '*':
4597 /* If there is more than one wildcards */
4598 if (pattern_wildcard)
4599 return 0;
4600 pattern_wildcard = pattern_left_label_end;
4601 break;
4602 }
4603 pattern_left_label_end++;
4604 }
4605
4606 /* If it's not trivial and there is no wildcard, it can't
4607 * match */
4608 if (!pattern_wildcard)
Evan Broderbe554312013-06-27 00:05:25 -07004609 return 0;
4610
4611 /* Make sure all labels match except the leftmost */
4612 hostname_left_label_end = strchr(hostname, '.');
4613 if (!hostname_left_label_end
William Lallemandb00a33b2020-09-14 15:20:10 +02004614 || strcasecmp(pattern_left_label_end, hostname_left_label_end) != 0)
Evan Broderbe554312013-06-27 00:05:25 -07004615 return 0;
4616
4617 /* Make sure the leftmost label of the hostname is long enough
4618 * that the wildcard can match */
Emeric Brun369da852013-10-08 11:39:35 +02004619 if (hostname_left_label_end - hostname < (pattern_left_label_end - pattern) - 1)
Evan Broderbe554312013-06-27 00:05:25 -07004620 return 0;
4621
4622 /* Finally compare the string on either side of the
4623 * wildcard */
4624 prefixlen = pattern_wildcard - pattern;
4625 suffixlen = pattern_left_label_end - (pattern_wildcard + 1);
William Lallemandb00a33b2020-09-14 15:20:10 +02004626 if ((prefixlen && (strncasecmp(pattern, hostname, prefixlen) != 0))
4627 || (suffixlen && (strncasecmp(pattern_wildcard + 1, hostname_left_label_end - suffixlen, suffixlen) != 0)))
Evan Broderbe554312013-06-27 00:05:25 -07004628 return 0;
4629
4630 return 1;
4631}
4632
4633static int ssl_sock_srv_verifycbk(int ok, X509_STORE_CTX *ctx)
4634{
4635 SSL *ssl;
4636 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01004637 struct ssl_sock_ctx *ssl_ctx;
Willy Tarreau2ab88672017-07-05 18:23:03 +02004638 const char *servername;
Willy Tarreau71d058c2017-07-26 20:09:56 +02004639 const char *sni;
Evan Broderbe554312013-06-27 00:05:25 -07004640
4641 int depth;
4642 X509 *cert;
4643 STACK_OF(GENERAL_NAME) *alt_names;
4644 int i;
4645 X509_NAME *cert_subject;
4646 char *str;
4647
4648 if (ok == 0)
4649 return ok;
4650
4651 ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
Thierry FOURNIER28962c92018-06-17 21:37:05 +02004652 conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Olivier Houchard66ab4982019-02-26 18:37:15 +01004653 ssl_ctx = conn->xprt_ctx;
Evan Broderbe554312013-06-27 00:05:25 -07004654
Willy Tarreauad92a9a2017-07-28 11:38:41 +02004655 /* We're checking if the provided hostnames match the desired one. The
4656 * desired hostname comes from the SNI we presented if any, or if not
4657 * provided then it may have been explicitly stated using a "verifyhost"
4658 * directive. If neither is set, we don't care about the name so the
4659 * verification is OK.
Willy Tarreau2ab88672017-07-05 18:23:03 +02004660 */
Olivier Houchard66ab4982019-02-26 18:37:15 +01004661 servername = SSL_get_servername(ssl_ctx->ssl, TLSEXT_NAMETYPE_host_name);
Willy Tarreau71d058c2017-07-26 20:09:56 +02004662 sni = servername;
Willy Tarreau2ab88672017-07-05 18:23:03 +02004663 if (!servername) {
Willy Tarreau07d94e42018-09-20 10:57:52 +02004664 servername = __objt_server(conn->target)->ssl_ctx.verify_host;
Willy Tarreau2ab88672017-07-05 18:23:03 +02004665 if (!servername)
4666 return ok;
4667 }
Evan Broderbe554312013-06-27 00:05:25 -07004668
4669 /* We only need to verify the CN on the actual server cert,
4670 * not the indirect CAs */
4671 depth = X509_STORE_CTX_get_error_depth(ctx);
4672 if (depth != 0)
4673 return ok;
4674
4675 /* At this point, the cert is *not* OK unless we can find a
4676 * hostname match */
4677 ok = 0;
4678
4679 cert = X509_STORE_CTX_get_current_cert(ctx);
4680 /* It seems like this might happen if verify peer isn't set */
4681 if (!cert)
4682 return ok;
4683
4684 alt_names = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
4685 if (alt_names) {
4686 for (i = 0; !ok && i < sk_GENERAL_NAME_num(alt_names); i++) {
4687 GENERAL_NAME *name = sk_GENERAL_NAME_value(alt_names, i);
4688 if (name->type == GEN_DNS) {
Willy Tarreau9a1ab082019-05-09 13:26:41 +02004689#if HA_OPENSSL_VERSION_NUMBER < 0x00907000L
Emeric Bruna33410c2013-09-17 15:47:48 +02004690 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.ia5) >= 0) {
4691#else
Evan Broderbe554312013-06-27 00:05:25 -07004692 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
Emeric Bruna33410c2013-09-17 15:47:48 +02004693#endif
Evan Broderbe554312013-06-27 00:05:25 -07004694 ok = ssl_sock_srv_hostcheck(str, servername);
4695 OPENSSL_free(str);
4696 }
4697 }
4698 }
Emeric Brun4ad50a42013-09-17 15:19:54 +02004699 sk_GENERAL_NAME_pop_free(alt_names, GENERAL_NAME_free);
Evan Broderbe554312013-06-27 00:05:25 -07004700 }
4701
4702 cert_subject = X509_get_subject_name(cert);
4703 i = -1;
4704 while (!ok && (i = X509_NAME_get_index_by_NID(cert_subject, NID_commonName, i)) != -1) {
4705 X509_NAME_ENTRY *entry = X509_NAME_get_entry(cert_subject, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02004706 ASN1_STRING *value;
4707 value = X509_NAME_ENTRY_get_data(entry);
4708 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
Evan Broderbe554312013-06-27 00:05:25 -07004709 ok = ssl_sock_srv_hostcheck(str, servername);
4710 OPENSSL_free(str);
4711 }
4712 }
4713
Willy Tarreau71d058c2017-07-26 20:09:56 +02004714 /* report the mismatch and indicate if SNI was used or not */
4715 if (!ok && !conn->err_code)
4716 conn->err_code = sni ? CO_ER_SSL_MISMATCH_SNI : CO_ER_SSL_MISMATCH;
Evan Broderbe554312013-06-27 00:05:25 -07004717 return ok;
4718}
4719
Emeric Brun94324a42012-10-11 14:00:19 +02004720/* prepare ssl context from servers options. Returns an error count */
Willy Tarreau03209342016-12-22 17:08:28 +01004721int ssl_sock_prepare_srv_ctx(struct server *srv)
Emeric Brun94324a42012-10-11 14:00:19 +02004722{
Willy Tarreau03209342016-12-22 17:08:28 +01004723 struct proxy *curproxy = srv->proxy;
Emeric Brun94324a42012-10-11 14:00:19 +02004724 int cfgerr = 0;
Remi Gacogneaf5c3da2014-05-19 10:29:58 +02004725 long options =
Emeric Brun94324a42012-10-11 14:00:19 +02004726 SSL_OP_ALL | /* all known workarounds for bugs */
4727 SSL_OP_NO_SSLv2 |
4728 SSL_OP_NO_COMPRESSION;
Remi Gacogneaf5c3da2014-05-19 10:29:58 +02004729 long mode =
Emeric Brun94324a42012-10-11 14:00:19 +02004730 SSL_MODE_ENABLE_PARTIAL_WRITE |
4731 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
Willy Tarreau396a1862014-11-13 14:06:52 +01004732 SSL_MODE_RELEASE_BUFFERS |
4733 SSL_MODE_SMALL_BUFFERS;
Emeric Brun850efd52014-01-29 12:24:34 +01004734 int verify = SSL_VERIFY_NONE;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004735 SSL_CTX *ctx = NULL;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004736 struct tls_version_filter *conf_ssl_methods = &srv->ssl_ctx.methods;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004737 int i, min, max, hole;
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004738 int flags = MC_SSL_O_ALL;
Emeric Brun94324a42012-10-11 14:00:19 +02004739
Thierry Fournier383085f2013-01-24 14:15:43 +01004740 /* Make sure openssl opens /dev/urandom before the chroot */
4741 if (!ssl_initialize_random()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004742 ha_alert("OpenSSL random data generator initialization failed.\n");
Thierry Fournier383085f2013-01-24 14:15:43 +01004743 cfgerr++;
4744 }
4745
Willy Tarreaufce03112015-01-15 21:32:40 +01004746 /* Automatic memory computations need to know we use SSL there */
4747 global.ssl_used_backend = 1;
4748
4749 /* Initiate SSL context for current server */
Emeric Brun821bb9b2017-06-15 16:37:39 +02004750 if (!srv->ssl_ctx.reused_sess) {
Olivier Houcharde6060c52017-11-16 17:42:52 +01004751 if ((srv->ssl_ctx.reused_sess = calloc(1, global.nbthread*sizeof(*srv->ssl_ctx.reused_sess))) == NULL) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004752 ha_alert("Proxy '%s', server '%s' [%s:%d] out of memory.\n",
4753 curproxy->id, srv->id,
4754 srv->conf.file, srv->conf.line);
Emeric Brun821bb9b2017-06-15 16:37:39 +02004755 cfgerr++;
4756 return cfgerr;
4757 }
4758 }
Christopher Faulet68d35ae2020-03-27 18:55:49 +01004759 if (srv->use_ssl == 1)
Emeric Brun94324a42012-10-11 14:00:19 +02004760 srv->xprt = &ssl_sock;
Emeric Brun94324a42012-10-11 14:00:19 +02004761
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004762 ctx = SSL_CTX_new(SSLv23_client_method());
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004763 if (!ctx) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004764 ha_alert("config : %s '%s', server '%s': unable to allocate ssl context.\n",
4765 proxy_type_str(curproxy), curproxy->id,
4766 srv->id);
Emeric Brun94324a42012-10-11 14:00:19 +02004767 cfgerr++;
4768 return cfgerr;
4769 }
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004770
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004771 if (conf_ssl_methods->flags && (conf_ssl_methods->min || conf_ssl_methods->max))
Christopher Faulet767a84b2017-11-24 16:50:31 +01004772 ha_warning("config : %s '%s': no-sslv3/no-tlsv1x are ignored for server '%s'. "
4773 "Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
4774 proxy_type_str(curproxy), curproxy->id, srv->id);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004775 else
4776 flags = conf_ssl_methods->flags;
4777
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004778 /* Real min and max should be determinate with configuration and openssl's capabilities */
4779 if (conf_ssl_methods->min)
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004780 flags |= (methodVersions[conf_ssl_methods->min].flag - 1);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004781 if (conf_ssl_methods->max)
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004782 flags |= ~((methodVersions[conf_ssl_methods->max].flag << 1) - 1);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004783
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004784 /* find min, max and holes */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004785 min = max = CONF_TLSV_NONE;
4786 hole = 0;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004787 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004788 /* version is in openssl && version not disable in configuration */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004789 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004790 if (min) {
4791 if (hole) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004792 ha_warning("config : %s '%s': SSL/TLS versions range not contiguous for server '%s'. "
4793 "Hole find for %s. Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
4794 proxy_type_str(curproxy), curproxy->id, srv->id,
4795 methodVersions[hole].name);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004796 hole = 0;
4797 }
4798 max = i;
4799 }
4800 else {
4801 min = max = i;
4802 }
4803 }
4804 else {
4805 if (min)
4806 hole = i;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004807 }
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004808 if (!min) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004809 ha_alert("config : %s '%s': all SSL/TLS versions are disabled for server '%s'.\n",
4810 proxy_type_str(curproxy), curproxy->id, srv->id);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004811 cfgerr += 1;
4812 }
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004813
Willy Tarreau9a1ab082019-05-09 13:26:41 +02004814#if (HA_OPENSSL_VERSION_NUMBER < 0x1010000fL)
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004815 /* Keep force-xxx implementation as it is in older haproxy. It's a
Joseph Herlant017b3da2018-11-15 09:07:59 -08004816 precautionary measure to avoid any surprise with older openssl version. */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004817 if (min == max)
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004818 methodVersions[min].ctx_set_version(ctx, SET_CLIENT);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004819 else
4820 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
4821 if (flags & methodVersions[i].flag)
4822 options |= methodVersions[i].option;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004823#else /* openssl >= 1.1.0 */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004824 /* set the max_version is required to cap TLS version or activate new TLS (v1.3) */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004825 methodVersions[min].ctx_set_version(ctx, SET_MIN);
4826 methodVersions[max].ctx_set_version(ctx, SET_MAX);
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004827#endif
4828
4829 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLS_TICKETS)
4830 options |= SSL_OP_NO_TICKET;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004831 SSL_CTX_set_options(ctx, options);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004832
Willy Tarreau5db847a2019-05-09 14:13:35 +02004833#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004834 if (global_ssl.async)
4835 mode |= SSL_MODE_ASYNC;
4836#endif
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004837 SSL_CTX_set_mode(ctx, mode);
4838 srv->ssl_ctx.ctx = ctx;
4839
Emeric Bruna7aa3092012-10-26 12:58:00 +02004840 if (srv->ssl_ctx.client_crt) {
4841 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 +01004842 ha_alert("config : %s '%s', server '%s': unable to load SSL private key from PEM file '%s'.\n",
4843 proxy_type_str(curproxy), curproxy->id,
4844 srv->id, srv->ssl_ctx.client_crt);
Emeric Bruna7aa3092012-10-26 12:58:00 +02004845 cfgerr++;
4846 }
4847 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 +01004848 ha_alert("config : %s '%s', server '%s': unable to load ssl certificate from PEM file '%s'.\n",
4849 proxy_type_str(curproxy), curproxy->id,
4850 srv->id, srv->ssl_ctx.client_crt);
Emeric Bruna7aa3092012-10-26 12:58:00 +02004851 cfgerr++;
4852 }
4853 else if (SSL_CTX_check_private_key(srv->ssl_ctx.ctx) <= 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004854 ha_alert("config : %s '%s', server '%s': inconsistencies between private key and certificate loaded from PEM file '%s'.\n",
4855 proxy_type_str(curproxy), curproxy->id,
4856 srv->id, srv->ssl_ctx.client_crt);
Emeric Bruna7aa3092012-10-26 12:58:00 +02004857 cfgerr++;
4858 }
4859 }
Emeric Brun94324a42012-10-11 14:00:19 +02004860
Emeric Brun850efd52014-01-29 12:24:34 +01004861 if (global.ssl_server_verify == SSL_SERVER_VERIFY_REQUIRED)
4862 verify = SSL_VERIFY_PEER;
Emeric Brun850efd52014-01-29 12:24:34 +01004863 switch (srv->ssl_ctx.verify) {
4864 case SSL_SOCK_VERIFY_NONE:
4865 verify = SSL_VERIFY_NONE;
4866 break;
4867 case SSL_SOCK_VERIFY_REQUIRED:
4868 verify = SSL_VERIFY_PEER;
4869 break;
4870 }
Evan Broderbe554312013-06-27 00:05:25 -07004871 SSL_CTX_set_verify(srv->ssl_ctx.ctx,
Emeric Brun850efd52014-01-29 12:24:34 +01004872 verify,
Willy Tarreau2ab88672017-07-05 18:23:03 +02004873 (srv->ssl_ctx.verify_host || (verify & SSL_VERIFY_PEER)) ? ssl_sock_srv_verifycbk : NULL);
Emeric Brun850efd52014-01-29 12:24:34 +01004874 if (verify & SSL_VERIFY_PEER) {
Emeric Brunef42d922012-10-11 16:11:36 +02004875 if (srv->ssl_ctx.ca_file) {
4876 /* load CAfile to verify */
4877 if (!SSL_CTX_load_verify_locations(srv->ssl_ctx.ctx, srv->ssl_ctx.ca_file, NULL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004878 ha_alert("Proxy '%s', server '%s' [%s:%d] unable to load CA file '%s'.\n",
4879 curproxy->id, srv->id,
4880 srv->conf.file, srv->conf.line, srv->ssl_ctx.ca_file);
Emeric Brunef42d922012-10-11 16:11:36 +02004881 cfgerr++;
4882 }
4883 }
Emeric Brun850efd52014-01-29 12:24:34 +01004884 else {
4885 if (global.ssl_server_verify == SSL_SERVER_VERIFY_REQUIRED)
Christopher Faulet767a84b2017-11-24 16:50:31 +01004886 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",
4887 curproxy->id, srv->id,
4888 srv->conf.file, srv->conf.line);
Emeric Brun850efd52014-01-29 12:24:34 +01004889 else
Christopher Faulet767a84b2017-11-24 16:50:31 +01004890 ha_alert("Proxy '%s', server '%s' [%s:%d] verify is enabled but no CA file specified.\n",
4891 curproxy->id, srv->id,
4892 srv->conf.file, srv->conf.line);
Emeric Brun850efd52014-01-29 12:24:34 +01004893 cfgerr++;
4894 }
Emeric Brunef42d922012-10-11 16:11:36 +02004895#ifdef X509_V_FLAG_CRL_CHECK
4896 if (srv->ssl_ctx.crl_file) {
4897 X509_STORE *store = SSL_CTX_get_cert_store(srv->ssl_ctx.ctx);
4898
4899 if (!store || !X509_STORE_load_locations(store, srv->ssl_ctx.crl_file, NULL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004900 ha_alert("Proxy '%s', server '%s' [%s:%d] unable to configure CRL file '%s'.\n",
4901 curproxy->id, srv->id,
4902 srv->conf.file, srv->conf.line, srv->ssl_ctx.crl_file);
Emeric Brunef42d922012-10-11 16:11:36 +02004903 cfgerr++;
4904 }
4905 else {
4906 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
4907 }
4908 }
4909#endif
4910 }
4911
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004912 SSL_CTX_set_session_cache_mode(srv->ssl_ctx.ctx, SSL_SESS_CACHE_CLIENT |
4913 SSL_SESS_CACHE_NO_INTERNAL_STORE);
4914 SSL_CTX_sess_set_new_cb(srv->ssl_ctx.ctx, ssl_sess_new_srv_cb);
Emeric Brun94324a42012-10-11 14:00:19 +02004915 if (srv->ssl_ctx.ciphers &&
4916 !SSL_CTX_set_cipher_list(srv->ssl_ctx.ctx, srv->ssl_ctx.ciphers)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004917 ha_alert("Proxy '%s', server '%s' [%s:%d] : unable to set SSL cipher list to '%s'.\n",
4918 curproxy->id, srv->id,
4919 srv->conf.file, srv->conf.line, srv->ssl_ctx.ciphers);
Emeric Brun94324a42012-10-11 14:00:19 +02004920 cfgerr++;
4921 }
Dirkjan Bussink415150f2018-09-14 11:14:21 +02004922
Emmanuel Hocdet839af572019-05-14 16:27:35 +02004923#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02004924 if (srv->ssl_ctx.ciphersuites &&
Pierre Cheynierbc34cd12019-03-21 16:15:47 +00004925 !SSL_CTX_set_ciphersuites(srv->ssl_ctx.ctx, srv->ssl_ctx.ciphersuites)) {
Dirkjan Bussink415150f2018-09-14 11:14:21 +02004926 ha_alert("Proxy '%s', server '%s' [%s:%d] : unable to set TLS 1.3 cipher suites to '%s'.\n",
4927 curproxy->id, srv->id,
4928 srv->conf.file, srv->conf.line, srv->ssl_ctx.ciphersuites);
4929 cfgerr++;
4930 }
4931#endif
Olivier Houchardc7566002018-11-20 23:33:50 +01004932#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
4933 if (srv->ssl_ctx.npn_str)
4934 SSL_CTX_set_next_proto_select_cb(ctx, ssl_sock_srv_select_protos, srv);
4935#endif
4936#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
4937 if (srv->ssl_ctx.alpn_str)
4938 SSL_CTX_set_alpn_protos(ctx, (unsigned char *)srv->ssl_ctx.alpn_str, srv->ssl_ctx.alpn_len);
4939#endif
4940
Emeric Brun94324a42012-10-11 14:00:19 +02004941
4942 return cfgerr;
4943}
4944
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004945/* Walks down the two trees in bind_conf and prepares all certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +02004946 * be NULL, in which case nothing is done. Returns the number of errors
4947 * encountered.
4948 */
Willy Tarreau03209342016-12-22 17:08:28 +01004949int ssl_sock_prepare_all_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02004950{
4951 struct ebmb_node *node;
4952 struct sni_ctx *sni;
4953 int err = 0;
4954
Willy Tarreaufce03112015-01-15 21:32:40 +01004955 /* Automatic memory computations need to know we use SSL there */
4956 global.ssl_used_frontend = 1;
4957
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004958 /* Make sure openssl opens /dev/urandom before the chroot */
4959 if (!ssl_initialize_random()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004960 ha_alert("OpenSSL random data generator initialization failed.\n");
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004961 err++;
4962 }
4963 /* Create initial_ctx used to start the ssl connection before do switchctx */
4964 if (!bind_conf->initial_ctx) {
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004965 err += ssl_sock_initial_ctx(bind_conf);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004966 /* It should not be necessary to call this function, but it's
4967 necessary first to check and move all initialisation related
4968 to initial_ctx in ssl_sock_initial_ctx. */
4969 err += ssl_sock_prepare_ctx(bind_conf, NULL, bind_conf->initial_ctx);
4970 }
Emeric Brun0bed9942014-10-30 19:25:24 +01004971 if (bind_conf->default_ctx)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004972 err += ssl_sock_prepare_ctx(bind_conf, bind_conf->default_ssl_conf, bind_conf->default_ctx);
Emeric Brun0bed9942014-10-30 19:25:24 +01004973
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004974 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004975 while (node) {
4976 sni = ebmb_entry(node, struct sni_ctx, name);
Emeric Brun0bed9942014-10-30 19:25:24 +01004977 if (!sni->order && sni->ctx != bind_conf->default_ctx)
4978 /* only initialize the CTX on its first occurrence and
4979 if it is not the default_ctx */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004980 err += ssl_sock_prepare_ctx(bind_conf, sni->conf, sni->ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004981 node = ebmb_next(node);
4982 }
4983
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004984 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004985 while (node) {
4986 sni = ebmb_entry(node, struct sni_ctx, name);
Emeric Brun0bed9942014-10-30 19:25:24 +01004987 if (!sni->order && sni->ctx != bind_conf->default_ctx)
4988 /* only initialize the CTX on its first occurrence and
4989 if it is not the default_ctx */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004990 err += ssl_sock_prepare_ctx(bind_conf, sni->conf, sni->ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004991 node = ebmb_next(node);
4992 }
4993 return err;
4994}
4995
Willy Tarreau55d37912016-12-21 23:38:39 +01004996/* Prepares all the contexts for a bind_conf and allocates the shared SSL
4997 * context if needed. Returns < 0 on error, 0 on success. The warnings and
4998 * alerts are directly emitted since the rest of the stack does it below.
4999 */
5000int ssl_sock_prepare_bind_conf(struct bind_conf *bind_conf)
5001{
5002 struct proxy *px = bind_conf->frontend;
5003 int alloc_ctx;
5004 int err;
5005
5006 if (!bind_conf->is_ssl) {
5007 if (bind_conf->default_ctx) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005008 ha_warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
5009 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreau55d37912016-12-21 23:38:39 +01005010 }
5011 return 0;
5012 }
5013 if (!bind_conf->default_ctx) {
Emmanuel Hocdetaa0d6372017-08-09 11:24:25 +02005014 if (bind_conf->strict_sni && !bind_conf->generate_certs) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005015 ha_warning("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d], ssl connections will fail (use 'crt').\n",
5016 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetaa0d6372017-08-09 11:24:25 +02005017 }
5018 else {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005019 ha_alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
5020 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetaa0d6372017-08-09 11:24:25 +02005021 return -1;
5022 }
Willy Tarreau55d37912016-12-21 23:38:39 +01005023 }
William Lallemandc61c0b32017-12-04 18:46:39 +01005024 if (!ssl_shctx && global.tune.sslcachesize) {
William Lallemandc3cd35f2017-11-28 11:04:43 +01005025 alloc_ctx = shctx_init(&ssl_shctx, global.tune.sslcachesize,
Frédéric Lécailleb7838af2018-10-22 16:21:39 +02005026 sizeof(struct sh_ssl_sess_hdr) + SHSESS_BLOCK_MIN_SIZE, -1,
William Lallemandc3cd35f2017-11-28 11:04:43 +01005027 sizeof(*sh_ssl_sess_tree),
5028 ((global.nbthread > 1) || (!global_ssl.private_cache && (global.nbproc > 1))) ? 1 : 0);
Frédéric Lécaille4c8aa112018-10-25 20:22:46 +02005029 if (alloc_ctx <= 0) {
William Lallemandc3cd35f2017-11-28 11:04:43 +01005030 if (alloc_ctx == SHCTX_E_INIT_LOCK)
5031 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");
5032 else
5033 ha_alert("Unable to allocate SSL session cache.\n");
5034 return -1;
5035 }
5036 /* free block callback */
5037 ssl_shctx->free_block = sh_ssl_sess_free_blocks;
5038 /* init the root tree within the extra space */
5039 sh_ssl_sess_tree = (void *)ssl_shctx + sizeof(struct shared_context);
5040 *sh_ssl_sess_tree = EB_ROOT_UNIQUE;
Willy Tarreau55d37912016-12-21 23:38:39 +01005041 }
Willy Tarreau55d37912016-12-21 23:38:39 +01005042 err = 0;
5043 /* initialize all certificate contexts */
5044 err += ssl_sock_prepare_all_ctx(bind_conf);
5045
5046 /* initialize CA variables if the certificates generation is enabled */
5047 err += ssl_sock_load_ca(bind_conf);
5048
5049 return -err;
5050}
Christopher Faulet77fe80c2015-07-29 13:02:40 +02005051
5052/* release ssl context allocated for servers. */
5053void ssl_sock_free_srv_ctx(struct server *srv)
5054{
Olivier Houchardc7566002018-11-20 23:33:50 +01005055#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
5056 if (srv->ssl_ctx.alpn_str)
5057 free(srv->ssl_ctx.alpn_str);
5058#endif
Lukas Tribusda95fd92018-11-25 13:21:27 +01005059#ifdef OPENSSL_NPN_NEGOTIATED
Olivier Houchardc7566002018-11-20 23:33:50 +01005060 if (srv->ssl_ctx.npn_str)
5061 free(srv->ssl_ctx.npn_str);
Lukas Tribus7706b852018-11-26 22:57:17 +01005062#endif
Christopher Faulet77fe80c2015-07-29 13:02:40 +02005063 if (srv->ssl_ctx.ctx)
5064 SSL_CTX_free(srv->ssl_ctx.ctx);
5065}
5066
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005067/* Walks down the two trees in bind_conf and frees all the certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +02005068 * be NULL, in which case nothing is done. The default_ctx is nullified too.
5069 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005070void ssl_sock_free_all_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02005071{
5072 struct ebmb_node *node, *back;
5073 struct sni_ctx *sni;
5074
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005075 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02005076 while (node) {
5077 sni = ebmb_entry(node, struct sni_ctx, name);
5078 back = ebmb_next(node);
5079 ebmb_delete(node);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005080 if (!sni->order) { /* only free the CTX on its first occurrence */
Emeric Brunfc0421f2012-09-07 17:30:07 +02005081 SSL_CTX_free(sni->ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005082 ssl_sock_free_ssl_conf(sni->conf);
5083 free(sni->conf);
5084 sni->conf = NULL;
5085 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02005086 free(sni);
5087 node = back;
5088 }
5089
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005090 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02005091 while (node) {
5092 sni = ebmb_entry(node, struct sni_ctx, name);
5093 back = ebmb_next(node);
5094 ebmb_delete(node);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005095 if (!sni->order) { /* only free the CTX on its first occurrence */
Emeric Brunfc0421f2012-09-07 17:30:07 +02005096 SSL_CTX_free(sni->ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005097 ssl_sock_free_ssl_conf(sni->conf);
5098 free(sni->conf);
5099 sni->conf = NULL;
5100 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02005101 free(sni);
5102 node = back;
5103 }
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01005104 SSL_CTX_free(bind_conf->initial_ctx);
5105 bind_conf->initial_ctx = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005106 bind_conf->default_ctx = NULL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005107 bind_conf->default_ssl_conf = NULL;
Emeric Brune1f38db2012-09-03 20:36:47 +02005108}
5109
Willy Tarreau795cdab2016-12-22 17:30:54 +01005110/* Destroys all the contexts for a bind_conf. This is used during deinit(). */
5111void ssl_sock_destroy_bind_conf(struct bind_conf *bind_conf)
5112{
5113 ssl_sock_free_ca(bind_conf);
5114 ssl_sock_free_all_ctx(bind_conf);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005115 ssl_sock_free_ssl_conf(&bind_conf->ssl_conf);
Willy Tarreau795cdab2016-12-22 17:30:54 +01005116 free(bind_conf->ca_sign_file);
5117 free(bind_conf->ca_sign_pass);
Willy Tarreau17b4aa12018-07-17 10:05:32 +02005118 if (bind_conf->keys_ref && !--bind_conf->keys_ref->refcount) {
Willy Tarreau795cdab2016-12-22 17:30:54 +01005119 free(bind_conf->keys_ref->filename);
5120 free(bind_conf->keys_ref->tlskeys);
5121 LIST_DEL(&bind_conf->keys_ref->list);
5122 free(bind_conf->keys_ref);
5123 }
5124 bind_conf->keys_ref = NULL;
Willy Tarreau795cdab2016-12-22 17:30:54 +01005125 bind_conf->ca_sign_pass = NULL;
5126 bind_conf->ca_sign_file = NULL;
Willy Tarreau795cdab2016-12-22 17:30:54 +01005127}
5128
Christopher Faulet31af49d2015-06-09 17:29:50 +02005129/* Load CA cert file and private key used to generate certificates */
5130int
Willy Tarreau03209342016-12-22 17:08:28 +01005131ssl_sock_load_ca(struct bind_conf *bind_conf)
Christopher Faulet31af49d2015-06-09 17:29:50 +02005132{
Willy Tarreau03209342016-12-22 17:08:28 +01005133 struct proxy *px = bind_conf->frontend;
Christopher Faulet31af49d2015-06-09 17:29:50 +02005134 FILE *fp;
5135 X509 *cacert = NULL;
5136 EVP_PKEY *capkey = NULL;
5137 int err = 0;
5138
Christopher Fauletf8bb0ce2017-09-15 09:52:49 +02005139 if (!bind_conf->generate_certs)
Christopher Faulet31af49d2015-06-09 17:29:50 +02005140 return err;
5141
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005142#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Emeric Brun821bb9b2017-06-15 16:37:39 +02005143 if (global_ssl.ctx_cache) {
Willy Tarreauef934602016-12-22 23:12:01 +01005144 ssl_ctx_lru_tree = lru64_new(global_ssl.ctx_cache);
Emeric Brun821bb9b2017-06-15 16:37:39 +02005145 }
Christopher Fauletd2cab922015-07-28 16:03:47 +02005146 ssl_ctx_lru_seed = (unsigned int)time(NULL);
Emeric Brun821bb9b2017-06-15 16:37:39 +02005147 ssl_ctx_serial = now_ms;
Willy Tarreaua84c2672015-10-09 12:10:13 +02005148#endif
Christopher Fauletd2cab922015-07-28 16:03:47 +02005149
Christopher Faulet31af49d2015-06-09 17:29:50 +02005150 if (!bind_conf->ca_sign_file) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005151 ha_alert("Proxy '%s': cannot enable certificate generation, "
5152 "no CA certificate File configured at [%s:%d].\n",
5153 px->id, bind_conf->file, bind_conf->line);
Christopher Faulet31af49d2015-06-09 17:29:50 +02005154 goto load_error;
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005155 }
Christopher Faulet31af49d2015-06-09 17:29:50 +02005156
5157 /* read in the CA certificate */
5158 if (!(fp = fopen(bind_conf->ca_sign_file, "r"))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005159 ha_alert("Proxy '%s': Failed to read CA certificate file '%s' at [%s:%d].\n",
5160 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Faulet31af49d2015-06-09 17:29:50 +02005161 goto load_error;
5162 }
5163 if (!(cacert = PEM_read_X509(fp, NULL, NULL, NULL))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005164 ha_alert("Proxy '%s': Failed to read CA certificate file '%s' at [%s:%d].\n",
5165 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005166 goto read_error;
Christopher Faulet31af49d2015-06-09 17:29:50 +02005167 }
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005168 rewind(fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02005169 if (!(capkey = PEM_read_PrivateKey(fp, NULL, NULL, bind_conf->ca_sign_pass))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005170 ha_alert("Proxy '%s': Failed to read CA private key file '%s' at [%s:%d].\n",
5171 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005172 goto read_error;
Christopher Faulet31af49d2015-06-09 17:29:50 +02005173 }
Christopher Faulet31af49d2015-06-09 17:29:50 +02005174
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005175 fclose (fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02005176 bind_conf->ca_sign_cert = cacert;
5177 bind_conf->ca_sign_pkey = capkey;
5178 return err;
5179
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005180 read_error:
5181 fclose (fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02005182 if (capkey) EVP_PKEY_free(capkey);
5183 if (cacert) X509_free(cacert);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005184 load_error:
5185 bind_conf->generate_certs = 0;
5186 err++;
Christopher Faulet31af49d2015-06-09 17:29:50 +02005187 return err;
5188}
5189
5190/* Release CA cert and private key used to generate certificated */
5191void
5192ssl_sock_free_ca(struct bind_conf *bind_conf)
5193{
Christopher Faulet31af49d2015-06-09 17:29:50 +02005194 if (bind_conf->ca_sign_pkey)
5195 EVP_PKEY_free(bind_conf->ca_sign_pkey);
5196 if (bind_conf->ca_sign_cert)
5197 X509_free(bind_conf->ca_sign_cert);
Willy Tarreau94ff03a2016-12-22 17:57:46 +01005198 bind_conf->ca_sign_pkey = NULL;
5199 bind_conf->ca_sign_cert = NULL;
Christopher Faulet31af49d2015-06-09 17:29:50 +02005200}
5201
Emeric Brun46591952012-05-18 15:47:34 +02005202/*
5203 * This function is called if SSL * context is not yet allocated. The function
5204 * is designed to be called before any other data-layer operation and sets the
5205 * handshake flag on the connection. It is safe to call it multiple times.
5206 * It returns 0 on success and -1 in error case.
5207 */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005208static int ssl_sock_init(struct connection *conn, void **xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02005209{
Olivier Houchard66ab4982019-02-26 18:37:15 +01005210 struct ssl_sock_ctx *ctx;
Emeric Brun46591952012-05-18 15:47:34 +02005211 /* already initialized */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005212 if (*xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02005213 return 0;
5214
Willy Tarreau3c728722014-01-23 13:50:42 +01005215 if (!conn_ctrl_ready(conn))
Willy Tarreauf79c8172013-10-21 16:30:56 +02005216 return 0;
5217
Olivier Houchard66ab4982019-02-26 18:37:15 +01005218 ctx = pool_alloc(ssl_sock_ctx_pool);
5219 if (!ctx) {
5220 conn->err_code = CO_ER_SSL_NO_MEM;
5221 return -1;
5222 }
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02005223 ctx->wait_event.tasklet = tasklet_new();
5224 if (!ctx->wait_event.tasklet) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02005225 conn->err_code = CO_ER_SSL_NO_MEM;
5226 pool_free(ssl_sock_ctx_pool, ctx);
5227 return -1;
5228 }
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02005229 ctx->wait_event.tasklet->process = ssl_sock_io_cb;
5230 ctx->wait_event.tasklet->context = ctx;
Olivier Houchardea8dd942019-05-20 14:02:16 +02005231 ctx->wait_event.events = 0;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01005232 ctx->sent_early_data = 0;
Olivier Houchardf6715e72019-12-19 15:02:39 +01005233 ctx->early_buf = BUF_NULL;
Olivier Houcharda8955d52019-04-07 22:00:38 +02005234 ctx->conn = conn;
Olivier Houchard81284e62019-06-06 13:21:23 +02005235 ctx->send_wait = NULL;
5236 ctx->recv_wait = NULL;
Emeric Brun87cfd662019-09-06 15:36:02 +02005237 ctx->xprt_st = 0;
5238 ctx->xprt_ctx = NULL;
Olivier Houcharda8955d52019-04-07 22:00:38 +02005239
5240 /* Only work with sockets for now, this should be adapted when we'll
5241 * add QUIC support.
5242 */
5243 ctx->xprt = xprt_get(XPRT_RAW);
Olivier Houchard19afb272019-05-23 18:24:07 +02005244 if (ctx->xprt->init) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02005245 if (ctx->xprt->init(conn, &ctx->xprt_ctx) != 0)
5246 goto err;
Olivier Houchard19afb272019-05-23 18:24:07 +02005247 }
Olivier Houchard66ab4982019-02-26 18:37:15 +01005248
Willy Tarreau20879a02012-12-03 16:32:10 +01005249 if (global.maxsslconn && sslconns >= global.maxsslconn) {
5250 conn->err_code = CO_ER_SSL_TOO_MANY;
Olivier Houchardea8dd942019-05-20 14:02:16 +02005251 goto err;
Willy Tarreau20879a02012-12-03 16:32:10 +01005252 }
Willy Tarreau403edff2012-09-06 11:58:37 +02005253
Emeric Brun46591952012-05-18 15:47:34 +02005254 /* If it is in client mode initiate SSL session
5255 in connect state otherwise accept state */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01005256 if (objt_server(conn->target)) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005257 int may_retry = 1;
5258
5259 retry_connect:
Emeric Brun46591952012-05-18 15:47:34 +02005260 /* Alloc a new SSL session ctx */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005261 ctx->ssl = SSL_new(__objt_server(conn->target)->ssl_ctx.ctx);
5262 if (!ctx->ssl) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005263 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005264 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005265 goto retry_connect;
5266 }
Willy Tarreau20879a02012-12-03 16:32:10 +01005267 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01005268 goto err;
Willy Tarreau20879a02012-12-03 16:32:10 +01005269 }
Olivier Houcharda8955d52019-04-07 22:00:38 +02005270 ctx->bio = BIO_new(ha_meth);
5271 if (!ctx->bio) {
Olivier Houchardb451b972020-01-24 15:17:38 +01005272 SSL_free(ctx->ssl);
5273 ctx->ssl = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005274 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005275 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005276 goto retry_connect;
5277 }
Emeric Brun55476152014-11-12 17:35:37 +01005278 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01005279 goto err;
Emeric Brun55476152014-11-12 17:35:37 +01005280 }
Olivier Houcharda8955d52019-04-07 22:00:38 +02005281 BIO_set_data(ctx->bio, ctx);
Olivier Houcharda8955d52019-04-07 22:00:38 +02005282 SSL_set_bio(ctx->ssl, ctx->bio, ctx->bio);
Emeric Brun46591952012-05-18 15:47:34 +02005283
Evan Broderbe554312013-06-27 00:05:25 -07005284 /* set connection pointer */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005285 if (!SSL_set_ex_data(ctx->ssl, ssl_app_data_index, conn)) {
5286 SSL_free(ctx->ssl);
5287 ctx->ssl = NULL;
Emeric Brun55476152014-11-12 17:35:37 +01005288 conn->xprt_ctx = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005289 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005290 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005291 goto retry_connect;
5292 }
Emeric Brun55476152014-11-12 17:35:37 +01005293 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01005294 goto err;
Emeric Brun55476152014-11-12 17:35:37 +01005295 }
5296
Olivier Houchard66ab4982019-02-26 18:37:15 +01005297 SSL_set_connect_state(ctx->ssl);
Willy Tarreau07d94e42018-09-20 10:57:52 +02005298 if (__objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr) {
5299 const unsigned char *ptr = __objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr;
5300 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 +01005301 if (sess && !SSL_set_session(ctx->ssl, sess)) {
Olivier Houcharde6060c52017-11-16 17:42:52 +01005302 SSL_SESSION_free(sess);
Willy Tarreau07d94e42018-09-20 10:57:52 +02005303 free(__objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr);
5304 __objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr = NULL;
Olivier Houcharde6060c52017-11-16 17:42:52 +01005305 } else if (sess) {
5306 SSL_SESSION_free(sess);
Emeric Brun55476152014-11-12 17:35:37 +01005307 }
5308 }
Evan Broderbe554312013-06-27 00:05:25 -07005309
Emeric Brun46591952012-05-18 15:47:34 +02005310 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +02005311 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Willy Tarreau403edff2012-09-06 11:58:37 +02005312
Olivier Houchard2be5a4c2019-03-08 18:54:43 +01005313 _HA_ATOMIC_ADD(&sslconns, 1);
5314 _HA_ATOMIC_ADD(&totalsslconns, 1);
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005315 *xprt_ctx = ctx;
Olivier Houchardea8dd942019-05-20 14:02:16 +02005316 /* Start the handshake */
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02005317 tasklet_wakeup(ctx->wait_event.tasklet);
Olivier Houchardea8dd942019-05-20 14:02:16 +02005318 if (conn->flags & CO_FL_ERROR)
5319 goto err;
Emeric Brun46591952012-05-18 15:47:34 +02005320 return 0;
5321 }
Willy Tarreau3fdb3662012-11-12 00:42:33 +01005322 else if (objt_listener(conn->target)) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005323 int may_retry = 1;
5324
5325 retry_accept:
Emeric Brun46591952012-05-18 15:47:34 +02005326 /* Alloc a new SSL session ctx */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005327 ctx->ssl = SSL_new(__objt_listener(conn->target)->bind_conf->initial_ctx);
5328 if (!ctx->ssl) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005329 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005330 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005331 goto retry_accept;
5332 }
Willy Tarreau20879a02012-12-03 16:32:10 +01005333 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01005334 goto err;
Willy Tarreau20879a02012-12-03 16:32:10 +01005335 }
Olivier Houcharda8955d52019-04-07 22:00:38 +02005336 ctx->bio = BIO_new(ha_meth);
5337 if (!ctx->bio) {
Olivier Houchardb451b972020-01-24 15:17:38 +01005338 SSL_free(ctx->ssl);
5339 ctx->ssl = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005340 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005341 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005342 goto retry_accept;
5343 }
Emeric Brun55476152014-11-12 17:35:37 +01005344 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01005345 goto err;
Emeric Brun55476152014-11-12 17:35:37 +01005346 }
Olivier Houcharda8955d52019-04-07 22:00:38 +02005347 BIO_set_data(ctx->bio, ctx);
Olivier Houcharda8955d52019-04-07 22:00:38 +02005348 SSL_set_bio(ctx->ssl, ctx->bio, ctx->bio);
Emeric Brun46591952012-05-18 15:47:34 +02005349
Emeric Brune1f38db2012-09-03 20:36:47 +02005350 /* set connection pointer */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005351 if (!SSL_set_ex_data(ctx->ssl, ssl_app_data_index, conn)) {
5352 SSL_free(ctx->ssl);
5353 ctx->ssl = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005354 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005355 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005356 goto retry_accept;
5357 }
Emeric Brun55476152014-11-12 17:35:37 +01005358 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01005359 goto err;
Emeric Brun55476152014-11-12 17:35:37 +01005360 }
5361
Frédéric Lécaille583362f2020-01-24 14:56:18 +01005362#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
5363 if (__objt_listener(conn->target)->bind_conf->ssl_conf.early_data) {
5364 b_alloc(&ctx->early_buf);
5365 SSL_set_max_early_data(ctx->ssl,
5366 /* Only allow early data if we managed to allocate
5367 * a buffer.
5368 */
5369 (!b_is_null(&ctx->early_buf)) ?
5370 global.tune.bufsize - global.tune.maxrewrite : 0);
5371 }
5372#endif
5373
Olivier Houchard66ab4982019-02-26 18:37:15 +01005374 SSL_set_accept_state(ctx->ssl);
Emeric Brune1f38db2012-09-03 20:36:47 +02005375
Emeric Brun46591952012-05-18 15:47:34 +02005376 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +02005377 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Emmanuel Hocdet510fce52019-08-05 18:04:16 +02005378#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Olivier Houchardc2aae742017-09-22 18:26:28 +02005379 conn->flags |= CO_FL_EARLY_SSL_HS;
5380#endif
Willy Tarreau403edff2012-09-06 11:58:37 +02005381
Olivier Houchard2be5a4c2019-03-08 18:54:43 +01005382 _HA_ATOMIC_ADD(&sslconns, 1);
5383 _HA_ATOMIC_ADD(&totalsslconns, 1);
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005384 *xprt_ctx = ctx;
Olivier Houchardea8dd942019-05-20 14:02:16 +02005385 /* Start the handshake */
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02005386 tasklet_wakeup(ctx->wait_event.tasklet);
Olivier Houchardea8dd942019-05-20 14:02:16 +02005387 if (conn->flags & CO_FL_ERROR)
5388 goto err;
Emeric Brun46591952012-05-18 15:47:34 +02005389 return 0;
5390 }
5391 /* don't know how to handle such a target */
Willy Tarreau20879a02012-12-03 16:32:10 +01005392 conn->err_code = CO_ER_SSL_NO_TARGET;
Olivier Houchard66ab4982019-02-26 18:37:15 +01005393err:
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02005394 if (ctx && ctx->wait_event.tasklet)
5395 tasklet_free(ctx->wait_event.tasklet);
Olivier Houchard66ab4982019-02-26 18:37:15 +01005396 pool_free(ssl_sock_ctx_pool, ctx);
Emeric Brun46591952012-05-18 15:47:34 +02005397 return -1;
5398}
5399
5400
5401/* This is the callback which is used when an SSL handshake is pending. It
5402 * updates the FD status if it wants some polling before being called again.
5403 * It returns 0 if it fails in a fatal way or needs to poll to go further,
5404 * otherwise it returns non-zero and removes itself from the connection's
5405 * flags (the bit is provided in <flag> by the caller).
5406 */
Olivier Houchard000694c2019-05-23 14:45:12 +02005407static int ssl_sock_handshake(struct connection *conn, unsigned int flag)
Emeric Brun46591952012-05-18 15:47:34 +02005408{
Olivier Houchard66ab4982019-02-26 18:37:15 +01005409 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
Emeric Brun46591952012-05-18 15:47:34 +02005410 int ret;
Willy Tarreau7a466f62021-02-02 15:42:25 +01005411 socklen_t lskerr;
5412 int skerr;
5413
Emeric Brun46591952012-05-18 15:47:34 +02005414
Willy Tarreau3c728722014-01-23 13:50:42 +01005415 if (!conn_ctrl_ready(conn))
Willy Tarreauf79c8172013-10-21 16:30:56 +02005416 return 0;
5417
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005418 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02005419 goto out_error;
5420
Willy Tarreau7a466f62021-02-02 15:42:25 +01005421 /* don't start calculating a handshake on a dead connection */
5422 if (conn->flags & (CO_FL_ERROR | CO_FL_SOCK_RD_SH | CO_FL_SOCK_WR_SH))
5423 goto out_error;
5424
5425 /* FIXME/WT: for now we don't have a clear way to inspect the connection
5426 * status from the lower layers, so let's check the FD directly. Ideally
5427 * the xprt layers should provide some status indicating their knowledge
5428 * of shutdowns or error.
5429 */
5430 skerr = 0;
5431 lskerr = sizeof(skerr);
5432 if ((getsockopt(conn->handle.fd, SOL_SOCKET, SO_ERROR, &skerr, &lskerr) < 0) ||
5433 skerr != 0)
5434 goto out_error;
5435
Willy Tarreau5db847a2019-05-09 14:13:35 +02005436#if HA_OPENSSL_VERSION_NUMBER >= 0x10101000L
Olivier Houchardc2aae742017-09-22 18:26:28 +02005437 /*
5438 * Check if we have early data. If we do, we have to read them
5439 * before SSL_do_handshake() is called, And there's no way to
5440 * detect early data, except to try to read them
5441 */
5442 if (conn->flags & CO_FL_EARLY_SSL_HS) {
Olivier Houchardf6715e72019-12-19 15:02:39 +01005443 size_t read_data = 0;
Olivier Houchardc2aae742017-09-22 18:26:28 +02005444
Olivier Houchardf6715e72019-12-19 15:02:39 +01005445 while (1) {
5446 ret = SSL_read_early_data(ctx->ssl,
5447 b_tail(&ctx->early_buf), b_room(&ctx->early_buf),
5448 &read_data);
5449 if (ret == SSL_READ_EARLY_DATA_ERROR)
5450 goto check_error;
5451 if (read_data > 0) {
5452 conn->flags |= CO_FL_EARLY_DATA;
5453 b_add(&ctx->early_buf, read_data);
5454 }
5455 if (ret == SSL_READ_EARLY_DATA_FINISH) {
5456 conn->flags &= ~CO_FL_EARLY_SSL_HS;
5457 if (!b_data(&ctx->early_buf))
5458 b_free(&ctx->early_buf);
5459 break;
5460 }
5461 }
Olivier Houchardc2aae742017-09-22 18:26:28 +02005462 }
5463#endif
Emeric Brun674b7432012-11-08 19:21:55 +01005464 /* If we use SSL_do_handshake to process a reneg initiated by
5465 * the remote peer, it sometimes returns SSL_ERROR_SSL.
5466 * Usually SSL_write and SSL_read are used and process implicitly
5467 * the reneg handshake.
5468 * Here we use SSL_peek as a workaround for reneg.
5469 */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005470 if ((conn->flags & CO_FL_CONNECTED) && SSL_renegotiate_pending(ctx->ssl)) {
Emeric Brun674b7432012-11-08 19:21:55 +01005471 char c;
5472
Olivier Houchard66ab4982019-02-26 18:37:15 +01005473 ret = SSL_peek(ctx->ssl, &c, 1);
Emeric Brun674b7432012-11-08 19:21:55 +01005474 if (ret <= 0) {
5475 /* handshake may have not been completed, let's find why */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005476 ret = SSL_get_error(ctx->ssl, ret);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005477
Emeric Brun674b7432012-11-08 19:21:55 +01005478 if (ret == SSL_ERROR_WANT_WRITE) {
5479 /* SSL handshake needs to write, L4 connection may not be ready */
Olivier Houchard03abf2d2019-05-28 10:12:02 +02005480 if (!(ctx->wait_event.events & SUB_RETRY_SEND))
Olivier Houchardea8dd942019-05-20 14:02:16 +02005481 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_SEND, &ctx->wait_event);
Emeric Brun674b7432012-11-08 19:21:55 +01005482 return 0;
5483 }
5484 else if (ret == SSL_ERROR_WANT_READ) {
5485 /* handshake may have been completed but we have
5486 * no more data to read.
5487 */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005488 if (!SSL_renegotiate_pending(ctx->ssl)) {
Emeric Brun674b7432012-11-08 19:21:55 +01005489 ret = 1;
5490 goto reneg_ok;
5491 }
5492 /* SSL handshake needs to read, L4 connection is ready */
Olivier Houchard03abf2d2019-05-28 10:12:02 +02005493 if (!(ctx->wait_event.events & SUB_RETRY_RECV))
Olivier Houchardea8dd942019-05-20 14:02:16 +02005494 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_RECV, &ctx->wait_event);
Emeric Brun674b7432012-11-08 19:21:55 +01005495 return 0;
5496 }
Willy Tarreau5db847a2019-05-09 14:13:35 +02005497#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005498 else if (ret == SSL_ERROR_WANT_ASYNC) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02005499 ssl_async_process_fds(ctx);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005500 return 0;
5501 }
5502#endif
Emeric Brun674b7432012-11-08 19:21:55 +01005503 else if (ret == SSL_ERROR_SYSCALL) {
5504 /* if errno is null, then connection was successfully established */
5505 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
5506 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Willy Tarreau20879a02012-12-03 16:32:10 +01005507 if (!conn->err_code) {
Lukas Tribus5db881f2019-07-08 14:29:15 +02005508#if defined(OPENSSL_IS_BORINGSSL) || defined(LIBRESSL_VERSION_NUMBER)
5509 /* do not handle empty handshakes in BoringSSL or LibreSSL */
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005510 conn->err_code = CO_ER_SSL_HANDSHAKE;
5511#else
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005512 int empty_handshake;
Willy Tarreau5db847a2019-05-09 14:13:35 +02005513#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL)
Lukas Tribus5db881f2019-07-08 14:29:15 +02005514 /* use SSL_get_state() in OpenSSL >= 1.1.0; SSL_state() is broken */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005515 OSSL_HANDSHAKE_STATE state = SSL_get_state((SSL *)ctx->ssl);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005516 empty_handshake = state == TLS_ST_BEFORE;
5517#else
Lukas Tribus5db881f2019-07-08 14:29:15 +02005518 /* access packet_length directly in OpenSSL <= 1.0.2; SSL_state() is broken */
5519 empty_handshake = !ctx->ssl->packet_length;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005520#endif
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005521 if (empty_handshake) {
Emeric Brun29f037d2014-04-25 19:05:36 +02005522 if (!errno) {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01005523 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emeric Brun29f037d2014-04-25 19:05:36 +02005524 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5525 else
5526 conn->err_code = CO_ER_SSL_EMPTY;
5527 }
5528 else {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01005529 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emeric Brun29f037d2014-04-25 19:05:36 +02005530 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5531 else
5532 conn->err_code = CO_ER_SSL_ABORT;
5533 }
5534 }
5535 else {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01005536 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emeric Brun29f037d2014-04-25 19:05:36 +02005537 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
Willy Tarreau20879a02012-12-03 16:32:10 +01005538 else
Emeric Brun29f037d2014-04-25 19:05:36 +02005539 conn->err_code = CO_ER_SSL_HANDSHAKE;
5540 }
Lukas Tribus5db881f2019-07-08 14:29:15 +02005541#endif /* BoringSSL or LibreSSL */
Willy Tarreau20879a02012-12-03 16:32:10 +01005542 }
Emeric Brun674b7432012-11-08 19:21:55 +01005543 goto out_error;
5544 }
5545 else {
5546 /* Fail on all other handshake errors */
5547 /* Note: OpenSSL may leave unread bytes in the socket's
5548 * buffer, causing an RST to be emitted upon close() on
5549 * TCP sockets. We first try to drain possibly pending
5550 * data to avoid this as much as possible.
5551 */
Willy Tarreaud85c4852015-03-13 00:40:28 +01005552 conn_sock_drain(conn);
Willy Tarreau20879a02012-12-03 16:32:10 +01005553 if (!conn->err_code)
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01005554 conn->err_code = (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT) ?
Willy Tarreauf51c6982014-04-25 20:02:39 +02005555 CO_ER_SSL_KILLED_HB : CO_ER_SSL_HANDSHAKE;
Emeric Brun674b7432012-11-08 19:21:55 +01005556 goto out_error;
5557 }
5558 }
5559 /* read some data: consider handshake completed */
5560 goto reneg_ok;
5561 }
Olivier Houchard66ab4982019-02-26 18:37:15 +01005562 ret = SSL_do_handshake(ctx->ssl);
Olivier Houchardc2aae742017-09-22 18:26:28 +02005563check_error:
Emeric Brun46591952012-05-18 15:47:34 +02005564 if (ret != 1) {
5565 /* handshake did not complete, let's find why */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005566 ret = SSL_get_error(ctx->ssl, ret);
Emeric Brun46591952012-05-18 15:47:34 +02005567
5568 if (ret == SSL_ERROR_WANT_WRITE) {
5569 /* SSL handshake needs to write, L4 connection may not be ready */
Olivier Houchard03abf2d2019-05-28 10:12:02 +02005570 if (!(ctx->wait_event.events & SUB_RETRY_SEND))
Olivier Houchardea8dd942019-05-20 14:02:16 +02005571 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_SEND, &ctx->wait_event);
Emeric Brun46591952012-05-18 15:47:34 +02005572 return 0;
5573 }
5574 else if (ret == SSL_ERROR_WANT_READ) {
5575 /* SSL handshake needs to read, L4 connection is ready */
Olivier Houchardea8dd942019-05-20 14:02:16 +02005576 if (!(ctx->wait_event.events & SUB_RETRY_RECV))
Olivier Houchardea8dd942019-05-20 14:02:16 +02005577 ctx->xprt->subscribe(conn, ctx->xprt_ctx,
5578 SUB_RETRY_RECV, &ctx->wait_event);
Emeric Brun46591952012-05-18 15:47:34 +02005579 return 0;
5580 }
Willy Tarreau5db847a2019-05-09 14:13:35 +02005581#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005582 else if (ret == SSL_ERROR_WANT_ASYNC) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02005583 ssl_async_process_fds(ctx);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005584 return 0;
5585 }
5586#endif
Willy Tarreau89230192012-09-28 20:22:13 +02005587 else if (ret == SSL_ERROR_SYSCALL) {
5588 /* if errno is null, then connection was successfully established */
5589 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
5590 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005591 if (!conn->err_code) {
Lukas Tribus5db881f2019-07-08 14:29:15 +02005592#if defined(OPENSSL_IS_BORINGSSL) || defined(LIBRESSL_VERSION_NUMBER)
5593 /* do not handle empty handshakes in BoringSSL or LibreSSL */
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005594 conn->err_code = CO_ER_SSL_HANDSHAKE;
5595#else
5596 int empty_handshake;
Willy Tarreau5db847a2019-05-09 14:13:35 +02005597#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL)
Lukas Tribus5db881f2019-07-08 14:29:15 +02005598 /* use SSL_get_state() in OpenSSL >= 1.1.0; SSL_state() is broken */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005599 OSSL_HANDSHAKE_STATE state = SSL_get_state(ctx->ssl);
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005600 empty_handshake = state == TLS_ST_BEFORE;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005601#else
Lukas Tribus5db881f2019-07-08 14:29:15 +02005602 /* access packet_length directly in OpenSSL <= 1.0.2; SSL_state() is broken */
5603 empty_handshake = !ctx->ssl->packet_length;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005604#endif
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005605 if (empty_handshake) {
5606 if (!errno) {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01005607 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005608 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5609 else
5610 conn->err_code = CO_ER_SSL_EMPTY;
5611 }
5612 else {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01005613 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005614 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5615 else
5616 conn->err_code = CO_ER_SSL_ABORT;
5617 }
Emeric Brun29f037d2014-04-25 19:05:36 +02005618 }
5619 else {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01005620 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emeric Brun29f037d2014-04-25 19:05:36 +02005621 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5622 else
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005623 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun29f037d2014-04-25 19:05:36 +02005624 }
Lukas Tribus5db881f2019-07-08 14:29:15 +02005625#endif /* BoringSSL or LibreSSL */
Emeric Brun29f037d2014-04-25 19:05:36 +02005626 }
Willy Tarreau89230192012-09-28 20:22:13 +02005627 goto out_error;
5628 }
Emeric Brun46591952012-05-18 15:47:34 +02005629 else {
5630 /* Fail on all other handshake errors */
Willy Tarreau566dc552012-10-19 20:52:18 +02005631 /* Note: OpenSSL may leave unread bytes in the socket's
5632 * buffer, causing an RST to be emitted upon close() on
5633 * TCP sockets. We first try to drain possibly pending
5634 * data to avoid this as much as possible.
5635 */
Willy Tarreaud85c4852015-03-13 00:40:28 +01005636 conn_sock_drain(conn);
Willy Tarreau20879a02012-12-03 16:32:10 +01005637 if (!conn->err_code)
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01005638 conn->err_code = (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT) ?
Willy Tarreauf51c6982014-04-25 20:02:39 +02005639 CO_ER_SSL_KILLED_HB : CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02005640 goto out_error;
5641 }
5642 }
Willy Tarreau5db847a2019-05-09 14:13:35 +02005643#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Olivier Houchard522eea72017-11-03 16:27:47 +01005644 else {
5645 /*
5646 * If the server refused the early data, we have to send a
5647 * 425 to the client, as we no longer have the data to sent
5648 * them again.
5649 */
5650 if ((conn->flags & CO_FL_EARLY_DATA) && (objt_server(conn->target))) {
Olivier Houchard66ab4982019-02-26 18:37:15 +01005651 if (SSL_get_early_data_status(ctx->ssl) == SSL_EARLY_DATA_REJECTED) {
Olivier Houchard522eea72017-11-03 16:27:47 +01005652 conn->err_code = CO_ER_SSL_EARLY_FAILED;
5653 goto out_error;
5654 }
5655 }
5656 }
5657#endif
5658
Emeric Brun46591952012-05-18 15:47:34 +02005659
Emeric Brun674b7432012-11-08 19:21:55 +01005660reneg_ok:
Emeric Brunb5e42a82017-06-06 12:35:14 +00005661
Willy Tarreau5db847a2019-05-09 14:13:35 +02005662#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00005663 /* ASYNC engine API doesn't support moving read/write
5664 * buffers. So we disable ASYNC mode right after
5665 * the handshake to avoid buffer oveflows.
5666 */
5667 if (global_ssl.async)
Olivier Houchard66ab4982019-02-26 18:37:15 +01005668 SSL_clear_mode(ctx->ssl, SSL_MODE_ASYNC);
Emeric Brunb5e42a82017-06-06 12:35:14 +00005669#endif
Emeric Brun46591952012-05-18 15:47:34 +02005670 /* Handshake succeeded */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005671 if (!SSL_session_reused(ctx->ssl)) {
Willy Tarreau0c9c2722014-05-28 12:28:58 +02005672 if (objt_server(conn->target)) {
5673 update_freq_ctr(&global.ssl_be_keys_per_sec, 1);
5674 if (global.ssl_be_keys_per_sec.curr_ctr > global.ssl_be_keys_max)
5675 global.ssl_be_keys_max = global.ssl_be_keys_per_sec.curr_ctr;
Emeric Brun46591952012-05-18 15:47:34 +02005676 }
Willy Tarreau0c9c2722014-05-28 12:28:58 +02005677 else {
5678 update_freq_ctr(&global.ssl_fe_keys_per_sec, 1);
5679 if (global.ssl_fe_keys_per_sec.curr_ctr > global.ssl_fe_keys_max)
5680 global.ssl_fe_keys_max = global.ssl_fe_keys_per_sec.curr_ctr;
5681 }
Emeric Brun46591952012-05-18 15:47:34 +02005682 }
5683
5684 /* The connection is now established at both layers, it's time to leave */
5685 conn->flags &= ~(flag | CO_FL_WAIT_L4_CONN | CO_FL_WAIT_L6_CONN);
5686 return 1;
5687
5688 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01005689 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02005690 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01005691 ERR_clear_error();
5692
Emeric Brun9fa89732012-10-04 17:09:56 +02005693 /* free resumed session if exists */
Willy Tarreau07d94e42018-09-20 10:57:52 +02005694 if (objt_server(conn->target) && __objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr) {
5695 free(__objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr);
5696 __objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr = NULL;
Emeric Brun9fa89732012-10-04 17:09:56 +02005697 }
5698
Emeric Brun46591952012-05-18 15:47:34 +02005699 /* Fail on all other handshake errors */
5700 conn->flags |= CO_FL_ERROR;
Willy Tarreau20879a02012-12-03 16:32:10 +01005701 if (!conn->err_code)
5702 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02005703 return 0;
5704}
5705
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005706static int ssl_subscribe(struct connection *conn, void *xprt_ctx, int event_type, void *param)
Olivier Houcharddf357842019-03-21 16:30:07 +01005707{
Olivier Houchardea8dd942019-05-20 14:02:16 +02005708 struct wait_event *sw;
5709 struct ssl_sock_ctx *ctx = xprt_ctx;
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005710
Olivier Houcharda37eb6a2019-06-24 18:57:39 +02005711 if (!ctx)
5712 return -1;
5713
Olivier Houchardea8dd942019-05-20 14:02:16 +02005714 if (event_type & SUB_RETRY_RECV) {
5715 sw = param;
5716 BUG_ON(ctx->recv_wait != NULL || (sw->events & SUB_RETRY_RECV));
5717 sw->events |= SUB_RETRY_RECV;
5718 ctx->recv_wait = sw;
5719 if (!(conn->flags & CO_FL_SSL_WAIT_HS) &&
5720 !(ctx->wait_event.events & SUB_RETRY_RECV))
5721 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_RECV, &ctx->wait_event);
5722 event_type &= ~SUB_RETRY_RECV;
5723 }
5724 if (event_type & SUB_RETRY_SEND) {
5725sw = param;
5726 BUG_ON(ctx->send_wait != NULL || (sw->events & SUB_RETRY_SEND));
5727 sw->events |= SUB_RETRY_SEND;
5728 ctx->send_wait = sw;
5729 if (!(conn->flags & CO_FL_SSL_WAIT_HS) &&
5730 !(ctx->wait_event.events & SUB_RETRY_SEND))
5731 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_SEND, &ctx->wait_event);
5732 event_type &= ~SUB_RETRY_SEND;
5733
5734 }
5735 if (event_type != 0)
5736 return -1;
5737 return 0;
Olivier Houcharddf357842019-03-21 16:30:07 +01005738}
5739
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005740static int ssl_unsubscribe(struct connection *conn, void *xprt_ctx, int event_type, void *param)
Olivier Houcharddf357842019-03-21 16:30:07 +01005741{
Olivier Houchardea8dd942019-05-20 14:02:16 +02005742 struct wait_event *sw;
5743 struct ssl_sock_ctx *ctx = xprt_ctx;
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005744
Olivier Houchardea8dd942019-05-20 14:02:16 +02005745 if (event_type & SUB_RETRY_RECV) {
5746 sw = param;
5747 BUG_ON(ctx->recv_wait != sw);
5748 ctx->recv_wait = NULL;
5749 sw->events &= ~SUB_RETRY_RECV;
5750 /* If we subscribed, and we're not doing the handshake,
5751 * then we subscribed because the upper layer asked for it,
5752 * as the upper layer is no longer interested, we can
5753 * unsubscribe too.
5754 */
5755 if (!(ctx->conn->flags & CO_FL_SSL_WAIT_HS) &&
5756 (ctx->wait_event.events & SUB_RETRY_RECV))
5757 conn_unsubscribe(conn, ctx->xprt_ctx, SUB_RETRY_RECV,
5758 &ctx->wait_event);
5759 }
5760 if (event_type & SUB_RETRY_SEND) {
5761 sw = param;
5762 BUG_ON(ctx->send_wait != sw);
5763 ctx->send_wait = NULL;
5764 sw->events &= ~SUB_RETRY_SEND;
5765 if (!(ctx->conn->flags & CO_FL_SSL_WAIT_HS) &&
5766 (ctx->wait_event.events & SUB_RETRY_SEND))
5767 conn_unsubscribe(conn, ctx->xprt_ctx, SUB_RETRY_SEND,
5768 &ctx->wait_event);
5769
5770 }
5771
5772 return 0;
Olivier Houcharddf357842019-03-21 16:30:07 +01005773}
5774
Olivier Houchard2e055482019-05-27 19:50:12 +02005775/* Use the provided XPRT as an underlying XPRT, and provide the old one.
5776 * Returns 0 on success, and non-zero on failure.
5777 */
5778static 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)
5779{
5780 struct ssl_sock_ctx *ctx = xprt_ctx;
5781
5782 if (oldxprt_ops != NULL)
5783 *oldxprt_ops = ctx->xprt;
5784 if (oldxprt_ctx != NULL)
5785 *oldxprt_ctx = ctx->xprt_ctx;
5786 ctx->xprt = toadd_ops;
5787 ctx->xprt_ctx = toadd_ctx;
5788 return 0;
5789}
5790
Olivier Houchard5149b592019-05-23 17:47:36 +02005791/* Remove the specified xprt. If if it our underlying XPRT, remove it and
5792 * return 0, otherwise just call the remove_xprt method from the underlying
5793 * XPRT.
5794 */
5795static int ssl_remove_xprt(struct connection *conn, void *xprt_ctx, void *toremove_ctx, const struct xprt_ops *newops, void *newctx)
5796{
5797 struct ssl_sock_ctx *ctx = xprt_ctx;
5798
5799 if (ctx->xprt_ctx == toremove_ctx) {
5800 ctx->xprt_ctx = newctx;
5801 ctx->xprt = newops;
5802 return 0;
5803 }
5804 return (ctx->xprt->remove_xprt(conn, ctx->xprt_ctx, toremove_ctx, newops, newctx));
5805}
5806
Olivier Houchardea8dd942019-05-20 14:02:16 +02005807static struct task *ssl_sock_io_cb(struct task *t, void *context, unsigned short state)
5808{
5809 struct ssl_sock_ctx *ctx = context;
5810
5811 /* First if we're doing an handshake, try that */
5812 if (ctx->conn->flags & CO_FL_SSL_WAIT_HS)
5813 ssl_sock_handshake(ctx->conn, CO_FL_SSL_WAIT_HS);
5814 /* If we had an error, or the handshake is done and I/O is available,
5815 * let the upper layer know.
5816 * If no mux was set up yet, and nobody subscribed, then call
5817 * xprt_done_cb() ourself if it's set, or destroy the connection,
5818 * we can't be sure conn_fd_handler() will be called again.
5819 */
5820 if ((ctx->conn->flags & CO_FL_ERROR) ||
5821 !(ctx->conn->flags & CO_FL_SSL_WAIT_HS)) {
5822 int ret = 0;
5823 int woke = 0;
5824
5825 /* On error, wake any waiter */
5826 if (ctx->recv_wait) {
5827 ctx->recv_wait->events &= ~SUB_RETRY_RECV;
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02005828 tasklet_wakeup(ctx->recv_wait->tasklet);
Olivier Houchardea8dd942019-05-20 14:02:16 +02005829 ctx->recv_wait = NULL;
5830 woke = 1;
5831 }
5832 if (ctx->send_wait) {
5833 ctx->send_wait->events &= ~SUB_RETRY_SEND;
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02005834 tasklet_wakeup(ctx->send_wait->tasklet);
Olivier Houchardea8dd942019-05-20 14:02:16 +02005835 ctx->send_wait = NULL;
5836 woke = 1;
5837 }
5838 /* If we're the first xprt for the connection, let the
5839 * upper layers know. If xprt_done_cb() is set, call it,
5840 * otherwise, we should have a mux, so call its wake
5841 * method if we didn't woke a tasklet already.
5842 */
5843 if (ctx->conn->xprt_ctx == ctx) {
5844 if (ctx->conn->xprt_done_cb)
5845 ret = ctx->conn->xprt_done_cb(ctx->conn);
5846 if (ret >= 0 && !woke && ctx->conn->mux && ctx->conn->mux->wake)
5847 ctx->conn->mux->wake(ctx->conn);
5848 return NULL;
5849 }
5850 }
Olivier Houchardf6715e72019-12-19 15:02:39 +01005851#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
5852 /* If we have early data and somebody wants to receive, let them */
5853 else if (b_data(&ctx->early_buf) && ctx->recv_wait) {
5854 ctx->recv_wait->events &= ~SUB_RETRY_RECV;
5855 tasklet_wakeup(ctx->recv_wait->tasklet);
5856 ctx->recv_wait = NULL;
5857
5858 }
5859#endif
Olivier Houchardea8dd942019-05-20 14:02:16 +02005860 return NULL;
5861}
5862
Emeric Brun46591952012-05-18 15:47:34 +02005863/* Receive up to <count> bytes from connection <conn>'s socket and store them
Willy Tarreauabf08d92014-01-14 11:31:27 +01005864 * into buffer <buf>. Only one call to recv() is performed, unless the
Emeric Brun46591952012-05-18 15:47:34 +02005865 * buffer wraps, in which case a second call may be performed. The connection's
5866 * flags are updated with whatever special event is detected (error, read0,
5867 * empty). The caller is responsible for taking care of those events and
5868 * avoiding the call if inappropriate. The function does not call the
5869 * connection's polling update function, so the caller is responsible for this.
5870 */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005871static 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 +02005872{
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005873 struct ssl_sock_ctx *ctx = xprt_ctx;
Willy Tarreaubfc4d772018-07-18 11:22:03 +02005874 ssize_t ret;
5875 size_t try, done = 0;
Emeric Brun46591952012-05-18 15:47:34 +02005876
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005877 conn_refresh_polling_flags(conn);
5878
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005879 if (!ctx)
Emeric Brun46591952012-05-18 15:47:34 +02005880 goto out_error;
5881
Olivier Houchardf6715e72019-12-19 15:02:39 +01005882#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
5883 if (b_data(&ctx->early_buf)) {
5884 try = b_contig_space(buf);
5885 if (try > b_data(&ctx->early_buf))
5886 try = b_data(&ctx->early_buf);
5887 memcpy(b_tail(buf), b_head(&ctx->early_buf), try);
5888 b_add(buf, try);
5889 b_del(&ctx->early_buf, try);
5890 if (b_data(&ctx->early_buf) == 0)
5891 b_free(&ctx->early_buf);
5892 return try;
5893 }
5894#endif
5895
Emeric Brun46591952012-05-18 15:47:34 +02005896 if (conn->flags & CO_FL_HANDSHAKE)
5897 /* a handshake was requested */
5898 return 0;
5899
Emeric Brun46591952012-05-18 15:47:34 +02005900 /* read the largest possible block. For this, we perform only one call
5901 * to recv() unless the buffer wraps and we exactly fill the first hunk,
5902 * in which case we accept to do it once again. A new attempt is made on
5903 * EINTR too.
5904 */
Willy Tarreau00b0fb92014-01-17 11:09:40 +01005905 while (count > 0) {
Olivier Houchardc2aae742017-09-22 18:26:28 +02005906
Willy Tarreau591d4452018-06-15 17:21:00 +02005907 try = b_contig_space(buf);
5908 if (!try)
5909 break;
5910
Willy Tarreauabf08d92014-01-14 11:31:27 +01005911 if (try > count)
5912 try = count;
Willy Tarreau591d4452018-06-15 17:21:00 +02005913
Olivier Houchard66ab4982019-02-26 18:37:15 +01005914 ret = SSL_read(ctx->ssl, b_tail(buf), try);
Emmanuel Hocdet510fce52019-08-05 18:04:16 +02005915
Emeric Brune1f38db2012-09-03 20:36:47 +02005916 if (conn->flags & CO_FL_ERROR) {
5917 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01005918 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02005919 }
Emeric Brun46591952012-05-18 15:47:34 +02005920 if (ret > 0) {
Olivier Houchardacd14032018-06-28 18:17:23 +02005921 b_add(buf, ret);
Emeric Brun46591952012-05-18 15:47:34 +02005922 done += ret;
Emeric Brun46591952012-05-18 15:47:34 +02005923 count -= ret;
Emeric Brun46591952012-05-18 15:47:34 +02005924 }
Emeric Brun46591952012-05-18 15:47:34 +02005925 else {
Olivier Houchard66ab4982019-02-26 18:37:15 +01005926 ret = SSL_get_error(ctx->ssl, ret);
Emeric Brun46591952012-05-18 15:47:34 +02005927 if (ret == SSL_ERROR_WANT_WRITE) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01005928 /* handshake is running, and it needs to enable write */
Emeric Brun46591952012-05-18 15:47:34 +02005929 conn->flags |= CO_FL_SSL_WAIT_HS;
Olivier Houchardea8dd942019-05-20 14:02:16 +02005930 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_SEND, &ctx->wait_event);
Willy Tarreau5db847a2019-05-09 14:13:35 +02005931#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00005932 /* Async mode can be re-enabled, because we're leaving data state.*/
5933 if (global_ssl.async)
Olivier Houchard66ab4982019-02-26 18:37:15 +01005934 SSL_set_mode(ctx->ssl, SSL_MODE_ASYNC);
Emeric Brunb5e42a82017-06-06 12:35:14 +00005935#endif
Emeric Brun46591952012-05-18 15:47:34 +02005936 break;
5937 }
5938 else if (ret == SSL_ERROR_WANT_READ) {
Olivier Houchard66ab4982019-02-26 18:37:15 +01005939 if (SSL_renegotiate_pending(ctx->ssl)) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02005940 ctx->xprt->subscribe(conn, ctx->xprt_ctx,
5941 SUB_RETRY_RECV,
5942 &ctx->wait_event);
Emeric Brun282a76a2012-11-08 18:02:56 +01005943 /* handshake is running, and it may need to re-enable read */
5944 conn->flags |= CO_FL_SSL_WAIT_HS;
Willy Tarreau5db847a2019-05-09 14:13:35 +02005945#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00005946 /* Async mode can be re-enabled, because we're leaving data state.*/
5947 if (global_ssl.async)
Olivier Houchard66ab4982019-02-26 18:37:15 +01005948 SSL_set_mode(ctx->ssl, SSL_MODE_ASYNC);
Emeric Brunb5e42a82017-06-06 12:35:14 +00005949#endif
Emeric Brun282a76a2012-11-08 18:02:56 +01005950 break;
5951 }
Emeric Brun46591952012-05-18 15:47:34 +02005952 break;
Olivier Houchardc2aae742017-09-22 18:26:28 +02005953 } else if (ret == SSL_ERROR_ZERO_RETURN)
5954 goto read0;
Christopher Faulet4ac77a92018-02-19 14:25:15 +01005955 /* For SSL_ERROR_SYSCALL, make sure to clear the error
5956 * stack before shutting down the connection for
5957 * reading. */
Olivier Houchard7e2e5052018-02-13 15:17:23 +01005958 if (ret == SSL_ERROR_SYSCALL && (!errno || errno == EAGAIN))
5959 goto clear_ssl_error;
Emeric Brun46591952012-05-18 15:47:34 +02005960 /* otherwise it's a real error */
5961 goto out_error;
5962 }
5963 }
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005964 leave:
Emeric Brun46591952012-05-18 15:47:34 +02005965 return done;
5966
Christopher Faulet4ac77a92018-02-19 14:25:15 +01005967 clear_ssl_error:
5968 /* Clear openssl global errors stack */
5969 ssl_sock_dump_errors(conn);
5970 ERR_clear_error();
Emeric Brun46591952012-05-18 15:47:34 +02005971 read0:
5972 conn_sock_read0(conn);
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005973 goto leave;
Christopher Faulet4ac77a92018-02-19 14:25:15 +01005974
Emeric Brun46591952012-05-18 15:47:34 +02005975 out_error:
Olivier Houchard7e2e5052018-02-13 15:17:23 +01005976 conn->flags |= CO_FL_ERROR;
Emeric Brun644cde02012-12-14 11:21:13 +01005977 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02005978 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01005979 ERR_clear_error();
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005980 goto leave;
Emeric Brun46591952012-05-18 15:47:34 +02005981}
5982
5983
Willy Tarreau787db9a2018-06-14 18:31:46 +02005984/* Send up to <count> pending bytes from buffer <buf> to connection <conn>'s
5985 * socket. <flags> may contain some CO_SFL_* flags to hint the system about
5986 * other pending data for example, but this flag is ignored at the moment.
Emeric Brun46591952012-05-18 15:47:34 +02005987 * Only one call to send() is performed, unless the buffer wraps, in which case
5988 * a second call may be performed. The connection's flags are updated with
5989 * whatever special event is detected (error, empty). The caller is responsible
5990 * for taking care of those events and avoiding the call if inappropriate. The
5991 * function does not call the connection's polling update function, so the caller
Willy Tarreau787db9a2018-06-14 18:31:46 +02005992 * is responsible for this. The buffer's output is not adjusted, it's up to the
5993 * caller to take care of this. It's up to the caller to update the buffer's
5994 * contents based on the return value.
Emeric Brun46591952012-05-18 15:47:34 +02005995 */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005996static 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 +02005997{
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005998 struct ssl_sock_ctx *ctx = xprt_ctx;
Willy Tarreau787db9a2018-06-14 18:31:46 +02005999 ssize_t ret;
6000 size_t try, done;
Emeric Brun46591952012-05-18 15:47:34 +02006001
6002 done = 0;
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02006003 conn_refresh_polling_flags(conn);
Emeric Brun46591952012-05-18 15:47:34 +02006004
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006005 if (!ctx)
Emeric Brun46591952012-05-18 15:47:34 +02006006 goto out_error;
6007
Olivier Houchard010941f2019-05-03 20:56:19 +02006008 if (conn->flags & (CO_FL_HANDSHAKE | CO_FL_EARLY_SSL_HS))
Emeric Brun46591952012-05-18 15:47:34 +02006009 /* a handshake was requested */
6010 return 0;
6011
6012 /* send the largest possible block. For this we perform only one call
6013 * to send() unless the buffer wraps and we exactly fill the first hunk,
6014 * in which case we accept to do it once again.
6015 */
Willy Tarreau787db9a2018-06-14 18:31:46 +02006016 while (count) {
Willy Tarreau5db847a2019-05-09 14:13:35 +02006017#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Olivier Houchardc2aae742017-09-22 18:26:28 +02006018 size_t written_data;
6019#endif
6020
Willy Tarreau787db9a2018-06-14 18:31:46 +02006021 try = b_contig_data(buf, done);
6022 if (try > count)
6023 try = count;
Willy Tarreaubfd59462013-02-21 07:46:09 +01006024
Willy Tarreau7bed9452014-02-02 02:00:24 +01006025 if (!(flags & CO_SFL_STREAMER) &&
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006026 !(ctx->xprt_st & SSL_SOCK_SEND_UNLIMITED) &&
Willy Tarreauef934602016-12-22 23:12:01 +01006027 global_ssl.max_record && try > global_ssl.max_record) {
6028 try = global_ssl.max_record;
Willy Tarreau518cedd2014-02-17 15:43:01 +01006029 }
6030 else {
6031 /* we need to keep the information about the fact that
6032 * we're not limiting the upcoming send(), because if it
6033 * fails, we'll have to retry with at least as many data.
6034 */
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006035 ctx->xprt_st |= SSL_SOCK_SEND_UNLIMITED;
Willy Tarreau518cedd2014-02-17 15:43:01 +01006036 }
Willy Tarreaubfd59462013-02-21 07:46:09 +01006037
Willy Tarreau5db847a2019-05-09 14:13:35 +02006038#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Olivier Houchard010941f2019-05-03 20:56:19 +02006039 if (!SSL_is_init_finished(ctx->ssl) && conn_is_back(conn)) {
Olivier Houchardc2aae742017-09-22 18:26:28 +02006040 unsigned int max_early;
6041
Olivier Houchard522eea72017-11-03 16:27:47 +01006042 if (objt_listener(conn->target))
Olivier Houchard66ab4982019-02-26 18:37:15 +01006043 max_early = SSL_get_max_early_data(ctx->ssl);
Olivier Houchard522eea72017-11-03 16:27:47 +01006044 else {
Olivier Houchard66ab4982019-02-26 18:37:15 +01006045 if (SSL_get0_session(ctx->ssl))
6046 max_early = SSL_SESSION_get_max_early_data(SSL_get0_session(ctx->ssl));
Olivier Houchard522eea72017-11-03 16:27:47 +01006047 else
6048 max_early = 0;
6049 }
6050
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006051 if (try + ctx->sent_early_data > max_early) {
6052 try -= (try + ctx->sent_early_data) - max_early;
Olivier Houchard522eea72017-11-03 16:27:47 +01006053 if (try <= 0) {
Olivier Houchard010941f2019-05-03 20:56:19 +02006054 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Olivier Houchard965e84e2019-06-15 20:59:30 +02006055 tasklet_wakeup(ctx->wait_event.tasklet);
Olivier Houchardc2aae742017-09-22 18:26:28 +02006056 break;
Olivier Houchard522eea72017-11-03 16:27:47 +01006057 }
Olivier Houchardc2aae742017-09-22 18:26:28 +02006058 }
Olivier Houchard66ab4982019-02-26 18:37:15 +01006059 ret = SSL_write_early_data(ctx->ssl, b_peek(buf, done), try, &written_data);
Olivier Houchardc2aae742017-09-22 18:26:28 +02006060 if (ret == 1) {
6061 ret = written_data;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006062 ctx->sent_early_data += ret;
Olivier Houchard965e84e2019-06-15 20:59:30 +02006063 if (objt_server(conn->target)) {
Olivier Houchard522eea72017-11-03 16:27:47 +01006064 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN | CO_FL_EARLY_DATA;
Olivier Houchard965e84e2019-06-15 20:59:30 +02006065 /* Initiate the handshake, now */
6066 tasklet_wakeup(ctx->wait_event.tasklet);
6067 }
Olivier Houchard522eea72017-11-03 16:27:47 +01006068
Olivier Houchardc2aae742017-09-22 18:26:28 +02006069 }
6070
6071 } else
6072#endif
Olivier Houchard66ab4982019-02-26 18:37:15 +01006073 ret = SSL_write(ctx->ssl, b_peek(buf, done), try);
Willy Tarreau518cedd2014-02-17 15:43:01 +01006074
Emeric Brune1f38db2012-09-03 20:36:47 +02006075 if (conn->flags & CO_FL_ERROR) {
6076 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01006077 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02006078 }
Emeric Brun46591952012-05-18 15:47:34 +02006079 if (ret > 0) {
Olivier Houchardf24502b2019-01-17 19:09:11 +01006080 /* A send succeeded, so we can consier ourself connected */
6081 conn->flags |= CO_FL_CONNECTED;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006082 ctx->xprt_st &= ~SSL_SOCK_SEND_UNLIMITED;
Willy Tarreau787db9a2018-06-14 18:31:46 +02006083 count -= ret;
Emeric Brun46591952012-05-18 15:47:34 +02006084 done += ret;
Emeric Brun46591952012-05-18 15:47:34 +02006085 }
6086 else {
Olivier Houchard66ab4982019-02-26 18:37:15 +01006087 ret = SSL_get_error(ctx->ssl, ret);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006088
Emeric Brun46591952012-05-18 15:47:34 +02006089 if (ret == SSL_ERROR_WANT_WRITE) {
Olivier Houchard66ab4982019-02-26 18:37:15 +01006090 if (SSL_renegotiate_pending(ctx->ssl)) {
Emeric Brun282a76a2012-11-08 18:02:56 +01006091 /* handshake is running, and it may need to re-enable write */
6092 conn->flags |= CO_FL_SSL_WAIT_HS;
Olivier Houchardea8dd942019-05-20 14:02:16 +02006093 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_SEND, &ctx->wait_event);
Willy Tarreau5db847a2019-05-09 14:13:35 +02006094#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00006095 /* Async mode can be re-enabled, because we're leaving data state.*/
6096 if (global_ssl.async)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006097 SSL_set_mode(ctx->ssl, SSL_MODE_ASYNC);
Emeric Brunb5e42a82017-06-06 12:35:14 +00006098#endif
Emeric Brun282a76a2012-11-08 18:02:56 +01006099 break;
6100 }
Olivier Houchardea8dd942019-05-20 14:02:16 +02006101
Emeric Brun46591952012-05-18 15:47:34 +02006102 break;
6103 }
6104 else if (ret == SSL_ERROR_WANT_READ) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01006105 /* handshake is running, and it needs to enable read */
Emeric Brun46591952012-05-18 15:47:34 +02006106 conn->flags |= CO_FL_SSL_WAIT_HS;
Olivier Houchardea8dd942019-05-20 14:02:16 +02006107 ctx->xprt->subscribe(conn, ctx->xprt_ctx,
6108 SUB_RETRY_RECV,
6109 &ctx->wait_event);
Willy Tarreau5db847a2019-05-09 14:13:35 +02006110#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00006111 /* Async mode can be re-enabled, because we're leaving data state.*/
6112 if (global_ssl.async)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006113 SSL_set_mode(ctx->ssl, SSL_MODE_ASYNC);
Emeric Brunb5e42a82017-06-06 12:35:14 +00006114#endif
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006115 break;
6116 }
Emeric Brun46591952012-05-18 15:47:34 +02006117 goto out_error;
6118 }
6119 }
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02006120 leave:
Emeric Brun46591952012-05-18 15:47:34 +02006121 return done;
6122
6123 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01006124 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02006125 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01006126 ERR_clear_error();
6127
Emeric Brun46591952012-05-18 15:47:34 +02006128 conn->flags |= CO_FL_ERROR;
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02006129 goto leave;
Emeric Brun46591952012-05-18 15:47:34 +02006130}
6131
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006132static void ssl_sock_close(struct connection *conn, void *xprt_ctx) {
Emeric Brun46591952012-05-18 15:47:34 +02006133
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006134 struct ssl_sock_ctx *ctx = xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006135
Olivier Houchardea8dd942019-05-20 14:02:16 +02006136
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006137 if (ctx) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02006138 if (ctx->wait_event.events != 0)
6139 ctx->xprt->unsubscribe(ctx->conn, ctx->xprt_ctx,
6140 ctx->wait_event.events,
6141 &ctx->wait_event);
6142 if (ctx->send_wait) {
6143 ctx->send_wait->events &= ~SUB_RETRY_SEND;
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02006144 tasklet_wakeup(ctx->send_wait->tasklet);
Olivier Houchardea8dd942019-05-20 14:02:16 +02006145 }
6146 if (ctx->recv_wait) {
6147 ctx->recv_wait->events &= ~SUB_RETRY_RECV;
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02006148 tasklet_wakeup(ctx->recv_wait->tasklet);
Olivier Houchardea8dd942019-05-20 14:02:16 +02006149 }
Olivier Houchard692c1d02019-05-23 18:41:47 +02006150 if (ctx->xprt->close)
6151 ctx->xprt->close(conn, ctx->xprt_ctx);
Willy Tarreau5db847a2019-05-09 14:13:35 +02006152#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brun3854e012017-05-17 20:42:48 +02006153 if (global_ssl.async) {
6154 OSSL_ASYNC_FD all_fd[32], afd;
6155 size_t num_all_fds = 0;
6156 int i;
6157
Olivier Houchard66ab4982019-02-26 18:37:15 +01006158 SSL_get_all_async_fds(ctx->ssl, NULL, &num_all_fds);
Emeric Brun3854e012017-05-17 20:42:48 +02006159 if (num_all_fds > 32) {
6160 send_log(NULL, LOG_EMERG, "haproxy: openssl returns too many async fds. It seems a bug. Process may crash\n");
6161 return;
6162 }
6163
Olivier Houchard66ab4982019-02-26 18:37:15 +01006164 SSL_get_all_async_fds(ctx->ssl, all_fd, &num_all_fds);
Emeric Brun3854e012017-05-17 20:42:48 +02006165
6166 /* If an async job is pending, we must try to
6167 to catch the end using polling before calling
6168 SSL_free */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006169 if (num_all_fds && SSL_waiting_for_async(ctx->ssl)) {
Emeric Brun3854e012017-05-17 20:42:48 +02006170 for (i=0 ; i < num_all_fds ; i++) {
6171 /* switch on an handler designed to
6172 * handle the SSL_free
6173 */
6174 afd = all_fd[i];
6175 fdtab[afd].iocb = ssl_async_fd_free;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006176 fdtab[afd].owner = ctx->ssl;
Emeric Brun3854e012017-05-17 20:42:48 +02006177 fd_want_recv(afd);
Emeric Brunce9e01c2017-05-31 10:02:53 +00006178 /* To ensure that the fd cache won't be used
6179 * and we'll catch a real RD event.
6180 */
6181 fd_cant_recv(afd);
Emeric Brun3854e012017-05-17 20:42:48 +02006182 }
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02006183 tasklet_free(ctx->wait_event.tasklet);
Olivier Houchard66ab4982019-02-26 18:37:15 +01006184 pool_free(ssl_sock_ctx_pool, ctx);
Olivier Houchard2be5a4c2019-03-08 18:54:43 +01006185 _HA_ATOMIC_ADD(&jobs, 1);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006186 return;
6187 }
Emeric Brun3854e012017-05-17 20:42:48 +02006188 /* Else we can remove the fds from the fdtab
6189 * and call SSL_free.
6190 * note: we do a fd_remove and not a delete
6191 * because the fd is owned by the engine.
6192 * the engine is responsible to close
6193 */
6194 for (i=0 ; i < num_all_fds ; i++)
6195 fd_remove(all_fd[i]);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006196 }
6197#endif
Olivier Houchard66ab4982019-02-26 18:37:15 +01006198 SSL_free(ctx->ssl);
Olivier Houchardf6715e72019-12-19 15:02:39 +01006199 b_free(&ctx->early_buf);
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02006200 tasklet_free(ctx->wait_event.tasklet);
Olivier Houchard66ab4982019-02-26 18:37:15 +01006201 pool_free(ssl_sock_ctx_pool, ctx);
Olivier Houchard2be5a4c2019-03-08 18:54:43 +01006202 _HA_ATOMIC_SUB(&sslconns, 1);
Emeric Brun46591952012-05-18 15:47:34 +02006203 }
Emeric Brun46591952012-05-18 15:47:34 +02006204}
6205
6206/* This function tries to perform a clean shutdown on an SSL connection, and in
6207 * any case, flags the connection as reusable if no handshake was in progress.
6208 */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006209static void ssl_sock_shutw(struct connection *conn, void *xprt_ctx, int clean)
Emeric Brun46591952012-05-18 15:47:34 +02006210{
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006211 struct ssl_sock_ctx *ctx = xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006212
Emeric Brun46591952012-05-18 15:47:34 +02006213 if (conn->flags & CO_FL_HANDSHAKE)
6214 return;
Emmanuel Hocdet405ff312017-01-08 14:07:39 +01006215 if (!clean)
6216 /* don't sent notify on SSL_shutdown */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006217 SSL_set_quiet_shutdown(ctx->ssl, 1);
Emeric Brun46591952012-05-18 15:47:34 +02006218 /* no handshake was in progress, try a clean ssl shutdown */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006219 if (SSL_shutdown(ctx->ssl) <= 0) {
Emeric Brun644cde02012-12-14 11:21:13 +01006220 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02006221 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01006222 ERR_clear_error();
6223 }
Emeric Brun46591952012-05-18 15:47:34 +02006224}
6225
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01006226/* used for ppv2 pkey alog (can be used for logging) */
Willy Tarreau83061a82018-07-13 11:56:34 +02006227int ssl_sock_get_pkey_algo(struct connection *conn, struct buffer *out)
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01006228{
Christopher Faulet4517b0c2019-09-10 10:12:03 +02006229 struct ssl_sock_ctx *ctx;
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01006230 struct pkey_info *pkinfo;
6231 int bits = 0;
6232 int sig = TLSEXT_signature_anonymous;
6233 int len = -1;
6234
6235 if (!ssl_sock_is_ssl(conn))
6236 return 0;
Christopher Faulet4517b0c2019-09-10 10:12:03 +02006237 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006238 pkinfo = SSL_CTX_get_ex_data(SSL_get_SSL_CTX(ctx->ssl), ssl_pkey_info_index);
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01006239 if (pkinfo) {
6240 sig = pkinfo->sig;
6241 bits = pkinfo->bits;
6242 } else {
6243 /* multicert and generated cert have no pkey info */
6244 X509 *crt;
6245 EVP_PKEY *pkey;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006246 crt = SSL_get_certificate(ctx->ssl);
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01006247 if (!crt)
6248 return 0;
6249 pkey = X509_get_pubkey(crt);
6250 if (pkey) {
6251 bits = EVP_PKEY_bits(pkey);
6252 switch(EVP_PKEY_base_id(pkey)) {
6253 case EVP_PKEY_RSA:
6254 sig = TLSEXT_signature_rsa;
6255 break;
6256 case EVP_PKEY_EC:
6257 sig = TLSEXT_signature_ecdsa;
6258 break;
6259 case EVP_PKEY_DSA:
6260 sig = TLSEXT_signature_dsa;
6261 break;
6262 }
6263 EVP_PKEY_free(pkey);
6264 }
6265 }
6266
6267 switch(sig) {
6268 case TLSEXT_signature_rsa:
6269 len = chunk_printf(out, "RSA%d", bits);
6270 break;
6271 case TLSEXT_signature_ecdsa:
6272 len = chunk_printf(out, "EC%d", bits);
6273 break;
6274 case TLSEXT_signature_dsa:
6275 len = chunk_printf(out, "DSA%d", bits);
6276 break;
6277 default:
6278 return 0;
6279 }
6280 if (len < 0)
6281 return 0;
6282 return 1;
6283}
6284
Emmanuel Hocdet283e0042017-11-02 14:05:23 +01006285/* used for ppv2 cert signature (can be used for logging) */
6286const char *ssl_sock_get_cert_sig(struct connection *conn)
6287{
Christopher Faulet4517b0c2019-09-10 10:12:03 +02006288 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006289
Emmanuel Hocdet283e0042017-11-02 14:05:23 +01006290 __OPENSSL_110_CONST__ ASN1_OBJECT *algorithm;
6291 X509 *crt;
6292
6293 if (!ssl_sock_is_ssl(conn))
6294 return NULL;
Christopher Faulet4517b0c2019-09-10 10:12:03 +02006295 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006296 crt = SSL_get_certificate(ctx->ssl);
Emmanuel Hocdet283e0042017-11-02 14:05:23 +01006297 if (!crt)
6298 return NULL;
6299 X509_ALGOR_get0(&algorithm, NULL, NULL, X509_get0_tbs_sigalg(crt));
6300 return OBJ_nid2sn(OBJ_obj2nid(algorithm));
6301}
6302
Emmanuel Hocdet253c3b72018-02-01 18:29:59 +01006303/* used for ppv2 authority */
6304const char *ssl_sock_get_sni(struct connection *conn)
6305{
6306#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Christopher Faulet4517b0c2019-09-10 10:12:03 +02006307 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006308
Emmanuel Hocdet253c3b72018-02-01 18:29:59 +01006309 if (!ssl_sock_is_ssl(conn))
6310 return NULL;
Christopher Faulet4517b0c2019-09-10 10:12:03 +02006311 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006312 return SSL_get_servername(ctx->ssl, TLSEXT_NAMETYPE_host_name);
Emmanuel Hocdet253c3b72018-02-01 18:29:59 +01006313#else
Olivier Houchard66ab4982019-02-26 18:37:15 +01006314 return NULL;
Emmanuel Hocdet253c3b72018-02-01 18:29:59 +01006315#endif
6316}
6317
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02006318/* used for logging/ppv2, may be changed for a sample fetch later */
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02006319const char *ssl_sock_get_cipher_name(struct connection *conn)
6320{
Christopher Faulet4517b0c2019-09-10 10:12:03 +02006321 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006322
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02006323 if (!ssl_sock_is_ssl(conn))
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02006324 return NULL;
Christopher Faulet4517b0c2019-09-10 10:12:03 +02006325 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006326 return SSL_get_cipher_name(ctx->ssl);
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02006327}
6328
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02006329/* used for logging/ppv2, may be changed for a sample fetch later */
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02006330const char *ssl_sock_get_proto_version(struct connection *conn)
6331{
Christopher Faulet4517b0c2019-09-10 10:12:03 +02006332 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006333
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02006334 if (!ssl_sock_is_ssl(conn))
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02006335 return NULL;
Christopher Faulet4517b0c2019-09-10 10:12:03 +02006336 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006337 return SSL_get_version(ctx->ssl);
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02006338}
6339
Willy Tarreau8d598402012-10-22 17:58:39 +02006340/* Extract a serial from a cert, and copy it to a chunk.
6341 * Returns 1 if serial is found and copied, 0 if no serial found and
6342 * -1 if output is not large enough.
6343 */
6344static int
Willy Tarreau83061a82018-07-13 11:56:34 +02006345ssl_sock_get_serial(X509 *crt, struct buffer *out)
Willy Tarreau8d598402012-10-22 17:58:39 +02006346{
6347 ASN1_INTEGER *serial;
6348
6349 serial = X509_get_serialNumber(crt);
6350 if (!serial)
6351 return 0;
6352
6353 if (out->size < serial->length)
6354 return -1;
6355
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006356 memcpy(out->area, serial->data, serial->length);
6357 out->data = serial->length;
Willy Tarreau8d598402012-10-22 17:58:39 +02006358 return 1;
6359}
6360
Emeric Brun43e79582014-10-29 19:03:26 +01006361/* Extract a cert to der, and copy it to a chunk.
Joseph Herlant017b3da2018-11-15 09:07:59 -08006362 * Returns 1 if the cert is found and copied, 0 on der conversion failure
6363 * and -1 if the output is not large enough.
Emeric Brun43e79582014-10-29 19:03:26 +01006364 */
6365static int
Willy Tarreau83061a82018-07-13 11:56:34 +02006366ssl_sock_crt2der(X509 *crt, struct buffer *out)
Emeric Brun43e79582014-10-29 19:03:26 +01006367{
6368 int len;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006369 unsigned char *p = (unsigned char *) out->area;;
Emeric Brun43e79582014-10-29 19:03:26 +01006370
6371 len =i2d_X509(crt, NULL);
6372 if (len <= 0)
6373 return 1;
6374
6375 if (out->size < len)
6376 return -1;
6377
6378 i2d_X509(crt,&p);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006379 out->data = len;
Emeric Brun43e79582014-10-29 19:03:26 +01006380 return 1;
6381}
6382
Emeric Brunce5ad802012-10-22 14:11:22 +02006383
Willy Tarreau83061a82018-07-13 11:56:34 +02006384/* Copy Date in ASN1_UTCTIME format in struct buffer out.
Emeric Brunce5ad802012-10-22 14:11:22 +02006385 * Returns 1 if serial is found and copied, 0 if no valid time found
6386 * and -1 if output is not large enough.
6387 */
6388static int
Willy Tarreau83061a82018-07-13 11:56:34 +02006389ssl_sock_get_time(ASN1_TIME *tm, struct buffer *out)
Emeric Brunce5ad802012-10-22 14:11:22 +02006390{
6391 if (tm->type == V_ASN1_GENERALIZEDTIME) {
6392 ASN1_GENERALIZEDTIME *gentm = (ASN1_GENERALIZEDTIME *)tm;
6393
6394 if (gentm->length < 12)
6395 return 0;
6396 if (gentm->data[0] != 0x32 || gentm->data[1] != 0x30)
6397 return 0;
6398 if (out->size < gentm->length-2)
6399 return -1;
6400
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006401 memcpy(out->area, gentm->data+2, gentm->length-2);
6402 out->data = gentm->length-2;
Emeric Brunce5ad802012-10-22 14:11:22 +02006403 return 1;
6404 }
6405 else if (tm->type == V_ASN1_UTCTIME) {
6406 ASN1_UTCTIME *utctm = (ASN1_UTCTIME *)tm;
6407
6408 if (utctm->length < 10)
6409 return 0;
6410 if (utctm->data[0] >= 0x35)
6411 return 0;
6412 if (out->size < utctm->length)
6413 return -1;
6414
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006415 memcpy(out->area, utctm->data, utctm->length);
6416 out->data = utctm->length;
Emeric Brunce5ad802012-10-22 14:11:22 +02006417 return 1;
6418 }
6419
6420 return 0;
6421}
6422
Emeric Brun87855892012-10-17 17:39:35 +02006423/* Extract an entry from a X509_NAME and copy its value to an output chunk.
6424 * Returns 1 if entry found, 0 if entry not found, or -1 if output not large enough.
6425 */
6426static int
Willy Tarreau83061a82018-07-13 11:56:34 +02006427ssl_sock_get_dn_entry(X509_NAME *a, const struct buffer *entry, int pos,
6428 struct buffer *out)
Emeric Brun87855892012-10-17 17:39:35 +02006429{
6430 X509_NAME_ENTRY *ne;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006431 ASN1_OBJECT *obj;
6432 ASN1_STRING *data;
6433 const unsigned char *data_ptr;
6434 int data_len;
Emeric Brun87855892012-10-17 17:39:35 +02006435 int i, j, n;
6436 int cur = 0;
6437 const char *s;
6438 char tmp[128];
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006439 int name_count;
6440
6441 name_count = X509_NAME_entry_count(a);
Emeric Brun87855892012-10-17 17:39:35 +02006442
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006443 out->data = 0;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006444 for (i = 0; i < name_count; i++) {
Emeric Brun87855892012-10-17 17:39:35 +02006445 if (pos < 0)
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006446 j = (name_count-1) - i;
Emeric Brun87855892012-10-17 17:39:35 +02006447 else
6448 j = i;
6449
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006450 ne = X509_NAME_get_entry(a, j);
6451 obj = X509_NAME_ENTRY_get_object(ne);
6452 data = X509_NAME_ENTRY_get_data(ne);
6453 data_ptr = ASN1_STRING_get0_data(data);
6454 data_len = ASN1_STRING_length(data);
6455 n = OBJ_obj2nid(obj);
Emeric Brun87855892012-10-17 17:39:35 +02006456 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006457 i2t_ASN1_OBJECT(tmp, sizeof(tmp), obj);
Emeric Brun87855892012-10-17 17:39:35 +02006458 s = tmp;
6459 }
6460
6461 if (chunk_strcasecmp(entry, s) != 0)
6462 continue;
6463
6464 if (pos < 0)
6465 cur--;
6466 else
6467 cur++;
6468
6469 if (cur != pos)
6470 continue;
6471
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006472 if (data_len > out->size)
Emeric Brun87855892012-10-17 17:39:35 +02006473 return -1;
6474
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006475 memcpy(out->area, data_ptr, data_len);
6476 out->data = data_len;
Emeric Brun87855892012-10-17 17:39:35 +02006477 return 1;
6478 }
6479
6480 return 0;
6481
6482}
6483
6484/* Extract and format full DN from a X509_NAME and copy result into a chunk
6485 * Returns 1 if dn entries exits, 0 if no dn entry found or -1 if output is not large enough.
6486 */
6487static int
Willy Tarreau83061a82018-07-13 11:56:34 +02006488ssl_sock_get_dn_oneline(X509_NAME *a, struct buffer *out)
Emeric Brun87855892012-10-17 17:39:35 +02006489{
6490 X509_NAME_ENTRY *ne;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006491 ASN1_OBJECT *obj;
6492 ASN1_STRING *data;
6493 const unsigned char *data_ptr;
6494 int data_len;
Emeric Brun87855892012-10-17 17:39:35 +02006495 int i, n, ln;
6496 int l = 0;
6497 const char *s;
6498 char *p;
6499 char tmp[128];
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006500 int name_count;
6501
6502
6503 name_count = X509_NAME_entry_count(a);
Emeric Brun87855892012-10-17 17:39:35 +02006504
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006505 out->data = 0;
6506 p = out->area;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006507 for (i = 0; i < name_count; i++) {
6508 ne = X509_NAME_get_entry(a, i);
6509 obj = X509_NAME_ENTRY_get_object(ne);
6510 data = X509_NAME_ENTRY_get_data(ne);
6511 data_ptr = ASN1_STRING_get0_data(data);
6512 data_len = ASN1_STRING_length(data);
6513 n = OBJ_obj2nid(obj);
Emeric Brun87855892012-10-17 17:39:35 +02006514 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006515 i2t_ASN1_OBJECT(tmp, sizeof(tmp), obj);
Emeric Brun87855892012-10-17 17:39:35 +02006516 s = tmp;
6517 }
6518 ln = strlen(s);
6519
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006520 l += 1 + ln + 1 + data_len;
Emeric Brun87855892012-10-17 17:39:35 +02006521 if (l > out->size)
6522 return -1;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006523 out->data = l;
Emeric Brun87855892012-10-17 17:39:35 +02006524
6525 *(p++)='/';
6526 memcpy(p, s, ln);
6527 p += ln;
6528 *(p++)='=';
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006529 memcpy(p, data_ptr, data_len);
6530 p += data_len;
Emeric Brun87855892012-10-17 17:39:35 +02006531 }
6532
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006533 if (!out->data)
Emeric Brun87855892012-10-17 17:39:35 +02006534 return 0;
6535
6536 return 1;
6537}
6538
Olivier Houchardab28a322018-12-21 19:45:40 +01006539void ssl_sock_set_alpn(struct connection *conn, const unsigned char *alpn, int len)
6540{
6541#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Christopher Faulet4517b0c2019-09-10 10:12:03 +02006542 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006543
Olivier Houchardaa2ecea2019-06-28 14:10:33 +02006544 if (!ssl_sock_is_ssl(conn))
6545 return;
Christopher Faulet4517b0c2019-09-10 10:12:03 +02006546 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006547 SSL_set_alpn_protos(ctx->ssl, alpn, len);
Olivier Houchardab28a322018-12-21 19:45:40 +01006548#endif
6549}
6550
Willy Tarreau119a4082016-12-22 21:58:38 +01006551/* Sets advertised SNI for outgoing connections. Please set <hostname> to NULL
6552 * to disable SNI.
6553 */
Willy Tarreau63076412015-07-10 11:33:32 +02006554void ssl_sock_set_servername(struct connection *conn, const char *hostname)
6555{
6556#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Christopher Faulet4517b0c2019-09-10 10:12:03 +02006557 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006558
Willy Tarreau119a4082016-12-22 21:58:38 +01006559 char *prev_name;
6560
Willy Tarreau63076412015-07-10 11:33:32 +02006561 if (!ssl_sock_is_ssl(conn))
6562 return;
Christopher Faulet4517b0c2019-09-10 10:12:03 +02006563 ctx = conn->xprt_ctx;
Willy Tarreau63076412015-07-10 11:33:32 +02006564
Willy Tarreau119a4082016-12-22 21:58:38 +01006565 /* if the SNI changes, we must destroy the reusable context so that a
6566 * new connection will present a new SNI. As an optimization we could
6567 * later imagine having a small cache of ssl_ctx to hold a few SNI per
6568 * server.
6569 */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006570 prev_name = (char *)SSL_get_servername(ctx->ssl, TLSEXT_NAMETYPE_host_name);
Willy Tarreau119a4082016-12-22 21:58:38 +01006571 if ((!prev_name && hostname) ||
6572 (prev_name && (!hostname || strcmp(hostname, prev_name) != 0)))
Olivier Houchard66ab4982019-02-26 18:37:15 +01006573 SSL_set_session(ctx->ssl, NULL);
Willy Tarreau119a4082016-12-22 21:58:38 +01006574
Olivier Houchard66ab4982019-02-26 18:37:15 +01006575 SSL_set_tlsext_host_name(ctx->ssl, hostname);
Willy Tarreau63076412015-07-10 11:33:32 +02006576#endif
6577}
6578
Emeric Brun0abf8362014-06-24 18:26:41 +02006579/* Extract peer certificate's common name into the chunk dest
6580 * Returns
6581 * the len of the extracted common name
6582 * or 0 if no CN found in DN
6583 * or -1 on error case (i.e. no peer certificate)
6584 */
Willy Tarreau83061a82018-07-13 11:56:34 +02006585int ssl_sock_get_remote_common_name(struct connection *conn,
6586 struct buffer *dest)
David Safb76832014-05-08 23:42:08 -04006587{
Christopher Faulet4517b0c2019-09-10 10:12:03 +02006588 struct ssl_sock_ctx *ctx;
David Safb76832014-05-08 23:42:08 -04006589 X509 *crt = NULL;
6590 X509_NAME *name;
David Safb76832014-05-08 23:42:08 -04006591 const char find_cn[] = "CN";
Willy Tarreau83061a82018-07-13 11:56:34 +02006592 const struct buffer find_cn_chunk = {
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006593 .area = (char *)&find_cn,
6594 .data = sizeof(find_cn)-1
David Safb76832014-05-08 23:42:08 -04006595 };
Emeric Brun0abf8362014-06-24 18:26:41 +02006596 int result = -1;
David Safb76832014-05-08 23:42:08 -04006597
6598 if (!ssl_sock_is_ssl(conn))
Emeric Brun0abf8362014-06-24 18:26:41 +02006599 goto out;
Christopher Faulet4517b0c2019-09-10 10:12:03 +02006600 ctx = conn->xprt_ctx;
David Safb76832014-05-08 23:42:08 -04006601
6602 /* SSL_get_peer_certificate, it increase X509 * ref count */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006603 crt = SSL_get_peer_certificate(ctx->ssl);
David Safb76832014-05-08 23:42:08 -04006604 if (!crt)
6605 goto out;
6606
6607 name = X509_get_subject_name(crt);
6608 if (!name)
6609 goto out;
David Safb76832014-05-08 23:42:08 -04006610
Emeric Brun0abf8362014-06-24 18:26:41 +02006611 result = ssl_sock_get_dn_entry(name, &find_cn_chunk, 1, dest);
6612out:
David Safb76832014-05-08 23:42:08 -04006613 if (crt)
6614 X509_free(crt);
6615
6616 return result;
6617}
6618
Dave McCowan328fb582014-07-30 10:39:13 -04006619/* returns 1 if client passed a certificate for this session, 0 if not */
6620int ssl_sock_get_cert_used_sess(struct connection *conn)
6621{
Christopher Faulet4517b0c2019-09-10 10:12:03 +02006622 struct ssl_sock_ctx *ctx;
Dave McCowan328fb582014-07-30 10:39:13 -04006623 X509 *crt = NULL;
6624
6625 if (!ssl_sock_is_ssl(conn))
6626 return 0;
Christopher Faulet4517b0c2019-09-10 10:12:03 +02006627 ctx = conn->xprt_ctx;
Dave McCowan328fb582014-07-30 10:39:13 -04006628
6629 /* SSL_get_peer_certificate, it increase X509 * ref count */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006630 crt = SSL_get_peer_certificate(ctx->ssl);
Dave McCowan328fb582014-07-30 10:39:13 -04006631 if (!crt)
6632 return 0;
6633
6634 X509_free(crt);
6635 return 1;
6636}
6637
6638/* returns 1 if client passed a certificate for this connection, 0 if not */
6639int ssl_sock_get_cert_used_conn(struct connection *conn)
David Safb76832014-05-08 23:42:08 -04006640{
Christopher Faulet4517b0c2019-09-10 10:12:03 +02006641 struct ssl_sock_ctx *ctx;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006642
David Safb76832014-05-08 23:42:08 -04006643 if (!ssl_sock_is_ssl(conn))
6644 return 0;
Christopher Faulet4517b0c2019-09-10 10:12:03 +02006645 ctx = conn->xprt_ctx;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006646 return SSL_SOCK_ST_FL_VERIFY_DONE & ctx->xprt_st ? 1 : 0;
David Safb76832014-05-08 23:42:08 -04006647}
6648
6649/* returns result from SSL verify */
6650unsigned int ssl_sock_get_verify_result(struct connection *conn)
6651{
Christopher Faulet4517b0c2019-09-10 10:12:03 +02006652 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006653
David Safb76832014-05-08 23:42:08 -04006654 if (!ssl_sock_is_ssl(conn))
6655 return (unsigned int)X509_V_ERR_APPLICATION_VERIFICATION;
Christopher Faulet4517b0c2019-09-10 10:12:03 +02006656 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006657 return (unsigned int)SSL_get_verify_result(ctx->ssl);
David Safb76832014-05-08 23:42:08 -04006658}
6659
Willy Tarreau8743f7e2016-12-04 18:44:29 +01006660/* Returns the application layer protocol name in <str> and <len> when known.
6661 * Zero is returned if the protocol name was not found, otherwise non-zero is
6662 * returned. The string is allocated in the SSL context and doesn't have to be
6663 * freed by the caller. NPN is also checked if available since older versions
6664 * of openssl (1.0.1) which are more common in field only support this one.
6665 */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006666static int ssl_sock_get_alpn(const struct connection *conn, void *xprt_ctx, const char **str, int *len)
Willy Tarreau8743f7e2016-12-04 18:44:29 +01006667{
Olivier Houchard66ab4982019-02-26 18:37:15 +01006668#if defined(TLSEXT_TYPE_application_layer_protocol_negotiation) || \
6669 defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006670 struct ssl_sock_ctx *ctx = xprt_ctx;
6671 if (!ctx)
Willy Tarreau8743f7e2016-12-04 18:44:29 +01006672 return 0;
6673
6674 *str = NULL;
6675
6676#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Olivier Houchard66ab4982019-02-26 18:37:15 +01006677 SSL_get0_alpn_selected(ctx->ssl, (const unsigned char **)str, (unsigned *)len);
Willy Tarreau8743f7e2016-12-04 18:44:29 +01006678 if (*str)
6679 return 1;
6680#endif
Bernard Spil13c53f82018-02-15 13:34:58 +01006681#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006682 SSL_get0_next_proto_negotiated(ctx->ssl, (const unsigned char **)str, (unsigned *)len);
Willy Tarreau8743f7e2016-12-04 18:44:29 +01006683 if (*str)
6684 return 1;
6685#endif
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006686#endif
Willy Tarreau8743f7e2016-12-04 18:44:29 +01006687 return 0;
6688}
6689
Willy Tarreau7875d092012-09-10 08:20:03 +02006690/***** Below are some sample fetching functions for ACL/patterns *****/
6691
Olivier Houchardccaa7de2017-10-02 11:51:03 +02006692static int
6693smp_fetch_ssl_fc_has_early(const struct arg *args, struct sample *smp, const char *kw, void *private)
6694{
6695 struct connection *conn;
6696
6697 conn = objt_conn(smp->sess->origin);
6698 if (!conn || conn->xprt != &ssl_sock)
6699 return 0;
6700
6701 smp->flags = 0;
6702 smp->data.type = SMP_T_BOOL;
Emmanuel Hocdetbb8643c2019-08-07 14:44:49 +02006703#ifdef OPENSSL_IS_BORINGSSL
6704 {
6705 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
6706 smp->data.u.sint = (SSL_in_early_data(ctx->ssl) &&
6707 SSL_early_data_accepted(ctx->ssl));
6708 }
6709#else
Olivier Houchard25ae45a2017-11-29 19:51:19 +01006710 smp->data.u.sint = ((conn->flags & CO_FL_EARLY_DATA) &&
Olivier Houchard629693f2020-01-23 14:57:36 +01006711 (conn->flags & (CO_FL_EARLY_SSL_HS | CO_FL_SSL_WAIT_HS))) ? 1 : 0;
Emmanuel Hocdetbb8643c2019-08-07 14:44:49 +02006712#endif
Olivier Houchardccaa7de2017-10-02 11:51:03 +02006713 return 1;
6714}
6715
Emeric Brune64aef12012-09-21 13:15:06 +02006716/* boolean, returns true if client cert was present */
6717static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006718smp_fetch_ssl_fc_has_crt(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brune64aef12012-09-21 13:15:06 +02006719{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006720 struct connection *conn;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006721 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006722
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006723 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006724 if (!conn || conn->xprt != &ssl_sock)
Emeric Brune64aef12012-09-21 13:15:06 +02006725 return 0;
6726
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006727 ctx = conn->xprt_ctx;
6728
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006729 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brune64aef12012-09-21 13:15:06 +02006730 smp->flags |= SMP_F_MAY_CHANGE;
6731 return 0;
6732 }
6733
6734 smp->flags = 0;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006735 smp->data.type = SMP_T_BOOL;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006736 smp->data.u.sint = SSL_SOCK_ST_FL_VERIFY_DONE & ctx->xprt_st ? 1 : 0;
Emeric Brune64aef12012-09-21 13:15:06 +02006737
6738 return 1;
6739}
6740
Emeric Brun43e79582014-10-29 19:03:26 +01006741/* binary, returns a certificate in a binary chunk (der/raw).
6742 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6743 * should be use.
6744 */
6745static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006746smp_fetch_ssl_x_der(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun43e79582014-10-29 19:03:26 +01006747{
6748 int cert_peer = (kw[4] == 'c') ? 1 : 0;
6749 X509 *crt = NULL;
6750 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02006751 struct buffer *smp_trash;
Emeric Brun43e79582014-10-29 19:03:26 +01006752 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006753 struct ssl_sock_ctx *ctx;
Emeric Brun43e79582014-10-29 19:03:26 +01006754
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006755 conn = objt_conn(smp->sess->origin);
Emeric Brun43e79582014-10-29 19:03:26 +01006756 if (!conn || conn->xprt != &ssl_sock)
6757 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006758 ctx = conn->xprt_ctx;
Emeric Brun43e79582014-10-29 19:03:26 +01006759
6760 if (!(conn->flags & CO_FL_CONNECTED)) {
6761 smp->flags |= SMP_F_MAY_CHANGE;
6762 return 0;
6763 }
6764
6765 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006766 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brun43e79582014-10-29 19:03:26 +01006767 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01006768 crt = SSL_get_certificate(ctx->ssl);
Emeric Brun43e79582014-10-29 19:03:26 +01006769
6770 if (!crt)
6771 goto out;
6772
6773 smp_trash = get_trash_chunk();
6774 if (ssl_sock_crt2der(crt, smp_trash) <= 0)
6775 goto out;
6776
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006777 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006778 smp->data.type = SMP_T_BIN;
Emeric Brun43e79582014-10-29 19:03:26 +01006779 ret = 1;
6780out:
6781 /* SSL_get_peer_certificate, it increase X509 * ref count */
6782 if (cert_peer && crt)
6783 X509_free(crt);
6784 return ret;
6785}
6786
Emeric Brunba841a12014-04-30 17:05:08 +02006787/* binary, returns serial of certificate in a binary chunk.
6788 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6789 * should be use.
6790 */
Willy Tarreau8d598402012-10-22 17:58:39 +02006791static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006792smp_fetch_ssl_x_serial(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau8d598402012-10-22 17:58:39 +02006793{
Emeric Brunba841a12014-04-30 17:05:08 +02006794 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Willy Tarreau8d598402012-10-22 17:58:39 +02006795 X509 *crt = NULL;
6796 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02006797 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006798 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006799 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006800
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006801 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006802 if (!conn || conn->xprt != &ssl_sock)
Willy Tarreau8d598402012-10-22 17:58:39 +02006803 return 0;
6804
Olivier Houchard66ab4982019-02-26 18:37:15 +01006805 ctx = conn->xprt_ctx;
6806
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006807 if (!(conn->flags & CO_FL_CONNECTED)) {
Willy Tarreau8d598402012-10-22 17:58:39 +02006808 smp->flags |= SMP_F_MAY_CHANGE;
6809 return 0;
6810 }
6811
Emeric Brunba841a12014-04-30 17:05:08 +02006812 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006813 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02006814 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01006815 crt = SSL_get_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02006816
Willy Tarreau8d598402012-10-22 17:58:39 +02006817 if (!crt)
6818 goto out;
6819
Willy Tarreau47ca5452012-12-23 20:22:19 +01006820 smp_trash = get_trash_chunk();
Willy Tarreau8d598402012-10-22 17:58:39 +02006821 if (ssl_sock_get_serial(crt, smp_trash) <= 0)
6822 goto out;
6823
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006824 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006825 smp->data.type = SMP_T_BIN;
Willy Tarreau8d598402012-10-22 17:58:39 +02006826 ret = 1;
6827out:
Emeric Brunba841a12014-04-30 17:05:08 +02006828 /* SSL_get_peer_certificate, it increase X509 * ref count */
6829 if (cert_peer && crt)
Willy Tarreau8d598402012-10-22 17:58:39 +02006830 X509_free(crt);
6831 return ret;
6832}
Emeric Brune64aef12012-09-21 13:15:06 +02006833
Emeric Brunba841a12014-04-30 17:05:08 +02006834/* binary, returns the client certificate's SHA-1 fingerprint (SHA-1 hash of DER-encoded certificate) in a binary chunk.
6835 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6836 * should be use.
6837 */
James Votha051b4a2013-05-14 20:37:59 +02006838static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006839smp_fetch_ssl_x_sha1(const struct arg *args, struct sample *smp, const char *kw, void *private)
James Votha051b4a2013-05-14 20:37:59 +02006840{
Emeric Brunba841a12014-04-30 17:05:08 +02006841 int cert_peer = (kw[4] == 'c') ? 1 : 0;
James Votha051b4a2013-05-14 20:37:59 +02006842 X509 *crt = NULL;
6843 const EVP_MD *digest;
6844 int ret = 0;
Willy Tarreau767e8ad2020-02-25 08:59:23 +01006845 unsigned int len = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02006846 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006847 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006848 struct ssl_sock_ctx *ctx;
James Votha051b4a2013-05-14 20:37:59 +02006849
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006850 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006851 if (!conn || conn->xprt != &ssl_sock)
6852 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006853 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006854
6855 if (!(conn->flags & CO_FL_CONNECTED)) {
James Votha051b4a2013-05-14 20:37:59 +02006856 smp->flags |= SMP_F_MAY_CHANGE;
6857 return 0;
6858 }
6859
Emeric Brunba841a12014-04-30 17:05:08 +02006860 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006861 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02006862 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01006863 crt = SSL_get_certificate(ctx->ssl);
James Votha051b4a2013-05-14 20:37:59 +02006864 if (!crt)
6865 goto out;
6866
6867 smp_trash = get_trash_chunk();
6868 digest = EVP_sha1();
Willy Tarreau767e8ad2020-02-25 08:59:23 +01006869 X509_digest(crt, digest, (unsigned char *) smp_trash->area, &len);
6870 smp_trash->data = len;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006871 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006872 smp->data.type = SMP_T_BIN;
James Votha051b4a2013-05-14 20:37:59 +02006873 ret = 1;
6874out:
Emeric Brunba841a12014-04-30 17:05:08 +02006875 /* SSL_get_peer_certificate, it increase X509 * ref count */
6876 if (cert_peer && crt)
James Votha051b4a2013-05-14 20:37:59 +02006877 X509_free(crt);
6878 return ret;
6879}
6880
Emeric Brunba841a12014-04-30 17:05:08 +02006881/* string, returns certificate's notafter date in ASN1_UTCTIME format.
6882 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6883 * should be use.
6884 */
Emeric Brunce5ad802012-10-22 14:11:22 +02006885static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006886smp_fetch_ssl_x_notafter(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunce5ad802012-10-22 14:11:22 +02006887{
Emeric Brunba841a12014-04-30 17:05:08 +02006888 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brunce5ad802012-10-22 14:11:22 +02006889 X509 *crt = NULL;
6890 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02006891 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006892 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006893 struct ssl_sock_ctx *ctx;
Emeric Brunce5ad802012-10-22 14:11:22 +02006894
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006895 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006896 if (!conn || conn->xprt != &ssl_sock)
6897 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006898 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006899
6900 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02006901 smp->flags |= SMP_F_MAY_CHANGE;
6902 return 0;
6903 }
6904
Emeric Brunba841a12014-04-30 17:05:08 +02006905 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006906 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02006907 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01006908 crt = SSL_get_certificate(ctx->ssl);
Emeric Brunce5ad802012-10-22 14:11:22 +02006909 if (!crt)
6910 goto out;
6911
Willy Tarreau47ca5452012-12-23 20:22:19 +01006912 smp_trash = get_trash_chunk();
Rosen Penev68185952018-12-14 08:47:02 -08006913 if (ssl_sock_get_time(X509_getm_notAfter(crt), smp_trash) <= 0)
Emeric Brunce5ad802012-10-22 14:11:22 +02006914 goto out;
6915
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006916 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006917 smp->data.type = SMP_T_STR;
Emeric Brunce5ad802012-10-22 14:11:22 +02006918 ret = 1;
6919out:
Emeric Brunba841a12014-04-30 17:05:08 +02006920 /* SSL_get_peer_certificate, it increase X509 * ref count */
6921 if (cert_peer && crt)
Emeric Brunce5ad802012-10-22 14:11:22 +02006922 X509_free(crt);
6923 return ret;
6924}
6925
Emeric Brunba841a12014-04-30 17:05:08 +02006926/* string, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. of certificate's issuer
6927 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6928 * should be use.
6929 */
Emeric Brun87855892012-10-17 17:39:35 +02006930static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006931smp_fetch_ssl_x_i_dn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun87855892012-10-17 17:39:35 +02006932{
Emeric Brunba841a12014-04-30 17:05:08 +02006933 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun87855892012-10-17 17:39:35 +02006934 X509 *crt = NULL;
6935 X509_NAME *name;
6936 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02006937 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006938 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006939 struct ssl_sock_ctx *ctx;
Emeric Brun87855892012-10-17 17:39:35 +02006940
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006941 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006942 if (!conn || conn->xprt != &ssl_sock)
6943 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006944 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006945
6946 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02006947 smp->flags |= SMP_F_MAY_CHANGE;
6948 return 0;
6949 }
6950
Emeric Brunba841a12014-04-30 17:05:08 +02006951 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006952 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02006953 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01006954 crt = SSL_get_certificate(ctx->ssl);
Emeric Brun87855892012-10-17 17:39:35 +02006955 if (!crt)
6956 goto out;
6957
6958 name = X509_get_issuer_name(crt);
6959 if (!name)
6960 goto out;
6961
Willy Tarreau47ca5452012-12-23 20:22:19 +01006962 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02006963 if (args && args[0].type == ARGT_STR) {
6964 int pos = 1;
6965
6966 if (args[1].type == ARGT_SINT)
6967 pos = args[1].data.sint;
Emeric Brun87855892012-10-17 17:39:35 +02006968
6969 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
6970 goto out;
6971 }
6972 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
6973 goto out;
6974
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006975 smp->data.type = SMP_T_STR;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006976 smp->data.u.str = *smp_trash;
Emeric Brun87855892012-10-17 17:39:35 +02006977 ret = 1;
6978out:
Emeric Brunba841a12014-04-30 17:05:08 +02006979 /* SSL_get_peer_certificate, it increase X509 * ref count */
6980 if (cert_peer && crt)
Emeric Brun87855892012-10-17 17:39:35 +02006981 X509_free(crt);
6982 return ret;
6983}
6984
Emeric Brunba841a12014-04-30 17:05:08 +02006985/* string, returns notbefore date in ASN1_UTCTIME format.
6986 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6987 * should be use.
6988 */
Emeric Brunce5ad802012-10-22 14:11:22 +02006989static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006990smp_fetch_ssl_x_notbefore(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunce5ad802012-10-22 14:11:22 +02006991{
Emeric Brunba841a12014-04-30 17:05:08 +02006992 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brunce5ad802012-10-22 14:11:22 +02006993 X509 *crt = NULL;
6994 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02006995 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006996 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006997 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006998
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006999 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007000 if (!conn || conn->xprt != &ssl_sock)
Emeric Brunce5ad802012-10-22 14:11:22 +02007001 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007002 ctx = conn->xprt_ctx;
Emeric Brunce5ad802012-10-22 14:11:22 +02007003
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007004 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02007005 smp->flags |= SMP_F_MAY_CHANGE;
7006 return 0;
7007 }
7008
Emeric Brunba841a12014-04-30 17:05:08 +02007009 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007010 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007011 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007012 crt = SSL_get_certificate(ctx->ssl);
Emeric Brunce5ad802012-10-22 14:11:22 +02007013 if (!crt)
7014 goto out;
7015
Willy Tarreau47ca5452012-12-23 20:22:19 +01007016 smp_trash = get_trash_chunk();
Rosen Penev68185952018-12-14 08:47:02 -08007017 if (ssl_sock_get_time(X509_getm_notBefore(crt), smp_trash) <= 0)
Emeric Brunce5ad802012-10-22 14:11:22 +02007018 goto out;
7019
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007020 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007021 smp->data.type = SMP_T_STR;
Emeric Brunce5ad802012-10-22 14:11:22 +02007022 ret = 1;
7023out:
Emeric Brunba841a12014-04-30 17:05:08 +02007024 /* SSL_get_peer_certificate, it increase X509 * ref count */
7025 if (cert_peer && crt)
Emeric Brunce5ad802012-10-22 14:11:22 +02007026 X509_free(crt);
7027 return ret;
7028}
7029
Emeric Brunba841a12014-04-30 17:05:08 +02007030/* string, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. of certificate's subject
7031 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7032 * should be use.
7033 */
Emeric Brun87855892012-10-17 17:39:35 +02007034static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007035smp_fetch_ssl_x_s_dn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun87855892012-10-17 17:39:35 +02007036{
Emeric Brunba841a12014-04-30 17:05:08 +02007037 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun87855892012-10-17 17:39:35 +02007038 X509 *crt = NULL;
7039 X509_NAME *name;
7040 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02007041 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007042 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007043 struct ssl_sock_ctx *ctx;
Emeric Brun87855892012-10-17 17:39:35 +02007044
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007045 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007046 if (!conn || conn->xprt != &ssl_sock)
7047 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007048 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007049
7050 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02007051 smp->flags |= SMP_F_MAY_CHANGE;
7052 return 0;
7053 }
7054
Emeric Brunba841a12014-04-30 17:05:08 +02007055 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007056 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007057 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007058 crt = SSL_get_certificate(ctx->ssl);
Emeric Brun87855892012-10-17 17:39:35 +02007059 if (!crt)
7060 goto out;
7061
7062 name = X509_get_subject_name(crt);
7063 if (!name)
7064 goto out;
7065
Willy Tarreau47ca5452012-12-23 20:22:19 +01007066 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02007067 if (args && args[0].type == ARGT_STR) {
7068 int pos = 1;
7069
7070 if (args[1].type == ARGT_SINT)
7071 pos = args[1].data.sint;
Emeric Brun87855892012-10-17 17:39:35 +02007072
7073 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
7074 goto out;
7075 }
7076 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
7077 goto out;
7078
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007079 smp->data.type = SMP_T_STR;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007080 smp->data.u.str = *smp_trash;
Emeric Brun87855892012-10-17 17:39:35 +02007081 ret = 1;
7082out:
Emeric Brunba841a12014-04-30 17:05:08 +02007083 /* SSL_get_peer_certificate, it increase X509 * ref count */
7084 if (cert_peer && crt)
Emeric Brun87855892012-10-17 17:39:35 +02007085 X509_free(crt);
7086 return ret;
7087}
Emeric Brun9143d372012-12-20 15:44:16 +01007088
7089/* integer, returns true if current session use a client certificate */
7090static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007091smp_fetch_ssl_c_used(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun9143d372012-12-20 15:44:16 +01007092{
7093 X509 *crt;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007094 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007095 struct ssl_sock_ctx *ctx;
Emeric Brun9143d372012-12-20 15:44:16 +01007096
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007097 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007098 if (!conn || conn->xprt != &ssl_sock)
7099 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007100 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007101
7102 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun9143d372012-12-20 15:44:16 +01007103 smp->flags |= SMP_F_MAY_CHANGE;
7104 return 0;
7105 }
7106
7107 /* SSL_get_peer_certificate returns a ptr on allocated X509 struct */
Olivier Houchard66ab4982019-02-26 18:37:15 +01007108 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brun9143d372012-12-20 15:44:16 +01007109 if (crt) {
7110 X509_free(crt);
7111 }
7112
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007113 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007114 smp->data.u.sint = (crt != NULL);
Emeric Brun9143d372012-12-20 15:44:16 +01007115 return 1;
7116}
7117
Emeric Brunba841a12014-04-30 17:05:08 +02007118/* integer, returns the certificate version
7119 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7120 * should be use.
7121 */
Emeric Bruna7359fd2012-10-17 15:03:11 +02007122static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007123smp_fetch_ssl_x_version(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Bruna7359fd2012-10-17 15:03:11 +02007124{
Emeric Brunba841a12014-04-30 17:05:08 +02007125 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Bruna7359fd2012-10-17 15:03:11 +02007126 X509 *crt;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007127 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007128 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007129
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007130 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007131 if (!conn || conn->xprt != &ssl_sock)
Emeric Bruna7359fd2012-10-17 15:03:11 +02007132 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007133 ctx = conn->xprt_ctx;
Emeric Bruna7359fd2012-10-17 15:03:11 +02007134
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007135 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Bruna7359fd2012-10-17 15:03:11 +02007136 smp->flags |= SMP_F_MAY_CHANGE;
7137 return 0;
7138 }
7139
Emeric Brunba841a12014-04-30 17:05:08 +02007140 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007141 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007142 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007143 crt = SSL_get_certificate(ctx->ssl);
Emeric Bruna7359fd2012-10-17 15:03:11 +02007144 if (!crt)
7145 return 0;
7146
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007147 smp->data.u.sint = (unsigned int)(1 + X509_get_version(crt));
Emeric Brunba841a12014-04-30 17:05:08 +02007148 /* SSL_get_peer_certificate increase X509 * ref count */
7149 if (cert_peer)
7150 X509_free(crt);
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007151 smp->data.type = SMP_T_SINT;
Emeric Bruna7359fd2012-10-17 15:03:11 +02007152
7153 return 1;
7154}
7155
Emeric Brunba841a12014-04-30 17:05:08 +02007156/* string, returns the certificate's signature algorithm.
7157 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7158 * should be use.
7159 */
Emeric Brun7f56e742012-10-19 18:15:40 +02007160static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007161smp_fetch_ssl_x_sig_alg(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun7f56e742012-10-19 18:15:40 +02007162{
Emeric Brunba841a12014-04-30 17:05:08 +02007163 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun7f56e742012-10-19 18:15:40 +02007164 X509 *crt;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007165 __OPENSSL_110_CONST__ ASN1_OBJECT *algorithm;
Emeric Brun7f56e742012-10-19 18:15:40 +02007166 int nid;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007167 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007168 struct ssl_sock_ctx *ctx;
Emeric Brun7f56e742012-10-19 18:15:40 +02007169
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007170 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007171 if (!conn || conn->xprt != &ssl_sock)
7172 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007173 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007174
7175 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun7f56e742012-10-19 18:15:40 +02007176 smp->flags |= SMP_F_MAY_CHANGE;
7177 return 0;
7178 }
7179
Emeric Brunba841a12014-04-30 17:05:08 +02007180 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007181 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007182 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007183 crt = SSL_get_certificate(ctx->ssl);
Emeric Brun7f56e742012-10-19 18:15:40 +02007184 if (!crt)
7185 return 0;
7186
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007187 X509_ALGOR_get0(&algorithm, NULL, NULL, X509_get0_tbs_sigalg(crt));
7188 nid = OBJ_obj2nid(algorithm);
Emeric Brun7f56e742012-10-19 18:15:40 +02007189
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007190 smp->data.u.str.area = (char *)OBJ_nid2sn(nid);
7191 if (!smp->data.u.str.area) {
Emeric Brunba841a12014-04-30 17:05:08 +02007192 /* SSL_get_peer_certificate increase X509 * ref count */
7193 if (cert_peer)
7194 X509_free(crt);
Emeric Brun7f56e742012-10-19 18:15:40 +02007195 return 0;
Emeric Brun9bf3ba22013-10-07 14:31:44 +02007196 }
Emeric Brun7f56e742012-10-19 18:15:40 +02007197
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007198 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01007199 smp->flags |= SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007200 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brunba841a12014-04-30 17:05:08 +02007201 /* SSL_get_peer_certificate increase X509 * ref count */
7202 if (cert_peer)
7203 X509_free(crt);
Emeric Brun7f56e742012-10-19 18:15:40 +02007204
7205 return 1;
7206}
7207
Emeric Brunba841a12014-04-30 17:05:08 +02007208/* string, returns the certificate's key algorithm.
7209 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7210 * should be use.
7211 */
Emeric Brun521a0112012-10-22 12:22:55 +02007212static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007213smp_fetch_ssl_x_key_alg(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun521a0112012-10-22 12:22:55 +02007214{
Emeric Brunba841a12014-04-30 17:05:08 +02007215 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun521a0112012-10-22 12:22:55 +02007216 X509 *crt;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007217 ASN1_OBJECT *algorithm;
Emeric Brun521a0112012-10-22 12:22:55 +02007218 int nid;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007219 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007220 struct ssl_sock_ctx *ctx;
Emeric Brun521a0112012-10-22 12:22:55 +02007221
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007222 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007223 if (!conn || conn->xprt != &ssl_sock)
7224 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007225 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007226
7227 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun521a0112012-10-22 12:22:55 +02007228 smp->flags |= SMP_F_MAY_CHANGE;
7229 return 0;
7230 }
7231
Emeric Brunba841a12014-04-30 17:05:08 +02007232 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007233 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007234 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007235 crt = SSL_get_certificate(ctx->ssl);
Emeric Brun521a0112012-10-22 12:22:55 +02007236 if (!crt)
7237 return 0;
7238
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007239 X509_PUBKEY_get0_param(&algorithm, NULL, NULL, NULL, X509_get_X509_PUBKEY(crt));
7240 nid = OBJ_obj2nid(algorithm);
Emeric Brun521a0112012-10-22 12:22:55 +02007241
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007242 smp->data.u.str.area = (char *)OBJ_nid2sn(nid);
7243 if (!smp->data.u.str.area) {
Emeric Brunba841a12014-04-30 17:05:08 +02007244 /* SSL_get_peer_certificate increase X509 * ref count */
7245 if (cert_peer)
7246 X509_free(crt);
Emeric Brun521a0112012-10-22 12:22:55 +02007247 return 0;
Emeric Brun9bf3ba22013-10-07 14:31:44 +02007248 }
Emeric Brun521a0112012-10-22 12:22:55 +02007249
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007250 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01007251 smp->flags |= SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007252 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brunba841a12014-04-30 17:05:08 +02007253 if (cert_peer)
7254 X509_free(crt);
Emeric Brun521a0112012-10-22 12:22:55 +02007255
7256 return 1;
7257}
7258
Emeric Brun645ae792014-04-30 14:21:06 +02007259/* boolean, returns true if front conn. transport layer is SSL.
7260 * This function is also usable on backend conn if the fetch keyword 5th
7261 * char is 'b'.
7262 */
Willy Tarreau7875d092012-09-10 08:20:03 +02007263static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007264smp_fetch_ssl_fc(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02007265{
Emeric Bruneb8def92018-02-19 15:59:48 +01007266 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7267 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007268
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007269 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007270 smp->data.u.sint = (conn && conn->xprt == &ssl_sock);
Willy Tarreau7875d092012-09-10 08:20:03 +02007271 return 1;
7272}
7273
Emeric Brun2525b6b2012-10-18 15:59:43 +02007274/* boolean, returns true if client present a SNI */
Willy Tarreau7875d092012-09-10 08:20:03 +02007275static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007276smp_fetch_ssl_fc_has_sni(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02007277{
7278#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007279 struct connection *conn = objt_conn(smp->sess->origin);
Olivier Houchard66ab4982019-02-26 18:37:15 +01007280 struct ssl_sock_ctx *ctx = conn ? conn->xprt_ctx : NULL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007281
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007282 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007283 smp->data.u.sint = (conn && conn->xprt == &ssl_sock) &&
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007284 conn->xprt_ctx &&
Olivier Houchard66ab4982019-02-26 18:37:15 +01007285 SSL_get_servername(ctx->ssl, TLSEXT_NAMETYPE_host_name) != NULL;
Willy Tarreau7875d092012-09-10 08:20:03 +02007286 return 1;
7287#else
7288 return 0;
7289#endif
7290}
7291
Emeric Brun74f7ffa2018-02-19 16:14:12 +01007292/* boolean, returns true if client session has been resumed.
7293 * This function is also usable on backend conn if the fetch keyword 5th
7294 * char is 'b'.
7295 */
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02007296static int
7297smp_fetch_ssl_fc_is_resumed(const struct arg *args, struct sample *smp, const char *kw, void *private)
7298{
Emeric Brun74f7ffa2018-02-19 16:14:12 +01007299 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7300 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007301 struct ssl_sock_ctx *ctx = conn ? conn->xprt_ctx : NULL;
Emeric Brun74f7ffa2018-02-19 16:14:12 +01007302
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02007303
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007304 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007305 smp->data.u.sint = (conn && conn->xprt == &ssl_sock) &&
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02007306 conn->xprt_ctx &&
Olivier Houchard66ab4982019-02-26 18:37:15 +01007307 SSL_session_reused(ctx->ssl);
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02007308 return 1;
7309}
7310
Emeric Brun645ae792014-04-30 14:21:06 +02007311/* string, returns the used cipher if front conn. transport layer is SSL.
7312 * This function is also usable on backend conn if the fetch keyword 5th
7313 * char is 'b'.
7314 */
Emeric Brun589fcad2012-10-16 14:13:26 +02007315static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007316smp_fetch_ssl_fc_cipher(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02007317{
Emeric Bruneb8def92018-02-19 15:59:48 +01007318 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7319 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007320 struct ssl_sock_ctx *ctx;
Emeric Brun589fcad2012-10-16 14:13:26 +02007321
Willy Tarreaube508f12016-03-10 11:47:01 +01007322 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007323 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02007324 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007325 ctx = conn->xprt_ctx;
Emeric Brun589fcad2012-10-16 14:13:26 +02007326
Olivier Houchard66ab4982019-02-26 18:37:15 +01007327 smp->data.u.str.area = (char *)SSL_get_cipher_name(ctx->ssl);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007328 if (!smp->data.u.str.area)
Emeric Brun589fcad2012-10-16 14:13:26 +02007329 return 0;
7330
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007331 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01007332 smp->flags |= SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007333 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brun589fcad2012-10-16 14:13:26 +02007334
7335 return 1;
7336}
7337
Emeric Brun645ae792014-04-30 14:21:06 +02007338/* integer, returns the algoritm's keysize if front conn. transport layer
7339 * is SSL.
7340 * This function is also usable on backend conn if the fetch keyword 5th
7341 * char is 'b'.
7342 */
Emeric Brun589fcad2012-10-16 14:13:26 +02007343static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007344smp_fetch_ssl_fc_alg_keysize(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02007345{
Emeric Bruneb8def92018-02-19 15:59:48 +01007346 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7347 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007348 struct ssl_sock_ctx *ctx;
Willy Tarreaue237fe12016-03-10 17:05:28 +01007349 int sint;
Willy Tarreaube508f12016-03-10 11:47:01 +01007350
Emeric Brun589fcad2012-10-16 14:13:26 +02007351 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007352 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02007353 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007354 ctx = conn->xprt_ctx;
Emeric Brun589fcad2012-10-16 14:13:26 +02007355
Olivier Houchard66ab4982019-02-26 18:37:15 +01007356 if (!SSL_get_cipher_bits(ctx->ssl, &sint))
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007357 return 0;
7358
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007359 smp->data.u.sint = sint;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007360 smp->data.type = SMP_T_SINT;
Emeric Brun589fcad2012-10-16 14:13:26 +02007361
7362 return 1;
7363}
7364
Emeric Brun645ae792014-04-30 14:21:06 +02007365/* integer, returns the used keysize if front conn. transport layer is SSL.
7366 * This function is also usable on backend conn if the fetch keyword 5th
7367 * char is 'b'.
7368 */
Emeric Brun589fcad2012-10-16 14:13:26 +02007369static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007370smp_fetch_ssl_fc_use_keysize(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02007371{
Emeric Bruneb8def92018-02-19 15:59:48 +01007372 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7373 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007374 struct ssl_sock_ctx *ctx;
Willy Tarreaube508f12016-03-10 11:47:01 +01007375
Emeric Brun589fcad2012-10-16 14:13:26 +02007376 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007377 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7378 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007379 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007380
Olivier Houchard66ab4982019-02-26 18:37:15 +01007381 smp->data.u.sint = (unsigned int)SSL_get_cipher_bits(ctx->ssl, NULL);
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007382 if (!smp->data.u.sint)
Emeric Brun589fcad2012-10-16 14:13:26 +02007383 return 0;
7384
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007385 smp->data.type = SMP_T_SINT;
Emeric Brun589fcad2012-10-16 14:13:26 +02007386
7387 return 1;
7388}
7389
Bernard Spil13c53f82018-02-15 13:34:58 +01007390#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Willy Tarreau7875d092012-09-10 08:20:03 +02007391static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007392smp_fetch_ssl_fc_npn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreaua33c6542012-10-15 13:19:06 +02007393{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007394 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007395 struct ssl_sock_ctx *ctx;
Willy Tarreau767e8ad2020-02-25 08:59:23 +01007396 unsigned int len = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007397
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01007398 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007399 smp->data.type = SMP_T_STR;
Willy Tarreaua33c6542012-10-15 13:19:06 +02007400
Olivier Houchard6b77f492018-11-22 18:18:29 +01007401 conn = (kw[4] != 'b' ) ? objt_conn(smp->sess->origin) :
7402 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007403 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7404 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007405 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007406
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007407 smp->data.u.str.area = NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007408 SSL_get0_next_proto_negotiated(ctx->ssl,
Willy Tarreau767e8ad2020-02-25 08:59:23 +01007409 (const unsigned char **)&smp->data.u.str.area,
7410 &len);
Willy Tarreaua33c6542012-10-15 13:19:06 +02007411
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007412 if (!smp->data.u.str.area)
Willy Tarreaua33c6542012-10-15 13:19:06 +02007413 return 0;
7414
Willy Tarreau767e8ad2020-02-25 08:59:23 +01007415 smp->data.u.str.data = len;
Willy Tarreaua33c6542012-10-15 13:19:06 +02007416 return 1;
Willy Tarreaua33c6542012-10-15 13:19:06 +02007417}
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02007418#endif
Willy Tarreaua33c6542012-10-15 13:19:06 +02007419
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01007420#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02007421static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007422smp_fetch_ssl_fc_alpn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreauab861d32013-04-02 02:30:41 +02007423{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007424 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007425 struct ssl_sock_ctx *ctx;
Willy Tarreau767e8ad2020-02-25 08:59:23 +01007426 unsigned int len = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007427
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01007428 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007429 smp->data.type = SMP_T_STR;
Willy Tarreauab861d32013-04-02 02:30:41 +02007430
Olivier Houchard6b77f492018-11-22 18:18:29 +01007431 conn = (kw[4] != 'b' ) ? objt_conn(smp->sess->origin) :
7432 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
7433
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007434 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Willy Tarreauab861d32013-04-02 02:30:41 +02007435 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007436 ctx = conn->xprt_ctx;
Willy Tarreauab861d32013-04-02 02:30:41 +02007437
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007438 smp->data.u.str.area = NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007439 SSL_get0_alpn_selected(ctx->ssl,
Willy Tarreau767e8ad2020-02-25 08:59:23 +01007440 (const unsigned char **)&smp->data.u.str.area,
7441 &len);
Willy Tarreauab861d32013-04-02 02:30:41 +02007442
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007443 if (!smp->data.u.str.area)
Willy Tarreauab861d32013-04-02 02:30:41 +02007444 return 0;
7445
Willy Tarreau767e8ad2020-02-25 08:59:23 +01007446 smp->data.u.str.data = len;
Willy Tarreauab861d32013-04-02 02:30:41 +02007447 return 1;
7448}
7449#endif
7450
Emeric Brun645ae792014-04-30 14:21:06 +02007451/* string, returns the used protocol if front conn. transport layer is SSL.
7452 * This function is also usable on backend conn if the fetch keyword 5th
7453 * char is 'b'.
7454 */
Willy Tarreaua33c6542012-10-15 13:19:06 +02007455static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007456smp_fetch_ssl_fc_protocol(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02007457{
Emeric Bruneb8def92018-02-19 15:59:48 +01007458 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7459 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007460 struct ssl_sock_ctx *ctx;
Willy Tarreaube508f12016-03-10 11:47:01 +01007461
Emeric Brun589fcad2012-10-16 14:13:26 +02007462 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007463 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7464 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007465 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007466
Olivier Houchard66ab4982019-02-26 18:37:15 +01007467 smp->data.u.str.area = (char *)SSL_get_version(ctx->ssl);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007468 if (!smp->data.u.str.area)
Emeric Brun589fcad2012-10-16 14:13:26 +02007469 return 0;
7470
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007471 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01007472 smp->flags = SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007473 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brun589fcad2012-10-16 14:13:26 +02007474
7475 return 1;
7476}
7477
Willy Tarreau87b09662015-04-03 00:22:06 +02007478/* binary, returns the SSL stream id if front conn. transport layer is SSL.
Emeric Brun645ae792014-04-30 14:21:06 +02007479 * This function is also usable on backend conn if the fetch keyword 5th
7480 * char is 'b'.
7481 */
Willy Tarreau9a1ab082019-05-09 13:26:41 +02007482#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
Emeric Brun589fcad2012-10-16 14:13:26 +02007483static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007484smp_fetch_ssl_fc_session_id(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunfe68f682012-10-16 14:59:28 +02007485{
Emeric Bruneb8def92018-02-19 15:59:48 +01007486 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7487 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaue237fe12016-03-10 17:05:28 +01007488 SSL_SESSION *ssl_sess;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007489 struct ssl_sock_ctx *ctx;
Willy Tarreau767e8ad2020-02-25 08:59:23 +01007490 unsigned int len = 0;
Willy Tarreaube508f12016-03-10 11:47:01 +01007491
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01007492 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007493 smp->data.type = SMP_T_BIN;
Emeric Brunfe68f682012-10-16 14:59:28 +02007494
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007495 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7496 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007497 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007498
Olivier Houchard66ab4982019-02-26 18:37:15 +01007499 ssl_sess = SSL_get_session(ctx->ssl);
Willy Tarreau192252e2015-04-04 01:47:55 +02007500 if (!ssl_sess)
Emeric Brunfe68f682012-10-16 14:59:28 +02007501 return 0;
7502
Willy Tarreau767e8ad2020-02-25 08:59:23 +01007503 smp->data.u.str.area = (char *)SSL_SESSION_get_id(ssl_sess, &len);
Dragan Dosen9dc47c42020-05-04 09:07:28 +02007504 if (!smp->data.u.str.area || !len)
Emeric Brunfe68f682012-10-16 14:59:28 +02007505 return 0;
7506
Willy Tarreau767e8ad2020-02-25 08:59:23 +01007507 smp->data.u.str.data = len;
Emeric Brunfe68f682012-10-16 14:59:28 +02007508 return 1;
Emeric Brunfe68f682012-10-16 14:59:28 +02007509}
Patrick Hemmer41966772018-04-28 19:15:48 -04007510#endif
7511
Emeric Brunfe68f682012-10-16 14:59:28 +02007512
Emmanuel Hocdet839af572019-05-14 16:27:35 +02007513#if HA_OPENSSL_VERSION_NUMBER >= 0x10100000L
Patrick Hemmere0275472018-04-28 19:15:51 -04007514static int
Patrick Hemmer65674662019-06-04 08:13:03 -04007515smp_fetch_ssl_fc_random(const struct arg *args, struct sample *smp, const char *kw, void *private)
7516{
7517 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7518 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
7519 struct buffer *data;
7520 struct ssl_sock_ctx *ctx;
7521
7522 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7523 return 0;
7524 ctx = conn->xprt_ctx;
7525
7526 data = get_trash_chunk();
7527 if (kw[7] == 'c')
7528 data->data = SSL_get_client_random(ctx->ssl,
7529 (unsigned char *) data->area,
7530 data->size);
7531 else
7532 data->data = SSL_get_server_random(ctx->ssl,
7533 (unsigned char *) data->area,
7534 data->size);
7535 if (!data->data)
7536 return 0;
7537
7538 smp->flags = 0;
7539 smp->data.type = SMP_T_BIN;
7540 smp->data.u.str = *data;
7541
7542 return 1;
7543}
7544
7545static int
Patrick Hemmere0275472018-04-28 19:15:51 -04007546smp_fetch_ssl_fc_session_key(const struct arg *args, struct sample *smp, const char *kw, void *private)
7547{
7548 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7549 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
7550 SSL_SESSION *ssl_sess;
Willy Tarreau83061a82018-07-13 11:56:34 +02007551 struct buffer *data;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007552 struct ssl_sock_ctx *ctx;
Patrick Hemmere0275472018-04-28 19:15:51 -04007553
7554 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7555 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007556 ctx = conn->xprt_ctx;
Patrick Hemmere0275472018-04-28 19:15:51 -04007557
Olivier Houchard66ab4982019-02-26 18:37:15 +01007558 ssl_sess = SSL_get_session(ctx->ssl);
Patrick Hemmere0275472018-04-28 19:15:51 -04007559 if (!ssl_sess)
7560 return 0;
7561
7562 data = get_trash_chunk();
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007563 data->data = SSL_SESSION_get_master_key(ssl_sess,
7564 (unsigned char *) data->area,
7565 data->size);
7566 if (!data->data)
Patrick Hemmere0275472018-04-28 19:15:51 -04007567 return 0;
7568
7569 smp->flags = 0;
7570 smp->data.type = SMP_T_BIN;
7571 smp->data.u.str = *data;
7572
7573 return 1;
7574}
7575#endif
7576
Patrick Hemmer41966772018-04-28 19:15:48 -04007577#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emeric Brunfe68f682012-10-16 14:59:28 +02007578static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007579smp_fetch_ssl_fc_sni(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02007580{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007581 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007582 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007583
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01007584 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007585 smp->data.type = SMP_T_STR;
Willy Tarreau7875d092012-09-10 08:20:03 +02007586
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007587 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007588 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7589 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007590 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007591
Olivier Houchard66ab4982019-02-26 18:37:15 +01007592 smp->data.u.str.area = (char *)SSL_get_servername(ctx->ssl, TLSEXT_NAMETYPE_host_name);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007593 if (!smp->data.u.str.area)
Willy Tarreau3e394c92012-09-14 23:56:58 +02007594 return 0;
7595
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007596 smp->data.u.str.data = strlen(smp->data.u.str.area);
Willy Tarreau7875d092012-09-10 08:20:03 +02007597 return 1;
Willy Tarreau7875d092012-09-10 08:20:03 +02007598}
Patrick Hemmer41966772018-04-28 19:15:48 -04007599#endif
Willy Tarreau7875d092012-09-10 08:20:03 +02007600
David Sc1ad52e2014-04-08 18:48:47 -04007601static int
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007602smp_fetch_ssl_fc_cl_bin(const struct arg *args, struct sample *smp, const char *kw, void *private)
7603{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007604 struct connection *conn;
7605 struct ssl_capture *capture;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007606 struct ssl_sock_ctx *ctx;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007607
7608 conn = objt_conn(smp->sess->origin);
7609 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7610 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007611 ctx = conn->xprt_ctx;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007612
Olivier Houchard66ab4982019-02-26 18:37:15 +01007613 capture = SSL_get_ex_data(ctx->ssl, ssl_capture_ptr_index);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007614 if (!capture)
7615 return 0;
7616
7617 smp->flags = SMP_F_CONST;
7618 smp->data.type = SMP_T_BIN;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007619 smp->data.u.str.area = capture->ciphersuite;
7620 smp->data.u.str.data = capture->ciphersuite_len;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007621 return 1;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007622}
7623
7624static int
7625smp_fetch_ssl_fc_cl_hex(const struct arg *args, struct sample *smp, const char *kw, void *private)
7626{
Willy Tarreau83061a82018-07-13 11:56:34 +02007627 struct buffer *data;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007628
7629 if (!smp_fetch_ssl_fc_cl_bin(args, smp, kw, private))
7630 return 0;
7631
7632 data = get_trash_chunk();
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007633 dump_binary(data, smp->data.u.str.area, smp->data.u.str.data);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007634 smp->data.type = SMP_T_BIN;
7635 smp->data.u.str = *data;
7636 return 1;
7637}
7638
7639static int
7640smp_fetch_ssl_fc_cl_xxh64(const struct arg *args, struct sample *smp, const char *kw, void *private)
7641{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007642 struct connection *conn;
7643 struct ssl_capture *capture;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007644 struct ssl_sock_ctx *ctx;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007645
7646 conn = objt_conn(smp->sess->origin);
7647 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7648 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007649 ctx = conn->xprt_ctx;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007650
Olivier Houchard66ab4982019-02-26 18:37:15 +01007651 capture = SSL_get_ex_data(ctx->ssl, ssl_capture_ptr_index);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007652 if (!capture)
7653 return 0;
7654
7655 smp->data.type = SMP_T_SINT;
7656 smp->data.u.sint = capture->xxh64;
7657 return 1;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007658}
7659
7660static int
7661smp_fetch_ssl_fc_cl_str(const struct arg *args, struct sample *smp, const char *kw, void *private)
7662{
Willy Tarreau5db847a2019-05-09 14:13:35 +02007663#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL)
Willy Tarreau83061a82018-07-13 11:56:34 +02007664 struct buffer *data;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007665 int i;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007666
7667 if (!smp_fetch_ssl_fc_cl_bin(args, smp, kw, private))
7668 return 0;
7669
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007670 data = get_trash_chunk();
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007671 for (i = 0; i + 1 < smp->data.u.str.data; i += 2) {
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02007672 const char *str;
7673 const SSL_CIPHER *cipher;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007674 const unsigned char *bin = (const unsigned char *) smp->data.u.str.area + i;
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02007675 uint16_t id = (bin[0] << 8) | bin[1];
7676#if defined(OPENSSL_IS_BORINGSSL)
7677 cipher = SSL_get_cipher_by_value(id);
7678#else
Willy Tarreaub7290772018-10-15 11:01:59 +02007679 struct connection *conn = __objt_conn(smp->sess->origin);
Olivier Houchard66ab4982019-02-26 18:37:15 +01007680 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
7681 cipher = SSL_CIPHER_find(ctx->ssl, bin);
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02007682#endif
7683 str = SSL_CIPHER_get_name(cipher);
7684 if (!str || strcmp(str, "(NONE)") == 0)
7685 chunk_appendf(data, "%sUNKNOWN(%04x)", i == 0 ? "" : ",", id);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007686 else
7687 chunk_appendf(data, "%s%s", i == 0 ? "" : ",", str);
7688 }
7689 smp->data.type = SMP_T_STR;
7690 smp->data.u.str = *data;
7691 return 1;
7692#else
7693 return smp_fetch_ssl_fc_cl_xxh64(args, smp, kw, private);
7694#endif
7695}
7696
Willy Tarreau9a1ab082019-05-09 13:26:41 +02007697#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007698static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007699smp_fetch_ssl_fc_unique_id(const struct arg *args, struct sample *smp, const char *kw, void *private)
David Sc1ad52e2014-04-08 18:48:47 -04007700{
Emeric Bruneb8def92018-02-19 15:59:48 +01007701 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7702 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
David Sc1ad52e2014-04-08 18:48:47 -04007703 int finished_len;
Willy Tarreau83061a82018-07-13 11:56:34 +02007704 struct buffer *finished_trash;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007705 struct ssl_sock_ctx *ctx;
David Sc1ad52e2014-04-08 18:48:47 -04007706
7707 smp->flags = 0;
David Sc1ad52e2014-04-08 18:48:47 -04007708 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7709 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007710 ctx = conn->xprt_ctx;
David Sc1ad52e2014-04-08 18:48:47 -04007711
7712 if (!(conn->flags & CO_FL_CONNECTED)) {
7713 smp->flags |= SMP_F_MAY_CHANGE;
7714 return 0;
7715 }
7716
7717 finished_trash = get_trash_chunk();
Olivier Houchard66ab4982019-02-26 18:37:15 +01007718 if (!SSL_session_reused(ctx->ssl))
7719 finished_len = SSL_get_peer_finished(ctx->ssl,
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007720 finished_trash->area,
7721 finished_trash->size);
David Sc1ad52e2014-04-08 18:48:47 -04007722 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007723 finished_len = SSL_get_finished(ctx->ssl,
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007724 finished_trash->area,
7725 finished_trash->size);
David Sc1ad52e2014-04-08 18:48:47 -04007726
7727 if (!finished_len)
7728 return 0;
7729
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007730 finished_trash->data = finished_len;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007731 smp->data.u.str = *finished_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007732 smp->data.type = SMP_T_BIN;
David Sc1ad52e2014-04-08 18:48:47 -04007733
7734 return 1;
David Sc1ad52e2014-04-08 18:48:47 -04007735}
Patrick Hemmer41966772018-04-28 19:15:48 -04007736#endif
David Sc1ad52e2014-04-08 18:48:47 -04007737
Emeric Brun2525b6b2012-10-18 15:59:43 +02007738/* integer, returns the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02007739static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007740smp_fetch_ssl_c_ca_err(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunf282a812012-09-21 15:27:54 +02007741{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007742 struct connection *conn;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007743 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007744
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007745 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007746 if (!conn || conn->xprt != &ssl_sock)
7747 return 0;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007748 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007749
7750 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02007751 smp->flags = SMP_F_MAY_CHANGE;
7752 return 0;
7753 }
7754
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007755 smp->data.type = SMP_T_SINT;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007756 smp->data.u.sint = (unsigned long long int)SSL_SOCK_ST_TO_CA_ERROR(ctx->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02007757 smp->flags = 0;
7758
7759 return 1;
7760}
7761
Emeric Brun2525b6b2012-10-18 15:59:43 +02007762/* integer, returns the depth of the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02007763static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007764smp_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 +02007765{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007766 struct connection *conn;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007767 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007768
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007769 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007770 if (!conn || conn->xprt != &ssl_sock)
Emeric Brunf282a812012-09-21 15:27:54 +02007771 return 0;
7772
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007773 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02007774 smp->flags = SMP_F_MAY_CHANGE;
7775 return 0;
7776 }
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007777 ctx = conn->xprt_ctx;
Emeric Brunf282a812012-09-21 15:27:54 +02007778
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007779 smp->data.type = SMP_T_SINT;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007780 smp->data.u.sint = (long long int)SSL_SOCK_ST_TO_CAEDEPTH(ctx->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02007781 smp->flags = 0;
7782
7783 return 1;
7784}
7785
Emeric Brun2525b6b2012-10-18 15:59:43 +02007786/* integer, returns the first verify error on client certificate */
Emeric Brunf282a812012-09-21 15:27:54 +02007787static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007788smp_fetch_ssl_c_err(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunf282a812012-09-21 15:27:54 +02007789{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007790 struct connection *conn;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007791 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007792
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007793 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007794 if (!conn || conn->xprt != &ssl_sock)
7795 return 0;
7796
7797 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02007798 smp->flags = SMP_F_MAY_CHANGE;
7799 return 0;
7800 }
7801
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007802 ctx = conn->xprt_ctx;
7803
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007804 smp->data.type = SMP_T_SINT;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007805 smp->data.u.sint = (long long int)SSL_SOCK_ST_TO_CRTERROR(ctx->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02007806 smp->flags = 0;
7807
7808 return 1;
7809}
7810
Emeric Brun2525b6b2012-10-18 15:59:43 +02007811/* integer, returns the verify result on client cert */
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02007812static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007813smp_fetch_ssl_c_verify(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02007814{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007815 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007816 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007817
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007818 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007819 if (!conn || conn->xprt != &ssl_sock)
7820 return 0;
7821
7822 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02007823 smp->flags = SMP_F_MAY_CHANGE;
7824 return 0;
7825 }
7826
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007827 if (!conn->xprt_ctx)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02007828 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007829 ctx = conn->xprt_ctx;
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02007830
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007831 smp->data.type = SMP_T_SINT;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007832 smp->data.u.sint = (long long int)SSL_get_verify_result(ctx->ssl);
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02007833 smp->flags = 0;
7834
7835 return 1;
7836}
7837
Emeric Brunfb510ea2012-10-05 12:00:26 +02007838/* parse the "ca-file" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007839static 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 +02007840{
7841 if (!*args[cur_arg + 1]) {
7842 if (err)
7843 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
7844 return ERR_ALERT | ERR_FATAL;
7845 }
7846
Willy Tarreauef934602016-12-22 23:12:01 +01007847 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
7848 memprintf(&conf->ca_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02007849 else
7850 memprintf(&conf->ca_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02007851
Emeric Brund94b3fe2012-09-20 18:23:56 +02007852 return 0;
7853}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007854static int bind_parse_ca_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7855{
7856 return ssl_bind_parse_ca_file(args, cur_arg, px, &conf->ssl_conf, err);
7857}
Emeric Brund94b3fe2012-09-20 18:23:56 +02007858
Christopher Faulet31af49d2015-06-09 17:29:50 +02007859/* parse the "ca-sign-file" bind keyword */
7860static int bind_parse_ca_sign_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7861{
7862 if (!*args[cur_arg + 1]) {
7863 if (err)
7864 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
7865 return ERR_ALERT | ERR_FATAL;
7866 }
7867
Willy Tarreauef934602016-12-22 23:12:01 +01007868 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
7869 memprintf(&conf->ca_sign_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Christopher Faulet31af49d2015-06-09 17:29:50 +02007870 else
7871 memprintf(&conf->ca_sign_file, "%s", args[cur_arg + 1]);
7872
7873 return 0;
7874}
7875
Bertrand Jacquinff13c062016-11-13 16:37:11 +00007876/* parse the "ca-sign-pass" bind keyword */
Christopher Faulet31af49d2015-06-09 17:29:50 +02007877static int bind_parse_ca_sign_pass(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7878{
7879 if (!*args[cur_arg + 1]) {
7880 if (err)
7881 memprintf(err, "'%s' : missing CAkey password", args[cur_arg]);
7882 return ERR_ALERT | ERR_FATAL;
7883 }
7884 memprintf(&conf->ca_sign_pass, "%s", args[cur_arg + 1]);
7885 return 0;
7886}
7887
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007888/* parse the "ciphers" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007889static 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 +02007890{
7891 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02007892 memprintf(err, "'%s' : missing cipher suite", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007893 return ERR_ALERT | ERR_FATAL;
7894 }
7895
Emeric Brun76d88952012-10-05 15:47:31 +02007896 free(conf->ciphers);
Willy Tarreau4348fad2012-09-20 16:48:07 +02007897 conf->ciphers = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007898 return 0;
7899}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007900static int bind_parse_ciphers(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7901{
7902 return ssl_bind_parse_ciphers(args, cur_arg, px, &conf->ssl_conf, err);
7903}
Dirkjan Bussink415150f2018-09-14 11:14:21 +02007904
Emmanuel Hocdet839af572019-05-14 16:27:35 +02007905#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02007906/* parse the "ciphersuites" bind keyword */
7907static int ssl_bind_parse_ciphersuites(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
7908{
7909 if (!*args[cur_arg + 1]) {
7910 memprintf(err, "'%s' : missing cipher suite", args[cur_arg]);
7911 return ERR_ALERT | ERR_FATAL;
7912 }
7913
7914 free(conf->ciphersuites);
7915 conf->ciphersuites = strdup(args[cur_arg + 1]);
7916 return 0;
7917}
7918static int bind_parse_ciphersuites(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7919{
7920 return ssl_bind_parse_ciphersuites(args, cur_arg, px, &conf->ssl_conf, err);
7921}
7922#endif
7923
Willy Tarreaub131c872019-10-16 16:42:19 +02007924/* parse the "crt" bind keyword. Returns a set of ERR_* flags possibly with an error in <err>. */
Willy Tarreau4348fad2012-09-20 16:48:07 +02007925static 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 +02007926{
Willy Tarreau38011032013-08-13 16:59:39 +02007927 char path[MAXPATHLEN];
Willy Tarreaub75d6922014-04-14 18:05:41 +02007928
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007929 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02007930 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007931 return ERR_ALERT | ERR_FATAL;
7932 }
7933
Willy Tarreauef934602016-12-22 23:12:01 +01007934 if ((*args[cur_arg + 1] != '/' ) && global_ssl.crt_base) {
7935 if ((strlen(global_ssl.crt_base) + 1 + strlen(args[cur_arg + 1]) + 1) > MAXPATHLEN) {
Emeric Brunc8e8d122012-10-02 18:42:10 +02007936 memprintf(err, "'%s' : path too long", args[cur_arg]);
7937 return ERR_ALERT | ERR_FATAL;
7938 }
Willy Tarreauef934602016-12-22 23:12:01 +01007939 snprintf(path, sizeof(path), "%s/%s", global_ssl.crt_base, args[cur_arg + 1]);
Willy Tarreaub131c872019-10-16 16:42:19 +02007940 return ssl_sock_load_cert(path, conf, err);
Emeric Brunc8e8d122012-10-02 18:42:10 +02007941 }
7942
Willy Tarreaub131c872019-10-16 16:42:19 +02007943 return ssl_sock_load_cert(args[cur_arg + 1], conf, err);
Emeric Brund94b3fe2012-09-20 18:23:56 +02007944}
7945
Willy Tarreaub131c872019-10-16 16:42:19 +02007946/* 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 +01007947static int bind_parse_crt_list(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7948{
Willy Tarreaub131c872019-10-16 16:42:19 +02007949 int err_code;
7950
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01007951 if (!*args[cur_arg + 1]) {
7952 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
7953 return ERR_ALERT | ERR_FATAL;
7954 }
7955
Willy Tarreaub131c872019-10-16 16:42:19 +02007956 err_code = ssl_sock_load_cert_list_file(args[cur_arg + 1], conf, px, err);
7957 if (err_code)
Willy Tarreauad1731d2013-04-02 17:35:58 +02007958 memprintf(err, "'%s' : %s", args[cur_arg], *err);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01007959
Willy Tarreaub131c872019-10-16 16:42:19 +02007960 return err_code;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01007961}
7962
Emeric Brunfb510ea2012-10-05 12:00:26 +02007963/* parse the "crl-file" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007964static 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 +02007965{
Emeric Brun051cdab2012-10-02 19:25:50 +02007966#ifndef X509_V_FLAG_CRL_CHECK
7967 if (err)
7968 memprintf(err, "'%s' : library does not support CRL verify", args[cur_arg]);
7969 return ERR_ALERT | ERR_FATAL;
7970#else
Emeric Brund94b3fe2012-09-20 18:23:56 +02007971 if (!*args[cur_arg + 1]) {
7972 if (err)
7973 memprintf(err, "'%s' : missing CRLfile path", args[cur_arg]);
7974 return ERR_ALERT | ERR_FATAL;
7975 }
Emeric Brun2b58d042012-09-20 17:10:03 +02007976
Willy Tarreauef934602016-12-22 23:12:01 +01007977 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
7978 memprintf(&conf->crl_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02007979 else
7980 memprintf(&conf->crl_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02007981
Emeric Brun2b58d042012-09-20 17:10:03 +02007982 return 0;
Emeric Brun051cdab2012-10-02 19:25:50 +02007983#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02007984}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007985static int bind_parse_crl_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7986{
7987 return ssl_bind_parse_crl_file(args, cur_arg, px, &conf->ssl_conf, err);
7988}
Emeric Brun2b58d042012-09-20 17:10:03 +02007989
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01007990/* parse the "curves" bind keyword keyword */
7991static int ssl_bind_parse_curves(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
7992{
Lukas Tribusd13e9252019-11-24 18:20:40 +01007993#if ((HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL) || defined(LIBRESSL_VERSION_NUMBER))
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01007994 if (!*args[cur_arg + 1]) {
7995 if (err)
7996 memprintf(err, "'%s' : missing curve suite", args[cur_arg]);
7997 return ERR_ALERT | ERR_FATAL;
7998 }
7999 conf->curves = strdup(args[cur_arg + 1]);
8000 return 0;
8001#else
8002 if (err)
8003 memprintf(err, "'%s' : library does not support curve suite", args[cur_arg]);
8004 return ERR_ALERT | ERR_FATAL;
8005#endif
8006}
8007static int bind_parse_curves(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8008{
8009 return ssl_bind_parse_curves(args, cur_arg, px, &conf->ssl_conf, err);
8010}
8011
Bertrand Jacquinff13c062016-11-13 16:37:11 +00008012/* parse the "ecdhe" bind keyword keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008013static 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 +02008014{
Willy Tarreau9a1ab082019-05-09 13:26:41 +02008015#if HA_OPENSSL_VERSION_NUMBER < 0x0090800fL
Emeric Brun2b58d042012-09-20 17:10:03 +02008016 if (err)
8017 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (too old)", args[cur_arg]);
8018 return ERR_ALERT | ERR_FATAL;
8019#elif defined(OPENSSL_NO_ECDH)
8020 if (err)
8021 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (disabled via OPENSSL_NO_ECDH)", args[cur_arg]);
8022 return ERR_ALERT | ERR_FATAL;
8023#else
8024 if (!*args[cur_arg + 1]) {
8025 if (err)
8026 memprintf(err, "'%s' : missing named curve", args[cur_arg]);
8027 return ERR_ALERT | ERR_FATAL;
8028 }
8029
8030 conf->ecdhe = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008031
8032 return 0;
Emeric Brun2b58d042012-09-20 17:10:03 +02008033#endif
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008034}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008035static int bind_parse_ecdhe(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8036{
8037 return ssl_bind_parse_ecdhe(args, cur_arg, px, &conf->ssl_conf, err);
8038}
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008039
Bertrand Jacquinff13c062016-11-13 16:37:11 +00008040/* parse the "crt-ignore-err" and "ca-ignore-err" bind keywords */
Emeric Brun81c00f02012-09-21 14:31:21 +02008041static int bind_parse_ignore_err(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8042{
8043 int code;
8044 char *p = args[cur_arg + 1];
8045 unsigned long long *ignerr = &conf->crt_ignerr;
8046
8047 if (!*p) {
8048 if (err)
8049 memprintf(err, "'%s' : missing error IDs list", args[cur_arg]);
8050 return ERR_ALERT | ERR_FATAL;
8051 }
8052
8053 if (strcmp(args[cur_arg], "ca-ignore-err") == 0)
8054 ignerr = &conf->ca_ignerr;
8055
8056 if (strcmp(p, "all") == 0) {
8057 *ignerr = ~0ULL;
8058 return 0;
8059 }
8060
8061 while (p) {
8062 code = atoi(p);
8063 if ((code <= 0) || (code > 63)) {
8064 if (err)
8065 memprintf(err, "'%s' : ID '%d' out of range (1..63) in error IDs list '%s'",
8066 args[cur_arg], code, args[cur_arg + 1]);
8067 return ERR_ALERT | ERR_FATAL;
8068 }
8069 *ignerr |= 1ULL << code;
8070 p = strchr(p, ',');
8071 if (p)
8072 p++;
8073 }
8074
Emeric Brun2cb7ae52012-10-05 14:14:21 +02008075 return 0;
8076}
8077
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008078/* parse tls_method_options "no-xxx" and "force-xxx" */
8079static int parse_tls_method_options(char *arg, struct tls_version_filter *methods, char **err)
Emeric Brun2cb7ae52012-10-05 14:14:21 +02008080{
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008081 uint16_t v;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008082 char *p;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008083 p = strchr(arg, '-');
8084 if (!p)
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008085 goto fail;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008086 p++;
8087 if (!strcmp(p, "sslv3"))
8088 v = CONF_SSLV3;
8089 else if (!strcmp(p, "tlsv10"))
8090 v = CONF_TLSV10;
8091 else if (!strcmp(p, "tlsv11"))
8092 v = CONF_TLSV11;
8093 else if (!strcmp(p, "tlsv12"))
8094 v = CONF_TLSV12;
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +02008095 else if (!strcmp(p, "tlsv13"))
8096 v = CONF_TLSV13;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008097 else
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008098 goto fail;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008099 if (!strncmp(arg, "no-", 3))
8100 methods->flags |= methodVersions[v].flag;
8101 else if (!strncmp(arg, "force-", 6))
8102 methods->min = methods->max = v;
8103 else
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008104 goto fail;
Emeric Brun2d0c4822012-10-02 13:45:20 +02008105 return 0;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008106 fail:
8107 if (err)
8108 memprintf(err, "'%s' : option not implemented", arg);
8109 return ERR_ALERT | ERR_FATAL;
Emeric Brun2d0c4822012-10-02 13:45:20 +02008110}
8111
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008112static 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 +02008113{
Emmanuel Hocdet43664762017-08-09 18:26:20 +02008114 return parse_tls_method_options(args[cur_arg], &conf->ssl_conf.ssl_methods, err);
Emeric Brun2cb7ae52012-10-05 14:14:21 +02008115}
8116
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008117static 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 +02008118{
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008119 return parse_tls_method_options(args[*cur_arg], &newsrv->ssl_ctx.methods, err);
8120}
8121
8122/* parse tls_method min/max: "ssl-min-ver" and "ssl-max-ver" */
8123static int parse_tls_method_minmax(char **args, int cur_arg, struct tls_version_filter *methods, char **err)
8124{
8125 uint16_t i, v = 0;
8126 char *argv = args[cur_arg + 1];
8127 if (!*argv) {
8128 if (err)
8129 memprintf(err, "'%s' : missing the ssl/tls version", args[cur_arg]);
8130 return ERR_ALERT | ERR_FATAL;
8131 }
8132 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
8133 if (!strcmp(argv, methodVersions[i].name))
8134 v = i;
8135 if (!v) {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008136 if (err)
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008137 memprintf(err, "'%s' : unknown ssl/tls version", args[cur_arg + 1]);
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008138 return ERR_ALERT | ERR_FATAL;
8139 }
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008140 if (!strcmp("ssl-min-ver", args[cur_arg]))
8141 methods->min = v;
8142 else if (!strcmp("ssl-max-ver", args[cur_arg]))
8143 methods->max = v;
8144 else {
8145 if (err)
8146 memprintf(err, "'%s' : option not implemented", args[cur_arg]);
8147 return ERR_ALERT | ERR_FATAL;
8148 }
Emeric Brun2cb7ae52012-10-05 14:14:21 +02008149 return 0;
Emeric Brun2cb7ae52012-10-05 14:14:21 +02008150}
Emeric Brun2cb7ae52012-10-05 14:14:21 +02008151
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02008152static int ssl_bind_parse_tls_method_minmax(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
8153{
Willy Tarreau9a1ab082019-05-09 13:26:41 +02008154#if (HA_OPENSSL_VERSION_NUMBER < 0x10101000L) && !defined(OPENSSL_IS_BORINGSSL)
Christopher Faulet767a84b2017-11-24 16:50:31 +01008155 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 +02008156#endif
8157 return parse_tls_method_minmax(args, cur_arg, &conf->ssl_methods, err);
8158}
8159
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008160static int bind_parse_tls_method_minmax(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8161{
Emmanuel Hocdet43664762017-08-09 18:26:20 +02008162 return parse_tls_method_minmax(args, cur_arg, &conf->ssl_conf.ssl_methods, err);
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008163}
8164
8165static int srv_parse_tls_method_minmax(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8166{
8167 return parse_tls_method_minmax(args, *cur_arg, &newsrv->ssl_ctx.methods, err);
8168}
8169
Emeric Brun2d0c4822012-10-02 13:45:20 +02008170/* parse the "no-tls-tickets" bind keyword */
Emmanuel Hocdet4608ed92017-01-20 13:06:27 +01008171static 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 +02008172{
Emeric Brun89675492012-10-05 13:48:26 +02008173 conf->ssl_options |= BC_SSL_O_NO_TLS_TICKETS;
Emeric Brun81c00f02012-09-21 14:31:21 +02008174 return 0;
8175}
Emeric Brun2d0c4822012-10-02 13:45:20 +02008176
Olivier Houchardc2aae742017-09-22 18:26:28 +02008177/* parse the "allow-0rtt" bind keyword */
8178static int ssl_bind_parse_allow_0rtt(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
8179{
8180 conf->early_data = 1;
8181 return 0;
8182}
8183
8184static int bind_parse_allow_0rtt(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8185{
Olivier Houchard9679ac92017-10-27 14:58:08 +02008186 conf->ssl_conf.early_data = 1;
Olivier Houchardc2aae742017-09-22 18:26:28 +02008187 return 0;
8188}
8189
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02008190/* parse the "npn" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008191static 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 +02008192{
Bernard Spil13c53f82018-02-15 13:34:58 +01008193#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02008194 char *p1, *p2;
8195
8196 if (!*args[cur_arg + 1]) {
8197 memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[cur_arg]);
8198 return ERR_ALERT | ERR_FATAL;
8199 }
8200
8201 free(conf->npn_str);
8202
Willy Tarreau3724da12016-02-12 17:11:12 +01008203 /* the NPN string is built as a suite of (<len> <name>)*,
8204 * so we reuse each comma to store the next <len> and need
8205 * one more for the end of the string.
8206 */
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02008207 conf->npn_len = strlen(args[cur_arg + 1]) + 1;
Willy Tarreau3724da12016-02-12 17:11:12 +01008208 conf->npn_str = calloc(1, conf->npn_len + 1);
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02008209 memcpy(conf->npn_str + 1, args[cur_arg + 1], conf->npn_len);
8210
8211 /* replace commas with the name length */
8212 p1 = conf->npn_str;
8213 p2 = p1 + 1;
8214 while (1) {
8215 p2 = memchr(p1 + 1, ',', conf->npn_str + conf->npn_len - (p1 + 1));
8216 if (!p2)
8217 p2 = p1 + 1 + strlen(p1 + 1);
8218
8219 if (p2 - (p1 + 1) > 255) {
8220 *p2 = '\0';
8221 memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
8222 return ERR_ALERT | ERR_FATAL;
8223 }
8224
8225 *p1 = p2 - (p1 + 1);
8226 p1 = p2;
8227
8228 if (!*p2)
8229 break;
8230
8231 *(p2++) = '\0';
8232 }
8233 return 0;
8234#else
8235 if (err)
8236 memprintf(err, "'%s' : library does not support TLS NPN extension", args[cur_arg]);
8237 return ERR_ALERT | ERR_FATAL;
8238#endif
8239}
8240
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008241static int bind_parse_npn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8242{
8243 return ssl_bind_parse_npn(args, cur_arg, px, &conf->ssl_conf, err);
8244}
8245
Willy Tarreauab861d32013-04-02 02:30:41 +02008246/* parse the "alpn" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008247static 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 +02008248{
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01008249#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02008250 char *p1, *p2;
8251
8252 if (!*args[cur_arg + 1]) {
8253 memprintf(err, "'%s' : missing the comma-delimited ALPN protocol suite", args[cur_arg]);
8254 return ERR_ALERT | ERR_FATAL;
8255 }
8256
8257 free(conf->alpn_str);
8258
Marcoen Hirschbergbef60912016-02-12 17:05:24 +01008259 /* the ALPN string is built as a suite of (<len> <name>)*,
8260 * so we reuse each comma to store the next <len> and need
8261 * one more for the end of the string.
8262 */
Willy Tarreauab861d32013-04-02 02:30:41 +02008263 conf->alpn_len = strlen(args[cur_arg + 1]) + 1;
Marcoen Hirschbergbef60912016-02-12 17:05:24 +01008264 conf->alpn_str = calloc(1, conf->alpn_len + 1);
Willy Tarreauab861d32013-04-02 02:30:41 +02008265 memcpy(conf->alpn_str + 1, args[cur_arg + 1], conf->alpn_len);
8266
8267 /* replace commas with the name length */
8268 p1 = conf->alpn_str;
8269 p2 = p1 + 1;
8270 while (1) {
8271 p2 = memchr(p1 + 1, ',', conf->alpn_str + conf->alpn_len - (p1 + 1));
8272 if (!p2)
8273 p2 = p1 + 1 + strlen(p1 + 1);
8274
8275 if (p2 - (p1 + 1) > 255) {
8276 *p2 = '\0';
8277 memprintf(err, "'%s' : ALPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
8278 return ERR_ALERT | ERR_FATAL;
8279 }
8280
8281 *p1 = p2 - (p1 + 1);
8282 p1 = p2;
8283
8284 if (!*p2)
8285 break;
8286
8287 *(p2++) = '\0';
8288 }
8289 return 0;
8290#else
8291 if (err)
8292 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[cur_arg]);
8293 return ERR_ALERT | ERR_FATAL;
8294#endif
8295}
8296
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008297static int bind_parse_alpn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8298{
8299 return ssl_bind_parse_alpn(args, cur_arg, px, &conf->ssl_conf, err);
8300}
8301
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008302/* parse the "ssl" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02008303static 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 +02008304{
Willy Tarreau71a8c7c2016-12-21 22:04:54 +01008305 conf->xprt = &ssl_sock;
Willy Tarreau4348fad2012-09-20 16:48:07 +02008306 conf->is_ssl = 1;
Emeric Brun76d88952012-10-05 15:47:31 +02008307
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008308 if (global_ssl.listen_default_ciphers && !conf->ssl_conf.ciphers)
8309 conf->ssl_conf.ciphers = strdup(global_ssl.listen_default_ciphers);
Emmanuel Hocdet839af572019-05-14 16:27:35 +02008310#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02008311 if (global_ssl.listen_default_ciphersuites && !conf->ssl_conf.ciphersuites)
8312 conf->ssl_conf.ciphersuites = strdup(global_ssl.listen_default_ciphersuites);
8313#endif
Emmanuel Hocdet4608ed92017-01-20 13:06:27 +01008314 conf->ssl_options |= global_ssl.listen_default_ssloptions;
Emmanuel Hocdet43664762017-08-09 18:26:20 +02008315 conf->ssl_conf.ssl_methods.flags |= global_ssl.listen_default_sslmethods.flags;
8316 if (!conf->ssl_conf.ssl_methods.min)
8317 conf->ssl_conf.ssl_methods.min = global_ssl.listen_default_sslmethods.min;
8318 if (!conf->ssl_conf.ssl_methods.max)
8319 conf->ssl_conf.ssl_methods.max = global_ssl.listen_default_sslmethods.max;
Emeric Brun76d88952012-10-05 15:47:31 +02008320
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008321 return 0;
8322}
8323
Lukas Tribus53ae85c2017-05-04 15:45:40 +00008324/* parse the "prefer-client-ciphers" bind keyword */
8325static int bind_parse_pcc(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8326{
8327 conf->ssl_options |= BC_SSL_O_PREF_CLIE_CIPH;
8328 return 0;
8329}
8330
Christopher Faulet31af49d2015-06-09 17:29:50 +02008331/* parse the "generate-certificates" bind keyword */
8332static int bind_parse_generate_certs(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8333{
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01008334#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Christopher Faulet31af49d2015-06-09 17:29:50 +02008335 conf->generate_certs = 1;
8336#else
8337 memprintf(err, "%sthis version of openssl cannot generate SSL certificates.\n",
8338 err && *err ? *err : "");
8339#endif
8340 return 0;
8341}
8342
Emmanuel Hocdet65623372013-01-24 17:17:15 +01008343/* parse the "strict-sni" bind keyword */
8344static int bind_parse_strict_sni(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8345{
8346 conf->strict_sni = 1;
8347 return 0;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008348}
8349
8350/* parse the "tls-ticket-keys" bind keyword */
8351static int bind_parse_tls_ticket_keys(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8352{
8353#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
Christopher Faulet2bbc80d2019-10-21 09:55:49 +02008354 FILE *f = NULL;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008355 int i = 0;
8356 char thisline[LINESIZE];
Christopher Faulet2bbc80d2019-10-21 09:55:49 +02008357 struct tls_keys_ref *keys_ref = NULL;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008358
8359 if (!*args[cur_arg + 1]) {
8360 if (err)
8361 memprintf(err, "'%s' : missing TLS ticket keys file path", args[cur_arg]);
Christopher Faulet2bbc80d2019-10-21 09:55:49 +02008362 goto fail;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008363 }
8364
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02008365 keys_ref = tlskeys_ref_lookup(args[cur_arg + 1]);
Willy Tarreau17b4aa12018-07-17 10:05:32 +02008366 if (keys_ref) {
8367 keys_ref->refcount++;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02008368 conf->keys_ref = keys_ref;
8369 return 0;
8370 }
8371
Christopher Faulet2bbc80d2019-10-21 09:55:49 +02008372 keys_ref = calloc(1, sizeof(*keys_ref));
Emeric Brun09852f72019-01-10 10:51:13 +01008373 if (!keys_ref) {
8374 if (err)
8375 memprintf(err, "'%s' : allocation error", args[cur_arg+1]);
Christopher Faulet2bbc80d2019-10-21 09:55:49 +02008376 goto fail;
Emeric Brun09852f72019-01-10 10:51:13 +01008377 }
8378
Emeric Brun9e754772019-01-10 17:51:55 +01008379 keys_ref->tlskeys = malloc(TLS_TICKETS_NO * sizeof(union tls_sess_key));
Emeric Brun09852f72019-01-10 10:51:13 +01008380 if (!keys_ref->tlskeys) {
Emeric Brun09852f72019-01-10 10:51:13 +01008381 if (err)
8382 memprintf(err, "'%s' : allocation error", args[cur_arg+1]);
Christopher Faulet2bbc80d2019-10-21 09:55:49 +02008383 goto fail;
Emeric Brun09852f72019-01-10 10:51:13 +01008384 }
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008385
8386 if ((f = fopen(args[cur_arg + 1], "r")) == NULL) {
8387 if (err)
8388 memprintf(err, "'%s' : unable to load ssl tickets keys file", args[cur_arg+1]);
Christopher Faulet2bbc80d2019-10-21 09:55:49 +02008389 goto fail;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008390 }
8391
Nenad Merdanovic146defa2015-05-09 08:46:00 +02008392 keys_ref->filename = strdup(args[cur_arg + 1]);
Emeric Brun09852f72019-01-10 10:51:13 +01008393 if (!keys_ref->filename) {
Emeric Brun09852f72019-01-10 10:51:13 +01008394 if (err)
8395 memprintf(err, "'%s' : allocation error", args[cur_arg+1]);
Christopher Faulet2bbc80d2019-10-21 09:55:49 +02008396 goto fail;
Emeric Brun09852f72019-01-10 10:51:13 +01008397 }
Nenad Merdanovic146defa2015-05-09 08:46:00 +02008398
Emeric Brun9e754772019-01-10 17:51:55 +01008399 keys_ref->key_size_bits = 0;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008400 while (fgets(thisline, sizeof(thisline), f) != NULL) {
8401 int len = strlen(thisline);
Emeric Brun9e754772019-01-10 17:51:55 +01008402 int dec_size;
8403
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008404 /* Strip newline characters from the end */
8405 if(thisline[len - 1] == '\n')
8406 thisline[--len] = 0;
8407
8408 if(thisline[len - 1] == '\r')
8409 thisline[--len] = 0;
8410
Emeric Brun9e754772019-01-10 17:51:55 +01008411 dec_size = base64dec(thisline, len, (char *) (keys_ref->tlskeys + i % TLS_TICKETS_NO), sizeof(union tls_sess_key));
8412 if (dec_size < 0) {
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008413 if (err)
8414 memprintf(err, "'%s' : unable to decode base64 key on line %d", args[cur_arg+1], i + 1);
Christopher Faulet2bbc80d2019-10-21 09:55:49 +02008415 goto fail;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008416 }
Emeric Brun9e754772019-01-10 17:51:55 +01008417 else if (!keys_ref->key_size_bits && (dec_size == sizeof(struct tls_sess_key_128))) {
8418 keys_ref->key_size_bits = 128;
8419 }
8420 else if (!keys_ref->key_size_bits && (dec_size == sizeof(struct tls_sess_key_256))) {
8421 keys_ref->key_size_bits = 256;
8422 }
8423 else if (((dec_size != sizeof(struct tls_sess_key_128)) && (dec_size != sizeof(struct tls_sess_key_256)))
8424 || ((dec_size == sizeof(struct tls_sess_key_128) && (keys_ref->key_size_bits != 128)))
8425 || ((dec_size == sizeof(struct tls_sess_key_256) && (keys_ref->key_size_bits != 256)))) {
Emeric Brun9e754772019-01-10 17:51:55 +01008426 if (err)
8427 memprintf(err, "'%s' : wrong sized key on line %d", args[cur_arg+1], i + 1);
Christopher Faulet2bbc80d2019-10-21 09:55:49 +02008428 goto fail;
Emeric Brun9e754772019-01-10 17:51:55 +01008429 }
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008430 i++;
8431 }
8432
8433 if (i < TLS_TICKETS_NO) {
8434 if (err)
8435 memprintf(err, "'%s' : please supply at least %d keys in the tls-tickets-file", args[cur_arg+1], TLS_TICKETS_NO);
Christopher Faulet2bbc80d2019-10-21 09:55:49 +02008436 goto fail;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008437 }
8438
8439 fclose(f);
8440
8441 /* Use penultimate key for encryption, handle when TLS_TICKETS_NO = 1 */
Nenad Merdanovic17891152016-03-25 22:16:57 +01008442 i -= 2;
8443 keys_ref->tls_ticket_enc_index = i < 0 ? 0 : i % TLS_TICKETS_NO;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02008444 keys_ref->unique_id = -1;
Willy Tarreau17b4aa12018-07-17 10:05:32 +02008445 keys_ref->refcount = 1;
Christopher Faulet16f45c82018-02-16 11:23:49 +01008446 HA_RWLOCK_INIT(&keys_ref->lock);
Nenad Merdanovic146defa2015-05-09 08:46:00 +02008447 conf->keys_ref = keys_ref;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008448
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02008449 LIST_ADD(&tlskeys_reference, &keys_ref->list);
8450
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008451 return 0;
Christopher Faulet2bbc80d2019-10-21 09:55:49 +02008452
8453 fail:
8454 if (f)
8455 fclose(f);
8456 if (keys_ref) {
8457 free(keys_ref->filename);
8458 free(keys_ref->tlskeys);
8459 free(keys_ref);
8460 }
8461 return ERR_ALERT | ERR_FATAL;
8462
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008463#else
8464 if (err)
8465 memprintf(err, "'%s' : TLS ticket callback extension not supported", args[cur_arg]);
8466 return ERR_ALERT | ERR_FATAL;
8467#endif /* SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB */
Emmanuel Hocdet65623372013-01-24 17:17:15 +01008468}
8469
Emeric Brund94b3fe2012-09-20 18:23:56 +02008470/* parse the "verify" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008471static 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 +02008472{
8473 if (!*args[cur_arg + 1]) {
8474 if (err)
8475 memprintf(err, "'%s' : missing verify method", args[cur_arg]);
8476 return ERR_ALERT | ERR_FATAL;
8477 }
8478
8479 if (strcmp(args[cur_arg + 1], "none") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01008480 conf->verify = SSL_SOCK_VERIFY_NONE;
Emeric Brund94b3fe2012-09-20 18:23:56 +02008481 else if (strcmp(args[cur_arg + 1], "optional") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01008482 conf->verify = SSL_SOCK_VERIFY_OPTIONAL;
Emeric Brund94b3fe2012-09-20 18:23:56 +02008483 else if (strcmp(args[cur_arg + 1], "required") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01008484 conf->verify = SSL_SOCK_VERIFY_REQUIRED;
Emeric Brund94b3fe2012-09-20 18:23:56 +02008485 else {
8486 if (err)
8487 memprintf(err, "'%s' : unknown verify method '%s', only 'none', 'optional', and 'required' are supported\n",
8488 args[cur_arg], args[cur_arg + 1]);
8489 return ERR_ALERT | ERR_FATAL;
8490 }
8491
8492 return 0;
8493}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008494static int bind_parse_verify(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8495{
8496 return ssl_bind_parse_verify(args, cur_arg, px, &conf->ssl_conf, err);
8497}
Emeric Brund94b3fe2012-09-20 18:23:56 +02008498
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02008499/* parse the "no-ca-names" bind keyword */
8500static int ssl_bind_parse_no_ca_names(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
8501{
8502 conf->no_ca_names = 1;
8503 return 0;
8504}
8505static int bind_parse_no_ca_names(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8506{
8507 return ssl_bind_parse_no_ca_names(args, cur_arg, px, &conf->ssl_conf, err);
8508}
8509
Willy Tarreau92faadf2012-10-10 23:04:25 +02008510/************** "server" keywords ****************/
8511
Olivier Houchardc7566002018-11-20 23:33:50 +01008512/* parse the "npn" bind keyword */
8513static int srv_parse_npn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8514{
8515#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
8516 char *p1, *p2;
8517
8518 if (!*args[*cur_arg + 1]) {
8519 memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[*cur_arg]);
8520 return ERR_ALERT | ERR_FATAL;
8521 }
8522
8523 free(newsrv->ssl_ctx.npn_str);
8524
8525 /* the NPN string is built as a suite of (<len> <name>)*,
8526 * so we reuse each comma to store the next <len> and need
8527 * one more for the end of the string.
8528 */
8529 newsrv->ssl_ctx.npn_len = strlen(args[*cur_arg + 1]) + 1;
8530 newsrv->ssl_ctx.npn_str = calloc(1, newsrv->ssl_ctx.npn_len + 1);
8531 memcpy(newsrv->ssl_ctx.npn_str + 1, args[*cur_arg + 1],
8532 newsrv->ssl_ctx.npn_len);
8533
8534 /* replace commas with the name length */
8535 p1 = newsrv->ssl_ctx.npn_str;
8536 p2 = p1 + 1;
8537 while (1) {
8538 p2 = memchr(p1 + 1, ',', newsrv->ssl_ctx.npn_str +
8539 newsrv->ssl_ctx.npn_len - (p1 + 1));
8540 if (!p2)
8541 p2 = p1 + 1 + strlen(p1 + 1);
8542
8543 if (p2 - (p1 + 1) > 255) {
8544 *p2 = '\0';
8545 memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[*cur_arg], p1 + 1);
8546 return ERR_ALERT | ERR_FATAL;
8547 }
8548
8549 *p1 = p2 - (p1 + 1);
8550 p1 = p2;
8551
8552 if (!*p2)
8553 break;
8554
8555 *(p2++) = '\0';
8556 }
8557 return 0;
8558#else
8559 if (err)
8560 memprintf(err, "'%s' : library does not support TLS NPN extension", args[*cur_arg]);
8561 return ERR_ALERT | ERR_FATAL;
8562#endif
8563}
8564
Olivier Houchard92150142018-12-21 19:47:01 +01008565/* parse the "alpn" or the "check-alpn" server keyword */
Olivier Houchardc7566002018-11-20 23:33:50 +01008566static int srv_parse_alpn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8567{
8568#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
8569 char *p1, *p2;
Olivier Houchard92150142018-12-21 19:47:01 +01008570 char **alpn_str;
8571 int *alpn_len;
Olivier Houchardc7566002018-11-20 23:33:50 +01008572
Olivier Houchard92150142018-12-21 19:47:01 +01008573 if (*args[*cur_arg] == 'c') {
8574 alpn_str = &newsrv->check.alpn_str;
8575 alpn_len = &newsrv->check.alpn_len;
8576 } else {
8577 alpn_str = &newsrv->ssl_ctx.alpn_str;
8578 alpn_len = &newsrv->ssl_ctx.alpn_len;
8579
8580 }
Olivier Houchardc7566002018-11-20 23:33:50 +01008581 if (!*args[*cur_arg + 1]) {
8582 memprintf(err, "'%s' : missing the comma-delimited ALPN protocol suite", args[*cur_arg]);
8583 return ERR_ALERT | ERR_FATAL;
8584 }
8585
Olivier Houchard92150142018-12-21 19:47:01 +01008586 free(*alpn_str);
Olivier Houchardc7566002018-11-20 23:33:50 +01008587
8588 /* the ALPN string is built as a suite of (<len> <name>)*,
8589 * so we reuse each comma to store the next <len> and need
8590 * one more for the end of the string.
8591 */
Olivier Houchard92150142018-12-21 19:47:01 +01008592 *alpn_len = strlen(args[*cur_arg + 1]) + 1;
8593 *alpn_str = calloc(1, *alpn_len + 1);
8594 memcpy(*alpn_str + 1, args[*cur_arg + 1], *alpn_len);
Olivier Houchardc7566002018-11-20 23:33:50 +01008595
8596 /* replace commas with the name length */
Olivier Houchard92150142018-12-21 19:47:01 +01008597 p1 = *alpn_str;
Olivier Houchardc7566002018-11-20 23:33:50 +01008598 p2 = p1 + 1;
8599 while (1) {
Olivier Houchard92150142018-12-21 19:47:01 +01008600 p2 = memchr(p1 + 1, ',', *alpn_str + *alpn_len - (p1 + 1));
Olivier Houchardc7566002018-11-20 23:33:50 +01008601 if (!p2)
8602 p2 = p1 + 1 + strlen(p1 + 1);
8603
8604 if (p2 - (p1 + 1) > 255) {
8605 *p2 = '\0';
8606 memprintf(err, "'%s' : ALPN protocol name too long : '%s'", args[*cur_arg], p1 + 1);
8607 return ERR_ALERT | ERR_FATAL;
8608 }
8609
8610 *p1 = p2 - (p1 + 1);
8611 p1 = p2;
8612
8613 if (!*p2)
8614 break;
8615
8616 *(p2++) = '\0';
8617 }
8618 return 0;
8619#else
8620 if (err)
8621 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[*cur_arg]);
8622 return ERR_ALERT | ERR_FATAL;
8623#endif
8624}
8625
Emeric Brunef42d922012-10-11 16:11:36 +02008626/* parse the "ca-file" server keyword */
8627static int srv_parse_ca_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8628{
8629 if (!*args[*cur_arg + 1]) {
8630 if (err)
8631 memprintf(err, "'%s' : missing CAfile path", args[*cur_arg]);
8632 return ERR_ALERT | ERR_FATAL;
8633 }
8634
Willy Tarreauef934602016-12-22 23:12:01 +01008635 if ((*args[*cur_arg + 1] != '/') && global_ssl.ca_base)
8636 memprintf(&newsrv->ssl_ctx.ca_file, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02008637 else
8638 memprintf(&newsrv->ssl_ctx.ca_file, "%s", args[*cur_arg + 1]);
8639
8640 return 0;
8641}
8642
Olivier Houchard9130a962017-10-17 17:33:43 +02008643/* parse the "check-sni" server keyword */
8644static int srv_parse_check_sni(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8645{
8646 if (!*args[*cur_arg + 1]) {
8647 if (err)
8648 memprintf(err, "'%s' : missing SNI", args[*cur_arg]);
8649 return ERR_ALERT | ERR_FATAL;
8650 }
8651
8652 newsrv->check.sni = strdup(args[*cur_arg + 1]);
8653 if (!newsrv->check.sni) {
8654 memprintf(err, "'%s' : failed to allocate memory", args[*cur_arg]);
8655 return ERR_ALERT | ERR_FATAL;
8656 }
8657 return 0;
8658
8659}
8660
Willy Tarreau92faadf2012-10-10 23:04:25 +02008661/* parse the "check-ssl" server keyword */
8662static int srv_parse_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8663{
8664 newsrv->check.use_ssl = 1;
Willy Tarreauef934602016-12-22 23:12:01 +01008665 if (global_ssl.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
8666 newsrv->ssl_ctx.ciphers = strdup(global_ssl.connect_default_ciphers);
Emmanuel Hocdet839af572019-05-14 16:27:35 +02008667#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02008668 if (global_ssl.connect_default_ciphersuites && !newsrv->ssl_ctx.ciphersuites)
8669 newsrv->ssl_ctx.ciphersuites = strdup(global_ssl.connect_default_ciphersuites);
8670#endif
Willy Tarreauef934602016-12-22 23:12:01 +01008671 newsrv->ssl_ctx.options |= global_ssl.connect_default_ssloptions;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008672 newsrv->ssl_ctx.methods.flags |= global_ssl.connect_default_sslmethods.flags;
8673 if (!newsrv->ssl_ctx.methods.min)
8674 newsrv->ssl_ctx.methods.min = global_ssl.connect_default_sslmethods.min;
8675 if (!newsrv->ssl_ctx.methods.max)
8676 newsrv->ssl_ctx.methods.max = global_ssl.connect_default_sslmethods.max;
8677
Willy Tarreau92faadf2012-10-10 23:04:25 +02008678 return 0;
8679}
8680
8681/* parse the "ciphers" server keyword */
8682static int srv_parse_ciphers(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8683{
8684 if (!*args[*cur_arg + 1]) {
8685 memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
8686 return ERR_ALERT | ERR_FATAL;
8687 }
8688
8689 free(newsrv->ssl_ctx.ciphers);
8690 newsrv->ssl_ctx.ciphers = strdup(args[*cur_arg + 1]);
8691 return 0;
8692}
Dirkjan Bussink415150f2018-09-14 11:14:21 +02008693
Emmanuel Hocdet839af572019-05-14 16:27:35 +02008694#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02008695/* parse the "ciphersuites" server keyword */
8696static int srv_parse_ciphersuites(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8697{
8698 if (!*args[*cur_arg + 1]) {
8699 memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
8700 return ERR_ALERT | ERR_FATAL;
8701 }
8702
8703 free(newsrv->ssl_ctx.ciphersuites);
8704 newsrv->ssl_ctx.ciphersuites = strdup(args[*cur_arg + 1]);
8705 return 0;
8706}
8707#endif
Willy Tarreau92faadf2012-10-10 23:04:25 +02008708
Emeric Brunef42d922012-10-11 16:11:36 +02008709/* parse the "crl-file" server keyword */
8710static int srv_parse_crl_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8711{
8712#ifndef X509_V_FLAG_CRL_CHECK
8713 if (err)
8714 memprintf(err, "'%s' : library does not support CRL verify", args[*cur_arg]);
8715 return ERR_ALERT | ERR_FATAL;
8716#else
8717 if (!*args[*cur_arg + 1]) {
8718 if (err)
8719 memprintf(err, "'%s' : missing CRLfile path", args[*cur_arg]);
8720 return ERR_ALERT | ERR_FATAL;
8721 }
8722
Willy Tarreauef934602016-12-22 23:12:01 +01008723 if ((*args[*cur_arg + 1] != '/') && global_ssl.ca_base)
8724 memprintf(&newsrv->ssl_ctx.crl_file, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02008725 else
8726 memprintf(&newsrv->ssl_ctx.crl_file, "%s", args[*cur_arg + 1]);
8727
8728 return 0;
8729#endif
8730}
8731
Emeric Bruna7aa3092012-10-26 12:58:00 +02008732/* parse the "crt" server keyword */
8733static int srv_parse_crt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8734{
8735 if (!*args[*cur_arg + 1]) {
8736 if (err)
8737 memprintf(err, "'%s' : missing certificate file path", args[*cur_arg]);
8738 return ERR_ALERT | ERR_FATAL;
8739 }
8740
Willy Tarreauef934602016-12-22 23:12:01 +01008741 if ((*args[*cur_arg + 1] != '/') && global_ssl.crt_base)
Christopher Fauletff3a41e2017-11-23 09:13:32 +01008742 memprintf(&newsrv->ssl_ctx.client_crt, "%s/%s", global_ssl.crt_base, args[*cur_arg + 1]);
Emeric Bruna7aa3092012-10-26 12:58:00 +02008743 else
8744 memprintf(&newsrv->ssl_ctx.client_crt, "%s", args[*cur_arg + 1]);
8745
8746 return 0;
8747}
Emeric Brunef42d922012-10-11 16:11:36 +02008748
Frédéric Lécaille340ae602017-03-13 10:38:04 +01008749/* parse the "no-check-ssl" server keyword */
8750static int srv_parse_no_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8751{
Christopher Faulet68d35ae2020-03-27 18:55:49 +01008752 newsrv->check.use_ssl = -1;
Frédéric Lécaille340ae602017-03-13 10:38:04 +01008753 free(newsrv->ssl_ctx.ciphers);
8754 newsrv->ssl_ctx.ciphers = NULL;
8755 newsrv->ssl_ctx.options &= ~global_ssl.connect_default_ssloptions;
8756 return 0;
8757}
8758
Frédéric Lécaillee892c4c2017-03-13 12:08:01 +01008759/* parse the "no-send-proxy-v2-ssl" server keyword */
8760static int srv_parse_no_send_proxy_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8761{
8762 newsrv->pp_opts &= ~SRV_PP_V2;
8763 newsrv->pp_opts &= ~SRV_PP_V2_SSL;
8764 return 0;
8765}
8766
8767/* parse the "no-send-proxy-v2-ssl-cn" server keyword */
8768static int srv_parse_no_send_proxy_cn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8769{
8770 newsrv->pp_opts &= ~SRV_PP_V2;
8771 newsrv->pp_opts &= ~SRV_PP_V2_SSL;
8772 newsrv->pp_opts &= ~SRV_PP_V2_SSL_CN;
8773 return 0;
8774}
8775
Frédéric Lécaillee381d762017-03-13 11:54:17 +01008776/* parse the "no-ssl" server keyword */
8777static int srv_parse_no_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8778{
Christopher Faulet68d35ae2020-03-27 18:55:49 +01008779 newsrv->use_ssl = -1;
Frédéric Lécaillee381d762017-03-13 11:54:17 +01008780 free(newsrv->ssl_ctx.ciphers);
8781 newsrv->ssl_ctx.ciphers = NULL;
8782 return 0;
8783}
8784
Olivier Houchard522eea72017-11-03 16:27:47 +01008785/* parse the "allow-0rtt" server keyword */
8786static int srv_parse_allow_0rtt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8787{
8788 newsrv->ssl_ctx.options |= SRV_SSL_O_EARLY_DATA;
8789 return 0;
8790}
8791
Willy Tarreau2a3fb1c2015-02-05 16:47:07 +01008792/* parse the "no-ssl-reuse" server keyword */
8793static int srv_parse_no_ssl_reuse(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8794{
8795 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_REUSE;
8796 return 0;
8797}
8798
Emeric Brunf9c5c472012-10-11 15:28:34 +02008799/* parse the "no-tls-tickets" server keyword */
8800static int srv_parse_no_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8801{
8802 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLS_TICKETS;
8803 return 0;
8804}
David Safb76832014-05-08 23:42:08 -04008805/* parse the "send-proxy-v2-ssl" server keyword */
8806static int srv_parse_send_proxy_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8807{
8808 newsrv->pp_opts |= SRV_PP_V2;
8809 newsrv->pp_opts |= SRV_PP_V2_SSL;
8810 return 0;
8811}
8812
8813/* parse the "send-proxy-v2-ssl-cn" server keyword */
8814static int srv_parse_send_proxy_cn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8815{
8816 newsrv->pp_opts |= SRV_PP_V2;
8817 newsrv->pp_opts |= SRV_PP_V2_SSL;
8818 newsrv->pp_opts |= SRV_PP_V2_SSL_CN;
8819 return 0;
8820}
Emeric Brunf9c5c472012-10-11 15:28:34 +02008821
Willy Tarreau732eac42015-07-09 11:40:25 +02008822/* parse the "sni" server keyword */
8823static int srv_parse_sni(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8824{
8825#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
8826 memprintf(err, "'%s' : the current SSL library doesn't support the SNI TLS extension", args[*cur_arg]);
8827 return ERR_ALERT | ERR_FATAL;
8828#else
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01008829 char *arg;
Willy Tarreau732eac42015-07-09 11:40:25 +02008830
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01008831 arg = args[*cur_arg + 1];
8832 if (!*arg) {
Willy Tarreau732eac42015-07-09 11:40:25 +02008833 memprintf(err, "'%s' : missing sni expression", args[*cur_arg]);
8834 return ERR_ALERT | ERR_FATAL;
8835 }
8836
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01008837 free(newsrv->sni_expr);
8838 newsrv->sni_expr = strdup(arg);
Willy Tarreau732eac42015-07-09 11:40:25 +02008839
Willy Tarreau732eac42015-07-09 11:40:25 +02008840 return 0;
8841#endif
8842}
8843
Willy Tarreau92faadf2012-10-10 23:04:25 +02008844/* parse the "ssl" server keyword */
8845static int srv_parse_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8846{
8847 newsrv->use_ssl = 1;
Willy Tarreauef934602016-12-22 23:12:01 +01008848 if (global_ssl.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
8849 newsrv->ssl_ctx.ciphers = strdup(global_ssl.connect_default_ciphers);
Emmanuel Hocdet839af572019-05-14 16:27:35 +02008850#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02008851 if (global_ssl.connect_default_ciphersuites && !newsrv->ssl_ctx.ciphersuites)
8852 newsrv->ssl_ctx.ciphersuites = strdup(global_ssl.connect_default_ciphersuites);
8853#endif
Jerome Magnin770bc8a2020-04-22 11:40:18 +02008854 newsrv->ssl_ctx.options |= global_ssl.connect_default_ssloptions;
8855 newsrv->ssl_ctx.methods.flags |= global_ssl.connect_default_sslmethods.flags;
8856
8857 if (!newsrv->ssl_ctx.methods.min)
8858 newsrv->ssl_ctx.methods.min = global_ssl.connect_default_sslmethods.min;
8859
8860 if (!newsrv->ssl_ctx.methods.max)
8861 newsrv->ssl_ctx.methods.max = global_ssl.connect_default_sslmethods.max;
8862
8863
Willy Tarreau92faadf2012-10-10 23:04:25 +02008864 return 0;
8865}
8866
Frédéric Lécaille2cfcdbe2017-03-13 11:32:20 +01008867/* parse the "ssl-reuse" server keyword */
8868static int srv_parse_ssl_reuse(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8869{
8870 newsrv->ssl_ctx.options &= ~SRV_SSL_O_NO_REUSE;
8871 return 0;
8872}
8873
Frédéric Lécaille2cfcdbe2017-03-13 11:32:20 +01008874/* parse the "tls-tickets" server keyword */
8875static int srv_parse_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8876{
8877 newsrv->ssl_ctx.options &= ~SRV_SSL_O_NO_TLS_TICKETS;
8878 return 0;
8879}
8880
Emeric Brunef42d922012-10-11 16:11:36 +02008881/* parse the "verify" server keyword */
8882static int srv_parse_verify(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8883{
8884 if (!*args[*cur_arg + 1]) {
8885 if (err)
8886 memprintf(err, "'%s' : missing verify method", args[*cur_arg]);
8887 return ERR_ALERT | ERR_FATAL;
8888 }
8889
8890 if (strcmp(args[*cur_arg + 1], "none") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01008891 newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_NONE;
Emeric Brunef42d922012-10-11 16:11:36 +02008892 else if (strcmp(args[*cur_arg + 1], "required") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01008893 newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_REQUIRED;
Emeric Brunef42d922012-10-11 16:11:36 +02008894 else {
8895 if (err)
8896 memprintf(err, "'%s' : unknown verify method '%s', only 'none' and 'required' are supported\n",
8897 args[*cur_arg], args[*cur_arg + 1]);
8898 return ERR_ALERT | ERR_FATAL;
8899 }
8900
Evan Broderbe554312013-06-27 00:05:25 -07008901 return 0;
8902}
8903
8904/* parse the "verifyhost" server keyword */
8905static int srv_parse_verifyhost(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8906{
8907 if (!*args[*cur_arg + 1]) {
8908 if (err)
8909 memprintf(err, "'%s' : missing hostname to verify against", args[*cur_arg]);
8910 return ERR_ALERT | ERR_FATAL;
8911 }
8912
Frédéric Lécaille273f3212017-03-13 15:52:01 +01008913 free(newsrv->ssl_ctx.verify_host);
Evan Broderbe554312013-06-27 00:05:25 -07008914 newsrv->ssl_ctx.verify_host = strdup(args[*cur_arg + 1]);
8915
Emeric Brunef42d922012-10-11 16:11:36 +02008916 return 0;
8917}
8918
Emeric Brun2c86cbf2014-10-30 15:56:50 +01008919/* parse the "ssl-default-bind-options" keyword in global section */
8920static int ssl_parse_default_bind_options(char **args, int section_type, struct proxy *curpx,
8921 struct proxy *defpx, const char *file, int line,
8922 char **err) {
8923 int i = 1;
8924
8925 if (*(args[i]) == 0) {
8926 memprintf(err, "global statement '%s' expects an option as an argument.", args[0]);
8927 return -1;
8928 }
8929 while (*(args[i])) {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008930 if (!strcmp(args[i], "no-tls-tickets"))
Willy Tarreauef934602016-12-22 23:12:01 +01008931 global_ssl.listen_default_ssloptions |= BC_SSL_O_NO_TLS_TICKETS;
Lukas Tribus53ae85c2017-05-04 15:45:40 +00008932 else if (!strcmp(args[i], "prefer-client-ciphers"))
8933 global_ssl.listen_default_ssloptions |= BC_SSL_O_PREF_CLIE_CIPH;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008934 else if (!strcmp(args[i], "ssl-min-ver") || !strcmp(args[i], "ssl-max-ver")) {
8935 if (!parse_tls_method_minmax(args, i, &global_ssl.listen_default_sslmethods, err))
8936 i++;
8937 else {
8938 memprintf(err, "%s on global statement '%s'.", *err, args[0]);
8939 return -1;
8940 }
8941 }
8942 else if (parse_tls_method_options(args[i], &global_ssl.listen_default_sslmethods, err)) {
Emeric Brun2c86cbf2014-10-30 15:56:50 +01008943 memprintf(err, "unknown option '%s' on global statement '%s'.", args[i], args[0]);
8944 return -1;
8945 }
8946 i++;
8947 }
8948 return 0;
8949}
8950
8951/* parse the "ssl-default-server-options" keyword in global section */
8952static int ssl_parse_default_server_options(char **args, int section_type, struct proxy *curpx,
8953 struct proxy *defpx, const char *file, int line,
8954 char **err) {
8955 int i = 1;
8956
8957 if (*(args[i]) == 0) {
8958 memprintf(err, "global statement '%s' expects an option as an argument.", args[0]);
8959 return -1;
8960 }
8961 while (*(args[i])) {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008962 if (!strcmp(args[i], "no-tls-tickets"))
Willy Tarreauef934602016-12-22 23:12:01 +01008963 global_ssl.connect_default_ssloptions |= SRV_SSL_O_NO_TLS_TICKETS;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008964 else if (!strcmp(args[i], "ssl-min-ver") || !strcmp(args[i], "ssl-max-ver")) {
8965 if (!parse_tls_method_minmax(args, i, &global_ssl.connect_default_sslmethods, err))
8966 i++;
8967 else {
8968 memprintf(err, "%s on global statement '%s'.", *err, args[0]);
8969 return -1;
8970 }
8971 }
8972 else if (parse_tls_method_options(args[i], &global_ssl.connect_default_sslmethods, err)) {
Emeric Brun2c86cbf2014-10-30 15:56:50 +01008973 memprintf(err, "unknown option '%s' on global statement '%s'.", args[i], args[0]);
8974 return -1;
8975 }
8976 i++;
8977 }
8978 return 0;
8979}
8980
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01008981/* parse the "ca-base" / "crt-base" keywords in global section.
8982 * Returns <0 on alert, >0 on warning, 0 on success.
8983 */
8984static int ssl_parse_global_ca_crt_base(char **args, int section_type, struct proxy *curpx,
8985 struct proxy *defpx, const char *file, int line,
8986 char **err)
8987{
8988 char **target;
8989
Willy Tarreauef934602016-12-22 23:12:01 +01008990 target = (args[0][1] == 'a') ? &global_ssl.ca_base : &global_ssl.crt_base;
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01008991
8992 if (too_many_args(1, args, err, NULL))
8993 return -1;
8994
8995 if (*target) {
8996 memprintf(err, "'%s' already specified.", args[0]);
8997 return -1;
8998 }
8999
9000 if (*(args[1]) == 0) {
9001 memprintf(err, "global statement '%s' expects a directory path as an argument.", args[0]);
9002 return -1;
9003 }
9004 *target = strdup(args[1]);
9005 return 0;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00009006}
9007
9008/* parse the "ssl-mode-async" keyword in global section.
9009 * Returns <0 on alert, >0 on warning, 0 on success.
9010 */
9011static int ssl_parse_global_ssl_async(char **args, int section_type, struct proxy *curpx,
9012 struct proxy *defpx, const char *file, int line,
9013 char **err)
9014{
Willy Tarreau5db847a2019-05-09 14:13:35 +02009015#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00009016 global_ssl.async = 1;
Emeric Brunece0c332017-12-06 13:51:49 +01009017 global.ssl_used_async_engines = nb_engines;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00009018 return 0;
9019#else
9020 memprintf(err, "'%s': openssl library does not support async mode", args[0]);
9021 return -1;
9022#endif
9023}
9024
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02009025#ifndef OPENSSL_NO_ENGINE
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00009026static int ssl_check_async_engine_count(void) {
9027 int err_code = 0;
9028
Emeric Brun3854e012017-05-17 20:42:48 +02009029 if (global_ssl.async && (openssl_engines_initialized > 32)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01009030 ha_alert("ssl-mode-async only supports a maximum of 32 engines.\n");
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00009031 err_code = ERR_ABORT;
9032 }
9033 return err_code;
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01009034}
9035
Grant Zhang872f9c22017-01-21 01:10:18 +00009036/* parse the "ssl-engine" keyword in global section.
9037 * Returns <0 on alert, >0 on warning, 0 on success.
9038 */
9039static int ssl_parse_global_ssl_engine(char **args, int section_type, struct proxy *curpx,
9040 struct proxy *defpx, const char *file, int line,
9041 char **err)
9042{
9043 char *algo;
9044 int ret = -1;
9045
9046 if (*(args[1]) == 0) {
9047 memprintf(err, "global statement '%s' expects a valid engine name as an argument.", args[0]);
9048 return ret;
9049 }
9050
9051 if (*(args[2]) == 0) {
9052 /* if no list of algorithms is given, it defaults to ALL */
9053 algo = strdup("ALL");
9054 goto add_engine;
9055 }
9056
9057 /* otherwise the expected format is ssl-engine <engine_name> algo <list of algo> */
9058 if (strcmp(args[2], "algo") != 0) {
9059 memprintf(err, "global statement '%s' expects to have algo keyword.", args[0]);
9060 return ret;
9061 }
9062
9063 if (*(args[3]) == 0) {
9064 memprintf(err, "global statement '%s' expects algorithm names as an argument.", args[0]);
9065 return ret;
9066 }
9067 algo = strdup(args[3]);
9068
9069add_engine:
9070 if (ssl_init_single_engine(args[1], algo)==0) {
9071 openssl_engines_initialized++;
9072 ret = 0;
9073 }
9074 free(algo);
9075 return ret;
9076}
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02009077#endif
Grant Zhang872f9c22017-01-21 01:10:18 +00009078
Willy Tarreauf22e9682016-12-21 23:23:19 +01009079/* parse the "ssl-default-bind-ciphers" / "ssl-default-server-ciphers" keywords
9080 * in global section. Returns <0 on alert, >0 on warning, 0 on success.
9081 */
9082static int ssl_parse_global_ciphers(char **args, int section_type, struct proxy *curpx,
9083 struct proxy *defpx, const char *file, int line,
9084 char **err)
9085{
9086 char **target;
9087
Willy Tarreauef934602016-12-22 23:12:01 +01009088 target = (args[0][12] == 'b') ? &global_ssl.listen_default_ciphers : &global_ssl.connect_default_ciphers;
Willy Tarreauf22e9682016-12-21 23:23:19 +01009089
9090 if (too_many_args(1, args, err, NULL))
9091 return -1;
9092
9093 if (*(args[1]) == 0) {
9094 memprintf(err, "global statement '%s' expects a cipher suite as an argument.", args[0]);
9095 return -1;
9096 }
9097
9098 free(*target);
9099 *target = strdup(args[1]);
9100 return 0;
9101}
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009102
Emmanuel Hocdet839af572019-05-14 16:27:35 +02009103#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009104/* parse the "ssl-default-bind-ciphersuites" / "ssl-default-server-ciphersuites" keywords
9105 * in global section. Returns <0 on alert, >0 on warning, 0 on success.
9106 */
9107static int ssl_parse_global_ciphersuites(char **args, int section_type, struct proxy *curpx,
9108 struct proxy *defpx, const char *file, int line,
9109 char **err)
9110{
9111 char **target;
9112
9113 target = (args[0][12] == 'b') ? &global_ssl.listen_default_ciphersuites : &global_ssl.connect_default_ciphersuites;
9114
9115 if (too_many_args(1, args, err, NULL))
9116 return -1;
9117
9118 if (*(args[1]) == 0) {
9119 memprintf(err, "global statement '%s' expects a cipher suite as an argument.", args[0]);
9120 return -1;
9121 }
9122
9123 free(*target);
9124 *target = strdup(args[1]);
9125 return 0;
9126}
9127#endif
Willy Tarreauf22e9682016-12-21 23:23:19 +01009128
Willy Tarreau9ceda382016-12-21 23:13:03 +01009129/* parse various global tune.ssl settings consisting in positive integers.
9130 * Returns <0 on alert, >0 on warning, 0 on success.
9131 */
9132static int ssl_parse_global_int(char **args, int section_type, struct proxy *curpx,
9133 struct proxy *defpx, const char *file, int line,
9134 char **err)
9135{
9136 int *target;
9137
9138 if (strcmp(args[0], "tune.ssl.cachesize") == 0)
9139 target = &global.tune.sslcachesize;
9140 else if (strcmp(args[0], "tune.ssl.maxrecord") == 0)
Willy Tarreauef934602016-12-22 23:12:01 +01009141 target = (int *)&global_ssl.max_record;
Willy Tarreau9ceda382016-12-21 23:13:03 +01009142 else if (strcmp(args[0], "tune.ssl.ssl-ctx-cache-size") == 0)
Willy Tarreauef934602016-12-22 23:12:01 +01009143 target = &global_ssl.ctx_cache;
Willy Tarreau0bea58d2016-12-21 23:17:25 +01009144 else if (strcmp(args[0], "maxsslconn") == 0)
9145 target = &global.maxsslconn;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01009146 else if (strcmp(args[0], "tune.ssl.capture-cipherlist-size") == 0)
9147 target = &global_ssl.capture_cipherlist;
Willy Tarreau9ceda382016-12-21 23:13:03 +01009148 else {
9149 memprintf(err, "'%s' keyword not unhandled (please report this bug).", args[0]);
9150 return -1;
9151 }
9152
9153 if (too_many_args(1, args, err, NULL))
9154 return -1;
9155
9156 if (*(args[1]) == 0) {
9157 memprintf(err, "'%s' expects an integer argument.", args[0]);
9158 return -1;
9159 }
9160
9161 *target = atoi(args[1]);
9162 if (*target < 0) {
9163 memprintf(err, "'%s' expects a positive numeric value.", args[0]);
9164 return -1;
9165 }
9166 return 0;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01009167}
9168
9169static int ssl_parse_global_capture_cipherlist(char **args, int section_type, struct proxy *curpx,
9170 struct proxy *defpx, const char *file, int line,
9171 char **err)
9172{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01009173 int ret;
9174
9175 ret = ssl_parse_global_int(args, section_type, curpx, defpx, file, line, err);
9176 if (ret != 0)
9177 return ret;
9178
Willy Tarreaubafbe012017-11-24 17:34:44 +01009179 if (pool_head_ssl_capture) {
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01009180 memprintf(err, "'%s' is already configured.", args[0]);
9181 return -1;
9182 }
9183
Willy Tarreaubafbe012017-11-24 17:34:44 +01009184 pool_head_ssl_capture = create_pool("ssl-capture", sizeof(struct ssl_capture) + global_ssl.capture_cipherlist, MEM_F_SHARED);
9185 if (!pool_head_ssl_capture) {
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01009186 memprintf(err, "Out of memory error.");
9187 return -1;
9188 }
9189 return 0;
Willy Tarreau9ceda382016-12-21 23:13:03 +01009190}
9191
9192/* parse "ssl.force-private-cache".
9193 * Returns <0 on alert, >0 on warning, 0 on success.
9194 */
9195static int ssl_parse_global_private_cache(char **args, int section_type, struct proxy *curpx,
9196 struct proxy *defpx, const char *file, int line,
9197 char **err)
9198{
9199 if (too_many_args(0, args, err, NULL))
9200 return -1;
9201
Willy Tarreauef934602016-12-22 23:12:01 +01009202 global_ssl.private_cache = 1;
Willy Tarreau9ceda382016-12-21 23:13:03 +01009203 return 0;
9204}
9205
9206/* parse "ssl.lifetime".
9207 * Returns <0 on alert, >0 on warning, 0 on success.
9208 */
9209static int ssl_parse_global_lifetime(char **args, int section_type, struct proxy *curpx,
9210 struct proxy *defpx, const char *file, int line,
9211 char **err)
9212{
9213 const char *res;
9214
9215 if (too_many_args(1, args, err, NULL))
9216 return -1;
9217
9218 if (*(args[1]) == 0) {
9219 memprintf(err, "'%s' expects ssl sessions <lifetime> in seconds as argument.", args[0]);
9220 return -1;
9221 }
9222
Willy Tarreauef934602016-12-22 23:12:01 +01009223 res = parse_time_err(args[1], &global_ssl.life_time, TIME_UNIT_S);
Willy Tarreau9faebe32019-06-07 19:00:37 +02009224 if (res == PARSE_TIME_OVER) {
9225 memprintf(err, "timer overflow in argument '%s' to <%s> (maximum value is 2147483647 s or ~68 years).",
9226 args[1], args[0]);
9227 return -1;
9228 }
9229 else if (res == PARSE_TIME_UNDER) {
9230 memprintf(err, "timer underflow in argument '%s' to <%s> (minimum non-null value is 1 s).",
9231 args[1], args[0]);
9232 return -1;
9233 }
9234 else if (res) {
Willy Tarreau9ceda382016-12-21 23:13:03 +01009235 memprintf(err, "unexpected character '%c' in argument to <%s>.", *res, args[0]);
9236 return -1;
9237 }
9238 return 0;
9239}
9240
9241#ifndef OPENSSL_NO_DH
Willy Tarreau14e36a12016-12-21 23:28:13 +01009242/* parse "ssl-dh-param-file".
9243 * Returns <0 on alert, >0 on warning, 0 on success.
9244 */
9245static int ssl_parse_global_dh_param_file(char **args, int section_type, struct proxy *curpx,
9246 struct proxy *defpx, const char *file, int line,
9247 char **err)
9248{
9249 if (too_many_args(1, args, err, NULL))
9250 return -1;
9251
9252 if (*(args[1]) == 0) {
9253 memprintf(err, "'%s' expects a file path as an argument.", args[0]);
9254 return -1;
9255 }
9256
9257 if (ssl_sock_load_global_dh_param_from_file(args[1])) {
9258 memprintf(err, "'%s': unable to load DH parameters from file <%s>.", args[0], args[1]);
9259 return -1;
9260 }
9261 return 0;
9262}
9263
Willy Tarreau9ceda382016-12-21 23:13:03 +01009264/* parse "ssl.default-dh-param".
9265 * Returns <0 on alert, >0 on warning, 0 on success.
9266 */
9267static int ssl_parse_global_default_dh(char **args, int section_type, struct proxy *curpx,
9268 struct proxy *defpx, const char *file, int line,
9269 char **err)
9270{
9271 if (too_many_args(1, args, err, NULL))
9272 return -1;
9273
9274 if (*(args[1]) == 0) {
9275 memprintf(err, "'%s' expects an integer argument.", args[0]);
9276 return -1;
9277 }
9278
Willy Tarreauef934602016-12-22 23:12:01 +01009279 global_ssl.default_dh_param = atoi(args[1]);
9280 if (global_ssl.default_dh_param < 1024) {
Willy Tarreau9ceda382016-12-21 23:13:03 +01009281 memprintf(err, "'%s' expects a value >= 1024.", args[0]);
9282 return -1;
9283 }
9284 return 0;
9285}
9286#endif
9287
9288
William Lallemand32af2032016-10-29 18:09:35 +02009289/* This function is used with TLS ticket keys management. It permits to browse
9290 * each reference. The variable <getnext> must contain the current node,
9291 * <end> point to the root node.
9292 */
9293#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
9294static inline
9295struct tls_keys_ref *tlskeys_list_get_next(struct tls_keys_ref *getnext, struct list *end)
9296{
9297 struct tls_keys_ref *ref = getnext;
9298
9299 while (1) {
9300
9301 /* Get next list entry. */
9302 ref = LIST_NEXT(&ref->list, struct tls_keys_ref *, list);
9303
9304 /* If the entry is the last of the list, return NULL. */
9305 if (&ref->list == end)
9306 return NULL;
9307
9308 return ref;
9309 }
9310}
9311
9312static inline
9313struct tls_keys_ref *tlskeys_ref_lookup_ref(const char *reference)
9314{
9315 int id;
9316 char *error;
9317
9318 /* If the reference starts by a '#', this is numeric id. */
9319 if (reference[0] == '#') {
9320 /* Try to convert the numeric id. If the conversion fails, the lookup fails. */
9321 id = strtol(reference + 1, &error, 10);
9322 if (*error != '\0')
9323 return NULL;
9324
9325 /* Perform the unique id lookup. */
9326 return tlskeys_ref_lookupid(id);
9327 }
9328
9329 /* Perform the string lookup. */
9330 return tlskeys_ref_lookup(reference);
9331}
9332#endif
9333
9334
9335#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
9336
9337static int cli_io_handler_tlskeys_files(struct appctx *appctx);
9338
9339static inline int cli_io_handler_tlskeys_entries(struct appctx *appctx) {
9340 return cli_io_handler_tlskeys_files(appctx);
9341}
9342
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009343/* dumps all tls keys. Relies on cli.i0 (non-null = only list file names), cli.i1
9344 * (next index to be dumped), and cli.p0 (next key reference).
9345 */
William Lallemand32af2032016-10-29 18:09:35 +02009346static int cli_io_handler_tlskeys_files(struct appctx *appctx) {
9347
9348 struct stream_interface *si = appctx->owner;
9349
9350 switch (appctx->st2) {
9351 case STAT_ST_INIT:
9352 /* Display the column headers. If the message cannot be sent,
Joseph Herlant017b3da2018-11-15 09:07:59 -08009353 * quit the function with returning 0. The function is called
William Lallemand32af2032016-10-29 18:09:35 +02009354 * later and restart at the state "STAT_ST_INIT".
9355 */
9356 chunk_reset(&trash);
9357
9358 if (appctx->io_handler == cli_io_handler_tlskeys_entries)
9359 chunk_appendf(&trash, "# id secret\n");
9360 else
9361 chunk_appendf(&trash, "# id (file)\n");
9362
Willy Tarreau06d80a92017-10-19 14:32:15 +02009363 if (ci_putchk(si_ic(si), &trash) == -1) {
Willy Tarreaudb398432018-11-15 11:08:52 +01009364 si_rx_room_blk(si);
William Lallemand32af2032016-10-29 18:09:35 +02009365 return 0;
9366 }
9367
William Lallemand32af2032016-10-29 18:09:35 +02009368 /* Now, we start the browsing of the references lists.
9369 * Note that the following call to LIST_ELEM return bad pointer. The only
9370 * available field of this pointer is <list>. It is used with the function
9371 * tlskeys_list_get_next() for retruning the first available entry
9372 */
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009373 if (appctx->ctx.cli.p0 == NULL) {
9374 appctx->ctx.cli.p0 = LIST_ELEM(&tlskeys_reference, struct tls_keys_ref *, list);
9375 appctx->ctx.cli.p0 = tlskeys_list_get_next(appctx->ctx.cli.p0, &tlskeys_reference);
William Lallemand32af2032016-10-29 18:09:35 +02009376 }
9377
9378 appctx->st2 = STAT_ST_LIST;
9379 /* fall through */
9380
9381 case STAT_ST_LIST:
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009382 while (appctx->ctx.cli.p0) {
9383 struct tls_keys_ref *ref = appctx->ctx.cli.p0;
William Lallemand32af2032016-10-29 18:09:35 +02009384
9385 chunk_reset(&trash);
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009386 if (appctx->io_handler == cli_io_handler_tlskeys_entries && appctx->ctx.cli.i1 == 0)
William Lallemand32af2032016-10-29 18:09:35 +02009387 chunk_appendf(&trash, "# ");
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009388
9389 if (appctx->ctx.cli.i1 == 0)
9390 chunk_appendf(&trash, "%d (%s)\n", ref->unique_id, ref->filename);
9391
William Lallemand32af2032016-10-29 18:09:35 +02009392 if (appctx->io_handler == cli_io_handler_tlskeys_entries) {
Christopher Faulet16f45c82018-02-16 11:23:49 +01009393 int head;
9394
9395 HA_RWLOCK_RDLOCK(TLSKEYS_REF_LOCK, &ref->lock);
9396 head = ref->tls_ticket_enc_index;
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009397 while (appctx->ctx.cli.i1 < TLS_TICKETS_NO) {
Willy Tarreau83061a82018-07-13 11:56:34 +02009398 struct buffer *t2 = get_trash_chunk();
William Lallemand32af2032016-10-29 18:09:35 +02009399
9400 chunk_reset(t2);
9401 /* should never fail here because we dump only a key in the t2 buffer */
Emeric Brun9e754772019-01-10 17:51:55 +01009402 if (ref->key_size_bits == 128) {
9403 t2->data = a2base64((char *)(ref->tlskeys + (head + 2 + appctx->ctx.cli.i1) % TLS_TICKETS_NO),
9404 sizeof(struct tls_sess_key_128),
9405 t2->area, t2->size);
9406 chunk_appendf(&trash, "%d.%d %s\n", ref->unique_id, appctx->ctx.cli.i1,
9407 t2->area);
9408 }
9409 else if (ref->key_size_bits == 256) {
9410 t2->data = a2base64((char *)(ref->tlskeys + (head + 2 + appctx->ctx.cli.i1) % TLS_TICKETS_NO),
9411 sizeof(struct tls_sess_key_256),
9412 t2->area, t2->size);
9413 chunk_appendf(&trash, "%d.%d %s\n", ref->unique_id, appctx->ctx.cli.i1,
9414 t2->area);
9415 }
9416 else {
9417 /* This case should never happen */
9418 chunk_appendf(&trash, "%d.%d <unknown>\n", ref->unique_id, appctx->ctx.cli.i1);
9419 }
William Lallemand32af2032016-10-29 18:09:35 +02009420
Willy Tarreau06d80a92017-10-19 14:32:15 +02009421 if (ci_putchk(si_ic(si), &trash) == -1) {
William Lallemand32af2032016-10-29 18:09:35 +02009422 /* let's try again later from this stream. We add ourselves into
9423 * this stream's users so that it can remove us upon termination.
9424 */
Christopher Faulet16f45c82018-02-16 11:23:49 +01009425 HA_RWLOCK_RDUNLOCK(TLSKEYS_REF_LOCK, &ref->lock);
Willy Tarreaudb398432018-11-15 11:08:52 +01009426 si_rx_room_blk(si);
William Lallemand32af2032016-10-29 18:09:35 +02009427 return 0;
9428 }
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009429 appctx->ctx.cli.i1++;
William Lallemand32af2032016-10-29 18:09:35 +02009430 }
Christopher Faulet16f45c82018-02-16 11:23:49 +01009431 HA_RWLOCK_RDUNLOCK(TLSKEYS_REF_LOCK, &ref->lock);
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009432 appctx->ctx.cli.i1 = 0;
William Lallemand32af2032016-10-29 18:09:35 +02009433 }
Willy Tarreau06d80a92017-10-19 14:32:15 +02009434 if (ci_putchk(si_ic(si), &trash) == -1) {
William Lallemand32af2032016-10-29 18:09:35 +02009435 /* let's try again later from this stream. We add ourselves into
9436 * this stream's users so that it can remove us upon termination.
9437 */
Willy Tarreaudb398432018-11-15 11:08:52 +01009438 si_rx_room_blk(si);
William Lallemand32af2032016-10-29 18:09:35 +02009439 return 0;
9440 }
9441
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009442 if (appctx->ctx.cli.i0 == 0) /* don't display everything if not necessary */
William Lallemand32af2032016-10-29 18:09:35 +02009443 break;
9444
9445 /* get next list entry and check the end of the list */
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009446 appctx->ctx.cli.p0 = tlskeys_list_get_next(appctx->ctx.cli.p0, &tlskeys_reference);
William Lallemand32af2032016-10-29 18:09:35 +02009447 }
9448
9449 appctx->st2 = STAT_ST_FIN;
9450 /* fall through */
9451
9452 default:
9453 appctx->st2 = STAT_ST_FIN;
9454 return 1;
9455 }
9456 return 0;
9457}
9458
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009459/* sets cli.i0 to non-zero if only file lists should be dumped */
Aurélien Nephtaliabbf6072018-04-18 13:26:46 +02009460static int cli_parse_show_tlskeys(char **args, char *payload, struct appctx *appctx, void *private)
William Lallemand32af2032016-10-29 18:09:35 +02009461{
William Lallemand32af2032016-10-29 18:09:35 +02009462 /* no parameter, shows only file list */
9463 if (!*args[2]) {
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009464 appctx->ctx.cli.i0 = 1;
William Lallemand32af2032016-10-29 18:09:35 +02009465 appctx->io_handler = cli_io_handler_tlskeys_files;
Willy Tarreau3067bfa2016-12-05 14:50:15 +01009466 return 0;
William Lallemand32af2032016-10-29 18:09:35 +02009467 }
9468
9469 if (args[2][0] == '*') {
9470 /* list every TLS ticket keys */
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009471 appctx->ctx.cli.i0 = 1;
William Lallemand32af2032016-10-29 18:09:35 +02009472 } else {
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009473 appctx->ctx.cli.p0 = tlskeys_ref_lookup_ref(args[2]);
9474 if (!appctx->ctx.cli.p0) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02009475 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02009476 appctx->ctx.cli.msg = "'show tls-keys' unable to locate referenced filename\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01009477 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02009478 return 1;
9479 }
9480 }
William Lallemand32af2032016-10-29 18:09:35 +02009481 appctx->io_handler = cli_io_handler_tlskeys_entries;
Willy Tarreau3067bfa2016-12-05 14:50:15 +01009482 return 0;
William Lallemand32af2032016-10-29 18:09:35 +02009483}
9484
Aurélien Nephtaliabbf6072018-04-18 13:26:46 +02009485static int cli_parse_set_tlskeys(char **args, char *payload, struct appctx *appctx, void *private)
William Lallemand32af2032016-10-29 18:09:35 +02009486{
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009487 struct tls_keys_ref *ref;
Willy Tarreau1c913e42018-08-22 05:26:57 +02009488 int ret;
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009489
William Lallemand32af2032016-10-29 18:09:35 +02009490 /* Expect two parameters: the filename and the new new TLS key in encoding */
9491 if (!*args[3] || !*args[4]) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02009492 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02009493 appctx->ctx.cli.msg = "'set ssl tls-key' expects a filename and the new TLS key in base64 encoding.\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01009494 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02009495 return 1;
9496 }
9497
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009498 ref = tlskeys_ref_lookup_ref(args[3]);
9499 if (!ref) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02009500 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02009501 appctx->ctx.cli.msg = "'set ssl tls-key' unable to locate referenced filename\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01009502 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02009503 return 1;
9504 }
9505
Willy Tarreau1c913e42018-08-22 05:26:57 +02009506 ret = base64dec(args[4], strlen(args[4]), trash.area, trash.size);
Emeric Brun9e754772019-01-10 17:51:55 +01009507 if (ret < 0) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02009508 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02009509 appctx->ctx.cli.msg = "'set ssl tls-key' received invalid base64 encoded TLS key.\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01009510 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02009511 return 1;
9512 }
Emeric Brun9e754772019-01-10 17:51:55 +01009513
Willy Tarreau1c913e42018-08-22 05:26:57 +02009514 trash.data = ret;
Emeric Brun9e754772019-01-10 17:51:55 +01009515 if (ssl_sock_update_tlskey_ref(ref, &trash) < 0) {
9516 appctx->ctx.cli.severity = LOG_ERR;
9517 appctx->ctx.cli.msg = "'set ssl tls-key' received a key of wrong size.\n";
9518 appctx->st0 = CLI_ST_PRINT;
9519 return 1;
9520 }
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02009521 appctx->ctx.cli.severity = LOG_INFO;
Aurélien Nephtali6e8a41d2018-03-15 21:48:50 +01009522 appctx->ctx.cli.msg = "TLS ticket key updated!\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01009523 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02009524 return 1;
9525
9526}
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01009527#endif
William Lallemand32af2032016-10-29 18:09:35 +02009528
Aurélien Nephtaliabbf6072018-04-18 13:26:46 +02009529static int cli_parse_set_ocspresponse(char **args, char *payload, struct appctx *appctx, void *private)
William Lallemand32af2032016-10-29 18:09:35 +02009530{
9531#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
9532 char *err = NULL;
Willy Tarreau1c913e42018-08-22 05:26:57 +02009533 int i, j, ret;
Aurélien Nephtali1e0867c2018-04-18 14:04:58 +02009534
9535 if (!payload)
9536 payload = args[3];
William Lallemand32af2032016-10-29 18:09:35 +02009537
9538 /* Expect one parameter: the new response in base64 encoding */
Aurélien Nephtali1e0867c2018-04-18 14:04:58 +02009539 if (!*payload) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02009540 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02009541 appctx->ctx.cli.msg = "'set ssl ocsp-response' expects response in base64 encoding.\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01009542 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02009543 return 1;
9544 }
Aurélien Nephtali1e0867c2018-04-18 14:04:58 +02009545
9546 /* remove \r and \n from the payload */
9547 for (i = 0, j = 0; payload[i]; i++) {
9548 if (payload[i] == '\r' || payload[i] == '\n')
9549 continue;
9550 payload[j++] = payload[i];
9551 }
9552 payload[j] = 0;
William Lallemand32af2032016-10-29 18:09:35 +02009553
Willy Tarreau1c913e42018-08-22 05:26:57 +02009554 ret = base64dec(payload, j, trash.area, trash.size);
9555 if (ret < 0) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02009556 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02009557 appctx->ctx.cli.msg = "'set ssl ocsp-response' received invalid base64 encoded response.\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01009558 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02009559 return 1;
9560 }
9561
Willy Tarreau1c913e42018-08-22 05:26:57 +02009562 trash.data = ret;
William Lallemand32af2032016-10-29 18:09:35 +02009563 if (ssl_sock_update_ocsp_response(&trash, &err)) {
9564 if (err) {
9565 memprintf(&err, "%s.\n", err);
9566 appctx->ctx.cli.err = err;
Willy Tarreau3b6e5472016-11-24 15:53:53 +01009567 appctx->st0 = CLI_ST_PRINT_FREE;
William Lallemand32af2032016-10-29 18:09:35 +02009568 }
Aurélien Nephtali9a4da682018-04-16 19:02:42 +02009569 else {
9570 appctx->ctx.cli.severity = LOG_ERR;
9571 appctx->ctx.cli.msg = "Failed to update OCSP response.\n";
9572 appctx->st0 = CLI_ST_PRINT;
9573 }
William Lallemand32af2032016-10-29 18:09:35 +02009574 return 1;
9575 }
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02009576 appctx->ctx.cli.severity = LOG_INFO;
Aurélien Nephtali6e8a41d2018-03-15 21:48:50 +01009577 appctx->ctx.cli.msg = "OCSP Response updated!\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01009578 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02009579 return 1;
9580#else
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02009581 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02009582 appctx->ctx.cli.msg = "HAProxy was compiled against a version of OpenSSL that doesn't support OCSP stapling.\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01009583 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02009584 return 1;
9585#endif
9586
Nenad Merdanovicc31499d2019-03-23 11:00:32 +01009587}
9588
Willy Tarreau86a394e2019-05-09 14:15:32 +02009589#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000100fL)
Dragan Dosene06e0642021-02-22 10:03:53 +01009590/* This function returns a sample struct filled with an <arg> content.
9591 * If the <arg> contains a string, it is returned in the sample flagged as
9592 * SMP_F_CONST. If the <arg> contains a variable descriptor, the sample is
9593 * filled with the content of the variable by using vars_get_by_desc().
9594 *
9595 * Keep in mind that the sample content may be written to a pre-allocated
9596 * trash chunk as returned by get_trash_chunk().
9597 *
9598 * This function returns 0 if an error occurs, otherwise it returns 1.
9599 */
Nenad Merdanovicc31499d2019-03-23 11:00:32 +01009600static inline int sample_conv_var2smp_str(const struct arg *arg, struct sample *smp)
9601{
9602 switch (arg->type) {
9603 case ARGT_STR:
9604 smp->data.type = SMP_T_STR;
9605 smp->data.u.str = arg->data.str;
Dragan Dosene06e0642021-02-22 10:03:53 +01009606 smp->flags = SMP_F_CONST;
Nenad Merdanovicc31499d2019-03-23 11:00:32 +01009607 return 1;
9608 case ARGT_VAR:
9609 if (!vars_get_by_desc(&arg->data.var, smp))
9610 return 0;
9611 if (!sample_casts[smp->data.type][SMP_T_STR])
9612 return 0;
9613 if (!sample_casts[smp->data.type][SMP_T_STR](smp))
9614 return 0;
9615 return 1;
9616 default:
9617 return 0;
9618 }
9619}
9620
Dragan Dosene06e0642021-02-22 10:03:53 +01009621/* This function checks an <arg> and fills it with a variable type if the
9622 * <arg> string contains a valid variable name. If failed, the function
9623 * tries to perform a base64 decode operation on the same string, and
9624 * fills the <arg> with the decoded content.
9625 *
9626 * Validation is skipped if the <arg> string is empty.
9627 *
9628 * This function returns 0 if the variable lookup fails and the specified
9629 * <arg> string is not a valid base64 encoded string, as well if
9630 * unexpected argument type is specified or memory allocation error
9631 * occurs. Otherwise it returns 1.
9632 */
9633static inline int sample_check_arg_base64(struct arg *arg, char **err)
9634{
9635 char *dec = NULL;
9636 int dec_size;
9637
9638 if (arg->type != ARGT_STR) {
9639 memprintf(err, "unexpected argument type");
9640 return 0;
9641 }
9642
9643 if (arg->data.str.data == 0) /* empty */
9644 return 1;
9645
9646 if (vars_check_arg(arg, NULL))
9647 return 1;
9648
9649 if (arg->data.str.data % 4) {
9650 memprintf(err, "argument needs to be base64 encoded, and "
9651 "can either be a string or a variable");
9652 return 0;
9653 }
9654
9655 dec_size = (arg->data.str.data / 4 * 3)
9656 - (arg->data.str.area[arg->data.str.data-1] == '=' ? 1 : 0)
9657 - (arg->data.str.area[arg->data.str.data-2] == '=' ? 1 : 0);
9658
9659 if ((dec = malloc(dec_size)) == NULL) {
9660 memprintf(err, "memory allocation error");
9661 return 0;
9662 }
9663
9664 dec_size = base64dec(arg->data.str.area, arg->data.str.data, dec, dec_size);
9665 if (dec_size < 0) {
9666 memprintf(err, "argument needs to be base64 encoded, and "
9667 "can either be a string or a variable");
9668 free(dec);
9669 return 0;
9670 }
9671
9672 /* base64 decoded */
9673 chunk_destroy(&arg->data.str);
9674 arg->data.str.area = dec;
9675 arg->data.str.data = dec_size;
9676 return 1;
9677}
9678
Nenad Merdanovicc31499d2019-03-23 11:00:32 +01009679static int check_aes_gcm(struct arg *args, struct sample_conv *conv,
9680 const char *file, int line, char **err)
9681{
9682 switch(args[0].data.sint) {
9683 case 128:
9684 case 192:
9685 case 256:
9686 break;
9687 default:
9688 memprintf(err, "key size must be 128, 192 or 256 (bits).");
9689 return 0;
9690 }
Dragan Dosene06e0642021-02-22 10:03:53 +01009691
9692 /* Try to decode variables. */
9693 if (!sample_check_arg_base64(&args[1], err)) {
9694 memprintf(err, "failed to parse nonce : %s", *err);
9695 return 0;
9696 }
9697 if (!sample_check_arg_base64(&args[2], err)) {
9698 memprintf(err, "failed to parse key : %s", *err);
9699 return 0;
9700 }
9701 if (!sample_check_arg_base64(&args[3], err)) {
9702 memprintf(err, "failed to parse aead_tag : %s", *err);
9703 return 0;
9704 }
9705
Nenad Merdanovicc31499d2019-03-23 11:00:32 +01009706 return 1;
9707}
9708
9709/* Arguements: AES size in bits, nonce, key, tag. The last three arguments are base64 encoded */
9710static int sample_conv_aes_gcm_dec(const struct arg *arg_p, struct sample *smp, void *private)
9711{
9712 struct sample nonce, key, aead_tag;
Dragan Dosene06e0642021-02-22 10:03:53 +01009713 struct buffer *smp_trash = NULL, *smp_trash_alloc = NULL;
Nenad Merdanovicc31499d2019-03-23 11:00:32 +01009714 EVP_CIPHER_CTX *ctx;
9715 int dec_size, ret;
9716
Nenad Merdanovicc31499d2019-03-23 11:00:32 +01009717 smp_trash_alloc = alloc_trash_chunk();
9718 if (!smp_trash_alloc)
9719 return 0;
9720
Dragan Dosene06e0642021-02-22 10:03:53 +01009721 /* smp copy */
9722 smp_trash_alloc->data = smp->data.u.str.data;
9723 if (unlikely(smp_trash_alloc->data > smp_trash_alloc->size))
9724 smp_trash_alloc->data = smp_trash_alloc->size;
9725 memcpy(smp_trash_alloc->area, smp->data.u.str.area, smp_trash_alloc->data);
9726
Nenad Merdanovicc31499d2019-03-23 11:00:32 +01009727 ctx = EVP_CIPHER_CTX_new();
9728
9729 if (!ctx)
9730 goto err;
9731
Dragan Dosene06e0642021-02-22 10:03:53 +01009732 smp_trash = alloc_trash_chunk();
9733 if (!smp_trash)
Nenad Merdanovicc31499d2019-03-23 11:00:32 +01009734 goto err;
Dragan Dosene06e0642021-02-22 10:03:53 +01009735
9736 smp_set_owner(&nonce, smp->px, smp->sess, smp->strm, smp->opt);
9737 if (!sample_conv_var2smp_str(&arg_p[1], &nonce))
9738 goto err;
9739
9740 if (arg_p[1].type == ARGT_VAR) {
9741 dec_size = base64dec(nonce.data.u.str.area, nonce.data.u.str.data, smp_trash->area, smp_trash->size);
9742 if (dec_size < 0)
9743 goto err;
9744 smp_trash->data = dec_size;
9745 nonce.data.u.str = *smp_trash;
9746 }
Nenad Merdanovicc31499d2019-03-23 11:00:32 +01009747
9748 /* Set cipher type and mode */
9749 switch(arg_p[0].data.sint) {
9750 case 128:
9751 EVP_DecryptInit_ex(ctx, EVP_aes_128_gcm(), NULL, NULL, NULL);
9752 break;
9753 case 192:
9754 EVP_DecryptInit_ex(ctx, EVP_aes_192_gcm(), NULL, NULL, NULL);
9755 break;
9756 case 256:
9757 EVP_DecryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL);
9758 break;
9759 }
9760
Dragan Dosene06e0642021-02-22 10:03:53 +01009761 EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, nonce.data.u.str.data, NULL);
Nenad Merdanovicc31499d2019-03-23 11:00:32 +01009762
9763 /* Initialise IV */
Dragan Dosene06e0642021-02-22 10:03:53 +01009764 if(!EVP_DecryptInit_ex(ctx, NULL, NULL, NULL, (unsigned char *) nonce.data.u.str.area))
Nenad Merdanovicc31499d2019-03-23 11:00:32 +01009765 goto err;
9766
Dragan Dosene06e0642021-02-22 10:03:53 +01009767 smp_set_owner(&key, smp->px, smp->sess, smp->strm, smp->opt);
9768 if (!sample_conv_var2smp_str(&arg_p[2], &key))
Nenad Merdanovicc31499d2019-03-23 11:00:32 +01009769 goto err;
Dragan Dosene06e0642021-02-22 10:03:53 +01009770
9771 if (arg_p[2].type == ARGT_VAR) {
9772 dec_size = base64dec(key.data.u.str.area, key.data.u.str.data, smp_trash->area, smp_trash->size);
9773 if (dec_size < 0)
9774 goto err;
9775 smp_trash->data = dec_size;
9776 key.data.u.str = *smp_trash;
9777 }
Nenad Merdanovicc31499d2019-03-23 11:00:32 +01009778
9779 /* Initialise key */
Dragan Dosene06e0642021-02-22 10:03:53 +01009780 if (!EVP_DecryptInit_ex(ctx, NULL, NULL, (unsigned char *) key.data.u.str.area, NULL))
Nenad Merdanovicc31499d2019-03-23 11:00:32 +01009781 goto err;
9782
9783 if (!EVP_DecryptUpdate(ctx, (unsigned char *) smp_trash->area, (int *) &smp_trash->data,
Dragan Dosene06e0642021-02-22 10:03:53 +01009784 (unsigned char *) smp_trash_alloc->area, (int) smp_trash_alloc->data))
Nenad Merdanovicc31499d2019-03-23 11:00:32 +01009785 goto err;
9786
Dragan Dosene06e0642021-02-22 10:03:53 +01009787 smp_set_owner(&aead_tag, smp->px, smp->sess, smp->strm, smp->opt);
9788 if (!sample_conv_var2smp_str(&arg_p[3], &aead_tag))
Nenad Merdanovicc31499d2019-03-23 11:00:32 +01009789 goto err;
Dragan Dosene06e0642021-02-22 10:03:53 +01009790
9791 if (arg_p[3].type == ARGT_VAR) {
9792 dec_size = base64dec(aead_tag.data.u.str.area, aead_tag.data.u.str.data, smp_trash_alloc->area, smp_trash_alloc->size);
9793 if (dec_size < 0)
9794 goto err;
9795 smp_trash_alloc->data = dec_size;
9796 aead_tag.data.u.str = *smp_trash_alloc;
9797 }
9798
Nenad Merdanovicc31499d2019-03-23 11:00:32 +01009799 dec_size = smp_trash->data;
9800
Dragan Dosene06e0642021-02-22 10:03:53 +01009801 EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, aead_tag.data.u.str.data, (void *) aead_tag.data.u.str.area);
Nenad Merdanovicc31499d2019-03-23 11:00:32 +01009802 ret = EVP_DecryptFinal_ex(ctx, (unsigned char *) smp_trash->area + smp_trash->data, (int *) &smp_trash->data);
9803
9804 if (ret <= 0)
9805 goto err;
9806
9807 smp->data.u.str.data = dec_size + smp_trash->data;
9808 smp->data.u.str.area = smp_trash->area;
9809 smp->data.type = SMP_T_BIN;
Dragan Dosene06e0642021-02-22 10:03:53 +01009810 smp_dup(smp);
Nenad Merdanovicc31499d2019-03-23 11:00:32 +01009811 free_trash_chunk(smp_trash_alloc);
Dragan Dosene06e0642021-02-22 10:03:53 +01009812 free_trash_chunk(smp_trash);
Nenad Merdanovicc31499d2019-03-23 11:00:32 +01009813 return 1;
9814
9815err:
9816 free_trash_chunk(smp_trash_alloc);
Dragan Dosene06e0642021-02-22 10:03:53 +01009817 free_trash_chunk(smp_trash);
Nenad Merdanovicc31499d2019-03-23 11:00:32 +01009818 return 0;
William Lallemand32af2032016-10-29 18:09:35 +02009819}
Nenad Merdanovicc31499d2019-03-23 11:00:32 +01009820# endif
William Lallemand32af2032016-10-29 18:09:35 +02009821
9822/* register cli keywords */
9823static struct cli_kw_list cli_kws = {{ },{
9824#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
9825 { { "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 +02009826 { { "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 +02009827#endif
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01009828 { { "set", "ssl", "ocsp-response", NULL }, NULL, cli_parse_set_ocspresponse, NULL },
William Lallemand32af2032016-10-29 18:09:35 +02009829 { { NULL }, NULL, NULL, NULL }
9830}};
9831
Willy Tarreau0108d902018-11-25 19:14:37 +01009832INITCALL1(STG_REGISTER, cli_register_kw, &cli_kws);
William Lallemand32af2032016-10-29 18:09:35 +02009833
Willy Tarreau7875d092012-09-10 08:20:03 +02009834/* Note: must not be declared <const> as its list will be overwritten.
9835 * Please take care of keeping this list alphabetically sorted.
9836 */
Willy Tarreaudc13c112013-06-21 23:16:39 +02009837static struct sample_fetch_kw_list sample_fetch_keywords = {ILH, {
Emeric Brun645ae792014-04-30 14:21:06 +02009838 { "ssl_bc", smp_fetch_ssl_fc, 0, NULL, SMP_T_BOOL, SMP_USE_L5SRV },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02009839 { "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 +01009840#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Jérôme Magnine064a802018-12-03 22:21:04 +01009841 { "ssl_bc_alpn", smp_fetch_ssl_fc_alpn, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
Olivier Houchard6b77f492018-11-22 18:18:29 +01009842#endif
Emeric Brun645ae792014-04-30 14:21:06 +02009843 { "ssl_bc_cipher", smp_fetch_ssl_fc_cipher, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
Olivier Houchard6b77f492018-11-22 18:18:29 +01009844#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
9845 { "ssl_bc_npn", smp_fetch_ssl_fc_npn, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
9846#endif
Emeric Brun74f7ffa2018-02-19 16:14:12 +01009847 { "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 +02009848 { "ssl_bc_protocol", smp_fetch_ssl_fc_protocol, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
Emeric Brunb73a9b02014-04-30 18:49:19 +02009849 { "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 +02009850 { "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 +02009851#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
Emeric Brun645ae792014-04-30 14:21:06 +02009852 { "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 -04009853#endif
Emmanuel Hocdet839af572019-05-14 16:27:35 +02009854#if HA_OPENSSL_VERSION_NUMBER >= 0x10100000L
Patrick Hemmer65674662019-06-04 08:13:03 -04009855 { "ssl_bc_client_random", smp_fetch_ssl_fc_random, 0, NULL, SMP_T_BIN, SMP_USE_L5SRV },
9856 { "ssl_bc_server_random", smp_fetch_ssl_fc_random, 0, NULL, SMP_T_BIN, SMP_USE_L5SRV },
Patrick Hemmere0275472018-04-28 19:15:51 -04009857 { "ssl_bc_session_key", smp_fetch_ssl_fc_session_key, 0, NULL, SMP_T_BIN, SMP_USE_L5SRV },
9858#endif
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02009859 { "ssl_c_ca_err", smp_fetch_ssl_c_ca_err, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
9860 { "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 +01009861 { "ssl_c_der", smp_fetch_ssl_x_der, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02009862 { "ssl_c_err", smp_fetch_ssl_c_err, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Emeric Brunba841a12014-04-30 17:05:08 +02009863 { "ssl_c_i_dn", smp_fetch_ssl_x_i_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
9864 { "ssl_c_key_alg", smp_fetch_ssl_x_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
9865 { "ssl_c_notafter", smp_fetch_ssl_x_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
9866 { "ssl_c_notbefore", smp_fetch_ssl_x_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
9867 { "ssl_c_sig_alg", smp_fetch_ssl_x_sig_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
9868 { "ssl_c_s_dn", smp_fetch_ssl_x_s_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
9869 { "ssl_c_serial", smp_fetch_ssl_x_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
9870 { "ssl_c_sha1", smp_fetch_ssl_x_sha1, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +01009871 { "ssl_c_used", smp_fetch_ssl_c_used, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02009872 { "ssl_c_verify", smp_fetch_ssl_c_verify, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
9873 { "ssl_c_version", smp_fetch_ssl_x_version, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Emeric Brun43e79582014-10-29 19:03:26 +01009874 { "ssl_f_der", smp_fetch_ssl_x_der, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Emeric Brunba841a12014-04-30 17:05:08 +02009875 { "ssl_f_i_dn", smp_fetch_ssl_x_i_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
9876 { "ssl_f_key_alg", smp_fetch_ssl_x_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
9877 { "ssl_f_notafter", smp_fetch_ssl_x_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
9878 { "ssl_f_notbefore", smp_fetch_ssl_x_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
9879 { "ssl_f_sig_alg", smp_fetch_ssl_x_sig_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
9880 { "ssl_f_s_dn", smp_fetch_ssl_x_s_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
9881 { "ssl_f_serial", smp_fetch_ssl_x_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Emeric Brun55f4fa82014-04-30 17:11:25 +02009882 { "ssl_f_sha1", smp_fetch_ssl_x_sha1, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02009883 { "ssl_f_version", smp_fetch_ssl_x_version, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +01009884 { "ssl_fc", smp_fetch_ssl_fc, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02009885 { "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 +01009886 { "ssl_fc_cipher", smp_fetch_ssl_fc_cipher, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +01009887 { "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 +02009888 { "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 +01009889 { "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 +02009890 { "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 +01009891#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01009892 { "ssl_fc_npn", smp_fetch_ssl_fc_npn, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreaua33c6542012-10-15 13:19:06 +02009893#endif
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01009894#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01009895 { "ssl_fc_alpn", smp_fetch_ssl_fc_alpn, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreauab861d32013-04-02 02:30:41 +02009896#endif
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01009897 { "ssl_fc_protocol", smp_fetch_ssl_fc_protocol, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreau9a1ab082019-05-09 13:26:41 +02009898#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
Emeric Brunb73a9b02014-04-30 18:49:19 +02009899 { "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 -04009900#endif
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02009901 { "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 +02009902#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01009903 { "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 -04009904#endif
Emmanuel Hocdet839af572019-05-14 16:27:35 +02009905#if HA_OPENSSL_VERSION_NUMBER >= 0x10100000L
Patrick Hemmer65674662019-06-04 08:13:03 -04009906 { "ssl_fc_client_random", smp_fetch_ssl_fc_random, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
9907 { "ssl_fc_server_random", smp_fetch_ssl_fc_random, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Patrick Hemmere0275472018-04-28 19:15:51 -04009908 { "ssl_fc_session_key", smp_fetch_ssl_fc_session_key, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
9909#endif
Patrick Hemmer41966772018-04-28 19:15:48 -04009910#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01009911 { "ssl_fc_sni", smp_fetch_ssl_fc_sni, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Patrick Hemmer41966772018-04-28 19:15:48 -04009912#endif
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01009913 { "ssl_fc_cipherlist_bin", smp_fetch_ssl_fc_cl_bin, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
9914 { "ssl_fc_cipherlist_hex", smp_fetch_ssl_fc_cl_hex, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
9915 { "ssl_fc_cipherlist_str", smp_fetch_ssl_fc_cl_str, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
9916 { "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 +02009917 { NULL, NULL, 0, 0, 0 },
9918}};
9919
Willy Tarreau0108d902018-11-25 19:14:37 +01009920INITCALL1(STG_REGISTER, sample_register_fetches, &sample_fetch_keywords);
9921
Willy Tarreau7875d092012-09-10 08:20:03 +02009922/* Note: must not be declared <const> as its list will be overwritten.
9923 * Please take care of keeping this list alphabetically sorted.
9924 */
Willy Tarreaudc13c112013-06-21 23:16:39 +02009925static struct acl_kw_list acl_kws = {ILH, {
Thierry FOURNIERc5a4e982014-03-05 16:07:08 +01009926 { "ssl_fc_sni_end", "ssl_fc_sni", PAT_MATCH_END },
9927 { "ssl_fc_sni_reg", "ssl_fc_sni", PAT_MATCH_REG },
Willy Tarreau8ed669b2013-01-11 15:49:37 +01009928 { /* END */ },
Willy Tarreau7875d092012-09-10 08:20:03 +02009929}};
9930
Willy Tarreau0108d902018-11-25 19:14:37 +01009931INITCALL1(STG_REGISTER, acl_register_keywords, &acl_kws);
9932
Willy Tarreau79eeafa2012-09-14 07:53:05 +02009933/* Note: must not be declared <const> as its list will be overwritten.
9934 * Please take care of keeping this list alphabetically sorted, doing so helps
9935 * all code contributors.
9936 * Optional keywords are also declared with a NULL ->parse() function so that
9937 * the config parser can report an appropriate error when a known keyword was
9938 * not enabled.
9939 */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01009940static struct ssl_bind_kw ssl_bind_kws[] = {
Olivier Houchardc2aae742017-09-22 18:26:28 +02009941 { "allow-0rtt", ssl_bind_parse_allow_0rtt, 0 }, /* allow 0-RTT */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01009942 { "alpn", ssl_bind_parse_alpn, 1 }, /* set ALPN supported protocols */
9943 { "ca-file", ssl_bind_parse_ca_file, 1 }, /* set CAfile to process verify on client cert */
9944 { "ciphers", ssl_bind_parse_ciphers, 1 }, /* set SSL cipher suite */
Emmanuel Hocdet839af572019-05-14 16:27:35 +02009945#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009946 { "ciphersuites", ssl_bind_parse_ciphersuites, 1 }, /* set TLS 1.3 cipher suite */
9947#endif
Emmanuel Hocdet98263292016-12-29 18:26:15 +01009948 { "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 +01009949 { "curves", ssl_bind_parse_curves, 1 }, /* set SSL curve suite */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01009950 { "ecdhe", ssl_bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02009951 { "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 +01009952 { "npn", ssl_bind_parse_npn, 1 }, /* set NPN supported protocols */
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02009953 { "ssl-min-ver", ssl_bind_parse_tls_method_minmax,1 }, /* minimum version */
9954 { "ssl-max-ver", ssl_bind_parse_tls_method_minmax,1 }, /* maximum version */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01009955 { "verify", ssl_bind_parse_verify, 1 }, /* set SSL verify method */
9956 { NULL, NULL, 0 },
9957};
9958
Willy Tarreau0108d902018-11-25 19:14:37 +01009959/* no initcall for ssl_bind_kws, these ones are parsed in the parser loop */
9960
Willy Tarreau51fb7652012-09-18 18:24:39 +02009961static struct bind_kw_list bind_kws = { "SSL", { }, {
Olivier Houchardc2aae742017-09-22 18:26:28 +02009962 { "allow-0rtt", bind_parse_allow_0rtt, 0 }, /* Allow 0RTT */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02009963 { "alpn", bind_parse_alpn, 1 }, /* set ALPN supported protocols */
9964 { "ca-file", bind_parse_ca_file, 1 }, /* set CAfile to process verify on client cert */
9965 { "ca-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ignore on verify depth > 0 */
9966 { "ca-sign-file", bind_parse_ca_sign_file, 1 }, /* set CAFile used to generate and sign server certs */
9967 { "ca-sign-pass", bind_parse_ca_sign_pass, 1 }, /* set CAKey passphrase */
9968 { "ciphers", bind_parse_ciphers, 1 }, /* set SSL cipher suite */
Emmanuel Hocdet839af572019-05-14 16:27:35 +02009969#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009970 { "ciphersuites", bind_parse_ciphersuites, 1 }, /* set TLS 1.3 cipher suite */
9971#endif
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02009972 { "crl-file", bind_parse_crl_file, 1 }, /* set certificat revocation list file use on client cert verify */
9973 { "crt", bind_parse_crt, 1 }, /* load SSL certificates from this location */
9974 { "crt-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ingore on verify depth == 0 */
9975 { "crt-list", bind_parse_crt_list, 1 }, /* load a list of crt from this location */
9976 { "curves", bind_parse_curves, 1 }, /* set SSL curve suite */
9977 { "ecdhe", bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
9978 { "force-sslv3", bind_parse_tls_method_options, 0 }, /* force SSLv3 */
9979 { "force-tlsv10", bind_parse_tls_method_options, 0 }, /* force TLSv10 */
9980 { "force-tlsv11", bind_parse_tls_method_options, 0 }, /* force TLSv11 */
9981 { "force-tlsv12", bind_parse_tls_method_options, 0 }, /* force TLSv12 */
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +02009982 { "force-tlsv13", bind_parse_tls_method_options, 0 }, /* force TLSv13 */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02009983 { "generate-certificates", bind_parse_generate_certs, 0 }, /* enable the server certificates generation */
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02009984 { "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 +02009985 { "no-sslv3", bind_parse_tls_method_options, 0 }, /* disable SSLv3 */
9986 { "no-tlsv10", bind_parse_tls_method_options, 0 }, /* disable TLSv10 */
9987 { "no-tlsv11", bind_parse_tls_method_options, 0 }, /* disable TLSv11 */
9988 { "no-tlsv12", bind_parse_tls_method_options, 0 }, /* disable TLSv12 */
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +02009989 { "no-tlsv13", bind_parse_tls_method_options, 0 }, /* disable TLSv13 */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02009990 { "no-tls-tickets", bind_parse_no_tls_tickets, 0 }, /* disable session resumption tickets */
9991 { "ssl", bind_parse_ssl, 0 }, /* enable SSL processing */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02009992 { "ssl-min-ver", bind_parse_tls_method_minmax, 1 }, /* minimum version */
9993 { "ssl-max-ver", bind_parse_tls_method_minmax, 1 }, /* maximum version */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02009994 { "strict-sni", bind_parse_strict_sni, 0 }, /* refuse negotiation if sni doesn't match a certificate */
9995 { "tls-ticket-keys", bind_parse_tls_ticket_keys, 1 }, /* set file to load TLS ticket keys from */
9996 { "verify", bind_parse_verify, 1 }, /* set SSL verify method */
9997 { "npn", bind_parse_npn, 1 }, /* set NPN supported protocols */
9998 { "prefer-client-ciphers", bind_parse_pcc, 0 }, /* prefer client ciphers */
Willy Tarreau79eeafa2012-09-14 07:53:05 +02009999 { NULL, NULL, 0 },
10000}};
Emeric Brun46591952012-05-18 15:47:34 +020010001
Willy Tarreau0108d902018-11-25 19:14:37 +010010002INITCALL1(STG_REGISTER, bind_register_keywords, &bind_kws);
10003
Willy Tarreau92faadf2012-10-10 23:04:25 +020010004/* Note: must not be declared <const> as its list will be overwritten.
10005 * Please take care of keeping this list alphabetically sorted, doing so helps
10006 * all code contributors.
10007 * Optional keywords are also declared with a NULL ->parse() function so that
10008 * the config parser can report an appropriate error when a known keyword was
10009 * not enabled.
10010 */
10011static struct srv_kw_list srv_kws = { "SSL", { }, {
Olivier Houchard522eea72017-11-03 16:27:47 +010010012 { "allow-0rtt", srv_parse_allow_0rtt, 0, 1 }, /* Allow using early data on this server */
Olivier Houchardc7566002018-11-20 23:33:50 +010010013 { "alpn", srv_parse_alpn, 1, 1 }, /* Set ALPN supported protocols */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +020010014 { "ca-file", srv_parse_ca_file, 1, 1 }, /* set CAfile to process verify server cert */
Olivier Houchard92150142018-12-21 19:47:01 +010010015 { "check-alpn", srv_parse_alpn, 1, 1 }, /* Set ALPN used for checks */
Olivier Houchard9130a962017-10-17 17:33:43 +020010016 { "check-sni", srv_parse_check_sni, 1, 1 }, /* set SNI */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +020010017 { "check-ssl", srv_parse_check_ssl, 0, 1 }, /* enable SSL for health checks */
10018 { "ciphers", srv_parse_ciphers, 1, 1 }, /* select the cipher suite */
Emmanuel Hocdet839af572019-05-14 16:27:35 +020010019#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +020010020 { "ciphersuites", srv_parse_ciphersuites, 1, 1 }, /* select the cipher suite */
10021#endif
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +020010022 { "crl-file", srv_parse_crl_file, 1, 1 }, /* set certificate revocation list file use on server cert verify */
10023 { "crt", srv_parse_crt, 1, 1 }, /* set client certificate */
10024 { "force-sslv3", srv_parse_tls_method_options, 0, 1 }, /* force SSLv3 */
10025 { "force-tlsv10", srv_parse_tls_method_options, 0, 1 }, /* force TLSv10 */
10026 { "force-tlsv11", srv_parse_tls_method_options, 0, 1 }, /* force TLSv11 */
10027 { "force-tlsv12", srv_parse_tls_method_options, 0, 1 }, /* force TLSv12 */
10028 { "force-tlsv13", srv_parse_tls_method_options, 0, 1 }, /* force TLSv13 */
10029 { "no-check-ssl", srv_parse_no_check_ssl, 0, 1 }, /* disable SSL for health checks */
10030 { "no-send-proxy-v2-ssl", srv_parse_no_send_proxy_ssl, 0, 1 }, /* do not send PROXY protocol header v2 with SSL info */
10031 { "no-send-proxy-v2-ssl-cn", srv_parse_no_send_proxy_cn, 0, 1 }, /* do not send PROXY protocol header v2 with CN */
10032 { "no-ssl", srv_parse_no_ssl, 0, 1 }, /* disable SSL processing */
10033 { "no-ssl-reuse", srv_parse_no_ssl_reuse, 0, 1 }, /* disable session reuse */
10034 { "no-sslv3", srv_parse_tls_method_options, 0, 0 }, /* disable SSLv3 */
10035 { "no-tlsv10", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv10 */
10036 { "no-tlsv11", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv11 */
10037 { "no-tlsv12", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv12 */
10038 { "no-tlsv13", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv13 */
10039 { "no-tls-tickets", srv_parse_no_tls_tickets, 0, 1 }, /* disable session resumption tickets */
Olivier Houchardc7566002018-11-20 23:33:50 +010010040 { "npn", srv_parse_npn, 1, 1 }, /* Set NPN supported protocols */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +020010041 { "send-proxy-v2-ssl", srv_parse_send_proxy_ssl, 0, 1 }, /* send PROXY protocol header v2 with SSL info */
10042 { "send-proxy-v2-ssl-cn", srv_parse_send_proxy_cn, 0, 1 }, /* send PROXY protocol header v2 with CN */
10043 { "sni", srv_parse_sni, 1, 1 }, /* send SNI extension */
10044 { "ssl", srv_parse_ssl, 0, 1 }, /* enable SSL processing */
10045 { "ssl-min-ver", srv_parse_tls_method_minmax, 1, 1 }, /* minimum version */
10046 { "ssl-max-ver", srv_parse_tls_method_minmax, 1, 1 }, /* maximum version */
10047 { "ssl-reuse", srv_parse_ssl_reuse, 0, 1 }, /* enable session reuse */
10048 { "tls-tickets", srv_parse_tls_tickets, 0, 1 }, /* enable session resumption tickets */
10049 { "verify", srv_parse_verify, 1, 1 }, /* set SSL verify method */
10050 { "verifyhost", srv_parse_verifyhost, 1, 1 }, /* require that SSL cert verifies for hostname */
Willy Tarreau92faadf2012-10-10 23:04:25 +020010051 { NULL, NULL, 0, 0 },
10052}};
10053
Willy Tarreau0108d902018-11-25 19:14:37 +010010054INITCALL1(STG_REGISTER, srv_register_keywords, &srv_kws);
10055
Emeric Brun2c86cbf2014-10-30 15:56:50 +010010056static struct cfg_kw_list cfg_kws = {ILH, {
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +010010057 { CFG_GLOBAL, "ca-base", ssl_parse_global_ca_crt_base },
10058 { CFG_GLOBAL, "crt-base", ssl_parse_global_ca_crt_base },
Willy Tarreau0bea58d2016-12-21 23:17:25 +010010059 { CFG_GLOBAL, "maxsslconn", ssl_parse_global_int },
Emeric Brun2c86cbf2014-10-30 15:56:50 +010010060 { CFG_GLOBAL, "ssl-default-bind-options", ssl_parse_default_bind_options },
10061 { CFG_GLOBAL, "ssl-default-server-options", ssl_parse_default_server_options },
Willy Tarreau14e36a12016-12-21 23:28:13 +010010062#ifndef OPENSSL_NO_DH
10063 { CFG_GLOBAL, "ssl-dh-param-file", ssl_parse_global_dh_param_file },
10064#endif
Grant Zhangfa6c7ee2017-01-14 01:42:15 +000010065 { CFG_GLOBAL, "ssl-mode-async", ssl_parse_global_ssl_async },
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020010066#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +000010067 { CFG_GLOBAL, "ssl-engine", ssl_parse_global_ssl_engine },
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020010068#endif
Willy Tarreau9ceda382016-12-21 23:13:03 +010010069 { CFG_GLOBAL, "tune.ssl.cachesize", ssl_parse_global_int },
10070#ifndef OPENSSL_NO_DH
10071 { CFG_GLOBAL, "tune.ssl.default-dh-param", ssl_parse_global_default_dh },
10072#endif
10073 { CFG_GLOBAL, "tune.ssl.force-private-cache", ssl_parse_global_private_cache },
10074 { CFG_GLOBAL, "tune.ssl.lifetime", ssl_parse_global_lifetime },
10075 { CFG_GLOBAL, "tune.ssl.maxrecord", ssl_parse_global_int },
10076 { CFG_GLOBAL, "tune.ssl.ssl-ctx-cache-size", ssl_parse_global_int },
Thierry FOURNIER5bf77322017-02-25 12:45:22 +010010077 { CFG_GLOBAL, "tune.ssl.capture-cipherlist-size", ssl_parse_global_capture_cipherlist },
Willy Tarreauf22e9682016-12-21 23:23:19 +010010078 { CFG_GLOBAL, "ssl-default-bind-ciphers", ssl_parse_global_ciphers },
10079 { CFG_GLOBAL, "ssl-default-server-ciphers", ssl_parse_global_ciphers },
Emmanuel Hocdet839af572019-05-14 16:27:35 +020010080#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +020010081 { CFG_GLOBAL, "ssl-default-bind-ciphersuites", ssl_parse_global_ciphersuites },
10082 { CFG_GLOBAL, "ssl-default-server-ciphersuites", ssl_parse_global_ciphersuites },
10083#endif
Emeric Brun2c86cbf2014-10-30 15:56:50 +010010084 { 0, NULL, NULL },
10085}};
10086
Willy Tarreau0108d902018-11-25 19:14:37 +010010087INITCALL1(STG_REGISTER, cfg_register_keywords, &cfg_kws);
10088
Nenad Merdanovicc31499d2019-03-23 11:00:32 +010010089/* Note: must not be declared <const> as its list will be overwritten */
10090static struct sample_conv_kw_list conv_kws = {ILH, {
Willy Tarreau86a394e2019-05-09 14:15:32 +020010091#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000100fL)
Nenad Merdanovicc31499d2019-03-23 11:00:32 +010010092 { "aes_gcm_dec", sample_conv_aes_gcm_dec, ARG4(4,SINT,STR,STR,STR), check_aes_gcm, SMP_T_BIN, SMP_T_BIN },
10093#endif
10094 { NULL, NULL, 0, 0, 0 },
10095}};
10096
10097INITCALL1(STG_REGISTER, sample_register_convs, &conv_kws);
10098
Willy Tarreauf7bc57c2012-10-03 00:19:48 +020010099/* transport-layer operations for SSL sockets */
Willy Tarreaud9f5cca2016-12-22 21:08:52 +010010100static struct xprt_ops ssl_sock = {
Emeric Brun46591952012-05-18 15:47:34 +020010101 .snd_buf = ssl_sock_from_buf,
10102 .rcv_buf = ssl_sock_to_buf,
Olivier Houcharddf357842019-03-21 16:30:07 +010010103 .subscribe = ssl_subscribe,
10104 .unsubscribe = ssl_unsubscribe,
Olivier Houchard5149b592019-05-23 17:47:36 +020010105 .remove_xprt = ssl_remove_xprt,
Olivier Houchard2e055482019-05-27 19:50:12 +020010106 .add_xprt = ssl_add_xprt,
Emeric Brun46591952012-05-18 15:47:34 +020010107 .rcv_pipe = NULL,
10108 .snd_pipe = NULL,
10109 .shutr = NULL,
10110 .shutw = ssl_sock_shutw,
10111 .close = ssl_sock_close,
10112 .init = ssl_sock_init,
Willy Tarreau55d37912016-12-21 23:38:39 +010010113 .prepare_bind_conf = ssl_sock_prepare_bind_conf,
Willy Tarreau795cdab2016-12-22 17:30:54 +010010114 .destroy_bind_conf = ssl_sock_destroy_bind_conf,
Willy Tarreau17d45382016-12-22 21:16:08 +010010115 .prepare_srv = ssl_sock_prepare_srv_ctx,
10116 .destroy_srv = ssl_sock_free_srv_ctx,
Willy Tarreau8743f7e2016-12-04 18:44:29 +010010117 .get_alpn = ssl_sock_get_alpn,
Willy Tarreau8e0bb0a2016-11-24 16:58:12 +010010118 .name = "SSL",
Emeric Brun46591952012-05-18 15:47:34 +020010119};
10120
Olivier Houchardccaa7de2017-10-02 11:51:03 +020010121enum act_return ssl_action_wait_for_hs(struct act_rule *rule, struct proxy *px,
10122 struct session *sess, struct stream *s, int flags)
10123{
10124 struct connection *conn;
Olivier Houchard6fa63d92017-11-27 18:41:32 +010010125 struct conn_stream *cs;
Olivier Houchardccaa7de2017-10-02 11:51:03 +020010126
10127 conn = objt_conn(sess->origin);
Olivier Houchard6fa63d92017-11-27 18:41:32 +010010128 cs = objt_cs(s->si[0].end);
Olivier Houchardccaa7de2017-10-02 11:51:03 +020010129
Olivier Houchard6fa63d92017-11-27 18:41:32 +010010130 if (conn && cs) {
Olivier Houchardccaa7de2017-10-02 11:51:03 +020010131 if (conn->flags & (CO_FL_EARLY_SSL_HS | CO_FL_SSL_WAIT_HS)) {
Olivier Houchard6fa63d92017-11-27 18:41:32 +010010132 cs->flags |= CS_FL_WAIT_FOR_HS;
Olivier Houchardccaa7de2017-10-02 11:51:03 +020010133 s->req.flags |= CF_READ_NULL;
10134 return ACT_RET_YIELD;
10135 }
10136 }
10137 return (ACT_RET_CONT);
10138}
10139
10140static enum act_parse_ret ssl_parse_wait_for_hs(const char **args, int *orig_arg, struct proxy *px, struct act_rule *rule, char **err)
10141{
10142 rule->action_ptr = ssl_action_wait_for_hs;
10143
10144 return ACT_RET_PRS_OK;
10145}
10146
10147static struct action_kw_list http_req_actions = {ILH, {
10148 { "wait-for-handshake", ssl_parse_wait_for_hs },
10149 { /* END */ }
10150}};
10151
Willy Tarreau0108d902018-11-25 19:14:37 +010010152INITCALL1(STG_REGISTER, http_req_keywords_register, &http_req_actions);
10153
Willy Tarreau5db847a2019-05-09 14:13:35 +020010154#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +010010155
10156static void ssl_sock_sctl_free_func(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, long argl, void *argp)
10157{
10158 if (ptr) {
10159 chunk_destroy(ptr);
10160 free(ptr);
10161 }
10162}
10163
10164#endif
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +010010165static void ssl_sock_capture_free_func(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, long argl, void *argp)
10166{
Willy Tarreaubafbe012017-11-24 17:34:44 +010010167 pool_free(pool_head_ssl_capture, ptr);
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +010010168}
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +010010169
Emeric Brun46591952012-05-18 15:47:34 +020010170__attribute__((constructor))
Willy Tarreau92faadf2012-10-10 23:04:25 +020010171static void __ssl_sock_init(void)
10172{
Ilya Shipitsin0590f442019-05-25 19:30:50 +050010173#if (!defined(OPENSSL_NO_COMP) && !defined(SSL_OP_NO_COMPRESSION))
Emeric Brun46591952012-05-18 15:47:34 +020010174 STACK_OF(SSL_COMP)* cm;
Ilya Shipitsine242f3d2019-05-25 03:38:14 +050010175 int n;
Ilya Shipitsin0590f442019-05-25 19:30:50 +050010176#endif
Emeric Brun46591952012-05-18 15:47:34 +020010177
Willy Tarreauef934602016-12-22 23:12:01 +010010178 if (global_ssl.listen_default_ciphers)
10179 global_ssl.listen_default_ciphers = strdup(global_ssl.listen_default_ciphers);
10180 if (global_ssl.connect_default_ciphers)
10181 global_ssl.connect_default_ciphers = strdup(global_ssl.connect_default_ciphers);
Emmanuel Hocdet839af572019-05-14 16:27:35 +020010182#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +020010183 if (global_ssl.listen_default_ciphersuites)
10184 global_ssl.listen_default_ciphersuites = strdup(global_ssl.listen_default_ciphersuites);
10185 if (global_ssl.connect_default_ciphersuites)
10186 global_ssl.connect_default_ciphersuites = strdup(global_ssl.connect_default_ciphersuites);
10187#endif
Willy Tarreau610f04b2014-02-13 11:36:41 +010010188
Willy Tarreau13e14102016-12-22 20:25:26 +010010189 xprt_register(XPRT_SSL, &ssl_sock);
Willy Tarreau9a1ab082019-05-09 13:26:41 +020010190#if HA_OPENSSL_VERSION_NUMBER < 0x10100000L
Emeric Brun46591952012-05-18 15:47:34 +020010191 SSL_library_init();
Rosen Penev68185952018-12-14 08:47:02 -080010192#endif
Ilya Shipitsin0590f442019-05-25 19:30:50 +050010193#if (!defined(OPENSSL_NO_COMP) && !defined(SSL_OP_NO_COMPRESSION))
Emeric Brun46591952012-05-18 15:47:34 +020010194 cm = SSL_COMP_get_compression_methods();
Ilya Shipitsine242f3d2019-05-25 03:38:14 +050010195 n = sk_SSL_COMP_num(cm);
10196 while (n--) {
10197 (void) sk_SSL_COMP_pop(cm);
10198 }
Ilya Shipitsin0590f442019-05-25 19:30:50 +050010199#endif
Ilya Shipitsine242f3d2019-05-25 03:38:14 +050010200
Willy Tarreau5db847a2019-05-09 14:13:35 +020010201#if defined(USE_THREAD) && (HA_OPENSSL_VERSION_NUMBER < 0x10100000L)
Emeric Brun821bb9b2017-06-15 16:37:39 +020010202 ssl_locking_init();
10203#endif
Willy Tarreau5db847a2019-05-09 14:13:35 +020010204#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +010010205 sctl_ex_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, ssl_sock_sctl_free_func);
10206#endif
Thierry FOURNIER28962c92018-06-17 21:37:05 +020010207 ssl_app_data_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL);
Thierry FOURNIER16ff0502018-06-17 21:33:01 +020010208 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 +010010209 ssl_pkey_info_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, NULL);
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020010210#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +000010211 ENGINE_load_builtin_engines();
Grant Zhangfa6c7ee2017-01-14 01:42:15 +000010212 hap_register_post_check(ssl_check_async_engine_count);
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020010213#endif
Willy Tarreaud1c57502016-12-22 22:46:15 +010010214#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
10215 hap_register_post_check(tlskeys_finalize_config);
10216#endif
Willy Tarreau80713382018-11-26 10:19:54 +010010217
10218 global.ssl_session_max_cost = SSL_SESSION_MAX_COST;
10219 global.ssl_handshake_max_cost = SSL_HANDSHAKE_MAX_COST;
10220
10221#ifndef OPENSSL_NO_DH
10222 ssl_dh_ptr_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, NULL);
10223 hap_register_post_deinit(ssl_free_dh);
10224#endif
10225#ifndef OPENSSL_NO_ENGINE
10226 hap_register_post_deinit(ssl_free_engines);
10227#endif
10228 /* Load SSL string for the verbose & debug mode. */
10229 ERR_load_SSL_strings();
Olivier Houcharda8955d52019-04-07 22:00:38 +020010230 ha_meth = BIO_meth_new(0x666, "ha methods");
10231 BIO_meth_set_write(ha_meth, ha_ssl_write);
10232 BIO_meth_set_read(ha_meth, ha_ssl_read);
10233 BIO_meth_set_ctrl(ha_meth, ha_ssl_ctrl);
10234 BIO_meth_set_create(ha_meth, ha_ssl_new);
10235 BIO_meth_set_destroy(ha_meth, ha_ssl_free);
10236 BIO_meth_set_puts(ha_meth, ha_ssl_puts);
10237 BIO_meth_set_gets(ha_meth, ha_ssl_gets);
Willy Tarreau80713382018-11-26 10:19:54 +010010238}
Willy Tarreaud92aa5c2015-01-15 21:34:39 +010010239
Willy Tarreau80713382018-11-26 10:19:54 +010010240/* Compute and register the version string */
10241static void ssl_register_build_options()
10242{
10243 char *ptr = NULL;
10244 int i;
10245
Willy Tarreauc2c0b612016-12-21 19:23:20 +010010246 memprintf(&ptr, "Built with OpenSSL version : "
10247#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet50e25e12017-03-24 15:20:03 +010010248 "BoringSSL");
Willy Tarreauc2c0b612016-12-21 19:23:20 +010010249#else /* OPENSSL_IS_BORINGSSL */
10250 OPENSSL_VERSION_TEXT
10251 "\nRunning on OpenSSL version : %s%s",
Rosen Penev68185952018-12-14 08:47:02 -080010252 OpenSSL_version(OPENSSL_VERSION),
Willy Tarreau1d158ab2019-05-09 13:41:45 +020010253 ((OPENSSL_VERSION_NUMBER ^ OpenSSL_version_num()) >> 8) ? " (VERSIONS DIFFER!)" : "");
Willy Tarreauc2c0b612016-12-21 19:23:20 +010010254#endif
10255 memprintf(&ptr, "%s\nOpenSSL library supports TLS extensions : "
Willy Tarreau9a1ab082019-05-09 13:26:41 +020010256#if HA_OPENSSL_VERSION_NUMBER < 0x00907000L
Willy Tarreauc2c0b612016-12-21 19:23:20 +010010257 "no (library version too old)"
10258#elif defined(OPENSSL_NO_TLSEXT)
10259 "no (disabled via OPENSSL_NO_TLSEXT)"
10260#else
10261 "yes"
10262#endif
10263 "", ptr);
10264
10265 memprintf(&ptr, "%s\nOpenSSL library supports SNI : "
10266#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
10267 "yes"
10268#else
10269#ifdef OPENSSL_NO_TLSEXT
10270 "no (because of OPENSSL_NO_TLSEXT)"
10271#else
10272 "no (version might be too old, 0.9.8f min needed)"
10273#endif
10274#endif
10275 "", ptr);
10276
Emmanuel Hocdetf80bc242017-07-12 14:25:38 +020010277 memprintf(&ptr, "%s\nOpenSSL library supports :", ptr);
10278 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
10279 if (methodVersions[i].option)
10280 memprintf(&ptr, "%s %s", ptr, methodVersions[i].name);
Emmanuel Hocdet50e25e12017-03-24 15:20:03 +010010281
Willy Tarreauc2c0b612016-12-21 19:23:20 +010010282 hap_register_build_opts(ptr, 1);
Willy Tarreau80713382018-11-26 10:19:54 +010010283}
Willy Tarreauc2c0b612016-12-21 19:23:20 +010010284
Willy Tarreau80713382018-11-26 10:19:54 +010010285INITCALL0(STG_REGISTER, ssl_register_build_options);
Remi Gacogne4f902b82015-05-28 16:23:00 +020010286
Emeric Brun46591952012-05-18 15:47:34 +020010287
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020010288#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +000010289void ssl_free_engines(void) {
10290 struct ssl_engine_list *wl, *wlb;
10291 /* free up engine list */
10292 list_for_each_entry_safe(wl, wlb, &openssl_engines, list) {
10293 ENGINE_finish(wl->e);
10294 ENGINE_free(wl->e);
10295 LIST_DEL(&wl->list);
10296 free(wl);
10297 }
10298}
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020010299#endif
Christopher Faulet31af49d2015-06-09 17:29:50 +020010300
Remi Gacogned3a23c32015-05-28 16:39:47 +020010301#ifndef OPENSSL_NO_DH
Grant Zhang872f9c22017-01-21 01:10:18 +000010302void ssl_free_dh(void) {
10303 if (local_dh_1024) {
10304 DH_free(local_dh_1024);
10305 local_dh_1024 = NULL;
10306 }
10307 if (local_dh_2048) {
10308 DH_free(local_dh_2048);
10309 local_dh_2048 = NULL;
10310 }
10311 if (local_dh_4096) {
10312 DH_free(local_dh_4096);
10313 local_dh_4096 = NULL;
10314 }
Remi Gacogne47783ef2015-05-29 15:53:22 +020010315 if (global_dh) {
10316 DH_free(global_dh);
10317 global_dh = NULL;
10318 }
Grant Zhang872f9c22017-01-21 01:10:18 +000010319}
10320#endif
10321
10322__attribute__((destructor))
10323static void __ssl_sock_deinit(void)
10324{
10325#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Emeric Brun821bb9b2017-06-15 16:37:39 +020010326 if (ssl_ctx_lru_tree) {
10327 lru64_destroy(ssl_ctx_lru_tree);
Christopher Faulet2a944ee2017-11-07 10:42:54 +010010328 HA_RWLOCK_DESTROY(&ssl_ctx_lru_rwlock);
Emeric Brun821bb9b2017-06-15 16:37:39 +020010329 }
Remi Gacogned3a23c32015-05-28 16:39:47 +020010330#endif
10331
Willy Tarreau5db847a2019-05-09 14:13:35 +020010332#if (HA_OPENSSL_VERSION_NUMBER < 0x10100000L)
Remi Gacogned3a23c32015-05-28 16:39:47 +020010333 ERR_remove_state(0);
10334 ERR_free_strings();
10335
10336 EVP_cleanup();
Rosen Penev68185952018-12-14 08:47:02 -080010337#endif
Remi Gacogned3a23c32015-05-28 16:39:47 +020010338
Willy Tarreau5db847a2019-05-09 14:13:35 +020010339#if (HA_OPENSSL_VERSION_NUMBER >= 0x00907000L) && (HA_OPENSSL_VERSION_NUMBER < 0x10100000L)
Remi Gacogned3a23c32015-05-28 16:39:47 +020010340 CRYPTO_cleanup_all_ex_data();
10341#endif
Olivier Houcharda8955d52019-04-07 22:00:38 +020010342 BIO_meth_free(ha_meth);
Remi Gacogned3a23c32015-05-28 16:39:47 +020010343}
10344
10345
Emeric Brun46591952012-05-18 15:47:34 +020010346/*
10347 * Local variables:
10348 * c-indent-level: 8
10349 * c-basic-offset: 8
10350 * End:
10351 */