blob: e85e328e950320b4f47897fe6727a46389d05faf [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;
458 fprintf(stderr, "fd[%04x] OpenSSL error[0x%lx] %s: %s\n",
Willy Tarreau585744b2017-08-24 14:31:19 +0200459 (unsigned short)conn->handle.fd, ret,
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100460 ERR_func_error_string(ret), ERR_reason_error_string(ret));
461 }
462 }
463}
464
yanbzhube2774d2015-12-10 15:07:30 -0500465
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +0200466#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +0000467static int ssl_init_single_engine(const char *engine_id, const char *def_algorithms)
468{
469 int err_code = ERR_ABORT;
470 ENGINE *engine;
471 struct ssl_engine_list *el;
472
473 /* grab the structural reference to the engine */
474 engine = ENGINE_by_id(engine_id);
475 if (engine == NULL) {
Christopher Faulet767a84b2017-11-24 16:50:31 +0100476 ha_alert("ssl-engine %s: failed to get structural reference\n", engine_id);
Grant Zhang872f9c22017-01-21 01:10:18 +0000477 goto fail_get;
478 }
479
480 if (!ENGINE_init(engine)) {
481 /* the engine couldn't initialise, release it */
Christopher Faulet767a84b2017-11-24 16:50:31 +0100482 ha_alert("ssl-engine %s: failed to initialize\n", engine_id);
Grant Zhang872f9c22017-01-21 01:10:18 +0000483 goto fail_init;
484 }
485
486 if (ENGINE_set_default_string(engine, def_algorithms) == 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +0100487 ha_alert("ssl-engine %s: failed on ENGINE_set_default_string\n", engine_id);
Grant Zhang872f9c22017-01-21 01:10:18 +0000488 goto fail_set_method;
489 }
490
491 el = calloc(1, sizeof(*el));
492 el->e = engine;
493 LIST_ADD(&openssl_engines, &el->list);
Emeric Brunece0c332017-12-06 13:51:49 +0100494 nb_engines++;
495 if (global_ssl.async)
496 global.ssl_used_async_engines = nb_engines;
Grant Zhang872f9c22017-01-21 01:10:18 +0000497 return 0;
498
499fail_set_method:
500 /* release the functional reference from ENGINE_init() */
501 ENGINE_finish(engine);
502
503fail_init:
504 /* release the structural reference from ENGINE_by_id() */
505 ENGINE_free(engine);
506
507fail_get:
508 return err_code;
509}
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +0200510#endif
Grant Zhang872f9c22017-01-21 01:10:18 +0000511
Willy Tarreau5db847a2019-05-09 14:13:35 +0200512#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brun3854e012017-05-17 20:42:48 +0200513/*
514 * openssl async fd handler
515 */
Emeric Brund0e095c2019-04-19 17:15:28 +0200516void ssl_async_fd_handler(int fd)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000517{
Olivier Houchardea8dd942019-05-20 14:02:16 +0200518 struct ssl_sock_ctx *ctx = fdtab[fd].owner;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000519
Emeric Brun3854e012017-05-17 20:42:48 +0200520 /* fd is an async enfine fd, we must stop
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000521 * to poll this fd until it is requested
522 */
Emeric Brunbbc16542017-06-02 15:54:06 +0000523 fd_stop_recv(fd);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000524 fd_cant_recv(fd);
525
526 /* crypto engine is available, let's notify the associated
527 * connection that it can pursue its processing.
528 */
Olivier Houchard03abf2d2019-05-28 10:12:02 +0200529 ssl_sock_io_cb(NULL, ctx, 0);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000530}
531
Emeric Brun3854e012017-05-17 20:42:48 +0200532/*
533 * openssl async delayed SSL_free handler
534 */
Emeric Brund0e095c2019-04-19 17:15:28 +0200535void ssl_async_fd_free(int fd)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000536{
537 SSL *ssl = fdtab[fd].owner;
Emeric Brun3854e012017-05-17 20:42:48 +0200538 OSSL_ASYNC_FD all_fd[32];
539 size_t num_all_fds = 0;
540 int i;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000541
Emeric Brun3854e012017-05-17 20:42:48 +0200542 /* We suppose that the async job for a same SSL *
543 * are serialized. So if we are awake it is
544 * because the running job has just finished
545 * and we can remove all async fds safely
546 */
547 SSL_get_all_async_fds(ssl, NULL, &num_all_fds);
548 if (num_all_fds > 32) {
549 send_log(NULL, LOG_EMERG, "haproxy: openssl returns too many async fds. It seems a bug. Process may crash\n");
550 return;
551 }
552
553 SSL_get_all_async_fds(ssl, all_fd, &num_all_fds);
554 for (i=0 ; i < num_all_fds ; i++)
555 fd_remove(all_fd[i]);
556
557 /* Now we can safely call SSL_free, no more pending job in engines */
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000558 SSL_free(ssl);
Olivier Houchard2be5a4c2019-03-08 18:54:43 +0100559 _HA_ATOMIC_SUB(&sslconns, 1);
560 _HA_ATOMIC_SUB(&jobs, 1);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000561}
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000562/*
Emeric Brun3854e012017-05-17 20:42:48 +0200563 * function used to manage a returned SSL_ERROR_WANT_ASYNC
564 * and enable/disable polling for async fds
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000565 */
Olivier Houchardea8dd942019-05-20 14:02:16 +0200566static inline void ssl_async_process_fds(struct ssl_sock_ctx *ctx)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000567{
Willy Tarreaua9786b62018-01-25 07:22:13 +0100568 OSSL_ASYNC_FD add_fd[32];
Emeric Brun3854e012017-05-17 20:42:48 +0200569 OSSL_ASYNC_FD del_fd[32];
Olivier Houchardea8dd942019-05-20 14:02:16 +0200570 SSL *ssl = ctx->ssl;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000571 size_t num_add_fds = 0;
572 size_t num_del_fds = 0;
Emeric Brun3854e012017-05-17 20:42:48 +0200573 int i;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000574
575 SSL_get_changed_async_fds(ssl, NULL, &num_add_fds, NULL,
576 &num_del_fds);
Emeric Brun3854e012017-05-17 20:42:48 +0200577 if (num_add_fds > 32 || num_del_fds > 32) {
578 send_log(NULL, LOG_EMERG, "haproxy: openssl returns too many async fds. It seems a bug. Process may crash\n");
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000579 return;
580 }
581
Emeric Brun3854e012017-05-17 20:42:48 +0200582 SSL_get_changed_async_fds(ssl, add_fd, &num_add_fds, del_fd, &num_del_fds);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000583
Emeric Brun3854e012017-05-17 20:42:48 +0200584 /* We remove unused fds from the fdtab */
585 for (i=0 ; i < num_del_fds ; i++)
586 fd_remove(del_fd[i]);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000587
Emeric Brun3854e012017-05-17 20:42:48 +0200588 /* We add new fds to the fdtab */
589 for (i=0 ; i < num_add_fds ; i++) {
Olivier Houchardea8dd942019-05-20 14:02:16 +0200590 fd_insert(add_fd[i], ctx, ssl_async_fd_handler, tid_bit);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000591 }
592
Emeric Brun3854e012017-05-17 20:42:48 +0200593 num_add_fds = 0;
594 SSL_get_all_async_fds(ssl, NULL, &num_add_fds);
595 if (num_add_fds > 32) {
596 send_log(NULL, LOG_EMERG, "haproxy: openssl returns too many async fds. It seems a bug. Process may crash\n");
597 return;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000598 }
Emeric Brun3854e012017-05-17 20:42:48 +0200599
600 /* We activate the polling for all known async fds */
601 SSL_get_all_async_fds(ssl, add_fd, &num_add_fds);
Emeric Brunce9e01c2017-05-31 10:02:53 +0000602 for (i=0 ; i < num_add_fds ; i++) {
Emeric Brun3854e012017-05-17 20:42:48 +0200603 fd_want_recv(add_fd[i]);
Emeric Brunce9e01c2017-05-31 10:02:53 +0000604 /* To ensure that the fd cache won't be used
605 * We'll prefer to catch a real RD event
606 * because handling an EAGAIN on this fd will
607 * result in a context switch and also
608 * some engines uses a fd in blocking mode.
609 */
610 fd_cant_recv(add_fd[i]);
611 }
Emeric Brun3854e012017-05-17 20:42:48 +0200612
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000613}
614#endif
615
William Lallemandc33d83d2019-10-14 14:14:59 +0200616#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
Emeric Brun4f3c87a2014-06-20 15:46:13 +0200617/*
618 * This function returns the number of seconds elapsed
619 * since the Epoch, 1970-01-01 00:00:00 +0000 (UTC) and the
620 * date presented un ASN1_GENERALIZEDTIME.
621 *
622 * In parsing error case, it returns -1.
623 */
624static long asn1_generalizedtime_to_epoch(ASN1_GENERALIZEDTIME *d)
625{
626 long epoch;
627 char *p, *end;
628 const unsigned short month_offset[12] = {
629 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
630 };
631 int year, month;
632
633 if (!d || (d->type != V_ASN1_GENERALIZEDTIME)) return -1;
634
635 p = (char *)d->data;
636 end = p + d->length;
637
638 if (end - p < 4) return -1;
639 year = 1000 * (p[0] - '0') + 100 * (p[1] - '0') + 10 * (p[2] - '0') + p[3] - '0';
640 p += 4;
641 if (end - p < 2) return -1;
642 month = 10 * (p[0] - '0') + p[1] - '0';
643 if (month < 1 || month > 12) return -1;
644 /* Compute the number of seconds since 1 jan 1970 and the beginning of current month
645 We consider leap years and the current month (<marsh or not) */
646 epoch = ( ((year - 1970) * 365)
647 + ((year - (month < 3)) / 4 - (year - (month < 3)) / 100 + (year - (month < 3)) / 400)
648 - ((1970 - 1) / 4 - (1970 - 1) / 100 + (1970 - 1) / 400)
649 + month_offset[month-1]
650 ) * 24 * 60 * 60;
651 p += 2;
652 if (end - p < 2) return -1;
653 /* Add the number of seconds of completed days of current month */
654 epoch += (10 * (p[0] - '0') + p[1] - '0' - 1) * 24 * 60 * 60;
655 p += 2;
656 if (end - p < 2) return -1;
657 /* Add the completed hours of the current day */
658 epoch += (10 * (p[0] - '0') + p[1] - '0') * 60 * 60;
659 p += 2;
660 if (end - p < 2) return -1;
661 /* Add the completed minutes of the current hour */
662 epoch += (10 * (p[0] - '0') + p[1] - '0') * 60;
663 p += 2;
664 if (p == end) return -1;
665 /* Test if there is available seconds */
666 if (p[0] < '0' || p[0] > '9')
667 goto nosec;
668 if (end - p < 2) return -1;
669 /* Add the seconds of the current minute */
670 epoch += 10 * (p[0] - '0') + p[1] - '0';
671 p += 2;
672 if (p == end) return -1;
673 /* Ignore seconds float part if present */
674 if (p[0] == '.') {
675 do {
676 if (++p == end) return -1;
677 } while (p[0] >= '0' && p[0] <= '9');
678 }
679
680nosec:
681 if (p[0] == 'Z') {
682 if (end - p != 1) return -1;
683 return epoch;
684 }
685 else if (p[0] == '+') {
686 if (end - p != 5) return -1;
687 /* Apply timezone offset */
Frederik Deweerdt953917a2017-10-16 07:37:31 -0700688 return epoch - ((10 * (p[1] - '0') + p[2] - '0') * 60 * 60 + (10 * (p[3] - '0') + p[4] - '0')) * 60;
Emeric Brun4f3c87a2014-06-20 15:46:13 +0200689 }
690 else if (p[0] == '-') {
691 if (end - p != 5) return -1;
692 /* Apply timezone offset */
Frederik Deweerdt953917a2017-10-16 07:37:31 -0700693 return epoch + ((10 * (p[1] - '0') + p[2] - '0') * 60 * 60 + (10 * (p[3] - '0') + p[4] - '0')) * 60;
Emeric Brun4f3c87a2014-06-20 15:46:13 +0200694 }
695
696 return -1;
697}
698
William Lallemandc33d83d2019-10-14 14:14:59 +0200699/*
700 * struct alignment works here such that the key.key is the same as key_data
701 * Do not change the placement of key_data
702 */
703struct certificate_ocsp {
704 struct ebmb_node key;
705 unsigned char key_data[OCSP_MAX_CERTID_ASN1_LENGTH];
706 struct buffer response;
707 long expire;
708};
709
710struct ocsp_cbk_arg {
711 int is_single;
712 int single_kt;
713 union {
714 struct certificate_ocsp *s_ocsp;
715 /*
716 * m_ocsp will have multiple entries dependent on key type
717 * Entry 0 - DSA
718 * Entry 1 - ECDSA
719 * Entry 2 - RSA
720 */
721 struct certificate_ocsp *m_ocsp[SSL_SOCK_NUM_KEYTYPES];
722 };
723};
724
Emeric Brun1d3865b2014-06-20 15:37:32 +0200725static struct eb_root cert_ocsp_tree = EB_ROOT_UNIQUE;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200726
727/* This function starts to check if the OCSP response (in DER format) contained
728 * in chunk 'ocsp_response' is valid (else exits on error).
729 * If 'cid' is not NULL, it will be compared to the OCSP certificate ID
730 * contained in the OCSP Response and exits on error if no match.
731 * If it's a valid OCSP Response:
732 * If 'ocsp' is not NULL, the chunk is copied in the OCSP response's container
733 * pointed by 'ocsp'.
734 * If 'ocsp' is NULL, the function looks up into the OCSP response's
735 * containers tree (using as index the ASN1 form of the OCSP Certificate ID extracted
736 * from the response) and exits on error if not found. Finally, If an OCSP response is
737 * already present in the container, it will be overwritten.
738 *
739 * Note: OCSP response containing more than one OCSP Single response is not
740 * considered valid.
741 *
742 * Returns 0 on success, 1 in error case.
743 */
Willy Tarreau83061a82018-07-13 11:56:34 +0200744static int ssl_sock_load_ocsp_response(struct buffer *ocsp_response,
745 struct certificate_ocsp *ocsp,
746 OCSP_CERTID *cid, char **err)
Emeric Brun4147b2e2014-06-16 18:36:30 +0200747{
748 OCSP_RESPONSE *resp;
749 OCSP_BASICRESP *bs = NULL;
750 OCSP_SINGLERESP *sr;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200751 OCSP_CERTID *id;
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200752 unsigned char *p = (unsigned char *) ocsp_response->area;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200753 int rc , count_sr;
Emeric Brun13a6b482014-06-20 15:44:34 +0200754 ASN1_GENERALIZEDTIME *revtime, *thisupd, *nextupd = NULL;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200755 int reason;
756 int ret = 1;
757
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200758 resp = d2i_OCSP_RESPONSE(NULL, (const unsigned char **)&p,
759 ocsp_response->data);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200760 if (!resp) {
761 memprintf(err, "Unable to parse OCSP response");
762 goto out;
763 }
764
765 rc = OCSP_response_status(resp);
766 if (rc != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
767 memprintf(err, "OCSP response status not successful");
768 goto out;
769 }
770
771 bs = OCSP_response_get1_basic(resp);
772 if (!bs) {
773 memprintf(err, "Failed to get basic response from OCSP Response");
774 goto out;
775 }
776
777 count_sr = OCSP_resp_count(bs);
778 if (count_sr > 1) {
779 memprintf(err, "OCSP response ignored because contains multiple single responses (%d)", count_sr);
780 goto out;
781 }
782
783 sr = OCSP_resp_get0(bs, 0);
784 if (!sr) {
785 memprintf(err, "Failed to get OCSP single response");
786 goto out;
787 }
788
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200789 id = (OCSP_CERTID*)OCSP_SINGLERESP_get0_id(sr);
790
Emeric Brun4147b2e2014-06-16 18:36:30 +0200791 rc = OCSP_single_get0_status(sr, &reason, &revtime, &thisupd, &nextupd);
Emmanuel Hocdetef607052017-10-24 14:57:16 +0200792 if (rc != V_OCSP_CERTSTATUS_GOOD && rc != V_OCSP_CERTSTATUS_REVOKED) {
Emmanuel Hocdet872085c2017-10-10 15:18:52 +0200793 memprintf(err, "OCSP single response: certificate status is unknown");
Emeric Brun4147b2e2014-06-16 18:36:30 +0200794 goto out;
795 }
796
Emeric Brun13a6b482014-06-20 15:44:34 +0200797 if (!nextupd) {
798 memprintf(err, "OCSP single response: missing nextupdate");
799 goto out;
800 }
801
Emeric Brunc8b27b62014-06-19 14:16:17 +0200802 rc = OCSP_check_validity(thisupd, nextupd, OCSP_MAX_RESPONSE_TIME_SKEW, -1);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200803 if (!rc) {
804 memprintf(err, "OCSP single response: no longer valid.");
805 goto out;
806 }
807
808 if (cid) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200809 if (OCSP_id_cmp(id, cid)) {
Emeric Brun4147b2e2014-06-16 18:36:30 +0200810 memprintf(err, "OCSP single response: Certificate ID does not match certificate and issuer");
811 goto out;
812 }
813 }
814
815 if (!ocsp) {
816 unsigned char key[OCSP_MAX_CERTID_ASN1_LENGTH];
817 unsigned char *p;
818
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200819 rc = i2d_OCSP_CERTID(id, NULL);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200820 if (!rc) {
821 memprintf(err, "OCSP single response: Unable to encode Certificate ID");
822 goto out;
823 }
824
825 if (rc > OCSP_MAX_CERTID_ASN1_LENGTH) {
826 memprintf(err, "OCSP single response: Certificate ID too long");
827 goto out;
828 }
829
830 p = key;
831 memset(key, 0, OCSP_MAX_CERTID_ASN1_LENGTH);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200832 i2d_OCSP_CERTID(id, &p);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200833 ocsp = (struct certificate_ocsp *)ebmb_lookup(&cert_ocsp_tree, key, OCSP_MAX_CERTID_ASN1_LENGTH);
834 if (!ocsp) {
835 memprintf(err, "OCSP single response: Certificate ID does not match any certificate or issuer");
836 goto out;
837 }
838 }
839
840 /* According to comments on "chunk_dup", the
841 previous chunk buffer will be freed */
842 if (!chunk_dup(&ocsp->response, ocsp_response)) {
843 memprintf(err, "OCSP response: Memory allocation error");
844 goto out;
845 }
846
Emeric Brun4f3c87a2014-06-20 15:46:13 +0200847 ocsp->expire = asn1_generalizedtime_to_epoch(nextupd) - OCSP_MAX_RESPONSE_TIME_SKEW;
848
Emeric Brun4147b2e2014-06-16 18:36:30 +0200849 ret = 0;
850out:
Janusz Dziemidowicz8d710492017-03-08 16:59:41 +0100851 ERR_clear_error();
852
Emeric Brun4147b2e2014-06-16 18:36:30 +0200853 if (bs)
854 OCSP_BASICRESP_free(bs);
855
856 if (resp)
857 OCSP_RESPONSE_free(resp);
858
859 return ret;
860}
861/*
862 * External function use to update the OCSP response in the OCSP response's
863 * containers tree. The chunk 'ocsp_response' must contain the OCSP response
864 * to update in DER format.
865 *
866 * Returns 0 on success, 1 in error case.
867 */
Willy Tarreau83061a82018-07-13 11:56:34 +0200868int ssl_sock_update_ocsp_response(struct buffer *ocsp_response, char **err)
Emeric Brun4147b2e2014-06-16 18:36:30 +0200869{
870 return ssl_sock_load_ocsp_response(ocsp_response, NULL, NULL, err);
871}
872
873/*
874 * This function load the OCSP Resonse in DER format contained in file at
875 * path 'ocsp_path' and call 'ssl_sock_load_ocsp_response'
876 *
877 * Returns 0 on success, 1 in error case.
878 */
879static int ssl_sock_load_ocsp_response_from_file(const char *ocsp_path, struct certificate_ocsp *ocsp, OCSP_CERTID *cid, char **err)
880{
881 int fd = -1;
882 int r = 0;
883 int ret = 1;
884
885 fd = open(ocsp_path, O_RDONLY);
886 if (fd == -1) {
887 memprintf(err, "Error opening OCSP response file");
888 goto end;
889 }
890
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200891 trash.data = 0;
892 while (trash.data < trash.size) {
893 r = read(fd, trash.area + trash.data, trash.size - trash.data);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200894 if (r < 0) {
895 if (errno == EINTR)
896 continue;
897
898 memprintf(err, "Error reading OCSP response from file");
899 goto end;
900 }
901 else if (r == 0) {
902 break;
903 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200904 trash.data += r;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200905 }
906
907 close(fd);
908 fd = -1;
909
910 ret = ssl_sock_load_ocsp_response(&trash, ocsp, cid, err);
911end:
912 if (fd != -1)
913 close(fd);
914
915 return ret;
916}
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100917#endif
Emeric Brun4147b2e2014-06-16 18:36:30 +0200918
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100919#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
920static 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)
921{
Christopher Faulet16f45c82018-02-16 11:23:49 +0100922 struct tls_keys_ref *ref;
Emeric Brun9e754772019-01-10 17:51:55 +0100923 union tls_sess_key *keys;
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100924 struct connection *conn;
925 int head;
926 int i;
Christopher Faulet16f45c82018-02-16 11:23:49 +0100927 int ret = -1; /* error by default */
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100928
Thierry FOURNIER28962c92018-06-17 21:37:05 +0200929 conn = SSL_get_ex_data(s, ssl_app_data_index);
Willy Tarreau07d94e42018-09-20 10:57:52 +0200930 ref = __objt_listener(conn->target)->bind_conf->keys_ref;
Christopher Faulet16f45c82018-02-16 11:23:49 +0100931 HA_RWLOCK_RDLOCK(TLSKEYS_REF_LOCK, &ref->lock);
932
933 keys = ref->tlskeys;
934 head = ref->tls_ticket_enc_index;
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100935
936 if (enc) {
937 memcpy(key_name, keys[head].name, 16);
938
939 if(!RAND_pseudo_bytes(iv, EVP_MAX_IV_LENGTH))
Christopher Faulet16f45c82018-02-16 11:23:49 +0100940 goto end;
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100941
Emeric Brun9e754772019-01-10 17:51:55 +0100942 if (ref->key_size_bits == 128) {
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100943
Emeric Brun9e754772019-01-10 17:51:55 +0100944 if(!EVP_EncryptInit_ex(ectx, EVP_aes_128_cbc(), NULL, keys[head].key_128.aes_key, iv))
945 goto end;
946
Willy Tarreau9356dac2019-05-10 09:22:53 +0200947 HMAC_Init_ex(hctx, keys[head].key_128.hmac_key, 16, TLS_TICKET_HASH_FUNCT(), NULL);
Emeric Brun9e754772019-01-10 17:51:55 +0100948 ret = 1;
949 }
950 else if (ref->key_size_bits == 256 ) {
951
952 if(!EVP_EncryptInit_ex(ectx, EVP_aes_256_cbc(), NULL, keys[head].key_256.aes_key, iv))
953 goto end;
954
Willy Tarreau9356dac2019-05-10 09:22:53 +0200955 HMAC_Init_ex(hctx, keys[head].key_256.hmac_key, 32, TLS_TICKET_HASH_FUNCT(), NULL);
Emeric Brun9e754772019-01-10 17:51:55 +0100956 ret = 1;
957 }
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100958 } else {
959 for (i = 0; i < TLS_TICKETS_NO; i++) {
960 if (!memcmp(key_name, keys[(head + i) % TLS_TICKETS_NO].name, 16))
961 goto found;
962 }
Christopher Faulet16f45c82018-02-16 11:23:49 +0100963 ret = 0;
964 goto end;
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100965
Christopher Faulet16f45c82018-02-16 11:23:49 +0100966 found:
Emeric Brun9e754772019-01-10 17:51:55 +0100967 if (ref->key_size_bits == 128) {
Willy Tarreau9356dac2019-05-10 09:22:53 +0200968 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 +0100969 if(!EVP_DecryptInit_ex(ectx, EVP_aes_128_cbc(), NULL, keys[(head + i) % TLS_TICKETS_NO].key_128.aes_key, iv))
970 goto end;
971 /* 2 for key renewal, 1 if current key is still valid */
972 ret = i ? 2 : 1;
973 }
974 else if (ref->key_size_bits == 256) {
Willy Tarreau9356dac2019-05-10 09:22:53 +0200975 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 +0100976 if(!EVP_DecryptInit_ex(ectx, EVP_aes_256_cbc(), NULL, keys[(head + i) % TLS_TICKETS_NO].key_256.aes_key, iv))
977 goto end;
978 /* 2 for key renewal, 1 if current key is still valid */
979 ret = i ? 2 : 1;
980 }
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100981 }
Emeric Brun9e754772019-01-10 17:51:55 +0100982
Christopher Faulet16f45c82018-02-16 11:23:49 +0100983 end:
984 HA_RWLOCK_RDUNLOCK(TLSKEYS_REF_LOCK, &ref->lock);
985 return ret;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200986}
987
988struct tls_keys_ref *tlskeys_ref_lookup(const char *filename)
989{
990 struct tls_keys_ref *ref;
991
992 list_for_each_entry(ref, &tlskeys_reference, list)
993 if (ref->filename && strcmp(filename, ref->filename) == 0)
994 return ref;
995 return NULL;
996}
997
998struct tls_keys_ref *tlskeys_ref_lookupid(int unique_id)
999{
1000 struct tls_keys_ref *ref;
1001
1002 list_for_each_entry(ref, &tlskeys_reference, list)
1003 if (ref->unique_id == unique_id)
1004 return ref;
1005 return NULL;
1006}
1007
Emeric Brun9e754772019-01-10 17:51:55 +01001008/* Update the key into ref: if keysize doesnt
1009 * match existing ones, this function returns -1
1010 * else it returns 0 on success.
1011 */
1012int ssl_sock_update_tlskey_ref(struct tls_keys_ref *ref,
Willy Tarreau83061a82018-07-13 11:56:34 +02001013 struct buffer *tlskey)
Christopher Faulet16f45c82018-02-16 11:23:49 +01001014{
Emeric Brun9e754772019-01-10 17:51:55 +01001015 if (ref->key_size_bits == 128) {
1016 if (tlskey->data != sizeof(struct tls_sess_key_128))
1017 return -1;
1018 }
1019 else if (ref->key_size_bits == 256) {
1020 if (tlskey->data != sizeof(struct tls_sess_key_256))
1021 return -1;
1022 }
1023 else
1024 return -1;
1025
Christopher Faulet16f45c82018-02-16 11:23:49 +01001026 HA_RWLOCK_WRLOCK(TLSKEYS_REF_LOCK, &ref->lock);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001027 memcpy((char *) (ref->tlskeys + ((ref->tls_ticket_enc_index + 2) % TLS_TICKETS_NO)),
1028 tlskey->area, tlskey->data);
Christopher Faulet16f45c82018-02-16 11:23:49 +01001029 ref->tls_ticket_enc_index = (ref->tls_ticket_enc_index + 1) % TLS_TICKETS_NO;
1030 HA_RWLOCK_WRUNLOCK(TLSKEYS_REF_LOCK, &ref->lock);
Emeric Brun9e754772019-01-10 17:51:55 +01001031
1032 return 0;
Christopher Faulet16f45c82018-02-16 11:23:49 +01001033}
1034
Willy Tarreau83061a82018-07-13 11:56:34 +02001035int ssl_sock_update_tlskey(char *filename, struct buffer *tlskey, char **err)
Christopher Faulet16f45c82018-02-16 11:23:49 +01001036{
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02001037 struct tls_keys_ref *ref = tlskeys_ref_lookup(filename);
1038
1039 if(!ref) {
1040 memprintf(err, "Unable to locate the referenced filename: %s", filename);
1041 return 1;
1042 }
Emeric Brun9e754772019-01-10 17:51:55 +01001043 if (ssl_sock_update_tlskey_ref(ref, tlskey) < 0) {
1044 memprintf(err, "Invalid key size");
1045 return 1;
1046 }
1047
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02001048 return 0;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01001049}
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02001050
1051/* This function finalize the configuration parsing. Its set all the
Willy Tarreaud1c57502016-12-22 22:46:15 +01001052 * automatic ids. It's called just after the basic checks. It returns
1053 * 0 on success otherwise ERR_*.
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02001054 */
Willy Tarreaud1c57502016-12-22 22:46:15 +01001055static int tlskeys_finalize_config(void)
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02001056{
1057 int i = 0;
1058 struct tls_keys_ref *ref, *ref2, *ref3;
1059 struct list tkr = LIST_HEAD_INIT(tkr);
1060
1061 list_for_each_entry(ref, &tlskeys_reference, list) {
1062 if (ref->unique_id == -1) {
1063 /* Look for the first free id. */
1064 while (1) {
1065 list_for_each_entry(ref2, &tlskeys_reference, list) {
1066 if (ref2->unique_id == i) {
1067 i++;
1068 break;
1069 }
1070 }
1071 if (&ref2->list == &tlskeys_reference)
1072 break;
1073 }
1074
1075 /* Uses the unique id and increment it for the next entry. */
1076 ref->unique_id = i;
1077 i++;
1078 }
1079 }
1080
1081 /* This sort the reference list by id. */
1082 list_for_each_entry_safe(ref, ref2, &tlskeys_reference, list) {
1083 LIST_DEL(&ref->list);
1084 list_for_each_entry(ref3, &tkr, list) {
1085 if (ref->unique_id < ref3->unique_id) {
1086 LIST_ADDQ(&ref3->list, &ref->list);
1087 break;
1088 }
1089 }
1090 if (&ref3->list == &tkr)
1091 LIST_ADDQ(&tkr, &ref->list);
1092 }
1093
1094 /* swap root */
1095 LIST_ADD(&tkr, &tlskeys_reference);
1096 LIST_DEL(&tkr);
Willy Tarreaud1c57502016-12-22 22:46:15 +01001097 return 0;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02001098}
Nenad Merdanovic05552d42015-02-27 19:56:49 +01001099#endif /* SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB */
1100
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01001101#ifndef OPENSSL_NO_OCSP
yanbzhube2774d2015-12-10 15:07:30 -05001102int ssl_sock_get_ocsp_arg_kt_index(int evp_keytype)
1103{
1104 switch (evp_keytype) {
1105 case EVP_PKEY_RSA:
1106 return 2;
1107 case EVP_PKEY_DSA:
1108 return 0;
1109 case EVP_PKEY_EC:
1110 return 1;
1111 }
1112
1113 return -1;
1114}
1115
Emeric Brun4147b2e2014-06-16 18:36:30 +02001116/*
1117 * Callback used to set OCSP status extension content in server hello.
1118 */
1119int ssl_sock_ocsp_stapling_cbk(SSL *ssl, void *arg)
1120{
yanbzhube2774d2015-12-10 15:07:30 -05001121 struct certificate_ocsp *ocsp;
1122 struct ocsp_cbk_arg *ocsp_arg;
1123 char *ssl_buf;
1124 EVP_PKEY *ssl_pkey;
1125 int key_type;
1126 int index;
1127
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02001128 ocsp_arg = arg;
yanbzhube2774d2015-12-10 15:07:30 -05001129
1130 ssl_pkey = SSL_get_privatekey(ssl);
1131 if (!ssl_pkey)
1132 return SSL_TLSEXT_ERR_NOACK;
1133
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001134 key_type = EVP_PKEY_base_id(ssl_pkey);
yanbzhube2774d2015-12-10 15:07:30 -05001135
1136 if (ocsp_arg->is_single && ocsp_arg->single_kt == key_type)
1137 ocsp = ocsp_arg->s_ocsp;
1138 else {
1139 /* For multiple certs per context, we have to find the correct OCSP response based on
1140 * the certificate type
1141 */
1142 index = ssl_sock_get_ocsp_arg_kt_index(key_type);
1143
1144 if (index < 0)
1145 return SSL_TLSEXT_ERR_NOACK;
1146
1147 ocsp = ocsp_arg->m_ocsp[index];
1148
1149 }
Emeric Brun4147b2e2014-06-16 18:36:30 +02001150
1151 if (!ocsp ||
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001152 !ocsp->response.area ||
1153 !ocsp->response.data ||
Emeric Brun4f3c87a2014-06-20 15:46:13 +02001154 (ocsp->expire < now.tv_sec))
Emeric Brun4147b2e2014-06-16 18:36:30 +02001155 return SSL_TLSEXT_ERR_NOACK;
1156
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001157 ssl_buf = OPENSSL_malloc(ocsp->response.data);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001158 if (!ssl_buf)
1159 return SSL_TLSEXT_ERR_NOACK;
1160
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001161 memcpy(ssl_buf, ocsp->response.area, ocsp->response.data);
1162 SSL_set_tlsext_status_ocsp_resp(ssl, ssl_buf, ocsp->response.data);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001163
1164 return SSL_TLSEXT_ERR_OK;
1165}
1166
1167/*
1168 * This function enables the handling of OCSP status extension on 'ctx' if a
1169 * file name 'cert_path' suffixed using ".ocsp" is present.
1170 * To enable OCSP status extension, the issuer's certificate is mandatory.
1171 * It should be present in the certificate's extra chain builded from file
1172 * 'cert_path'. If not found, the issuer certificate is loaded from a file
1173 * named 'cert_path' suffixed using '.issuer'.
1174 *
1175 * In addition, ".ocsp" file content is loaded as a DER format of an OCSP
1176 * response. If file is empty or content is not a valid OCSP response,
1177 * OCSP status extension is enabled but OCSP response is ignored (a warning
1178 * is displayed).
1179 *
1180 * Returns 1 if no ".ocsp" file found, 0 if OCSP status extension is
Joseph Herlant017b3da2018-11-15 09:07:59 -08001181 * successfully enabled, or -1 in other error case.
Emeric Brun4147b2e2014-06-16 18:36:30 +02001182 */
1183static int ssl_sock_load_ocsp(SSL_CTX *ctx, const char *cert_path)
1184{
1185
1186 BIO *in = NULL;
1187 X509 *x, *xi = NULL, *issuer = NULL;
1188 STACK_OF(X509) *chain = NULL;
1189 OCSP_CERTID *cid = NULL;
1190 SSL *ssl;
1191 char ocsp_path[MAXPATHLEN+1];
1192 int i, ret = -1;
1193 struct stat st;
1194 struct certificate_ocsp *ocsp = NULL, *iocsp;
1195 char *warn = NULL;
1196 unsigned char *p;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001197 pem_password_cb *passwd_cb;
1198 void *passwd_cb_userdata;
1199 void (*callback) (void);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001200
1201 snprintf(ocsp_path, MAXPATHLEN+1, "%s.ocsp", cert_path);
1202
1203 if (stat(ocsp_path, &st))
1204 return 1;
1205
1206 ssl = SSL_new(ctx);
1207 if (!ssl)
1208 goto out;
1209
1210 x = SSL_get_certificate(ssl);
1211 if (!x)
1212 goto out;
1213
1214 /* Try to lookup for issuer in certificate extra chain */
Emeric Brun4147b2e2014-06-16 18:36:30 +02001215 SSL_CTX_get_extra_chain_certs(ctx, &chain);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001216 for (i = 0; i < sk_X509_num(chain); i++) {
1217 issuer = sk_X509_value(chain, i);
1218 if (X509_check_issued(issuer, x) == X509_V_OK)
1219 break;
1220 else
1221 issuer = NULL;
1222 }
1223
1224 /* If not found try to load issuer from a suffixed file */
1225 if (!issuer) {
1226 char issuer_path[MAXPATHLEN+1];
1227
1228 in = BIO_new(BIO_s_file());
1229 if (!in)
1230 goto out;
1231
1232 snprintf(issuer_path, MAXPATHLEN+1, "%s.issuer", cert_path);
1233 if (BIO_read_filename(in, issuer_path) <= 0)
1234 goto out;
1235
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001236 passwd_cb = SSL_CTX_get_default_passwd_cb(ctx);
1237 passwd_cb_userdata = SSL_CTX_get_default_passwd_cb_userdata(ctx);
1238
1239 xi = PEM_read_bio_X509_AUX(in, NULL, passwd_cb, passwd_cb_userdata);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001240 if (!xi)
1241 goto out;
1242
1243 if (X509_check_issued(xi, x) != X509_V_OK)
1244 goto out;
1245
1246 issuer = xi;
1247 }
1248
1249 cid = OCSP_cert_to_id(0, x, issuer);
1250 if (!cid)
1251 goto out;
1252
1253 i = i2d_OCSP_CERTID(cid, NULL);
1254 if (!i || (i > OCSP_MAX_CERTID_ASN1_LENGTH))
1255 goto out;
1256
Vincent Bernat02779b62016-04-03 13:48:43 +02001257 ocsp = calloc(1, sizeof(*ocsp));
Emeric Brun4147b2e2014-06-16 18:36:30 +02001258 if (!ocsp)
1259 goto out;
1260
1261 p = ocsp->key_data;
1262 i2d_OCSP_CERTID(cid, &p);
1263
1264 iocsp = (struct certificate_ocsp *)ebmb_insert(&cert_ocsp_tree, &ocsp->key, OCSP_MAX_CERTID_ASN1_LENGTH);
1265 if (iocsp == ocsp)
1266 ocsp = NULL;
1267
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001268#ifndef SSL_CTX_get_tlsext_status_cb
1269# define SSL_CTX_get_tlsext_status_cb(ctx, cb) \
1270 *cb = (void (*) (void))ctx->tlsext_status_cb;
1271#endif
1272 SSL_CTX_get_tlsext_status_cb(ctx, &callback);
1273
1274 if (!callback) {
William Lallemanda4864492020-07-31 11:43:20 +02001275 struct ocsp_cbk_arg *cb_arg;
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001276 EVP_PKEY *pkey;
yanbzhube2774d2015-12-10 15:07:30 -05001277
William Lallemanda4864492020-07-31 11:43:20 +02001278 cb_arg = calloc(1, sizeof(*cb_arg));
1279 if (!cb_arg)
1280 goto out;
1281
yanbzhube2774d2015-12-10 15:07:30 -05001282 cb_arg->is_single = 1;
1283 cb_arg->s_ocsp = iocsp;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001284
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001285 pkey = X509_get_pubkey(x);
1286 cb_arg->single_kt = EVP_PKEY_base_id(pkey);
1287 EVP_PKEY_free(pkey);
yanbzhube2774d2015-12-10 15:07:30 -05001288
1289 SSL_CTX_set_tlsext_status_cb(ctx, ssl_sock_ocsp_stapling_cbk);
1290 SSL_CTX_set_tlsext_status_arg(ctx, cb_arg);
1291 } else {
1292 /*
1293 * If the ctx has a status CB, then we have previously set an OCSP staple for this ctx
1294 * Update that cb_arg with the new cert's staple
1295 */
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001296 struct ocsp_cbk_arg *cb_arg;
yanbzhube2774d2015-12-10 15:07:30 -05001297 struct certificate_ocsp *tmp_ocsp;
1298 int index;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001299 int key_type;
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001300 EVP_PKEY *pkey;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001301
1302#ifdef SSL_CTX_get_tlsext_status_arg
1303 SSL_CTX_ctrl(ctx, SSL_CTRL_GET_TLSEXT_STATUS_REQ_CB_ARG, 0, &cb_arg);
1304#else
1305 cb_arg = ctx->tlsext_status_arg;
1306#endif
yanbzhube2774d2015-12-10 15:07:30 -05001307
1308 /*
1309 * The following few lines will convert cb_arg from a single ocsp to multi ocsp
1310 * the order of operations below matter, take care when changing it
1311 */
1312 tmp_ocsp = cb_arg->s_ocsp;
1313 index = ssl_sock_get_ocsp_arg_kt_index(cb_arg->single_kt);
1314 cb_arg->s_ocsp = NULL;
1315 cb_arg->m_ocsp[index] = tmp_ocsp;
1316 cb_arg->is_single = 0;
1317 cb_arg->single_kt = 0;
1318
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001319 pkey = X509_get_pubkey(x);
1320 key_type = EVP_PKEY_base_id(pkey);
1321 EVP_PKEY_free(pkey);
1322
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001323 index = ssl_sock_get_ocsp_arg_kt_index(key_type);
yanbzhube2774d2015-12-10 15:07:30 -05001324 if (index >= 0 && !cb_arg->m_ocsp[index])
1325 cb_arg->m_ocsp[index] = iocsp;
1326
1327 }
Emeric Brun4147b2e2014-06-16 18:36:30 +02001328
1329 ret = 0;
1330
1331 warn = NULL;
1332 if (ssl_sock_load_ocsp_response_from_file(ocsp_path, iocsp, cid, &warn)) {
1333 memprintf(&warn, "Loading '%s': %s. Content will be ignored", ocsp_path, warn ? warn : "failure");
Christopher Faulet767a84b2017-11-24 16:50:31 +01001334 ha_warning("%s.\n", warn);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001335 }
1336
1337out:
1338 if (ssl)
1339 SSL_free(ssl);
1340
1341 if (in)
1342 BIO_free(in);
1343
1344 if (xi)
1345 X509_free(xi);
1346
1347 if (cid)
1348 OCSP_CERTID_free(cid);
1349
1350 if (ocsp)
1351 free(ocsp);
1352
1353 if (warn)
1354 free(warn);
1355
1356
1357 return ret;
1358}
1359
1360#endif
1361
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02001362#ifdef OPENSSL_IS_BORINGSSL
1363static int ssl_sock_set_ocsp_response_from_file(SSL_CTX *ctx, const char *cert_path)
1364{
1365 char ocsp_path[MAXPATHLEN+1];
1366 struct stat st;
1367 int fd = -1, r = 0;
1368
1369 snprintf(ocsp_path, MAXPATHLEN+1, "%s.ocsp", cert_path);
1370 if (stat(ocsp_path, &st))
1371 return 0;
1372
1373 fd = open(ocsp_path, O_RDONLY);
1374 if (fd == -1) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001375 ha_warning("Error opening OCSP response file %s.\n", ocsp_path);
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02001376 return -1;
1377 }
1378
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001379 trash.data = 0;
1380 while (trash.data < trash.size) {
1381 r = read(fd, trash.area + trash.data, trash.size - trash.data);
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02001382 if (r < 0) {
1383 if (errno == EINTR)
1384 continue;
Christopher Faulet767a84b2017-11-24 16:50:31 +01001385 ha_warning("Error reading OCSP response from file %s.\n", ocsp_path);
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02001386 close(fd);
1387 return -1;
1388 }
1389 else if (r == 0) {
1390 break;
1391 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001392 trash.data += r;
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02001393 }
1394 close(fd);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001395 return SSL_CTX_set_ocsp_response(ctx, (const uint8_t *) trash.area,
1396 trash.data);
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02001397}
1398#endif
1399
Willy Tarreau5db847a2019-05-09 14:13:35 +02001400#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001401
1402#define CT_EXTENSION_TYPE 18
1403
1404static int sctl_ex_index = -1;
1405
1406/*
1407 * Try to parse Signed Certificate Timestamp List structure. This function
1408 * makes only basic test if the data seems like SCTL. No signature validation
1409 * is performed.
1410 */
Willy Tarreau83061a82018-07-13 11:56:34 +02001411static int ssl_sock_parse_sctl(struct buffer *sctl)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001412{
1413 int ret = 1;
1414 int len, pos, sct_len;
1415 unsigned char *data;
1416
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001417 if (sctl->data < 2)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001418 goto out;
1419
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001420 data = (unsigned char *) sctl->area;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001421 len = (data[0] << 8) | data[1];
1422
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001423 if (len + 2 != sctl->data)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001424 goto out;
1425
1426 data = data + 2;
1427 pos = 0;
1428 while (pos < len) {
1429 if (len - pos < 2)
1430 goto out;
1431
1432 sct_len = (data[pos] << 8) | data[pos + 1];
1433 if (pos + sct_len + 2 > len)
1434 goto out;
1435
1436 pos += sct_len + 2;
1437 }
1438
1439 ret = 0;
1440
1441out:
1442 return ret;
1443}
1444
Willy Tarreau83061a82018-07-13 11:56:34 +02001445static int ssl_sock_load_sctl_from_file(const char *sctl_path,
1446 struct buffer **sctl)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001447{
1448 int fd = -1;
1449 int r = 0;
1450 int ret = 1;
1451
1452 *sctl = NULL;
1453
1454 fd = open(sctl_path, O_RDONLY);
1455 if (fd == -1)
1456 goto end;
1457
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001458 trash.data = 0;
1459 while (trash.data < trash.size) {
1460 r = read(fd, trash.area + trash.data, trash.size - trash.data);
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001461 if (r < 0) {
1462 if (errno == EINTR)
1463 continue;
1464
1465 goto end;
1466 }
1467 else if (r == 0) {
1468 break;
1469 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001470 trash.data += r;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001471 }
1472
1473 ret = ssl_sock_parse_sctl(&trash);
1474 if (ret)
1475 goto end;
1476
Vincent Bernat02779b62016-04-03 13:48:43 +02001477 *sctl = calloc(1, sizeof(**sctl));
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001478 if (!chunk_dup(*sctl, &trash)) {
1479 free(*sctl);
1480 *sctl = NULL;
1481 goto end;
1482 }
1483
1484end:
1485 if (fd != -1)
1486 close(fd);
1487
1488 return ret;
1489}
1490
1491int ssl_sock_sctl_add_cbk(SSL *ssl, unsigned ext_type, const unsigned char **out, size_t *outlen, int *al, void *add_arg)
1492{
Willy Tarreau83061a82018-07-13 11:56:34 +02001493 struct buffer *sctl = add_arg;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001494
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001495 *out = (unsigned char *) sctl->area;
1496 *outlen = sctl->data;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001497
1498 return 1;
1499}
1500
1501int ssl_sock_sctl_parse_cbk(SSL *s, unsigned int ext_type, const unsigned char *in, size_t inlen, int *al, void *parse_arg)
1502{
1503 return 1;
1504}
1505
1506static int ssl_sock_load_sctl(SSL_CTX *ctx, const char *cert_path)
1507{
1508 char sctl_path[MAXPATHLEN+1];
1509 int ret = -1;
1510 struct stat st;
Willy Tarreau83061a82018-07-13 11:56:34 +02001511 struct buffer *sctl = NULL;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001512
1513 snprintf(sctl_path, MAXPATHLEN+1, "%s.sctl", cert_path);
1514
1515 if (stat(sctl_path, &st))
1516 return 1;
1517
1518 if (ssl_sock_load_sctl_from_file(sctl_path, &sctl))
1519 goto out;
1520
1521 if (!SSL_CTX_add_server_custom_ext(ctx, CT_EXTENSION_TYPE, ssl_sock_sctl_add_cbk, NULL, sctl, ssl_sock_sctl_parse_cbk, NULL)) {
1522 free(sctl);
1523 goto out;
1524 }
1525
1526 SSL_CTX_set_ex_data(ctx, sctl_ex_index, sctl);
1527
1528 ret = 0;
1529
1530out:
1531 return ret;
1532}
1533
1534#endif
1535
Emeric Brune1f38db2012-09-03 20:36:47 +02001536void ssl_sock_infocbk(const SSL *ssl, int where, int ret)
1537{
Thierry FOURNIER28962c92018-06-17 21:37:05 +02001538 struct connection *conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001539 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
Emeric Brund8b2bb52014-01-28 15:43:53 +01001540 BIO *write_bio;
Willy Tarreau622317d2015-02-27 16:36:16 +01001541 (void)ret; /* shut gcc stupid warning */
Emeric Brune1f38db2012-09-03 20:36:47 +02001542
Dirkjan Bussink526894f2019-01-21 09:35:03 -08001543#ifndef SSL_OP_NO_RENEGOTIATION
1544 /* Please note that BoringSSL defines this macro to zero so don't
1545 * change this to #if and do not assign a default value to this macro!
1546 */
Emeric Brune1f38db2012-09-03 20:36:47 +02001547 if (where & SSL_CB_HANDSHAKE_START) {
1548 /* Disable renegotiation (CVE-2009-3555) */
Olivier Houchard90084a12017-11-23 18:21:29 +01001549 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 +02001550 conn->flags |= CO_FL_ERROR;
Willy Tarreau20879a02012-12-03 16:32:10 +01001551 conn->err_code = CO_ER_SSL_RENEG;
1552 }
Emeric Brune1f38db2012-09-03 20:36:47 +02001553 }
Dirkjan Bussink526894f2019-01-21 09:35:03 -08001554#endif
Emeric Brund8b2bb52014-01-28 15:43:53 +01001555
1556 if ((where & SSL_CB_ACCEPT_LOOP) == SSL_CB_ACCEPT_LOOP) {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001557 if (!(ctx->xprt_st & SSL_SOCK_ST_FL_16K_WBFSIZE)) {
Emeric Brund8b2bb52014-01-28 15:43:53 +01001558 /* Long certificate chains optimz
1559 If write and read bios are differents, we
1560 consider that the buffering was activated,
1561 so we rise the output buffer size from 4k
1562 to 16k */
1563 write_bio = SSL_get_wbio(ssl);
1564 if (write_bio != SSL_get_rbio(ssl)) {
1565 BIO_set_write_buffer_size(write_bio, 16384);
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001566 ctx->xprt_st |= SSL_SOCK_ST_FL_16K_WBFSIZE;
Emeric Brund8b2bb52014-01-28 15:43:53 +01001567 }
1568 }
1569 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02001570}
1571
Emeric Brune64aef12012-09-21 13:15:06 +02001572/* Callback is called for each certificate of the chain during a verify
1573 ok is set to 1 if preverify detect no error on current certificate.
1574 Returns 0 to break the handshake, 1 otherwise. */
Evan Broderbe554312013-06-27 00:05:25 -07001575int ssl_sock_bind_verifycbk(int ok, X509_STORE_CTX *x_store)
Emeric Brune64aef12012-09-21 13:15:06 +02001576{
1577 SSL *ssl;
1578 struct connection *conn;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001579 struct ssl_sock_ctx *ctx;
Emeric Brun81c00f02012-09-21 14:31:21 +02001580 int err, depth;
Emeric Brune64aef12012-09-21 13:15:06 +02001581
1582 ssl = X509_STORE_CTX_get_ex_data(x_store, SSL_get_ex_data_X509_STORE_CTX_idx());
Thierry FOURNIER28962c92018-06-17 21:37:05 +02001583 conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Emeric Brune64aef12012-09-21 13:15:06 +02001584
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001585 ctx = conn->xprt_ctx;
1586
1587 ctx->xprt_st |= SSL_SOCK_ST_FL_VERIFY_DONE;
Emeric Brune64aef12012-09-21 13:15:06 +02001588
Emeric Brun81c00f02012-09-21 14:31:21 +02001589 if (ok) /* no errors */
1590 return ok;
1591
1592 depth = X509_STORE_CTX_get_error_depth(x_store);
1593 err = X509_STORE_CTX_get_error(x_store);
1594
1595 /* check if CA error needs to be ignored */
1596 if (depth > 0) {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001597 if (!SSL_SOCK_ST_TO_CA_ERROR(ctx->xprt_st)) {
1598 ctx->xprt_st |= SSL_SOCK_CA_ERROR_TO_ST(err);
1599 ctx->xprt_st |= SSL_SOCK_CAEDEPTH_TO_ST(depth);
Emeric Brunf282a812012-09-21 15:27:54 +02001600 }
1601
Willy Tarreaua9d299f2020-02-04 14:02:02 +01001602 if (err < 64 && __objt_listener(conn->target)->bind_conf->ca_ignerr & (1ULL << err)) {
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02001603 ssl_sock_dump_errors(conn);
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001604 ERR_clear_error();
Emeric Brun81c00f02012-09-21 14:31:21 +02001605 return 1;
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001606 }
Emeric Brun81c00f02012-09-21 14:31:21 +02001607
Willy Tarreau20879a02012-12-03 16:32:10 +01001608 conn->err_code = CO_ER_SSL_CA_FAIL;
Emeric Brun81c00f02012-09-21 14:31:21 +02001609 return 0;
1610 }
1611
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001612 if (!SSL_SOCK_ST_TO_CRTERROR(ctx->xprt_st))
1613 ctx->xprt_st |= SSL_SOCK_CRTERROR_TO_ST(err);
Emeric Brunf282a812012-09-21 15:27:54 +02001614
Emeric Brun81c00f02012-09-21 14:31:21 +02001615 /* check if certificate error needs to be ignored */
Willy Tarreaua9d299f2020-02-04 14:02:02 +01001616 if (err < 64 && __objt_listener(conn->target)->bind_conf->crt_ignerr & (1ULL << err)) {
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02001617 ssl_sock_dump_errors(conn);
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001618 ERR_clear_error();
Emeric Brun81c00f02012-09-21 14:31:21 +02001619 return 1;
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001620 }
Emeric Brun81c00f02012-09-21 14:31:21 +02001621
Willy Tarreau20879a02012-12-03 16:32:10 +01001622 conn->err_code = CO_ER_SSL_CRT_FAIL;
Emeric Brun81c00f02012-09-21 14:31:21 +02001623 return 0;
Emeric Brune64aef12012-09-21 13:15:06 +02001624}
1625
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001626static inline
1627void ssl_sock_parse_clienthello(int write_p, int version, int content_type,
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001628 const void *buf, size_t len, SSL *ssl)
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001629{
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001630 struct ssl_capture *capture;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001631 unsigned char *msg;
1632 unsigned char *end;
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001633 size_t rec_len;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001634
1635 /* This function is called for "from client" and "to server"
1636 * connections. The combination of write_p == 0 and content_type == 22
Joseph Herlant017b3da2018-11-15 09:07:59 -08001637 * is only available during "from client" connection.
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001638 */
1639
1640 /* "write_p" is set to 0 is the bytes are received messages,
1641 * otherwise it is set to 1.
1642 */
1643 if (write_p != 0)
1644 return;
1645
1646 /* content_type contains the type of message received or sent
1647 * according with the SSL/TLS protocol spec. This message is
1648 * encoded with one byte. The value 256 (two bytes) is used
1649 * for designing the SSL/TLS record layer. According with the
1650 * rfc6101, the expected message (other than 256) are:
1651 * - change_cipher_spec(20)
1652 * - alert(21)
1653 * - handshake(22)
1654 * - application_data(23)
1655 * - (255)
1656 * We are interessed by the handshake and specially the client
1657 * hello.
1658 */
1659 if (content_type != 22)
1660 return;
1661
1662 /* The message length is at least 4 bytes, containing the
1663 * message type and the message length.
1664 */
1665 if (len < 4)
1666 return;
1667
1668 /* First byte of the handshake message id the type of
1669 * message. The konwn types are:
1670 * - hello_request(0)
1671 * - client_hello(1)
1672 * - server_hello(2)
1673 * - certificate(11)
1674 * - server_key_exchange (12)
1675 * - certificate_request(13)
1676 * - server_hello_done(14)
1677 * We are interested by the client hello.
1678 */
1679 msg = (unsigned char *)buf;
1680 if (msg[0] != 1)
1681 return;
1682
1683 /* Next three bytes are the length of the message. The total length
1684 * must be this decoded length + 4. If the length given as argument
1685 * is not the same, we abort the protocol dissector.
1686 */
1687 rec_len = (msg[1] << 16) + (msg[2] << 8) + msg[3];
1688 if (len < rec_len + 4)
1689 return;
1690 msg += 4;
1691 end = msg + rec_len;
1692 if (end < msg)
1693 return;
1694
1695 /* Expect 2 bytes for protocol version (1 byte for major and 1 byte
1696 * for minor, the random, composed by 4 bytes for the unix time and
Baptiste Assmann6be139f2018-11-28 15:20:25 +01001697 * 28 bytes for unix payload. So we jump 1 + 1 + 4 + 28.
1698 */
1699 msg += 1 + 1 + 4 + 28;
1700 if (msg > end)
1701 return;
1702
1703 /* Next, is session id:
1704 * if present, we have to jump by length + 1 for the size information
1705 * if not present, we have to jump by 1 only
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001706 */
Baptiste Assmann6be139f2018-11-28 15:20:25 +01001707 if (msg[0] > 0)
1708 msg += msg[0];
1709 msg += 1;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001710 if (msg > end)
1711 return;
1712
1713 /* Next two bytes are the ciphersuite length. */
1714 if (msg + 2 > end)
1715 return;
1716 rec_len = (msg[0] << 8) + msg[1];
1717 msg += 2;
1718 if (msg + rec_len > end || msg + rec_len < msg)
1719 return;
1720
Willy Tarreaubafbe012017-11-24 17:34:44 +01001721 capture = pool_alloc_dirty(pool_head_ssl_capture);
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001722 if (!capture)
1723 return;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001724 /* Compute the xxh64 of the ciphersuite. */
1725 capture->xxh64 = XXH64(msg, rec_len, 0);
1726
1727 /* Capture the ciphersuite. */
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001728 capture->ciphersuite_len = (global_ssl.capture_cipherlist < rec_len) ?
1729 global_ssl.capture_cipherlist : rec_len;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001730 memcpy(capture->ciphersuite, msg, capture->ciphersuite_len);
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001731
1732 SSL_set_ex_data(ssl, ssl_capture_ptr_index, capture);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001733}
1734
Emeric Brun29f037d2014-04-25 19:05:36 +02001735/* Callback is called for ssl protocol analyse */
1736void ssl_sock_msgcbk(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg)
1737{
Emeric Brun29f037d2014-04-25 19:05:36 +02001738#ifdef TLS1_RT_HEARTBEAT
1739 /* test heartbeat received (write_p is set to 0
1740 for a received record) */
Willy Tarreauf51c6982014-04-25 20:02:39 +02001741 if ((content_type == TLS1_RT_HEARTBEAT) && (write_p == 0)) {
Thierry FOURNIER28962c92018-06-17 21:37:05 +02001742 struct connection *conn = SSL_get_ex_data(ssl, ssl_app_data_index);
William Lallemand7e1770b2019-05-13 14:31:34 +02001743 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
Willy Tarreauf51c6982014-04-25 20:02:39 +02001744 const unsigned char *p = buf;
1745 unsigned int payload;
1746
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001747 ctx->xprt_st |= SSL_SOCK_RECV_HEARTBEAT;
Willy Tarreauf51c6982014-04-25 20:02:39 +02001748
1749 /* Check if this is a CVE-2014-0160 exploitation attempt. */
1750 if (*p != TLS1_HB_REQUEST)
1751 return;
1752
Willy Tarreauaeed6722014-04-25 23:59:58 +02001753 if (len < 1 + 2 + 16) /* 1 type + 2 size + 0 payload + 16 padding */
Willy Tarreauf51c6982014-04-25 20:02:39 +02001754 goto kill_it;
1755
1756 payload = (p[1] * 256) + p[2];
Willy Tarreau3b2fdb62014-04-25 23:44:22 +02001757 if (3 + payload + 16 <= len)
Willy Tarreauf51c6982014-04-25 20:02:39 +02001758 return; /* OK no problem */
Willy Tarreauaeed6722014-04-25 23:59:58 +02001759 kill_it:
Willy Tarreau3b2fdb62014-04-25 23:44:22 +02001760 /* We have a clear heartbleed attack (CVE-2014-0160), the
1761 * advertised payload is larger than the advertised packet
1762 * length, so we have garbage in the buffer between the
1763 * payload and the end of the buffer (p+len). We can't know
1764 * if the SSL stack is patched, and we don't know if we can
1765 * safely wipe out the area between p+3+len and payload.
1766 * So instead, we prevent the response from being sent by
1767 * setting the max_send_fragment to 0 and we report an SSL
1768 * error, which will kill this connection. It will be reported
1769 * above as SSL_ERROR_SSL while an other handshake failure with
Willy Tarreauf51c6982014-04-25 20:02:39 +02001770 * a heartbeat message will be reported as SSL_ERROR_SYSCALL.
1771 */
Willy Tarreau3b2fdb62014-04-25 23:44:22 +02001772 ssl->max_send_fragment = 0;
Willy Tarreauf51c6982014-04-25 20:02:39 +02001773 SSLerr(SSL_F_TLS1_HEARTBEAT, SSL_R_SSL_HANDSHAKE_FAILURE);
1774 return;
1775 }
Emeric Brun29f037d2014-04-25 19:05:36 +02001776#endif
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001777 if (global_ssl.capture_cipherlist > 0)
1778 ssl_sock_parse_clienthello(write_p, version, content_type, buf, len, ssl);
Emeric Brun29f037d2014-04-25 19:05:36 +02001779}
1780
Bernard Spil13c53f82018-02-15 13:34:58 +01001781#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Olivier Houchardc7566002018-11-20 23:33:50 +01001782static int ssl_sock_srv_select_protos(SSL *s, unsigned char **out, unsigned char *outlen,
1783 const unsigned char *in, unsigned int inlen,
1784 void *arg)
1785{
1786 struct server *srv = arg;
1787
1788 if (SSL_select_next_proto(out, outlen, in, inlen, (unsigned char *)srv->ssl_ctx.npn_str,
1789 srv->ssl_ctx.npn_len) == OPENSSL_NPN_NEGOTIATED)
1790 return SSL_TLSEXT_ERR_OK;
1791 return SSL_TLSEXT_ERR_NOACK;
1792}
1793#endif
1794
1795#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02001796/* This callback is used so that the server advertises the list of
1797 * negociable protocols for NPN.
1798 */
1799static int ssl_sock_advertise_npn_protos(SSL *s, const unsigned char **data,
1800 unsigned int *len, void *arg)
1801{
Emmanuel Hocdet98263292016-12-29 18:26:15 +01001802 struct ssl_bind_conf *conf = arg;
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02001803
1804 *data = (const unsigned char *)conf->npn_str;
1805 *len = conf->npn_len;
1806 return SSL_TLSEXT_ERR_OK;
1807}
1808#endif
1809
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01001810#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02001811/* This callback is used so that the server advertises the list of
1812 * negociable protocols for ALPN.
1813 */
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01001814static int ssl_sock_advertise_alpn_protos(SSL *s, const unsigned char **out,
1815 unsigned char *outlen,
1816 const unsigned char *server,
1817 unsigned int server_len, void *arg)
Willy Tarreauab861d32013-04-02 02:30:41 +02001818{
Emmanuel Hocdet98263292016-12-29 18:26:15 +01001819 struct ssl_bind_conf *conf = arg;
Willy Tarreauab861d32013-04-02 02:30:41 +02001820
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01001821 if (SSL_select_next_proto((unsigned char**) out, outlen, (const unsigned char *)conf->alpn_str,
1822 conf->alpn_len, server, server_len) != OPENSSL_NPN_NEGOTIATED) {
1823 return SSL_TLSEXT_ERR_NOACK;
1824 }
Willy Tarreauab861d32013-04-02 02:30:41 +02001825 return SSL_TLSEXT_ERR_OK;
1826}
1827#endif
1828
Willy Tarreauc8ad3be2015-06-17 15:48:26 +02001829#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01001830#ifndef SSL_NO_GENERATE_CERTIFICATES
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001831
Christopher Faulet30548802015-06-11 13:39:32 +02001832/* Create a X509 certificate with the specified servername and serial. This
1833 * function returns a SSL_CTX object or NULL if an error occurs. */
Christopher Faulet7969a332015-10-09 11:15:03 +02001834static SSL_CTX *
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001835ssl_sock_do_create_cert(const char *servername, struct bind_conf *bind_conf, SSL *ssl)
Christopher Faulet31af49d2015-06-09 17:29:50 +02001836{
Christopher Faulet7969a332015-10-09 11:15:03 +02001837 X509 *cacert = bind_conf->ca_sign_cert;
1838 EVP_PKEY *capkey = bind_conf->ca_sign_pkey;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001839 SSL_CTX *ssl_ctx = NULL;
1840 X509 *newcrt = NULL;
1841 EVP_PKEY *pkey = NULL;
Emmanuel Hocdet15969292017-08-11 10:56:00 +02001842 SSL *tmp_ssl = NULL;
Emmanuel Hocdeta9b84022018-10-01 18:41:36 +02001843 CONF *ctmp = NULL;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001844 X509_NAME *name;
1845 const EVP_MD *digest;
1846 X509V3_CTX ctx;
1847 unsigned int i;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001848 int key_type;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001849
Christopher Faulet48a83322017-07-28 16:56:09 +02001850 /* Get the private key of the default certificate and use it */
Willy Tarreau5db847a2019-05-09 14:13:35 +02001851#if (HA_OPENSSL_VERSION_NUMBER >= 0x10002000L)
Emmanuel Hocdet15969292017-08-11 10:56:00 +02001852 pkey = SSL_CTX_get0_privatekey(bind_conf->default_ctx);
1853#else
1854 tmp_ssl = SSL_new(bind_conf->default_ctx);
1855 if (tmp_ssl)
1856 pkey = SSL_get_privatekey(tmp_ssl);
1857#endif
1858 if (!pkey)
Christopher Faulet31af49d2015-06-09 17:29:50 +02001859 goto mkcert_error;
1860
1861 /* Create the certificate */
1862 if (!(newcrt = X509_new()))
1863 goto mkcert_error;
1864
1865 /* Set version number for the certificate (X509v3) and the serial
1866 * number */
1867 if (X509_set_version(newcrt, 2L) != 1)
1868 goto mkcert_error;
Olivier Houchard2be5a4c2019-03-08 18:54:43 +01001869 ASN1_INTEGER_set(X509_get_serialNumber(newcrt), _HA_ATOMIC_ADD(&ssl_ctx_serial, 1));
Christopher Faulet31af49d2015-06-09 17:29:50 +02001870
1871 /* Set duration for the certificate */
Rosen Penev68185952018-12-14 08:47:02 -08001872 if (!X509_gmtime_adj(X509_getm_notBefore(newcrt), (long)-60*60*24) ||
1873 !X509_gmtime_adj(X509_getm_notAfter(newcrt),(long)60*60*24*365))
Christopher Faulet31af49d2015-06-09 17:29:50 +02001874 goto mkcert_error;
1875
1876 /* set public key in the certificate */
1877 if (X509_set_pubkey(newcrt, pkey) != 1)
1878 goto mkcert_error;
1879
1880 /* Set issuer name from the CA */
1881 if (!(name = X509_get_subject_name(cacert)))
1882 goto mkcert_error;
1883 if (X509_set_issuer_name(newcrt, name) != 1)
1884 goto mkcert_error;
1885
1886 /* Set the subject name using the same, but the CN */
1887 name = X509_NAME_dup(name);
1888 if (X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC,
1889 (const unsigned char *)servername,
1890 -1, -1, 0) != 1) {
1891 X509_NAME_free(name);
1892 goto mkcert_error;
1893 }
1894 if (X509_set_subject_name(newcrt, name) != 1) {
1895 X509_NAME_free(name);
1896 goto mkcert_error;
1897 }
1898 X509_NAME_free(name);
1899
1900 /* Add x509v3 extensions as specified */
Emmanuel Hocdeta9b84022018-10-01 18:41:36 +02001901 ctmp = NCONF_new(NULL);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001902 X509V3_set_ctx(&ctx, cacert, newcrt, NULL, NULL, 0);
1903 for (i = 0; i < X509V3_EXT_SIZE; i++) {
1904 X509_EXTENSION *ext;
1905
Emmanuel Hocdeta9b84022018-10-01 18:41:36 +02001906 if (!(ext = X509V3_EXT_nconf(ctmp, &ctx, x509v3_ext_names[i], x509v3_ext_values[i])))
Christopher Faulet31af49d2015-06-09 17:29:50 +02001907 goto mkcert_error;
1908 if (!X509_add_ext(newcrt, ext, -1)) {
1909 X509_EXTENSION_free(ext);
1910 goto mkcert_error;
1911 }
1912 X509_EXTENSION_free(ext);
1913 }
1914
1915 /* Sign the certificate with the CA private key */
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001916
1917 key_type = EVP_PKEY_base_id(capkey);
1918
1919 if (key_type == EVP_PKEY_DSA)
1920 digest = EVP_sha1();
1921 else if (key_type == EVP_PKEY_RSA)
Christopher Faulet31af49d2015-06-09 17:29:50 +02001922 digest = EVP_sha256();
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001923 else if (key_type == EVP_PKEY_EC)
Christopher Faulet7969a332015-10-09 11:15:03 +02001924 digest = EVP_sha256();
1925 else {
Willy Tarreau9a1ab082019-05-09 13:26:41 +02001926#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000000fL) && !defined(OPENSSL_IS_BORINGSSL)
Christopher Faulet7969a332015-10-09 11:15:03 +02001927 int nid;
1928
1929 if (EVP_PKEY_get_default_digest_nid(capkey, &nid) <= 0)
1930 goto mkcert_error;
1931 if (!(digest = EVP_get_digestbynid(nid)))
1932 goto mkcert_error;
Christopher Faulete7db2162015-10-19 13:59:24 +02001933#else
1934 goto mkcert_error;
1935#endif
Christopher Faulet7969a332015-10-09 11:15:03 +02001936 }
1937
Christopher Faulet31af49d2015-06-09 17:29:50 +02001938 if (!(X509_sign(newcrt, capkey, digest)))
1939 goto mkcert_error;
1940
1941 /* Create and set the new SSL_CTX */
1942 if (!(ssl_ctx = SSL_CTX_new(SSLv23_server_method())))
1943 goto mkcert_error;
1944 if (!SSL_CTX_use_PrivateKey(ssl_ctx, pkey))
1945 goto mkcert_error;
1946 if (!SSL_CTX_use_certificate(ssl_ctx, newcrt))
1947 goto mkcert_error;
1948 if (!SSL_CTX_check_private_key(ssl_ctx))
1949 goto mkcert_error;
1950
1951 if (newcrt) X509_free(newcrt);
Christopher Faulet7969a332015-10-09 11:15:03 +02001952
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01001953#ifndef OPENSSL_NO_DH
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001954 SSL_CTX_set_tmp_dh_callback(ssl_ctx, ssl_get_tmp_dh);
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01001955#endif
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001956#if defined(SSL_CTX_set_tmp_ecdh) && !defined(OPENSSL_NO_ECDH)
1957 {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01001958 const char *ecdhe = (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe : ECDHE_DEFAULT_CURVE);
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001959 EC_KEY *ecc;
1960 int nid;
1961
1962 if ((nid = OBJ_sn2nid(ecdhe)) == NID_undef)
1963 goto end;
1964 if (!(ecc = EC_KEY_new_by_curve_name(nid)))
1965 goto end;
1966 SSL_CTX_set_tmp_ecdh(ssl_ctx, ecc);
1967 EC_KEY_free(ecc);
1968 }
1969#endif
1970 end:
Christopher Faulet31af49d2015-06-09 17:29:50 +02001971 return ssl_ctx;
1972
1973 mkcert_error:
Emmanuel Hocdeta9b84022018-10-01 18:41:36 +02001974 if (ctmp) NCONF_free(ctmp);
Emmanuel Hocdet15969292017-08-11 10:56:00 +02001975 if (tmp_ssl) SSL_free(tmp_ssl);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001976 if (ssl_ctx) SSL_CTX_free(ssl_ctx);
1977 if (newcrt) X509_free(newcrt);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001978 return NULL;
1979}
1980
Christopher Faulet7969a332015-10-09 11:15:03 +02001981SSL_CTX *
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001982ssl_sock_create_cert(struct connection *conn, const char *servername, unsigned int key)
Christopher Faulet7969a332015-10-09 11:15:03 +02001983{
Willy Tarreau07d94e42018-09-20 10:57:52 +02001984 struct bind_conf *bind_conf = __objt_listener(conn->target)->bind_conf;
Olivier Houchard66ab4982019-02-26 18:37:15 +01001985 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001986
Olivier Houchard66ab4982019-02-26 18:37:15 +01001987 return ssl_sock_do_create_cert(servername, bind_conf, ctx->ssl);
Christopher Faulet7969a332015-10-09 11:15:03 +02001988}
1989
Christopher Faulet30548802015-06-11 13:39:32 +02001990/* Do a lookup for a certificate in the LRU cache used to store generated
Emeric Brun821bb9b2017-06-15 16:37:39 +02001991 * certificates and immediately assign it to the SSL session if not null. */
Christopher Faulet30548802015-06-11 13:39:32 +02001992SSL_CTX *
Emeric Brun821bb9b2017-06-15 16:37:39 +02001993ssl_sock_assign_generated_cert(unsigned int key, struct bind_conf *bind_conf, SSL *ssl)
Christopher Faulet30548802015-06-11 13:39:32 +02001994{
1995 struct lru64 *lru = NULL;
1996
1997 if (ssl_ctx_lru_tree) {
Willy Tarreau03f4ec42018-05-17 10:56:47 +02001998 HA_RWLOCK_WRLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001999 lru = lru64_lookup(key, ssl_ctx_lru_tree, bind_conf->ca_sign_cert, 0);
Emeric Brun821bb9b2017-06-15 16:37:39 +02002000 if (lru && lru->domain) {
2001 if (ssl)
2002 SSL_set_SSL_CTX(ssl, (SSL_CTX *)lru->data);
Willy Tarreau03f4ec42018-05-17 10:56:47 +02002003 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet30548802015-06-11 13:39:32 +02002004 return (SSL_CTX *)lru->data;
Emeric Brun821bb9b2017-06-15 16:37:39 +02002005 }
Willy Tarreau03f4ec42018-05-17 10:56:47 +02002006 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet30548802015-06-11 13:39:32 +02002007 }
2008 return NULL;
2009}
2010
Emeric Brun821bb9b2017-06-15 16:37:39 +02002011/* Same as <ssl_sock_assign_generated_cert> but without SSL session. This
2012 * function is not thread-safe, it should only be used to check if a certificate
2013 * exists in the lru cache (with no warranty it will not be removed by another
2014 * thread). It is kept for backward compatibility. */
2015SSL_CTX *
2016ssl_sock_get_generated_cert(unsigned int key, struct bind_conf *bind_conf)
2017{
2018 return ssl_sock_assign_generated_cert(key, bind_conf, NULL);
2019}
2020
Christopher Fauletd2cab922015-07-28 16:03:47 +02002021/* Set a certificate int the LRU cache used to store generated
2022 * certificate. Return 0 on success, otherwise -1 */
2023int
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002024ssl_sock_set_generated_cert(SSL_CTX *ssl_ctx, unsigned int key, struct bind_conf *bind_conf)
Christopher Faulet30548802015-06-11 13:39:32 +02002025{
2026 struct lru64 *lru = NULL;
2027
2028 if (ssl_ctx_lru_tree) {
Christopher Faulet2a944ee2017-11-07 10:42:54 +01002029 HA_RWLOCK_WRLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002030 lru = lru64_get(key, ssl_ctx_lru_tree, bind_conf->ca_sign_cert, 0);
Emeric Brun821bb9b2017-06-15 16:37:39 +02002031 if (!lru) {
Christopher Faulet2a944ee2017-11-07 10:42:54 +01002032 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Fauletd2cab922015-07-28 16:03:47 +02002033 return -1;
Emeric Brun821bb9b2017-06-15 16:37:39 +02002034 }
Christopher Faulet30548802015-06-11 13:39:32 +02002035 if (lru->domain && lru->data)
2036 lru->free((SSL_CTX *)lru->data);
Christopher Faulet7969a332015-10-09 11:15:03 +02002037 lru64_commit(lru, ssl_ctx, bind_conf->ca_sign_cert, 0, (void (*)(void *))SSL_CTX_free);
Christopher Faulet2a944ee2017-11-07 10:42:54 +01002038 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Fauletd2cab922015-07-28 16:03:47 +02002039 return 0;
Christopher Faulet30548802015-06-11 13:39:32 +02002040 }
Christopher Fauletd2cab922015-07-28 16:03:47 +02002041 return -1;
Christopher Faulet30548802015-06-11 13:39:32 +02002042}
2043
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002044/* Compute the key of the certificate. */
Christopher Faulet30548802015-06-11 13:39:32 +02002045unsigned int
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002046ssl_sock_generated_cert_key(const void *data, size_t len)
Christopher Faulet30548802015-06-11 13:39:32 +02002047{
2048 return XXH32(data, len, ssl_ctx_lru_seed);
2049}
2050
Willy Tarreau2f63ef42015-10-20 15:16:01 +02002051/* Generate a cert and immediately assign it to the SSL session so that the cert's
2052 * refcount is maintained regardless of the cert's presence in the LRU cache.
2053 */
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002054static int
Christopher Faulet7969a332015-10-09 11:15:03 +02002055ssl_sock_generate_certificate(const char *servername, struct bind_conf *bind_conf, SSL *ssl)
Christopher Faulet31af49d2015-06-09 17:29:50 +02002056{
2057 X509 *cacert = bind_conf->ca_sign_cert;
Christopher Faulet31af49d2015-06-09 17:29:50 +02002058 SSL_CTX *ssl_ctx = NULL;
2059 struct lru64 *lru = NULL;
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002060 unsigned int key;
Christopher Faulet31af49d2015-06-09 17:29:50 +02002061
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002062 key = ssl_sock_generated_cert_key(servername, strlen(servername));
Christopher Faulet31af49d2015-06-09 17:29:50 +02002063 if (ssl_ctx_lru_tree) {
Christopher Faulet2a944ee2017-11-07 10:42:54 +01002064 HA_RWLOCK_WRLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002065 lru = lru64_get(key, ssl_ctx_lru_tree, cacert, 0);
Christopher Faulet31af49d2015-06-09 17:29:50 +02002066 if (lru && lru->domain)
2067 ssl_ctx = (SSL_CTX *)lru->data;
Christopher Fauletd2cab922015-07-28 16:03:47 +02002068 if (!ssl_ctx && lru) {
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002069 ssl_ctx = ssl_sock_do_create_cert(servername, bind_conf, ssl);
Christopher Faulet31af49d2015-06-09 17:29:50 +02002070 lru64_commit(lru, ssl_ctx, cacert, 0, (void (*)(void *))SSL_CTX_free);
Christopher Fauletd2cab922015-07-28 16:03:47 +02002071 }
Willy Tarreau2f63ef42015-10-20 15:16:01 +02002072 SSL_set_SSL_CTX(ssl, ssl_ctx);
Christopher Faulet2a944ee2017-11-07 10:42:54 +01002073 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002074 return 1;
Christopher Faulet31af49d2015-06-09 17:29:50 +02002075 }
Willy Tarreau2f63ef42015-10-20 15:16:01 +02002076 else {
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002077 ssl_ctx = ssl_sock_do_create_cert(servername, bind_conf, ssl);
Willy Tarreau2f63ef42015-10-20 15:16:01 +02002078 SSL_set_SSL_CTX(ssl, ssl_ctx);
2079 /* No LRU cache, this CTX will be released as soon as the session dies */
2080 SSL_CTX_free(ssl_ctx);
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002081 return 1;
Willy Tarreau2f63ef42015-10-20 15:16:01 +02002082 }
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002083 return 0;
2084}
2085static int
2086ssl_sock_generate_certificate_from_conn(struct bind_conf *bind_conf, SSL *ssl)
2087{
2088 unsigned int key;
Thierry FOURNIER28962c92018-06-17 21:37:05 +02002089 struct connection *conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002090
2091 conn_get_to_addr(conn);
2092 if (conn->flags & CO_FL_ADDR_TO_SET) {
2093 key = ssl_sock_generated_cert_key(&conn->addr.to, get_addr_len(&conn->addr.to));
Emeric Brun821bb9b2017-06-15 16:37:39 +02002094 if (ssl_sock_assign_generated_cert(key, bind_conf, ssl))
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002095 return 1;
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002096 }
2097 return 0;
Christopher Faulet31af49d2015-06-09 17:29:50 +02002098}
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002099#endif /* !defined SSL_NO_GENERATE_CERTIFICATES */
Christopher Faulet31af49d2015-06-09 17:29:50 +02002100
Willy Tarreau9a1ab082019-05-09 13:26:41 +02002101#if (HA_OPENSSL_VERSION_NUMBER < 0x1010000fL)
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002102typedef enum { SET_CLIENT, SET_SERVER } set_context_func;
2103
2104static void ctx_set_SSLv3_func(SSL_CTX *ctx, set_context_func c)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002105{
Emmanuel Hocdet23877ab2017-07-12 12:53:02 +02002106#if SSL_OP_NO_SSLv3
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002107 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, SSLv3_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002108 : SSL_CTX_set_ssl_version(ctx, SSLv3_client_method());
2109#endif
2110}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002111static void ctx_set_TLSv10_func(SSL_CTX *ctx, set_context_func c) {
2112 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, TLSv1_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002113 : SSL_CTX_set_ssl_version(ctx, TLSv1_client_method());
2114}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002115static void ctx_set_TLSv11_func(SSL_CTX *ctx, set_context_func c) {
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002116#if SSL_OP_NO_TLSv1_1
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002117 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, TLSv1_1_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002118 : SSL_CTX_set_ssl_version(ctx, TLSv1_1_client_method());
2119#endif
2120}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002121static void ctx_set_TLSv12_func(SSL_CTX *ctx, set_context_func c) {
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002122#if SSL_OP_NO_TLSv1_2
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002123 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, TLSv1_2_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002124 : SSL_CTX_set_ssl_version(ctx, TLSv1_2_client_method());
2125#endif
2126}
Bertrand Jacquina25282b2018-08-14 00:56:13 +01002127/* TLSv1.2 is the last supported version in this context. */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002128static void ctx_set_TLSv13_func(SSL_CTX *ctx, set_context_func c) {}
2129/* Unusable in this context. */
2130static void ssl_set_SSLv3_func(SSL *ssl, set_context_func c) {}
2131static void ssl_set_TLSv10_func(SSL *ssl, set_context_func c) {}
2132static void ssl_set_TLSv11_func(SSL *ssl, set_context_func c) {}
2133static void ssl_set_TLSv12_func(SSL *ssl, set_context_func c) {}
2134static void ssl_set_TLSv13_func(SSL *ssl, set_context_func c) {}
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002135#else /* openssl >= 1.1.0 */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002136typedef enum { SET_MIN, SET_MAX } set_context_func;
2137
2138static void ctx_set_SSLv3_func(SSL_CTX *ctx, set_context_func c) {
2139 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, SSL3_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002140 : SSL_CTX_set_min_proto_version(ctx, SSL3_VERSION);
2141}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002142static void ssl_set_SSLv3_func(SSL *ssl, set_context_func c) {
2143 c == SET_MAX ? SSL_set_max_proto_version(ssl, SSL3_VERSION)
2144 : SSL_set_min_proto_version(ssl, SSL3_VERSION);
2145}
2146static void ctx_set_TLSv10_func(SSL_CTX *ctx, set_context_func c) {
2147 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002148 : SSL_CTX_set_min_proto_version(ctx, TLS1_VERSION);
2149}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002150static void ssl_set_TLSv10_func(SSL *ssl, set_context_func c) {
2151 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_VERSION)
2152 : SSL_set_min_proto_version(ssl, TLS1_VERSION);
2153}
2154static void ctx_set_TLSv11_func(SSL_CTX *ctx, set_context_func c) {
2155 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_1_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002156 : SSL_CTX_set_min_proto_version(ctx, TLS1_1_VERSION);
2157}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002158static void ssl_set_TLSv11_func(SSL *ssl, set_context_func c) {
2159 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_1_VERSION)
2160 : SSL_set_min_proto_version(ssl, TLS1_1_VERSION);
2161}
2162static void ctx_set_TLSv12_func(SSL_CTX *ctx, set_context_func c) {
2163 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_2_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002164 : SSL_CTX_set_min_proto_version(ctx, TLS1_2_VERSION);
2165}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002166static void ssl_set_TLSv12_func(SSL *ssl, set_context_func c) {
2167 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_2_VERSION)
2168 : SSL_set_min_proto_version(ssl, TLS1_2_VERSION);
2169}
2170static void ctx_set_TLSv13_func(SSL_CTX *ctx, set_context_func c) {
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002171#if SSL_OP_NO_TLSv1_3
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002172 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_3_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002173 : SSL_CTX_set_min_proto_version(ctx, TLS1_3_VERSION);
2174#endif
2175}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002176static void ssl_set_TLSv13_func(SSL *ssl, set_context_func c) {
2177#if SSL_OP_NO_TLSv1_3
2178 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_3_VERSION)
2179 : SSL_set_min_proto_version(ssl, TLS1_3_VERSION);
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002180#endif
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002181}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002182#endif
2183static void ctx_set_None_func(SSL_CTX *ctx, set_context_func c) { }
2184static void ssl_set_None_func(SSL *ssl, set_context_func c) { }
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002185
2186static struct {
2187 int option;
2188 uint16_t flag;
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002189 void (*ctx_set_version)(SSL_CTX *, set_context_func);
2190 void (*ssl_set_version)(SSL *, set_context_func);
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002191 const char *name;
2192} methodVersions[] = {
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002193 {0, 0, ctx_set_None_func, ssl_set_None_func, "NONE"}, /* CONF_TLSV_NONE */
2194 {SSL_OP_NO_SSLv3, MC_SSL_O_NO_SSLV3, ctx_set_SSLv3_func, ssl_set_SSLv3_func, "SSLv3"}, /* CONF_SSLV3 */
2195 {SSL_OP_NO_TLSv1, MC_SSL_O_NO_TLSV10, ctx_set_TLSv10_func, ssl_set_TLSv10_func, "TLSv1.0"}, /* CONF_TLSV10 */
2196 {SSL_OP_NO_TLSv1_1, MC_SSL_O_NO_TLSV11, ctx_set_TLSv11_func, ssl_set_TLSv11_func, "TLSv1.1"}, /* CONF_TLSV11 */
2197 {SSL_OP_NO_TLSv1_2, MC_SSL_O_NO_TLSV12, ctx_set_TLSv12_func, ssl_set_TLSv12_func, "TLSv1.2"}, /* CONF_TLSV12 */
2198 {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 +02002199};
2200
Emmanuel Hocdet530141f2017-03-01 18:54:56 +01002201static void ssl_sock_switchctx_set(SSL *ssl, SSL_CTX *ctx)
2202{
2203 SSL_set_verify(ssl, SSL_CTX_get_verify_mode(ctx), ssl_sock_bind_verifycbk);
2204 SSL_set_client_CA_list(ssl, SSL_dup_CA_list(SSL_CTX_get_client_CA_list(ctx)));
2205 SSL_set_SSL_CTX(ssl, ctx);
2206}
2207
Willy Tarreau5db847a2019-05-09 14:13:35 +02002208#if ((HA_OPENSSL_VERSION_NUMBER >= 0x10101000L) || defined(OPENSSL_IS_BORINGSSL))
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002209
2210static int ssl_sock_switchctx_err_cbk(SSL *ssl, int *al, void *priv)
2211{
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002212 struct bind_conf *s = priv;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002213 (void)al; /* shut gcc stupid warning */
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002214
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002215 if (SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name) || s->generate_certs)
2216 return SSL_TLSEXT_ERR_OK;
2217 return SSL_TLSEXT_ERR_NOACK;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002218}
2219
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002220#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002221static int ssl_sock_switchctx_cbk(const struct ssl_early_callback_ctx *ctx)
2222{
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002223 SSL *ssl = ctx->ssl;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002224#else
2225static int ssl_sock_switchctx_cbk(SSL *ssl, int *al, void *arg)
2226{
2227#endif
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002228 struct connection *conn;
2229 struct bind_conf *s;
2230 const uint8_t *extension_data;
2231 size_t extension_len;
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002232 int has_rsa_sig = 0, has_ecdsa_sig = 0;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002233
2234 char *wildp = NULL;
2235 const uint8_t *servername;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002236 size_t servername_len;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002237 struct ebmb_node *node, *n, *node_ecdsa = NULL, *node_rsa = NULL, *node_anonymous = NULL;
Olivier Houchardc2aae742017-09-22 18:26:28 +02002238 int allow_early = 0;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002239 int i;
2240
Thierry FOURNIER28962c92018-06-17 21:37:05 +02002241 conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Willy Tarreaua8825522018-10-15 13:20:07 +02002242 s = __objt_listener(conn->target)->bind_conf;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002243
Olivier Houchard9679ac92017-10-27 14:58:08 +02002244 if (s->ssl_conf.early_data)
Olivier Houchardc2aae742017-09-22 18:26:28 +02002245 allow_early = 1;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002246#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002247 if (SSL_early_callback_ctx_extension_get(ctx, TLSEXT_TYPE_server_name,
2248 &extension_data, &extension_len)) {
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002249#else
2250 if (SSL_client_hello_get0_ext(ssl, TLSEXT_TYPE_server_name, &extension_data, &extension_len)) {
2251#endif
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002252 /*
2253 * The server_name extension was given too much extensibility when it
2254 * was written, so parsing the normal case is a bit complex.
2255 */
2256 size_t len;
2257 if (extension_len <= 2)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002258 goto abort;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002259 /* Extract the length of the supplied list of names. */
2260 len = (*extension_data++) << 8;
2261 len |= *extension_data++;
2262 if (len + 2 != extension_len)
2263 goto abort;
2264 /*
2265 * The list in practice only has a single element, so we only consider
2266 * the first one.
2267 */
2268 if (len == 0 || *extension_data++ != TLSEXT_NAMETYPE_host_name)
2269 goto abort;
2270 extension_len = len - 1;
2271 /* Now we can finally pull out the byte array with the actual hostname. */
2272 if (extension_len <= 2)
2273 goto abort;
2274 len = (*extension_data++) << 8;
2275 len |= *extension_data++;
2276 if (len == 0 || len + 2 > extension_len || len > TLSEXT_MAXLEN_host_name
2277 || memchr(extension_data, 0, len) != NULL)
2278 goto abort;
2279 servername = extension_data;
2280 servername_len = len;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002281 } else {
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002282#if (!defined SSL_NO_GENERATE_CERTIFICATES)
2283 if (s->generate_certs && ssl_sock_generate_certificate_from_conn(s, ssl)) {
Olivier Houchardc2aae742017-09-22 18:26:28 +02002284 goto allow_early;
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002285 }
2286#endif
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002287 /* without SNI extension, is the default_ctx (need SSL_TLSEXT_ERR_NOACK) */
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002288 if (!s->strict_sni) {
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002289 ssl_sock_switchctx_set(ssl, s->default_ctx);
Olivier Houchardc2aae742017-09-22 18:26:28 +02002290 goto allow_early;
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002291 }
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002292 goto abort;
2293 }
2294
2295 /* extract/check clientHello informations */
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002296#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002297 if (SSL_early_callback_ctx_extension_get(ctx, TLSEXT_TYPE_signature_algorithms, &extension_data, &extension_len)) {
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002298#else
2299 if (SSL_client_hello_get0_ext(ssl, TLSEXT_TYPE_signature_algorithms, &extension_data, &extension_len)) {
2300#endif
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002301 uint8_t sign;
2302 size_t len;
2303 if (extension_len < 2)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002304 goto abort;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002305 len = (*extension_data++) << 8;
2306 len |= *extension_data++;
2307 if (len + 2 != extension_len)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002308 goto abort;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002309 if (len % 2 != 0)
2310 goto abort;
2311 for (; len > 0; len -= 2) {
2312 extension_data++; /* hash */
2313 sign = *extension_data++;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002314 switch (sign) {
2315 case TLSEXT_signature_rsa:
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002316 has_rsa_sig = 1;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002317 break;
2318 case TLSEXT_signature_ecdsa:
2319 has_ecdsa_sig = 1;
2320 break;
2321 default:
2322 continue;
2323 }
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002324 if (has_ecdsa_sig && has_rsa_sig)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002325 break;
2326 }
2327 } else {
Bertrand Jacquina25282b2018-08-14 00:56:13 +01002328 /* without TLSEXT_TYPE_signature_algorithms extension (< TLSv1.2) */
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002329 has_rsa_sig = 1;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002330 }
2331 if (has_ecdsa_sig) { /* in very rare case: has ecdsa sign but not a ECDSA cipher */
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002332 const SSL_CIPHER *cipher;
2333 size_t len;
2334 const uint8_t *cipher_suites;
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002335 has_ecdsa_sig = 0;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002336#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002337 len = ctx->cipher_suites_len;
2338 cipher_suites = ctx->cipher_suites;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002339#else
2340 len = SSL_client_hello_get0_ciphers(ssl, &cipher_suites);
2341#endif
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002342 if (len % 2 != 0)
2343 goto abort;
2344 for (; len != 0; len -= 2, cipher_suites += 2) {
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002345#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002346 uint16_t cipher_suite = (cipher_suites[0] << 8) | cipher_suites[1];
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002347 cipher = SSL_get_cipher_by_value(cipher_suite);
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002348#else
2349 cipher = SSL_CIPHER_find(ssl, cipher_suites);
2350#endif
Emmanuel Hocdet019f9b12017-10-02 17:12:06 +02002351 if (cipher && SSL_CIPHER_get_auth_nid(cipher) == NID_auth_ecdsa) {
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002352 has_ecdsa_sig = 1;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002353 break;
2354 }
2355 }
2356 }
2357
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002358 for (i = 0; i < trash.size && i < servername_len; i++) {
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002359 trash.area[i] = tolower(servername[i]);
2360 if (!wildp && (trash.area[i] == '.'))
2361 wildp = &trash.area[i];
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002362 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002363 trash.area[i] = 0;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002364
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002365
Emmanuel Hocdetcc957c32019-11-06 16:05:34 +01002366 for (i = 0; i < 2; i++) {
2367 if (i == 0) /* lookup in full qualified names */
2368 node = ebst_lookup(&s->sni_ctx, trash.area);
2369 else if (i == 1 && wildp) /* lookup in wildcards names */
2370 node = ebst_lookup(&s->sni_w_ctx, wildp);
2371 else
2372 break;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002373 for (n = node; n; n = ebmb_next_dup(n)) {
Emmanuel Hocdetcc957c32019-11-06 16:05:34 +01002374 /* lookup a not neg filter */
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002375 if (!container_of(n, struct sni_ctx, name)->neg) {
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002376 switch(container_of(n, struct sni_ctx, name)->kinfo.sig) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002377 case TLSEXT_signature_ecdsa:
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002378 if (!node_ecdsa)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002379 node_ecdsa = n;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002380 break;
2381 case TLSEXT_signature_rsa:
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002382 if (!node_rsa)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002383 node_rsa = n;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002384 break;
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002385 default: /* TLSEXT_signature_anonymous|dsa */
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002386 if (!node_anonymous)
2387 node_anonymous = n;
2388 break;
2389 }
2390 }
2391 }
Emmanuel Hocdetcc957c32019-11-06 16:05:34 +01002392 /* select by key_signature priority order */
2393 node = (has_ecdsa_sig && node_ecdsa) ? node_ecdsa
2394 : ((has_rsa_sig && node_rsa) ? node_rsa
2395 : (node_anonymous ? node_anonymous
2396 : (node_ecdsa ? node_ecdsa /* no ecdsa signature case (< TLSv1.2) */
2397 : node_rsa /* no rsa signature case (far far away) */
2398 )));
2399 if (node) {
2400 /* switch ctx */
2401 struct ssl_bind_conf *conf = container_of(node, struct sni_ctx, name)->conf;
2402 ssl_sock_switchctx_set(ssl, container_of(node, struct sni_ctx, name)->ctx);
Olivier Houchard35a63cc2017-11-02 19:04:38 +01002403 if (conf) {
2404 methodVersions[conf->ssl_methods.min].ssl_set_version(ssl, SET_MIN);
2405 methodVersions[conf->ssl_methods.max].ssl_set_version(ssl, SET_MAX);
2406 if (conf->early_data)
2407 allow_early = 1;
2408 }
2409 goto allow_early;
Emmanuel Hocdetcc957c32019-11-06 16:05:34 +01002410 }
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002411 }
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002412#if (!defined SSL_NO_GENERATE_CERTIFICATES)
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002413 if (s->generate_certs && ssl_sock_generate_certificate(trash.area, s, ssl)) {
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002414 /* switch ctx done in ssl_sock_generate_certificate */
Olivier Houchardc2aae742017-09-22 18:26:28 +02002415 goto allow_early;
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002416 }
2417#endif
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002418 if (!s->strict_sni) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002419 /* no certificate match, is the default_ctx */
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002420 ssl_sock_switchctx_set(ssl, s->default_ctx);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002421 }
Olivier Houchardc2aae742017-09-22 18:26:28 +02002422allow_early:
2423#ifdef OPENSSL_IS_BORINGSSL
2424 if (allow_early)
2425 SSL_set_early_data_enabled(ssl, 1);
2426#else
2427 if (!allow_early)
2428 SSL_set_max_early_data(ssl, 0);
2429#endif
2430 return 1;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002431 abort:
2432 /* abort handshake (was SSL_TLSEXT_ERR_ALERT_FATAL) */
2433 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002434#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002435 return ssl_select_cert_error;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002436#else
2437 *al = SSL_AD_UNRECOGNIZED_NAME;
2438 return 0;
2439#endif
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002440}
2441
2442#else /* OPENSSL_IS_BORINGSSL */
2443
Emeric Brunfc0421f2012-09-07 17:30:07 +02002444/* Sets the SSL ctx of <ssl> to match the advertised server name. Returns a
2445 * warning when no match is found, which implies the default (first) cert
2446 * will keep being used.
2447 */
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002448static int ssl_sock_switchctx_cbk(SSL *ssl, int *al, void *priv)
Emeric Brunfc0421f2012-09-07 17:30:07 +02002449{
2450 const char *servername;
2451 const char *wildp = NULL;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002452 struct ebmb_node *node, *n;
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002453 struct bind_conf *s = priv;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002454 int i;
2455 (void)al; /* shut gcc stupid warning */
2456
2457 servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
Emmanuel Hocdet65623372013-01-24 17:17:15 +01002458 if (!servername) {
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002459#if (!defined SSL_NO_GENERATE_CERTIFICATES)
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002460 if (s->generate_certs && ssl_sock_generate_certificate_from_conn(s, ssl))
2461 return SSL_TLSEXT_ERR_OK;
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002462#endif
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002463 if (s->strict_sni)
2464 return SSL_TLSEXT_ERR_ALERT_FATAL;
2465 ssl_sock_switchctx_set(ssl, s->default_ctx);
2466 return SSL_TLSEXT_ERR_NOACK;
Emmanuel Hocdet65623372013-01-24 17:17:15 +01002467 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02002468
Willy Tarreau19d14ef2012-10-29 16:51:55 +01002469 for (i = 0; i < trash.size; i++) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02002470 if (!servername[i])
2471 break;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002472 trash.area[i] = tolower(servername[i]);
2473 if (!wildp && (trash.area[i] == '.'))
2474 wildp = &trash.area[i];
Emeric Brunfc0421f2012-09-07 17:30:07 +02002475 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002476 trash.area[i] = 0;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002477
Emmanuel Hocdet26b7b802019-11-04 15:49:46 +01002478 node = NULL;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002479 /* lookup in full qualified names */
Emmanuel Hocdet26b7b802019-11-04 15:49:46 +01002480 for (n = ebst_lookup(&s->sni_ctx, trash.area); n; n = ebmb_next_dup(n)) {
2481 /* lookup a not neg filter */
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002482 if (!container_of(n, struct sni_ctx, name)->neg) {
2483 node = n;
2484 break;
Emmanuel Hocdet65623372013-01-24 17:17:15 +01002485 }
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002486 }
2487 if (!node && wildp) {
2488 /* lookup in wildcards names */
Emmanuel Hocdet26b7b802019-11-04 15:49:46 +01002489 for (n = ebst_lookup(&s->sni_w_ctx, wildp); n; n = ebmb_next_dup(n)) {
2490 /* lookup a not neg filter */
2491 if (!container_of(n, struct sni_ctx, name)->neg) {
2492 node = n;
2493 break;
2494 }
2495 }
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002496 }
Emmanuel Hocdet26b7b802019-11-04 15:49:46 +01002497 if (!node) {
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002498#if (!defined SSL_NO_GENERATE_CERTIFICATES)
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002499 if (s->generate_certs && ssl_sock_generate_certificate(servername, s, ssl)) {
2500 /* switch ctx done in ssl_sock_generate_certificate */
Christopher Faulet31af49d2015-06-09 17:29:50 +02002501 return SSL_TLSEXT_ERR_OK;
2502 }
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002503#endif
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002504 if (s->strict_sni)
2505 return SSL_TLSEXT_ERR_ALERT_FATAL;
2506 ssl_sock_switchctx_set(ssl, s->default_ctx);
2507 return SSL_TLSEXT_ERR_OK;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002508 }
2509
2510 /* switch ctx */
Emmanuel Hocdet530141f2017-03-01 18:54:56 +01002511 ssl_sock_switchctx_set(ssl, container_of(node, struct sni_ctx, name)->ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02002512 return SSL_TLSEXT_ERR_OK;
2513}
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002514#endif /* (!) OPENSSL_IS_BORINGSSL */
Emeric Brunfc0421f2012-09-07 17:30:07 +02002515#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
2516
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002517#ifndef OPENSSL_NO_DH
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002518
2519static DH * ssl_get_dh_1024(void)
2520{
Remi Gacogned3a341a2015-05-29 16:26:17 +02002521 static unsigned char dh1024_p[]={
2522 0xFA,0xF9,0x2A,0x22,0x2A,0xA7,0x7F,0xE1,0x67,0x4E,0x53,0xF7,
2523 0x56,0x13,0xC3,0xB1,0xE3,0x29,0x6B,0x66,0x31,0x6A,0x7F,0xB3,
2524 0xC2,0x68,0x6B,0xCB,0x1D,0x57,0x39,0x1D,0x1F,0xFF,0x1C,0xC9,
2525 0xA6,0xA4,0x98,0x82,0x31,0x5D,0x25,0xFF,0x8A,0xE0,0x73,0x96,
2526 0x81,0xC8,0x83,0x79,0xC1,0x5A,0x04,0xF8,0x37,0x0D,0xA8,0x3D,
2527 0xAE,0x74,0xBC,0xDB,0xB6,0xA4,0x75,0xD9,0x71,0x8A,0xA0,0x17,
2528 0x9E,0x2D,0xC8,0xA8,0xDF,0x2C,0x5F,0x82,0x95,0xF8,0x92,0x9B,
2529 0xA7,0x33,0x5F,0x89,0x71,0xC8,0x2D,0x6B,0x18,0x86,0xC4,0x94,
2530 0x22,0xA5,0x52,0x8D,0xF6,0xF6,0xD2,0x37,0x92,0x0F,0xA5,0xCC,
2531 0xDB,0x7B,0x1D,0x3D,0xA1,0x31,0xB7,0x80,0x8F,0x0B,0x67,0x5E,
2532 0x36,0xA5,0x60,0x0C,0xF1,0x95,0x33,0x8B,
2533 };
2534 static unsigned char dh1024_g[]={
2535 0x02,
2536 };
2537
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002538 BIGNUM *p;
2539 BIGNUM *g;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002540 DH *dh = DH_new();
2541 if (dh) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002542 p = BN_bin2bn(dh1024_p, sizeof dh1024_p, NULL);
2543 g = BN_bin2bn(dh1024_g, sizeof dh1024_g, NULL);
Remi Gacogned3a341a2015-05-29 16:26:17 +02002544
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002545 if (!p || !g) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002546 DH_free(dh);
2547 dh = NULL;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002548 } else {
2549 DH_set0_pqg(dh, p, NULL, g);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002550 }
2551 }
2552 return dh;
2553}
2554
2555static DH *ssl_get_dh_2048(void)
2556{
Remi Gacogned3a341a2015-05-29 16:26:17 +02002557 static unsigned char dh2048_p[]={
2558 0xEC,0x86,0xF8,0x70,0xA0,0x33,0x16,0xEC,0x05,0x1A,0x73,0x59,
2559 0xCD,0x1F,0x8B,0xF8,0x29,0xE4,0xD2,0xCF,0x52,0xDD,0xC2,0x24,
2560 0x8D,0xB5,0x38,0x9A,0xFB,0x5C,0xA4,0xE4,0xB2,0xDA,0xCE,0x66,
2561 0x50,0x74,0xA6,0x85,0x4D,0x4B,0x1D,0x30,0xB8,0x2B,0xF3,0x10,
2562 0xE9,0xA7,0x2D,0x05,0x71,0xE7,0x81,0xDF,0x8B,0x59,0x52,0x3B,
2563 0x5F,0x43,0x0B,0x68,0xF1,0xDB,0x07,0xBE,0x08,0x6B,0x1B,0x23,
2564 0xEE,0x4D,0xCC,0x9E,0x0E,0x43,0xA0,0x1E,0xDF,0x43,0x8C,0xEC,
2565 0xBE,0xBE,0x90,0xB4,0x51,0x54,0xB9,0x2F,0x7B,0x64,0x76,0x4E,
2566 0x5D,0xD4,0x2E,0xAE,0xC2,0x9E,0xAE,0x51,0x43,0x59,0xC7,0x77,
2567 0x9C,0x50,0x3C,0x0E,0xED,0x73,0x04,0x5F,0xF1,0x4C,0x76,0x2A,
2568 0xD8,0xF8,0xCF,0xFC,0x34,0x40,0xD1,0xB4,0x42,0x61,0x84,0x66,
2569 0x42,0x39,0x04,0xF8,0x68,0xB2,0x62,0xD7,0x55,0xED,0x1B,0x74,
2570 0x75,0x91,0xE0,0xC5,0x69,0xC1,0x31,0x5C,0xDB,0x7B,0x44,0x2E,
2571 0xCE,0x84,0x58,0x0D,0x1E,0x66,0x0C,0xC8,0x44,0x9E,0xFD,0x40,
2572 0x08,0x67,0x5D,0xFB,0xA7,0x76,0x8F,0x00,0x11,0x87,0xE9,0x93,
2573 0xF9,0x7D,0xC4,0xBC,0x74,0x55,0x20,0xD4,0x4A,0x41,0x2F,0x43,
2574 0x42,0x1A,0xC1,0xF2,0x97,0x17,0x49,0x27,0x37,0x6B,0x2F,0x88,
2575 0x7E,0x1C,0xA0,0xA1,0x89,0x92,0x27,0xD9,0x56,0x5A,0x71,0xC1,
2576 0x56,0x37,0x7E,0x3A,0x9D,0x05,0xE7,0xEE,0x5D,0x8F,0x82,0x17,
2577 0xBC,0xE9,0xC2,0x93,0x30,0x82,0xF9,0xF4,0xC9,0xAE,0x49,0xDB,
2578 0xD0,0x54,0xB4,0xD9,0x75,0x4D,0xFA,0x06,0xB8,0xD6,0x38,0x41,
2579 0xB7,0x1F,0x77,0xF3,
2580 };
2581 static unsigned char dh2048_g[]={
2582 0x02,
2583 };
2584
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002585 BIGNUM *p;
2586 BIGNUM *g;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002587 DH *dh = DH_new();
2588 if (dh) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002589 p = BN_bin2bn(dh2048_p, sizeof dh2048_p, NULL);
2590 g = BN_bin2bn(dh2048_g, sizeof dh2048_g, NULL);
Remi Gacogned3a341a2015-05-29 16:26:17 +02002591
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002592 if (!p || !g) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002593 DH_free(dh);
2594 dh = NULL;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002595 } else {
2596 DH_set0_pqg(dh, p, NULL, g);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002597 }
2598 }
2599 return dh;
2600}
2601
2602static DH *ssl_get_dh_4096(void)
2603{
Remi Gacogned3a341a2015-05-29 16:26:17 +02002604 static unsigned char dh4096_p[]={
2605 0xDE,0x16,0x94,0xCD,0x99,0x58,0x07,0xF1,0xF7,0x32,0x96,0x11,
2606 0x04,0x82,0xD4,0x84,0x72,0x80,0x99,0x06,0xCA,0xF0,0xA3,0x68,
2607 0x07,0xCE,0x64,0x50,0xE7,0x74,0x45,0x20,0x80,0x5E,0x4D,0xAD,
2608 0xA5,0xB6,0xED,0xFA,0x80,0x6C,0x3B,0x35,0xC4,0x9A,0x14,0x6B,
2609 0x32,0xBB,0xFD,0x1F,0x17,0x8E,0xB7,0x1F,0xD6,0xFA,0x3F,0x7B,
2610 0xEE,0x16,0xA5,0x62,0x33,0x0D,0xED,0xBC,0x4E,0x58,0xE5,0x47,
2611 0x4D,0xE9,0xAB,0x8E,0x38,0xD3,0x6E,0x90,0x57,0xE3,0x22,0x15,
2612 0x33,0xBD,0xF6,0x43,0x45,0xB5,0x10,0x0A,0xBE,0x2C,0xB4,0x35,
2613 0xB8,0x53,0x8D,0xAD,0xFB,0xA7,0x1F,0x85,0x58,0x41,0x7A,0x79,
2614 0x20,0x68,0xB3,0xE1,0x3D,0x08,0x76,0xBF,0x86,0x0D,0x49,0xE3,
2615 0x82,0x71,0x8C,0xB4,0x8D,0x81,0x84,0xD4,0xE7,0xBE,0x91,0xDC,
2616 0x26,0x39,0x48,0x0F,0x35,0xC4,0xCA,0x65,0xE3,0x40,0x93,0x52,
2617 0x76,0x58,0x7D,0xDD,0x51,0x75,0xDC,0x69,0x61,0xBF,0x47,0x2C,
2618 0x16,0x68,0x2D,0xC9,0x29,0xD3,0xE6,0xC0,0x99,0x48,0xA0,0x9A,
2619 0xC8,0x78,0xC0,0x6D,0x81,0x67,0x12,0x61,0x3F,0x71,0xBA,0x41,
2620 0x1F,0x6C,0x89,0x44,0x03,0xBA,0x3B,0x39,0x60,0xAA,0x28,0x55,
2621 0x59,0xAE,0xB8,0xFA,0xCB,0x6F,0xA5,0x1A,0xF7,0x2B,0xDD,0x52,
2622 0x8A,0x8B,0xE2,0x71,0xA6,0x5E,0x7E,0xD8,0x2E,0x18,0xE0,0x66,
2623 0xDF,0xDD,0x22,0x21,0x99,0x52,0x73,0xA6,0x33,0x20,0x65,0x0E,
2624 0x53,0xE7,0x6B,0x9B,0xC5,0xA3,0x2F,0x97,0x65,0x76,0xD3,0x47,
2625 0x23,0x77,0x12,0xB6,0x11,0x7B,0x24,0xED,0xF1,0xEF,0xC0,0xE2,
2626 0xA3,0x7E,0x67,0x05,0x3E,0x96,0x4D,0x45,0xC2,0x18,0xD1,0x73,
2627 0x9E,0x07,0xF3,0x81,0x6E,0x52,0x63,0xF6,0x20,0x76,0xB9,0x13,
2628 0xD2,0x65,0x30,0x18,0x16,0x09,0x16,0x9E,0x8F,0xF1,0xD2,0x10,
2629 0x5A,0xD3,0xD4,0xAF,0x16,0x61,0xDA,0x55,0x2E,0x18,0x5E,0x14,
2630 0x08,0x54,0x2E,0x2A,0x25,0xA2,0x1A,0x9B,0x8B,0x32,0xA9,0xFD,
2631 0xC2,0x48,0x96,0xE1,0x80,0xCA,0xE9,0x22,0x17,0xBB,0xCE,0x3E,
2632 0x9E,0xED,0xC7,0xF1,0x1F,0xEC,0x17,0x21,0xDC,0x7B,0x82,0x48,
2633 0x8E,0xBB,0x4B,0x9D,0x5B,0x04,0x04,0xDA,0xDB,0x39,0xDF,0x01,
2634 0x40,0xC3,0xAA,0x26,0x23,0x89,0x75,0xC6,0x0B,0xD0,0xA2,0x60,
2635 0x6A,0xF1,0xCC,0x65,0x18,0x98,0x1B,0x52,0xD2,0x74,0x61,0xCC,
2636 0xBD,0x60,0xAE,0xA3,0xA0,0x66,0x6A,0x16,0x34,0x92,0x3F,0x41,
2637 0x40,0x31,0x29,0xC0,0x2C,0x63,0xB2,0x07,0x8D,0xEB,0x94,0xB8,
2638 0xE8,0x47,0x92,0x52,0x93,0x6A,0x1B,0x7E,0x1A,0x61,0xB3,0x1B,
2639 0xF0,0xD6,0x72,0x9B,0xF1,0xB0,0xAF,0xBF,0x3E,0x65,0xEF,0x23,
2640 0x1D,0x6F,0xFF,0x70,0xCD,0x8A,0x4C,0x8A,0xA0,0x72,0x9D,0xBE,
2641 0xD4,0xBB,0x24,0x47,0x4A,0x68,0xB5,0xF5,0xC6,0xD5,0x7A,0xCD,
2642 0xCA,0x06,0x41,0x07,0xAD,0xC2,0x1E,0xE6,0x54,0xA7,0xAD,0x03,
2643 0xD9,0x12,0xC1,0x9C,0x13,0xB1,0xC9,0x0A,0x43,0x8E,0x1E,0x08,
2644 0xCE,0x50,0x82,0x73,0x5F,0xA7,0x55,0x1D,0xD9,0x59,0xAC,0xB5,
2645 0xEA,0x02,0x7F,0x6C,0x5B,0x74,0x96,0x98,0x67,0x24,0xA3,0x0F,
2646 0x15,0xFC,0xA9,0x7D,0x3E,0x67,0xD1,0x70,0xF8,0x97,0xF3,0x67,
2647 0xC5,0x8C,0x88,0x44,0x08,0x02,0xC7,0x2B,
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002648 };
Remi Gacogned3a341a2015-05-29 16:26:17 +02002649 static unsigned char dh4096_g[]={
2650 0x02,
2651 };
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002652
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002653 BIGNUM *p;
2654 BIGNUM *g;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002655 DH *dh = DH_new();
2656 if (dh) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002657 p = BN_bin2bn(dh4096_p, sizeof dh4096_p, NULL);
2658 g = BN_bin2bn(dh4096_g, sizeof dh4096_g, NULL);
Remi Gacogned3a341a2015-05-29 16:26:17 +02002659
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002660 if (!p || !g) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002661 DH_free(dh);
2662 dh = NULL;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002663 } else {
2664 DH_set0_pqg(dh, p, NULL, g);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002665 }
2666 }
2667 return dh;
2668}
2669
2670/* Returns Diffie-Hellman parameters matching the private key length
Willy Tarreauef934602016-12-22 23:12:01 +01002671 but not exceeding global_ssl.default_dh_param */
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002672static DH *ssl_get_tmp_dh(SSL *ssl, int export, int keylen)
2673{
2674 DH *dh = NULL;
2675 EVP_PKEY *pkey = SSL_get_privatekey(ssl);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002676 int type;
2677
2678 type = pkey ? EVP_PKEY_base_id(pkey) : EVP_PKEY_NONE;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002679
2680 /* The keylen supplied by OpenSSL can only be 512 or 1024.
2681 See ssl3_send_server_key_exchange() in ssl/s3_srvr.c
2682 */
2683 if (type == EVP_PKEY_RSA || type == EVP_PKEY_DSA) {
2684 keylen = EVP_PKEY_bits(pkey);
2685 }
2686
Willy Tarreauef934602016-12-22 23:12:01 +01002687 if (keylen > global_ssl.default_dh_param) {
2688 keylen = global_ssl.default_dh_param;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002689 }
2690
Remi Gacogned3a341a2015-05-29 16:26:17 +02002691 if (keylen >= 4096) {
Remi Gacogne8de54152014-07-15 11:36:40 +02002692 dh = local_dh_4096;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002693 }
2694 else if (keylen >= 2048) {
Remi Gacogne8de54152014-07-15 11:36:40 +02002695 dh = local_dh_2048;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002696 }
2697 else {
Remi Gacogne8de54152014-07-15 11:36:40 +02002698 dh = local_dh_1024;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002699 }
2700
2701 return dh;
2702}
2703
Remi Gacogne47783ef2015-05-29 15:53:22 +02002704static DH * ssl_sock_get_dh_from_file(const char *filename)
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002705{
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002706 DH *dh = NULL;
Remi Gacogne47783ef2015-05-29 15:53:22 +02002707 BIO *in = BIO_new(BIO_s_file());
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002708
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002709 if (in == NULL)
2710 goto end;
2711
Remi Gacogne47783ef2015-05-29 15:53:22 +02002712 if (BIO_read_filename(in, filename) <= 0)
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002713 goto end;
2714
Remi Gacogne47783ef2015-05-29 15:53:22 +02002715 dh = PEM_read_bio_DHparams(in, NULL, NULL, NULL);
2716
2717end:
2718 if (in)
2719 BIO_free(in);
2720
Emeric Brune1b4ed42018-08-16 15:14:12 +02002721 ERR_clear_error();
2722
Remi Gacogne47783ef2015-05-29 15:53:22 +02002723 return dh;
2724}
2725
2726int ssl_sock_load_global_dh_param_from_file(const char *filename)
2727{
2728 global_dh = ssl_sock_get_dh_from_file(filename);
2729
2730 if (global_dh) {
2731 return 0;
2732 }
2733
2734 return -1;
2735}
2736
Emeric Bruncfc1afe2019-10-17 13:27:40 +02002737/* Loads Diffie-Hellman parameter from a ckchs to an SSL_CTX.
2738 * If there is no DH paramater availaible in the ckchs, the global
2739 * DH parameter is loaded into the SSL_CTX and if there is no
2740 * DH parameter available in ckchs nor in global, the default
2741 * DH parameters are applied on the SSL_CTX.
2742 * Returns a bitfield containing the flags:
2743 * ERR_FATAL in any fatal error case
2744 * ERR_ALERT if a reason of the error is availabine in err
2745 * ERR_WARN if a warning is available into err
2746 * The value 0 means there is no error nor warning and
2747 * the operation succeed.
2748 */
2749static int ssl_sock_load_dh_params(SSL_CTX *ctx, const char *file, char **err)
2750 {
2751 int ret = 0;
Remi Gacogne47783ef2015-05-29 15:53:22 +02002752 DH *dh = ssl_sock_get_dh_from_file(file);
2753
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002754 if (dh) {
Emeric Brund6de1512019-10-17 14:53:03 +02002755 if (!SSL_CTX_set_tmp_dh(ctx, dh)) {
2756 memprintf(err, "%sunable to load the DH parameter specified in '%s'",
2757 err && *err ? *err : "", file);
2758#if defined(SSL_CTX_set_dh_auto)
2759 SSL_CTX_set_dh_auto(ctx, 1);
2760 memprintf(err, "%s, SSL library will use an automatically generated DH parameter.\n",
2761 err && *err ? *err : "");
2762#else
2763 memprintf(err, "%s, DH ciphers won't be available.\n",
2764 err && *err ? *err : "");
2765#endif
2766 ret |= ERR_WARN;
2767 goto end;
2768 }
Remi Gacogne4f902b82015-05-28 16:23:00 +02002769
2770 if (ssl_dh_ptr_index >= 0) {
2771 /* store a pointer to the DH params to avoid complaining about
2772 ssl-default-dh-param not being set for this SSL_CTX */
2773 SSL_CTX_set_ex_data(ctx, ssl_dh_ptr_index, dh);
2774 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002775 }
Remi Gacogne47783ef2015-05-29 15:53:22 +02002776 else if (global_dh) {
Emeric Brund6de1512019-10-17 14:53:03 +02002777 if (!SSL_CTX_set_tmp_dh(ctx, global_dh)) {
2778 memprintf(err, "%sunable to use the global DH parameter for certificate '%s'",
2779 err && *err ? *err : "", file);
2780#if defined(SSL_CTX_set_dh_auto)
2781 SSL_CTX_set_dh_auto(ctx, 1);
2782 memprintf(err, "%s, SSL library will use an automatically generated DH parameter.\n",
2783 err && *err ? *err : "");
2784#else
2785 memprintf(err, "%s, DH ciphers won't be available.\n",
2786 err && *err ? *err : "");
2787#endif
2788 ret |= ERR_WARN;
2789 goto end;
2790 }
Remi Gacogne47783ef2015-05-29 15:53:22 +02002791 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002792 else {
Emeric Brun41fdb3c2013-04-26 11:05:44 +02002793 /* Clear openssl global errors stack */
2794 ERR_clear_error();
2795
Willy Tarreauef934602016-12-22 23:12:01 +01002796 if (global_ssl.default_dh_param <= 1024) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002797 /* we are limited to DH parameter of 1024 bits anyway */
Remi Gacognec7e12632016-07-02 16:26:10 +02002798 if (local_dh_1024 == NULL)
2799 local_dh_1024 = ssl_get_dh_1024();
2800
Emeric Bruncfc1afe2019-10-17 13:27:40 +02002801 if (local_dh_1024 == NULL) {
2802 memprintf(err, "%sunable to load default 1024 bits DH parameter for certificate '%s'.\n",
2803 err && *err ? *err : "", file);
2804 ret |= ERR_ALERT | ERR_FATAL;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002805 goto end;
Emeric Bruncfc1afe2019-10-17 13:27:40 +02002806 }
Willy Tarreau6e774b42014-04-25 21:35:23 +02002807
Emeric Brund6de1512019-10-17 14:53:03 +02002808 if (!SSL_CTX_set_tmp_dh(ctx, local_dh_1024)) {
2809 memprintf(err, "%sunable to load default 1024 bits DH parameter for certificate '%s'.\n",
2810 err && *err ? *err : "", file);
2811#if defined(SSL_CTX_set_dh_auto)
2812 SSL_CTX_set_dh_auto(ctx, 1);
2813 memprintf(err, "%s, SSL library will use an automatically generated DH parameter.\n",
2814 err && *err ? *err : "");
2815#else
2816 memprintf(err, "%s, DH ciphers won't be available.\n",
2817 err && *err ? *err : "");
2818#endif
2819 ret |= ERR_WARN;
2820 goto end;
2821 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002822 }
2823 else {
2824 SSL_CTX_set_tmp_dh_callback(ctx, ssl_get_tmp_dh);
2825 }
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002826 }
Emeric Brun644cde02012-12-14 11:21:13 +01002827
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002828end:
2829 if (dh)
2830 DH_free(dh);
2831
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002832 return ret;
2833}
2834#endif
2835
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002836static 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 +02002837 struct pkey_info kinfo, char *name, int order)
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002838{
2839 struct sni_ctx *sc;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002840 int wild = 0, neg = 0;
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002841 struct ebmb_node *node;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002842
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002843 if (*name == '!') {
2844 neg = 1;
2845 name++;
2846 }
2847 if (*name == '*') {
2848 wild = 1;
2849 name++;
2850 }
2851 /* !* filter is a nop */
2852 if (neg && wild)
2853 return order;
2854 if (*name) {
2855 int j, len;
2856 len = strlen(name);
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002857 for (j = 0; j < len && j < trash.size; j++)
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002858 trash.area[j] = tolower(name[j]);
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002859 if (j >= trash.size)
William Lallemand24e292c2019-10-03 23:46:33 +02002860 return -1;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002861 trash.area[j] = 0;
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002862
2863 /* Check for duplicates. */
2864 if (wild)
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002865 node = ebst_lookup(&s->sni_w_ctx, trash.area);
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002866 else
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002867 node = ebst_lookup(&s->sni_ctx, trash.area);
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002868 for (; node; node = ebmb_next_dup(node)) {
2869 sc = ebmb_entry(node, struct sni_ctx, name);
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002870 if (sc->ctx == ctx && sc->conf == conf && sc->neg == neg)
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002871 return order;
2872 }
2873
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002874 sc = malloc(sizeof(struct sni_ctx) + len + 1);
Thierry FOURNIER / OZON.IO7a3bd3b2016-10-06 10:35:29 +02002875 if (!sc)
William Lallemand24e292c2019-10-03 23:46:33 +02002876 return -1;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002877 memcpy(sc->name.key, trash.area, len + 1);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002878 sc->ctx = ctx;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01002879 sc->conf = conf;
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002880 sc->kinfo = kinfo;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002881 sc->order = order++;
2882 sc->neg = neg;
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01002883 if (kinfo.sig != TLSEXT_signature_anonymous)
2884 SSL_CTX_set_ex_data(ctx, ssl_pkey_info_index, &sc->kinfo);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002885 if (wild)
2886 ebst_insert(&s->sni_w_ctx, &sc->name);
2887 else
2888 ebst_insert(&s->sni_ctx, &sc->name);
2889 }
2890 return order;
2891}
2892
yanbzhu488a4d22015-12-01 15:16:07 -05002893
2894/* The following code is used for loading multiple crt files into
2895 * SSL_CTX's based on CN/SAN
2896 */
Willy Tarreau5db847a2019-05-09 14:13:35 +02002897#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
yanbzhu488a4d22015-12-01 15:16:07 -05002898/* This is used to preload the certifcate, private key
2899 * and Cert Chain of a file passed in via the crt
2900 * argument
2901 *
2902 * This way, we do not have to read the file multiple times
2903 */
2904struct cert_key_and_chain {
2905 X509 *cert;
2906 EVP_PKEY *key;
2907 unsigned int num_chain_certs;
2908 /* This is an array of X509 pointers */
2909 X509 **chain_certs;
2910};
2911
yanbzhu08ce6ab2015-12-02 13:01:29 -05002912#define SSL_SOCK_POSSIBLE_KT_COMBOS (1<<(SSL_SOCK_NUM_KEYTYPES))
2913
2914struct key_combo_ctx {
2915 SSL_CTX *ctx;
2916 int order;
2917};
2918
2919/* Map used for processing multiple keypairs for a single purpose
2920 *
2921 * This maps CN/SNI name to certificate type
2922 */
2923struct sni_keytype {
2924 int keytypes; /* BITMASK for keytypes */
2925 struct ebmb_node name; /* node holding the servername value */
2926};
2927
2928
yanbzhu488a4d22015-12-01 15:16:07 -05002929/* Frees the contents of a cert_key_and_chain
2930 */
2931static void ssl_sock_free_cert_key_and_chain_contents(struct cert_key_and_chain *ckch)
2932{
2933 int i;
2934
2935 if (!ckch)
2936 return;
2937
2938 /* Free the certificate and set pointer to NULL */
2939 if (ckch->cert)
2940 X509_free(ckch->cert);
2941 ckch->cert = NULL;
2942
2943 /* Free the key and set pointer to NULL */
2944 if (ckch->key)
2945 EVP_PKEY_free(ckch->key);
2946 ckch->key = NULL;
2947
2948 /* Free each certificate in the chain */
2949 for (i = 0; i < ckch->num_chain_certs; i++) {
2950 if (ckch->chain_certs[i])
2951 X509_free(ckch->chain_certs[i]);
2952 }
2953
2954 /* Free the chain obj itself and set to NULL */
2955 if (ckch->num_chain_certs > 0) {
2956 free(ckch->chain_certs);
2957 ckch->num_chain_certs = 0;
2958 ckch->chain_certs = NULL;
2959 }
2960
2961}
2962
2963/* checks if a key and cert exists in the ckch
2964 */
2965static int ssl_sock_is_ckch_valid(struct cert_key_and_chain *ckch)
2966{
2967 return (ckch->cert != NULL && ckch->key != NULL);
2968}
2969
2970
2971/* Loads the contents of a crt file (path) into a cert_key_and_chain
2972 * This allows us to carry the contents of the file without having to
2973 * read the file multiple times.
2974 *
2975 * returns:
2976 * 0 on Success
2977 * 1 on SSL Failure
2978 * 2 on file not found
2979 */
2980static int ssl_sock_load_crt_file_into_ckch(const char *path, struct cert_key_and_chain *ckch, char **err)
2981{
2982
2983 BIO *in;
2984 X509 *ca = NULL;
2985 int ret = 1;
2986
2987 ssl_sock_free_cert_key_and_chain_contents(ckch);
2988
2989 in = BIO_new(BIO_s_file());
2990 if (in == NULL)
2991 goto end;
2992
2993 if (BIO_read_filename(in, path) <= 0)
2994 goto end;
2995
yanbzhu488a4d22015-12-01 15:16:07 -05002996 /* Read Private Key */
2997 ckch->key = PEM_read_bio_PrivateKey(in, NULL, NULL, NULL);
2998 if (ckch->key == NULL) {
2999 memprintf(err, "%sunable to load private key from file '%s'.\n",
3000 err && *err ? *err : "", path);
3001 goto end;
3002 }
3003
Willy Tarreaubb137a82016-04-06 19:02:38 +02003004 /* Seek back to beginning of file */
Thierry FOURNIER / OZON.IOd44ea3f2016-10-14 00:49:21 +02003005 if (BIO_reset(in) == -1) {
3006 memprintf(err, "%san error occurred while reading the file '%s'.\n",
3007 err && *err ? *err : "", path);
3008 goto end;
3009 }
Willy Tarreaubb137a82016-04-06 19:02:38 +02003010
3011 /* Read Certificate */
3012 ckch->cert = PEM_read_bio_X509_AUX(in, NULL, NULL, NULL);
3013 if (ckch->cert == NULL) {
3014 memprintf(err, "%sunable to load certificate from file '%s'.\n",
3015 err && *err ? *err : "", path);
3016 goto end;
3017 }
3018
yanbzhu488a4d22015-12-01 15:16:07 -05003019 /* Read Certificate Chain */
3020 while ((ca = PEM_read_bio_X509(in, NULL, NULL, NULL))) {
3021 /* Grow the chain certs */
3022 ckch->num_chain_certs++;
3023 ckch->chain_certs = realloc(ckch->chain_certs, (ckch->num_chain_certs * sizeof(X509 *)));
3024
3025 /* use - 1 here since we just incremented it above */
3026 ckch->chain_certs[ckch->num_chain_certs - 1] = ca;
3027 }
3028 ret = ERR_get_error();
3029 if (ret && (ERR_GET_LIB(ret) != ERR_LIB_PEM && ERR_GET_REASON(ret) != PEM_R_NO_START_LINE)) {
3030 memprintf(err, "%sunable to load certificate chain from file '%s'.\n",
3031 err && *err ? *err : "", path);
3032 ret = 1;
3033 goto end;
3034 }
3035
3036 ret = 0;
3037
3038end:
3039
3040 ERR_clear_error();
3041 if (in)
3042 BIO_free(in);
3043
3044 /* Something went wrong in one of the reads */
3045 if (ret != 0)
3046 ssl_sock_free_cert_key_and_chain_contents(ckch);
3047
3048 return ret;
3049}
3050
3051/* Loads the info in ckch into ctx
Emeric Brun394701d2019-10-17 13:25:14 +02003052 * Returns a bitfield containing the flags:
3053 * ERR_FATAL in any fatal error case
3054 * ERR_ALERT if the reason of the error is available in err
3055 * ERR_WARN if a warning is available into err
3056 * The value 0 means there is no error nor warning and
3057 * the operation succeed.
yanbzhu488a4d22015-12-01 15:16:07 -05003058 */
3059static int ssl_sock_put_ckch_into_ctx(const char *path, const struct cert_key_and_chain *ckch, SSL_CTX *ctx, char **err)
3060{
3061 int i = 0;
Emeric Brun394701d2019-10-17 13:25:14 +02003062 int errcode = 0;
yanbzhu488a4d22015-12-01 15:16:07 -05003063
3064 if (SSL_CTX_use_PrivateKey(ctx, ckch->key) <= 0) {
3065 memprintf(err, "%sunable to load SSL private key into SSL Context '%s'.\n",
3066 err && *err ? *err : "", path);
Emeric Brun394701d2019-10-17 13:25:14 +02003067 errcode |= ERR_ALERT | ERR_FATAL;
3068 return errcode;
yanbzhu488a4d22015-12-01 15:16:07 -05003069 }
3070
3071 if (!SSL_CTX_use_certificate(ctx, ckch->cert)) {
3072 memprintf(err, "%sunable to load SSL certificate into SSL Context '%s'.\n",
3073 err && *err ? *err : "", path);
Emeric Brun394701d2019-10-17 13:25:14 +02003074 errcode |= ERR_ALERT | ERR_FATAL;
3075 goto end;
yanbzhu488a4d22015-12-01 15:16:07 -05003076 }
3077
yanbzhu488a4d22015-12-01 15:16:07 -05003078 /* Load all certs in the ckch into the ctx_chain for the ssl_ctx */
3079 for (i = 0; i < ckch->num_chain_certs; i++) {
3080 if (!SSL_CTX_add1_chain_cert(ctx, ckch->chain_certs[i])) {
yanbzhu08ce6ab2015-12-02 13:01:29 -05003081 memprintf(err, "%sunable to load chain certificate #%d into SSL Context '%s'. Make sure you are linking against Openssl >= 1.0.2.\n",
3082 err && *err ? *err : "", (i+1), path);
Emeric Brun394701d2019-10-17 13:25:14 +02003083 errcode |= ERR_ALERT | ERR_FATAL;
3084 goto end;
yanbzhu488a4d22015-12-01 15:16:07 -05003085 }
3086 }
3087
3088 if (SSL_CTX_check_private_key(ctx) <= 0) {
3089 memprintf(err, "%sinconsistencies between private key and certificate loaded from PEM file '%s'.\n",
3090 err && *err ? *err : "", path);
Emeric Brun394701d2019-10-17 13:25:14 +02003091 errcode |= ERR_ALERT | ERR_FATAL;
yanbzhu488a4d22015-12-01 15:16:07 -05003092 }
3093
Emeric Brun394701d2019-10-17 13:25:14 +02003094 end:
3095 return errcode;
yanbzhu488a4d22015-12-01 15:16:07 -05003096}
3097
yanbzhu08ce6ab2015-12-02 13:01:29 -05003098
William Lallemand4801c702019-10-04 17:36:55 +02003099static int ssl_sock_populate_sni_keytypes_hplr(const char *str, struct eb_root *sni_keytypes, int key_index)
yanbzhu08ce6ab2015-12-02 13:01:29 -05003100{
3101 struct sni_keytype *s_kt = NULL;
3102 struct ebmb_node *node;
3103 int i;
3104
3105 for (i = 0; i < trash.size; i++) {
3106 if (!str[i])
3107 break;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02003108 trash.area[i] = tolower(str[i]);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003109 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +02003110 trash.area[i] = 0;
3111 node = ebst_lookup(sni_keytypes, trash.area);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003112 if (!node) {
3113 /* CN not found in tree */
3114 s_kt = malloc(sizeof(struct sni_keytype) + i + 1);
3115 /* Using memcpy here instead of strncpy.
3116 * strncpy will cause sig_abrt errors under certain versions of gcc with -O2
3117 * See: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=60792
3118 */
William Lallemand4801c702019-10-04 17:36:55 +02003119 if (!s_kt)
3120 return -1;
3121
Willy Tarreau843b7cb2018-07-13 10:54:26 +02003122 memcpy(s_kt->name.key, trash.area, i+1);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003123 s_kt->keytypes = 0;
3124 ebst_insert(sni_keytypes, &s_kt->name);
3125 } else {
3126 /* CN found in tree */
3127 s_kt = container_of(node, struct sni_keytype, name);
3128 }
3129
3130 /* Mark that this CN has the keytype of key_index via keytypes mask */
3131 s_kt->keytypes |= 1<<key_index;
3132
William Lallemand4801c702019-10-04 17:36:55 +02003133 return 0;
3134
yanbzhu08ce6ab2015-12-02 13:01:29 -05003135}
3136
3137
3138/* Given a path that does not exist, try to check for path.rsa, path.dsa and path.ecdsa files.
3139 * If any are found, group these files into a set of SSL_CTX*
3140 * based on shared and unique CN and SAN entries. Add these SSL_CTX* to the SNI tree.
3141 *
Joseph Herlant017b3da2018-11-15 09:07:59 -08003142 * This will allow the user to explicitly group multiple cert/keys for a single purpose
yanbzhu08ce6ab2015-12-02 13:01:29 -05003143 *
Willy Tarreaub131c872019-10-16 16:42:19 +02003144 * Returns a set of ERR_* flags possibly with an error in <err>.
3145 *
yanbzhu08ce6ab2015-12-02 13:01:29 -05003146 */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003147static int ssl_sock_load_multi_cert(const char *path, struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
3148 char **sni_filter, int fcount, char **err)
yanbzhu08ce6ab2015-12-02 13:01:29 -05003149{
3150 char fp[MAXPATHLEN+1] = {0};
3151 int n = 0;
3152 int i = 0;
3153 struct cert_key_and_chain certs_and_keys[SSL_SOCK_NUM_KEYTYPES] = { {0} };
3154 struct eb_root sni_keytypes_map = { {0} };
3155 struct ebmb_node *node;
3156 struct ebmb_node *next;
3157 /* Array of SSL_CTX pointers corresponding to each possible combo
3158 * of keytypes
3159 */
3160 struct key_combo_ctx key_combos[SSL_SOCK_POSSIBLE_KT_COMBOS] = { {0} };
Willy Tarreaub131c872019-10-16 16:42:19 +02003161 int errcode = 0;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003162 X509_NAME *xname = NULL;
3163 char *str = NULL;
3164#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
3165 STACK_OF(GENERAL_NAME) *names = NULL;
3166#endif
3167
3168 /* Load all possible certs and keys */
3169 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
3170 struct stat buf;
3171
3172 snprintf(fp, sizeof(fp), "%s.%s", path, SSL_SOCK_KEYTYPE_NAMES[n]);
3173 if (stat(fp, &buf) == 0) {
3174 if (ssl_sock_load_crt_file_into_ckch(fp, &certs_and_keys[n], err) == 1) {
Willy Tarreaub131c872019-10-16 16:42:19 +02003175 errcode |= ERR_ALERT | ERR_FATAL;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003176 goto end;
3177 }
3178 }
3179 }
3180
3181 /* Process each ckch and update keytypes for each CN/SAN
3182 * for example, if CN/SAN www.a.com is associated with
3183 * certs with keytype 0 and 2, then at the end of the loop,
3184 * www.a.com will have:
3185 * keyindex = 0 | 1 | 4 = 5
3186 */
3187 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
William Lallemand4801c702019-10-04 17:36:55 +02003188 int ret;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003189
3190 if (!ssl_sock_is_ckch_valid(&certs_and_keys[n]))
3191 continue;
3192
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003193 if (fcount) {
William Lallemand4801c702019-10-04 17:36:55 +02003194 for (i = 0; i < fcount; i++) {
3195 ret = ssl_sock_populate_sni_keytypes_hplr(sni_filter[i], &sni_keytypes_map, n);
3196 if (ret < 0) {
3197 memprintf(err, "%sunable to allocate SSL context.\n",
3198 err && *err ? *err : "");
Willy Tarreaub131c872019-10-16 16:42:19 +02003199 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemand4801c702019-10-04 17:36:55 +02003200 goto end;
3201 }
3202 }
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003203 } else {
3204 /* A lot of the following code is OpenSSL boilerplate for processing CN's and SAN's,
3205 * so the line that contains logic is marked via comments
3206 */
3207 xname = X509_get_subject_name(certs_and_keys[n].cert);
3208 i = -1;
3209 while ((i = X509_NAME_get_index_by_NID(xname, NID_commonName, i)) != -1) {
3210 X509_NAME_ENTRY *entry = X509_NAME_get_entry(xname, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003211 ASN1_STRING *value;
3212 value = X509_NAME_ENTRY_get_data(entry);
3213 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003214 /* Important line is here */
William Lallemand4801c702019-10-04 17:36:55 +02003215 ret = ssl_sock_populate_sni_keytypes_hplr(str, &sni_keytypes_map, n);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003216
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003217 OPENSSL_free(str);
3218 str = NULL;
William Lallemand4801c702019-10-04 17:36:55 +02003219 if (ret < 0) {
3220 memprintf(err, "%sunable to allocate SSL context.\n",
3221 err && *err ? *err : "");
Willy Tarreaub131c872019-10-16 16:42:19 +02003222 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemand4801c702019-10-04 17:36:55 +02003223 goto end;
3224 }
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003225 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003226 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003227
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003228 /* Do the above logic for each SAN */
yanbzhu08ce6ab2015-12-02 13:01:29 -05003229#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003230 names = X509_get_ext_d2i(certs_and_keys[n].cert, NID_subject_alt_name, NULL, NULL);
3231 if (names) {
3232 for (i = 0; i < sk_GENERAL_NAME_num(names); i++) {
3233 GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003234
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003235 if (name->type == GEN_DNS) {
3236 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
3237 /* Important line is here */
William Lallemand4801c702019-10-04 17:36:55 +02003238 ret = ssl_sock_populate_sni_keytypes_hplr(str, &sni_keytypes_map, n);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003239
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003240 OPENSSL_free(str);
3241 str = NULL;
William Lallemand4801c702019-10-04 17:36:55 +02003242 if (ret < 0) {
3243 memprintf(err, "%sunable to allocate SSL context.\n",
3244 err && *err ? *err : "");
Willy Tarreaub131c872019-10-16 16:42:19 +02003245 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemand4801c702019-10-04 17:36:55 +02003246 goto end;
3247 }
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003248 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003249 }
3250 }
3251 }
3252 }
3253#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
3254 }
3255
3256 /* If no files found, return error */
3257 if (eb_is_empty(&sni_keytypes_map)) {
3258 memprintf(err, "%sunable to load SSL certificate file '%s' file does not exist.\n",
3259 err && *err ? *err : "", path);
Willy Tarreaub131c872019-10-16 16:42:19 +02003260 errcode |= ERR_ALERT | ERR_FATAL;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003261 goto end;
3262 }
3263
3264 /* We now have a map of CN/SAN to keytypes that are loaded in
3265 * Iterate through the map to create the SSL_CTX's (if needed)
3266 * and add each CTX to the SNI tree
3267 *
3268 * Some math here:
Joseph Herlant017b3da2018-11-15 09:07:59 -08003269 * There are 2^n - 1 possible combinations, each unique
yanbzhu08ce6ab2015-12-02 13:01:29 -05003270 * combination is denoted by the key in the map. Each key
3271 * has a value between 1 and 2^n - 1. Conveniently, the array
3272 * of SSL_CTX* is sized 2^n. So, we can simply use the i'th
3273 * entry in the array to correspond to the unique combo (key)
3274 * associated with i. This unique key combo (i) will be associated
3275 * with combos[i-1]
3276 */
3277
3278 node = ebmb_first(&sni_keytypes_map);
3279 while (node) {
3280 SSL_CTX *cur_ctx;
Bertrand Jacquin33423092016-11-13 16:37:13 +00003281 char cur_file[MAXPATHLEN+1];
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003282 const struct pkey_info kinfo = { .sig = TLSEXT_signature_anonymous, .bits = 0 };
yanbzhu08ce6ab2015-12-02 13:01:29 -05003283
3284 str = (char *)container_of(node, struct sni_keytype, name)->name.key;
3285 i = container_of(node, struct sni_keytype, name)->keytypes;
3286 cur_ctx = key_combos[i-1].ctx;
3287
3288 if (cur_ctx == NULL) {
3289 /* need to create SSL_CTX */
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003290 cur_ctx = SSL_CTX_new(SSLv23_server_method());
yanbzhu08ce6ab2015-12-02 13:01:29 -05003291 if (cur_ctx == NULL) {
3292 memprintf(err, "%sunable to allocate SSL context.\n",
3293 err && *err ? *err : "");
Willy Tarreaub131c872019-10-16 16:42:19 +02003294 errcode |= ERR_ALERT | ERR_FATAL;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003295 goto end;
3296 }
3297
yanbzhube2774d2015-12-10 15:07:30 -05003298 /* Load all required certs/keys/chains/OCSPs info into SSL_CTX */
yanbzhu08ce6ab2015-12-02 13:01:29 -05003299 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
3300 if (i & (1<<n)) {
3301 /* Key combo contains ckch[n] */
Bertrand Jacquin33423092016-11-13 16:37:13 +00003302 snprintf(cur_file, MAXPATHLEN+1, "%s.%s", path, SSL_SOCK_KEYTYPE_NAMES[n]);
Emeric Brun394701d2019-10-17 13:25:14 +02003303 errcode |= ssl_sock_put_ckch_into_ctx(cur_file, &certs_and_keys[n], cur_ctx, err);
3304 if (errcode & ERR_CODE) {
yanbzhu08ce6ab2015-12-02 13:01:29 -05003305 SSL_CTX_free(cur_ctx);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003306 goto end;
3307 }
yanbzhube2774d2015-12-10 15:07:30 -05003308
3309#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
3310 /* Load OCSP Info into context */
Bertrand Jacquin33423092016-11-13 16:37:13 +00003311 if (ssl_sock_load_ocsp(cur_ctx, cur_file) < 0) {
yanbzhube2774d2015-12-10 15:07:30 -05003312 if (err)
3313 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 +00003314 *err ? *err : "", cur_file);
yanbzhube2774d2015-12-10 15:07:30 -05003315 SSL_CTX_free(cur_ctx);
Willy Tarreaub131c872019-10-16 16:42:19 +02003316 errcode |= ERR_ALERT | ERR_FATAL;
yanbzhube2774d2015-12-10 15:07:30 -05003317 goto end;
3318 }
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02003319#elif (defined OPENSSL_IS_BORINGSSL)
3320 ssl_sock_set_ocsp_response_from_file(cur_ctx, cur_file);
yanbzhube2774d2015-12-10 15:07:30 -05003321#endif
yanbzhu08ce6ab2015-12-02 13:01:29 -05003322 }
3323 }
3324
3325 /* Load DH params into the ctx to support DHE keys */
3326#ifndef OPENSSL_NO_DH
3327 if (ssl_dh_ptr_index >= 0)
3328 SSL_CTX_set_ex_data(cur_ctx, ssl_dh_ptr_index, NULL);
3329
Emeric Bruncfc1afe2019-10-17 13:27:40 +02003330 errcode |= ssl_sock_load_dh_params(cur_ctx, NULL, err);
3331 if (errcode & ERR_CODE) {
yanbzhu08ce6ab2015-12-02 13:01:29 -05003332 if (err)
3333 memprintf(err, "%sunable to load DH parameters from file '%s'.\n",
3334 *err ? *err : "", path);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003335 goto end;
3336 }
3337#endif
3338
3339 /* Update key_combos */
3340 key_combos[i-1].ctx = cur_ctx;
3341 }
3342
3343 /* Update SNI Tree */
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003344 key_combos[i-1].order = ssl_sock_add_cert_sni(cur_ctx, bind_conf, ssl_conf,
William Lallemand24e292c2019-10-03 23:46:33 +02003345 kinfo, str, key_combos[i-1].order);
3346 if (key_combos[i-1].order < 0) {
3347 memprintf(err, "%sunable to create a sni context.\n", err && *err ? *err : "");
Willy Tarreaub131c872019-10-16 16:42:19 +02003348 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemand24e292c2019-10-03 23:46:33 +02003349 goto end;
3350 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003351 node = ebmb_next(node);
3352 }
3353
3354
3355 /* Mark a default context if none exists, using the ctx that has the most shared keys */
3356 if (!bind_conf->default_ctx) {
3357 for (i = SSL_SOCK_POSSIBLE_KT_COMBOS - 1; i >= 0; i--) {
3358 if (key_combos[i].ctx) {
3359 bind_conf->default_ctx = key_combos[i].ctx;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003360 bind_conf->default_ssl_conf = ssl_conf;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003361 break;
3362 }
3363 }
3364 }
3365
3366end:
3367
3368 if (names)
3369 sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
3370
3371 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++)
3372 ssl_sock_free_cert_key_and_chain_contents(&certs_and_keys[n]);
3373
3374 node = ebmb_first(&sni_keytypes_map);
3375 while (node) {
3376 next = ebmb_next(node);
3377 ebmb_delete(node);
William Lallemande92c0302019-10-04 17:24:39 +02003378 free(ebmb_entry(node, struct sni_keytype, name));
yanbzhu08ce6ab2015-12-02 13:01:29 -05003379 node = next;
3380 }
3381
Willy Tarreaub131c872019-10-16 16:42:19 +02003382 return errcode;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003383}
3384#else
3385/* This is a dummy, that just logs an error and returns error */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003386static int ssl_sock_load_multi_cert(const char *path, struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
3387 char **sni_filter, int fcount, char **err)
yanbzhu08ce6ab2015-12-02 13:01:29 -05003388{
3389 memprintf(err, "%sunable to stat SSL certificate from file '%s' : %s.\n",
3390 err && *err ? *err : "", path, strerror(errno));
3391 return 1;
3392}
3393
Willy Tarreau9a1ab082019-05-09 13:26:41 +02003394#endif /* #if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL: Support for loading multiple certs into a single SSL_CTX */
yanbzhu488a4d22015-12-01 15:16:07 -05003395
Emeric Brunfc0421f2012-09-07 17:30:07 +02003396/* Loads a certificate key and CA chain from a file. Returns 0 on error, -1 if
3397 * an early error happens and the caller must call SSL_CTX_free() by itelf.
3398 */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003399static int ssl_sock_load_cert_chain_file(SSL_CTX *ctx, const char *file, struct bind_conf *s,
3400 struct ssl_bind_conf *ssl_conf, char **sni_filter, int fcount)
Emeric Brunfc0421f2012-09-07 17:30:07 +02003401{
3402 BIO *in;
3403 X509 *x = NULL, *ca;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02003404 int i, err;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003405 int ret = -1;
3406 int order = 0;
3407 X509_NAME *xname;
3408 char *str;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003409 pem_password_cb *passwd_cb;
3410 void *passwd_cb_userdata;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003411 EVP_PKEY *pkey;
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003412 struct pkey_info kinfo = { .sig = TLSEXT_signature_anonymous, .bits = 0 };
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003413
Emeric Brunfc0421f2012-09-07 17:30:07 +02003414#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
3415 STACK_OF(GENERAL_NAME) *names;
3416#endif
3417
3418 in = BIO_new(BIO_s_file());
3419 if (in == NULL)
3420 goto end;
3421
3422 if (BIO_read_filename(in, file) <= 0)
3423 goto end;
3424
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003425
3426 passwd_cb = SSL_CTX_get_default_passwd_cb(ctx);
3427 passwd_cb_userdata = SSL_CTX_get_default_passwd_cb_userdata(ctx);
3428
3429 x = PEM_read_bio_X509_AUX(in, NULL, passwd_cb, passwd_cb_userdata);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003430 if (x == NULL)
3431 goto end;
3432
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003433 pkey = X509_get_pubkey(x);
3434 if (pkey) {
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003435 kinfo.bits = EVP_PKEY_bits(pkey);
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003436 switch(EVP_PKEY_base_id(pkey)) {
3437 case EVP_PKEY_RSA:
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003438 kinfo.sig = TLSEXT_signature_rsa;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003439 break;
3440 case EVP_PKEY_EC:
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003441 kinfo.sig = TLSEXT_signature_ecdsa;
3442 break;
3443 case EVP_PKEY_DSA:
3444 kinfo.sig = TLSEXT_signature_dsa;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003445 break;
3446 }
3447 EVP_PKEY_free(pkey);
3448 }
3449
Emeric Brun50bcecc2013-04-22 13:05:23 +02003450 if (fcount) {
William Lallemand24e292c2019-10-03 23:46:33 +02003451 while (fcount--) {
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003452 order = ssl_sock_add_cert_sni(ctx, s, ssl_conf, kinfo, sni_filter[fcount], order);
William Lallemand24e292c2019-10-03 23:46:33 +02003453 if (order < 0)
3454 goto end;
3455 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003456 }
3457 else {
Emeric Brunfc0421f2012-09-07 17:30:07 +02003458#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003459 names = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL);
3460 if (names) {
3461 for (i = 0; i < sk_GENERAL_NAME_num(names); i++) {
3462 GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i);
3463 if (name->type == GEN_DNS) {
3464 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003465 order = ssl_sock_add_cert_sni(ctx, s, ssl_conf, kinfo, str, order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003466 OPENSSL_free(str);
William Lallemand24e292c2019-10-03 23:46:33 +02003467 if (order < 0)
3468 goto end;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003469 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003470 }
3471 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003472 sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003473 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003474#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003475 xname = X509_get_subject_name(x);
3476 i = -1;
3477 while ((i = X509_NAME_get_index_by_NID(xname, NID_commonName, i)) != -1) {
3478 X509_NAME_ENTRY *entry = X509_NAME_get_entry(xname, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003479 ASN1_STRING *value;
3480
3481 value = X509_NAME_ENTRY_get_data(entry);
3482 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003483 order = ssl_sock_add_cert_sni(ctx, s, ssl_conf, kinfo, str, order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003484 OPENSSL_free(str);
William Lallemand24e292c2019-10-03 23:46:33 +02003485 if (order < 0)
3486 goto end;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003487 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003488 }
3489 }
3490
3491 ret = 0; /* the caller must not free the SSL_CTX argument anymore */
3492 if (!SSL_CTX_use_certificate(ctx, x))
3493 goto end;
3494
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003495#ifdef SSL_CTX_clear_extra_chain_certs
3496 SSL_CTX_clear_extra_chain_certs(ctx);
3497#else
Emeric Brunfc0421f2012-09-07 17:30:07 +02003498 if (ctx->extra_certs != NULL) {
3499 sk_X509_pop_free(ctx->extra_certs, X509_free);
3500 ctx->extra_certs = NULL;
3501 }
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003502#endif
Emeric Brunfc0421f2012-09-07 17:30:07 +02003503
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003504 while ((ca = PEM_read_bio_X509(in, NULL, passwd_cb, passwd_cb_userdata))) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02003505 if (!SSL_CTX_add_extra_chain_cert(ctx, ca)) {
3506 X509_free(ca);
3507 goto end;
3508 }
3509 }
3510
3511 err = ERR_get_error();
3512 if (!err || (ERR_GET_LIB(err) == ERR_LIB_PEM && ERR_GET_REASON(err) == PEM_R_NO_START_LINE)) {
3513 /* we successfully reached the last cert in the file */
3514 ret = 1;
3515 }
3516 ERR_clear_error();
3517
3518end:
3519 if (x)
3520 X509_free(x);
3521
3522 if (in)
3523 BIO_free(in);
3524
3525 return ret;
3526}
3527
Willy Tarreaub131c872019-10-16 16:42:19 +02003528/* Returns a set of ERR_* flags possibly with an error in <err>. */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003529static int ssl_sock_load_cert_file(const char *path, struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
3530 char **sni_filter, int fcount, char **err)
Emeric Brunfc0421f2012-09-07 17:30:07 +02003531{
Emeric Bruncfc1afe2019-10-17 13:27:40 +02003532 int errcode = 0;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003533 int ret;
3534 SSL_CTX *ctx;
3535
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003536 ctx = SSL_CTX_new(SSLv23_server_method());
Emeric Brunfc0421f2012-09-07 17:30:07 +02003537 if (!ctx) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02003538 memprintf(err, "%sunable to allocate SSL context for cert '%s'.\n",
3539 err && *err ? *err : "", path);
Willy Tarreaub131c872019-10-16 16:42:19 +02003540 return ERR_ALERT | ERR_FATAL;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003541 }
3542
3543 if (SSL_CTX_use_PrivateKey_file(ctx, path, SSL_FILETYPE_PEM) <= 0) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02003544 memprintf(err, "%sunable to load SSL private key from PEM file '%s'.\n",
3545 err && *err ? *err : "", path);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003546 SSL_CTX_free(ctx);
Willy Tarreaub131c872019-10-16 16:42:19 +02003547 return ERR_ALERT | ERR_FATAL;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003548 }
3549
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003550 ret = ssl_sock_load_cert_chain_file(ctx, path, bind_conf, ssl_conf, sni_filter, fcount);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003551 if (ret <= 0) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02003552 memprintf(err, "%sunable to load SSL certificate from PEM file '%s'.\n",
3553 err && *err ? *err : "", path);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003554 if (ret < 0) /* serious error, must do that ourselves */
3555 SSL_CTX_free(ctx);
Willy Tarreaub131c872019-10-16 16:42:19 +02003556 return ERR_ALERT | ERR_FATAL;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003557 }
Emeric Brun61694ab2012-10-26 13:35:33 +02003558
3559 if (SSL_CTX_check_private_key(ctx) <= 0) {
3560 memprintf(err, "%sinconsistencies between private key and certificate loaded from PEM file '%s'.\n",
3561 err && *err ? *err : "", path);
Willy Tarreaub131c872019-10-16 16:42:19 +02003562 return ERR_ALERT | ERR_FATAL;
Emeric Brun61694ab2012-10-26 13:35:33 +02003563 }
3564
Emeric Brunfc0421f2012-09-07 17:30:07 +02003565 /* we must not free the SSL_CTX anymore below, since it's already in
3566 * the tree, so it will be discovered and cleaned in time.
3567 */
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02003568#ifndef OPENSSL_NO_DH
Remi Gacogne4f902b82015-05-28 16:23:00 +02003569 /* store a NULL pointer to indicate we have not yet loaded
3570 a custom DH param file */
3571 if (ssl_dh_ptr_index >= 0) {
3572 SSL_CTX_set_ex_data(ctx, ssl_dh_ptr_index, NULL);
3573 }
3574
Emeric Bruncfc1afe2019-10-17 13:27:40 +02003575 errcode |= ssl_sock_load_dh_params(ctx, path, err);
3576 if (errcode & ERR_CODE) {
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02003577 if (err)
3578 memprintf(err, "%sunable to load DH parameters from file '%s'.\n",
3579 *err ? *err : "", path);
Emeric Bruncfc1afe2019-10-17 13:27:40 +02003580 return errcode;
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02003581 }
3582#endif
3583
Lukas Tribuse4e30f72014-12-09 16:32:51 +01003584#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
Emeric Brun4147b2e2014-06-16 18:36:30 +02003585 ret = ssl_sock_load_ocsp(ctx, path);
3586 if (ret < 0) {
3587 if (err)
3588 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",
3589 *err ? *err : "", path);
Willy Tarreaub131c872019-10-16 16:42:19 +02003590 return ERR_ALERT | ERR_FATAL;
Emeric Brun4147b2e2014-06-16 18:36:30 +02003591 }
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02003592#elif (defined OPENSSL_IS_BORINGSSL)
3593 ssl_sock_set_ocsp_response_from_file(ctx, path);
Emeric Brun4147b2e2014-06-16 18:36:30 +02003594#endif
3595
Willy Tarreau5db847a2019-05-09 14:13:35 +02003596#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01003597 if (sctl_ex_index >= 0) {
3598 ret = ssl_sock_load_sctl(ctx, path);
3599 if (ret < 0) {
3600 if (err)
3601 memprintf(err, "%s '%s.sctl' is present but cannot be read or parsed'.\n",
3602 *err ? *err : "", path);
Willy Tarreaub131c872019-10-16 16:42:19 +02003603 return ERR_ALERT | ERR_FATAL;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01003604 }
3605 }
3606#endif
3607
Emeric Brunfc0421f2012-09-07 17:30:07 +02003608#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
Willy Tarreau2a65ff02012-09-13 17:54:29 +02003609 if (bind_conf->default_ctx) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02003610 memprintf(err, "%sthis version of openssl cannot load multiple SSL certificates.\n",
3611 err && *err ? *err : "");
Willy Tarreaub131c872019-10-16 16:42:19 +02003612 return ERR_ALERT | ERR_FATAL;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003613 }
3614#endif
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003615 if (!bind_conf->default_ctx) {
Willy Tarreau2a65ff02012-09-13 17:54:29 +02003616 bind_conf->default_ctx = ctx;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003617 bind_conf->default_ssl_conf = ssl_conf;
3618 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003619
Emeric Bruncfc1afe2019-10-17 13:27:40 +02003620 return errcode;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003621}
3622
Willy Tarreaub131c872019-10-16 16:42:19 +02003623
3624/* Returns a set of ERR_* flags possibly with an error in <err>. */
Willy Tarreau03209342016-12-22 17:08:28 +01003625int ssl_sock_load_cert(char *path, struct bind_conf *bind_conf, char **err)
Emeric Brunfc0421f2012-09-07 17:30:07 +02003626{
Cyril Bonté3180f7b2015-01-25 00:16:08 +01003627 struct dirent **de_list;
3628 int i, n;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003629 DIR *dir;
3630 struct stat buf;
Willy Tarreauee2663b2012-12-06 11:36:59 +01003631 char *end;
3632 char fp[MAXPATHLEN+1];
Emeric Brunfc0421f2012-09-07 17:30:07 +02003633 int cfgerr = 0;
Willy Tarreau9a1ab082019-05-09 13:26:41 +02003634#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
yanbzhu63ea8462015-12-09 13:35:14 -05003635 int is_bundle;
3636 int j;
3637#endif
Emeric Brunfc0421f2012-09-07 17:30:07 +02003638
yanbzhu08ce6ab2015-12-02 13:01:29 -05003639 if (stat(path, &buf) == 0) {
3640 dir = opendir(path);
3641 if (!dir)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003642 return ssl_sock_load_cert_file(path, bind_conf, NULL, NULL, 0, err);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003643
yanbzhu08ce6ab2015-12-02 13:01:29 -05003644 /* strip trailing slashes, including first one */
3645 for (end = path + strlen(path) - 1; end >= path && *end == '/'; end--)
3646 *end = 0;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003647
yanbzhu08ce6ab2015-12-02 13:01:29 -05003648 n = scandir(path, &de_list, 0, alphasort);
3649 if (n < 0) {
3650 memprintf(err, "%sunable to scan directory '%s' : %s.\n",
3651 err && *err ? *err : "", path, strerror(errno));
Willy Tarreaub131c872019-10-16 16:42:19 +02003652 cfgerr |= ERR_ALERT | ERR_FATAL;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003653 }
3654 else {
3655 for (i = 0; i < n; i++) {
3656 struct dirent *de = de_list[i];
Emeric Brun2aab7222014-06-18 18:15:09 +02003657
yanbzhu08ce6ab2015-12-02 13:01:29 -05003658 end = strrchr(de->d_name, '.');
3659 if (end && (!strcmp(end, ".issuer") || !strcmp(end, ".ocsp") || !strcmp(end, ".sctl")))
3660 goto ignore_entry;
Cyril Bonté3180f7b2015-01-25 00:16:08 +01003661
yanbzhu08ce6ab2015-12-02 13:01:29 -05003662 snprintf(fp, sizeof(fp), "%s/%s", path, de->d_name);
3663 if (stat(fp, &buf) != 0) {
3664 memprintf(err, "%sunable to stat SSL certificate from file '%s' : %s.\n",
3665 err && *err ? *err : "", fp, strerror(errno));
Willy Tarreaub131c872019-10-16 16:42:19 +02003666 cfgerr |= ERR_ALERT | ERR_FATAL;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003667 goto ignore_entry;
3668 }
3669 if (!S_ISREG(buf.st_mode))
3670 goto ignore_entry;
yanbzhu63ea8462015-12-09 13:35:14 -05003671
Willy Tarreau9a1ab082019-05-09 13:26:41 +02003672#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
yanbzhu63ea8462015-12-09 13:35:14 -05003673 is_bundle = 0;
3674 /* Check if current entry in directory is part of a multi-cert bundle */
3675
3676 if (end) {
3677 for (j = 0; j < SSL_SOCK_NUM_KEYTYPES; j++) {
3678 if (!strcmp(end + 1, SSL_SOCK_KEYTYPE_NAMES[j])) {
3679 is_bundle = 1;
3680 break;
3681 }
3682 }
3683
3684 if (is_bundle) {
yanbzhu63ea8462015-12-09 13:35:14 -05003685 int dp_len;
3686
3687 dp_len = end - de->d_name;
yanbzhu63ea8462015-12-09 13:35:14 -05003688
3689 /* increment i and free de until we get to a non-bundle cert
3690 * Note here that we look at de_list[i + 1] before freeing de
Willy Tarreau5b8a8652019-10-29 10:48:50 +01003691 * this is important since ignore_entry will free de. This also
3692 * guarantees that de->d_name continues to hold the same prefix.
yanbzhu63ea8462015-12-09 13:35:14 -05003693 */
Willy Tarreau5b8a8652019-10-29 10:48:50 +01003694 while (i + 1 < n && !strncmp(de_list[i + 1]->d_name, de->d_name, dp_len)) {
yanbzhu63ea8462015-12-09 13:35:14 -05003695 free(de);
3696 i++;
3697 de = de_list[i];
3698 }
3699
Willy Tarreau5b8a8652019-10-29 10:48:50 +01003700 snprintf(fp, sizeof(fp), "%s/%.*s", path, dp_len, de->d_name);
Willy Tarreaub131c872019-10-16 16:42:19 +02003701 cfgerr |= ssl_sock_load_multi_cert(fp, bind_conf, NULL, NULL, 0, err);
yanbzhu63ea8462015-12-09 13:35:14 -05003702 /* Successfully processed the bundle */
3703 goto ignore_entry;
3704 }
3705 }
3706
3707#endif
Willy Tarreaub131c872019-10-16 16:42:19 +02003708 cfgerr |= ssl_sock_load_cert_file(fp, bind_conf, NULL, NULL, 0, err);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003709ignore_entry:
3710 free(de);
Cyril Bonté3180f7b2015-01-25 00:16:08 +01003711 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003712 free(de_list);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003713 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003714 closedir(dir);
3715 return cfgerr;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003716 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003717
Willy Tarreaub131c872019-10-16 16:42:19 +02003718 cfgerr |= ssl_sock_load_multi_cert(path, bind_conf, NULL, NULL, 0, err);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003719
Emeric Brunfc0421f2012-09-07 17:30:07 +02003720 return cfgerr;
3721}
3722
Thierry Fournier383085f2013-01-24 14:15:43 +01003723/* Make sure openssl opens /dev/urandom before the chroot. The work is only
3724 * done once. Zero is returned if the operation fails. No error is returned
3725 * if the random is said as not implemented, because we expect that openssl
3726 * will use another method once needed.
3727 */
3728static int ssl_initialize_random()
3729{
3730 unsigned char random;
3731 static int random_initialized = 0;
3732
3733 if (!random_initialized && RAND_bytes(&random, 1) != 0)
3734 random_initialized = 1;
3735
3736 return random_initialized;
3737}
3738
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003739/* release ssl bind conf */
3740void ssl_sock_free_ssl_conf(struct ssl_bind_conf *conf)
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003741{
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003742 if (conf) {
Bernard Spil13c53f82018-02-15 13:34:58 +01003743#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003744 free(conf->npn_str);
3745 conf->npn_str = NULL;
3746#endif
3747#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
3748 free(conf->alpn_str);
3749 conf->alpn_str = NULL;
3750#endif
3751 free(conf->ca_file);
3752 conf->ca_file = NULL;
3753 free(conf->crl_file);
3754 conf->crl_file = NULL;
3755 free(conf->ciphers);
3756 conf->ciphers = NULL;
Emmanuel Hocdet839af572019-05-14 16:27:35 +02003757#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02003758 free(conf->ciphersuites);
3759 conf->ciphersuites = NULL;
3760#endif
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01003761 free(conf->curves);
3762 conf->curves = NULL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003763 free(conf->ecdhe);
3764 conf->ecdhe = NULL;
3765 }
3766}
3767
Willy Tarreaub131c872019-10-16 16:42:19 +02003768/* Returns a set of ERR_* flags possibly with an error in <err>. */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003769int ssl_sock_load_cert_list_file(char *file, struct bind_conf *bind_conf, struct proxy *curproxy, char **err)
3770{
3771 char thisline[CRT_LINESIZE];
3772 char path[MAXPATHLEN+1];
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003773 FILE *f;
yanbzhu1b04e5b2015-12-02 13:54:14 -05003774 struct stat buf;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003775 int linenum = 0;
3776 int cfgerr = 0;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003777
Willy Tarreauad1731d2013-04-02 17:35:58 +02003778 if ((f = fopen(file, "r")) == NULL) {
3779 memprintf(err, "cannot open file '%s' : %s", file, strerror(errno));
Willy Tarreaub131c872019-10-16 16:42:19 +02003780 return ERR_ALERT | ERR_FATAL;
Willy Tarreauad1731d2013-04-02 17:35:58 +02003781 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003782
3783 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003784 int arg, newarg, cur_arg, i, ssl_b = 0, ssl_e = 0;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003785 char *end;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003786 char *args[MAX_CRT_ARGS + 1];
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003787 char *line = thisline;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003788 char *crt_path;
3789 struct ssl_bind_conf *ssl_conf = NULL;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003790
3791 linenum++;
3792 end = line + strlen(line);
3793 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
3794 /* Check if we reached the limit and the last char is not \n.
3795 * Watch out for the last line without the terminating '\n'!
3796 */
Willy Tarreauad1731d2013-04-02 17:35:58 +02003797 memprintf(err, "line %d too long in file '%s', limit is %d characters",
3798 linenum, file, (int)sizeof(thisline)-1);
Willy Tarreaub131c872019-10-16 16:42:19 +02003799 cfgerr |= ERR_ALERT | ERR_FATAL;
Willy Tarreauad1731d2013-04-02 17:35:58 +02003800 break;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003801 }
3802
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003803 arg = 0;
Emeric Brun50bcecc2013-04-22 13:05:23 +02003804 newarg = 1;
3805 while (*line) {
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003806 if (*line == '#' || *line == '\n' || *line == '\r') {
3807 /* end of string, end of loop */
3808 *line = 0;
3809 break;
Willy Tarreau26e4ab42020-02-25 07:51:59 +01003810 } else if (isspace((unsigned char)*line)) {
Emeric Brun50bcecc2013-04-22 13:05:23 +02003811 newarg = 1;
3812 *line = 0;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003813 } else if (*line == '[') {
3814 if (ssl_b) {
3815 memprintf(err, "too many '[' on line %d in file '%s'.", linenum, file);
Willy Tarreaub131c872019-10-16 16:42:19 +02003816 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003817 break;
3818 }
3819 if (!arg) {
3820 memprintf(err, "file must start with a cert on line %d in file '%s'", linenum, file);
Willy Tarreaub131c872019-10-16 16:42:19 +02003821 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003822 break;
3823 }
3824 ssl_b = arg;
3825 newarg = 1;
3826 *line = 0;
3827 } else if (*line == ']') {
3828 if (ssl_e) {
3829 memprintf(err, "too many ']' on line %d in file '%s'.", linenum, file);
Willy Tarreaub131c872019-10-16 16:42:19 +02003830 cfgerr |= ERR_ALERT | ERR_FATAL;
Emeric Brun50bcecc2013-04-22 13:05:23 +02003831 break;
3832 }
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003833 if (!ssl_b) {
3834 memprintf(err, "missing '[' in line %d in file '%s'.", linenum, file);
Willy Tarreaub131c872019-10-16 16:42:19 +02003835 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003836 break;
3837 }
3838 ssl_e = arg;
3839 newarg = 1;
3840 *line = 0;
3841 } else if (newarg) {
3842 if (arg == MAX_CRT_ARGS) {
3843 memprintf(err, "too many args on line %d in file '%s'.", linenum, file);
Willy Tarreaub131c872019-10-16 16:42:19 +02003844 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003845 break;
3846 }
Emeric Brun50bcecc2013-04-22 13:05:23 +02003847 newarg = 0;
3848 args[arg++] = line;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003849 }
Emeric Brun50bcecc2013-04-22 13:05:23 +02003850 line++;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003851 }
Willy Tarreaub131c872019-10-16 16:42:19 +02003852 if (cfgerr & ERR_CODE)
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02003853 break;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003854 args[arg++] = line;
Willy Tarreauad1731d2013-04-02 17:35:58 +02003855
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003856 /* empty line */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003857 if (!*args[0])
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003858 continue;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003859
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003860 crt_path = args[0];
3861 if (*crt_path != '/' && global_ssl.crt_base) {
3862 if ((strlen(global_ssl.crt_base) + 1 + strlen(crt_path)) > MAXPATHLEN) {
3863 memprintf(err, "'%s' : path too long on line %d in file '%s'",
3864 crt_path, linenum, file);
Willy Tarreaub131c872019-10-16 16:42:19 +02003865 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003866 break;
3867 }
3868 snprintf(path, sizeof(path), "%s/%s", global_ssl.crt_base, crt_path);
3869 crt_path = path;
3870 }
3871
3872 ssl_conf = calloc(1, sizeof *ssl_conf);
3873 cur_arg = ssl_b ? ssl_b : 1;
3874 while (cur_arg < ssl_e) {
3875 newarg = 0;
3876 for (i = 0; ssl_bind_kws[i].kw != NULL; i++) {
3877 if (strcmp(ssl_bind_kws[i].kw, args[cur_arg]) == 0) {
3878 newarg = 1;
Willy Tarreaub131c872019-10-16 16:42:19 +02003879 cfgerr |= ssl_bind_kws[i].parse(args, cur_arg, curproxy, ssl_conf, err);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003880 if (cur_arg + 1 + ssl_bind_kws[i].skip > ssl_e) {
3881 memprintf(err, "ssl args out of '[]' for %s on line %d in file '%s'",
3882 args[cur_arg], linenum, file);
Willy Tarreaub131c872019-10-16 16:42:19 +02003883 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003884 }
3885 cur_arg += 1 + ssl_bind_kws[i].skip;
3886 break;
3887 }
3888 }
3889 if (!cfgerr && !newarg) {
3890 memprintf(err, "unknown ssl keyword %s on line %d in file '%s'.",
3891 args[cur_arg], linenum, file);
Willy Tarreaub131c872019-10-16 16:42:19 +02003892 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003893 break;
3894 }
3895 }
Willy Tarreaub131c872019-10-16 16:42:19 +02003896
3897 if (cfgerr & ERR_CODE) {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003898 ssl_sock_free_ssl_conf(ssl_conf);
3899 free(ssl_conf);
3900 ssl_conf = NULL;
3901 break;
3902 }
3903
3904 if (stat(crt_path, &buf) == 0) {
Willy Tarreaub131c872019-10-16 16:42:19 +02003905 cfgerr |= ssl_sock_load_cert_file(crt_path, bind_conf, ssl_conf,
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003906 &args[cur_arg], arg - cur_arg - 1, err);
Willy Tarreaub131c872019-10-16 16:42:19 +02003907 } else {
3908 cfgerr |= ssl_sock_load_multi_cert(crt_path, bind_conf, ssl_conf,
3909 &args[cur_arg], arg - cur_arg - 1, err);
yanbzhu1b04e5b2015-12-02 13:54:14 -05003910 }
3911
Willy Tarreaub131c872019-10-16 16:42:19 +02003912 if (cfgerr & ERR_CODE) {
Willy Tarreauad1731d2013-04-02 17:35:58 +02003913 memprintf(err, "error processing line %d in file '%s' : %s", linenum, file, *err);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003914 break;
Willy Tarreauad1731d2013-04-02 17:35:58 +02003915 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003916 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003917 fclose(f);
3918 return cfgerr;
3919}
3920
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003921/* Create an initial CTX used to start the SSL connection before switchctx */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003922static int
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003923ssl_sock_initial_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02003924{
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01003925 SSL_CTX *ctx = NULL;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003926 long options =
Emeric Brunfc0421f2012-09-07 17:30:07 +02003927 SSL_OP_ALL | /* all known workarounds for bugs */
3928 SSL_OP_NO_SSLv2 |
3929 SSL_OP_NO_COMPRESSION |
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02003930 SSL_OP_SINGLE_DH_USE |
Emeric Brun2b58d042012-09-20 17:10:03 +02003931 SSL_OP_SINGLE_ECDH_USE |
Emeric Brun3c4bc6e2012-10-04 18:44:19 +02003932 SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION |
Lukas Tribus926594f2018-05-18 17:55:57 +02003933 SSL_OP_PRIORITIZE_CHACHA |
Emeric Brun3c4bc6e2012-10-04 18:44:19 +02003934 SSL_OP_CIPHER_SERVER_PREFERENCE;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003935 long mode =
Emeric Brunfc0421f2012-09-07 17:30:07 +02003936 SSL_MODE_ENABLE_PARTIAL_WRITE |
3937 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
Willy Tarreau396a1862014-11-13 14:06:52 +01003938 SSL_MODE_RELEASE_BUFFERS |
3939 SSL_MODE_SMALL_BUFFERS;
Emmanuel Hocdet43664762017-08-09 18:26:20 +02003940 struct tls_version_filter *conf_ssl_methods = &bind_conf->ssl_conf.ssl_methods;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003941 int i, min, max, hole;
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003942 int flags = MC_SSL_O_ALL;
3943 int cfgerr = 0;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01003944
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003945 ctx = SSL_CTX_new(SSLv23_server_method());
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003946 bind_conf->initial_ctx = ctx;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003947
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003948 if (conf_ssl_methods->flags && (conf_ssl_methods->min || conf_ssl_methods->max))
Christopher Faulet767a84b2017-11-24 16:50:31 +01003949 ha_warning("Proxy '%s': no-sslv3/no-tlsv1x are ignored for bind '%s' at [%s:%d]. "
3950 "Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
3951 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003952 else
3953 flags = conf_ssl_methods->flags;
3954
Emmanuel Hocdetbd695fe2017-05-15 15:53:41 +02003955 min = conf_ssl_methods->min;
3956 max = conf_ssl_methods->max;
3957 /* start with TLSv10 to remove SSLv3 per default */
3958 if (!min && (!max || max >= CONF_TLSV10))
3959 min = CONF_TLSV10;
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02003960 /* Real min and max should be determinate with configuration and openssl's capabilities */
Emmanuel Hocdetbd695fe2017-05-15 15:53:41 +02003961 if (min)
3962 flags |= (methodVersions[min].flag - 1);
3963 if (max)
3964 flags |= ~((methodVersions[max].flag << 1) - 1);
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02003965 /* find min, max and holes */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003966 min = max = CONF_TLSV_NONE;
3967 hole = 0;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003968 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003969 /* version is in openssl && version not disable in configuration */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003970 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003971 if (min) {
3972 if (hole) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003973 ha_warning("Proxy '%s': SSL/TLS versions range not contiguous for bind '%s' at [%s:%d]. "
3974 "Hole find for %s. Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
3975 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line,
3976 methodVersions[hole].name);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003977 hole = 0;
3978 }
3979 max = i;
3980 }
3981 else {
3982 min = max = i;
3983 }
3984 }
3985 else {
3986 if (min)
3987 hole = i;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003988 }
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003989 if (!min) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003990 ha_alert("Proxy '%s': all SSL/TLS versions are disabled for bind '%s' at [%s:%d].\n",
3991 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003992 cfgerr += 1;
3993 }
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02003994 /* save real min/max in bind_conf */
3995 conf_ssl_methods->min = min;
3996 conf_ssl_methods->max = max;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003997
Willy Tarreau9a1ab082019-05-09 13:26:41 +02003998#if (HA_OPENSSL_VERSION_NUMBER < 0x1010000fL)
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003999 /* Keep force-xxx implementation as it is in older haproxy. It's a
Joseph Herlant017b3da2018-11-15 09:07:59 -08004000 precautionary measure to avoid any surprise with older openssl version. */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004001 if (min == max)
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004002 methodVersions[min].ctx_set_version(ctx, SET_SERVER);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004003 else
William Lallemand6dbb9a12020-06-11 17:34:00 +02004004 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++) {
4005 /* clear every version flags in case SSL_CTX_new()
4006 * returns an SSL_CTX with disabled versions */
4007 SSL_CTX_clear_options(ctx, methodVersions[i].option);
4008
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004009 if (flags & methodVersions[i].flag)
4010 options |= methodVersions[i].option;
William Lallemand6dbb9a12020-06-11 17:34:00 +02004011
4012 }
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004013#else /* openssl >= 1.1.0 */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004014 /* set the max_version is required to cap TLS version or activate new TLS (v1.3) */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004015 methodVersions[min].ctx_set_version(ctx, SET_MIN);
4016 methodVersions[max].ctx_set_version(ctx, SET_MAX);
Emeric Brunfa5c5c82017-04-28 16:19:51 +02004017#endif
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004018
4019 if (bind_conf->ssl_options & BC_SSL_O_NO_TLS_TICKETS)
4020 options |= SSL_OP_NO_TICKET;
4021 if (bind_conf->ssl_options & BC_SSL_O_PREF_CLIE_CIPH)
4022 options &= ~SSL_OP_CIPHER_SERVER_PREFERENCE;
Dirkjan Bussink526894f2019-01-21 09:35:03 -08004023
4024#ifdef SSL_OP_NO_RENEGOTIATION
4025 options |= SSL_OP_NO_RENEGOTIATION;
4026#endif
4027
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004028 SSL_CTX_set_options(ctx, options);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004029
Willy Tarreau5db847a2019-05-09 14:13:35 +02004030#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004031 if (global_ssl.async)
4032 mode |= SSL_MODE_ASYNC;
4033#endif
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004034 SSL_CTX_set_mode(ctx, mode);
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004035 if (global_ssl.life_time)
4036 SSL_CTX_set_timeout(ctx, global_ssl.life_time);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004037
4038#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
4039#ifdef OPENSSL_IS_BORINGSSL
4040 SSL_CTX_set_select_certificate_cb(ctx, ssl_sock_switchctx_cbk);
4041 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_err_cbk);
Willy Tarreau5db847a2019-05-09 14:13:35 +02004042#elif (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Olivier Houcharde82c1d42019-12-17 15:39:54 +01004043 if (bind_conf->ssl_conf.early_data)
Olivier Houchard51088ce2019-01-02 18:46:41 +01004044 SSL_CTX_set_options(ctx, SSL_OP_NO_ANTI_REPLAY);
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02004045 SSL_CTX_set_client_hello_cb(ctx, ssl_sock_switchctx_cbk, NULL);
4046 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_err_cbk);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004047#else
4048 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_cbk);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004049#endif
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02004050 SSL_CTX_set_tlsext_servername_arg(ctx, bind_conf);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004051#endif
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004052 return cfgerr;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004053}
4054
William Lallemand4f45bb92017-10-30 20:08:51 +01004055
4056static inline void sh_ssl_sess_free_blocks(struct shared_block *first, struct shared_block *block)
4057{
4058 if (first == block) {
4059 struct sh_ssl_sess_hdr *sh_ssl_sess = (struct sh_ssl_sess_hdr *)first->data;
4060 if (first->len > 0)
4061 sh_ssl_sess_tree_delete(sh_ssl_sess);
4062 }
4063}
4064
4065/* return first block from sh_ssl_sess */
4066static inline struct shared_block *sh_ssl_sess_first_block(struct sh_ssl_sess_hdr *sh_ssl_sess)
4067{
4068 return (struct shared_block *)((unsigned char *)sh_ssl_sess - ((struct shared_block *)NULL)->data);
4069
4070}
4071
4072/* store a session into the cache
4073 * s_id : session id padded with zero to SSL_MAX_SSL_SESSION_ID_LENGTH
4074 * data: asn1 encoded session
4075 * data_len: asn1 encoded session length
4076 * Returns 1 id session was stored (else 0)
4077 */
4078static int sh_ssl_sess_store(unsigned char *s_id, unsigned char *data, int data_len)
4079{
4080 struct shared_block *first;
4081 struct sh_ssl_sess_hdr *sh_ssl_sess, *oldsh_ssl_sess;
4082
Frédéric Lécaille0bec8072018-10-22 17:55:57 +02004083 first = shctx_row_reserve_hot(ssl_shctx, NULL, data_len + sizeof(struct sh_ssl_sess_hdr));
William Lallemand4f45bb92017-10-30 20:08:51 +01004084 if (!first) {
4085 /* Could not retrieve enough free blocks to store that session */
4086 return 0;
4087 }
4088
4089 /* STORE the key in the first elem */
4090 sh_ssl_sess = (struct sh_ssl_sess_hdr *)first->data;
4091 memcpy(sh_ssl_sess->key_data, s_id, SSL_MAX_SSL_SESSION_ID_LENGTH);
4092 first->len = sizeof(struct sh_ssl_sess_hdr);
4093
4094 /* it returns the already existing node
4095 or current node if none, never returns null */
4096 oldsh_ssl_sess = sh_ssl_sess_tree_insert(sh_ssl_sess);
4097 if (oldsh_ssl_sess != sh_ssl_sess) {
4098 /* NOTE: Row couldn't be in use because we lock read & write function */
4099 /* release the reserved row */
4100 shctx_row_dec_hot(ssl_shctx, first);
4101 /* replace the previous session already in the tree */
4102 sh_ssl_sess = oldsh_ssl_sess;
4103 /* ignore the previous session data, only use the header */
4104 first = sh_ssl_sess_first_block(sh_ssl_sess);
4105 shctx_row_inc_hot(ssl_shctx, first);
4106 first->len = sizeof(struct sh_ssl_sess_hdr);
4107 }
4108
Frédéric Lécaille0bec8072018-10-22 17:55:57 +02004109 if (shctx_row_data_append(ssl_shctx, first, NULL, data, data_len) < 0) {
William Lallemand99b90af2018-01-03 19:15:51 +01004110 shctx_row_dec_hot(ssl_shctx, first);
William Lallemand4f45bb92017-10-30 20:08:51 +01004111 return 0;
William Lallemand99b90af2018-01-03 19:15:51 +01004112 }
4113
4114 shctx_row_dec_hot(ssl_shctx, first);
William Lallemand4f45bb92017-10-30 20:08:51 +01004115
4116 return 1;
4117}
William Lallemanded0b5ad2017-10-30 19:36:36 +01004118
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004119/* SSL callback used when a new session is created while connecting to a server */
4120static int ssl_sess_new_srv_cb(SSL *ssl, SSL_SESSION *sess)
4121{
Thierry FOURNIER28962c92018-06-17 21:37:05 +02004122 struct connection *conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Olivier Houcharde6060c52017-11-16 17:42:52 +01004123 struct server *s;
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004124
Willy Tarreau07d94e42018-09-20 10:57:52 +02004125 s = __objt_server(conn->target);
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004126
Olivier Houcharde6060c52017-11-16 17:42:52 +01004127 if (!(s->ssl_ctx.options & SRV_SSL_O_NO_REUSE)) {
4128 int len;
4129 unsigned char *ptr;
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004130
Olivier Houcharde6060c52017-11-16 17:42:52 +01004131 len = i2d_SSL_SESSION(sess, NULL);
4132 if (s->ssl_ctx.reused_sess[tid].ptr && s->ssl_ctx.reused_sess[tid].allocated_size >= len) {
4133 ptr = s->ssl_ctx.reused_sess[tid].ptr;
4134 } else {
4135 free(s->ssl_ctx.reused_sess[tid].ptr);
4136 ptr = s->ssl_ctx.reused_sess[tid].ptr = malloc(len);
4137 s->ssl_ctx.reused_sess[tid].allocated_size = len;
4138 }
4139 if (s->ssl_ctx.reused_sess[tid].ptr) {
4140 s->ssl_ctx.reused_sess[tid].size = i2d_SSL_SESSION(sess,
4141 &ptr);
4142 }
4143 } else {
4144 free(s->ssl_ctx.reused_sess[tid].ptr);
4145 s->ssl_ctx.reused_sess[tid].ptr = NULL;
4146 }
4147
4148 return 0;
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004149}
4150
Olivier Houcharde6060c52017-11-16 17:42:52 +01004151
William Lallemanded0b5ad2017-10-30 19:36:36 +01004152/* SSL callback used on new session creation */
William Lallemand4f45bb92017-10-30 20:08:51 +01004153int sh_ssl_sess_new_cb(SSL *ssl, SSL_SESSION *sess)
William Lallemanded0b5ad2017-10-30 19:36:36 +01004154{
4155 unsigned char encsess[SHSESS_MAX_DATA_LEN]; /* encoded session */
4156 unsigned char encid[SSL_MAX_SSL_SESSION_ID_LENGTH]; /* encoded id */
4157 unsigned char *p;
4158 int data_len;
Emeric Brun7b34de32019-10-08 18:27:37 +02004159 unsigned int sid_length;
William Lallemanded0b5ad2017-10-30 19:36:36 +01004160 const unsigned char *sid_data;
William Lallemanded0b5ad2017-10-30 19:36:36 +01004161
4162 /* Session id is already stored in to key and session id is known
4163 * so we dont store it to keep size.
Emeric Brun7b34de32019-10-08 18:27:37 +02004164 * note: SSL_SESSION_set1_id is using
4165 * a memcpy so we need to use a different pointer
4166 * than sid_data or sid_ctx_data to avoid valgrind
4167 * complaining.
William Lallemanded0b5ad2017-10-30 19:36:36 +01004168 */
4169
4170 sid_data = SSL_SESSION_get_id(sess, &sid_length);
Emeric Brun7b34de32019-10-08 18:27:37 +02004171
4172 /* copy value in an other buffer */
4173 memcpy(encid, sid_data, sid_length);
4174
4175 /* pad with 0 */
4176 if (sid_length < SSL_MAX_SSL_SESSION_ID_LENGTH)
4177 memset(encid + sid_length, 0, SSL_MAX_SSL_SESSION_ID_LENGTH-sid_length);
4178
4179 /* force length to zero to avoid ASN1 encoding */
4180 SSL_SESSION_set1_id(sess, encid, 0);
4181
4182 /* force length to zero to avoid ASN1 encoding */
4183 SSL_SESSION_set1_id_context(sess, (const unsigned char *)SHCTX_APPNAME, 0);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004184
4185 /* check if buffer is large enough for the ASN1 encoded session */
4186 data_len = i2d_SSL_SESSION(sess, NULL);
4187 if (data_len > SHSESS_MAX_DATA_LEN)
4188 goto err;
4189
4190 p = encsess;
4191
4192 /* process ASN1 session encoding before the lock */
4193 i2d_SSL_SESSION(sess, &p);
4194
William Lallemanded0b5ad2017-10-30 19:36:36 +01004195
William Lallemanda3c77cf2017-10-30 23:44:40 +01004196 shctx_lock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004197 /* store to cache */
William Lallemand4f45bb92017-10-30 20:08:51 +01004198 sh_ssl_sess_store(encid, encsess, data_len);
William Lallemanda3c77cf2017-10-30 23:44:40 +01004199 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004200err:
4201 /* reset original length values */
Emeric Brun7b34de32019-10-08 18:27:37 +02004202 SSL_SESSION_set1_id(sess, encid, sid_length);
4203 SSL_SESSION_set1_id_context(sess, (const unsigned char *)SHCTX_APPNAME, strlen(SHCTX_APPNAME));
William Lallemanded0b5ad2017-10-30 19:36:36 +01004204
4205 return 0; /* do not increment session reference count */
4206}
4207
4208/* SSL callback used on lookup an existing session cause none found in internal cache */
William Lallemand4f45bb92017-10-30 20:08:51 +01004209SSL_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 +01004210{
William Lallemand4f45bb92017-10-30 20:08:51 +01004211 struct sh_ssl_sess_hdr *sh_ssl_sess;
William Lallemanded0b5ad2017-10-30 19:36:36 +01004212 unsigned char data[SHSESS_MAX_DATA_LEN], *p;
4213 unsigned char tmpkey[SSL_MAX_SSL_SESSION_ID_LENGTH];
William Lallemanded0b5ad2017-10-30 19:36:36 +01004214 SSL_SESSION *sess;
William Lallemand4f45bb92017-10-30 20:08:51 +01004215 struct shared_block *first;
William Lallemanded0b5ad2017-10-30 19:36:36 +01004216
4217 global.shctx_lookups++;
4218
4219 /* allow the session to be freed automatically by openssl */
4220 *do_copy = 0;
4221
4222 /* tree key is zeros padded sessionid */
4223 if (key_len < SSL_MAX_SSL_SESSION_ID_LENGTH) {
4224 memcpy(tmpkey, key, key_len);
4225 memset(tmpkey + key_len, 0, SSL_MAX_SSL_SESSION_ID_LENGTH - key_len);
4226 key = tmpkey;
4227 }
4228
4229 /* lock cache */
William Lallemanda3c77cf2017-10-30 23:44:40 +01004230 shctx_lock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004231
4232 /* lookup for session */
William Lallemand4f45bb92017-10-30 20:08:51 +01004233 sh_ssl_sess = sh_ssl_sess_tree_lookup(key);
4234 if (!sh_ssl_sess) {
William Lallemanded0b5ad2017-10-30 19:36:36 +01004235 /* no session found: unlock cache and exit */
William Lallemanda3c77cf2017-10-30 23:44:40 +01004236 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004237 global.shctx_misses++;
4238 return NULL;
4239 }
4240
William Lallemand4f45bb92017-10-30 20:08:51 +01004241 /* sh_ssl_sess (shared_block->data) is at the end of shared_block */
4242 first = sh_ssl_sess_first_block(sh_ssl_sess);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004243
William Lallemand4f45bb92017-10-30 20:08:51 +01004244 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 +01004245
William Lallemanda3c77cf2017-10-30 23:44:40 +01004246 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004247
4248 /* decode ASN1 session */
4249 p = data;
William Lallemand4f45bb92017-10-30 20:08:51 +01004250 sess = d2i_SSL_SESSION(NULL, (const unsigned char **)&p, first->len-sizeof(struct sh_ssl_sess_hdr));
William Lallemanded0b5ad2017-10-30 19:36:36 +01004251 /* Reset session id and session id contenxt */
4252 if (sess) {
4253 SSL_SESSION_set1_id(sess, key, key_len);
4254 SSL_SESSION_set1_id_context(sess, (const unsigned char *)SHCTX_APPNAME, strlen(SHCTX_APPNAME));
4255 }
4256
4257 return sess;
4258}
4259
William Lallemand4f45bb92017-10-30 20:08:51 +01004260
William Lallemanded0b5ad2017-10-30 19:36:36 +01004261/* SSL callback used to signal session is no more used in internal cache */
William Lallemand4f45bb92017-10-30 20:08:51 +01004262void sh_ssl_sess_remove_cb(SSL_CTX *ctx, SSL_SESSION *sess)
William Lallemanded0b5ad2017-10-30 19:36:36 +01004263{
William Lallemand4f45bb92017-10-30 20:08:51 +01004264 struct sh_ssl_sess_hdr *sh_ssl_sess;
William Lallemanded0b5ad2017-10-30 19:36:36 +01004265 unsigned char tmpkey[SSL_MAX_SSL_SESSION_ID_LENGTH];
4266 unsigned int sid_length;
4267 const unsigned char *sid_data;
4268 (void)ctx;
4269
4270 sid_data = SSL_SESSION_get_id(sess, &sid_length);
4271 /* tree key is zeros padded sessionid */
4272 if (sid_length < SSL_MAX_SSL_SESSION_ID_LENGTH) {
4273 memcpy(tmpkey, sid_data, sid_length);
4274 memset(tmpkey+sid_length, 0, SSL_MAX_SSL_SESSION_ID_LENGTH - sid_length);
4275 sid_data = tmpkey;
4276 }
4277
William Lallemanda3c77cf2017-10-30 23:44:40 +01004278 shctx_lock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004279
4280 /* lookup for session */
William Lallemand4f45bb92017-10-30 20:08:51 +01004281 sh_ssl_sess = sh_ssl_sess_tree_lookup(sid_data);
4282 if (sh_ssl_sess) {
William Lallemanded0b5ad2017-10-30 19:36:36 +01004283 /* free session */
William Lallemand4f45bb92017-10-30 20:08:51 +01004284 sh_ssl_sess_tree_delete(sh_ssl_sess);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004285 }
4286
4287 /* unlock cache */
William Lallemanda3c77cf2017-10-30 23:44:40 +01004288 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004289}
4290
4291/* Set session cache mode to server and disable openssl internal cache.
4292 * Set shared cache callbacks on an ssl context.
4293 * Shared context MUST be firstly initialized */
William Lallemand4f45bb92017-10-30 20:08:51 +01004294void ssl_set_shctx(SSL_CTX *ctx)
William Lallemanded0b5ad2017-10-30 19:36:36 +01004295{
4296 SSL_CTX_set_session_id_context(ctx, (const unsigned char *)SHCTX_APPNAME, strlen(SHCTX_APPNAME));
4297
4298 if (!ssl_shctx) {
4299 SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF);
4300 return;
4301 }
4302
4303 SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_SERVER |
4304 SSL_SESS_CACHE_NO_INTERNAL |
4305 SSL_SESS_CACHE_NO_AUTO_CLEAR);
4306
4307 /* Set callbacks */
William Lallemand4f45bb92017-10-30 20:08:51 +01004308 SSL_CTX_sess_set_new_cb(ctx, sh_ssl_sess_new_cb);
4309 SSL_CTX_sess_set_get_cb(ctx, sh_ssl_sess_get_cb);
4310 SSL_CTX_sess_set_remove_cb(ctx, sh_ssl_sess_remove_cb);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004311}
4312
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004313int ssl_sock_prepare_ctx(struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf, SSL_CTX *ctx)
4314{
4315 struct proxy *curproxy = bind_conf->frontend;
4316 int cfgerr = 0;
4317 int verify = SSL_VERIFY_NONE;
Willy Tarreau5d4cafb2018-01-04 18:55:19 +01004318 struct ssl_bind_conf __maybe_unused *ssl_conf_cur;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004319 const char *conf_ciphers;
Emmanuel Hocdet839af572019-05-14 16:27:35 +02004320#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02004321 const char *conf_ciphersuites;
4322#endif
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004323 const char *conf_curves = NULL;
Emeric Brunfc0421f2012-09-07 17:30:07 +02004324
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02004325 if (ssl_conf) {
4326 struct tls_version_filter *conf_ssl_methods = &ssl_conf->ssl_methods;
4327 int i, min, max;
4328 int flags = MC_SSL_O_ALL;
4329
4330 /* Real min and max should be determinate with configuration and openssl's capabilities */
Emmanuel Hocdet43664762017-08-09 18:26:20 +02004331 min = conf_ssl_methods->min ? conf_ssl_methods->min : bind_conf->ssl_conf.ssl_methods.min;
4332 max = conf_ssl_methods->max ? conf_ssl_methods->max : bind_conf->ssl_conf.ssl_methods.max;
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02004333 if (min)
4334 flags |= (methodVersions[min].flag - 1);
4335 if (max)
4336 flags |= ~((methodVersions[max].flag << 1) - 1);
4337 min = max = CONF_TLSV_NONE;
4338 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
4339 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
4340 if (min)
4341 max = i;
4342 else
4343 min = max = i;
4344 }
4345 /* save real min/max */
4346 conf_ssl_methods->min = min;
4347 conf_ssl_methods->max = max;
4348 if (!min) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004349 ha_alert("Proxy '%s': all SSL/TLS versions are disabled for bind '%s' at [%s:%d].\n",
4350 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02004351 cfgerr += 1;
4352 }
4353 }
4354
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004355 switch ((ssl_conf && ssl_conf->verify) ? ssl_conf->verify : bind_conf->ssl_conf.verify) {
Emeric Brun850efd52014-01-29 12:24:34 +01004356 case SSL_SOCK_VERIFY_NONE:
4357 verify = SSL_VERIFY_NONE;
4358 break;
4359 case SSL_SOCK_VERIFY_OPTIONAL:
4360 verify = SSL_VERIFY_PEER;
4361 break;
4362 case SSL_SOCK_VERIFY_REQUIRED:
4363 verify = SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
4364 break;
4365 }
4366 SSL_CTX_set_verify(ctx, verify, ssl_sock_bind_verifycbk);
4367 if (verify & SSL_VERIFY_PEER) {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004368 char *ca_file = (ssl_conf && ssl_conf->ca_file) ? ssl_conf->ca_file : bind_conf->ssl_conf.ca_file;
4369 char *crl_file = (ssl_conf && ssl_conf->crl_file) ? ssl_conf->crl_file : bind_conf->ssl_conf.crl_file;
4370 if (ca_file) {
Emeric Brund94b3fe2012-09-20 18:23:56 +02004371 /* load CAfile to verify */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004372 if (!SSL_CTX_load_verify_locations(ctx, ca_file, NULL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004373 ha_alert("Proxy '%s': unable to load CA file '%s' for bind '%s' at [%s:%d].\n",
4374 curproxy->id, ca_file, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brund94b3fe2012-09-20 18:23:56 +02004375 cfgerr++;
4376 }
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02004377 if (!((ssl_conf && ssl_conf->no_ca_names) || bind_conf->ssl_conf.no_ca_names)) {
4378 /* set CA names for client cert request, function returns void */
4379 SSL_CTX_set_client_CA_list(ctx, SSL_load_client_CA_file(ca_file));
4380 }
Emeric Brund94b3fe2012-09-20 18:23:56 +02004381 }
Emeric Brun850efd52014-01-29 12:24:34 +01004382 else {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004383 ha_alert("Proxy '%s': verify is enabled but no CA file specified for bind '%s' at [%s:%d].\n",
4384 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brun850efd52014-01-29 12:24:34 +01004385 cfgerr++;
4386 }
Emeric Brun051cdab2012-10-02 19:25:50 +02004387#ifdef X509_V_FLAG_CRL_CHECK
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004388 if (crl_file) {
Emeric Brund94b3fe2012-09-20 18:23:56 +02004389 X509_STORE *store = SSL_CTX_get_cert_store(ctx);
4390
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004391 if (!store || !X509_STORE_load_locations(store, crl_file, NULL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004392 ha_alert("Proxy '%s': unable to configure CRL file '%s' for bind '%s' at [%s:%d].\n",
4393 curproxy->id, crl_file, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brund94b3fe2012-09-20 18:23:56 +02004394 cfgerr++;
4395 }
Emeric Brun561e5742012-10-02 15:20:55 +02004396 else {
4397 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
4398 }
Emeric Brund94b3fe2012-09-20 18:23:56 +02004399 }
Emeric Brun051cdab2012-10-02 19:25:50 +02004400#endif
Emeric Brun644cde02012-12-14 11:21:13 +01004401 ERR_clear_error();
Emeric Brund94b3fe2012-09-20 18:23:56 +02004402 }
Nenad Merdanovic05552d42015-02-27 19:56:49 +01004403#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
Nenad Merdanovic146defa2015-05-09 08:46:00 +02004404 if(bind_conf->keys_ref) {
Nenad Merdanovic05552d42015-02-27 19:56:49 +01004405 if (!SSL_CTX_set_tlsext_ticket_key_cb(ctx, ssl_tlsext_ticket_key_cb)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004406 ha_alert("Proxy '%s': unable to set callback for TLS ticket validation for bind '%s' at [%s:%d].\n",
4407 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Nenad Merdanovic05552d42015-02-27 19:56:49 +01004408 cfgerr++;
4409 }
4410 }
4411#endif
4412
William Lallemand4f45bb92017-10-30 20:08:51 +01004413 ssl_set_shctx(ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004414 conf_ciphers = (ssl_conf && ssl_conf->ciphers) ? ssl_conf->ciphers : bind_conf->ssl_conf.ciphers;
4415 if (conf_ciphers &&
4416 !SSL_CTX_set_cipher_list(ctx, conf_ciphers)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004417 ha_alert("Proxy '%s': unable to set SSL cipher list to '%s' for bind '%s' at [%s:%d].\n",
4418 curproxy->id, conf_ciphers, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004419 cfgerr++;
4420 }
4421
Emmanuel Hocdet839af572019-05-14 16:27:35 +02004422#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02004423 conf_ciphersuites = (ssl_conf && ssl_conf->ciphersuites) ? ssl_conf->ciphersuites : bind_conf->ssl_conf.ciphersuites;
4424 if (conf_ciphersuites &&
4425 !SSL_CTX_set_ciphersuites(ctx, conf_ciphersuites)) {
4426 ha_alert("Proxy '%s': unable to set TLS 1.3 cipher suites to '%s' for bind '%s' at [%s:%d].\n",
4427 curproxy->id, conf_ciphersuites, bind_conf->arg, bind_conf->file, bind_conf->line);
4428 cfgerr++;
4429 }
4430#endif
4431
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01004432#ifndef OPENSSL_NO_DH
Remi Gacogne47783ef2015-05-29 15:53:22 +02004433 /* If tune.ssl.default-dh-param has not been set,
4434 neither has ssl-default-dh-file and no static DH
4435 params were in the certificate file. */
Willy Tarreauef934602016-12-22 23:12:01 +01004436 if (global_ssl.default_dh_param == 0 &&
Remi Gacogne47783ef2015-05-29 15:53:22 +02004437 global_dh == NULL &&
Remi Gacogne4f902b82015-05-28 16:23:00 +02004438 (ssl_dh_ptr_index == -1 ||
4439 SSL_CTX_get_ex_data(ctx, ssl_dh_ptr_index) == NULL)) {
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01004440 STACK_OF(SSL_CIPHER) * ciphers = NULL;
4441 const SSL_CIPHER * cipher = NULL;
4442 char cipher_description[128];
4443 /* The description of ciphers using an Ephemeral Diffie Hellman key exchange
4444 contains " Kx=DH " or " Kx=DH(". Beware of " Kx=DH/",
4445 which is not ephemeral DH. */
4446 const char dhe_description[] = " Kx=DH ";
4447 const char dhe_export_description[] = " Kx=DH(";
4448 int idx = 0;
4449 int dhe_found = 0;
4450 SSL *ssl = NULL;
Lukas Tribus90132722014-08-18 00:56:33 +02004451
Remi Gacogne23d5d372014-10-10 17:04:26 +02004452 ssl = SSL_new(ctx);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004453
Remi Gacogne23d5d372014-10-10 17:04:26 +02004454 if (ssl) {
4455 ciphers = SSL_get_ciphers(ssl);
4456
4457 if (ciphers) {
4458 for (idx = 0; idx < sk_SSL_CIPHER_num(ciphers); idx++) {
4459 cipher = sk_SSL_CIPHER_value(ciphers, idx);
4460 if (SSL_CIPHER_description(cipher, cipher_description, sizeof (cipher_description)) == cipher_description) {
4461 if (strstr(cipher_description, dhe_description) != NULL ||
4462 strstr(cipher_description, dhe_export_description) != NULL) {
4463 dhe_found = 1;
4464 break;
4465 }
Remi Gacognec1eab8c2014-06-12 18:20:11 +02004466 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004467 }
4468 }
Remi Gacogne23d5d372014-10-10 17:04:26 +02004469 SSL_free(ssl);
4470 ssl = NULL;
Lukas Tribus90132722014-08-18 00:56:33 +02004471 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004472
Lukas Tribus90132722014-08-18 00:56:33 +02004473 if (dhe_found) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004474 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 +02004475 }
4476
Willy Tarreauef934602016-12-22 23:12:01 +01004477 global_ssl.default_dh_param = 1024;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004478 }
Remi Gacogne8de54152014-07-15 11:36:40 +02004479
Willy Tarreauef934602016-12-22 23:12:01 +01004480 if (global_ssl.default_dh_param >= 1024) {
Remi Gacogne8de54152014-07-15 11:36:40 +02004481 if (local_dh_1024 == NULL) {
4482 local_dh_1024 = ssl_get_dh_1024();
4483 }
Willy Tarreauef934602016-12-22 23:12:01 +01004484 if (global_ssl.default_dh_param >= 2048) {
Remi Gacogne8de54152014-07-15 11:36:40 +02004485 if (local_dh_2048 == NULL) {
4486 local_dh_2048 = ssl_get_dh_2048();
4487 }
Willy Tarreauef934602016-12-22 23:12:01 +01004488 if (global_ssl.default_dh_param >= 4096) {
Remi Gacogne8de54152014-07-15 11:36:40 +02004489 if (local_dh_4096 == NULL) {
4490 local_dh_4096 = ssl_get_dh_4096();
4491 }
Remi Gacogne8de54152014-07-15 11:36:40 +02004492 }
4493 }
4494 }
4495#endif /* OPENSSL_NO_DH */
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004496
Emeric Brunfc0421f2012-09-07 17:30:07 +02004497 SSL_CTX_set_info_callback(ctx, ssl_sock_infocbk);
Willy Tarreau9a1ab082019-05-09 13:26:41 +02004498#if HA_OPENSSL_VERSION_NUMBER >= 0x00907000L
Emeric Brun29f037d2014-04-25 19:05:36 +02004499 SSL_CTX_set_msg_callback(ctx, ssl_sock_msgcbk);
Willy Tarreau5cbe4ef2014-05-08 22:45:11 +02004500#endif
Emeric Brun29f037d2014-04-25 19:05:36 +02004501
Bernard Spil13c53f82018-02-15 13:34:58 +01004502#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004503 ssl_conf_cur = NULL;
4504 if (ssl_conf && ssl_conf->npn_str)
4505 ssl_conf_cur = ssl_conf;
4506 else if (bind_conf->ssl_conf.npn_str)
4507 ssl_conf_cur = &bind_conf->ssl_conf;
4508 if (ssl_conf_cur)
4509 SSL_CTX_set_next_protos_advertised_cb(ctx, ssl_sock_advertise_npn_protos, ssl_conf_cur);
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02004510#endif
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01004511#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004512 ssl_conf_cur = NULL;
4513 if (ssl_conf && ssl_conf->alpn_str)
4514 ssl_conf_cur = ssl_conf;
4515 else if (bind_conf->ssl_conf.alpn_str)
4516 ssl_conf_cur = &bind_conf->ssl_conf;
4517 if (ssl_conf_cur)
4518 SSL_CTX_set_alpn_select_cb(ctx, ssl_sock_advertise_alpn_protos, ssl_conf_cur);
Willy Tarreauab861d32013-04-02 02:30:41 +02004519#endif
Lukas Tribusd13e9252019-11-24 18:20:40 +01004520#if ((HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL) || defined(LIBRESSL_VERSION_NUMBER))
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004521 conf_curves = (ssl_conf && ssl_conf->curves) ? ssl_conf->curves : bind_conf->ssl_conf.curves;
4522 if (conf_curves) {
4523 if (!SSL_CTX_set1_curves_list(ctx, conf_curves)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004524 ha_alert("Proxy '%s': unable to set SSL curves list to '%s' for bind '%s' at [%s:%d].\n",
4525 curproxy->id, conf_curves, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004526 cfgerr++;
4527 }
Emmanuel Hocdeta52bb152017-03-20 11:11:49 +01004528 (void)SSL_CTX_set_ecdh_auto(ctx, 1);
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004529 }
4530#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02004531#if defined(SSL_CTX_set_tmp_ecdh) && !defined(OPENSSL_NO_ECDH)
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004532 if (!conf_curves) {
Emeric Brun2b58d042012-09-20 17:10:03 +02004533 int i;
4534 EC_KEY *ecdh;
Willy Tarreau9a1ab082019-05-09 13:26:41 +02004535#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004536 const char *ecdhe = (ssl_conf && ssl_conf->ecdhe) ? ssl_conf->ecdhe :
Olivier Houchardc2aae742017-09-22 18:26:28 +02004537 (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe :
4538 NULL);
4539
4540 if (ecdhe == NULL) {
Eric Salama27c21cd2019-11-20 11:33:40 +01004541 (void)SSL_CTX_set_ecdh_auto(ctx, 1);
Olivier Houchardc2aae742017-09-22 18:26:28 +02004542 return cfgerr;
4543 }
4544#else
4545 const char *ecdhe = (ssl_conf && ssl_conf->ecdhe) ? ssl_conf->ecdhe :
4546 (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe :
4547 ECDHE_DEFAULT_CURVE);
4548#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02004549
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004550 i = OBJ_sn2nid(ecdhe);
Emeric Brun2b58d042012-09-20 17:10:03 +02004551 if (!i || ((ecdh = EC_KEY_new_by_curve_name(i)) == NULL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004552 ha_alert("Proxy '%s': unable to set elliptic named curve to '%s' for bind '%s' at [%s:%d].\n",
4553 curproxy->id, ecdhe, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brun2b58d042012-09-20 17:10:03 +02004554 cfgerr++;
4555 }
4556 else {
4557 SSL_CTX_set_tmp_ecdh(ctx, ecdh);
4558 EC_KEY_free(ecdh);
4559 }
4560 }
4561#endif
4562
Emeric Brunfc0421f2012-09-07 17:30:07 +02004563 return cfgerr;
4564}
4565
Evan Broderbe554312013-06-27 00:05:25 -07004566static int ssl_sock_srv_hostcheck(const char *pattern, const char *hostname)
4567{
4568 const char *pattern_wildcard, *pattern_left_label_end, *hostname_left_label_end;
4569 size_t prefixlen, suffixlen;
4570
4571 /* Trivial case */
4572 if (strcmp(pattern, hostname) == 0)
4573 return 1;
4574
Evan Broderbe554312013-06-27 00:05:25 -07004575 /* The rest of this logic is based on RFC 6125, section 6.4.3
4576 * (http://tools.ietf.org/html/rfc6125#section-6.4.3) */
4577
Emeric Bruna848dae2013-10-08 11:27:28 +02004578 pattern_wildcard = NULL;
4579 pattern_left_label_end = pattern;
4580 while (*pattern_left_label_end != '.') {
4581 switch (*pattern_left_label_end) {
4582 case 0:
4583 /* End of label not found */
4584 return 0;
4585 case '*':
4586 /* If there is more than one wildcards */
4587 if (pattern_wildcard)
4588 return 0;
4589 pattern_wildcard = pattern_left_label_end;
4590 break;
4591 }
4592 pattern_left_label_end++;
4593 }
4594
4595 /* If it's not trivial and there is no wildcard, it can't
4596 * match */
4597 if (!pattern_wildcard)
Evan Broderbe554312013-06-27 00:05:25 -07004598 return 0;
4599
4600 /* Make sure all labels match except the leftmost */
4601 hostname_left_label_end = strchr(hostname, '.');
4602 if (!hostname_left_label_end
4603 || strcmp(pattern_left_label_end, hostname_left_label_end) != 0)
4604 return 0;
4605
4606 /* Make sure the leftmost label of the hostname is long enough
4607 * that the wildcard can match */
Emeric Brun369da852013-10-08 11:39:35 +02004608 if (hostname_left_label_end - hostname < (pattern_left_label_end - pattern) - 1)
Evan Broderbe554312013-06-27 00:05:25 -07004609 return 0;
4610
4611 /* Finally compare the string on either side of the
4612 * wildcard */
4613 prefixlen = pattern_wildcard - pattern;
4614 suffixlen = pattern_left_label_end - (pattern_wildcard + 1);
Emeric Bruna848dae2013-10-08 11:27:28 +02004615 if ((prefixlen && (memcmp(pattern, hostname, prefixlen) != 0))
4616 || (suffixlen && (memcmp(pattern_wildcard + 1, hostname_left_label_end - suffixlen, suffixlen) != 0)))
Evan Broderbe554312013-06-27 00:05:25 -07004617 return 0;
4618
4619 return 1;
4620}
4621
4622static int ssl_sock_srv_verifycbk(int ok, X509_STORE_CTX *ctx)
4623{
4624 SSL *ssl;
4625 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01004626 struct ssl_sock_ctx *ssl_ctx;
Willy Tarreau2ab88672017-07-05 18:23:03 +02004627 const char *servername;
Willy Tarreau71d058c2017-07-26 20:09:56 +02004628 const char *sni;
Evan Broderbe554312013-06-27 00:05:25 -07004629
4630 int depth;
4631 X509 *cert;
4632 STACK_OF(GENERAL_NAME) *alt_names;
4633 int i;
4634 X509_NAME *cert_subject;
4635 char *str;
4636
4637 if (ok == 0)
4638 return ok;
4639
4640 ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
Thierry FOURNIER28962c92018-06-17 21:37:05 +02004641 conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Olivier Houchard66ab4982019-02-26 18:37:15 +01004642 ssl_ctx = conn->xprt_ctx;
Evan Broderbe554312013-06-27 00:05:25 -07004643
Willy Tarreauad92a9a2017-07-28 11:38:41 +02004644 /* We're checking if the provided hostnames match the desired one. The
4645 * desired hostname comes from the SNI we presented if any, or if not
4646 * provided then it may have been explicitly stated using a "verifyhost"
4647 * directive. If neither is set, we don't care about the name so the
4648 * verification is OK.
Willy Tarreau2ab88672017-07-05 18:23:03 +02004649 */
Olivier Houchard66ab4982019-02-26 18:37:15 +01004650 servername = SSL_get_servername(ssl_ctx->ssl, TLSEXT_NAMETYPE_host_name);
Willy Tarreau71d058c2017-07-26 20:09:56 +02004651 sni = servername;
Willy Tarreau2ab88672017-07-05 18:23:03 +02004652 if (!servername) {
Willy Tarreau07d94e42018-09-20 10:57:52 +02004653 servername = __objt_server(conn->target)->ssl_ctx.verify_host;
Willy Tarreau2ab88672017-07-05 18:23:03 +02004654 if (!servername)
4655 return ok;
4656 }
Evan Broderbe554312013-06-27 00:05:25 -07004657
4658 /* We only need to verify the CN on the actual server cert,
4659 * not the indirect CAs */
4660 depth = X509_STORE_CTX_get_error_depth(ctx);
4661 if (depth != 0)
4662 return ok;
4663
4664 /* At this point, the cert is *not* OK unless we can find a
4665 * hostname match */
4666 ok = 0;
4667
4668 cert = X509_STORE_CTX_get_current_cert(ctx);
4669 /* It seems like this might happen if verify peer isn't set */
4670 if (!cert)
4671 return ok;
4672
4673 alt_names = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
4674 if (alt_names) {
4675 for (i = 0; !ok && i < sk_GENERAL_NAME_num(alt_names); i++) {
4676 GENERAL_NAME *name = sk_GENERAL_NAME_value(alt_names, i);
4677 if (name->type == GEN_DNS) {
Willy Tarreau9a1ab082019-05-09 13:26:41 +02004678#if HA_OPENSSL_VERSION_NUMBER < 0x00907000L
Emeric Bruna33410c2013-09-17 15:47:48 +02004679 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.ia5) >= 0) {
4680#else
Evan Broderbe554312013-06-27 00:05:25 -07004681 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
Emeric Bruna33410c2013-09-17 15:47:48 +02004682#endif
Evan Broderbe554312013-06-27 00:05:25 -07004683 ok = ssl_sock_srv_hostcheck(str, servername);
4684 OPENSSL_free(str);
4685 }
4686 }
4687 }
Emeric Brun4ad50a42013-09-17 15:19:54 +02004688 sk_GENERAL_NAME_pop_free(alt_names, GENERAL_NAME_free);
Evan Broderbe554312013-06-27 00:05:25 -07004689 }
4690
4691 cert_subject = X509_get_subject_name(cert);
4692 i = -1;
4693 while (!ok && (i = X509_NAME_get_index_by_NID(cert_subject, NID_commonName, i)) != -1) {
4694 X509_NAME_ENTRY *entry = X509_NAME_get_entry(cert_subject, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02004695 ASN1_STRING *value;
4696 value = X509_NAME_ENTRY_get_data(entry);
4697 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
Evan Broderbe554312013-06-27 00:05:25 -07004698 ok = ssl_sock_srv_hostcheck(str, servername);
4699 OPENSSL_free(str);
4700 }
4701 }
4702
Willy Tarreau71d058c2017-07-26 20:09:56 +02004703 /* report the mismatch and indicate if SNI was used or not */
4704 if (!ok && !conn->err_code)
4705 conn->err_code = sni ? CO_ER_SSL_MISMATCH_SNI : CO_ER_SSL_MISMATCH;
Evan Broderbe554312013-06-27 00:05:25 -07004706 return ok;
4707}
4708
Emeric Brun94324a42012-10-11 14:00:19 +02004709/* prepare ssl context from servers options. Returns an error count */
Willy Tarreau03209342016-12-22 17:08:28 +01004710int ssl_sock_prepare_srv_ctx(struct server *srv)
Emeric Brun94324a42012-10-11 14:00:19 +02004711{
Willy Tarreau03209342016-12-22 17:08:28 +01004712 struct proxy *curproxy = srv->proxy;
Emeric Brun94324a42012-10-11 14:00:19 +02004713 int cfgerr = 0;
Remi Gacogneaf5c3da2014-05-19 10:29:58 +02004714 long options =
Emeric Brun94324a42012-10-11 14:00:19 +02004715 SSL_OP_ALL | /* all known workarounds for bugs */
4716 SSL_OP_NO_SSLv2 |
4717 SSL_OP_NO_COMPRESSION;
Remi Gacogneaf5c3da2014-05-19 10:29:58 +02004718 long mode =
Emeric Brun94324a42012-10-11 14:00:19 +02004719 SSL_MODE_ENABLE_PARTIAL_WRITE |
4720 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
Willy Tarreau396a1862014-11-13 14:06:52 +01004721 SSL_MODE_RELEASE_BUFFERS |
4722 SSL_MODE_SMALL_BUFFERS;
Emeric Brun850efd52014-01-29 12:24:34 +01004723 int verify = SSL_VERIFY_NONE;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004724 SSL_CTX *ctx = NULL;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004725 struct tls_version_filter *conf_ssl_methods = &srv->ssl_ctx.methods;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004726 int i, min, max, hole;
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004727 int flags = MC_SSL_O_ALL;
Emeric Brun94324a42012-10-11 14:00:19 +02004728
Thierry Fournier383085f2013-01-24 14:15:43 +01004729 /* Make sure openssl opens /dev/urandom before the chroot */
4730 if (!ssl_initialize_random()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004731 ha_alert("OpenSSL random data generator initialization failed.\n");
Thierry Fournier383085f2013-01-24 14:15:43 +01004732 cfgerr++;
4733 }
4734
Willy Tarreaufce03112015-01-15 21:32:40 +01004735 /* Automatic memory computations need to know we use SSL there */
4736 global.ssl_used_backend = 1;
4737
4738 /* Initiate SSL context for current server */
Emeric Brun821bb9b2017-06-15 16:37:39 +02004739 if (!srv->ssl_ctx.reused_sess) {
Olivier Houcharde6060c52017-11-16 17:42:52 +01004740 if ((srv->ssl_ctx.reused_sess = calloc(1, global.nbthread*sizeof(*srv->ssl_ctx.reused_sess))) == NULL) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004741 ha_alert("Proxy '%s', server '%s' [%s:%d] out of memory.\n",
4742 curproxy->id, srv->id,
4743 srv->conf.file, srv->conf.line);
Emeric Brun821bb9b2017-06-15 16:37:39 +02004744 cfgerr++;
4745 return cfgerr;
4746 }
4747 }
Christopher Faulet68d35ae2020-03-27 18:55:49 +01004748 if (srv->use_ssl == 1)
Emeric Brun94324a42012-10-11 14:00:19 +02004749 srv->xprt = &ssl_sock;
Emeric Brun94324a42012-10-11 14:00:19 +02004750
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004751 ctx = SSL_CTX_new(SSLv23_client_method());
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004752 if (!ctx) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004753 ha_alert("config : %s '%s', server '%s': unable to allocate ssl context.\n",
4754 proxy_type_str(curproxy), curproxy->id,
4755 srv->id);
Emeric Brun94324a42012-10-11 14:00:19 +02004756 cfgerr++;
4757 return cfgerr;
4758 }
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004759
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004760 if (conf_ssl_methods->flags && (conf_ssl_methods->min || conf_ssl_methods->max))
Christopher Faulet767a84b2017-11-24 16:50:31 +01004761 ha_warning("config : %s '%s': no-sslv3/no-tlsv1x are ignored for server '%s'. "
4762 "Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
4763 proxy_type_str(curproxy), curproxy->id, srv->id);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004764 else
4765 flags = conf_ssl_methods->flags;
4766
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004767 /* Real min and max should be determinate with configuration and openssl's capabilities */
4768 if (conf_ssl_methods->min)
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004769 flags |= (methodVersions[conf_ssl_methods->min].flag - 1);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004770 if (conf_ssl_methods->max)
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004771 flags |= ~((methodVersions[conf_ssl_methods->max].flag << 1) - 1);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004772
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004773 /* find min, max and holes */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004774 min = max = CONF_TLSV_NONE;
4775 hole = 0;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004776 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004777 /* version is in openssl && version not disable in configuration */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004778 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004779 if (min) {
4780 if (hole) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004781 ha_warning("config : %s '%s': SSL/TLS versions range not contiguous for server '%s'. "
4782 "Hole find for %s. Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
4783 proxy_type_str(curproxy), curproxy->id, srv->id,
4784 methodVersions[hole].name);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004785 hole = 0;
4786 }
4787 max = i;
4788 }
4789 else {
4790 min = max = i;
4791 }
4792 }
4793 else {
4794 if (min)
4795 hole = i;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004796 }
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004797 if (!min) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004798 ha_alert("config : %s '%s': all SSL/TLS versions are disabled for server '%s'.\n",
4799 proxy_type_str(curproxy), curproxy->id, srv->id);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004800 cfgerr += 1;
4801 }
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004802
Willy Tarreau9a1ab082019-05-09 13:26:41 +02004803#if (HA_OPENSSL_VERSION_NUMBER < 0x1010000fL)
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004804 /* Keep force-xxx implementation as it is in older haproxy. It's a
Joseph Herlant017b3da2018-11-15 09:07:59 -08004805 precautionary measure to avoid any surprise with older openssl version. */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004806 if (min == max)
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004807 methodVersions[min].ctx_set_version(ctx, SET_CLIENT);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004808 else
4809 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
4810 if (flags & methodVersions[i].flag)
4811 options |= methodVersions[i].option;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004812#else /* openssl >= 1.1.0 */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004813 /* set the max_version is required to cap TLS version or activate new TLS (v1.3) */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004814 methodVersions[min].ctx_set_version(ctx, SET_MIN);
4815 methodVersions[max].ctx_set_version(ctx, SET_MAX);
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004816#endif
4817
4818 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLS_TICKETS)
4819 options |= SSL_OP_NO_TICKET;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004820 SSL_CTX_set_options(ctx, options);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004821
Willy Tarreau5db847a2019-05-09 14:13:35 +02004822#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004823 if (global_ssl.async)
4824 mode |= SSL_MODE_ASYNC;
4825#endif
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004826 SSL_CTX_set_mode(ctx, mode);
4827 srv->ssl_ctx.ctx = ctx;
4828
Emeric Bruna7aa3092012-10-26 12:58:00 +02004829 if (srv->ssl_ctx.client_crt) {
4830 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 +01004831 ha_alert("config : %s '%s', server '%s': unable to load SSL private key from PEM file '%s'.\n",
4832 proxy_type_str(curproxy), curproxy->id,
4833 srv->id, srv->ssl_ctx.client_crt);
Emeric Bruna7aa3092012-10-26 12:58:00 +02004834 cfgerr++;
4835 }
4836 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 +01004837 ha_alert("config : %s '%s', server '%s': unable to load ssl certificate from PEM file '%s'.\n",
4838 proxy_type_str(curproxy), curproxy->id,
4839 srv->id, srv->ssl_ctx.client_crt);
Emeric Bruna7aa3092012-10-26 12:58:00 +02004840 cfgerr++;
4841 }
4842 else if (SSL_CTX_check_private_key(srv->ssl_ctx.ctx) <= 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004843 ha_alert("config : %s '%s', server '%s': inconsistencies between private key and certificate loaded from PEM file '%s'.\n",
4844 proxy_type_str(curproxy), curproxy->id,
4845 srv->id, srv->ssl_ctx.client_crt);
Emeric Bruna7aa3092012-10-26 12:58:00 +02004846 cfgerr++;
4847 }
4848 }
Emeric Brun94324a42012-10-11 14:00:19 +02004849
Emeric Brun850efd52014-01-29 12:24:34 +01004850 if (global.ssl_server_verify == SSL_SERVER_VERIFY_REQUIRED)
4851 verify = SSL_VERIFY_PEER;
Emeric Brun850efd52014-01-29 12:24:34 +01004852 switch (srv->ssl_ctx.verify) {
4853 case SSL_SOCK_VERIFY_NONE:
4854 verify = SSL_VERIFY_NONE;
4855 break;
4856 case SSL_SOCK_VERIFY_REQUIRED:
4857 verify = SSL_VERIFY_PEER;
4858 break;
4859 }
Evan Broderbe554312013-06-27 00:05:25 -07004860 SSL_CTX_set_verify(srv->ssl_ctx.ctx,
Emeric Brun850efd52014-01-29 12:24:34 +01004861 verify,
Willy Tarreau2ab88672017-07-05 18:23:03 +02004862 (srv->ssl_ctx.verify_host || (verify & SSL_VERIFY_PEER)) ? ssl_sock_srv_verifycbk : NULL);
Emeric Brun850efd52014-01-29 12:24:34 +01004863 if (verify & SSL_VERIFY_PEER) {
Emeric Brunef42d922012-10-11 16:11:36 +02004864 if (srv->ssl_ctx.ca_file) {
4865 /* load CAfile to verify */
4866 if (!SSL_CTX_load_verify_locations(srv->ssl_ctx.ctx, srv->ssl_ctx.ca_file, NULL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004867 ha_alert("Proxy '%s', server '%s' [%s:%d] unable to load CA file '%s'.\n",
4868 curproxy->id, srv->id,
4869 srv->conf.file, srv->conf.line, srv->ssl_ctx.ca_file);
Emeric Brunef42d922012-10-11 16:11:36 +02004870 cfgerr++;
4871 }
4872 }
Emeric Brun850efd52014-01-29 12:24:34 +01004873 else {
4874 if (global.ssl_server_verify == SSL_SERVER_VERIFY_REQUIRED)
Christopher Faulet767a84b2017-11-24 16:50:31 +01004875 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",
4876 curproxy->id, srv->id,
4877 srv->conf.file, srv->conf.line);
Emeric Brun850efd52014-01-29 12:24:34 +01004878 else
Christopher Faulet767a84b2017-11-24 16:50:31 +01004879 ha_alert("Proxy '%s', server '%s' [%s:%d] verify is enabled but no CA file specified.\n",
4880 curproxy->id, srv->id,
4881 srv->conf.file, srv->conf.line);
Emeric Brun850efd52014-01-29 12:24:34 +01004882 cfgerr++;
4883 }
Emeric Brunef42d922012-10-11 16:11:36 +02004884#ifdef X509_V_FLAG_CRL_CHECK
4885 if (srv->ssl_ctx.crl_file) {
4886 X509_STORE *store = SSL_CTX_get_cert_store(srv->ssl_ctx.ctx);
4887
4888 if (!store || !X509_STORE_load_locations(store, srv->ssl_ctx.crl_file, NULL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004889 ha_alert("Proxy '%s', server '%s' [%s:%d] unable to configure CRL file '%s'.\n",
4890 curproxy->id, srv->id,
4891 srv->conf.file, srv->conf.line, srv->ssl_ctx.crl_file);
Emeric Brunef42d922012-10-11 16:11:36 +02004892 cfgerr++;
4893 }
4894 else {
4895 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
4896 }
4897 }
4898#endif
4899 }
4900
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004901 SSL_CTX_set_session_cache_mode(srv->ssl_ctx.ctx, SSL_SESS_CACHE_CLIENT |
4902 SSL_SESS_CACHE_NO_INTERNAL_STORE);
4903 SSL_CTX_sess_set_new_cb(srv->ssl_ctx.ctx, ssl_sess_new_srv_cb);
Emeric Brun94324a42012-10-11 14:00:19 +02004904 if (srv->ssl_ctx.ciphers &&
4905 !SSL_CTX_set_cipher_list(srv->ssl_ctx.ctx, srv->ssl_ctx.ciphers)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004906 ha_alert("Proxy '%s', server '%s' [%s:%d] : unable to set SSL cipher list to '%s'.\n",
4907 curproxy->id, srv->id,
4908 srv->conf.file, srv->conf.line, srv->ssl_ctx.ciphers);
Emeric Brun94324a42012-10-11 14:00:19 +02004909 cfgerr++;
4910 }
Dirkjan Bussink415150f2018-09-14 11:14:21 +02004911
Emmanuel Hocdet839af572019-05-14 16:27:35 +02004912#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02004913 if (srv->ssl_ctx.ciphersuites &&
Pierre Cheynierbc34cd12019-03-21 16:15:47 +00004914 !SSL_CTX_set_ciphersuites(srv->ssl_ctx.ctx, srv->ssl_ctx.ciphersuites)) {
Dirkjan Bussink415150f2018-09-14 11:14:21 +02004915 ha_alert("Proxy '%s', server '%s' [%s:%d] : unable to set TLS 1.3 cipher suites to '%s'.\n",
4916 curproxy->id, srv->id,
4917 srv->conf.file, srv->conf.line, srv->ssl_ctx.ciphersuites);
4918 cfgerr++;
4919 }
4920#endif
Olivier Houchardc7566002018-11-20 23:33:50 +01004921#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
4922 if (srv->ssl_ctx.npn_str)
4923 SSL_CTX_set_next_proto_select_cb(ctx, ssl_sock_srv_select_protos, srv);
4924#endif
4925#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
4926 if (srv->ssl_ctx.alpn_str)
4927 SSL_CTX_set_alpn_protos(ctx, (unsigned char *)srv->ssl_ctx.alpn_str, srv->ssl_ctx.alpn_len);
4928#endif
4929
Emeric Brun94324a42012-10-11 14:00:19 +02004930
4931 return cfgerr;
4932}
4933
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004934/* Walks down the two trees in bind_conf and prepares all certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +02004935 * be NULL, in which case nothing is done. Returns the number of errors
4936 * encountered.
4937 */
Willy Tarreau03209342016-12-22 17:08:28 +01004938int ssl_sock_prepare_all_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02004939{
4940 struct ebmb_node *node;
4941 struct sni_ctx *sni;
4942 int err = 0;
4943
Willy Tarreaufce03112015-01-15 21:32:40 +01004944 /* Automatic memory computations need to know we use SSL there */
4945 global.ssl_used_frontend = 1;
4946
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004947 /* Make sure openssl opens /dev/urandom before the chroot */
4948 if (!ssl_initialize_random()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004949 ha_alert("OpenSSL random data generator initialization failed.\n");
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004950 err++;
4951 }
4952 /* Create initial_ctx used to start the ssl connection before do switchctx */
4953 if (!bind_conf->initial_ctx) {
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004954 err += ssl_sock_initial_ctx(bind_conf);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004955 /* It should not be necessary to call this function, but it's
4956 necessary first to check and move all initialisation related
4957 to initial_ctx in ssl_sock_initial_ctx. */
4958 err += ssl_sock_prepare_ctx(bind_conf, NULL, bind_conf->initial_ctx);
4959 }
Emeric Brun0bed9942014-10-30 19:25:24 +01004960 if (bind_conf->default_ctx)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004961 err += ssl_sock_prepare_ctx(bind_conf, bind_conf->default_ssl_conf, bind_conf->default_ctx);
Emeric Brun0bed9942014-10-30 19:25:24 +01004962
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004963 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004964 while (node) {
4965 sni = ebmb_entry(node, struct sni_ctx, name);
Emeric Brun0bed9942014-10-30 19:25:24 +01004966 if (!sni->order && sni->ctx != bind_conf->default_ctx)
4967 /* only initialize the CTX on its first occurrence and
4968 if it is not the default_ctx */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004969 err += ssl_sock_prepare_ctx(bind_conf, sni->conf, sni->ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004970 node = ebmb_next(node);
4971 }
4972
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004973 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004974 while (node) {
4975 sni = ebmb_entry(node, struct sni_ctx, name);
Emeric Brun0bed9942014-10-30 19:25:24 +01004976 if (!sni->order && sni->ctx != bind_conf->default_ctx)
4977 /* only initialize the CTX on its first occurrence and
4978 if it is not the default_ctx */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004979 err += ssl_sock_prepare_ctx(bind_conf, sni->conf, sni->ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004980 node = ebmb_next(node);
4981 }
4982 return err;
4983}
4984
Willy Tarreau55d37912016-12-21 23:38:39 +01004985/* Prepares all the contexts for a bind_conf and allocates the shared SSL
4986 * context if needed. Returns < 0 on error, 0 on success. The warnings and
4987 * alerts are directly emitted since the rest of the stack does it below.
4988 */
4989int ssl_sock_prepare_bind_conf(struct bind_conf *bind_conf)
4990{
4991 struct proxy *px = bind_conf->frontend;
4992 int alloc_ctx;
4993 int err;
4994
4995 if (!bind_conf->is_ssl) {
4996 if (bind_conf->default_ctx) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004997 ha_warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
4998 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreau55d37912016-12-21 23:38:39 +01004999 }
5000 return 0;
5001 }
5002 if (!bind_conf->default_ctx) {
Emmanuel Hocdetaa0d6372017-08-09 11:24:25 +02005003 if (bind_conf->strict_sni && !bind_conf->generate_certs) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005004 ha_warning("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d], ssl connections will fail (use 'crt').\n",
5005 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetaa0d6372017-08-09 11:24:25 +02005006 }
5007 else {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005008 ha_alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
5009 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetaa0d6372017-08-09 11:24:25 +02005010 return -1;
5011 }
Willy Tarreau55d37912016-12-21 23:38:39 +01005012 }
William Lallemandc61c0b32017-12-04 18:46:39 +01005013 if (!ssl_shctx && global.tune.sslcachesize) {
William Lallemandc3cd35f2017-11-28 11:04:43 +01005014 alloc_ctx = shctx_init(&ssl_shctx, global.tune.sslcachesize,
Frédéric Lécailleb7838af2018-10-22 16:21:39 +02005015 sizeof(struct sh_ssl_sess_hdr) + SHSESS_BLOCK_MIN_SIZE, -1,
William Lallemandc3cd35f2017-11-28 11:04:43 +01005016 sizeof(*sh_ssl_sess_tree),
5017 ((global.nbthread > 1) || (!global_ssl.private_cache && (global.nbproc > 1))) ? 1 : 0);
Frédéric Lécaille4c8aa112018-10-25 20:22:46 +02005018 if (alloc_ctx <= 0) {
William Lallemandc3cd35f2017-11-28 11:04:43 +01005019 if (alloc_ctx == SHCTX_E_INIT_LOCK)
5020 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");
5021 else
5022 ha_alert("Unable to allocate SSL session cache.\n");
5023 return -1;
5024 }
5025 /* free block callback */
5026 ssl_shctx->free_block = sh_ssl_sess_free_blocks;
5027 /* init the root tree within the extra space */
5028 sh_ssl_sess_tree = (void *)ssl_shctx + sizeof(struct shared_context);
5029 *sh_ssl_sess_tree = EB_ROOT_UNIQUE;
Willy Tarreau55d37912016-12-21 23:38:39 +01005030 }
Willy Tarreau55d37912016-12-21 23:38:39 +01005031 err = 0;
5032 /* initialize all certificate contexts */
5033 err += ssl_sock_prepare_all_ctx(bind_conf);
5034
5035 /* initialize CA variables if the certificates generation is enabled */
5036 err += ssl_sock_load_ca(bind_conf);
5037
5038 return -err;
5039}
Christopher Faulet77fe80c2015-07-29 13:02:40 +02005040
5041/* release ssl context allocated for servers. */
5042void ssl_sock_free_srv_ctx(struct server *srv)
5043{
Olivier Houchardc7566002018-11-20 23:33:50 +01005044#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
5045 if (srv->ssl_ctx.alpn_str)
5046 free(srv->ssl_ctx.alpn_str);
5047#endif
Lukas Tribusda95fd92018-11-25 13:21:27 +01005048#ifdef OPENSSL_NPN_NEGOTIATED
Olivier Houchardc7566002018-11-20 23:33:50 +01005049 if (srv->ssl_ctx.npn_str)
5050 free(srv->ssl_ctx.npn_str);
Lukas Tribus7706b852018-11-26 22:57:17 +01005051#endif
Christopher Faulet77fe80c2015-07-29 13:02:40 +02005052 if (srv->ssl_ctx.ctx)
5053 SSL_CTX_free(srv->ssl_ctx.ctx);
5054}
5055
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005056/* Walks down the two trees in bind_conf and frees all the certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +02005057 * be NULL, in which case nothing is done. The default_ctx is nullified too.
5058 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005059void ssl_sock_free_all_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02005060{
5061 struct ebmb_node *node, *back;
5062 struct sni_ctx *sni;
5063
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005064 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02005065 while (node) {
5066 sni = ebmb_entry(node, struct sni_ctx, name);
5067 back = ebmb_next(node);
5068 ebmb_delete(node);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005069 if (!sni->order) { /* only free the CTX on its first occurrence */
Emeric Brunfc0421f2012-09-07 17:30:07 +02005070 SSL_CTX_free(sni->ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005071 ssl_sock_free_ssl_conf(sni->conf);
5072 free(sni->conf);
5073 sni->conf = NULL;
5074 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02005075 free(sni);
5076 node = back;
5077 }
5078
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005079 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02005080 while (node) {
5081 sni = ebmb_entry(node, struct sni_ctx, name);
5082 back = ebmb_next(node);
5083 ebmb_delete(node);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005084 if (!sni->order) { /* only free the CTX on its first occurrence */
Emeric Brunfc0421f2012-09-07 17:30:07 +02005085 SSL_CTX_free(sni->ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005086 ssl_sock_free_ssl_conf(sni->conf);
5087 free(sni->conf);
5088 sni->conf = NULL;
5089 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02005090 free(sni);
5091 node = back;
5092 }
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01005093 SSL_CTX_free(bind_conf->initial_ctx);
5094 bind_conf->initial_ctx = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005095 bind_conf->default_ctx = NULL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005096 bind_conf->default_ssl_conf = NULL;
Emeric Brune1f38db2012-09-03 20:36:47 +02005097}
5098
Willy Tarreau795cdab2016-12-22 17:30:54 +01005099/* Destroys all the contexts for a bind_conf. This is used during deinit(). */
5100void ssl_sock_destroy_bind_conf(struct bind_conf *bind_conf)
5101{
5102 ssl_sock_free_ca(bind_conf);
5103 ssl_sock_free_all_ctx(bind_conf);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005104 ssl_sock_free_ssl_conf(&bind_conf->ssl_conf);
Willy Tarreau795cdab2016-12-22 17:30:54 +01005105 free(bind_conf->ca_sign_file);
5106 free(bind_conf->ca_sign_pass);
Willy Tarreau17b4aa12018-07-17 10:05:32 +02005107 if (bind_conf->keys_ref && !--bind_conf->keys_ref->refcount) {
Willy Tarreau795cdab2016-12-22 17:30:54 +01005108 free(bind_conf->keys_ref->filename);
5109 free(bind_conf->keys_ref->tlskeys);
5110 LIST_DEL(&bind_conf->keys_ref->list);
5111 free(bind_conf->keys_ref);
5112 }
5113 bind_conf->keys_ref = NULL;
Willy Tarreau795cdab2016-12-22 17:30:54 +01005114 bind_conf->ca_sign_pass = NULL;
5115 bind_conf->ca_sign_file = NULL;
Willy Tarreau795cdab2016-12-22 17:30:54 +01005116}
5117
Christopher Faulet31af49d2015-06-09 17:29:50 +02005118/* Load CA cert file and private key used to generate certificates */
5119int
Willy Tarreau03209342016-12-22 17:08:28 +01005120ssl_sock_load_ca(struct bind_conf *bind_conf)
Christopher Faulet31af49d2015-06-09 17:29:50 +02005121{
Willy Tarreau03209342016-12-22 17:08:28 +01005122 struct proxy *px = bind_conf->frontend;
Christopher Faulet31af49d2015-06-09 17:29:50 +02005123 FILE *fp;
5124 X509 *cacert = NULL;
5125 EVP_PKEY *capkey = NULL;
5126 int err = 0;
5127
Christopher Fauletf8bb0ce2017-09-15 09:52:49 +02005128 if (!bind_conf->generate_certs)
Christopher Faulet31af49d2015-06-09 17:29:50 +02005129 return err;
5130
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005131#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Emeric Brun821bb9b2017-06-15 16:37:39 +02005132 if (global_ssl.ctx_cache) {
Willy Tarreauef934602016-12-22 23:12:01 +01005133 ssl_ctx_lru_tree = lru64_new(global_ssl.ctx_cache);
Emeric Brun821bb9b2017-06-15 16:37:39 +02005134 }
Christopher Fauletd2cab922015-07-28 16:03:47 +02005135 ssl_ctx_lru_seed = (unsigned int)time(NULL);
Emeric Brun821bb9b2017-06-15 16:37:39 +02005136 ssl_ctx_serial = now_ms;
Willy Tarreaua84c2672015-10-09 12:10:13 +02005137#endif
Christopher Fauletd2cab922015-07-28 16:03:47 +02005138
Christopher Faulet31af49d2015-06-09 17:29:50 +02005139 if (!bind_conf->ca_sign_file) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005140 ha_alert("Proxy '%s': cannot enable certificate generation, "
5141 "no CA certificate File configured at [%s:%d].\n",
5142 px->id, bind_conf->file, bind_conf->line);
Christopher Faulet31af49d2015-06-09 17:29:50 +02005143 goto load_error;
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005144 }
Christopher Faulet31af49d2015-06-09 17:29:50 +02005145
5146 /* read in the CA certificate */
5147 if (!(fp = fopen(bind_conf->ca_sign_file, "r"))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005148 ha_alert("Proxy '%s': Failed to read CA certificate file '%s' at [%s:%d].\n",
5149 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Faulet31af49d2015-06-09 17:29:50 +02005150 goto load_error;
5151 }
5152 if (!(cacert = PEM_read_X509(fp, NULL, NULL, NULL))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005153 ha_alert("Proxy '%s': Failed to read CA certificate file '%s' at [%s:%d].\n",
5154 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005155 goto read_error;
Christopher Faulet31af49d2015-06-09 17:29:50 +02005156 }
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005157 rewind(fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02005158 if (!(capkey = PEM_read_PrivateKey(fp, NULL, NULL, bind_conf->ca_sign_pass))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005159 ha_alert("Proxy '%s': Failed to read CA private key file '%s' at [%s:%d].\n",
5160 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005161 goto read_error;
Christopher Faulet31af49d2015-06-09 17:29:50 +02005162 }
Christopher Faulet31af49d2015-06-09 17:29:50 +02005163
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005164 fclose (fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02005165 bind_conf->ca_sign_cert = cacert;
5166 bind_conf->ca_sign_pkey = capkey;
5167 return err;
5168
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005169 read_error:
5170 fclose (fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02005171 if (capkey) EVP_PKEY_free(capkey);
5172 if (cacert) X509_free(cacert);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005173 load_error:
5174 bind_conf->generate_certs = 0;
5175 err++;
Christopher Faulet31af49d2015-06-09 17:29:50 +02005176 return err;
5177}
5178
5179/* Release CA cert and private key used to generate certificated */
5180void
5181ssl_sock_free_ca(struct bind_conf *bind_conf)
5182{
Christopher Faulet31af49d2015-06-09 17:29:50 +02005183 if (bind_conf->ca_sign_pkey)
5184 EVP_PKEY_free(bind_conf->ca_sign_pkey);
5185 if (bind_conf->ca_sign_cert)
5186 X509_free(bind_conf->ca_sign_cert);
Willy Tarreau94ff03a2016-12-22 17:57:46 +01005187 bind_conf->ca_sign_pkey = NULL;
5188 bind_conf->ca_sign_cert = NULL;
Christopher Faulet31af49d2015-06-09 17:29:50 +02005189}
5190
Emeric Brun46591952012-05-18 15:47:34 +02005191/*
5192 * This function is called if SSL * context is not yet allocated. The function
5193 * is designed to be called before any other data-layer operation and sets the
5194 * handshake flag on the connection. It is safe to call it multiple times.
5195 * It returns 0 on success and -1 in error case.
5196 */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005197static int ssl_sock_init(struct connection *conn, void **xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02005198{
Olivier Houchard66ab4982019-02-26 18:37:15 +01005199 struct ssl_sock_ctx *ctx;
Emeric Brun46591952012-05-18 15:47:34 +02005200 /* already initialized */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005201 if (*xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02005202 return 0;
5203
Willy Tarreau3c728722014-01-23 13:50:42 +01005204 if (!conn_ctrl_ready(conn))
Willy Tarreauf79c8172013-10-21 16:30:56 +02005205 return 0;
5206
Olivier Houchard66ab4982019-02-26 18:37:15 +01005207 ctx = pool_alloc(ssl_sock_ctx_pool);
5208 if (!ctx) {
5209 conn->err_code = CO_ER_SSL_NO_MEM;
5210 return -1;
5211 }
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02005212 ctx->wait_event.tasklet = tasklet_new();
5213 if (!ctx->wait_event.tasklet) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02005214 conn->err_code = CO_ER_SSL_NO_MEM;
5215 pool_free(ssl_sock_ctx_pool, ctx);
5216 return -1;
5217 }
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02005218 ctx->wait_event.tasklet->process = ssl_sock_io_cb;
5219 ctx->wait_event.tasklet->context = ctx;
Olivier Houchardea8dd942019-05-20 14:02:16 +02005220 ctx->wait_event.events = 0;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01005221 ctx->sent_early_data = 0;
Olivier Houchardf6715e72019-12-19 15:02:39 +01005222 ctx->early_buf = BUF_NULL;
Olivier Houcharda8955d52019-04-07 22:00:38 +02005223 ctx->conn = conn;
Olivier Houchard81284e62019-06-06 13:21:23 +02005224 ctx->send_wait = NULL;
5225 ctx->recv_wait = NULL;
Emeric Brun87cfd662019-09-06 15:36:02 +02005226 ctx->xprt_st = 0;
5227 ctx->xprt_ctx = NULL;
Olivier Houcharda8955d52019-04-07 22:00:38 +02005228
5229 /* Only work with sockets for now, this should be adapted when we'll
5230 * add QUIC support.
5231 */
5232 ctx->xprt = xprt_get(XPRT_RAW);
Olivier Houchard19afb272019-05-23 18:24:07 +02005233 if (ctx->xprt->init) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02005234 if (ctx->xprt->init(conn, &ctx->xprt_ctx) != 0)
5235 goto err;
Olivier Houchard19afb272019-05-23 18:24:07 +02005236 }
Olivier Houchard66ab4982019-02-26 18:37:15 +01005237
Willy Tarreau20879a02012-12-03 16:32:10 +01005238 if (global.maxsslconn && sslconns >= global.maxsslconn) {
5239 conn->err_code = CO_ER_SSL_TOO_MANY;
Olivier Houchardea8dd942019-05-20 14:02:16 +02005240 goto err;
Willy Tarreau20879a02012-12-03 16:32:10 +01005241 }
Willy Tarreau403edff2012-09-06 11:58:37 +02005242
Emeric Brun46591952012-05-18 15:47:34 +02005243 /* If it is in client mode initiate SSL session
5244 in connect state otherwise accept state */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01005245 if (objt_server(conn->target)) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005246 int may_retry = 1;
5247
5248 retry_connect:
Emeric Brun46591952012-05-18 15:47:34 +02005249 /* Alloc a new SSL session ctx */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005250 ctx->ssl = SSL_new(__objt_server(conn->target)->ssl_ctx.ctx);
5251 if (!ctx->ssl) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005252 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005253 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005254 goto retry_connect;
5255 }
Willy Tarreau20879a02012-12-03 16:32:10 +01005256 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01005257 goto err;
Willy Tarreau20879a02012-12-03 16:32:10 +01005258 }
Olivier Houcharda8955d52019-04-07 22:00:38 +02005259 ctx->bio = BIO_new(ha_meth);
5260 if (!ctx->bio) {
Olivier Houchardb451b972020-01-24 15:17:38 +01005261 SSL_free(ctx->ssl);
5262 ctx->ssl = NULL;
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 }
Emeric Brun55476152014-11-12 17:35:37 +01005267 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01005268 goto err;
Emeric Brun55476152014-11-12 17:35:37 +01005269 }
Olivier Houcharda8955d52019-04-07 22:00:38 +02005270 BIO_set_data(ctx->bio, ctx);
Olivier Houcharda8955d52019-04-07 22:00:38 +02005271 SSL_set_bio(ctx->ssl, ctx->bio, ctx->bio);
Emeric Brun46591952012-05-18 15:47:34 +02005272
Evan Broderbe554312013-06-27 00:05:25 -07005273 /* set connection pointer */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005274 if (!SSL_set_ex_data(ctx->ssl, ssl_app_data_index, conn)) {
5275 SSL_free(ctx->ssl);
5276 ctx->ssl = NULL;
Emeric Brun55476152014-11-12 17:35:37 +01005277 conn->xprt_ctx = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005278 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005279 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005280 goto retry_connect;
5281 }
Emeric Brun55476152014-11-12 17:35:37 +01005282 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01005283 goto err;
Emeric Brun55476152014-11-12 17:35:37 +01005284 }
5285
Olivier Houchard66ab4982019-02-26 18:37:15 +01005286 SSL_set_connect_state(ctx->ssl);
Willy Tarreau07d94e42018-09-20 10:57:52 +02005287 if (__objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr) {
5288 const unsigned char *ptr = __objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr;
5289 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 +01005290 if (sess && !SSL_set_session(ctx->ssl, sess)) {
Olivier Houcharde6060c52017-11-16 17:42:52 +01005291 SSL_SESSION_free(sess);
Willy Tarreau07d94e42018-09-20 10:57:52 +02005292 free(__objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr);
5293 __objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr = NULL;
Olivier Houcharde6060c52017-11-16 17:42:52 +01005294 } else if (sess) {
5295 SSL_SESSION_free(sess);
Emeric Brun55476152014-11-12 17:35:37 +01005296 }
5297 }
Evan Broderbe554312013-06-27 00:05:25 -07005298
Emeric Brun46591952012-05-18 15:47:34 +02005299 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +02005300 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Willy Tarreau403edff2012-09-06 11:58:37 +02005301
Olivier Houchard2be5a4c2019-03-08 18:54:43 +01005302 _HA_ATOMIC_ADD(&sslconns, 1);
5303 _HA_ATOMIC_ADD(&totalsslconns, 1);
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005304 *xprt_ctx = ctx;
Olivier Houchardea8dd942019-05-20 14:02:16 +02005305 /* Start the handshake */
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02005306 tasklet_wakeup(ctx->wait_event.tasklet);
Olivier Houchardea8dd942019-05-20 14:02:16 +02005307 if (conn->flags & CO_FL_ERROR)
5308 goto err;
Emeric Brun46591952012-05-18 15:47:34 +02005309 return 0;
5310 }
Willy Tarreau3fdb3662012-11-12 00:42:33 +01005311 else if (objt_listener(conn->target)) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005312 int may_retry = 1;
5313
5314 retry_accept:
Emeric Brun46591952012-05-18 15:47:34 +02005315 /* Alloc a new SSL session ctx */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005316 ctx->ssl = SSL_new(__objt_listener(conn->target)->bind_conf->initial_ctx);
5317 if (!ctx->ssl) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005318 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005319 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005320 goto retry_accept;
5321 }
Willy Tarreau20879a02012-12-03 16:32:10 +01005322 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01005323 goto err;
Willy Tarreau20879a02012-12-03 16:32:10 +01005324 }
Olivier Houcharda8955d52019-04-07 22:00:38 +02005325 ctx->bio = BIO_new(ha_meth);
5326 if (!ctx->bio) {
Olivier Houchardb451b972020-01-24 15:17:38 +01005327 SSL_free(ctx->ssl);
5328 ctx->ssl = NULL;
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 }
Emeric Brun55476152014-11-12 17:35:37 +01005333 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01005334 goto err;
Emeric Brun55476152014-11-12 17:35:37 +01005335 }
Olivier Houcharda8955d52019-04-07 22:00:38 +02005336 BIO_set_data(ctx->bio, ctx);
Olivier Houcharda8955d52019-04-07 22:00:38 +02005337 SSL_set_bio(ctx->ssl, ctx->bio, ctx->bio);
Emeric Brun46591952012-05-18 15:47:34 +02005338
Emeric Brune1f38db2012-09-03 20:36:47 +02005339 /* set connection pointer */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005340 if (!SSL_set_ex_data(ctx->ssl, ssl_app_data_index, conn)) {
5341 SSL_free(ctx->ssl);
5342 ctx->ssl = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005343 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005344 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005345 goto retry_accept;
5346 }
Emeric Brun55476152014-11-12 17:35:37 +01005347 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01005348 goto err;
Emeric Brun55476152014-11-12 17:35:37 +01005349 }
5350
Frédéric Lécaille583362f2020-01-24 14:56:18 +01005351#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
5352 if (__objt_listener(conn->target)->bind_conf->ssl_conf.early_data) {
5353 b_alloc(&ctx->early_buf);
5354 SSL_set_max_early_data(ctx->ssl,
5355 /* Only allow early data if we managed to allocate
5356 * a buffer.
5357 */
5358 (!b_is_null(&ctx->early_buf)) ?
5359 global.tune.bufsize - global.tune.maxrewrite : 0);
5360 }
5361#endif
5362
Olivier Houchard66ab4982019-02-26 18:37:15 +01005363 SSL_set_accept_state(ctx->ssl);
Emeric Brune1f38db2012-09-03 20:36:47 +02005364
Emeric Brun46591952012-05-18 15:47:34 +02005365 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +02005366 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Emmanuel Hocdet510fce52019-08-05 18:04:16 +02005367#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Olivier Houchardc2aae742017-09-22 18:26:28 +02005368 conn->flags |= CO_FL_EARLY_SSL_HS;
5369#endif
Willy Tarreau403edff2012-09-06 11:58:37 +02005370
Olivier Houchard2be5a4c2019-03-08 18:54:43 +01005371 _HA_ATOMIC_ADD(&sslconns, 1);
5372 _HA_ATOMIC_ADD(&totalsslconns, 1);
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005373 *xprt_ctx = ctx;
Olivier Houchardea8dd942019-05-20 14:02:16 +02005374 /* Start the handshake */
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02005375 tasklet_wakeup(ctx->wait_event.tasklet);
Olivier Houchardea8dd942019-05-20 14:02:16 +02005376 if (conn->flags & CO_FL_ERROR)
5377 goto err;
Emeric Brun46591952012-05-18 15:47:34 +02005378 return 0;
5379 }
5380 /* don't know how to handle such a target */
Willy Tarreau20879a02012-12-03 16:32:10 +01005381 conn->err_code = CO_ER_SSL_NO_TARGET;
Olivier Houchard66ab4982019-02-26 18:37:15 +01005382err:
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02005383 if (ctx && ctx->wait_event.tasklet)
5384 tasklet_free(ctx->wait_event.tasklet);
Olivier Houchard66ab4982019-02-26 18:37:15 +01005385 pool_free(ssl_sock_ctx_pool, ctx);
Emeric Brun46591952012-05-18 15:47:34 +02005386 return -1;
5387}
5388
5389
5390/* This is the callback which is used when an SSL handshake is pending. It
5391 * updates the FD status if it wants some polling before being called again.
5392 * It returns 0 if it fails in a fatal way or needs to poll to go further,
5393 * otherwise it returns non-zero and removes itself from the connection's
5394 * flags (the bit is provided in <flag> by the caller).
5395 */
Olivier Houchard000694c2019-05-23 14:45:12 +02005396static int ssl_sock_handshake(struct connection *conn, unsigned int flag)
Emeric Brun46591952012-05-18 15:47:34 +02005397{
Olivier Houchard66ab4982019-02-26 18:37:15 +01005398 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
Emeric Brun46591952012-05-18 15:47:34 +02005399 int ret;
5400
Willy Tarreau3c728722014-01-23 13:50:42 +01005401 if (!conn_ctrl_ready(conn))
Willy Tarreauf79c8172013-10-21 16:30:56 +02005402 return 0;
5403
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005404 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02005405 goto out_error;
5406
Willy Tarreau5db847a2019-05-09 14:13:35 +02005407#if HA_OPENSSL_VERSION_NUMBER >= 0x10101000L
Olivier Houchardc2aae742017-09-22 18:26:28 +02005408 /*
5409 * Check if we have early data. If we do, we have to read them
5410 * before SSL_do_handshake() is called, And there's no way to
5411 * detect early data, except to try to read them
5412 */
5413 if (conn->flags & CO_FL_EARLY_SSL_HS) {
Olivier Houchardf6715e72019-12-19 15:02:39 +01005414 size_t read_data = 0;
Olivier Houchardc2aae742017-09-22 18:26:28 +02005415
Olivier Houchardf6715e72019-12-19 15:02:39 +01005416 while (1) {
5417 ret = SSL_read_early_data(ctx->ssl,
5418 b_tail(&ctx->early_buf), b_room(&ctx->early_buf),
5419 &read_data);
5420 if (ret == SSL_READ_EARLY_DATA_ERROR)
5421 goto check_error;
5422 if (read_data > 0) {
5423 conn->flags |= CO_FL_EARLY_DATA;
5424 b_add(&ctx->early_buf, read_data);
5425 }
5426 if (ret == SSL_READ_EARLY_DATA_FINISH) {
5427 conn->flags &= ~CO_FL_EARLY_SSL_HS;
5428 if (!b_data(&ctx->early_buf))
5429 b_free(&ctx->early_buf);
5430 break;
5431 }
5432 }
Olivier Houchardc2aae742017-09-22 18:26:28 +02005433 }
5434#endif
Emeric Brun674b7432012-11-08 19:21:55 +01005435 /* If we use SSL_do_handshake to process a reneg initiated by
5436 * the remote peer, it sometimes returns SSL_ERROR_SSL.
5437 * Usually SSL_write and SSL_read are used and process implicitly
5438 * the reneg handshake.
5439 * Here we use SSL_peek as a workaround for reneg.
5440 */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005441 if ((conn->flags & CO_FL_CONNECTED) && SSL_renegotiate_pending(ctx->ssl)) {
Emeric Brun674b7432012-11-08 19:21:55 +01005442 char c;
5443
Olivier Houchard66ab4982019-02-26 18:37:15 +01005444 ret = SSL_peek(ctx->ssl, &c, 1);
Emeric Brun674b7432012-11-08 19:21:55 +01005445 if (ret <= 0) {
5446 /* handshake may have not been completed, let's find why */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005447 ret = SSL_get_error(ctx->ssl, ret);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005448
Emeric Brun674b7432012-11-08 19:21:55 +01005449 if (ret == SSL_ERROR_WANT_WRITE) {
5450 /* SSL handshake needs to write, L4 connection may not be ready */
Olivier Houchard03abf2d2019-05-28 10:12:02 +02005451 if (!(ctx->wait_event.events & SUB_RETRY_SEND))
Olivier Houchardea8dd942019-05-20 14:02:16 +02005452 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_SEND, &ctx->wait_event);
Emeric Brun674b7432012-11-08 19:21:55 +01005453 return 0;
5454 }
5455 else if (ret == SSL_ERROR_WANT_READ) {
5456 /* handshake may have been completed but we have
5457 * no more data to read.
5458 */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005459 if (!SSL_renegotiate_pending(ctx->ssl)) {
Emeric Brun674b7432012-11-08 19:21:55 +01005460 ret = 1;
5461 goto reneg_ok;
5462 }
5463 /* SSL handshake needs to read, L4 connection is ready */
Olivier Houchard03abf2d2019-05-28 10:12:02 +02005464 if (!(ctx->wait_event.events & SUB_RETRY_RECV))
Olivier Houchardea8dd942019-05-20 14:02:16 +02005465 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_RECV, &ctx->wait_event);
Emeric Brun674b7432012-11-08 19:21:55 +01005466 return 0;
5467 }
Willy Tarreau5db847a2019-05-09 14:13:35 +02005468#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005469 else if (ret == SSL_ERROR_WANT_ASYNC) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02005470 ssl_async_process_fds(ctx);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005471 return 0;
5472 }
5473#endif
Emeric Brun674b7432012-11-08 19:21:55 +01005474 else if (ret == SSL_ERROR_SYSCALL) {
5475 /* if errno is null, then connection was successfully established */
5476 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
5477 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Willy Tarreau20879a02012-12-03 16:32:10 +01005478 if (!conn->err_code) {
Lukas Tribus5db881f2019-07-08 14:29:15 +02005479#if defined(OPENSSL_IS_BORINGSSL) || defined(LIBRESSL_VERSION_NUMBER)
5480 /* do not handle empty handshakes in BoringSSL or LibreSSL */
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005481 conn->err_code = CO_ER_SSL_HANDSHAKE;
5482#else
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005483 int empty_handshake;
Willy Tarreau5db847a2019-05-09 14:13:35 +02005484#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL)
Lukas Tribus5db881f2019-07-08 14:29:15 +02005485 /* use SSL_get_state() in OpenSSL >= 1.1.0; SSL_state() is broken */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005486 OSSL_HANDSHAKE_STATE state = SSL_get_state((SSL *)ctx->ssl);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005487 empty_handshake = state == TLS_ST_BEFORE;
5488#else
Lukas Tribus5db881f2019-07-08 14:29:15 +02005489 /* access packet_length directly in OpenSSL <= 1.0.2; SSL_state() is broken */
5490 empty_handshake = !ctx->ssl->packet_length;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005491#endif
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005492 if (empty_handshake) {
Emeric Brun29f037d2014-04-25 19:05:36 +02005493 if (!errno) {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01005494 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emeric Brun29f037d2014-04-25 19:05:36 +02005495 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5496 else
5497 conn->err_code = CO_ER_SSL_EMPTY;
5498 }
5499 else {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01005500 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emeric Brun29f037d2014-04-25 19:05:36 +02005501 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5502 else
5503 conn->err_code = CO_ER_SSL_ABORT;
5504 }
5505 }
5506 else {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01005507 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emeric Brun29f037d2014-04-25 19:05:36 +02005508 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
Willy Tarreau20879a02012-12-03 16:32:10 +01005509 else
Emeric Brun29f037d2014-04-25 19:05:36 +02005510 conn->err_code = CO_ER_SSL_HANDSHAKE;
5511 }
Lukas Tribus5db881f2019-07-08 14:29:15 +02005512#endif /* BoringSSL or LibreSSL */
Willy Tarreau20879a02012-12-03 16:32:10 +01005513 }
Emeric Brun674b7432012-11-08 19:21:55 +01005514 goto out_error;
5515 }
5516 else {
5517 /* Fail on all other handshake errors */
5518 /* Note: OpenSSL may leave unread bytes in the socket's
5519 * buffer, causing an RST to be emitted upon close() on
5520 * TCP sockets. We first try to drain possibly pending
5521 * data to avoid this as much as possible.
5522 */
Willy Tarreaud85c4852015-03-13 00:40:28 +01005523 conn_sock_drain(conn);
Willy Tarreau20879a02012-12-03 16:32:10 +01005524 if (!conn->err_code)
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01005525 conn->err_code = (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT) ?
Willy Tarreauf51c6982014-04-25 20:02:39 +02005526 CO_ER_SSL_KILLED_HB : CO_ER_SSL_HANDSHAKE;
Emeric Brun674b7432012-11-08 19:21:55 +01005527 goto out_error;
5528 }
5529 }
5530 /* read some data: consider handshake completed */
5531 goto reneg_ok;
5532 }
Olivier Houchard66ab4982019-02-26 18:37:15 +01005533 ret = SSL_do_handshake(ctx->ssl);
Olivier Houchardc2aae742017-09-22 18:26:28 +02005534check_error:
Emeric Brun46591952012-05-18 15:47:34 +02005535 if (ret != 1) {
5536 /* handshake did not complete, let's find why */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005537 ret = SSL_get_error(ctx->ssl, ret);
Emeric Brun46591952012-05-18 15:47:34 +02005538
5539 if (ret == SSL_ERROR_WANT_WRITE) {
5540 /* SSL handshake needs to write, L4 connection may not be ready */
Olivier Houchard03abf2d2019-05-28 10:12:02 +02005541 if (!(ctx->wait_event.events & SUB_RETRY_SEND))
Olivier Houchardea8dd942019-05-20 14:02:16 +02005542 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_SEND, &ctx->wait_event);
Emeric Brun46591952012-05-18 15:47:34 +02005543 return 0;
5544 }
5545 else if (ret == SSL_ERROR_WANT_READ) {
5546 /* SSL handshake needs to read, L4 connection is ready */
Olivier Houchardea8dd942019-05-20 14:02:16 +02005547 if (!(ctx->wait_event.events & SUB_RETRY_RECV))
Olivier Houchardea8dd942019-05-20 14:02:16 +02005548 ctx->xprt->subscribe(conn, ctx->xprt_ctx,
5549 SUB_RETRY_RECV, &ctx->wait_event);
Emeric Brun46591952012-05-18 15:47:34 +02005550 return 0;
5551 }
Willy Tarreau5db847a2019-05-09 14:13:35 +02005552#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005553 else if (ret == SSL_ERROR_WANT_ASYNC) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02005554 ssl_async_process_fds(ctx);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005555 return 0;
5556 }
5557#endif
Willy Tarreau89230192012-09-28 20:22:13 +02005558 else if (ret == SSL_ERROR_SYSCALL) {
5559 /* if errno is null, then connection was successfully established */
5560 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
5561 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005562 if (!conn->err_code) {
Lukas Tribus5db881f2019-07-08 14:29:15 +02005563#if defined(OPENSSL_IS_BORINGSSL) || defined(LIBRESSL_VERSION_NUMBER)
5564 /* do not handle empty handshakes in BoringSSL or LibreSSL */
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005565 conn->err_code = CO_ER_SSL_HANDSHAKE;
5566#else
5567 int empty_handshake;
Willy Tarreau5db847a2019-05-09 14:13:35 +02005568#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL)
Lukas Tribus5db881f2019-07-08 14:29:15 +02005569 /* use SSL_get_state() in OpenSSL >= 1.1.0; SSL_state() is broken */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005570 OSSL_HANDSHAKE_STATE state = SSL_get_state(ctx->ssl);
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005571 empty_handshake = state == TLS_ST_BEFORE;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005572#else
Lukas Tribus5db881f2019-07-08 14:29:15 +02005573 /* access packet_length directly in OpenSSL <= 1.0.2; SSL_state() is broken */
5574 empty_handshake = !ctx->ssl->packet_length;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005575#endif
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005576 if (empty_handshake) {
5577 if (!errno) {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01005578 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005579 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5580 else
5581 conn->err_code = CO_ER_SSL_EMPTY;
5582 }
5583 else {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01005584 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005585 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5586 else
5587 conn->err_code = CO_ER_SSL_ABORT;
5588 }
Emeric Brun29f037d2014-04-25 19:05:36 +02005589 }
5590 else {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01005591 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emeric Brun29f037d2014-04-25 19:05:36 +02005592 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5593 else
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005594 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun29f037d2014-04-25 19:05:36 +02005595 }
Lukas Tribus5db881f2019-07-08 14:29:15 +02005596#endif /* BoringSSL or LibreSSL */
Emeric Brun29f037d2014-04-25 19:05:36 +02005597 }
Willy Tarreau89230192012-09-28 20:22:13 +02005598 goto out_error;
5599 }
Emeric Brun46591952012-05-18 15:47:34 +02005600 else {
5601 /* Fail on all other handshake errors */
Willy Tarreau566dc552012-10-19 20:52:18 +02005602 /* Note: OpenSSL may leave unread bytes in the socket's
5603 * buffer, causing an RST to be emitted upon close() on
5604 * TCP sockets. We first try to drain possibly pending
5605 * data to avoid this as much as possible.
5606 */
Willy Tarreaud85c4852015-03-13 00:40:28 +01005607 conn_sock_drain(conn);
Willy Tarreau20879a02012-12-03 16:32:10 +01005608 if (!conn->err_code)
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01005609 conn->err_code = (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT) ?
Willy Tarreauf51c6982014-04-25 20:02:39 +02005610 CO_ER_SSL_KILLED_HB : CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02005611 goto out_error;
5612 }
5613 }
Willy Tarreau5db847a2019-05-09 14:13:35 +02005614#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Olivier Houchard522eea72017-11-03 16:27:47 +01005615 else {
5616 /*
5617 * If the server refused the early data, we have to send a
5618 * 425 to the client, as we no longer have the data to sent
5619 * them again.
5620 */
5621 if ((conn->flags & CO_FL_EARLY_DATA) && (objt_server(conn->target))) {
Olivier Houchard66ab4982019-02-26 18:37:15 +01005622 if (SSL_get_early_data_status(ctx->ssl) == SSL_EARLY_DATA_REJECTED) {
Olivier Houchard522eea72017-11-03 16:27:47 +01005623 conn->err_code = CO_ER_SSL_EARLY_FAILED;
5624 goto out_error;
5625 }
5626 }
5627 }
5628#endif
5629
Emeric Brun46591952012-05-18 15:47:34 +02005630
Emeric Brun674b7432012-11-08 19:21:55 +01005631reneg_ok:
Emeric Brunb5e42a82017-06-06 12:35:14 +00005632
Willy Tarreau5db847a2019-05-09 14:13:35 +02005633#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00005634 /* ASYNC engine API doesn't support moving read/write
5635 * buffers. So we disable ASYNC mode right after
5636 * the handshake to avoid buffer oveflows.
5637 */
5638 if (global_ssl.async)
Olivier Houchard66ab4982019-02-26 18:37:15 +01005639 SSL_clear_mode(ctx->ssl, SSL_MODE_ASYNC);
Emeric Brunb5e42a82017-06-06 12:35:14 +00005640#endif
Emeric Brun46591952012-05-18 15:47:34 +02005641 /* Handshake succeeded */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005642 if (!SSL_session_reused(ctx->ssl)) {
Willy Tarreau0c9c2722014-05-28 12:28:58 +02005643 if (objt_server(conn->target)) {
5644 update_freq_ctr(&global.ssl_be_keys_per_sec, 1);
5645 if (global.ssl_be_keys_per_sec.curr_ctr > global.ssl_be_keys_max)
5646 global.ssl_be_keys_max = global.ssl_be_keys_per_sec.curr_ctr;
Emeric Brun46591952012-05-18 15:47:34 +02005647 }
Willy Tarreau0c9c2722014-05-28 12:28:58 +02005648 else {
5649 update_freq_ctr(&global.ssl_fe_keys_per_sec, 1);
5650 if (global.ssl_fe_keys_per_sec.curr_ctr > global.ssl_fe_keys_max)
5651 global.ssl_fe_keys_max = global.ssl_fe_keys_per_sec.curr_ctr;
5652 }
Emeric Brun46591952012-05-18 15:47:34 +02005653 }
5654
5655 /* The connection is now established at both layers, it's time to leave */
5656 conn->flags &= ~(flag | CO_FL_WAIT_L4_CONN | CO_FL_WAIT_L6_CONN);
5657 return 1;
5658
5659 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01005660 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02005661 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01005662 ERR_clear_error();
5663
Emeric Brun9fa89732012-10-04 17:09:56 +02005664 /* free resumed session if exists */
Willy Tarreau07d94e42018-09-20 10:57:52 +02005665 if (objt_server(conn->target) && __objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr) {
5666 free(__objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr);
5667 __objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr = NULL;
Emeric Brun9fa89732012-10-04 17:09:56 +02005668 }
5669
Emeric Brun46591952012-05-18 15:47:34 +02005670 /* Fail on all other handshake errors */
5671 conn->flags |= CO_FL_ERROR;
Willy Tarreau20879a02012-12-03 16:32:10 +01005672 if (!conn->err_code)
5673 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02005674 return 0;
5675}
5676
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005677static int ssl_subscribe(struct connection *conn, void *xprt_ctx, int event_type, void *param)
Olivier Houcharddf357842019-03-21 16:30:07 +01005678{
Olivier Houchardea8dd942019-05-20 14:02:16 +02005679 struct wait_event *sw;
5680 struct ssl_sock_ctx *ctx = xprt_ctx;
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005681
Olivier Houcharda37eb6a2019-06-24 18:57:39 +02005682 if (!ctx)
5683 return -1;
5684
Olivier Houchardea8dd942019-05-20 14:02:16 +02005685 if (event_type & SUB_RETRY_RECV) {
5686 sw = param;
5687 BUG_ON(ctx->recv_wait != NULL || (sw->events & SUB_RETRY_RECV));
5688 sw->events |= SUB_RETRY_RECV;
5689 ctx->recv_wait = sw;
5690 if (!(conn->flags & CO_FL_SSL_WAIT_HS) &&
5691 !(ctx->wait_event.events & SUB_RETRY_RECV))
5692 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_RECV, &ctx->wait_event);
5693 event_type &= ~SUB_RETRY_RECV;
5694 }
5695 if (event_type & SUB_RETRY_SEND) {
5696sw = param;
5697 BUG_ON(ctx->send_wait != NULL || (sw->events & SUB_RETRY_SEND));
5698 sw->events |= SUB_RETRY_SEND;
5699 ctx->send_wait = sw;
5700 if (!(conn->flags & CO_FL_SSL_WAIT_HS) &&
5701 !(ctx->wait_event.events & SUB_RETRY_SEND))
5702 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_SEND, &ctx->wait_event);
5703 event_type &= ~SUB_RETRY_SEND;
5704
5705 }
5706 if (event_type != 0)
5707 return -1;
5708 return 0;
Olivier Houcharddf357842019-03-21 16:30:07 +01005709}
5710
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005711static int ssl_unsubscribe(struct connection *conn, void *xprt_ctx, int event_type, void *param)
Olivier Houcharddf357842019-03-21 16:30:07 +01005712{
Olivier Houchardea8dd942019-05-20 14:02:16 +02005713 struct wait_event *sw;
5714 struct ssl_sock_ctx *ctx = xprt_ctx;
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005715
Olivier Houchardea8dd942019-05-20 14:02:16 +02005716 if (event_type & SUB_RETRY_RECV) {
5717 sw = param;
5718 BUG_ON(ctx->recv_wait != sw);
5719 ctx->recv_wait = NULL;
5720 sw->events &= ~SUB_RETRY_RECV;
5721 /* If we subscribed, and we're not doing the handshake,
5722 * then we subscribed because the upper layer asked for it,
5723 * as the upper layer is no longer interested, we can
5724 * unsubscribe too.
5725 */
5726 if (!(ctx->conn->flags & CO_FL_SSL_WAIT_HS) &&
5727 (ctx->wait_event.events & SUB_RETRY_RECV))
5728 conn_unsubscribe(conn, ctx->xprt_ctx, SUB_RETRY_RECV,
5729 &ctx->wait_event);
5730 }
5731 if (event_type & SUB_RETRY_SEND) {
5732 sw = param;
5733 BUG_ON(ctx->send_wait != sw);
5734 ctx->send_wait = NULL;
5735 sw->events &= ~SUB_RETRY_SEND;
5736 if (!(ctx->conn->flags & CO_FL_SSL_WAIT_HS) &&
5737 (ctx->wait_event.events & SUB_RETRY_SEND))
5738 conn_unsubscribe(conn, ctx->xprt_ctx, SUB_RETRY_SEND,
5739 &ctx->wait_event);
5740
5741 }
5742
5743 return 0;
Olivier Houcharddf357842019-03-21 16:30:07 +01005744}
5745
Olivier Houchard2e055482019-05-27 19:50:12 +02005746/* Use the provided XPRT as an underlying XPRT, and provide the old one.
5747 * Returns 0 on success, and non-zero on failure.
5748 */
5749static 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)
5750{
5751 struct ssl_sock_ctx *ctx = xprt_ctx;
5752
5753 if (oldxprt_ops != NULL)
5754 *oldxprt_ops = ctx->xprt;
5755 if (oldxprt_ctx != NULL)
5756 *oldxprt_ctx = ctx->xprt_ctx;
5757 ctx->xprt = toadd_ops;
5758 ctx->xprt_ctx = toadd_ctx;
5759 return 0;
5760}
5761
Olivier Houchard5149b592019-05-23 17:47:36 +02005762/* Remove the specified xprt. If if it our underlying XPRT, remove it and
5763 * return 0, otherwise just call the remove_xprt method from the underlying
5764 * XPRT.
5765 */
5766static int ssl_remove_xprt(struct connection *conn, void *xprt_ctx, void *toremove_ctx, const struct xprt_ops *newops, void *newctx)
5767{
5768 struct ssl_sock_ctx *ctx = xprt_ctx;
5769
5770 if (ctx->xprt_ctx == toremove_ctx) {
5771 ctx->xprt_ctx = newctx;
5772 ctx->xprt = newops;
5773 return 0;
5774 }
5775 return (ctx->xprt->remove_xprt(conn, ctx->xprt_ctx, toremove_ctx, newops, newctx));
5776}
5777
Olivier Houchardea8dd942019-05-20 14:02:16 +02005778static struct task *ssl_sock_io_cb(struct task *t, void *context, unsigned short state)
5779{
5780 struct ssl_sock_ctx *ctx = context;
5781
5782 /* First if we're doing an handshake, try that */
5783 if (ctx->conn->flags & CO_FL_SSL_WAIT_HS)
5784 ssl_sock_handshake(ctx->conn, CO_FL_SSL_WAIT_HS);
5785 /* If we had an error, or the handshake is done and I/O is available,
5786 * let the upper layer know.
5787 * If no mux was set up yet, and nobody subscribed, then call
5788 * xprt_done_cb() ourself if it's set, or destroy the connection,
5789 * we can't be sure conn_fd_handler() will be called again.
5790 */
5791 if ((ctx->conn->flags & CO_FL_ERROR) ||
5792 !(ctx->conn->flags & CO_FL_SSL_WAIT_HS)) {
5793 int ret = 0;
5794 int woke = 0;
5795
5796 /* On error, wake any waiter */
5797 if (ctx->recv_wait) {
5798 ctx->recv_wait->events &= ~SUB_RETRY_RECV;
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02005799 tasklet_wakeup(ctx->recv_wait->tasklet);
Olivier Houchardea8dd942019-05-20 14:02:16 +02005800 ctx->recv_wait = NULL;
5801 woke = 1;
5802 }
5803 if (ctx->send_wait) {
5804 ctx->send_wait->events &= ~SUB_RETRY_SEND;
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02005805 tasklet_wakeup(ctx->send_wait->tasklet);
Olivier Houchardea8dd942019-05-20 14:02:16 +02005806 ctx->send_wait = NULL;
5807 woke = 1;
5808 }
5809 /* If we're the first xprt for the connection, let the
5810 * upper layers know. If xprt_done_cb() is set, call it,
5811 * otherwise, we should have a mux, so call its wake
5812 * method if we didn't woke a tasklet already.
5813 */
5814 if (ctx->conn->xprt_ctx == ctx) {
5815 if (ctx->conn->xprt_done_cb)
5816 ret = ctx->conn->xprt_done_cb(ctx->conn);
5817 if (ret >= 0 && !woke && ctx->conn->mux && ctx->conn->mux->wake)
5818 ctx->conn->mux->wake(ctx->conn);
5819 return NULL;
5820 }
5821 }
Olivier Houchardf6715e72019-12-19 15:02:39 +01005822#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
5823 /* If we have early data and somebody wants to receive, let them */
5824 else if (b_data(&ctx->early_buf) && ctx->recv_wait) {
5825 ctx->recv_wait->events &= ~SUB_RETRY_RECV;
5826 tasklet_wakeup(ctx->recv_wait->tasklet);
5827 ctx->recv_wait = NULL;
5828
5829 }
5830#endif
Olivier Houchardea8dd942019-05-20 14:02:16 +02005831 return NULL;
5832}
5833
Emeric Brun46591952012-05-18 15:47:34 +02005834/* Receive up to <count> bytes from connection <conn>'s socket and store them
Willy Tarreauabf08d92014-01-14 11:31:27 +01005835 * into buffer <buf>. Only one call to recv() is performed, unless the
Emeric Brun46591952012-05-18 15:47:34 +02005836 * buffer wraps, in which case a second call may be performed. The connection's
5837 * flags are updated with whatever special event is detected (error, read0,
5838 * empty). The caller is responsible for taking care of those events and
5839 * avoiding the call if inappropriate. The function does not call the
5840 * connection's polling update function, so the caller is responsible for this.
5841 */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005842static 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 +02005843{
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005844 struct ssl_sock_ctx *ctx = xprt_ctx;
Willy Tarreaubfc4d772018-07-18 11:22:03 +02005845 ssize_t ret;
5846 size_t try, done = 0;
Emeric Brun46591952012-05-18 15:47:34 +02005847
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005848 conn_refresh_polling_flags(conn);
5849
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005850 if (!ctx)
Emeric Brun46591952012-05-18 15:47:34 +02005851 goto out_error;
5852
Olivier Houchardf6715e72019-12-19 15:02:39 +01005853#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
5854 if (b_data(&ctx->early_buf)) {
5855 try = b_contig_space(buf);
5856 if (try > b_data(&ctx->early_buf))
5857 try = b_data(&ctx->early_buf);
5858 memcpy(b_tail(buf), b_head(&ctx->early_buf), try);
5859 b_add(buf, try);
5860 b_del(&ctx->early_buf, try);
5861 if (b_data(&ctx->early_buf) == 0)
5862 b_free(&ctx->early_buf);
5863 return try;
5864 }
5865#endif
5866
Emeric Brun46591952012-05-18 15:47:34 +02005867 if (conn->flags & CO_FL_HANDSHAKE)
5868 /* a handshake was requested */
5869 return 0;
5870
Emeric Brun46591952012-05-18 15:47:34 +02005871 /* read the largest possible block. For this, we perform only one call
5872 * to recv() unless the buffer wraps and we exactly fill the first hunk,
5873 * in which case we accept to do it once again. A new attempt is made on
5874 * EINTR too.
5875 */
Willy Tarreau00b0fb92014-01-17 11:09:40 +01005876 while (count > 0) {
Olivier Houchardc2aae742017-09-22 18:26:28 +02005877
Willy Tarreau591d4452018-06-15 17:21:00 +02005878 try = b_contig_space(buf);
5879 if (!try)
5880 break;
5881
Willy Tarreauabf08d92014-01-14 11:31:27 +01005882 if (try > count)
5883 try = count;
Willy Tarreau591d4452018-06-15 17:21:00 +02005884
Olivier Houchard66ab4982019-02-26 18:37:15 +01005885 ret = SSL_read(ctx->ssl, b_tail(buf), try);
Emmanuel Hocdet510fce52019-08-05 18:04:16 +02005886
Emeric Brune1f38db2012-09-03 20:36:47 +02005887 if (conn->flags & CO_FL_ERROR) {
5888 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01005889 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02005890 }
Emeric Brun46591952012-05-18 15:47:34 +02005891 if (ret > 0) {
Olivier Houchardacd14032018-06-28 18:17:23 +02005892 b_add(buf, ret);
Emeric Brun46591952012-05-18 15:47:34 +02005893 done += ret;
Emeric Brun46591952012-05-18 15:47:34 +02005894 count -= ret;
Emeric Brun46591952012-05-18 15:47:34 +02005895 }
Emeric Brun46591952012-05-18 15:47:34 +02005896 else {
Olivier Houchard66ab4982019-02-26 18:37:15 +01005897 ret = SSL_get_error(ctx->ssl, ret);
Emeric Brun46591952012-05-18 15:47:34 +02005898 if (ret == SSL_ERROR_WANT_WRITE) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01005899 /* handshake is running, and it needs to enable write */
Emeric Brun46591952012-05-18 15:47:34 +02005900 conn->flags |= CO_FL_SSL_WAIT_HS;
Olivier Houchardea8dd942019-05-20 14:02:16 +02005901 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_SEND, &ctx->wait_event);
Willy Tarreau5db847a2019-05-09 14:13:35 +02005902#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00005903 /* Async mode can be re-enabled, because we're leaving data state.*/
5904 if (global_ssl.async)
Olivier Houchard66ab4982019-02-26 18:37:15 +01005905 SSL_set_mode(ctx->ssl, SSL_MODE_ASYNC);
Emeric Brunb5e42a82017-06-06 12:35:14 +00005906#endif
Emeric Brun46591952012-05-18 15:47:34 +02005907 break;
5908 }
5909 else if (ret == SSL_ERROR_WANT_READ) {
Olivier Houchard66ab4982019-02-26 18:37:15 +01005910 if (SSL_renegotiate_pending(ctx->ssl)) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02005911 ctx->xprt->subscribe(conn, ctx->xprt_ctx,
5912 SUB_RETRY_RECV,
5913 &ctx->wait_event);
Emeric Brun282a76a2012-11-08 18:02:56 +01005914 /* handshake is running, and it may need to re-enable read */
5915 conn->flags |= CO_FL_SSL_WAIT_HS;
Willy Tarreau5db847a2019-05-09 14:13:35 +02005916#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00005917 /* Async mode can be re-enabled, because we're leaving data state.*/
5918 if (global_ssl.async)
Olivier Houchard66ab4982019-02-26 18:37:15 +01005919 SSL_set_mode(ctx->ssl, SSL_MODE_ASYNC);
Emeric Brunb5e42a82017-06-06 12:35:14 +00005920#endif
Emeric Brun282a76a2012-11-08 18:02:56 +01005921 break;
5922 }
Emeric Brun46591952012-05-18 15:47:34 +02005923 break;
Olivier Houchardc2aae742017-09-22 18:26:28 +02005924 } else if (ret == SSL_ERROR_ZERO_RETURN)
5925 goto read0;
Christopher Faulet4ac77a92018-02-19 14:25:15 +01005926 /* For SSL_ERROR_SYSCALL, make sure to clear the error
5927 * stack before shutting down the connection for
5928 * reading. */
Olivier Houchard7e2e5052018-02-13 15:17:23 +01005929 if (ret == SSL_ERROR_SYSCALL && (!errno || errno == EAGAIN))
5930 goto clear_ssl_error;
Emeric Brun46591952012-05-18 15:47:34 +02005931 /* otherwise it's a real error */
5932 goto out_error;
5933 }
5934 }
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005935 leave:
Emeric Brun46591952012-05-18 15:47:34 +02005936 return done;
5937
Christopher Faulet4ac77a92018-02-19 14:25:15 +01005938 clear_ssl_error:
5939 /* Clear openssl global errors stack */
5940 ssl_sock_dump_errors(conn);
5941 ERR_clear_error();
Emeric Brun46591952012-05-18 15:47:34 +02005942 read0:
5943 conn_sock_read0(conn);
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005944 goto leave;
Christopher Faulet4ac77a92018-02-19 14:25:15 +01005945
Emeric Brun46591952012-05-18 15:47:34 +02005946 out_error:
Olivier Houchard7e2e5052018-02-13 15:17:23 +01005947 conn->flags |= CO_FL_ERROR;
Emeric Brun644cde02012-12-14 11:21:13 +01005948 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02005949 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01005950 ERR_clear_error();
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005951 goto leave;
Emeric Brun46591952012-05-18 15:47:34 +02005952}
5953
5954
Willy Tarreau787db9a2018-06-14 18:31:46 +02005955/* Send up to <count> pending bytes from buffer <buf> to connection <conn>'s
5956 * socket. <flags> may contain some CO_SFL_* flags to hint the system about
5957 * other pending data for example, but this flag is ignored at the moment.
Emeric Brun46591952012-05-18 15:47:34 +02005958 * Only one call to send() is performed, unless the buffer wraps, in which case
5959 * a second call may be performed. The connection's flags are updated with
5960 * whatever special event is detected (error, empty). The caller is responsible
5961 * for taking care of those events and avoiding the call if inappropriate. The
5962 * function does not call the connection's polling update function, so the caller
Willy Tarreau787db9a2018-06-14 18:31:46 +02005963 * is responsible for this. The buffer's output is not adjusted, it's up to the
5964 * caller to take care of this. It's up to the caller to update the buffer's
5965 * contents based on the return value.
Emeric Brun46591952012-05-18 15:47:34 +02005966 */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005967static 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 +02005968{
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005969 struct ssl_sock_ctx *ctx = xprt_ctx;
Willy Tarreau787db9a2018-06-14 18:31:46 +02005970 ssize_t ret;
5971 size_t try, done;
Emeric Brun46591952012-05-18 15:47:34 +02005972
5973 done = 0;
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005974 conn_refresh_polling_flags(conn);
Emeric Brun46591952012-05-18 15:47:34 +02005975
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005976 if (!ctx)
Emeric Brun46591952012-05-18 15:47:34 +02005977 goto out_error;
5978
Olivier Houchard010941f2019-05-03 20:56:19 +02005979 if (conn->flags & (CO_FL_HANDSHAKE | CO_FL_EARLY_SSL_HS))
Emeric Brun46591952012-05-18 15:47:34 +02005980 /* a handshake was requested */
5981 return 0;
5982
5983 /* send the largest possible block. For this we perform only one call
5984 * to send() unless the buffer wraps and we exactly fill the first hunk,
5985 * in which case we accept to do it once again.
5986 */
Willy Tarreau787db9a2018-06-14 18:31:46 +02005987 while (count) {
Willy Tarreau5db847a2019-05-09 14:13:35 +02005988#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Olivier Houchardc2aae742017-09-22 18:26:28 +02005989 size_t written_data;
5990#endif
5991
Willy Tarreau787db9a2018-06-14 18:31:46 +02005992 try = b_contig_data(buf, done);
5993 if (try > count)
5994 try = count;
Willy Tarreaubfd59462013-02-21 07:46:09 +01005995
Willy Tarreau7bed9452014-02-02 02:00:24 +01005996 if (!(flags & CO_SFL_STREAMER) &&
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01005997 !(ctx->xprt_st & SSL_SOCK_SEND_UNLIMITED) &&
Willy Tarreauef934602016-12-22 23:12:01 +01005998 global_ssl.max_record && try > global_ssl.max_record) {
5999 try = global_ssl.max_record;
Willy Tarreau518cedd2014-02-17 15:43:01 +01006000 }
6001 else {
6002 /* we need to keep the information about the fact that
6003 * we're not limiting the upcoming send(), because if it
6004 * fails, we'll have to retry with at least as many data.
6005 */
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006006 ctx->xprt_st |= SSL_SOCK_SEND_UNLIMITED;
Willy Tarreau518cedd2014-02-17 15:43:01 +01006007 }
Willy Tarreaubfd59462013-02-21 07:46:09 +01006008
Willy Tarreau5db847a2019-05-09 14:13:35 +02006009#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Olivier Houchard010941f2019-05-03 20:56:19 +02006010 if (!SSL_is_init_finished(ctx->ssl) && conn_is_back(conn)) {
Olivier Houchardc2aae742017-09-22 18:26:28 +02006011 unsigned int max_early;
6012
Olivier Houchard522eea72017-11-03 16:27:47 +01006013 if (objt_listener(conn->target))
Olivier Houchard66ab4982019-02-26 18:37:15 +01006014 max_early = SSL_get_max_early_data(ctx->ssl);
Olivier Houchard522eea72017-11-03 16:27:47 +01006015 else {
Olivier Houchard66ab4982019-02-26 18:37:15 +01006016 if (SSL_get0_session(ctx->ssl))
6017 max_early = SSL_SESSION_get_max_early_data(SSL_get0_session(ctx->ssl));
Olivier Houchard522eea72017-11-03 16:27:47 +01006018 else
6019 max_early = 0;
6020 }
6021
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006022 if (try + ctx->sent_early_data > max_early) {
6023 try -= (try + ctx->sent_early_data) - max_early;
Olivier Houchard522eea72017-11-03 16:27:47 +01006024 if (try <= 0) {
Olivier Houchard010941f2019-05-03 20:56:19 +02006025 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Olivier Houchard965e84e2019-06-15 20:59:30 +02006026 tasklet_wakeup(ctx->wait_event.tasklet);
Olivier Houchardc2aae742017-09-22 18:26:28 +02006027 break;
Olivier Houchard522eea72017-11-03 16:27:47 +01006028 }
Olivier Houchardc2aae742017-09-22 18:26:28 +02006029 }
Olivier Houchard66ab4982019-02-26 18:37:15 +01006030 ret = SSL_write_early_data(ctx->ssl, b_peek(buf, done), try, &written_data);
Olivier Houchardc2aae742017-09-22 18:26:28 +02006031 if (ret == 1) {
6032 ret = written_data;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006033 ctx->sent_early_data += ret;
Olivier Houchard965e84e2019-06-15 20:59:30 +02006034 if (objt_server(conn->target)) {
Olivier Houchard522eea72017-11-03 16:27:47 +01006035 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN | CO_FL_EARLY_DATA;
Olivier Houchard965e84e2019-06-15 20:59:30 +02006036 /* Initiate the handshake, now */
6037 tasklet_wakeup(ctx->wait_event.tasklet);
6038 }
Olivier Houchard522eea72017-11-03 16:27:47 +01006039
Olivier Houchardc2aae742017-09-22 18:26:28 +02006040 }
6041
6042 } else
6043#endif
Olivier Houchard66ab4982019-02-26 18:37:15 +01006044 ret = SSL_write(ctx->ssl, b_peek(buf, done), try);
Willy Tarreau518cedd2014-02-17 15:43:01 +01006045
Emeric Brune1f38db2012-09-03 20:36:47 +02006046 if (conn->flags & CO_FL_ERROR) {
6047 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01006048 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02006049 }
Emeric Brun46591952012-05-18 15:47:34 +02006050 if (ret > 0) {
Olivier Houchardf24502b2019-01-17 19:09:11 +01006051 /* A send succeeded, so we can consier ourself connected */
6052 conn->flags |= CO_FL_CONNECTED;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006053 ctx->xprt_st &= ~SSL_SOCK_SEND_UNLIMITED;
Willy Tarreau787db9a2018-06-14 18:31:46 +02006054 count -= ret;
Emeric Brun46591952012-05-18 15:47:34 +02006055 done += ret;
Emeric Brun46591952012-05-18 15:47:34 +02006056 }
6057 else {
Olivier Houchard66ab4982019-02-26 18:37:15 +01006058 ret = SSL_get_error(ctx->ssl, ret);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006059
Emeric Brun46591952012-05-18 15:47:34 +02006060 if (ret == SSL_ERROR_WANT_WRITE) {
Olivier Houchard66ab4982019-02-26 18:37:15 +01006061 if (SSL_renegotiate_pending(ctx->ssl)) {
Emeric Brun282a76a2012-11-08 18:02:56 +01006062 /* handshake is running, and it may need to re-enable write */
6063 conn->flags |= CO_FL_SSL_WAIT_HS;
Olivier Houchardea8dd942019-05-20 14:02:16 +02006064 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_SEND, &ctx->wait_event);
Willy Tarreau5db847a2019-05-09 14:13:35 +02006065#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00006066 /* Async mode can be re-enabled, because we're leaving data state.*/
6067 if (global_ssl.async)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006068 SSL_set_mode(ctx->ssl, SSL_MODE_ASYNC);
Emeric Brunb5e42a82017-06-06 12:35:14 +00006069#endif
Emeric Brun282a76a2012-11-08 18:02:56 +01006070 break;
6071 }
Olivier Houchardea8dd942019-05-20 14:02:16 +02006072
Emeric Brun46591952012-05-18 15:47:34 +02006073 break;
6074 }
6075 else if (ret == SSL_ERROR_WANT_READ) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01006076 /* handshake is running, and it needs to enable read */
Emeric Brun46591952012-05-18 15:47:34 +02006077 conn->flags |= CO_FL_SSL_WAIT_HS;
Olivier Houchardea8dd942019-05-20 14:02:16 +02006078 ctx->xprt->subscribe(conn, ctx->xprt_ctx,
6079 SUB_RETRY_RECV,
6080 &ctx->wait_event);
Willy Tarreau5db847a2019-05-09 14:13:35 +02006081#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00006082 /* Async mode can be re-enabled, because we're leaving data state.*/
6083 if (global_ssl.async)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006084 SSL_set_mode(ctx->ssl, SSL_MODE_ASYNC);
Emeric Brunb5e42a82017-06-06 12:35:14 +00006085#endif
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006086 break;
6087 }
Emeric Brun46591952012-05-18 15:47:34 +02006088 goto out_error;
6089 }
6090 }
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02006091 leave:
Emeric Brun46591952012-05-18 15:47:34 +02006092 return done;
6093
6094 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01006095 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02006096 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01006097 ERR_clear_error();
6098
Emeric Brun46591952012-05-18 15:47:34 +02006099 conn->flags |= CO_FL_ERROR;
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02006100 goto leave;
Emeric Brun46591952012-05-18 15:47:34 +02006101}
6102
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006103static void ssl_sock_close(struct connection *conn, void *xprt_ctx) {
Emeric Brun46591952012-05-18 15:47:34 +02006104
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006105 struct ssl_sock_ctx *ctx = xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006106
Olivier Houchardea8dd942019-05-20 14:02:16 +02006107
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006108 if (ctx) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02006109 if (ctx->wait_event.events != 0)
6110 ctx->xprt->unsubscribe(ctx->conn, ctx->xprt_ctx,
6111 ctx->wait_event.events,
6112 &ctx->wait_event);
6113 if (ctx->send_wait) {
6114 ctx->send_wait->events &= ~SUB_RETRY_SEND;
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02006115 tasklet_wakeup(ctx->send_wait->tasklet);
Olivier Houchardea8dd942019-05-20 14:02:16 +02006116 }
6117 if (ctx->recv_wait) {
6118 ctx->recv_wait->events &= ~SUB_RETRY_RECV;
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02006119 tasklet_wakeup(ctx->recv_wait->tasklet);
Olivier Houchardea8dd942019-05-20 14:02:16 +02006120 }
Olivier Houchard692c1d02019-05-23 18:41:47 +02006121 if (ctx->xprt->close)
6122 ctx->xprt->close(conn, ctx->xprt_ctx);
Willy Tarreau5db847a2019-05-09 14:13:35 +02006123#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brun3854e012017-05-17 20:42:48 +02006124 if (global_ssl.async) {
6125 OSSL_ASYNC_FD all_fd[32], afd;
6126 size_t num_all_fds = 0;
6127 int i;
6128
Olivier Houchard66ab4982019-02-26 18:37:15 +01006129 SSL_get_all_async_fds(ctx->ssl, NULL, &num_all_fds);
Emeric Brun3854e012017-05-17 20:42:48 +02006130 if (num_all_fds > 32) {
6131 send_log(NULL, LOG_EMERG, "haproxy: openssl returns too many async fds. It seems a bug. Process may crash\n");
6132 return;
6133 }
6134
Olivier Houchard66ab4982019-02-26 18:37:15 +01006135 SSL_get_all_async_fds(ctx->ssl, all_fd, &num_all_fds);
Emeric Brun3854e012017-05-17 20:42:48 +02006136
6137 /* If an async job is pending, we must try to
6138 to catch the end using polling before calling
6139 SSL_free */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006140 if (num_all_fds && SSL_waiting_for_async(ctx->ssl)) {
Emeric Brun3854e012017-05-17 20:42:48 +02006141 for (i=0 ; i < num_all_fds ; i++) {
6142 /* switch on an handler designed to
6143 * handle the SSL_free
6144 */
6145 afd = all_fd[i];
6146 fdtab[afd].iocb = ssl_async_fd_free;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006147 fdtab[afd].owner = ctx->ssl;
Emeric Brun3854e012017-05-17 20:42:48 +02006148 fd_want_recv(afd);
Emeric Brunce9e01c2017-05-31 10:02:53 +00006149 /* To ensure that the fd cache won't be used
6150 * and we'll catch a real RD event.
6151 */
6152 fd_cant_recv(afd);
Emeric Brun3854e012017-05-17 20:42:48 +02006153 }
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02006154 tasklet_free(ctx->wait_event.tasklet);
Olivier Houchard66ab4982019-02-26 18:37:15 +01006155 pool_free(ssl_sock_ctx_pool, ctx);
Olivier Houchard2be5a4c2019-03-08 18:54:43 +01006156 _HA_ATOMIC_ADD(&jobs, 1);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006157 return;
6158 }
Emeric Brun3854e012017-05-17 20:42:48 +02006159 /* Else we can remove the fds from the fdtab
6160 * and call SSL_free.
6161 * note: we do a fd_remove and not a delete
6162 * because the fd is owned by the engine.
6163 * the engine is responsible to close
6164 */
6165 for (i=0 ; i < num_all_fds ; i++)
6166 fd_remove(all_fd[i]);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006167 }
6168#endif
Olivier Houchard66ab4982019-02-26 18:37:15 +01006169 SSL_free(ctx->ssl);
Olivier Houchardf6715e72019-12-19 15:02:39 +01006170 b_free(&ctx->early_buf);
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02006171 tasklet_free(ctx->wait_event.tasklet);
Olivier Houchard66ab4982019-02-26 18:37:15 +01006172 pool_free(ssl_sock_ctx_pool, ctx);
Olivier Houchard2be5a4c2019-03-08 18:54:43 +01006173 _HA_ATOMIC_SUB(&sslconns, 1);
Emeric Brun46591952012-05-18 15:47:34 +02006174 }
Emeric Brun46591952012-05-18 15:47:34 +02006175}
6176
6177/* This function tries to perform a clean shutdown on an SSL connection, and in
6178 * any case, flags the connection as reusable if no handshake was in progress.
6179 */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006180static void ssl_sock_shutw(struct connection *conn, void *xprt_ctx, int clean)
Emeric Brun46591952012-05-18 15:47:34 +02006181{
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006182 struct ssl_sock_ctx *ctx = xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006183
Emeric Brun46591952012-05-18 15:47:34 +02006184 if (conn->flags & CO_FL_HANDSHAKE)
6185 return;
Emmanuel Hocdet405ff312017-01-08 14:07:39 +01006186 if (!clean)
6187 /* don't sent notify on SSL_shutdown */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006188 SSL_set_quiet_shutdown(ctx->ssl, 1);
Emeric Brun46591952012-05-18 15:47:34 +02006189 /* no handshake was in progress, try a clean ssl shutdown */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006190 if (SSL_shutdown(ctx->ssl) <= 0) {
Emeric Brun644cde02012-12-14 11:21:13 +01006191 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02006192 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01006193 ERR_clear_error();
6194 }
Emeric Brun46591952012-05-18 15:47:34 +02006195}
6196
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01006197/* used for ppv2 pkey alog (can be used for logging) */
Willy Tarreau83061a82018-07-13 11:56:34 +02006198int ssl_sock_get_pkey_algo(struct connection *conn, struct buffer *out)
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01006199{
Christopher Faulet4517b0c2019-09-10 10:12:03 +02006200 struct ssl_sock_ctx *ctx;
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01006201 struct pkey_info *pkinfo;
6202 int bits = 0;
6203 int sig = TLSEXT_signature_anonymous;
6204 int len = -1;
6205
6206 if (!ssl_sock_is_ssl(conn))
6207 return 0;
Christopher Faulet4517b0c2019-09-10 10:12:03 +02006208 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006209 pkinfo = SSL_CTX_get_ex_data(SSL_get_SSL_CTX(ctx->ssl), ssl_pkey_info_index);
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01006210 if (pkinfo) {
6211 sig = pkinfo->sig;
6212 bits = pkinfo->bits;
6213 } else {
6214 /* multicert and generated cert have no pkey info */
6215 X509 *crt;
6216 EVP_PKEY *pkey;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006217 crt = SSL_get_certificate(ctx->ssl);
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01006218 if (!crt)
6219 return 0;
6220 pkey = X509_get_pubkey(crt);
6221 if (pkey) {
6222 bits = EVP_PKEY_bits(pkey);
6223 switch(EVP_PKEY_base_id(pkey)) {
6224 case EVP_PKEY_RSA:
6225 sig = TLSEXT_signature_rsa;
6226 break;
6227 case EVP_PKEY_EC:
6228 sig = TLSEXT_signature_ecdsa;
6229 break;
6230 case EVP_PKEY_DSA:
6231 sig = TLSEXT_signature_dsa;
6232 break;
6233 }
6234 EVP_PKEY_free(pkey);
6235 }
6236 }
6237
6238 switch(sig) {
6239 case TLSEXT_signature_rsa:
6240 len = chunk_printf(out, "RSA%d", bits);
6241 break;
6242 case TLSEXT_signature_ecdsa:
6243 len = chunk_printf(out, "EC%d", bits);
6244 break;
6245 case TLSEXT_signature_dsa:
6246 len = chunk_printf(out, "DSA%d", bits);
6247 break;
6248 default:
6249 return 0;
6250 }
6251 if (len < 0)
6252 return 0;
6253 return 1;
6254}
6255
Emmanuel Hocdet283e0042017-11-02 14:05:23 +01006256/* used for ppv2 cert signature (can be used for logging) */
6257const char *ssl_sock_get_cert_sig(struct connection *conn)
6258{
Christopher Faulet4517b0c2019-09-10 10:12:03 +02006259 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006260
Emmanuel Hocdet283e0042017-11-02 14:05:23 +01006261 __OPENSSL_110_CONST__ ASN1_OBJECT *algorithm;
6262 X509 *crt;
6263
6264 if (!ssl_sock_is_ssl(conn))
6265 return NULL;
Christopher Faulet4517b0c2019-09-10 10:12:03 +02006266 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006267 crt = SSL_get_certificate(ctx->ssl);
Emmanuel Hocdet283e0042017-11-02 14:05:23 +01006268 if (!crt)
6269 return NULL;
6270 X509_ALGOR_get0(&algorithm, NULL, NULL, X509_get0_tbs_sigalg(crt));
6271 return OBJ_nid2sn(OBJ_obj2nid(algorithm));
6272}
6273
Emmanuel Hocdet253c3b72018-02-01 18:29:59 +01006274/* used for ppv2 authority */
6275const char *ssl_sock_get_sni(struct connection *conn)
6276{
6277#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Christopher Faulet4517b0c2019-09-10 10:12:03 +02006278 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006279
Emmanuel Hocdet253c3b72018-02-01 18:29:59 +01006280 if (!ssl_sock_is_ssl(conn))
6281 return NULL;
Christopher Faulet4517b0c2019-09-10 10:12:03 +02006282 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006283 return SSL_get_servername(ctx->ssl, TLSEXT_NAMETYPE_host_name);
Emmanuel Hocdet253c3b72018-02-01 18:29:59 +01006284#else
Olivier Houchard66ab4982019-02-26 18:37:15 +01006285 return NULL;
Emmanuel Hocdet253c3b72018-02-01 18:29:59 +01006286#endif
6287}
6288
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02006289/* used for logging/ppv2, may be changed for a sample fetch later */
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02006290const char *ssl_sock_get_cipher_name(struct connection *conn)
6291{
Christopher Faulet4517b0c2019-09-10 10:12:03 +02006292 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006293
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02006294 if (!ssl_sock_is_ssl(conn))
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02006295 return NULL;
Christopher Faulet4517b0c2019-09-10 10:12:03 +02006296 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006297 return SSL_get_cipher_name(ctx->ssl);
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02006298}
6299
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02006300/* used for logging/ppv2, may be changed for a sample fetch later */
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02006301const char *ssl_sock_get_proto_version(struct connection *conn)
6302{
Christopher Faulet4517b0c2019-09-10 10:12:03 +02006303 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006304
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02006305 if (!ssl_sock_is_ssl(conn))
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02006306 return NULL;
Christopher Faulet4517b0c2019-09-10 10:12:03 +02006307 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006308 return SSL_get_version(ctx->ssl);
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02006309}
6310
Willy Tarreau8d598402012-10-22 17:58:39 +02006311/* Extract a serial from a cert, and copy it to a chunk.
6312 * Returns 1 if serial is found and copied, 0 if no serial found and
6313 * -1 if output is not large enough.
6314 */
6315static int
Willy Tarreau83061a82018-07-13 11:56:34 +02006316ssl_sock_get_serial(X509 *crt, struct buffer *out)
Willy Tarreau8d598402012-10-22 17:58:39 +02006317{
6318 ASN1_INTEGER *serial;
6319
6320 serial = X509_get_serialNumber(crt);
6321 if (!serial)
6322 return 0;
6323
6324 if (out->size < serial->length)
6325 return -1;
6326
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006327 memcpy(out->area, serial->data, serial->length);
6328 out->data = serial->length;
Willy Tarreau8d598402012-10-22 17:58:39 +02006329 return 1;
6330}
6331
Emeric Brun43e79582014-10-29 19:03:26 +01006332/* Extract a cert to der, and copy it to a chunk.
Joseph Herlant017b3da2018-11-15 09:07:59 -08006333 * Returns 1 if the cert is found and copied, 0 on der conversion failure
6334 * and -1 if the output is not large enough.
Emeric Brun43e79582014-10-29 19:03:26 +01006335 */
6336static int
Willy Tarreau83061a82018-07-13 11:56:34 +02006337ssl_sock_crt2der(X509 *crt, struct buffer *out)
Emeric Brun43e79582014-10-29 19:03:26 +01006338{
6339 int len;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006340 unsigned char *p = (unsigned char *) out->area;;
Emeric Brun43e79582014-10-29 19:03:26 +01006341
6342 len =i2d_X509(crt, NULL);
6343 if (len <= 0)
6344 return 1;
6345
6346 if (out->size < len)
6347 return -1;
6348
6349 i2d_X509(crt,&p);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006350 out->data = len;
Emeric Brun43e79582014-10-29 19:03:26 +01006351 return 1;
6352}
6353
Emeric Brunce5ad802012-10-22 14:11:22 +02006354
Willy Tarreau83061a82018-07-13 11:56:34 +02006355/* Copy Date in ASN1_UTCTIME format in struct buffer out.
Emeric Brunce5ad802012-10-22 14:11:22 +02006356 * Returns 1 if serial is found and copied, 0 if no valid time found
6357 * and -1 if output is not large enough.
6358 */
6359static int
Willy Tarreau83061a82018-07-13 11:56:34 +02006360ssl_sock_get_time(ASN1_TIME *tm, struct buffer *out)
Emeric Brunce5ad802012-10-22 14:11:22 +02006361{
6362 if (tm->type == V_ASN1_GENERALIZEDTIME) {
6363 ASN1_GENERALIZEDTIME *gentm = (ASN1_GENERALIZEDTIME *)tm;
6364
6365 if (gentm->length < 12)
6366 return 0;
6367 if (gentm->data[0] != 0x32 || gentm->data[1] != 0x30)
6368 return 0;
6369 if (out->size < gentm->length-2)
6370 return -1;
6371
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006372 memcpy(out->area, gentm->data+2, gentm->length-2);
6373 out->data = gentm->length-2;
Emeric Brunce5ad802012-10-22 14:11:22 +02006374 return 1;
6375 }
6376 else if (tm->type == V_ASN1_UTCTIME) {
6377 ASN1_UTCTIME *utctm = (ASN1_UTCTIME *)tm;
6378
6379 if (utctm->length < 10)
6380 return 0;
6381 if (utctm->data[0] >= 0x35)
6382 return 0;
6383 if (out->size < utctm->length)
6384 return -1;
6385
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006386 memcpy(out->area, utctm->data, utctm->length);
6387 out->data = utctm->length;
Emeric Brunce5ad802012-10-22 14:11:22 +02006388 return 1;
6389 }
6390
6391 return 0;
6392}
6393
Emeric Brun87855892012-10-17 17:39:35 +02006394/* Extract an entry from a X509_NAME and copy its value to an output chunk.
6395 * Returns 1 if entry found, 0 if entry not found, or -1 if output not large enough.
6396 */
6397static int
Willy Tarreau83061a82018-07-13 11:56:34 +02006398ssl_sock_get_dn_entry(X509_NAME *a, const struct buffer *entry, int pos,
6399 struct buffer *out)
Emeric Brun87855892012-10-17 17:39:35 +02006400{
6401 X509_NAME_ENTRY *ne;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006402 ASN1_OBJECT *obj;
6403 ASN1_STRING *data;
6404 const unsigned char *data_ptr;
6405 int data_len;
Emeric Brun87855892012-10-17 17:39:35 +02006406 int i, j, n;
6407 int cur = 0;
6408 const char *s;
6409 char tmp[128];
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006410 int name_count;
6411
6412 name_count = X509_NAME_entry_count(a);
Emeric Brun87855892012-10-17 17:39:35 +02006413
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006414 out->data = 0;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006415 for (i = 0; i < name_count; i++) {
Emeric Brun87855892012-10-17 17:39:35 +02006416 if (pos < 0)
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006417 j = (name_count-1) - i;
Emeric Brun87855892012-10-17 17:39:35 +02006418 else
6419 j = i;
6420
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006421 ne = X509_NAME_get_entry(a, j);
6422 obj = X509_NAME_ENTRY_get_object(ne);
6423 data = X509_NAME_ENTRY_get_data(ne);
6424 data_ptr = ASN1_STRING_get0_data(data);
6425 data_len = ASN1_STRING_length(data);
6426 n = OBJ_obj2nid(obj);
Emeric Brun87855892012-10-17 17:39:35 +02006427 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006428 i2t_ASN1_OBJECT(tmp, sizeof(tmp), obj);
Emeric Brun87855892012-10-17 17:39:35 +02006429 s = tmp;
6430 }
6431
6432 if (chunk_strcasecmp(entry, s) != 0)
6433 continue;
6434
6435 if (pos < 0)
6436 cur--;
6437 else
6438 cur++;
6439
6440 if (cur != pos)
6441 continue;
6442
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006443 if (data_len > out->size)
Emeric Brun87855892012-10-17 17:39:35 +02006444 return -1;
6445
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006446 memcpy(out->area, data_ptr, data_len);
6447 out->data = data_len;
Emeric Brun87855892012-10-17 17:39:35 +02006448 return 1;
6449 }
6450
6451 return 0;
6452
6453}
6454
6455/* Extract and format full DN from a X509_NAME and copy result into a chunk
6456 * Returns 1 if dn entries exits, 0 if no dn entry found or -1 if output is not large enough.
6457 */
6458static int
Willy Tarreau83061a82018-07-13 11:56:34 +02006459ssl_sock_get_dn_oneline(X509_NAME *a, struct buffer *out)
Emeric Brun87855892012-10-17 17:39:35 +02006460{
6461 X509_NAME_ENTRY *ne;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006462 ASN1_OBJECT *obj;
6463 ASN1_STRING *data;
6464 const unsigned char *data_ptr;
6465 int data_len;
Emeric Brun87855892012-10-17 17:39:35 +02006466 int i, n, ln;
6467 int l = 0;
6468 const char *s;
6469 char *p;
6470 char tmp[128];
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006471 int name_count;
6472
6473
6474 name_count = X509_NAME_entry_count(a);
Emeric Brun87855892012-10-17 17:39:35 +02006475
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006476 out->data = 0;
6477 p = out->area;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006478 for (i = 0; i < name_count; i++) {
6479 ne = X509_NAME_get_entry(a, i);
6480 obj = X509_NAME_ENTRY_get_object(ne);
6481 data = X509_NAME_ENTRY_get_data(ne);
6482 data_ptr = ASN1_STRING_get0_data(data);
6483 data_len = ASN1_STRING_length(data);
6484 n = OBJ_obj2nid(obj);
Emeric Brun87855892012-10-17 17:39:35 +02006485 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006486 i2t_ASN1_OBJECT(tmp, sizeof(tmp), obj);
Emeric Brun87855892012-10-17 17:39:35 +02006487 s = tmp;
6488 }
6489 ln = strlen(s);
6490
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006491 l += 1 + ln + 1 + data_len;
Emeric Brun87855892012-10-17 17:39:35 +02006492 if (l > out->size)
6493 return -1;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006494 out->data = l;
Emeric Brun87855892012-10-17 17:39:35 +02006495
6496 *(p++)='/';
6497 memcpy(p, s, ln);
6498 p += ln;
6499 *(p++)='=';
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006500 memcpy(p, data_ptr, data_len);
6501 p += data_len;
Emeric Brun87855892012-10-17 17:39:35 +02006502 }
6503
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006504 if (!out->data)
Emeric Brun87855892012-10-17 17:39:35 +02006505 return 0;
6506
6507 return 1;
6508}
6509
Olivier Houchardab28a322018-12-21 19:45:40 +01006510void ssl_sock_set_alpn(struct connection *conn, const unsigned char *alpn, int len)
6511{
6512#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Christopher Faulet4517b0c2019-09-10 10:12:03 +02006513 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006514
Olivier Houchardaa2ecea2019-06-28 14:10:33 +02006515 if (!ssl_sock_is_ssl(conn))
6516 return;
Christopher Faulet4517b0c2019-09-10 10:12:03 +02006517 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006518 SSL_set_alpn_protos(ctx->ssl, alpn, len);
Olivier Houchardab28a322018-12-21 19:45:40 +01006519#endif
6520}
6521
Willy Tarreau119a4082016-12-22 21:58:38 +01006522/* Sets advertised SNI for outgoing connections. Please set <hostname> to NULL
6523 * to disable SNI.
6524 */
Willy Tarreau63076412015-07-10 11:33:32 +02006525void ssl_sock_set_servername(struct connection *conn, const char *hostname)
6526{
6527#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Christopher Faulet4517b0c2019-09-10 10:12:03 +02006528 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006529
Willy Tarreau119a4082016-12-22 21:58:38 +01006530 char *prev_name;
6531
Willy Tarreau63076412015-07-10 11:33:32 +02006532 if (!ssl_sock_is_ssl(conn))
6533 return;
Christopher Faulet4517b0c2019-09-10 10:12:03 +02006534 ctx = conn->xprt_ctx;
Willy Tarreau63076412015-07-10 11:33:32 +02006535
Willy Tarreau119a4082016-12-22 21:58:38 +01006536 /* if the SNI changes, we must destroy the reusable context so that a
6537 * new connection will present a new SNI. As an optimization we could
6538 * later imagine having a small cache of ssl_ctx to hold a few SNI per
6539 * server.
6540 */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006541 prev_name = (char *)SSL_get_servername(ctx->ssl, TLSEXT_NAMETYPE_host_name);
Willy Tarreau119a4082016-12-22 21:58:38 +01006542 if ((!prev_name && hostname) ||
6543 (prev_name && (!hostname || strcmp(hostname, prev_name) != 0)))
Olivier Houchard66ab4982019-02-26 18:37:15 +01006544 SSL_set_session(ctx->ssl, NULL);
Willy Tarreau119a4082016-12-22 21:58:38 +01006545
Olivier Houchard66ab4982019-02-26 18:37:15 +01006546 SSL_set_tlsext_host_name(ctx->ssl, hostname);
Willy Tarreau63076412015-07-10 11:33:32 +02006547#endif
6548}
6549
Emeric Brun0abf8362014-06-24 18:26:41 +02006550/* Extract peer certificate's common name into the chunk dest
6551 * Returns
6552 * the len of the extracted common name
6553 * or 0 if no CN found in DN
6554 * or -1 on error case (i.e. no peer certificate)
6555 */
Willy Tarreau83061a82018-07-13 11:56:34 +02006556int ssl_sock_get_remote_common_name(struct connection *conn,
6557 struct buffer *dest)
David Safb76832014-05-08 23:42:08 -04006558{
Christopher Faulet4517b0c2019-09-10 10:12:03 +02006559 struct ssl_sock_ctx *ctx;
David Safb76832014-05-08 23:42:08 -04006560 X509 *crt = NULL;
6561 X509_NAME *name;
David Safb76832014-05-08 23:42:08 -04006562 const char find_cn[] = "CN";
Willy Tarreau83061a82018-07-13 11:56:34 +02006563 const struct buffer find_cn_chunk = {
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006564 .area = (char *)&find_cn,
6565 .data = sizeof(find_cn)-1
David Safb76832014-05-08 23:42:08 -04006566 };
Emeric Brun0abf8362014-06-24 18:26:41 +02006567 int result = -1;
David Safb76832014-05-08 23:42:08 -04006568
6569 if (!ssl_sock_is_ssl(conn))
Emeric Brun0abf8362014-06-24 18:26:41 +02006570 goto out;
Christopher Faulet4517b0c2019-09-10 10:12:03 +02006571 ctx = conn->xprt_ctx;
David Safb76832014-05-08 23:42:08 -04006572
6573 /* SSL_get_peer_certificate, it increase X509 * ref count */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006574 crt = SSL_get_peer_certificate(ctx->ssl);
David Safb76832014-05-08 23:42:08 -04006575 if (!crt)
6576 goto out;
6577
6578 name = X509_get_subject_name(crt);
6579 if (!name)
6580 goto out;
David Safb76832014-05-08 23:42:08 -04006581
Emeric Brun0abf8362014-06-24 18:26:41 +02006582 result = ssl_sock_get_dn_entry(name, &find_cn_chunk, 1, dest);
6583out:
David Safb76832014-05-08 23:42:08 -04006584 if (crt)
6585 X509_free(crt);
6586
6587 return result;
6588}
6589
Dave McCowan328fb582014-07-30 10:39:13 -04006590/* returns 1 if client passed a certificate for this session, 0 if not */
6591int ssl_sock_get_cert_used_sess(struct connection *conn)
6592{
Christopher Faulet4517b0c2019-09-10 10:12:03 +02006593 struct ssl_sock_ctx *ctx;
Dave McCowan328fb582014-07-30 10:39:13 -04006594 X509 *crt = NULL;
6595
6596 if (!ssl_sock_is_ssl(conn))
6597 return 0;
Christopher Faulet4517b0c2019-09-10 10:12:03 +02006598 ctx = conn->xprt_ctx;
Dave McCowan328fb582014-07-30 10:39:13 -04006599
6600 /* SSL_get_peer_certificate, it increase X509 * ref count */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006601 crt = SSL_get_peer_certificate(ctx->ssl);
Dave McCowan328fb582014-07-30 10:39:13 -04006602 if (!crt)
6603 return 0;
6604
6605 X509_free(crt);
6606 return 1;
6607}
6608
6609/* returns 1 if client passed a certificate for this connection, 0 if not */
6610int ssl_sock_get_cert_used_conn(struct connection *conn)
David Safb76832014-05-08 23:42:08 -04006611{
Christopher Faulet4517b0c2019-09-10 10:12:03 +02006612 struct ssl_sock_ctx *ctx;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006613
David Safb76832014-05-08 23:42:08 -04006614 if (!ssl_sock_is_ssl(conn))
6615 return 0;
Christopher Faulet4517b0c2019-09-10 10:12:03 +02006616 ctx = conn->xprt_ctx;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006617 return SSL_SOCK_ST_FL_VERIFY_DONE & ctx->xprt_st ? 1 : 0;
David Safb76832014-05-08 23:42:08 -04006618}
6619
6620/* returns result from SSL verify */
6621unsigned int ssl_sock_get_verify_result(struct connection *conn)
6622{
Christopher Faulet4517b0c2019-09-10 10:12:03 +02006623 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006624
David Safb76832014-05-08 23:42:08 -04006625 if (!ssl_sock_is_ssl(conn))
6626 return (unsigned int)X509_V_ERR_APPLICATION_VERIFICATION;
Christopher Faulet4517b0c2019-09-10 10:12:03 +02006627 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006628 return (unsigned int)SSL_get_verify_result(ctx->ssl);
David Safb76832014-05-08 23:42:08 -04006629}
6630
Willy Tarreau8743f7e2016-12-04 18:44:29 +01006631/* Returns the application layer protocol name in <str> and <len> when known.
6632 * Zero is returned if the protocol name was not found, otherwise non-zero is
6633 * returned. The string is allocated in the SSL context and doesn't have to be
6634 * freed by the caller. NPN is also checked if available since older versions
6635 * of openssl (1.0.1) which are more common in field only support this one.
6636 */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006637static int ssl_sock_get_alpn(const struct connection *conn, void *xprt_ctx, const char **str, int *len)
Willy Tarreau8743f7e2016-12-04 18:44:29 +01006638{
Olivier Houchard66ab4982019-02-26 18:37:15 +01006639#if defined(TLSEXT_TYPE_application_layer_protocol_negotiation) || \
6640 defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006641 struct ssl_sock_ctx *ctx = xprt_ctx;
6642 if (!ctx)
Willy Tarreau8743f7e2016-12-04 18:44:29 +01006643 return 0;
6644
6645 *str = NULL;
6646
6647#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Olivier Houchard66ab4982019-02-26 18:37:15 +01006648 SSL_get0_alpn_selected(ctx->ssl, (const unsigned char **)str, (unsigned *)len);
Willy Tarreau8743f7e2016-12-04 18:44:29 +01006649 if (*str)
6650 return 1;
6651#endif
Bernard Spil13c53f82018-02-15 13:34:58 +01006652#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006653 SSL_get0_next_proto_negotiated(ctx->ssl, (const unsigned char **)str, (unsigned *)len);
Willy Tarreau8743f7e2016-12-04 18:44:29 +01006654 if (*str)
6655 return 1;
6656#endif
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006657#endif
Willy Tarreau8743f7e2016-12-04 18:44:29 +01006658 return 0;
6659}
6660
Willy Tarreau7875d092012-09-10 08:20:03 +02006661/***** Below are some sample fetching functions for ACL/patterns *****/
6662
Olivier Houchardccaa7de2017-10-02 11:51:03 +02006663static int
6664smp_fetch_ssl_fc_has_early(const struct arg *args, struct sample *smp, const char *kw, void *private)
6665{
6666 struct connection *conn;
6667
6668 conn = objt_conn(smp->sess->origin);
6669 if (!conn || conn->xprt != &ssl_sock)
6670 return 0;
6671
6672 smp->flags = 0;
6673 smp->data.type = SMP_T_BOOL;
Emmanuel Hocdetbb8643c2019-08-07 14:44:49 +02006674#ifdef OPENSSL_IS_BORINGSSL
6675 {
6676 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
6677 smp->data.u.sint = (SSL_in_early_data(ctx->ssl) &&
6678 SSL_early_data_accepted(ctx->ssl));
6679 }
6680#else
Olivier Houchard25ae45a2017-11-29 19:51:19 +01006681 smp->data.u.sint = ((conn->flags & CO_FL_EARLY_DATA) &&
Olivier Houchard629693f2020-01-23 14:57:36 +01006682 (conn->flags & (CO_FL_EARLY_SSL_HS | CO_FL_SSL_WAIT_HS))) ? 1 : 0;
Emmanuel Hocdetbb8643c2019-08-07 14:44:49 +02006683#endif
Olivier Houchardccaa7de2017-10-02 11:51:03 +02006684 return 1;
6685}
6686
Emeric Brune64aef12012-09-21 13:15:06 +02006687/* boolean, returns true if client cert was present */
6688static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006689smp_fetch_ssl_fc_has_crt(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brune64aef12012-09-21 13:15:06 +02006690{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006691 struct connection *conn;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006692 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006693
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006694 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006695 if (!conn || conn->xprt != &ssl_sock)
Emeric Brune64aef12012-09-21 13:15:06 +02006696 return 0;
6697
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006698 ctx = conn->xprt_ctx;
6699
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006700 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brune64aef12012-09-21 13:15:06 +02006701 smp->flags |= SMP_F_MAY_CHANGE;
6702 return 0;
6703 }
6704
6705 smp->flags = 0;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006706 smp->data.type = SMP_T_BOOL;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006707 smp->data.u.sint = SSL_SOCK_ST_FL_VERIFY_DONE & ctx->xprt_st ? 1 : 0;
Emeric Brune64aef12012-09-21 13:15:06 +02006708
6709 return 1;
6710}
6711
Emeric Brun43e79582014-10-29 19:03:26 +01006712/* binary, returns a certificate in a binary chunk (der/raw).
6713 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6714 * should be use.
6715 */
6716static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006717smp_fetch_ssl_x_der(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun43e79582014-10-29 19:03:26 +01006718{
6719 int cert_peer = (kw[4] == 'c') ? 1 : 0;
6720 X509 *crt = NULL;
6721 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02006722 struct buffer *smp_trash;
Emeric Brun43e79582014-10-29 19:03:26 +01006723 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006724 struct ssl_sock_ctx *ctx;
Emeric Brun43e79582014-10-29 19:03:26 +01006725
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006726 conn = objt_conn(smp->sess->origin);
Emeric Brun43e79582014-10-29 19:03:26 +01006727 if (!conn || conn->xprt != &ssl_sock)
6728 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006729 ctx = conn->xprt_ctx;
Emeric Brun43e79582014-10-29 19:03:26 +01006730
6731 if (!(conn->flags & CO_FL_CONNECTED)) {
6732 smp->flags |= SMP_F_MAY_CHANGE;
6733 return 0;
6734 }
6735
6736 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006737 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brun43e79582014-10-29 19:03:26 +01006738 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01006739 crt = SSL_get_certificate(ctx->ssl);
Emeric Brun43e79582014-10-29 19:03:26 +01006740
6741 if (!crt)
6742 goto out;
6743
6744 smp_trash = get_trash_chunk();
6745 if (ssl_sock_crt2der(crt, smp_trash) <= 0)
6746 goto out;
6747
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006748 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006749 smp->data.type = SMP_T_BIN;
Emeric Brun43e79582014-10-29 19:03:26 +01006750 ret = 1;
6751out:
6752 /* SSL_get_peer_certificate, it increase X509 * ref count */
6753 if (cert_peer && crt)
6754 X509_free(crt);
6755 return ret;
6756}
6757
Emeric Brunba841a12014-04-30 17:05:08 +02006758/* binary, returns serial of certificate in a binary chunk.
6759 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6760 * should be use.
6761 */
Willy Tarreau8d598402012-10-22 17:58:39 +02006762static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006763smp_fetch_ssl_x_serial(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau8d598402012-10-22 17:58:39 +02006764{
Emeric Brunba841a12014-04-30 17:05:08 +02006765 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Willy Tarreau8d598402012-10-22 17:58:39 +02006766 X509 *crt = NULL;
6767 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02006768 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006769 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006770 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006771
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006772 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006773 if (!conn || conn->xprt != &ssl_sock)
Willy Tarreau8d598402012-10-22 17:58:39 +02006774 return 0;
6775
Olivier Houchard66ab4982019-02-26 18:37:15 +01006776 ctx = conn->xprt_ctx;
6777
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006778 if (!(conn->flags & CO_FL_CONNECTED)) {
Willy Tarreau8d598402012-10-22 17:58:39 +02006779 smp->flags |= SMP_F_MAY_CHANGE;
6780 return 0;
6781 }
6782
Emeric Brunba841a12014-04-30 17:05:08 +02006783 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006784 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02006785 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01006786 crt = SSL_get_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02006787
Willy Tarreau8d598402012-10-22 17:58:39 +02006788 if (!crt)
6789 goto out;
6790
Willy Tarreau47ca5452012-12-23 20:22:19 +01006791 smp_trash = get_trash_chunk();
Willy Tarreau8d598402012-10-22 17:58:39 +02006792 if (ssl_sock_get_serial(crt, smp_trash) <= 0)
6793 goto out;
6794
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006795 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006796 smp->data.type = SMP_T_BIN;
Willy Tarreau8d598402012-10-22 17:58:39 +02006797 ret = 1;
6798out:
Emeric Brunba841a12014-04-30 17:05:08 +02006799 /* SSL_get_peer_certificate, it increase X509 * ref count */
6800 if (cert_peer && crt)
Willy Tarreau8d598402012-10-22 17:58:39 +02006801 X509_free(crt);
6802 return ret;
6803}
Emeric Brune64aef12012-09-21 13:15:06 +02006804
Emeric Brunba841a12014-04-30 17:05:08 +02006805/* binary, returns the client certificate's SHA-1 fingerprint (SHA-1 hash of DER-encoded certificate) in a binary chunk.
6806 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6807 * should be use.
6808 */
James Votha051b4a2013-05-14 20:37:59 +02006809static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006810smp_fetch_ssl_x_sha1(const struct arg *args, struct sample *smp, const char *kw, void *private)
James Votha051b4a2013-05-14 20:37:59 +02006811{
Emeric Brunba841a12014-04-30 17:05:08 +02006812 int cert_peer = (kw[4] == 'c') ? 1 : 0;
James Votha051b4a2013-05-14 20:37:59 +02006813 X509 *crt = NULL;
6814 const EVP_MD *digest;
6815 int ret = 0;
Willy Tarreau767e8ad2020-02-25 08:59:23 +01006816 unsigned int len = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02006817 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006818 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006819 struct ssl_sock_ctx *ctx;
James Votha051b4a2013-05-14 20:37:59 +02006820
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006821 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006822 if (!conn || conn->xprt != &ssl_sock)
6823 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006824 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006825
6826 if (!(conn->flags & CO_FL_CONNECTED)) {
James Votha051b4a2013-05-14 20:37:59 +02006827 smp->flags |= SMP_F_MAY_CHANGE;
6828 return 0;
6829 }
6830
Emeric Brunba841a12014-04-30 17:05:08 +02006831 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006832 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02006833 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01006834 crt = SSL_get_certificate(ctx->ssl);
James Votha051b4a2013-05-14 20:37:59 +02006835 if (!crt)
6836 goto out;
6837
6838 smp_trash = get_trash_chunk();
6839 digest = EVP_sha1();
Willy Tarreau767e8ad2020-02-25 08:59:23 +01006840 X509_digest(crt, digest, (unsigned char *) smp_trash->area, &len);
6841 smp_trash->data = len;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006842 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006843 smp->data.type = SMP_T_BIN;
James Votha051b4a2013-05-14 20:37:59 +02006844 ret = 1;
6845out:
Emeric Brunba841a12014-04-30 17:05:08 +02006846 /* SSL_get_peer_certificate, it increase X509 * ref count */
6847 if (cert_peer && crt)
James Votha051b4a2013-05-14 20:37:59 +02006848 X509_free(crt);
6849 return ret;
6850}
6851
Emeric Brunba841a12014-04-30 17:05:08 +02006852/* string, returns certificate's notafter date in ASN1_UTCTIME format.
6853 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6854 * should be use.
6855 */
Emeric Brunce5ad802012-10-22 14:11:22 +02006856static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006857smp_fetch_ssl_x_notafter(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunce5ad802012-10-22 14:11:22 +02006858{
Emeric Brunba841a12014-04-30 17:05:08 +02006859 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brunce5ad802012-10-22 14:11:22 +02006860 X509 *crt = NULL;
6861 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02006862 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006863 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006864 struct ssl_sock_ctx *ctx;
Emeric Brunce5ad802012-10-22 14:11:22 +02006865
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006866 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006867 if (!conn || conn->xprt != &ssl_sock)
6868 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006869 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006870
6871 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02006872 smp->flags |= SMP_F_MAY_CHANGE;
6873 return 0;
6874 }
6875
Emeric Brunba841a12014-04-30 17:05:08 +02006876 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006877 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02006878 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01006879 crt = SSL_get_certificate(ctx->ssl);
Emeric Brunce5ad802012-10-22 14:11:22 +02006880 if (!crt)
6881 goto out;
6882
Willy Tarreau47ca5452012-12-23 20:22:19 +01006883 smp_trash = get_trash_chunk();
Rosen Penev68185952018-12-14 08:47:02 -08006884 if (ssl_sock_get_time(X509_getm_notAfter(crt), smp_trash) <= 0)
Emeric Brunce5ad802012-10-22 14:11:22 +02006885 goto out;
6886
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006887 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006888 smp->data.type = SMP_T_STR;
Emeric Brunce5ad802012-10-22 14:11:22 +02006889 ret = 1;
6890out:
Emeric Brunba841a12014-04-30 17:05:08 +02006891 /* SSL_get_peer_certificate, it increase X509 * ref count */
6892 if (cert_peer && crt)
Emeric Brunce5ad802012-10-22 14:11:22 +02006893 X509_free(crt);
6894 return ret;
6895}
6896
Emeric Brunba841a12014-04-30 17:05:08 +02006897/* string, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. of certificate's issuer
6898 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6899 * should be use.
6900 */
Emeric Brun87855892012-10-17 17:39:35 +02006901static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006902smp_fetch_ssl_x_i_dn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun87855892012-10-17 17:39:35 +02006903{
Emeric Brunba841a12014-04-30 17:05:08 +02006904 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun87855892012-10-17 17:39:35 +02006905 X509 *crt = NULL;
6906 X509_NAME *name;
6907 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02006908 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006909 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006910 struct ssl_sock_ctx *ctx;
Emeric Brun87855892012-10-17 17:39:35 +02006911
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006912 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006913 if (!conn || conn->xprt != &ssl_sock)
6914 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006915 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006916
6917 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02006918 smp->flags |= SMP_F_MAY_CHANGE;
6919 return 0;
6920 }
6921
Emeric Brunba841a12014-04-30 17:05:08 +02006922 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006923 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02006924 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01006925 crt = SSL_get_certificate(ctx->ssl);
Emeric Brun87855892012-10-17 17:39:35 +02006926 if (!crt)
6927 goto out;
6928
6929 name = X509_get_issuer_name(crt);
6930 if (!name)
6931 goto out;
6932
Willy Tarreau47ca5452012-12-23 20:22:19 +01006933 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02006934 if (args && args[0].type == ARGT_STR) {
6935 int pos = 1;
6936
6937 if (args[1].type == ARGT_SINT)
6938 pos = args[1].data.sint;
Emeric Brun87855892012-10-17 17:39:35 +02006939
6940 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
6941 goto out;
6942 }
6943 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
6944 goto out;
6945
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006946 smp->data.type = SMP_T_STR;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006947 smp->data.u.str = *smp_trash;
Emeric Brun87855892012-10-17 17:39:35 +02006948 ret = 1;
6949out:
Emeric Brunba841a12014-04-30 17:05:08 +02006950 /* SSL_get_peer_certificate, it increase X509 * ref count */
6951 if (cert_peer && crt)
Emeric Brun87855892012-10-17 17:39:35 +02006952 X509_free(crt);
6953 return ret;
6954}
6955
Emeric Brunba841a12014-04-30 17:05:08 +02006956/* string, returns notbefore date in ASN1_UTCTIME format.
6957 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6958 * should be use.
6959 */
Emeric Brunce5ad802012-10-22 14:11:22 +02006960static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006961smp_fetch_ssl_x_notbefore(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunce5ad802012-10-22 14:11:22 +02006962{
Emeric Brunba841a12014-04-30 17:05:08 +02006963 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brunce5ad802012-10-22 14:11:22 +02006964 X509 *crt = NULL;
6965 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02006966 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006967 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006968 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006969
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006970 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006971 if (!conn || conn->xprt != &ssl_sock)
Emeric Brunce5ad802012-10-22 14:11:22 +02006972 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006973 ctx = conn->xprt_ctx;
Emeric Brunce5ad802012-10-22 14:11:22 +02006974
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006975 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02006976 smp->flags |= SMP_F_MAY_CHANGE;
6977 return 0;
6978 }
6979
Emeric Brunba841a12014-04-30 17:05:08 +02006980 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006981 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02006982 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01006983 crt = SSL_get_certificate(ctx->ssl);
Emeric Brunce5ad802012-10-22 14:11:22 +02006984 if (!crt)
6985 goto out;
6986
Willy Tarreau47ca5452012-12-23 20:22:19 +01006987 smp_trash = get_trash_chunk();
Rosen Penev68185952018-12-14 08:47:02 -08006988 if (ssl_sock_get_time(X509_getm_notBefore(crt), smp_trash) <= 0)
Emeric Brunce5ad802012-10-22 14:11:22 +02006989 goto out;
6990
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006991 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006992 smp->data.type = SMP_T_STR;
Emeric Brunce5ad802012-10-22 14:11:22 +02006993 ret = 1;
6994out:
Emeric Brunba841a12014-04-30 17:05:08 +02006995 /* SSL_get_peer_certificate, it increase X509 * ref count */
6996 if (cert_peer && crt)
Emeric Brunce5ad802012-10-22 14:11:22 +02006997 X509_free(crt);
6998 return ret;
6999}
7000
Emeric Brunba841a12014-04-30 17:05:08 +02007001/* string, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. of certificate's subject
7002 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7003 * should be use.
7004 */
Emeric Brun87855892012-10-17 17:39:35 +02007005static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007006smp_fetch_ssl_x_s_dn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun87855892012-10-17 17:39:35 +02007007{
Emeric Brunba841a12014-04-30 17:05:08 +02007008 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun87855892012-10-17 17:39:35 +02007009 X509 *crt = NULL;
7010 X509_NAME *name;
7011 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02007012 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007013 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007014 struct ssl_sock_ctx *ctx;
Emeric Brun87855892012-10-17 17:39:35 +02007015
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007016 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007017 if (!conn || conn->xprt != &ssl_sock)
7018 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007019 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007020
7021 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02007022 smp->flags |= SMP_F_MAY_CHANGE;
7023 return 0;
7024 }
7025
Emeric Brunba841a12014-04-30 17:05:08 +02007026 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007027 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007028 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007029 crt = SSL_get_certificate(ctx->ssl);
Emeric Brun87855892012-10-17 17:39:35 +02007030 if (!crt)
7031 goto out;
7032
7033 name = X509_get_subject_name(crt);
7034 if (!name)
7035 goto out;
7036
Willy Tarreau47ca5452012-12-23 20:22:19 +01007037 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02007038 if (args && args[0].type == ARGT_STR) {
7039 int pos = 1;
7040
7041 if (args[1].type == ARGT_SINT)
7042 pos = args[1].data.sint;
Emeric Brun87855892012-10-17 17:39:35 +02007043
7044 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
7045 goto out;
7046 }
7047 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
7048 goto out;
7049
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007050 smp->data.type = SMP_T_STR;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007051 smp->data.u.str = *smp_trash;
Emeric Brun87855892012-10-17 17:39:35 +02007052 ret = 1;
7053out:
Emeric Brunba841a12014-04-30 17:05:08 +02007054 /* SSL_get_peer_certificate, it increase X509 * ref count */
7055 if (cert_peer && crt)
Emeric Brun87855892012-10-17 17:39:35 +02007056 X509_free(crt);
7057 return ret;
7058}
Emeric Brun9143d372012-12-20 15:44:16 +01007059
7060/* integer, returns true if current session use a client certificate */
7061static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007062smp_fetch_ssl_c_used(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun9143d372012-12-20 15:44:16 +01007063{
7064 X509 *crt;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007065 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007066 struct ssl_sock_ctx *ctx;
Emeric Brun9143d372012-12-20 15:44:16 +01007067
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007068 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007069 if (!conn || conn->xprt != &ssl_sock)
7070 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007071 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007072
7073 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun9143d372012-12-20 15:44:16 +01007074 smp->flags |= SMP_F_MAY_CHANGE;
7075 return 0;
7076 }
7077
7078 /* SSL_get_peer_certificate returns a ptr on allocated X509 struct */
Olivier Houchard66ab4982019-02-26 18:37:15 +01007079 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brun9143d372012-12-20 15:44:16 +01007080 if (crt) {
7081 X509_free(crt);
7082 }
7083
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007084 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007085 smp->data.u.sint = (crt != NULL);
Emeric Brun9143d372012-12-20 15:44:16 +01007086 return 1;
7087}
7088
Emeric Brunba841a12014-04-30 17:05:08 +02007089/* integer, returns the certificate version
7090 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7091 * should be use.
7092 */
Emeric Bruna7359fd2012-10-17 15:03:11 +02007093static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007094smp_fetch_ssl_x_version(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Bruna7359fd2012-10-17 15:03:11 +02007095{
Emeric Brunba841a12014-04-30 17:05:08 +02007096 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Bruna7359fd2012-10-17 15:03:11 +02007097 X509 *crt;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007098 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007099 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007100
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007101 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007102 if (!conn || conn->xprt != &ssl_sock)
Emeric Bruna7359fd2012-10-17 15:03:11 +02007103 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007104 ctx = conn->xprt_ctx;
Emeric Bruna7359fd2012-10-17 15:03:11 +02007105
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007106 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Bruna7359fd2012-10-17 15:03:11 +02007107 smp->flags |= SMP_F_MAY_CHANGE;
7108 return 0;
7109 }
7110
Emeric Brunba841a12014-04-30 17:05:08 +02007111 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007112 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007113 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007114 crt = SSL_get_certificate(ctx->ssl);
Emeric Bruna7359fd2012-10-17 15:03:11 +02007115 if (!crt)
7116 return 0;
7117
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007118 smp->data.u.sint = (unsigned int)(1 + X509_get_version(crt));
Emeric Brunba841a12014-04-30 17:05:08 +02007119 /* SSL_get_peer_certificate increase X509 * ref count */
7120 if (cert_peer)
7121 X509_free(crt);
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007122 smp->data.type = SMP_T_SINT;
Emeric Bruna7359fd2012-10-17 15:03:11 +02007123
7124 return 1;
7125}
7126
Emeric Brunba841a12014-04-30 17:05:08 +02007127/* string, returns the certificate's signature algorithm.
7128 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7129 * should be use.
7130 */
Emeric Brun7f56e742012-10-19 18:15:40 +02007131static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007132smp_fetch_ssl_x_sig_alg(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun7f56e742012-10-19 18:15:40 +02007133{
Emeric Brunba841a12014-04-30 17:05:08 +02007134 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun7f56e742012-10-19 18:15:40 +02007135 X509 *crt;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007136 __OPENSSL_110_CONST__ ASN1_OBJECT *algorithm;
Emeric Brun7f56e742012-10-19 18:15:40 +02007137 int nid;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007138 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007139 struct ssl_sock_ctx *ctx;
Emeric Brun7f56e742012-10-19 18:15:40 +02007140
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007141 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007142 if (!conn || conn->xprt != &ssl_sock)
7143 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007144 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007145
7146 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun7f56e742012-10-19 18:15:40 +02007147 smp->flags |= SMP_F_MAY_CHANGE;
7148 return 0;
7149 }
7150
Emeric Brunba841a12014-04-30 17:05:08 +02007151 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007152 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007153 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007154 crt = SSL_get_certificate(ctx->ssl);
Emeric Brun7f56e742012-10-19 18:15:40 +02007155 if (!crt)
7156 return 0;
7157
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007158 X509_ALGOR_get0(&algorithm, NULL, NULL, X509_get0_tbs_sigalg(crt));
7159 nid = OBJ_obj2nid(algorithm);
Emeric Brun7f56e742012-10-19 18:15:40 +02007160
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007161 smp->data.u.str.area = (char *)OBJ_nid2sn(nid);
7162 if (!smp->data.u.str.area) {
Emeric Brunba841a12014-04-30 17:05:08 +02007163 /* SSL_get_peer_certificate increase X509 * ref count */
7164 if (cert_peer)
7165 X509_free(crt);
Emeric Brun7f56e742012-10-19 18:15:40 +02007166 return 0;
Emeric Brun9bf3ba22013-10-07 14:31:44 +02007167 }
Emeric Brun7f56e742012-10-19 18:15:40 +02007168
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007169 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01007170 smp->flags |= SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007171 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brunba841a12014-04-30 17:05:08 +02007172 /* SSL_get_peer_certificate increase X509 * ref count */
7173 if (cert_peer)
7174 X509_free(crt);
Emeric Brun7f56e742012-10-19 18:15:40 +02007175
7176 return 1;
7177}
7178
Emeric Brunba841a12014-04-30 17:05:08 +02007179/* string, returns the certificate's key algorithm.
7180 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7181 * should be use.
7182 */
Emeric Brun521a0112012-10-22 12:22:55 +02007183static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007184smp_fetch_ssl_x_key_alg(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun521a0112012-10-22 12:22:55 +02007185{
Emeric Brunba841a12014-04-30 17:05:08 +02007186 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun521a0112012-10-22 12:22:55 +02007187 X509 *crt;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007188 ASN1_OBJECT *algorithm;
Emeric Brun521a0112012-10-22 12:22:55 +02007189 int nid;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007190 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007191 struct ssl_sock_ctx *ctx;
Emeric Brun521a0112012-10-22 12:22:55 +02007192
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007193 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007194 if (!conn || conn->xprt != &ssl_sock)
7195 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007196 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007197
7198 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun521a0112012-10-22 12:22:55 +02007199 smp->flags |= SMP_F_MAY_CHANGE;
7200 return 0;
7201 }
7202
Emeric Brunba841a12014-04-30 17:05:08 +02007203 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007204 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007205 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007206 crt = SSL_get_certificate(ctx->ssl);
Emeric Brun521a0112012-10-22 12:22:55 +02007207 if (!crt)
7208 return 0;
7209
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007210 X509_PUBKEY_get0_param(&algorithm, NULL, NULL, NULL, X509_get_X509_PUBKEY(crt));
7211 nid = OBJ_obj2nid(algorithm);
Emeric Brun521a0112012-10-22 12:22:55 +02007212
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007213 smp->data.u.str.area = (char *)OBJ_nid2sn(nid);
7214 if (!smp->data.u.str.area) {
Emeric Brunba841a12014-04-30 17:05:08 +02007215 /* SSL_get_peer_certificate increase X509 * ref count */
7216 if (cert_peer)
7217 X509_free(crt);
Emeric Brun521a0112012-10-22 12:22:55 +02007218 return 0;
Emeric Brun9bf3ba22013-10-07 14:31:44 +02007219 }
Emeric Brun521a0112012-10-22 12:22:55 +02007220
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007221 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01007222 smp->flags |= SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007223 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brunba841a12014-04-30 17:05:08 +02007224 if (cert_peer)
7225 X509_free(crt);
Emeric Brun521a0112012-10-22 12:22:55 +02007226
7227 return 1;
7228}
7229
Emeric Brun645ae792014-04-30 14:21:06 +02007230/* boolean, returns true if front conn. transport layer is SSL.
7231 * This function is also usable on backend conn if the fetch keyword 5th
7232 * char is 'b'.
7233 */
Willy Tarreau7875d092012-09-10 08:20:03 +02007234static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007235smp_fetch_ssl_fc(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02007236{
Emeric Bruneb8def92018-02-19 15:59:48 +01007237 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7238 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007239
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007240 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007241 smp->data.u.sint = (conn && conn->xprt == &ssl_sock);
Willy Tarreau7875d092012-09-10 08:20:03 +02007242 return 1;
7243}
7244
Emeric Brun2525b6b2012-10-18 15:59:43 +02007245/* boolean, returns true if client present a SNI */
Willy Tarreau7875d092012-09-10 08:20:03 +02007246static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007247smp_fetch_ssl_fc_has_sni(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02007248{
7249#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007250 struct connection *conn = objt_conn(smp->sess->origin);
Olivier Houchard66ab4982019-02-26 18:37:15 +01007251 struct ssl_sock_ctx *ctx = conn ? conn->xprt_ctx : NULL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007252
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007253 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007254 smp->data.u.sint = (conn && conn->xprt == &ssl_sock) &&
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007255 conn->xprt_ctx &&
Olivier Houchard66ab4982019-02-26 18:37:15 +01007256 SSL_get_servername(ctx->ssl, TLSEXT_NAMETYPE_host_name) != NULL;
Willy Tarreau7875d092012-09-10 08:20:03 +02007257 return 1;
7258#else
7259 return 0;
7260#endif
7261}
7262
Emeric Brun74f7ffa2018-02-19 16:14:12 +01007263/* boolean, returns true if client session has been resumed.
7264 * This function is also usable on backend conn if the fetch keyword 5th
7265 * char is 'b'.
7266 */
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02007267static int
7268smp_fetch_ssl_fc_is_resumed(const struct arg *args, struct sample *smp, const char *kw, void *private)
7269{
Emeric Brun74f7ffa2018-02-19 16:14:12 +01007270 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7271 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007272 struct ssl_sock_ctx *ctx = conn ? conn->xprt_ctx : NULL;
Emeric Brun74f7ffa2018-02-19 16:14:12 +01007273
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02007274
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007275 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007276 smp->data.u.sint = (conn && conn->xprt == &ssl_sock) &&
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02007277 conn->xprt_ctx &&
Olivier Houchard66ab4982019-02-26 18:37:15 +01007278 SSL_session_reused(ctx->ssl);
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02007279 return 1;
7280}
7281
Emeric Brun645ae792014-04-30 14:21:06 +02007282/* string, returns the used cipher if front conn. transport layer is SSL.
7283 * This function is also usable on backend conn if the fetch keyword 5th
7284 * char is 'b'.
7285 */
Emeric Brun589fcad2012-10-16 14:13:26 +02007286static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007287smp_fetch_ssl_fc_cipher(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02007288{
Emeric Bruneb8def92018-02-19 15:59:48 +01007289 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7290 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007291 struct ssl_sock_ctx *ctx;
Emeric Brun589fcad2012-10-16 14:13:26 +02007292
Willy Tarreaube508f12016-03-10 11:47:01 +01007293 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007294 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02007295 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007296 ctx = conn->xprt_ctx;
Emeric Brun589fcad2012-10-16 14:13:26 +02007297
Olivier Houchard66ab4982019-02-26 18:37:15 +01007298 smp->data.u.str.area = (char *)SSL_get_cipher_name(ctx->ssl);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007299 if (!smp->data.u.str.area)
Emeric Brun589fcad2012-10-16 14:13:26 +02007300 return 0;
7301
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007302 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01007303 smp->flags |= SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007304 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brun589fcad2012-10-16 14:13:26 +02007305
7306 return 1;
7307}
7308
Emeric Brun645ae792014-04-30 14:21:06 +02007309/* integer, returns the algoritm's keysize if front conn. transport layer
7310 * is SSL.
7311 * This function is also usable on backend conn if the fetch keyword 5th
7312 * char is 'b'.
7313 */
Emeric Brun589fcad2012-10-16 14:13:26 +02007314static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007315smp_fetch_ssl_fc_alg_keysize(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02007316{
Emeric Bruneb8def92018-02-19 15:59:48 +01007317 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7318 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007319 struct ssl_sock_ctx *ctx;
Willy Tarreaue237fe12016-03-10 17:05:28 +01007320 int sint;
Willy Tarreaube508f12016-03-10 11:47:01 +01007321
Emeric Brun589fcad2012-10-16 14:13:26 +02007322 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 if (!SSL_get_cipher_bits(ctx->ssl, &sint))
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007328 return 0;
7329
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007330 smp->data.u.sint = sint;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007331 smp->data.type = SMP_T_SINT;
Emeric Brun589fcad2012-10-16 14:13:26 +02007332
7333 return 1;
7334}
7335
Emeric Brun645ae792014-04-30 14:21:06 +02007336/* integer, returns the used keysize if front conn. transport layer is SSL.
7337 * This function is also usable on backend conn if the fetch keyword 5th
7338 * char is 'b'.
7339 */
Emeric Brun589fcad2012-10-16 14:13:26 +02007340static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007341smp_fetch_ssl_fc_use_keysize(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02007342{
Emeric Bruneb8def92018-02-19 15:59:48 +01007343 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7344 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007345 struct ssl_sock_ctx *ctx;
Willy Tarreaube508f12016-03-10 11:47:01 +01007346
Emeric Brun589fcad2012-10-16 14:13:26 +02007347 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007348 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7349 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007350 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007351
Olivier Houchard66ab4982019-02-26 18:37:15 +01007352 smp->data.u.sint = (unsigned int)SSL_get_cipher_bits(ctx->ssl, NULL);
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007353 if (!smp->data.u.sint)
Emeric Brun589fcad2012-10-16 14:13:26 +02007354 return 0;
7355
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007356 smp->data.type = SMP_T_SINT;
Emeric Brun589fcad2012-10-16 14:13:26 +02007357
7358 return 1;
7359}
7360
Bernard Spil13c53f82018-02-15 13:34:58 +01007361#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Willy Tarreau7875d092012-09-10 08:20:03 +02007362static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007363smp_fetch_ssl_fc_npn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreaua33c6542012-10-15 13:19:06 +02007364{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007365 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007366 struct ssl_sock_ctx *ctx;
Willy Tarreau767e8ad2020-02-25 08:59:23 +01007367 unsigned int len = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007368
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01007369 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007370 smp->data.type = SMP_T_STR;
Willy Tarreaua33c6542012-10-15 13:19:06 +02007371
Olivier Houchard6b77f492018-11-22 18:18:29 +01007372 conn = (kw[4] != 'b' ) ? objt_conn(smp->sess->origin) :
7373 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007374 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7375 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007376 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007377
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007378 smp->data.u.str.area = NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007379 SSL_get0_next_proto_negotiated(ctx->ssl,
Willy Tarreau767e8ad2020-02-25 08:59:23 +01007380 (const unsigned char **)&smp->data.u.str.area,
7381 &len);
Willy Tarreaua33c6542012-10-15 13:19:06 +02007382
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007383 if (!smp->data.u.str.area)
Willy Tarreaua33c6542012-10-15 13:19:06 +02007384 return 0;
7385
Willy Tarreau767e8ad2020-02-25 08:59:23 +01007386 smp->data.u.str.data = len;
Willy Tarreaua33c6542012-10-15 13:19:06 +02007387 return 1;
Willy Tarreaua33c6542012-10-15 13:19:06 +02007388}
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02007389#endif
Willy Tarreaua33c6542012-10-15 13:19:06 +02007390
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01007391#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02007392static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007393smp_fetch_ssl_fc_alpn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreauab861d32013-04-02 02:30:41 +02007394{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007395 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007396 struct ssl_sock_ctx *ctx;
Willy Tarreau767e8ad2020-02-25 08:59:23 +01007397 unsigned int len = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007398
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01007399 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007400 smp->data.type = SMP_T_STR;
Willy Tarreauab861d32013-04-02 02:30:41 +02007401
Olivier Houchard6b77f492018-11-22 18:18:29 +01007402 conn = (kw[4] != 'b' ) ? objt_conn(smp->sess->origin) :
7403 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
7404
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007405 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Willy Tarreauab861d32013-04-02 02:30:41 +02007406 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007407 ctx = conn->xprt_ctx;
Willy Tarreauab861d32013-04-02 02:30:41 +02007408
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007409 smp->data.u.str.area = NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007410 SSL_get0_alpn_selected(ctx->ssl,
Willy Tarreau767e8ad2020-02-25 08:59:23 +01007411 (const unsigned char **)&smp->data.u.str.area,
7412 &len);
Willy Tarreauab861d32013-04-02 02:30:41 +02007413
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007414 if (!smp->data.u.str.area)
Willy Tarreauab861d32013-04-02 02:30:41 +02007415 return 0;
7416
Willy Tarreau767e8ad2020-02-25 08:59:23 +01007417 smp->data.u.str.data = len;
Willy Tarreauab861d32013-04-02 02:30:41 +02007418 return 1;
7419}
7420#endif
7421
Emeric Brun645ae792014-04-30 14:21:06 +02007422/* string, returns the used protocol if front conn. transport layer is SSL.
7423 * This function is also usable on backend conn if the fetch keyword 5th
7424 * char is 'b'.
7425 */
Willy Tarreaua33c6542012-10-15 13:19:06 +02007426static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007427smp_fetch_ssl_fc_protocol(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02007428{
Emeric Bruneb8def92018-02-19 15:59:48 +01007429 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7430 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007431 struct ssl_sock_ctx *ctx;
Willy Tarreaube508f12016-03-10 11:47:01 +01007432
Emeric Brun589fcad2012-10-16 14:13:26 +02007433 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007434 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7435 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007436 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007437
Olivier Houchard66ab4982019-02-26 18:37:15 +01007438 smp->data.u.str.area = (char *)SSL_get_version(ctx->ssl);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007439 if (!smp->data.u.str.area)
Emeric Brun589fcad2012-10-16 14:13:26 +02007440 return 0;
7441
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007442 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01007443 smp->flags = SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007444 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brun589fcad2012-10-16 14:13:26 +02007445
7446 return 1;
7447}
7448
Willy Tarreau87b09662015-04-03 00:22:06 +02007449/* binary, returns the SSL stream id if front conn. transport layer is SSL.
Emeric Brun645ae792014-04-30 14:21:06 +02007450 * This function is also usable on backend conn if the fetch keyword 5th
7451 * char is 'b'.
7452 */
Willy Tarreau9a1ab082019-05-09 13:26:41 +02007453#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
Emeric Brun589fcad2012-10-16 14:13:26 +02007454static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007455smp_fetch_ssl_fc_session_id(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunfe68f682012-10-16 14:59:28 +02007456{
Emeric Bruneb8def92018-02-19 15:59:48 +01007457 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7458 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaue237fe12016-03-10 17:05:28 +01007459 SSL_SESSION *ssl_sess;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007460 struct ssl_sock_ctx *ctx;
Willy Tarreau767e8ad2020-02-25 08:59:23 +01007461 unsigned int len = 0;
Willy Tarreaube508f12016-03-10 11:47:01 +01007462
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01007463 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007464 smp->data.type = SMP_T_BIN;
Emeric Brunfe68f682012-10-16 14:59:28 +02007465
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007466 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7467 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007468 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007469
Olivier Houchard66ab4982019-02-26 18:37:15 +01007470 ssl_sess = SSL_get_session(ctx->ssl);
Willy Tarreau192252e2015-04-04 01:47:55 +02007471 if (!ssl_sess)
Emeric Brunfe68f682012-10-16 14:59:28 +02007472 return 0;
7473
Willy Tarreau767e8ad2020-02-25 08:59:23 +01007474 smp->data.u.str.area = (char *)SSL_SESSION_get_id(ssl_sess, &len);
Dragan Dosen9dc47c42020-05-04 09:07:28 +02007475 if (!smp->data.u.str.area || !len)
Emeric Brunfe68f682012-10-16 14:59:28 +02007476 return 0;
7477
Willy Tarreau767e8ad2020-02-25 08:59:23 +01007478 smp->data.u.str.data = len;
Emeric Brunfe68f682012-10-16 14:59:28 +02007479 return 1;
Emeric Brunfe68f682012-10-16 14:59:28 +02007480}
Patrick Hemmer41966772018-04-28 19:15:48 -04007481#endif
7482
Emeric Brunfe68f682012-10-16 14:59:28 +02007483
Emmanuel Hocdet839af572019-05-14 16:27:35 +02007484#if HA_OPENSSL_VERSION_NUMBER >= 0x10100000L
Patrick Hemmere0275472018-04-28 19:15:51 -04007485static int
Patrick Hemmer65674662019-06-04 08:13:03 -04007486smp_fetch_ssl_fc_random(const struct arg *args, struct sample *smp, const char *kw, void *private)
7487{
7488 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7489 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
7490 struct buffer *data;
7491 struct ssl_sock_ctx *ctx;
7492
7493 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7494 return 0;
7495 ctx = conn->xprt_ctx;
7496
7497 data = get_trash_chunk();
7498 if (kw[7] == 'c')
7499 data->data = SSL_get_client_random(ctx->ssl,
7500 (unsigned char *) data->area,
7501 data->size);
7502 else
7503 data->data = SSL_get_server_random(ctx->ssl,
7504 (unsigned char *) data->area,
7505 data->size);
7506 if (!data->data)
7507 return 0;
7508
7509 smp->flags = 0;
7510 smp->data.type = SMP_T_BIN;
7511 smp->data.u.str = *data;
7512
7513 return 1;
7514}
7515
7516static int
Patrick Hemmere0275472018-04-28 19:15:51 -04007517smp_fetch_ssl_fc_session_key(const struct arg *args, struct sample *smp, const char *kw, void *private)
7518{
7519 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7520 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
7521 SSL_SESSION *ssl_sess;
Willy Tarreau83061a82018-07-13 11:56:34 +02007522 struct buffer *data;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007523 struct ssl_sock_ctx *ctx;
Patrick Hemmere0275472018-04-28 19:15:51 -04007524
7525 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7526 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007527 ctx = conn->xprt_ctx;
Patrick Hemmere0275472018-04-28 19:15:51 -04007528
Olivier Houchard66ab4982019-02-26 18:37:15 +01007529 ssl_sess = SSL_get_session(ctx->ssl);
Patrick Hemmere0275472018-04-28 19:15:51 -04007530 if (!ssl_sess)
7531 return 0;
7532
7533 data = get_trash_chunk();
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007534 data->data = SSL_SESSION_get_master_key(ssl_sess,
7535 (unsigned char *) data->area,
7536 data->size);
7537 if (!data->data)
Patrick Hemmere0275472018-04-28 19:15:51 -04007538 return 0;
7539
7540 smp->flags = 0;
7541 smp->data.type = SMP_T_BIN;
7542 smp->data.u.str = *data;
7543
7544 return 1;
7545}
7546#endif
7547
Patrick Hemmer41966772018-04-28 19:15:48 -04007548#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emeric Brunfe68f682012-10-16 14:59:28 +02007549static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007550smp_fetch_ssl_fc_sni(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02007551{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007552 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007553 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007554
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01007555 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007556 smp->data.type = SMP_T_STR;
Willy Tarreau7875d092012-09-10 08:20:03 +02007557
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007558 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007559 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7560 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007561 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007562
Olivier Houchard66ab4982019-02-26 18:37:15 +01007563 smp->data.u.str.area = (char *)SSL_get_servername(ctx->ssl, TLSEXT_NAMETYPE_host_name);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007564 if (!smp->data.u.str.area)
Willy Tarreau3e394c92012-09-14 23:56:58 +02007565 return 0;
7566
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007567 smp->data.u.str.data = strlen(smp->data.u.str.area);
Willy Tarreau7875d092012-09-10 08:20:03 +02007568 return 1;
Willy Tarreau7875d092012-09-10 08:20:03 +02007569}
Patrick Hemmer41966772018-04-28 19:15:48 -04007570#endif
Willy Tarreau7875d092012-09-10 08:20:03 +02007571
David Sc1ad52e2014-04-08 18:48:47 -04007572static int
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007573smp_fetch_ssl_fc_cl_bin(const struct arg *args, struct sample *smp, const char *kw, void *private)
7574{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007575 struct connection *conn;
7576 struct ssl_capture *capture;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007577 struct ssl_sock_ctx *ctx;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007578
7579 conn = objt_conn(smp->sess->origin);
7580 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7581 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007582 ctx = conn->xprt_ctx;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007583
Olivier Houchard66ab4982019-02-26 18:37:15 +01007584 capture = SSL_get_ex_data(ctx->ssl, ssl_capture_ptr_index);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007585 if (!capture)
7586 return 0;
7587
7588 smp->flags = SMP_F_CONST;
7589 smp->data.type = SMP_T_BIN;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007590 smp->data.u.str.area = capture->ciphersuite;
7591 smp->data.u.str.data = capture->ciphersuite_len;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007592 return 1;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007593}
7594
7595static int
7596smp_fetch_ssl_fc_cl_hex(const struct arg *args, struct sample *smp, const char *kw, void *private)
7597{
Willy Tarreau83061a82018-07-13 11:56:34 +02007598 struct buffer *data;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007599
7600 if (!smp_fetch_ssl_fc_cl_bin(args, smp, kw, private))
7601 return 0;
7602
7603 data = get_trash_chunk();
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007604 dump_binary(data, smp->data.u.str.area, smp->data.u.str.data);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007605 smp->data.type = SMP_T_BIN;
7606 smp->data.u.str = *data;
7607 return 1;
7608}
7609
7610static int
7611smp_fetch_ssl_fc_cl_xxh64(const struct arg *args, struct sample *smp, const char *kw, void *private)
7612{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007613 struct connection *conn;
7614 struct ssl_capture *capture;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007615 struct ssl_sock_ctx *ctx;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007616
7617 conn = objt_conn(smp->sess->origin);
7618 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7619 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007620 ctx = conn->xprt_ctx;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007621
Olivier Houchard66ab4982019-02-26 18:37:15 +01007622 capture = SSL_get_ex_data(ctx->ssl, ssl_capture_ptr_index);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007623 if (!capture)
7624 return 0;
7625
7626 smp->data.type = SMP_T_SINT;
7627 smp->data.u.sint = capture->xxh64;
7628 return 1;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007629}
7630
7631static int
7632smp_fetch_ssl_fc_cl_str(const struct arg *args, struct sample *smp, const char *kw, void *private)
7633{
Willy Tarreau5db847a2019-05-09 14:13:35 +02007634#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL)
Willy Tarreau83061a82018-07-13 11:56:34 +02007635 struct buffer *data;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007636 int i;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007637
7638 if (!smp_fetch_ssl_fc_cl_bin(args, smp, kw, private))
7639 return 0;
7640
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007641 data = get_trash_chunk();
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007642 for (i = 0; i + 1 < smp->data.u.str.data; i += 2) {
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02007643 const char *str;
7644 const SSL_CIPHER *cipher;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007645 const unsigned char *bin = (const unsigned char *) smp->data.u.str.area + i;
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02007646 uint16_t id = (bin[0] << 8) | bin[1];
7647#if defined(OPENSSL_IS_BORINGSSL)
7648 cipher = SSL_get_cipher_by_value(id);
7649#else
Willy Tarreaub7290772018-10-15 11:01:59 +02007650 struct connection *conn = __objt_conn(smp->sess->origin);
Olivier Houchard66ab4982019-02-26 18:37:15 +01007651 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
7652 cipher = SSL_CIPHER_find(ctx->ssl, bin);
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02007653#endif
7654 str = SSL_CIPHER_get_name(cipher);
7655 if (!str || strcmp(str, "(NONE)") == 0)
7656 chunk_appendf(data, "%sUNKNOWN(%04x)", i == 0 ? "" : ",", id);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007657 else
7658 chunk_appendf(data, "%s%s", i == 0 ? "" : ",", str);
7659 }
7660 smp->data.type = SMP_T_STR;
7661 smp->data.u.str = *data;
7662 return 1;
7663#else
7664 return smp_fetch_ssl_fc_cl_xxh64(args, smp, kw, private);
7665#endif
7666}
7667
Willy Tarreau9a1ab082019-05-09 13:26:41 +02007668#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007669static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007670smp_fetch_ssl_fc_unique_id(const struct arg *args, struct sample *smp, const char *kw, void *private)
David Sc1ad52e2014-04-08 18:48:47 -04007671{
Emeric Bruneb8def92018-02-19 15:59:48 +01007672 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7673 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
David Sc1ad52e2014-04-08 18:48:47 -04007674 int finished_len;
Willy Tarreau83061a82018-07-13 11:56:34 +02007675 struct buffer *finished_trash;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007676 struct ssl_sock_ctx *ctx;
David Sc1ad52e2014-04-08 18:48:47 -04007677
7678 smp->flags = 0;
David Sc1ad52e2014-04-08 18:48:47 -04007679 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7680 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007681 ctx = conn->xprt_ctx;
David Sc1ad52e2014-04-08 18:48:47 -04007682
7683 if (!(conn->flags & CO_FL_CONNECTED)) {
7684 smp->flags |= SMP_F_MAY_CHANGE;
7685 return 0;
7686 }
7687
7688 finished_trash = get_trash_chunk();
Olivier Houchard66ab4982019-02-26 18:37:15 +01007689 if (!SSL_session_reused(ctx->ssl))
7690 finished_len = SSL_get_peer_finished(ctx->ssl,
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007691 finished_trash->area,
7692 finished_trash->size);
David Sc1ad52e2014-04-08 18:48:47 -04007693 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007694 finished_len = SSL_get_finished(ctx->ssl,
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007695 finished_trash->area,
7696 finished_trash->size);
David Sc1ad52e2014-04-08 18:48:47 -04007697
7698 if (!finished_len)
7699 return 0;
7700
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007701 finished_trash->data = finished_len;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007702 smp->data.u.str = *finished_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007703 smp->data.type = SMP_T_BIN;
David Sc1ad52e2014-04-08 18:48:47 -04007704
7705 return 1;
David Sc1ad52e2014-04-08 18:48:47 -04007706}
Patrick Hemmer41966772018-04-28 19:15:48 -04007707#endif
David Sc1ad52e2014-04-08 18:48:47 -04007708
Emeric Brun2525b6b2012-10-18 15:59:43 +02007709/* integer, returns the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02007710static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007711smp_fetch_ssl_c_ca_err(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunf282a812012-09-21 15:27:54 +02007712{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007713 struct connection *conn;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007714 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007715
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007716 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007717 if (!conn || conn->xprt != &ssl_sock)
7718 return 0;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007719 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007720
7721 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02007722 smp->flags = SMP_F_MAY_CHANGE;
7723 return 0;
7724 }
7725
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007726 smp->data.type = SMP_T_SINT;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007727 smp->data.u.sint = (unsigned long long int)SSL_SOCK_ST_TO_CA_ERROR(ctx->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02007728 smp->flags = 0;
7729
7730 return 1;
7731}
7732
Emeric Brun2525b6b2012-10-18 15:59:43 +02007733/* integer, returns the depth of the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02007734static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007735smp_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 +02007736{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007737 struct connection *conn;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007738 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007739
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007740 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007741 if (!conn || conn->xprt != &ssl_sock)
Emeric Brunf282a812012-09-21 15:27:54 +02007742 return 0;
7743
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007744 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02007745 smp->flags = SMP_F_MAY_CHANGE;
7746 return 0;
7747 }
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007748 ctx = conn->xprt_ctx;
Emeric Brunf282a812012-09-21 15:27:54 +02007749
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007750 smp->data.type = SMP_T_SINT;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007751 smp->data.u.sint = (long long int)SSL_SOCK_ST_TO_CAEDEPTH(ctx->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02007752 smp->flags = 0;
7753
7754 return 1;
7755}
7756
Emeric Brun2525b6b2012-10-18 15:59:43 +02007757/* integer, returns the first verify error on client certificate */
Emeric Brunf282a812012-09-21 15:27:54 +02007758static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007759smp_fetch_ssl_c_err(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunf282a812012-09-21 15:27:54 +02007760{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007761 struct connection *conn;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007762 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007763
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007764 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007765 if (!conn || conn->xprt != &ssl_sock)
7766 return 0;
7767
7768 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02007769 smp->flags = SMP_F_MAY_CHANGE;
7770 return 0;
7771 }
7772
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007773 ctx = conn->xprt_ctx;
7774
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007775 smp->data.type = SMP_T_SINT;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007776 smp->data.u.sint = (long long int)SSL_SOCK_ST_TO_CRTERROR(ctx->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02007777 smp->flags = 0;
7778
7779 return 1;
7780}
7781
Emeric Brun2525b6b2012-10-18 15:59:43 +02007782/* integer, returns the verify result on client cert */
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02007783static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007784smp_fetch_ssl_c_verify(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02007785{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007786 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007787 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007788
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007789 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007790 if (!conn || conn->xprt != &ssl_sock)
7791 return 0;
7792
7793 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02007794 smp->flags = SMP_F_MAY_CHANGE;
7795 return 0;
7796 }
7797
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007798 if (!conn->xprt_ctx)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02007799 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007800 ctx = conn->xprt_ctx;
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02007801
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007802 smp->data.type = SMP_T_SINT;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007803 smp->data.u.sint = (long long int)SSL_get_verify_result(ctx->ssl);
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02007804 smp->flags = 0;
7805
7806 return 1;
7807}
7808
Emeric Brunfb510ea2012-10-05 12:00:26 +02007809/* parse the "ca-file" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007810static 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 +02007811{
7812 if (!*args[cur_arg + 1]) {
7813 if (err)
7814 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
7815 return ERR_ALERT | ERR_FATAL;
7816 }
7817
Willy Tarreauef934602016-12-22 23:12:01 +01007818 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
7819 memprintf(&conf->ca_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02007820 else
7821 memprintf(&conf->ca_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02007822
Emeric Brund94b3fe2012-09-20 18:23:56 +02007823 return 0;
7824}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007825static int bind_parse_ca_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7826{
7827 return ssl_bind_parse_ca_file(args, cur_arg, px, &conf->ssl_conf, err);
7828}
Emeric Brund94b3fe2012-09-20 18:23:56 +02007829
Christopher Faulet31af49d2015-06-09 17:29:50 +02007830/* parse the "ca-sign-file" bind keyword */
7831static int bind_parse_ca_sign_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7832{
7833 if (!*args[cur_arg + 1]) {
7834 if (err)
7835 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
7836 return ERR_ALERT | ERR_FATAL;
7837 }
7838
Willy Tarreauef934602016-12-22 23:12:01 +01007839 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
7840 memprintf(&conf->ca_sign_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Christopher Faulet31af49d2015-06-09 17:29:50 +02007841 else
7842 memprintf(&conf->ca_sign_file, "%s", args[cur_arg + 1]);
7843
7844 return 0;
7845}
7846
Bertrand Jacquinff13c062016-11-13 16:37:11 +00007847/* parse the "ca-sign-pass" bind keyword */
Christopher Faulet31af49d2015-06-09 17:29:50 +02007848static int bind_parse_ca_sign_pass(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7849{
7850 if (!*args[cur_arg + 1]) {
7851 if (err)
7852 memprintf(err, "'%s' : missing CAkey password", args[cur_arg]);
7853 return ERR_ALERT | ERR_FATAL;
7854 }
7855 memprintf(&conf->ca_sign_pass, "%s", args[cur_arg + 1]);
7856 return 0;
7857}
7858
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007859/* parse the "ciphers" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007860static 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 +02007861{
7862 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02007863 memprintf(err, "'%s' : missing cipher suite", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007864 return ERR_ALERT | ERR_FATAL;
7865 }
7866
Emeric Brun76d88952012-10-05 15:47:31 +02007867 free(conf->ciphers);
Willy Tarreau4348fad2012-09-20 16:48:07 +02007868 conf->ciphers = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007869 return 0;
7870}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007871static int bind_parse_ciphers(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7872{
7873 return ssl_bind_parse_ciphers(args, cur_arg, px, &conf->ssl_conf, err);
7874}
Dirkjan Bussink415150f2018-09-14 11:14:21 +02007875
Emmanuel Hocdet839af572019-05-14 16:27:35 +02007876#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02007877/* parse the "ciphersuites" bind keyword */
7878static int ssl_bind_parse_ciphersuites(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
7879{
7880 if (!*args[cur_arg + 1]) {
7881 memprintf(err, "'%s' : missing cipher suite", args[cur_arg]);
7882 return ERR_ALERT | ERR_FATAL;
7883 }
7884
7885 free(conf->ciphersuites);
7886 conf->ciphersuites = strdup(args[cur_arg + 1]);
7887 return 0;
7888}
7889static int bind_parse_ciphersuites(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7890{
7891 return ssl_bind_parse_ciphersuites(args, cur_arg, px, &conf->ssl_conf, err);
7892}
7893#endif
7894
Willy Tarreaub131c872019-10-16 16:42:19 +02007895/* parse the "crt" bind keyword. Returns a set of ERR_* flags possibly with an error in <err>. */
Willy Tarreau4348fad2012-09-20 16:48:07 +02007896static 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 +02007897{
Willy Tarreau38011032013-08-13 16:59:39 +02007898 char path[MAXPATHLEN];
Willy Tarreaub75d6922014-04-14 18:05:41 +02007899
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007900 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02007901 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007902 return ERR_ALERT | ERR_FATAL;
7903 }
7904
Willy Tarreauef934602016-12-22 23:12:01 +01007905 if ((*args[cur_arg + 1] != '/' ) && global_ssl.crt_base) {
7906 if ((strlen(global_ssl.crt_base) + 1 + strlen(args[cur_arg + 1]) + 1) > MAXPATHLEN) {
Emeric Brunc8e8d122012-10-02 18:42:10 +02007907 memprintf(err, "'%s' : path too long", args[cur_arg]);
7908 return ERR_ALERT | ERR_FATAL;
7909 }
Willy Tarreauef934602016-12-22 23:12:01 +01007910 snprintf(path, sizeof(path), "%s/%s", global_ssl.crt_base, args[cur_arg + 1]);
Willy Tarreaub131c872019-10-16 16:42:19 +02007911 return ssl_sock_load_cert(path, conf, err);
Emeric Brunc8e8d122012-10-02 18:42:10 +02007912 }
7913
Willy Tarreaub131c872019-10-16 16:42:19 +02007914 return ssl_sock_load_cert(args[cur_arg + 1], conf, err);
Emeric Brund94b3fe2012-09-20 18:23:56 +02007915}
7916
Willy Tarreaub131c872019-10-16 16:42:19 +02007917/* 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 +01007918static int bind_parse_crt_list(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7919{
Willy Tarreaub131c872019-10-16 16:42:19 +02007920 int err_code;
7921
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01007922 if (!*args[cur_arg + 1]) {
7923 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
7924 return ERR_ALERT | ERR_FATAL;
7925 }
7926
Willy Tarreaub131c872019-10-16 16:42:19 +02007927 err_code = ssl_sock_load_cert_list_file(args[cur_arg + 1], conf, px, err);
7928 if (err_code)
Willy Tarreauad1731d2013-04-02 17:35:58 +02007929 memprintf(err, "'%s' : %s", args[cur_arg], *err);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01007930
Willy Tarreaub131c872019-10-16 16:42:19 +02007931 return err_code;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01007932}
7933
Emeric Brunfb510ea2012-10-05 12:00:26 +02007934/* parse the "crl-file" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007935static 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 +02007936{
Emeric Brun051cdab2012-10-02 19:25:50 +02007937#ifndef X509_V_FLAG_CRL_CHECK
7938 if (err)
7939 memprintf(err, "'%s' : library does not support CRL verify", args[cur_arg]);
7940 return ERR_ALERT | ERR_FATAL;
7941#else
Emeric Brund94b3fe2012-09-20 18:23:56 +02007942 if (!*args[cur_arg + 1]) {
7943 if (err)
7944 memprintf(err, "'%s' : missing CRLfile path", args[cur_arg]);
7945 return ERR_ALERT | ERR_FATAL;
7946 }
Emeric Brun2b58d042012-09-20 17:10:03 +02007947
Willy Tarreauef934602016-12-22 23:12:01 +01007948 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
7949 memprintf(&conf->crl_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02007950 else
7951 memprintf(&conf->crl_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02007952
Emeric Brun2b58d042012-09-20 17:10:03 +02007953 return 0;
Emeric Brun051cdab2012-10-02 19:25:50 +02007954#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02007955}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007956static int bind_parse_crl_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7957{
7958 return ssl_bind_parse_crl_file(args, cur_arg, px, &conf->ssl_conf, err);
7959}
Emeric Brun2b58d042012-09-20 17:10:03 +02007960
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01007961/* parse the "curves" bind keyword keyword */
7962static int ssl_bind_parse_curves(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
7963{
Lukas Tribusd13e9252019-11-24 18:20:40 +01007964#if ((HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL) || defined(LIBRESSL_VERSION_NUMBER))
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01007965 if (!*args[cur_arg + 1]) {
7966 if (err)
7967 memprintf(err, "'%s' : missing curve suite", args[cur_arg]);
7968 return ERR_ALERT | ERR_FATAL;
7969 }
7970 conf->curves = strdup(args[cur_arg + 1]);
7971 return 0;
7972#else
7973 if (err)
7974 memprintf(err, "'%s' : library does not support curve suite", args[cur_arg]);
7975 return ERR_ALERT | ERR_FATAL;
7976#endif
7977}
7978static int bind_parse_curves(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7979{
7980 return ssl_bind_parse_curves(args, cur_arg, px, &conf->ssl_conf, err);
7981}
7982
Bertrand Jacquinff13c062016-11-13 16:37:11 +00007983/* parse the "ecdhe" bind keyword keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007984static 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 +02007985{
Willy Tarreau9a1ab082019-05-09 13:26:41 +02007986#if HA_OPENSSL_VERSION_NUMBER < 0x0090800fL
Emeric Brun2b58d042012-09-20 17:10:03 +02007987 if (err)
7988 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (too old)", args[cur_arg]);
7989 return ERR_ALERT | ERR_FATAL;
7990#elif defined(OPENSSL_NO_ECDH)
7991 if (err)
7992 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (disabled via OPENSSL_NO_ECDH)", args[cur_arg]);
7993 return ERR_ALERT | ERR_FATAL;
7994#else
7995 if (!*args[cur_arg + 1]) {
7996 if (err)
7997 memprintf(err, "'%s' : missing named curve", args[cur_arg]);
7998 return ERR_ALERT | ERR_FATAL;
7999 }
8000
8001 conf->ecdhe = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008002
8003 return 0;
Emeric Brun2b58d042012-09-20 17:10:03 +02008004#endif
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008005}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008006static int bind_parse_ecdhe(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8007{
8008 return ssl_bind_parse_ecdhe(args, cur_arg, px, &conf->ssl_conf, err);
8009}
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008010
Bertrand Jacquinff13c062016-11-13 16:37:11 +00008011/* parse the "crt-ignore-err" and "ca-ignore-err" bind keywords */
Emeric Brun81c00f02012-09-21 14:31:21 +02008012static int bind_parse_ignore_err(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8013{
8014 int code;
8015 char *p = args[cur_arg + 1];
8016 unsigned long long *ignerr = &conf->crt_ignerr;
8017
8018 if (!*p) {
8019 if (err)
8020 memprintf(err, "'%s' : missing error IDs list", args[cur_arg]);
8021 return ERR_ALERT | ERR_FATAL;
8022 }
8023
8024 if (strcmp(args[cur_arg], "ca-ignore-err") == 0)
8025 ignerr = &conf->ca_ignerr;
8026
8027 if (strcmp(p, "all") == 0) {
8028 *ignerr = ~0ULL;
8029 return 0;
8030 }
8031
8032 while (p) {
8033 code = atoi(p);
8034 if ((code <= 0) || (code > 63)) {
8035 if (err)
8036 memprintf(err, "'%s' : ID '%d' out of range (1..63) in error IDs list '%s'",
8037 args[cur_arg], code, args[cur_arg + 1]);
8038 return ERR_ALERT | ERR_FATAL;
8039 }
8040 *ignerr |= 1ULL << code;
8041 p = strchr(p, ',');
8042 if (p)
8043 p++;
8044 }
8045
Emeric Brun2cb7ae52012-10-05 14:14:21 +02008046 return 0;
8047}
8048
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008049/* parse tls_method_options "no-xxx" and "force-xxx" */
8050static int parse_tls_method_options(char *arg, struct tls_version_filter *methods, char **err)
Emeric Brun2cb7ae52012-10-05 14:14:21 +02008051{
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008052 uint16_t v;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008053 char *p;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008054 p = strchr(arg, '-');
8055 if (!p)
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008056 goto fail;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008057 p++;
8058 if (!strcmp(p, "sslv3"))
8059 v = CONF_SSLV3;
8060 else if (!strcmp(p, "tlsv10"))
8061 v = CONF_TLSV10;
8062 else if (!strcmp(p, "tlsv11"))
8063 v = CONF_TLSV11;
8064 else if (!strcmp(p, "tlsv12"))
8065 v = CONF_TLSV12;
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +02008066 else if (!strcmp(p, "tlsv13"))
8067 v = CONF_TLSV13;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008068 else
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008069 goto fail;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008070 if (!strncmp(arg, "no-", 3))
8071 methods->flags |= methodVersions[v].flag;
8072 else if (!strncmp(arg, "force-", 6))
8073 methods->min = methods->max = v;
8074 else
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008075 goto fail;
Emeric Brun2d0c4822012-10-02 13:45:20 +02008076 return 0;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008077 fail:
8078 if (err)
8079 memprintf(err, "'%s' : option not implemented", arg);
8080 return ERR_ALERT | ERR_FATAL;
Emeric Brun2d0c4822012-10-02 13:45:20 +02008081}
8082
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008083static 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 +02008084{
Emmanuel Hocdet43664762017-08-09 18:26:20 +02008085 return parse_tls_method_options(args[cur_arg], &conf->ssl_conf.ssl_methods, err);
Emeric Brun2cb7ae52012-10-05 14:14:21 +02008086}
8087
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008088static 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 +02008089{
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008090 return parse_tls_method_options(args[*cur_arg], &newsrv->ssl_ctx.methods, err);
8091}
8092
8093/* parse tls_method min/max: "ssl-min-ver" and "ssl-max-ver" */
8094static int parse_tls_method_minmax(char **args, int cur_arg, struct tls_version_filter *methods, char **err)
8095{
8096 uint16_t i, v = 0;
8097 char *argv = args[cur_arg + 1];
8098 if (!*argv) {
8099 if (err)
8100 memprintf(err, "'%s' : missing the ssl/tls version", args[cur_arg]);
8101 return ERR_ALERT | ERR_FATAL;
8102 }
8103 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
8104 if (!strcmp(argv, methodVersions[i].name))
8105 v = i;
8106 if (!v) {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008107 if (err)
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008108 memprintf(err, "'%s' : unknown ssl/tls version", args[cur_arg + 1]);
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008109 return ERR_ALERT | ERR_FATAL;
8110 }
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008111 if (!strcmp("ssl-min-ver", args[cur_arg]))
8112 methods->min = v;
8113 else if (!strcmp("ssl-max-ver", args[cur_arg]))
8114 methods->max = v;
8115 else {
8116 if (err)
8117 memprintf(err, "'%s' : option not implemented", args[cur_arg]);
8118 return ERR_ALERT | ERR_FATAL;
8119 }
Emeric Brun2cb7ae52012-10-05 14:14:21 +02008120 return 0;
Emeric Brun2cb7ae52012-10-05 14:14:21 +02008121}
Emeric Brun2cb7ae52012-10-05 14:14:21 +02008122
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02008123static int ssl_bind_parse_tls_method_minmax(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
8124{
Willy Tarreau9a1ab082019-05-09 13:26:41 +02008125#if (HA_OPENSSL_VERSION_NUMBER < 0x10101000L) && !defined(OPENSSL_IS_BORINGSSL)
Christopher Faulet767a84b2017-11-24 16:50:31 +01008126 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 +02008127#endif
8128 return parse_tls_method_minmax(args, cur_arg, &conf->ssl_methods, err);
8129}
8130
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008131static int bind_parse_tls_method_minmax(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8132{
Emmanuel Hocdet43664762017-08-09 18:26:20 +02008133 return parse_tls_method_minmax(args, cur_arg, &conf->ssl_conf.ssl_methods, err);
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008134}
8135
8136static int srv_parse_tls_method_minmax(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8137{
8138 return parse_tls_method_minmax(args, *cur_arg, &newsrv->ssl_ctx.methods, err);
8139}
8140
Emeric Brun2d0c4822012-10-02 13:45:20 +02008141/* parse the "no-tls-tickets" bind keyword */
Emmanuel Hocdet4608ed92017-01-20 13:06:27 +01008142static 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 +02008143{
Emeric Brun89675492012-10-05 13:48:26 +02008144 conf->ssl_options |= BC_SSL_O_NO_TLS_TICKETS;
Emeric Brun81c00f02012-09-21 14:31:21 +02008145 return 0;
8146}
Emeric Brun2d0c4822012-10-02 13:45:20 +02008147
Olivier Houchardc2aae742017-09-22 18:26:28 +02008148/* parse the "allow-0rtt" bind keyword */
8149static int ssl_bind_parse_allow_0rtt(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
8150{
8151 conf->early_data = 1;
8152 return 0;
8153}
8154
8155static int bind_parse_allow_0rtt(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8156{
Olivier Houchard9679ac92017-10-27 14:58:08 +02008157 conf->ssl_conf.early_data = 1;
Olivier Houchardc2aae742017-09-22 18:26:28 +02008158 return 0;
8159}
8160
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02008161/* parse the "npn" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008162static 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 +02008163{
Bernard Spil13c53f82018-02-15 13:34:58 +01008164#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02008165 char *p1, *p2;
8166
8167 if (!*args[cur_arg + 1]) {
8168 memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[cur_arg]);
8169 return ERR_ALERT | ERR_FATAL;
8170 }
8171
8172 free(conf->npn_str);
8173
Willy Tarreau3724da12016-02-12 17:11:12 +01008174 /* the NPN string is built as a suite of (<len> <name>)*,
8175 * so we reuse each comma to store the next <len> and need
8176 * one more for the end of the string.
8177 */
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02008178 conf->npn_len = strlen(args[cur_arg + 1]) + 1;
Willy Tarreau3724da12016-02-12 17:11:12 +01008179 conf->npn_str = calloc(1, conf->npn_len + 1);
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02008180 memcpy(conf->npn_str + 1, args[cur_arg + 1], conf->npn_len);
8181
8182 /* replace commas with the name length */
8183 p1 = conf->npn_str;
8184 p2 = p1 + 1;
8185 while (1) {
8186 p2 = memchr(p1 + 1, ',', conf->npn_str + conf->npn_len - (p1 + 1));
8187 if (!p2)
8188 p2 = p1 + 1 + strlen(p1 + 1);
8189
8190 if (p2 - (p1 + 1) > 255) {
8191 *p2 = '\0';
8192 memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
8193 return ERR_ALERT | ERR_FATAL;
8194 }
8195
8196 *p1 = p2 - (p1 + 1);
8197 p1 = p2;
8198
8199 if (!*p2)
8200 break;
8201
8202 *(p2++) = '\0';
8203 }
8204 return 0;
8205#else
8206 if (err)
8207 memprintf(err, "'%s' : library does not support TLS NPN extension", args[cur_arg]);
8208 return ERR_ALERT | ERR_FATAL;
8209#endif
8210}
8211
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008212static int bind_parse_npn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8213{
8214 return ssl_bind_parse_npn(args, cur_arg, px, &conf->ssl_conf, err);
8215}
8216
Willy Tarreauab861d32013-04-02 02:30:41 +02008217/* parse the "alpn" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008218static 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 +02008219{
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01008220#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02008221 char *p1, *p2;
8222
8223 if (!*args[cur_arg + 1]) {
8224 memprintf(err, "'%s' : missing the comma-delimited ALPN protocol suite", args[cur_arg]);
8225 return ERR_ALERT | ERR_FATAL;
8226 }
8227
8228 free(conf->alpn_str);
8229
Marcoen Hirschbergbef60912016-02-12 17:05:24 +01008230 /* the ALPN string is built as a suite of (<len> <name>)*,
8231 * so we reuse each comma to store the next <len> and need
8232 * one more for the end of the string.
8233 */
Willy Tarreauab861d32013-04-02 02:30:41 +02008234 conf->alpn_len = strlen(args[cur_arg + 1]) + 1;
Marcoen Hirschbergbef60912016-02-12 17:05:24 +01008235 conf->alpn_str = calloc(1, conf->alpn_len + 1);
Willy Tarreauab861d32013-04-02 02:30:41 +02008236 memcpy(conf->alpn_str + 1, args[cur_arg + 1], conf->alpn_len);
8237
8238 /* replace commas with the name length */
8239 p1 = conf->alpn_str;
8240 p2 = p1 + 1;
8241 while (1) {
8242 p2 = memchr(p1 + 1, ',', conf->alpn_str + conf->alpn_len - (p1 + 1));
8243 if (!p2)
8244 p2 = p1 + 1 + strlen(p1 + 1);
8245
8246 if (p2 - (p1 + 1) > 255) {
8247 *p2 = '\0';
8248 memprintf(err, "'%s' : ALPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
8249 return ERR_ALERT | ERR_FATAL;
8250 }
8251
8252 *p1 = p2 - (p1 + 1);
8253 p1 = p2;
8254
8255 if (!*p2)
8256 break;
8257
8258 *(p2++) = '\0';
8259 }
8260 return 0;
8261#else
8262 if (err)
8263 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[cur_arg]);
8264 return ERR_ALERT | ERR_FATAL;
8265#endif
8266}
8267
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008268static int bind_parse_alpn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8269{
8270 return ssl_bind_parse_alpn(args, cur_arg, px, &conf->ssl_conf, err);
8271}
8272
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008273/* parse the "ssl" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02008274static 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 +02008275{
Willy Tarreau71a8c7c2016-12-21 22:04:54 +01008276 conf->xprt = &ssl_sock;
Willy Tarreau4348fad2012-09-20 16:48:07 +02008277 conf->is_ssl = 1;
Emeric Brun76d88952012-10-05 15:47:31 +02008278
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008279 if (global_ssl.listen_default_ciphers && !conf->ssl_conf.ciphers)
8280 conf->ssl_conf.ciphers = strdup(global_ssl.listen_default_ciphers);
Emmanuel Hocdet839af572019-05-14 16:27:35 +02008281#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02008282 if (global_ssl.listen_default_ciphersuites && !conf->ssl_conf.ciphersuites)
8283 conf->ssl_conf.ciphersuites = strdup(global_ssl.listen_default_ciphersuites);
8284#endif
Emmanuel Hocdet4608ed92017-01-20 13:06:27 +01008285 conf->ssl_options |= global_ssl.listen_default_ssloptions;
Emmanuel Hocdet43664762017-08-09 18:26:20 +02008286 conf->ssl_conf.ssl_methods.flags |= global_ssl.listen_default_sslmethods.flags;
8287 if (!conf->ssl_conf.ssl_methods.min)
8288 conf->ssl_conf.ssl_methods.min = global_ssl.listen_default_sslmethods.min;
8289 if (!conf->ssl_conf.ssl_methods.max)
8290 conf->ssl_conf.ssl_methods.max = global_ssl.listen_default_sslmethods.max;
Emeric Brun76d88952012-10-05 15:47:31 +02008291
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008292 return 0;
8293}
8294
Lukas Tribus53ae85c2017-05-04 15:45:40 +00008295/* parse the "prefer-client-ciphers" bind keyword */
8296static int bind_parse_pcc(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8297{
8298 conf->ssl_options |= BC_SSL_O_PREF_CLIE_CIPH;
8299 return 0;
8300}
8301
Christopher Faulet31af49d2015-06-09 17:29:50 +02008302/* parse the "generate-certificates" bind keyword */
8303static int bind_parse_generate_certs(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8304{
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01008305#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Christopher Faulet31af49d2015-06-09 17:29:50 +02008306 conf->generate_certs = 1;
8307#else
8308 memprintf(err, "%sthis version of openssl cannot generate SSL certificates.\n",
8309 err && *err ? *err : "");
8310#endif
8311 return 0;
8312}
8313
Emmanuel Hocdet65623372013-01-24 17:17:15 +01008314/* parse the "strict-sni" bind keyword */
8315static int bind_parse_strict_sni(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8316{
8317 conf->strict_sni = 1;
8318 return 0;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008319}
8320
8321/* parse the "tls-ticket-keys" bind keyword */
8322static int bind_parse_tls_ticket_keys(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8323{
8324#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
Christopher Faulet2bbc80d2019-10-21 09:55:49 +02008325 FILE *f = NULL;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008326 int i = 0;
8327 char thisline[LINESIZE];
Christopher Faulet2bbc80d2019-10-21 09:55:49 +02008328 struct tls_keys_ref *keys_ref = NULL;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008329
8330 if (!*args[cur_arg + 1]) {
8331 if (err)
8332 memprintf(err, "'%s' : missing TLS ticket keys file path", args[cur_arg]);
Christopher Faulet2bbc80d2019-10-21 09:55:49 +02008333 goto fail;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008334 }
8335
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02008336 keys_ref = tlskeys_ref_lookup(args[cur_arg + 1]);
Willy Tarreau17b4aa12018-07-17 10:05:32 +02008337 if (keys_ref) {
8338 keys_ref->refcount++;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02008339 conf->keys_ref = keys_ref;
8340 return 0;
8341 }
8342
Christopher Faulet2bbc80d2019-10-21 09:55:49 +02008343 keys_ref = calloc(1, sizeof(*keys_ref));
Emeric Brun09852f72019-01-10 10:51:13 +01008344 if (!keys_ref) {
8345 if (err)
8346 memprintf(err, "'%s' : allocation error", args[cur_arg+1]);
Christopher Faulet2bbc80d2019-10-21 09:55:49 +02008347 goto fail;
Emeric Brun09852f72019-01-10 10:51:13 +01008348 }
8349
Emeric Brun9e754772019-01-10 17:51:55 +01008350 keys_ref->tlskeys = malloc(TLS_TICKETS_NO * sizeof(union tls_sess_key));
Emeric Brun09852f72019-01-10 10:51:13 +01008351 if (!keys_ref->tlskeys) {
Emeric Brun09852f72019-01-10 10:51:13 +01008352 if (err)
8353 memprintf(err, "'%s' : allocation error", args[cur_arg+1]);
Christopher Faulet2bbc80d2019-10-21 09:55:49 +02008354 goto fail;
Emeric Brun09852f72019-01-10 10:51:13 +01008355 }
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008356
8357 if ((f = fopen(args[cur_arg + 1], "r")) == NULL) {
8358 if (err)
8359 memprintf(err, "'%s' : unable to load ssl tickets keys file", args[cur_arg+1]);
Christopher Faulet2bbc80d2019-10-21 09:55:49 +02008360 goto fail;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008361 }
8362
Nenad Merdanovic146defa2015-05-09 08:46:00 +02008363 keys_ref->filename = strdup(args[cur_arg + 1]);
Emeric Brun09852f72019-01-10 10:51:13 +01008364 if (!keys_ref->filename) {
Emeric Brun09852f72019-01-10 10:51:13 +01008365 if (err)
8366 memprintf(err, "'%s' : allocation error", args[cur_arg+1]);
Christopher Faulet2bbc80d2019-10-21 09:55:49 +02008367 goto fail;
Emeric Brun09852f72019-01-10 10:51:13 +01008368 }
Nenad Merdanovic146defa2015-05-09 08:46:00 +02008369
Emeric Brun9e754772019-01-10 17:51:55 +01008370 keys_ref->key_size_bits = 0;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008371 while (fgets(thisline, sizeof(thisline), f) != NULL) {
8372 int len = strlen(thisline);
Emeric Brun9e754772019-01-10 17:51:55 +01008373 int dec_size;
8374
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008375 /* Strip newline characters from the end */
8376 if(thisline[len - 1] == '\n')
8377 thisline[--len] = 0;
8378
8379 if(thisline[len - 1] == '\r')
8380 thisline[--len] = 0;
8381
Emeric Brun9e754772019-01-10 17:51:55 +01008382 dec_size = base64dec(thisline, len, (char *) (keys_ref->tlskeys + i % TLS_TICKETS_NO), sizeof(union tls_sess_key));
8383 if (dec_size < 0) {
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008384 if (err)
8385 memprintf(err, "'%s' : unable to decode base64 key on line %d", args[cur_arg+1], i + 1);
Christopher Faulet2bbc80d2019-10-21 09:55:49 +02008386 goto fail;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008387 }
Emeric Brun9e754772019-01-10 17:51:55 +01008388 else if (!keys_ref->key_size_bits && (dec_size == sizeof(struct tls_sess_key_128))) {
8389 keys_ref->key_size_bits = 128;
8390 }
8391 else if (!keys_ref->key_size_bits && (dec_size == sizeof(struct tls_sess_key_256))) {
8392 keys_ref->key_size_bits = 256;
8393 }
8394 else if (((dec_size != sizeof(struct tls_sess_key_128)) && (dec_size != sizeof(struct tls_sess_key_256)))
8395 || ((dec_size == sizeof(struct tls_sess_key_128) && (keys_ref->key_size_bits != 128)))
8396 || ((dec_size == sizeof(struct tls_sess_key_256) && (keys_ref->key_size_bits != 256)))) {
Emeric Brun9e754772019-01-10 17:51:55 +01008397 if (err)
8398 memprintf(err, "'%s' : wrong sized key on line %d", args[cur_arg+1], i + 1);
Christopher Faulet2bbc80d2019-10-21 09:55:49 +02008399 goto fail;
Emeric Brun9e754772019-01-10 17:51:55 +01008400 }
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008401 i++;
8402 }
8403
8404 if (i < TLS_TICKETS_NO) {
8405 if (err)
8406 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 +02008407 goto fail;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008408 }
8409
8410 fclose(f);
8411
8412 /* Use penultimate key for encryption, handle when TLS_TICKETS_NO = 1 */
Nenad Merdanovic17891152016-03-25 22:16:57 +01008413 i -= 2;
8414 keys_ref->tls_ticket_enc_index = i < 0 ? 0 : i % TLS_TICKETS_NO;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02008415 keys_ref->unique_id = -1;
Willy Tarreau17b4aa12018-07-17 10:05:32 +02008416 keys_ref->refcount = 1;
Christopher Faulet16f45c82018-02-16 11:23:49 +01008417 HA_RWLOCK_INIT(&keys_ref->lock);
Nenad Merdanovic146defa2015-05-09 08:46:00 +02008418 conf->keys_ref = keys_ref;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008419
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02008420 LIST_ADD(&tlskeys_reference, &keys_ref->list);
8421
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008422 return 0;
Christopher Faulet2bbc80d2019-10-21 09:55:49 +02008423
8424 fail:
8425 if (f)
8426 fclose(f);
8427 if (keys_ref) {
8428 free(keys_ref->filename);
8429 free(keys_ref->tlskeys);
8430 free(keys_ref);
8431 }
8432 return ERR_ALERT | ERR_FATAL;
8433
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008434#else
8435 if (err)
8436 memprintf(err, "'%s' : TLS ticket callback extension not supported", args[cur_arg]);
8437 return ERR_ALERT | ERR_FATAL;
8438#endif /* SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB */
Emmanuel Hocdet65623372013-01-24 17:17:15 +01008439}
8440
Emeric Brund94b3fe2012-09-20 18:23:56 +02008441/* parse the "verify" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008442static 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 +02008443{
8444 if (!*args[cur_arg + 1]) {
8445 if (err)
8446 memprintf(err, "'%s' : missing verify method", args[cur_arg]);
8447 return ERR_ALERT | ERR_FATAL;
8448 }
8449
8450 if (strcmp(args[cur_arg + 1], "none") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01008451 conf->verify = SSL_SOCK_VERIFY_NONE;
Emeric Brund94b3fe2012-09-20 18:23:56 +02008452 else if (strcmp(args[cur_arg + 1], "optional") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01008453 conf->verify = SSL_SOCK_VERIFY_OPTIONAL;
Emeric Brund94b3fe2012-09-20 18:23:56 +02008454 else if (strcmp(args[cur_arg + 1], "required") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01008455 conf->verify = SSL_SOCK_VERIFY_REQUIRED;
Emeric Brund94b3fe2012-09-20 18:23:56 +02008456 else {
8457 if (err)
8458 memprintf(err, "'%s' : unknown verify method '%s', only 'none', 'optional', and 'required' are supported\n",
8459 args[cur_arg], args[cur_arg + 1]);
8460 return ERR_ALERT | ERR_FATAL;
8461 }
8462
8463 return 0;
8464}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008465static int bind_parse_verify(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8466{
8467 return ssl_bind_parse_verify(args, cur_arg, px, &conf->ssl_conf, err);
8468}
Emeric Brund94b3fe2012-09-20 18:23:56 +02008469
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02008470/* parse the "no-ca-names" bind keyword */
8471static int ssl_bind_parse_no_ca_names(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
8472{
8473 conf->no_ca_names = 1;
8474 return 0;
8475}
8476static int bind_parse_no_ca_names(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8477{
8478 return ssl_bind_parse_no_ca_names(args, cur_arg, px, &conf->ssl_conf, err);
8479}
8480
Willy Tarreau92faadf2012-10-10 23:04:25 +02008481/************** "server" keywords ****************/
8482
Olivier Houchardc7566002018-11-20 23:33:50 +01008483/* parse the "npn" bind keyword */
8484static int srv_parse_npn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8485{
8486#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
8487 char *p1, *p2;
8488
8489 if (!*args[*cur_arg + 1]) {
8490 memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[*cur_arg]);
8491 return ERR_ALERT | ERR_FATAL;
8492 }
8493
8494 free(newsrv->ssl_ctx.npn_str);
8495
8496 /* the NPN string is built as a suite of (<len> <name>)*,
8497 * so we reuse each comma to store the next <len> and need
8498 * one more for the end of the string.
8499 */
8500 newsrv->ssl_ctx.npn_len = strlen(args[*cur_arg + 1]) + 1;
8501 newsrv->ssl_ctx.npn_str = calloc(1, newsrv->ssl_ctx.npn_len + 1);
8502 memcpy(newsrv->ssl_ctx.npn_str + 1, args[*cur_arg + 1],
8503 newsrv->ssl_ctx.npn_len);
8504
8505 /* replace commas with the name length */
8506 p1 = newsrv->ssl_ctx.npn_str;
8507 p2 = p1 + 1;
8508 while (1) {
8509 p2 = memchr(p1 + 1, ',', newsrv->ssl_ctx.npn_str +
8510 newsrv->ssl_ctx.npn_len - (p1 + 1));
8511 if (!p2)
8512 p2 = p1 + 1 + strlen(p1 + 1);
8513
8514 if (p2 - (p1 + 1) > 255) {
8515 *p2 = '\0';
8516 memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[*cur_arg], p1 + 1);
8517 return ERR_ALERT | ERR_FATAL;
8518 }
8519
8520 *p1 = p2 - (p1 + 1);
8521 p1 = p2;
8522
8523 if (!*p2)
8524 break;
8525
8526 *(p2++) = '\0';
8527 }
8528 return 0;
8529#else
8530 if (err)
8531 memprintf(err, "'%s' : library does not support TLS NPN extension", args[*cur_arg]);
8532 return ERR_ALERT | ERR_FATAL;
8533#endif
8534}
8535
Olivier Houchard92150142018-12-21 19:47:01 +01008536/* parse the "alpn" or the "check-alpn" server keyword */
Olivier Houchardc7566002018-11-20 23:33:50 +01008537static int srv_parse_alpn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8538{
8539#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
8540 char *p1, *p2;
Olivier Houchard92150142018-12-21 19:47:01 +01008541 char **alpn_str;
8542 int *alpn_len;
Olivier Houchardc7566002018-11-20 23:33:50 +01008543
Olivier Houchard92150142018-12-21 19:47:01 +01008544 if (*args[*cur_arg] == 'c') {
8545 alpn_str = &newsrv->check.alpn_str;
8546 alpn_len = &newsrv->check.alpn_len;
8547 } else {
8548 alpn_str = &newsrv->ssl_ctx.alpn_str;
8549 alpn_len = &newsrv->ssl_ctx.alpn_len;
8550
8551 }
Olivier Houchardc7566002018-11-20 23:33:50 +01008552 if (!*args[*cur_arg + 1]) {
8553 memprintf(err, "'%s' : missing the comma-delimited ALPN protocol suite", args[*cur_arg]);
8554 return ERR_ALERT | ERR_FATAL;
8555 }
8556
Olivier Houchard92150142018-12-21 19:47:01 +01008557 free(*alpn_str);
Olivier Houchardc7566002018-11-20 23:33:50 +01008558
8559 /* the ALPN string is built as a suite of (<len> <name>)*,
8560 * so we reuse each comma to store the next <len> and need
8561 * one more for the end of the string.
8562 */
Olivier Houchard92150142018-12-21 19:47:01 +01008563 *alpn_len = strlen(args[*cur_arg + 1]) + 1;
8564 *alpn_str = calloc(1, *alpn_len + 1);
8565 memcpy(*alpn_str + 1, args[*cur_arg + 1], *alpn_len);
Olivier Houchardc7566002018-11-20 23:33:50 +01008566
8567 /* replace commas with the name length */
Olivier Houchard92150142018-12-21 19:47:01 +01008568 p1 = *alpn_str;
Olivier Houchardc7566002018-11-20 23:33:50 +01008569 p2 = p1 + 1;
8570 while (1) {
Olivier Houchard92150142018-12-21 19:47:01 +01008571 p2 = memchr(p1 + 1, ',', *alpn_str + *alpn_len - (p1 + 1));
Olivier Houchardc7566002018-11-20 23:33:50 +01008572 if (!p2)
8573 p2 = p1 + 1 + strlen(p1 + 1);
8574
8575 if (p2 - (p1 + 1) > 255) {
8576 *p2 = '\0';
8577 memprintf(err, "'%s' : ALPN protocol name too long : '%s'", args[*cur_arg], p1 + 1);
8578 return ERR_ALERT | ERR_FATAL;
8579 }
8580
8581 *p1 = p2 - (p1 + 1);
8582 p1 = p2;
8583
8584 if (!*p2)
8585 break;
8586
8587 *(p2++) = '\0';
8588 }
8589 return 0;
8590#else
8591 if (err)
8592 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[*cur_arg]);
8593 return ERR_ALERT | ERR_FATAL;
8594#endif
8595}
8596
Emeric Brunef42d922012-10-11 16:11:36 +02008597/* parse the "ca-file" server keyword */
8598static int srv_parse_ca_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8599{
8600 if (!*args[*cur_arg + 1]) {
8601 if (err)
8602 memprintf(err, "'%s' : missing CAfile path", args[*cur_arg]);
8603 return ERR_ALERT | ERR_FATAL;
8604 }
8605
Willy Tarreauef934602016-12-22 23:12:01 +01008606 if ((*args[*cur_arg + 1] != '/') && global_ssl.ca_base)
8607 memprintf(&newsrv->ssl_ctx.ca_file, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02008608 else
8609 memprintf(&newsrv->ssl_ctx.ca_file, "%s", args[*cur_arg + 1]);
8610
8611 return 0;
8612}
8613
Olivier Houchard9130a962017-10-17 17:33:43 +02008614/* parse the "check-sni" server keyword */
8615static int srv_parse_check_sni(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8616{
8617 if (!*args[*cur_arg + 1]) {
8618 if (err)
8619 memprintf(err, "'%s' : missing SNI", args[*cur_arg]);
8620 return ERR_ALERT | ERR_FATAL;
8621 }
8622
8623 newsrv->check.sni = strdup(args[*cur_arg + 1]);
8624 if (!newsrv->check.sni) {
8625 memprintf(err, "'%s' : failed to allocate memory", args[*cur_arg]);
8626 return ERR_ALERT | ERR_FATAL;
8627 }
8628 return 0;
8629
8630}
8631
Willy Tarreau92faadf2012-10-10 23:04:25 +02008632/* parse the "check-ssl" server keyword */
8633static int srv_parse_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8634{
8635 newsrv->check.use_ssl = 1;
Willy Tarreauef934602016-12-22 23:12:01 +01008636 if (global_ssl.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
8637 newsrv->ssl_ctx.ciphers = strdup(global_ssl.connect_default_ciphers);
Emmanuel Hocdet839af572019-05-14 16:27:35 +02008638#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02008639 if (global_ssl.connect_default_ciphersuites && !newsrv->ssl_ctx.ciphersuites)
8640 newsrv->ssl_ctx.ciphersuites = strdup(global_ssl.connect_default_ciphersuites);
8641#endif
Willy Tarreauef934602016-12-22 23:12:01 +01008642 newsrv->ssl_ctx.options |= global_ssl.connect_default_ssloptions;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008643 newsrv->ssl_ctx.methods.flags |= global_ssl.connect_default_sslmethods.flags;
8644 if (!newsrv->ssl_ctx.methods.min)
8645 newsrv->ssl_ctx.methods.min = global_ssl.connect_default_sslmethods.min;
8646 if (!newsrv->ssl_ctx.methods.max)
8647 newsrv->ssl_ctx.methods.max = global_ssl.connect_default_sslmethods.max;
8648
Willy Tarreau92faadf2012-10-10 23:04:25 +02008649 return 0;
8650}
8651
8652/* parse the "ciphers" server keyword */
8653static int srv_parse_ciphers(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8654{
8655 if (!*args[*cur_arg + 1]) {
8656 memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
8657 return ERR_ALERT | ERR_FATAL;
8658 }
8659
8660 free(newsrv->ssl_ctx.ciphers);
8661 newsrv->ssl_ctx.ciphers = strdup(args[*cur_arg + 1]);
8662 return 0;
8663}
Dirkjan Bussink415150f2018-09-14 11:14:21 +02008664
Emmanuel Hocdet839af572019-05-14 16:27:35 +02008665#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02008666/* parse the "ciphersuites" server keyword */
8667static int srv_parse_ciphersuites(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8668{
8669 if (!*args[*cur_arg + 1]) {
8670 memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
8671 return ERR_ALERT | ERR_FATAL;
8672 }
8673
8674 free(newsrv->ssl_ctx.ciphersuites);
8675 newsrv->ssl_ctx.ciphersuites = strdup(args[*cur_arg + 1]);
8676 return 0;
8677}
8678#endif
Willy Tarreau92faadf2012-10-10 23:04:25 +02008679
Emeric Brunef42d922012-10-11 16:11:36 +02008680/* parse the "crl-file" server keyword */
8681static int srv_parse_crl_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8682{
8683#ifndef X509_V_FLAG_CRL_CHECK
8684 if (err)
8685 memprintf(err, "'%s' : library does not support CRL verify", args[*cur_arg]);
8686 return ERR_ALERT | ERR_FATAL;
8687#else
8688 if (!*args[*cur_arg + 1]) {
8689 if (err)
8690 memprintf(err, "'%s' : missing CRLfile path", args[*cur_arg]);
8691 return ERR_ALERT | ERR_FATAL;
8692 }
8693
Willy Tarreauef934602016-12-22 23:12:01 +01008694 if ((*args[*cur_arg + 1] != '/') && global_ssl.ca_base)
8695 memprintf(&newsrv->ssl_ctx.crl_file, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02008696 else
8697 memprintf(&newsrv->ssl_ctx.crl_file, "%s", args[*cur_arg + 1]);
8698
8699 return 0;
8700#endif
8701}
8702
Emeric Bruna7aa3092012-10-26 12:58:00 +02008703/* parse the "crt" server keyword */
8704static int srv_parse_crt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8705{
8706 if (!*args[*cur_arg + 1]) {
8707 if (err)
8708 memprintf(err, "'%s' : missing certificate file path", args[*cur_arg]);
8709 return ERR_ALERT | ERR_FATAL;
8710 }
8711
Willy Tarreauef934602016-12-22 23:12:01 +01008712 if ((*args[*cur_arg + 1] != '/') && global_ssl.crt_base)
Christopher Fauletff3a41e2017-11-23 09:13:32 +01008713 memprintf(&newsrv->ssl_ctx.client_crt, "%s/%s", global_ssl.crt_base, args[*cur_arg + 1]);
Emeric Bruna7aa3092012-10-26 12:58:00 +02008714 else
8715 memprintf(&newsrv->ssl_ctx.client_crt, "%s", args[*cur_arg + 1]);
8716
8717 return 0;
8718}
Emeric Brunef42d922012-10-11 16:11:36 +02008719
Frédéric Lécaille340ae602017-03-13 10:38:04 +01008720/* parse the "no-check-ssl" server keyword */
8721static int srv_parse_no_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8722{
Christopher Faulet68d35ae2020-03-27 18:55:49 +01008723 newsrv->check.use_ssl = -1;
Frédéric Lécaille340ae602017-03-13 10:38:04 +01008724 free(newsrv->ssl_ctx.ciphers);
8725 newsrv->ssl_ctx.ciphers = NULL;
8726 newsrv->ssl_ctx.options &= ~global_ssl.connect_default_ssloptions;
8727 return 0;
8728}
8729
Frédéric Lécaillee892c4c2017-03-13 12:08:01 +01008730/* parse the "no-send-proxy-v2-ssl" server keyword */
8731static int srv_parse_no_send_proxy_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8732{
8733 newsrv->pp_opts &= ~SRV_PP_V2;
8734 newsrv->pp_opts &= ~SRV_PP_V2_SSL;
8735 return 0;
8736}
8737
8738/* parse the "no-send-proxy-v2-ssl-cn" server keyword */
8739static int srv_parse_no_send_proxy_cn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8740{
8741 newsrv->pp_opts &= ~SRV_PP_V2;
8742 newsrv->pp_opts &= ~SRV_PP_V2_SSL;
8743 newsrv->pp_opts &= ~SRV_PP_V2_SSL_CN;
8744 return 0;
8745}
8746
Frédéric Lécaillee381d762017-03-13 11:54:17 +01008747/* parse the "no-ssl" server keyword */
8748static int srv_parse_no_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8749{
Christopher Faulet68d35ae2020-03-27 18:55:49 +01008750 newsrv->use_ssl = -1;
Frédéric Lécaillee381d762017-03-13 11:54:17 +01008751 free(newsrv->ssl_ctx.ciphers);
8752 newsrv->ssl_ctx.ciphers = NULL;
8753 return 0;
8754}
8755
Olivier Houchard522eea72017-11-03 16:27:47 +01008756/* parse the "allow-0rtt" server keyword */
8757static int srv_parse_allow_0rtt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8758{
8759 newsrv->ssl_ctx.options |= SRV_SSL_O_EARLY_DATA;
8760 return 0;
8761}
8762
Willy Tarreau2a3fb1c2015-02-05 16:47:07 +01008763/* parse the "no-ssl-reuse" server keyword */
8764static int srv_parse_no_ssl_reuse(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8765{
8766 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_REUSE;
8767 return 0;
8768}
8769
Emeric Brunf9c5c472012-10-11 15:28:34 +02008770/* parse the "no-tls-tickets" server keyword */
8771static int srv_parse_no_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8772{
8773 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLS_TICKETS;
8774 return 0;
8775}
David Safb76832014-05-08 23:42:08 -04008776/* parse the "send-proxy-v2-ssl" server keyword */
8777static int srv_parse_send_proxy_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8778{
8779 newsrv->pp_opts |= SRV_PP_V2;
8780 newsrv->pp_opts |= SRV_PP_V2_SSL;
8781 return 0;
8782}
8783
8784/* parse the "send-proxy-v2-ssl-cn" server keyword */
8785static int srv_parse_send_proxy_cn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8786{
8787 newsrv->pp_opts |= SRV_PP_V2;
8788 newsrv->pp_opts |= SRV_PP_V2_SSL;
8789 newsrv->pp_opts |= SRV_PP_V2_SSL_CN;
8790 return 0;
8791}
Emeric Brunf9c5c472012-10-11 15:28:34 +02008792
Willy Tarreau732eac42015-07-09 11:40:25 +02008793/* parse the "sni" server keyword */
8794static int srv_parse_sni(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8795{
8796#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
8797 memprintf(err, "'%s' : the current SSL library doesn't support the SNI TLS extension", args[*cur_arg]);
8798 return ERR_ALERT | ERR_FATAL;
8799#else
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01008800 char *arg;
Willy Tarreau732eac42015-07-09 11:40:25 +02008801
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01008802 arg = args[*cur_arg + 1];
8803 if (!*arg) {
Willy Tarreau732eac42015-07-09 11:40:25 +02008804 memprintf(err, "'%s' : missing sni expression", args[*cur_arg]);
8805 return ERR_ALERT | ERR_FATAL;
8806 }
8807
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01008808 free(newsrv->sni_expr);
8809 newsrv->sni_expr = strdup(arg);
Willy Tarreau732eac42015-07-09 11:40:25 +02008810
Willy Tarreau732eac42015-07-09 11:40:25 +02008811 return 0;
8812#endif
8813}
8814
Willy Tarreau92faadf2012-10-10 23:04:25 +02008815/* parse the "ssl" server keyword */
8816static int srv_parse_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8817{
8818 newsrv->use_ssl = 1;
Willy Tarreauef934602016-12-22 23:12:01 +01008819 if (global_ssl.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
8820 newsrv->ssl_ctx.ciphers = strdup(global_ssl.connect_default_ciphers);
Emmanuel Hocdet839af572019-05-14 16:27:35 +02008821#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02008822 if (global_ssl.connect_default_ciphersuites && !newsrv->ssl_ctx.ciphersuites)
8823 newsrv->ssl_ctx.ciphersuites = strdup(global_ssl.connect_default_ciphersuites);
8824#endif
Jerome Magnin770bc8a2020-04-22 11:40:18 +02008825 newsrv->ssl_ctx.options |= global_ssl.connect_default_ssloptions;
8826 newsrv->ssl_ctx.methods.flags |= global_ssl.connect_default_sslmethods.flags;
8827
8828 if (!newsrv->ssl_ctx.methods.min)
8829 newsrv->ssl_ctx.methods.min = global_ssl.connect_default_sslmethods.min;
8830
8831 if (!newsrv->ssl_ctx.methods.max)
8832 newsrv->ssl_ctx.methods.max = global_ssl.connect_default_sslmethods.max;
8833
8834
Willy Tarreau92faadf2012-10-10 23:04:25 +02008835 return 0;
8836}
8837
Frédéric Lécaille2cfcdbe2017-03-13 11:32:20 +01008838/* parse the "ssl-reuse" server keyword */
8839static int srv_parse_ssl_reuse(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8840{
8841 newsrv->ssl_ctx.options &= ~SRV_SSL_O_NO_REUSE;
8842 return 0;
8843}
8844
Frédéric Lécaille2cfcdbe2017-03-13 11:32:20 +01008845/* parse the "tls-tickets" server keyword */
8846static int srv_parse_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8847{
8848 newsrv->ssl_ctx.options &= ~SRV_SSL_O_NO_TLS_TICKETS;
8849 return 0;
8850}
8851
Emeric Brunef42d922012-10-11 16:11:36 +02008852/* parse the "verify" server keyword */
8853static int srv_parse_verify(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8854{
8855 if (!*args[*cur_arg + 1]) {
8856 if (err)
8857 memprintf(err, "'%s' : missing verify method", args[*cur_arg]);
8858 return ERR_ALERT | ERR_FATAL;
8859 }
8860
8861 if (strcmp(args[*cur_arg + 1], "none") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01008862 newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_NONE;
Emeric Brunef42d922012-10-11 16:11:36 +02008863 else if (strcmp(args[*cur_arg + 1], "required") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01008864 newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_REQUIRED;
Emeric Brunef42d922012-10-11 16:11:36 +02008865 else {
8866 if (err)
8867 memprintf(err, "'%s' : unknown verify method '%s', only 'none' and 'required' are supported\n",
8868 args[*cur_arg], args[*cur_arg + 1]);
8869 return ERR_ALERT | ERR_FATAL;
8870 }
8871
Evan Broderbe554312013-06-27 00:05:25 -07008872 return 0;
8873}
8874
8875/* parse the "verifyhost" server keyword */
8876static int srv_parse_verifyhost(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8877{
8878 if (!*args[*cur_arg + 1]) {
8879 if (err)
8880 memprintf(err, "'%s' : missing hostname to verify against", args[*cur_arg]);
8881 return ERR_ALERT | ERR_FATAL;
8882 }
8883
Frédéric Lécaille273f3212017-03-13 15:52:01 +01008884 free(newsrv->ssl_ctx.verify_host);
Evan Broderbe554312013-06-27 00:05:25 -07008885 newsrv->ssl_ctx.verify_host = strdup(args[*cur_arg + 1]);
8886
Emeric Brunef42d922012-10-11 16:11:36 +02008887 return 0;
8888}
8889
Emeric Brun2c86cbf2014-10-30 15:56:50 +01008890/* parse the "ssl-default-bind-options" keyword in global section */
8891static int ssl_parse_default_bind_options(char **args, int section_type, struct proxy *curpx,
8892 struct proxy *defpx, const char *file, int line,
8893 char **err) {
8894 int i = 1;
8895
8896 if (*(args[i]) == 0) {
8897 memprintf(err, "global statement '%s' expects an option as an argument.", args[0]);
8898 return -1;
8899 }
8900 while (*(args[i])) {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008901 if (!strcmp(args[i], "no-tls-tickets"))
Willy Tarreauef934602016-12-22 23:12:01 +01008902 global_ssl.listen_default_ssloptions |= BC_SSL_O_NO_TLS_TICKETS;
Lukas Tribus53ae85c2017-05-04 15:45:40 +00008903 else if (!strcmp(args[i], "prefer-client-ciphers"))
8904 global_ssl.listen_default_ssloptions |= BC_SSL_O_PREF_CLIE_CIPH;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008905 else if (!strcmp(args[i], "ssl-min-ver") || !strcmp(args[i], "ssl-max-ver")) {
8906 if (!parse_tls_method_minmax(args, i, &global_ssl.listen_default_sslmethods, err))
8907 i++;
8908 else {
8909 memprintf(err, "%s on global statement '%s'.", *err, args[0]);
8910 return -1;
8911 }
8912 }
8913 else if (parse_tls_method_options(args[i], &global_ssl.listen_default_sslmethods, err)) {
Emeric Brun2c86cbf2014-10-30 15:56:50 +01008914 memprintf(err, "unknown option '%s' on global statement '%s'.", args[i], args[0]);
8915 return -1;
8916 }
8917 i++;
8918 }
8919 return 0;
8920}
8921
8922/* parse the "ssl-default-server-options" keyword in global section */
8923static int ssl_parse_default_server_options(char **args, int section_type, struct proxy *curpx,
8924 struct proxy *defpx, const char *file, int line,
8925 char **err) {
8926 int i = 1;
8927
8928 if (*(args[i]) == 0) {
8929 memprintf(err, "global statement '%s' expects an option as an argument.", args[0]);
8930 return -1;
8931 }
8932 while (*(args[i])) {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008933 if (!strcmp(args[i], "no-tls-tickets"))
Willy Tarreauef934602016-12-22 23:12:01 +01008934 global_ssl.connect_default_ssloptions |= SRV_SSL_O_NO_TLS_TICKETS;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008935 else if (!strcmp(args[i], "ssl-min-ver") || !strcmp(args[i], "ssl-max-ver")) {
8936 if (!parse_tls_method_minmax(args, i, &global_ssl.connect_default_sslmethods, err))
8937 i++;
8938 else {
8939 memprintf(err, "%s on global statement '%s'.", *err, args[0]);
8940 return -1;
8941 }
8942 }
8943 else if (parse_tls_method_options(args[i], &global_ssl.connect_default_sslmethods, err)) {
Emeric Brun2c86cbf2014-10-30 15:56:50 +01008944 memprintf(err, "unknown option '%s' on global statement '%s'.", args[i], args[0]);
8945 return -1;
8946 }
8947 i++;
8948 }
8949 return 0;
8950}
8951
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01008952/* parse the "ca-base" / "crt-base" keywords in global section.
8953 * Returns <0 on alert, >0 on warning, 0 on success.
8954 */
8955static int ssl_parse_global_ca_crt_base(char **args, int section_type, struct proxy *curpx,
8956 struct proxy *defpx, const char *file, int line,
8957 char **err)
8958{
8959 char **target;
8960
Willy Tarreauef934602016-12-22 23:12:01 +01008961 target = (args[0][1] == 'a') ? &global_ssl.ca_base : &global_ssl.crt_base;
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01008962
8963 if (too_many_args(1, args, err, NULL))
8964 return -1;
8965
8966 if (*target) {
8967 memprintf(err, "'%s' already specified.", args[0]);
8968 return -1;
8969 }
8970
8971 if (*(args[1]) == 0) {
8972 memprintf(err, "global statement '%s' expects a directory path as an argument.", args[0]);
8973 return -1;
8974 }
8975 *target = strdup(args[1]);
8976 return 0;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00008977}
8978
8979/* parse the "ssl-mode-async" keyword in global section.
8980 * Returns <0 on alert, >0 on warning, 0 on success.
8981 */
8982static int ssl_parse_global_ssl_async(char **args, int section_type, struct proxy *curpx,
8983 struct proxy *defpx, const char *file, int line,
8984 char **err)
8985{
Willy Tarreau5db847a2019-05-09 14:13:35 +02008986#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00008987 global_ssl.async = 1;
Emeric Brunece0c332017-12-06 13:51:49 +01008988 global.ssl_used_async_engines = nb_engines;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00008989 return 0;
8990#else
8991 memprintf(err, "'%s': openssl library does not support async mode", args[0]);
8992 return -1;
8993#endif
8994}
8995
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008996#ifndef OPENSSL_NO_ENGINE
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00008997static int ssl_check_async_engine_count(void) {
8998 int err_code = 0;
8999
Emeric Brun3854e012017-05-17 20:42:48 +02009000 if (global_ssl.async && (openssl_engines_initialized > 32)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01009001 ha_alert("ssl-mode-async only supports a maximum of 32 engines.\n");
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00009002 err_code = ERR_ABORT;
9003 }
9004 return err_code;
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01009005}
9006
Grant Zhang872f9c22017-01-21 01:10:18 +00009007/* parse the "ssl-engine" keyword in global section.
9008 * Returns <0 on alert, >0 on warning, 0 on success.
9009 */
9010static int ssl_parse_global_ssl_engine(char **args, int section_type, struct proxy *curpx,
9011 struct proxy *defpx, const char *file, int line,
9012 char **err)
9013{
9014 char *algo;
9015 int ret = -1;
9016
9017 if (*(args[1]) == 0) {
9018 memprintf(err, "global statement '%s' expects a valid engine name as an argument.", args[0]);
9019 return ret;
9020 }
9021
9022 if (*(args[2]) == 0) {
9023 /* if no list of algorithms is given, it defaults to ALL */
9024 algo = strdup("ALL");
9025 goto add_engine;
9026 }
9027
9028 /* otherwise the expected format is ssl-engine <engine_name> algo <list of algo> */
9029 if (strcmp(args[2], "algo") != 0) {
9030 memprintf(err, "global statement '%s' expects to have algo keyword.", args[0]);
9031 return ret;
9032 }
9033
9034 if (*(args[3]) == 0) {
9035 memprintf(err, "global statement '%s' expects algorithm names as an argument.", args[0]);
9036 return ret;
9037 }
9038 algo = strdup(args[3]);
9039
9040add_engine:
9041 if (ssl_init_single_engine(args[1], algo)==0) {
9042 openssl_engines_initialized++;
9043 ret = 0;
9044 }
9045 free(algo);
9046 return ret;
9047}
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02009048#endif
Grant Zhang872f9c22017-01-21 01:10:18 +00009049
Willy Tarreauf22e9682016-12-21 23:23:19 +01009050/* parse the "ssl-default-bind-ciphers" / "ssl-default-server-ciphers" keywords
9051 * in global section. Returns <0 on alert, >0 on warning, 0 on success.
9052 */
9053static int ssl_parse_global_ciphers(char **args, int section_type, struct proxy *curpx,
9054 struct proxy *defpx, const char *file, int line,
9055 char **err)
9056{
9057 char **target;
9058
Willy Tarreauef934602016-12-22 23:12:01 +01009059 target = (args[0][12] == 'b') ? &global_ssl.listen_default_ciphers : &global_ssl.connect_default_ciphers;
Willy Tarreauf22e9682016-12-21 23:23:19 +01009060
9061 if (too_many_args(1, args, err, NULL))
9062 return -1;
9063
9064 if (*(args[1]) == 0) {
9065 memprintf(err, "global statement '%s' expects a cipher suite as an argument.", args[0]);
9066 return -1;
9067 }
9068
9069 free(*target);
9070 *target = strdup(args[1]);
9071 return 0;
9072}
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009073
Emmanuel Hocdet839af572019-05-14 16:27:35 +02009074#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009075/* parse the "ssl-default-bind-ciphersuites" / "ssl-default-server-ciphersuites" keywords
9076 * in global section. Returns <0 on alert, >0 on warning, 0 on success.
9077 */
9078static int ssl_parse_global_ciphersuites(char **args, int section_type, struct proxy *curpx,
9079 struct proxy *defpx, const char *file, int line,
9080 char **err)
9081{
9082 char **target;
9083
9084 target = (args[0][12] == 'b') ? &global_ssl.listen_default_ciphersuites : &global_ssl.connect_default_ciphersuites;
9085
9086 if (too_many_args(1, args, err, NULL))
9087 return -1;
9088
9089 if (*(args[1]) == 0) {
9090 memprintf(err, "global statement '%s' expects a cipher suite as an argument.", args[0]);
9091 return -1;
9092 }
9093
9094 free(*target);
9095 *target = strdup(args[1]);
9096 return 0;
9097}
9098#endif
Willy Tarreauf22e9682016-12-21 23:23:19 +01009099
Willy Tarreau9ceda382016-12-21 23:13:03 +01009100/* parse various global tune.ssl settings consisting in positive integers.
9101 * Returns <0 on alert, >0 on warning, 0 on success.
9102 */
9103static int ssl_parse_global_int(char **args, int section_type, struct proxy *curpx,
9104 struct proxy *defpx, const char *file, int line,
9105 char **err)
9106{
9107 int *target;
9108
9109 if (strcmp(args[0], "tune.ssl.cachesize") == 0)
9110 target = &global.tune.sslcachesize;
9111 else if (strcmp(args[0], "tune.ssl.maxrecord") == 0)
Willy Tarreauef934602016-12-22 23:12:01 +01009112 target = (int *)&global_ssl.max_record;
Willy Tarreau9ceda382016-12-21 23:13:03 +01009113 else if (strcmp(args[0], "tune.ssl.ssl-ctx-cache-size") == 0)
Willy Tarreauef934602016-12-22 23:12:01 +01009114 target = &global_ssl.ctx_cache;
Willy Tarreau0bea58d2016-12-21 23:17:25 +01009115 else if (strcmp(args[0], "maxsslconn") == 0)
9116 target = &global.maxsslconn;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01009117 else if (strcmp(args[0], "tune.ssl.capture-cipherlist-size") == 0)
9118 target = &global_ssl.capture_cipherlist;
Willy Tarreau9ceda382016-12-21 23:13:03 +01009119 else {
9120 memprintf(err, "'%s' keyword not unhandled (please report this bug).", args[0]);
9121 return -1;
9122 }
9123
9124 if (too_many_args(1, args, err, NULL))
9125 return -1;
9126
9127 if (*(args[1]) == 0) {
9128 memprintf(err, "'%s' expects an integer argument.", args[0]);
9129 return -1;
9130 }
9131
9132 *target = atoi(args[1]);
9133 if (*target < 0) {
9134 memprintf(err, "'%s' expects a positive numeric value.", args[0]);
9135 return -1;
9136 }
9137 return 0;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01009138}
9139
9140static int ssl_parse_global_capture_cipherlist(char **args, int section_type, struct proxy *curpx,
9141 struct proxy *defpx, const char *file, int line,
9142 char **err)
9143{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01009144 int ret;
9145
9146 ret = ssl_parse_global_int(args, section_type, curpx, defpx, file, line, err);
9147 if (ret != 0)
9148 return ret;
9149
Willy Tarreaubafbe012017-11-24 17:34:44 +01009150 if (pool_head_ssl_capture) {
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01009151 memprintf(err, "'%s' is already configured.", args[0]);
9152 return -1;
9153 }
9154
Willy Tarreaubafbe012017-11-24 17:34:44 +01009155 pool_head_ssl_capture = create_pool("ssl-capture", sizeof(struct ssl_capture) + global_ssl.capture_cipherlist, MEM_F_SHARED);
9156 if (!pool_head_ssl_capture) {
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01009157 memprintf(err, "Out of memory error.");
9158 return -1;
9159 }
9160 return 0;
Willy Tarreau9ceda382016-12-21 23:13:03 +01009161}
9162
9163/* parse "ssl.force-private-cache".
9164 * Returns <0 on alert, >0 on warning, 0 on success.
9165 */
9166static int ssl_parse_global_private_cache(char **args, int section_type, struct proxy *curpx,
9167 struct proxy *defpx, const char *file, int line,
9168 char **err)
9169{
9170 if (too_many_args(0, args, err, NULL))
9171 return -1;
9172
Willy Tarreauef934602016-12-22 23:12:01 +01009173 global_ssl.private_cache = 1;
Willy Tarreau9ceda382016-12-21 23:13:03 +01009174 return 0;
9175}
9176
9177/* parse "ssl.lifetime".
9178 * Returns <0 on alert, >0 on warning, 0 on success.
9179 */
9180static int ssl_parse_global_lifetime(char **args, int section_type, struct proxy *curpx,
9181 struct proxy *defpx, const char *file, int line,
9182 char **err)
9183{
9184 const char *res;
9185
9186 if (too_many_args(1, args, err, NULL))
9187 return -1;
9188
9189 if (*(args[1]) == 0) {
9190 memprintf(err, "'%s' expects ssl sessions <lifetime> in seconds as argument.", args[0]);
9191 return -1;
9192 }
9193
Willy Tarreauef934602016-12-22 23:12:01 +01009194 res = parse_time_err(args[1], &global_ssl.life_time, TIME_UNIT_S);
Willy Tarreau9faebe32019-06-07 19:00:37 +02009195 if (res == PARSE_TIME_OVER) {
9196 memprintf(err, "timer overflow in argument '%s' to <%s> (maximum value is 2147483647 s or ~68 years).",
9197 args[1], args[0]);
9198 return -1;
9199 }
9200 else if (res == PARSE_TIME_UNDER) {
9201 memprintf(err, "timer underflow in argument '%s' to <%s> (minimum non-null value is 1 s).",
9202 args[1], args[0]);
9203 return -1;
9204 }
9205 else if (res) {
Willy Tarreau9ceda382016-12-21 23:13:03 +01009206 memprintf(err, "unexpected character '%c' in argument to <%s>.", *res, args[0]);
9207 return -1;
9208 }
9209 return 0;
9210}
9211
9212#ifndef OPENSSL_NO_DH
Willy Tarreau14e36a12016-12-21 23:28:13 +01009213/* parse "ssl-dh-param-file".
9214 * Returns <0 on alert, >0 on warning, 0 on success.
9215 */
9216static int ssl_parse_global_dh_param_file(char **args, int section_type, struct proxy *curpx,
9217 struct proxy *defpx, const char *file, int line,
9218 char **err)
9219{
9220 if (too_many_args(1, args, err, NULL))
9221 return -1;
9222
9223 if (*(args[1]) == 0) {
9224 memprintf(err, "'%s' expects a file path as an argument.", args[0]);
9225 return -1;
9226 }
9227
9228 if (ssl_sock_load_global_dh_param_from_file(args[1])) {
9229 memprintf(err, "'%s': unable to load DH parameters from file <%s>.", args[0], args[1]);
9230 return -1;
9231 }
9232 return 0;
9233}
9234
Willy Tarreau9ceda382016-12-21 23:13:03 +01009235/* parse "ssl.default-dh-param".
9236 * Returns <0 on alert, >0 on warning, 0 on success.
9237 */
9238static int ssl_parse_global_default_dh(char **args, int section_type, struct proxy *curpx,
9239 struct proxy *defpx, const char *file, int line,
9240 char **err)
9241{
9242 if (too_many_args(1, args, err, NULL))
9243 return -1;
9244
9245 if (*(args[1]) == 0) {
9246 memprintf(err, "'%s' expects an integer argument.", args[0]);
9247 return -1;
9248 }
9249
Willy Tarreauef934602016-12-22 23:12:01 +01009250 global_ssl.default_dh_param = atoi(args[1]);
9251 if (global_ssl.default_dh_param < 1024) {
Willy Tarreau9ceda382016-12-21 23:13:03 +01009252 memprintf(err, "'%s' expects a value >= 1024.", args[0]);
9253 return -1;
9254 }
9255 return 0;
9256}
9257#endif
9258
9259
William Lallemand32af2032016-10-29 18:09:35 +02009260/* This function is used with TLS ticket keys management. It permits to browse
9261 * each reference. The variable <getnext> must contain the current node,
9262 * <end> point to the root node.
9263 */
9264#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
9265static inline
9266struct tls_keys_ref *tlskeys_list_get_next(struct tls_keys_ref *getnext, struct list *end)
9267{
9268 struct tls_keys_ref *ref = getnext;
9269
9270 while (1) {
9271
9272 /* Get next list entry. */
9273 ref = LIST_NEXT(&ref->list, struct tls_keys_ref *, list);
9274
9275 /* If the entry is the last of the list, return NULL. */
9276 if (&ref->list == end)
9277 return NULL;
9278
9279 return ref;
9280 }
9281}
9282
9283static inline
9284struct tls_keys_ref *tlskeys_ref_lookup_ref(const char *reference)
9285{
9286 int id;
9287 char *error;
9288
9289 /* If the reference starts by a '#', this is numeric id. */
9290 if (reference[0] == '#') {
9291 /* Try to convert the numeric id. If the conversion fails, the lookup fails. */
9292 id = strtol(reference + 1, &error, 10);
9293 if (*error != '\0')
9294 return NULL;
9295
9296 /* Perform the unique id lookup. */
9297 return tlskeys_ref_lookupid(id);
9298 }
9299
9300 /* Perform the string lookup. */
9301 return tlskeys_ref_lookup(reference);
9302}
9303#endif
9304
9305
9306#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
9307
9308static int cli_io_handler_tlskeys_files(struct appctx *appctx);
9309
9310static inline int cli_io_handler_tlskeys_entries(struct appctx *appctx) {
9311 return cli_io_handler_tlskeys_files(appctx);
9312}
9313
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009314/* dumps all tls keys. Relies on cli.i0 (non-null = only list file names), cli.i1
9315 * (next index to be dumped), and cli.p0 (next key reference).
9316 */
William Lallemand32af2032016-10-29 18:09:35 +02009317static int cli_io_handler_tlskeys_files(struct appctx *appctx) {
9318
9319 struct stream_interface *si = appctx->owner;
9320
9321 switch (appctx->st2) {
9322 case STAT_ST_INIT:
9323 /* Display the column headers. If the message cannot be sent,
Joseph Herlant017b3da2018-11-15 09:07:59 -08009324 * quit the function with returning 0. The function is called
William Lallemand32af2032016-10-29 18:09:35 +02009325 * later and restart at the state "STAT_ST_INIT".
9326 */
9327 chunk_reset(&trash);
9328
9329 if (appctx->io_handler == cli_io_handler_tlskeys_entries)
9330 chunk_appendf(&trash, "# id secret\n");
9331 else
9332 chunk_appendf(&trash, "# id (file)\n");
9333
Willy Tarreau06d80a92017-10-19 14:32:15 +02009334 if (ci_putchk(si_ic(si), &trash) == -1) {
Willy Tarreaudb398432018-11-15 11:08:52 +01009335 si_rx_room_blk(si);
William Lallemand32af2032016-10-29 18:09:35 +02009336 return 0;
9337 }
9338
William Lallemand32af2032016-10-29 18:09:35 +02009339 /* Now, we start the browsing of the references lists.
9340 * Note that the following call to LIST_ELEM return bad pointer. The only
9341 * available field of this pointer is <list>. It is used with the function
9342 * tlskeys_list_get_next() for retruning the first available entry
9343 */
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009344 if (appctx->ctx.cli.p0 == NULL) {
9345 appctx->ctx.cli.p0 = LIST_ELEM(&tlskeys_reference, struct tls_keys_ref *, list);
9346 appctx->ctx.cli.p0 = tlskeys_list_get_next(appctx->ctx.cli.p0, &tlskeys_reference);
William Lallemand32af2032016-10-29 18:09:35 +02009347 }
9348
9349 appctx->st2 = STAT_ST_LIST;
9350 /* fall through */
9351
9352 case STAT_ST_LIST:
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009353 while (appctx->ctx.cli.p0) {
9354 struct tls_keys_ref *ref = appctx->ctx.cli.p0;
William Lallemand32af2032016-10-29 18:09:35 +02009355
9356 chunk_reset(&trash);
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009357 if (appctx->io_handler == cli_io_handler_tlskeys_entries && appctx->ctx.cli.i1 == 0)
William Lallemand32af2032016-10-29 18:09:35 +02009358 chunk_appendf(&trash, "# ");
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009359
9360 if (appctx->ctx.cli.i1 == 0)
9361 chunk_appendf(&trash, "%d (%s)\n", ref->unique_id, ref->filename);
9362
William Lallemand32af2032016-10-29 18:09:35 +02009363 if (appctx->io_handler == cli_io_handler_tlskeys_entries) {
Christopher Faulet16f45c82018-02-16 11:23:49 +01009364 int head;
9365
9366 HA_RWLOCK_RDLOCK(TLSKEYS_REF_LOCK, &ref->lock);
9367 head = ref->tls_ticket_enc_index;
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009368 while (appctx->ctx.cli.i1 < TLS_TICKETS_NO) {
Willy Tarreau83061a82018-07-13 11:56:34 +02009369 struct buffer *t2 = get_trash_chunk();
William Lallemand32af2032016-10-29 18:09:35 +02009370
9371 chunk_reset(t2);
9372 /* should never fail here because we dump only a key in the t2 buffer */
Emeric Brun9e754772019-01-10 17:51:55 +01009373 if (ref->key_size_bits == 128) {
9374 t2->data = a2base64((char *)(ref->tlskeys + (head + 2 + appctx->ctx.cli.i1) % TLS_TICKETS_NO),
9375 sizeof(struct tls_sess_key_128),
9376 t2->area, t2->size);
9377 chunk_appendf(&trash, "%d.%d %s\n", ref->unique_id, appctx->ctx.cli.i1,
9378 t2->area);
9379 }
9380 else if (ref->key_size_bits == 256) {
9381 t2->data = a2base64((char *)(ref->tlskeys + (head + 2 + appctx->ctx.cli.i1) % TLS_TICKETS_NO),
9382 sizeof(struct tls_sess_key_256),
9383 t2->area, t2->size);
9384 chunk_appendf(&trash, "%d.%d %s\n", ref->unique_id, appctx->ctx.cli.i1,
9385 t2->area);
9386 }
9387 else {
9388 /* This case should never happen */
9389 chunk_appendf(&trash, "%d.%d <unknown>\n", ref->unique_id, appctx->ctx.cli.i1);
9390 }
William Lallemand32af2032016-10-29 18:09:35 +02009391
Willy Tarreau06d80a92017-10-19 14:32:15 +02009392 if (ci_putchk(si_ic(si), &trash) == -1) {
William Lallemand32af2032016-10-29 18:09:35 +02009393 /* let's try again later from this stream. We add ourselves into
9394 * this stream's users so that it can remove us upon termination.
9395 */
Christopher Faulet16f45c82018-02-16 11:23:49 +01009396 HA_RWLOCK_RDUNLOCK(TLSKEYS_REF_LOCK, &ref->lock);
Willy Tarreaudb398432018-11-15 11:08:52 +01009397 si_rx_room_blk(si);
William Lallemand32af2032016-10-29 18:09:35 +02009398 return 0;
9399 }
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009400 appctx->ctx.cli.i1++;
William Lallemand32af2032016-10-29 18:09:35 +02009401 }
Christopher Faulet16f45c82018-02-16 11:23:49 +01009402 HA_RWLOCK_RDUNLOCK(TLSKEYS_REF_LOCK, &ref->lock);
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009403 appctx->ctx.cli.i1 = 0;
William Lallemand32af2032016-10-29 18:09:35 +02009404 }
Willy Tarreau06d80a92017-10-19 14:32:15 +02009405 if (ci_putchk(si_ic(si), &trash) == -1) {
William Lallemand32af2032016-10-29 18:09:35 +02009406 /* let's try again later from this stream. We add ourselves into
9407 * this stream's users so that it can remove us upon termination.
9408 */
Willy Tarreaudb398432018-11-15 11:08:52 +01009409 si_rx_room_blk(si);
William Lallemand32af2032016-10-29 18:09:35 +02009410 return 0;
9411 }
9412
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009413 if (appctx->ctx.cli.i0 == 0) /* don't display everything if not necessary */
William Lallemand32af2032016-10-29 18:09:35 +02009414 break;
9415
9416 /* get next list entry and check the end of the list */
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009417 appctx->ctx.cli.p0 = tlskeys_list_get_next(appctx->ctx.cli.p0, &tlskeys_reference);
William Lallemand32af2032016-10-29 18:09:35 +02009418 }
9419
9420 appctx->st2 = STAT_ST_FIN;
9421 /* fall through */
9422
9423 default:
9424 appctx->st2 = STAT_ST_FIN;
9425 return 1;
9426 }
9427 return 0;
9428}
9429
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009430/* sets cli.i0 to non-zero if only file lists should be dumped */
Aurélien Nephtaliabbf6072018-04-18 13:26:46 +02009431static int cli_parse_show_tlskeys(char **args, char *payload, struct appctx *appctx, void *private)
William Lallemand32af2032016-10-29 18:09:35 +02009432{
William Lallemand32af2032016-10-29 18:09:35 +02009433 /* no parameter, shows only file list */
9434 if (!*args[2]) {
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009435 appctx->ctx.cli.i0 = 1;
William Lallemand32af2032016-10-29 18:09:35 +02009436 appctx->io_handler = cli_io_handler_tlskeys_files;
Willy Tarreau3067bfa2016-12-05 14:50:15 +01009437 return 0;
William Lallemand32af2032016-10-29 18:09:35 +02009438 }
9439
9440 if (args[2][0] == '*') {
9441 /* list every TLS ticket keys */
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009442 appctx->ctx.cli.i0 = 1;
William Lallemand32af2032016-10-29 18:09:35 +02009443 } else {
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009444 appctx->ctx.cli.p0 = tlskeys_ref_lookup_ref(args[2]);
9445 if (!appctx->ctx.cli.p0) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02009446 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02009447 appctx->ctx.cli.msg = "'show tls-keys' unable to locate referenced filename\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01009448 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02009449 return 1;
9450 }
9451 }
William Lallemand32af2032016-10-29 18:09:35 +02009452 appctx->io_handler = cli_io_handler_tlskeys_entries;
Willy Tarreau3067bfa2016-12-05 14:50:15 +01009453 return 0;
William Lallemand32af2032016-10-29 18:09:35 +02009454}
9455
Aurélien Nephtaliabbf6072018-04-18 13:26:46 +02009456static int cli_parse_set_tlskeys(char **args, char *payload, struct appctx *appctx, void *private)
William Lallemand32af2032016-10-29 18:09:35 +02009457{
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009458 struct tls_keys_ref *ref;
Willy Tarreau1c913e42018-08-22 05:26:57 +02009459 int ret;
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009460
William Lallemand32af2032016-10-29 18:09:35 +02009461 /* Expect two parameters: the filename and the new new TLS key in encoding */
9462 if (!*args[3] || !*args[4]) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02009463 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02009464 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 +01009465 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02009466 return 1;
9467 }
9468
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009469 ref = tlskeys_ref_lookup_ref(args[3]);
9470 if (!ref) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02009471 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02009472 appctx->ctx.cli.msg = "'set ssl tls-key' unable to locate referenced filename\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01009473 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02009474 return 1;
9475 }
9476
Willy Tarreau1c913e42018-08-22 05:26:57 +02009477 ret = base64dec(args[4], strlen(args[4]), trash.area, trash.size);
Emeric Brun9e754772019-01-10 17:51:55 +01009478 if (ret < 0) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02009479 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02009480 appctx->ctx.cli.msg = "'set ssl tls-key' received invalid base64 encoded TLS key.\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01009481 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02009482 return 1;
9483 }
Emeric Brun9e754772019-01-10 17:51:55 +01009484
Willy Tarreau1c913e42018-08-22 05:26:57 +02009485 trash.data = ret;
Emeric Brun9e754772019-01-10 17:51:55 +01009486 if (ssl_sock_update_tlskey_ref(ref, &trash) < 0) {
9487 appctx->ctx.cli.severity = LOG_ERR;
9488 appctx->ctx.cli.msg = "'set ssl tls-key' received a key of wrong size.\n";
9489 appctx->st0 = CLI_ST_PRINT;
9490 return 1;
9491 }
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02009492 appctx->ctx.cli.severity = LOG_INFO;
Aurélien Nephtali6e8a41d2018-03-15 21:48:50 +01009493 appctx->ctx.cli.msg = "TLS ticket key updated!\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}
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01009498#endif
William Lallemand32af2032016-10-29 18:09:35 +02009499
Aurélien Nephtaliabbf6072018-04-18 13:26:46 +02009500static int cli_parse_set_ocspresponse(char **args, char *payload, struct appctx *appctx, void *private)
William Lallemand32af2032016-10-29 18:09:35 +02009501{
9502#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
9503 char *err = NULL;
Willy Tarreau1c913e42018-08-22 05:26:57 +02009504 int i, j, ret;
Aurélien Nephtali1e0867c2018-04-18 14:04:58 +02009505
9506 if (!payload)
9507 payload = args[3];
William Lallemand32af2032016-10-29 18:09:35 +02009508
9509 /* Expect one parameter: the new response in base64 encoding */
Aurélien Nephtali1e0867c2018-04-18 14:04:58 +02009510 if (!*payload) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02009511 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02009512 appctx->ctx.cli.msg = "'set ssl ocsp-response' expects response in base64 encoding.\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01009513 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02009514 return 1;
9515 }
Aurélien Nephtali1e0867c2018-04-18 14:04:58 +02009516
9517 /* remove \r and \n from the payload */
9518 for (i = 0, j = 0; payload[i]; i++) {
9519 if (payload[i] == '\r' || payload[i] == '\n')
9520 continue;
9521 payload[j++] = payload[i];
9522 }
9523 payload[j] = 0;
William Lallemand32af2032016-10-29 18:09:35 +02009524
Willy Tarreau1c913e42018-08-22 05:26:57 +02009525 ret = base64dec(payload, j, trash.area, trash.size);
9526 if (ret < 0) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02009527 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02009528 appctx->ctx.cli.msg = "'set ssl ocsp-response' received invalid base64 encoded response.\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01009529 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02009530 return 1;
9531 }
9532
Willy Tarreau1c913e42018-08-22 05:26:57 +02009533 trash.data = ret;
William Lallemand32af2032016-10-29 18:09:35 +02009534 if (ssl_sock_update_ocsp_response(&trash, &err)) {
9535 if (err) {
9536 memprintf(&err, "%s.\n", err);
9537 appctx->ctx.cli.err = err;
Willy Tarreau3b6e5472016-11-24 15:53:53 +01009538 appctx->st0 = CLI_ST_PRINT_FREE;
William Lallemand32af2032016-10-29 18:09:35 +02009539 }
Aurélien Nephtali9a4da682018-04-16 19:02:42 +02009540 else {
9541 appctx->ctx.cli.severity = LOG_ERR;
9542 appctx->ctx.cli.msg = "Failed to update OCSP response.\n";
9543 appctx->st0 = CLI_ST_PRINT;
9544 }
William Lallemand32af2032016-10-29 18:09:35 +02009545 return 1;
9546 }
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02009547 appctx->ctx.cli.severity = LOG_INFO;
Aurélien Nephtali6e8a41d2018-03-15 21:48:50 +01009548 appctx->ctx.cli.msg = "OCSP Response updated!\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01009549 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02009550 return 1;
9551#else
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02009552 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02009553 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 +01009554 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02009555 return 1;
9556#endif
9557
Nenad Merdanovicc31499d2019-03-23 11:00:32 +01009558}
9559
Willy Tarreau86a394e2019-05-09 14:15:32 +02009560#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000100fL)
Nenad Merdanovicc31499d2019-03-23 11:00:32 +01009561static inline int sample_conv_var2smp_str(const struct arg *arg, struct sample *smp)
9562{
9563 switch (arg->type) {
9564 case ARGT_STR:
9565 smp->data.type = SMP_T_STR;
9566 smp->data.u.str = arg->data.str;
9567 return 1;
9568 case ARGT_VAR:
9569 if (!vars_get_by_desc(&arg->data.var, smp))
9570 return 0;
9571 if (!sample_casts[smp->data.type][SMP_T_STR])
9572 return 0;
9573 if (!sample_casts[smp->data.type][SMP_T_STR](smp))
9574 return 0;
9575 return 1;
9576 default:
9577 return 0;
9578 }
9579}
9580
9581static int check_aes_gcm(struct arg *args, struct sample_conv *conv,
9582 const char *file, int line, char **err)
9583{
9584 switch(args[0].data.sint) {
9585 case 128:
9586 case 192:
9587 case 256:
9588 break;
9589 default:
9590 memprintf(err, "key size must be 128, 192 or 256 (bits).");
9591 return 0;
9592 }
9593 /* Try to decode a variable. */
9594 vars_check_arg(&args[1], NULL);
9595 vars_check_arg(&args[2], NULL);
9596 vars_check_arg(&args[3], NULL);
9597 return 1;
9598}
9599
9600/* Arguements: AES size in bits, nonce, key, tag. The last three arguments are base64 encoded */
9601static int sample_conv_aes_gcm_dec(const struct arg *arg_p, struct sample *smp, void *private)
9602{
9603 struct sample nonce, key, aead_tag;
9604 struct buffer *smp_trash, *smp_trash_alloc;
9605 EVP_CIPHER_CTX *ctx;
9606 int dec_size, ret;
9607
9608 smp_set_owner(&nonce, smp->px, smp->sess, smp->strm, smp->opt);
9609 if (!sample_conv_var2smp_str(&arg_p[1], &nonce))
9610 return 0;
9611
9612 smp_set_owner(&key, smp->px, smp->sess, smp->strm, smp->opt);
9613 if (!sample_conv_var2smp_str(&arg_p[2], &key))
9614 return 0;
9615
9616 smp_set_owner(&aead_tag, smp->px, smp->sess, smp->strm, smp->opt);
9617 if (!sample_conv_var2smp_str(&arg_p[3], &aead_tag))
9618 return 0;
9619
9620 smp_trash = get_trash_chunk();
9621 smp_trash_alloc = alloc_trash_chunk();
9622 if (!smp_trash_alloc)
9623 return 0;
9624
9625 ctx = EVP_CIPHER_CTX_new();
9626
9627 if (!ctx)
9628 goto err;
9629
9630 dec_size = base64dec(nonce.data.u.str.area, nonce.data.u.str.data, smp_trash->area, smp_trash->size);
9631 if (dec_size < 0)
9632 goto err;
9633 smp_trash->data = dec_size;
9634
9635 /* Set cipher type and mode */
9636 switch(arg_p[0].data.sint) {
9637 case 128:
9638 EVP_DecryptInit_ex(ctx, EVP_aes_128_gcm(), NULL, NULL, NULL);
9639 break;
9640 case 192:
9641 EVP_DecryptInit_ex(ctx, EVP_aes_192_gcm(), NULL, NULL, NULL);
9642 break;
9643 case 256:
9644 EVP_DecryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL);
9645 break;
9646 }
9647
9648 EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, smp_trash->data, NULL);
9649
9650 /* Initialise IV */
9651 if(!EVP_DecryptInit_ex(ctx, NULL, NULL, NULL, (unsigned char *) smp_trash->area))
9652 goto err;
9653
9654 dec_size = base64dec(key.data.u.str.area, key.data.u.str.data, smp_trash->area, smp_trash->size);
9655 if (dec_size < 0)
9656 goto err;
9657 smp_trash->data = dec_size;
9658
9659 /* Initialise key */
9660 if (!EVP_DecryptInit_ex(ctx, NULL, NULL, (unsigned char *) smp_trash->area, NULL))
9661 goto err;
9662
9663 if (!EVP_DecryptUpdate(ctx, (unsigned char *) smp_trash->area, (int *) &smp_trash->data,
9664 (unsigned char *) smp->data.u.str.area, (int) smp->data.u.str.data))
9665 goto err;
9666
9667 dec_size = base64dec(aead_tag.data.u.str.area, aead_tag.data.u.str.data, smp_trash_alloc->area, smp_trash_alloc->size);
9668 if (dec_size < 0)
9669 goto err;
9670 smp_trash_alloc->data = dec_size;
9671 dec_size = smp_trash->data;
9672
9673 EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, smp_trash_alloc->data, (void *) smp_trash_alloc->area);
9674 ret = EVP_DecryptFinal_ex(ctx, (unsigned char *) smp_trash->area + smp_trash->data, (int *) &smp_trash->data);
9675
9676 if (ret <= 0)
9677 goto err;
9678
9679 smp->data.u.str.data = dec_size + smp_trash->data;
9680 smp->data.u.str.area = smp_trash->area;
9681 smp->data.type = SMP_T_BIN;
9682 smp->flags &= ~SMP_F_CONST;
9683 free_trash_chunk(smp_trash_alloc);
9684 return 1;
9685
9686err:
9687 free_trash_chunk(smp_trash_alloc);
9688 return 0;
William Lallemand32af2032016-10-29 18:09:35 +02009689}
Nenad Merdanovicc31499d2019-03-23 11:00:32 +01009690# endif
William Lallemand32af2032016-10-29 18:09:35 +02009691
9692/* register cli keywords */
9693static struct cli_kw_list cli_kws = {{ },{
9694#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
9695 { { "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 +02009696 { { "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 +02009697#endif
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01009698 { { "set", "ssl", "ocsp-response", NULL }, NULL, cli_parse_set_ocspresponse, NULL },
William Lallemand32af2032016-10-29 18:09:35 +02009699 { { NULL }, NULL, NULL, NULL }
9700}};
9701
Willy Tarreau0108d902018-11-25 19:14:37 +01009702INITCALL1(STG_REGISTER, cli_register_kw, &cli_kws);
William Lallemand32af2032016-10-29 18:09:35 +02009703
Willy Tarreau7875d092012-09-10 08:20:03 +02009704/* Note: must not be declared <const> as its list will be overwritten.
9705 * Please take care of keeping this list alphabetically sorted.
9706 */
Willy Tarreaudc13c112013-06-21 23:16:39 +02009707static struct sample_fetch_kw_list sample_fetch_keywords = {ILH, {
Emeric Brun645ae792014-04-30 14:21:06 +02009708 { "ssl_bc", smp_fetch_ssl_fc, 0, NULL, SMP_T_BOOL, SMP_USE_L5SRV },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02009709 { "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 +01009710#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Jérôme Magnine064a802018-12-03 22:21:04 +01009711 { "ssl_bc_alpn", smp_fetch_ssl_fc_alpn, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
Olivier Houchard6b77f492018-11-22 18:18:29 +01009712#endif
Emeric Brun645ae792014-04-30 14:21:06 +02009713 { "ssl_bc_cipher", smp_fetch_ssl_fc_cipher, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
Olivier Houchard6b77f492018-11-22 18:18:29 +01009714#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
9715 { "ssl_bc_npn", smp_fetch_ssl_fc_npn, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
9716#endif
Emeric Brun74f7ffa2018-02-19 16:14:12 +01009717 { "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 +02009718 { "ssl_bc_protocol", smp_fetch_ssl_fc_protocol, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
Emeric Brunb73a9b02014-04-30 18:49:19 +02009719 { "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 +02009720 { "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 +02009721#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
Emeric Brun645ae792014-04-30 14:21:06 +02009722 { "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 -04009723#endif
Emmanuel Hocdet839af572019-05-14 16:27:35 +02009724#if HA_OPENSSL_VERSION_NUMBER >= 0x10100000L
Patrick Hemmer65674662019-06-04 08:13:03 -04009725 { "ssl_bc_client_random", smp_fetch_ssl_fc_random, 0, NULL, SMP_T_BIN, SMP_USE_L5SRV },
9726 { "ssl_bc_server_random", smp_fetch_ssl_fc_random, 0, NULL, SMP_T_BIN, SMP_USE_L5SRV },
Patrick Hemmere0275472018-04-28 19:15:51 -04009727 { "ssl_bc_session_key", smp_fetch_ssl_fc_session_key, 0, NULL, SMP_T_BIN, SMP_USE_L5SRV },
9728#endif
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02009729 { "ssl_c_ca_err", smp_fetch_ssl_c_ca_err, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
9730 { "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 +01009731 { "ssl_c_der", smp_fetch_ssl_x_der, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02009732 { "ssl_c_err", smp_fetch_ssl_c_err, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Emeric Brunba841a12014-04-30 17:05:08 +02009733 { "ssl_c_i_dn", smp_fetch_ssl_x_i_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
9734 { "ssl_c_key_alg", smp_fetch_ssl_x_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
9735 { "ssl_c_notafter", smp_fetch_ssl_x_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
9736 { "ssl_c_notbefore", smp_fetch_ssl_x_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
9737 { "ssl_c_sig_alg", smp_fetch_ssl_x_sig_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
9738 { "ssl_c_s_dn", smp_fetch_ssl_x_s_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
9739 { "ssl_c_serial", smp_fetch_ssl_x_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
9740 { "ssl_c_sha1", smp_fetch_ssl_x_sha1, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +01009741 { "ssl_c_used", smp_fetch_ssl_c_used, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02009742 { "ssl_c_verify", smp_fetch_ssl_c_verify, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
9743 { "ssl_c_version", smp_fetch_ssl_x_version, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Emeric Brun43e79582014-10-29 19:03:26 +01009744 { "ssl_f_der", smp_fetch_ssl_x_der, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Emeric Brunba841a12014-04-30 17:05:08 +02009745 { "ssl_f_i_dn", smp_fetch_ssl_x_i_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
9746 { "ssl_f_key_alg", smp_fetch_ssl_x_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
9747 { "ssl_f_notafter", smp_fetch_ssl_x_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
9748 { "ssl_f_notbefore", smp_fetch_ssl_x_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
9749 { "ssl_f_sig_alg", smp_fetch_ssl_x_sig_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
9750 { "ssl_f_s_dn", smp_fetch_ssl_x_s_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
9751 { "ssl_f_serial", smp_fetch_ssl_x_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Emeric Brun55f4fa82014-04-30 17:11:25 +02009752 { "ssl_f_sha1", smp_fetch_ssl_x_sha1, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02009753 { "ssl_f_version", smp_fetch_ssl_x_version, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +01009754 { "ssl_fc", smp_fetch_ssl_fc, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02009755 { "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 +01009756 { "ssl_fc_cipher", smp_fetch_ssl_fc_cipher, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +01009757 { "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 +02009758 { "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 +01009759 { "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 +02009760 { "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 +01009761#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01009762 { "ssl_fc_npn", smp_fetch_ssl_fc_npn, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreaua33c6542012-10-15 13:19:06 +02009763#endif
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01009764#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01009765 { "ssl_fc_alpn", smp_fetch_ssl_fc_alpn, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreauab861d32013-04-02 02:30:41 +02009766#endif
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01009767 { "ssl_fc_protocol", smp_fetch_ssl_fc_protocol, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreau9a1ab082019-05-09 13:26:41 +02009768#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
Emeric Brunb73a9b02014-04-30 18:49:19 +02009769 { "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 -04009770#endif
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02009771 { "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 +02009772#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01009773 { "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 -04009774#endif
Emmanuel Hocdet839af572019-05-14 16:27:35 +02009775#if HA_OPENSSL_VERSION_NUMBER >= 0x10100000L
Patrick Hemmer65674662019-06-04 08:13:03 -04009776 { "ssl_fc_client_random", smp_fetch_ssl_fc_random, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
9777 { "ssl_fc_server_random", smp_fetch_ssl_fc_random, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Patrick Hemmere0275472018-04-28 19:15:51 -04009778 { "ssl_fc_session_key", smp_fetch_ssl_fc_session_key, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
9779#endif
Patrick Hemmer41966772018-04-28 19:15:48 -04009780#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01009781 { "ssl_fc_sni", smp_fetch_ssl_fc_sni, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Patrick Hemmer41966772018-04-28 19:15:48 -04009782#endif
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01009783 { "ssl_fc_cipherlist_bin", smp_fetch_ssl_fc_cl_bin, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
9784 { "ssl_fc_cipherlist_hex", smp_fetch_ssl_fc_cl_hex, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
9785 { "ssl_fc_cipherlist_str", smp_fetch_ssl_fc_cl_str, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
9786 { "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 +02009787 { NULL, NULL, 0, 0, 0 },
9788}};
9789
Willy Tarreau0108d902018-11-25 19:14:37 +01009790INITCALL1(STG_REGISTER, sample_register_fetches, &sample_fetch_keywords);
9791
Willy Tarreau7875d092012-09-10 08:20:03 +02009792/* Note: must not be declared <const> as its list will be overwritten.
9793 * Please take care of keeping this list alphabetically sorted.
9794 */
Willy Tarreaudc13c112013-06-21 23:16:39 +02009795static struct acl_kw_list acl_kws = {ILH, {
Thierry FOURNIERc5a4e982014-03-05 16:07:08 +01009796 { "ssl_fc_sni_end", "ssl_fc_sni", PAT_MATCH_END },
9797 { "ssl_fc_sni_reg", "ssl_fc_sni", PAT_MATCH_REG },
Willy Tarreau8ed669b2013-01-11 15:49:37 +01009798 { /* END */ },
Willy Tarreau7875d092012-09-10 08:20:03 +02009799}};
9800
Willy Tarreau0108d902018-11-25 19:14:37 +01009801INITCALL1(STG_REGISTER, acl_register_keywords, &acl_kws);
9802
Willy Tarreau79eeafa2012-09-14 07:53:05 +02009803/* Note: must not be declared <const> as its list will be overwritten.
9804 * Please take care of keeping this list alphabetically sorted, doing so helps
9805 * all code contributors.
9806 * Optional keywords are also declared with a NULL ->parse() function so that
9807 * the config parser can report an appropriate error when a known keyword was
9808 * not enabled.
9809 */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01009810static struct ssl_bind_kw ssl_bind_kws[] = {
Olivier Houchardc2aae742017-09-22 18:26:28 +02009811 { "allow-0rtt", ssl_bind_parse_allow_0rtt, 0 }, /* allow 0-RTT */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01009812 { "alpn", ssl_bind_parse_alpn, 1 }, /* set ALPN supported protocols */
9813 { "ca-file", ssl_bind_parse_ca_file, 1 }, /* set CAfile to process verify on client cert */
9814 { "ciphers", ssl_bind_parse_ciphers, 1 }, /* set SSL cipher suite */
Emmanuel Hocdet839af572019-05-14 16:27:35 +02009815#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009816 { "ciphersuites", ssl_bind_parse_ciphersuites, 1 }, /* set TLS 1.3 cipher suite */
9817#endif
Emmanuel Hocdet98263292016-12-29 18:26:15 +01009818 { "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 +01009819 { "curves", ssl_bind_parse_curves, 1 }, /* set SSL curve suite */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01009820 { "ecdhe", ssl_bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02009821 { "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 +01009822 { "npn", ssl_bind_parse_npn, 1 }, /* set NPN supported protocols */
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02009823 { "ssl-min-ver", ssl_bind_parse_tls_method_minmax,1 }, /* minimum version */
9824 { "ssl-max-ver", ssl_bind_parse_tls_method_minmax,1 }, /* maximum version */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01009825 { "verify", ssl_bind_parse_verify, 1 }, /* set SSL verify method */
9826 { NULL, NULL, 0 },
9827};
9828
Willy Tarreau0108d902018-11-25 19:14:37 +01009829/* no initcall for ssl_bind_kws, these ones are parsed in the parser loop */
9830
Willy Tarreau51fb7652012-09-18 18:24:39 +02009831static struct bind_kw_list bind_kws = { "SSL", { }, {
Olivier Houchardc2aae742017-09-22 18:26:28 +02009832 { "allow-0rtt", bind_parse_allow_0rtt, 0 }, /* Allow 0RTT */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02009833 { "alpn", bind_parse_alpn, 1 }, /* set ALPN supported protocols */
9834 { "ca-file", bind_parse_ca_file, 1 }, /* set CAfile to process verify on client cert */
9835 { "ca-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ignore on verify depth > 0 */
9836 { "ca-sign-file", bind_parse_ca_sign_file, 1 }, /* set CAFile used to generate and sign server certs */
9837 { "ca-sign-pass", bind_parse_ca_sign_pass, 1 }, /* set CAKey passphrase */
9838 { "ciphers", bind_parse_ciphers, 1 }, /* set SSL cipher suite */
Emmanuel Hocdet839af572019-05-14 16:27:35 +02009839#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009840 { "ciphersuites", bind_parse_ciphersuites, 1 }, /* set TLS 1.3 cipher suite */
9841#endif
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02009842 { "crl-file", bind_parse_crl_file, 1 }, /* set certificat revocation list file use on client cert verify */
9843 { "crt", bind_parse_crt, 1 }, /* load SSL certificates from this location */
9844 { "crt-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ingore on verify depth == 0 */
9845 { "crt-list", bind_parse_crt_list, 1 }, /* load a list of crt from this location */
9846 { "curves", bind_parse_curves, 1 }, /* set SSL curve suite */
9847 { "ecdhe", bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
9848 { "force-sslv3", bind_parse_tls_method_options, 0 }, /* force SSLv3 */
9849 { "force-tlsv10", bind_parse_tls_method_options, 0 }, /* force TLSv10 */
9850 { "force-tlsv11", bind_parse_tls_method_options, 0 }, /* force TLSv11 */
9851 { "force-tlsv12", bind_parse_tls_method_options, 0 }, /* force TLSv12 */
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +02009852 { "force-tlsv13", bind_parse_tls_method_options, 0 }, /* force TLSv13 */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02009853 { "generate-certificates", bind_parse_generate_certs, 0 }, /* enable the server certificates generation */
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02009854 { "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 +02009855 { "no-sslv3", bind_parse_tls_method_options, 0 }, /* disable SSLv3 */
9856 { "no-tlsv10", bind_parse_tls_method_options, 0 }, /* disable TLSv10 */
9857 { "no-tlsv11", bind_parse_tls_method_options, 0 }, /* disable TLSv11 */
9858 { "no-tlsv12", bind_parse_tls_method_options, 0 }, /* disable TLSv12 */
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +02009859 { "no-tlsv13", bind_parse_tls_method_options, 0 }, /* disable TLSv13 */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02009860 { "no-tls-tickets", bind_parse_no_tls_tickets, 0 }, /* disable session resumption tickets */
9861 { "ssl", bind_parse_ssl, 0 }, /* enable SSL processing */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02009862 { "ssl-min-ver", bind_parse_tls_method_minmax, 1 }, /* minimum version */
9863 { "ssl-max-ver", bind_parse_tls_method_minmax, 1 }, /* maximum version */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02009864 { "strict-sni", bind_parse_strict_sni, 0 }, /* refuse negotiation if sni doesn't match a certificate */
9865 { "tls-ticket-keys", bind_parse_tls_ticket_keys, 1 }, /* set file to load TLS ticket keys from */
9866 { "verify", bind_parse_verify, 1 }, /* set SSL verify method */
9867 { "npn", bind_parse_npn, 1 }, /* set NPN supported protocols */
9868 { "prefer-client-ciphers", bind_parse_pcc, 0 }, /* prefer client ciphers */
Willy Tarreau79eeafa2012-09-14 07:53:05 +02009869 { NULL, NULL, 0 },
9870}};
Emeric Brun46591952012-05-18 15:47:34 +02009871
Willy Tarreau0108d902018-11-25 19:14:37 +01009872INITCALL1(STG_REGISTER, bind_register_keywords, &bind_kws);
9873
Willy Tarreau92faadf2012-10-10 23:04:25 +02009874/* Note: must not be declared <const> as its list will be overwritten.
9875 * Please take care of keeping this list alphabetically sorted, doing so helps
9876 * all code contributors.
9877 * Optional keywords are also declared with a NULL ->parse() function so that
9878 * the config parser can report an appropriate error when a known keyword was
9879 * not enabled.
9880 */
9881static struct srv_kw_list srv_kws = { "SSL", { }, {
Olivier Houchard522eea72017-11-03 16:27:47 +01009882 { "allow-0rtt", srv_parse_allow_0rtt, 0, 1 }, /* Allow using early data on this server */
Olivier Houchardc7566002018-11-20 23:33:50 +01009883 { "alpn", srv_parse_alpn, 1, 1 }, /* Set ALPN supported protocols */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02009884 { "ca-file", srv_parse_ca_file, 1, 1 }, /* set CAfile to process verify server cert */
Olivier Houchard92150142018-12-21 19:47:01 +01009885 { "check-alpn", srv_parse_alpn, 1, 1 }, /* Set ALPN used for checks */
Olivier Houchard9130a962017-10-17 17:33:43 +02009886 { "check-sni", srv_parse_check_sni, 1, 1 }, /* set SNI */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02009887 { "check-ssl", srv_parse_check_ssl, 0, 1 }, /* enable SSL for health checks */
9888 { "ciphers", srv_parse_ciphers, 1, 1 }, /* select the cipher suite */
Emmanuel Hocdet839af572019-05-14 16:27:35 +02009889#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009890 { "ciphersuites", srv_parse_ciphersuites, 1, 1 }, /* select the cipher suite */
9891#endif
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02009892 { "crl-file", srv_parse_crl_file, 1, 1 }, /* set certificate revocation list file use on server cert verify */
9893 { "crt", srv_parse_crt, 1, 1 }, /* set client certificate */
9894 { "force-sslv3", srv_parse_tls_method_options, 0, 1 }, /* force SSLv3 */
9895 { "force-tlsv10", srv_parse_tls_method_options, 0, 1 }, /* force TLSv10 */
9896 { "force-tlsv11", srv_parse_tls_method_options, 0, 1 }, /* force TLSv11 */
9897 { "force-tlsv12", srv_parse_tls_method_options, 0, 1 }, /* force TLSv12 */
9898 { "force-tlsv13", srv_parse_tls_method_options, 0, 1 }, /* force TLSv13 */
9899 { "no-check-ssl", srv_parse_no_check_ssl, 0, 1 }, /* disable SSL for health checks */
9900 { "no-send-proxy-v2-ssl", srv_parse_no_send_proxy_ssl, 0, 1 }, /* do not send PROXY protocol header v2 with SSL info */
9901 { "no-send-proxy-v2-ssl-cn", srv_parse_no_send_proxy_cn, 0, 1 }, /* do not send PROXY protocol header v2 with CN */
9902 { "no-ssl", srv_parse_no_ssl, 0, 1 }, /* disable SSL processing */
9903 { "no-ssl-reuse", srv_parse_no_ssl_reuse, 0, 1 }, /* disable session reuse */
9904 { "no-sslv3", srv_parse_tls_method_options, 0, 0 }, /* disable SSLv3 */
9905 { "no-tlsv10", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv10 */
9906 { "no-tlsv11", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv11 */
9907 { "no-tlsv12", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv12 */
9908 { "no-tlsv13", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv13 */
9909 { "no-tls-tickets", srv_parse_no_tls_tickets, 0, 1 }, /* disable session resumption tickets */
Olivier Houchardc7566002018-11-20 23:33:50 +01009910 { "npn", srv_parse_npn, 1, 1 }, /* Set NPN supported protocols */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02009911 { "send-proxy-v2-ssl", srv_parse_send_proxy_ssl, 0, 1 }, /* send PROXY protocol header v2 with SSL info */
9912 { "send-proxy-v2-ssl-cn", srv_parse_send_proxy_cn, 0, 1 }, /* send PROXY protocol header v2 with CN */
9913 { "sni", srv_parse_sni, 1, 1 }, /* send SNI extension */
9914 { "ssl", srv_parse_ssl, 0, 1 }, /* enable SSL processing */
9915 { "ssl-min-ver", srv_parse_tls_method_minmax, 1, 1 }, /* minimum version */
9916 { "ssl-max-ver", srv_parse_tls_method_minmax, 1, 1 }, /* maximum version */
9917 { "ssl-reuse", srv_parse_ssl_reuse, 0, 1 }, /* enable session reuse */
9918 { "tls-tickets", srv_parse_tls_tickets, 0, 1 }, /* enable session resumption tickets */
9919 { "verify", srv_parse_verify, 1, 1 }, /* set SSL verify method */
9920 { "verifyhost", srv_parse_verifyhost, 1, 1 }, /* require that SSL cert verifies for hostname */
Willy Tarreau92faadf2012-10-10 23:04:25 +02009921 { NULL, NULL, 0, 0 },
9922}};
9923
Willy Tarreau0108d902018-11-25 19:14:37 +01009924INITCALL1(STG_REGISTER, srv_register_keywords, &srv_kws);
9925
Emeric Brun2c86cbf2014-10-30 15:56:50 +01009926static struct cfg_kw_list cfg_kws = {ILH, {
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01009927 { CFG_GLOBAL, "ca-base", ssl_parse_global_ca_crt_base },
9928 { CFG_GLOBAL, "crt-base", ssl_parse_global_ca_crt_base },
Willy Tarreau0bea58d2016-12-21 23:17:25 +01009929 { CFG_GLOBAL, "maxsslconn", ssl_parse_global_int },
Emeric Brun2c86cbf2014-10-30 15:56:50 +01009930 { CFG_GLOBAL, "ssl-default-bind-options", ssl_parse_default_bind_options },
9931 { CFG_GLOBAL, "ssl-default-server-options", ssl_parse_default_server_options },
Willy Tarreau14e36a12016-12-21 23:28:13 +01009932#ifndef OPENSSL_NO_DH
9933 { CFG_GLOBAL, "ssl-dh-param-file", ssl_parse_global_dh_param_file },
9934#endif
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00009935 { CFG_GLOBAL, "ssl-mode-async", ssl_parse_global_ssl_async },
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02009936#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +00009937 { CFG_GLOBAL, "ssl-engine", ssl_parse_global_ssl_engine },
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02009938#endif
Willy Tarreau9ceda382016-12-21 23:13:03 +01009939 { CFG_GLOBAL, "tune.ssl.cachesize", ssl_parse_global_int },
9940#ifndef OPENSSL_NO_DH
9941 { CFG_GLOBAL, "tune.ssl.default-dh-param", ssl_parse_global_default_dh },
9942#endif
9943 { CFG_GLOBAL, "tune.ssl.force-private-cache", ssl_parse_global_private_cache },
9944 { CFG_GLOBAL, "tune.ssl.lifetime", ssl_parse_global_lifetime },
9945 { CFG_GLOBAL, "tune.ssl.maxrecord", ssl_parse_global_int },
9946 { CFG_GLOBAL, "tune.ssl.ssl-ctx-cache-size", ssl_parse_global_int },
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01009947 { CFG_GLOBAL, "tune.ssl.capture-cipherlist-size", ssl_parse_global_capture_cipherlist },
Willy Tarreauf22e9682016-12-21 23:23:19 +01009948 { CFG_GLOBAL, "ssl-default-bind-ciphers", ssl_parse_global_ciphers },
9949 { CFG_GLOBAL, "ssl-default-server-ciphers", ssl_parse_global_ciphers },
Emmanuel Hocdet839af572019-05-14 16:27:35 +02009950#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009951 { CFG_GLOBAL, "ssl-default-bind-ciphersuites", ssl_parse_global_ciphersuites },
9952 { CFG_GLOBAL, "ssl-default-server-ciphersuites", ssl_parse_global_ciphersuites },
9953#endif
Emeric Brun2c86cbf2014-10-30 15:56:50 +01009954 { 0, NULL, NULL },
9955}};
9956
Willy Tarreau0108d902018-11-25 19:14:37 +01009957INITCALL1(STG_REGISTER, cfg_register_keywords, &cfg_kws);
9958
Nenad Merdanovicc31499d2019-03-23 11:00:32 +01009959/* Note: must not be declared <const> as its list will be overwritten */
9960static struct sample_conv_kw_list conv_kws = {ILH, {
Willy Tarreau86a394e2019-05-09 14:15:32 +02009961#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000100fL)
Nenad Merdanovicc31499d2019-03-23 11:00:32 +01009962 { "aes_gcm_dec", sample_conv_aes_gcm_dec, ARG4(4,SINT,STR,STR,STR), check_aes_gcm, SMP_T_BIN, SMP_T_BIN },
9963#endif
9964 { NULL, NULL, 0, 0, 0 },
9965}};
9966
9967INITCALL1(STG_REGISTER, sample_register_convs, &conv_kws);
9968
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02009969/* transport-layer operations for SSL sockets */
Willy Tarreaud9f5cca2016-12-22 21:08:52 +01009970static struct xprt_ops ssl_sock = {
Emeric Brun46591952012-05-18 15:47:34 +02009971 .snd_buf = ssl_sock_from_buf,
9972 .rcv_buf = ssl_sock_to_buf,
Olivier Houcharddf357842019-03-21 16:30:07 +01009973 .subscribe = ssl_subscribe,
9974 .unsubscribe = ssl_unsubscribe,
Olivier Houchard5149b592019-05-23 17:47:36 +02009975 .remove_xprt = ssl_remove_xprt,
Olivier Houchard2e055482019-05-27 19:50:12 +02009976 .add_xprt = ssl_add_xprt,
Emeric Brun46591952012-05-18 15:47:34 +02009977 .rcv_pipe = NULL,
9978 .snd_pipe = NULL,
9979 .shutr = NULL,
9980 .shutw = ssl_sock_shutw,
9981 .close = ssl_sock_close,
9982 .init = ssl_sock_init,
Willy Tarreau55d37912016-12-21 23:38:39 +01009983 .prepare_bind_conf = ssl_sock_prepare_bind_conf,
Willy Tarreau795cdab2016-12-22 17:30:54 +01009984 .destroy_bind_conf = ssl_sock_destroy_bind_conf,
Willy Tarreau17d45382016-12-22 21:16:08 +01009985 .prepare_srv = ssl_sock_prepare_srv_ctx,
9986 .destroy_srv = ssl_sock_free_srv_ctx,
Willy Tarreau8743f7e2016-12-04 18:44:29 +01009987 .get_alpn = ssl_sock_get_alpn,
Willy Tarreau8e0bb0a2016-11-24 16:58:12 +01009988 .name = "SSL",
Emeric Brun46591952012-05-18 15:47:34 +02009989};
9990
Olivier Houchardccaa7de2017-10-02 11:51:03 +02009991enum act_return ssl_action_wait_for_hs(struct act_rule *rule, struct proxy *px,
9992 struct session *sess, struct stream *s, int flags)
9993{
9994 struct connection *conn;
Olivier Houchard6fa63d92017-11-27 18:41:32 +01009995 struct conn_stream *cs;
Olivier Houchardccaa7de2017-10-02 11:51:03 +02009996
9997 conn = objt_conn(sess->origin);
Olivier Houchard6fa63d92017-11-27 18:41:32 +01009998 cs = objt_cs(s->si[0].end);
Olivier Houchardccaa7de2017-10-02 11:51:03 +02009999
Olivier Houchard6fa63d92017-11-27 18:41:32 +010010000 if (conn && cs) {
Olivier Houchardccaa7de2017-10-02 11:51:03 +020010001 if (conn->flags & (CO_FL_EARLY_SSL_HS | CO_FL_SSL_WAIT_HS)) {
Olivier Houchard6fa63d92017-11-27 18:41:32 +010010002 cs->flags |= CS_FL_WAIT_FOR_HS;
Olivier Houchardccaa7de2017-10-02 11:51:03 +020010003 s->req.flags |= CF_READ_NULL;
10004 return ACT_RET_YIELD;
10005 }
10006 }
10007 return (ACT_RET_CONT);
10008}
10009
10010static enum act_parse_ret ssl_parse_wait_for_hs(const char **args, int *orig_arg, struct proxy *px, struct act_rule *rule, char **err)
10011{
10012 rule->action_ptr = ssl_action_wait_for_hs;
10013
10014 return ACT_RET_PRS_OK;
10015}
10016
10017static struct action_kw_list http_req_actions = {ILH, {
10018 { "wait-for-handshake", ssl_parse_wait_for_hs },
10019 { /* END */ }
10020}};
10021
Willy Tarreau0108d902018-11-25 19:14:37 +010010022INITCALL1(STG_REGISTER, http_req_keywords_register, &http_req_actions);
10023
Willy Tarreau5db847a2019-05-09 14:13:35 +020010024#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +010010025
10026static void ssl_sock_sctl_free_func(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, long argl, void *argp)
10027{
10028 if (ptr) {
10029 chunk_destroy(ptr);
10030 free(ptr);
10031 }
10032}
10033
10034#endif
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +010010035static void ssl_sock_capture_free_func(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, long argl, void *argp)
10036{
Willy Tarreaubafbe012017-11-24 17:34:44 +010010037 pool_free(pool_head_ssl_capture, ptr);
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +010010038}
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +010010039
Emeric Brun46591952012-05-18 15:47:34 +020010040__attribute__((constructor))
Willy Tarreau92faadf2012-10-10 23:04:25 +020010041static void __ssl_sock_init(void)
10042{
Ilya Shipitsin0590f442019-05-25 19:30:50 +050010043#if (!defined(OPENSSL_NO_COMP) && !defined(SSL_OP_NO_COMPRESSION))
Emeric Brun46591952012-05-18 15:47:34 +020010044 STACK_OF(SSL_COMP)* cm;
Ilya Shipitsine242f3d2019-05-25 03:38:14 +050010045 int n;
Ilya Shipitsin0590f442019-05-25 19:30:50 +050010046#endif
Emeric Brun46591952012-05-18 15:47:34 +020010047
Willy Tarreauef934602016-12-22 23:12:01 +010010048 if (global_ssl.listen_default_ciphers)
10049 global_ssl.listen_default_ciphers = strdup(global_ssl.listen_default_ciphers);
10050 if (global_ssl.connect_default_ciphers)
10051 global_ssl.connect_default_ciphers = strdup(global_ssl.connect_default_ciphers);
Emmanuel Hocdet839af572019-05-14 16:27:35 +020010052#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +020010053 if (global_ssl.listen_default_ciphersuites)
10054 global_ssl.listen_default_ciphersuites = strdup(global_ssl.listen_default_ciphersuites);
10055 if (global_ssl.connect_default_ciphersuites)
10056 global_ssl.connect_default_ciphersuites = strdup(global_ssl.connect_default_ciphersuites);
10057#endif
Willy Tarreau610f04b2014-02-13 11:36:41 +010010058
Willy Tarreau13e14102016-12-22 20:25:26 +010010059 xprt_register(XPRT_SSL, &ssl_sock);
Willy Tarreau9a1ab082019-05-09 13:26:41 +020010060#if HA_OPENSSL_VERSION_NUMBER < 0x10100000L
Emeric Brun46591952012-05-18 15:47:34 +020010061 SSL_library_init();
Rosen Penev68185952018-12-14 08:47:02 -080010062#endif
Ilya Shipitsin0590f442019-05-25 19:30:50 +050010063#if (!defined(OPENSSL_NO_COMP) && !defined(SSL_OP_NO_COMPRESSION))
Emeric Brun46591952012-05-18 15:47:34 +020010064 cm = SSL_COMP_get_compression_methods();
Ilya Shipitsine242f3d2019-05-25 03:38:14 +050010065 n = sk_SSL_COMP_num(cm);
10066 while (n--) {
10067 (void) sk_SSL_COMP_pop(cm);
10068 }
Ilya Shipitsin0590f442019-05-25 19:30:50 +050010069#endif
Ilya Shipitsine242f3d2019-05-25 03:38:14 +050010070
Willy Tarreau5db847a2019-05-09 14:13:35 +020010071#if defined(USE_THREAD) && (HA_OPENSSL_VERSION_NUMBER < 0x10100000L)
Emeric Brun821bb9b2017-06-15 16:37:39 +020010072 ssl_locking_init();
10073#endif
Willy Tarreau5db847a2019-05-09 14:13:35 +020010074#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +010010075 sctl_ex_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, ssl_sock_sctl_free_func);
10076#endif
Thierry FOURNIER28962c92018-06-17 21:37:05 +020010077 ssl_app_data_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL);
Thierry FOURNIER16ff0502018-06-17 21:33:01 +020010078 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 +010010079 ssl_pkey_info_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, NULL);
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020010080#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +000010081 ENGINE_load_builtin_engines();
Grant Zhangfa6c7ee2017-01-14 01:42:15 +000010082 hap_register_post_check(ssl_check_async_engine_count);
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020010083#endif
Willy Tarreaud1c57502016-12-22 22:46:15 +010010084#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
10085 hap_register_post_check(tlskeys_finalize_config);
10086#endif
Willy Tarreau80713382018-11-26 10:19:54 +010010087
10088 global.ssl_session_max_cost = SSL_SESSION_MAX_COST;
10089 global.ssl_handshake_max_cost = SSL_HANDSHAKE_MAX_COST;
10090
10091#ifndef OPENSSL_NO_DH
10092 ssl_dh_ptr_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, NULL);
10093 hap_register_post_deinit(ssl_free_dh);
10094#endif
10095#ifndef OPENSSL_NO_ENGINE
10096 hap_register_post_deinit(ssl_free_engines);
10097#endif
10098 /* Load SSL string for the verbose & debug mode. */
10099 ERR_load_SSL_strings();
Olivier Houcharda8955d52019-04-07 22:00:38 +020010100 ha_meth = BIO_meth_new(0x666, "ha methods");
10101 BIO_meth_set_write(ha_meth, ha_ssl_write);
10102 BIO_meth_set_read(ha_meth, ha_ssl_read);
10103 BIO_meth_set_ctrl(ha_meth, ha_ssl_ctrl);
10104 BIO_meth_set_create(ha_meth, ha_ssl_new);
10105 BIO_meth_set_destroy(ha_meth, ha_ssl_free);
10106 BIO_meth_set_puts(ha_meth, ha_ssl_puts);
10107 BIO_meth_set_gets(ha_meth, ha_ssl_gets);
Willy Tarreau80713382018-11-26 10:19:54 +010010108}
Willy Tarreaud92aa5c2015-01-15 21:34:39 +010010109
Willy Tarreau80713382018-11-26 10:19:54 +010010110/* Compute and register the version string */
10111static void ssl_register_build_options()
10112{
10113 char *ptr = NULL;
10114 int i;
10115
Willy Tarreauc2c0b612016-12-21 19:23:20 +010010116 memprintf(&ptr, "Built with OpenSSL version : "
10117#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet50e25e12017-03-24 15:20:03 +010010118 "BoringSSL");
Willy Tarreauc2c0b612016-12-21 19:23:20 +010010119#else /* OPENSSL_IS_BORINGSSL */
10120 OPENSSL_VERSION_TEXT
10121 "\nRunning on OpenSSL version : %s%s",
Rosen Penev68185952018-12-14 08:47:02 -080010122 OpenSSL_version(OPENSSL_VERSION),
Willy Tarreau1d158ab2019-05-09 13:41:45 +020010123 ((OPENSSL_VERSION_NUMBER ^ OpenSSL_version_num()) >> 8) ? " (VERSIONS DIFFER!)" : "");
Willy Tarreauc2c0b612016-12-21 19:23:20 +010010124#endif
10125 memprintf(&ptr, "%s\nOpenSSL library supports TLS extensions : "
Willy Tarreau9a1ab082019-05-09 13:26:41 +020010126#if HA_OPENSSL_VERSION_NUMBER < 0x00907000L
Willy Tarreauc2c0b612016-12-21 19:23:20 +010010127 "no (library version too old)"
10128#elif defined(OPENSSL_NO_TLSEXT)
10129 "no (disabled via OPENSSL_NO_TLSEXT)"
10130#else
10131 "yes"
10132#endif
10133 "", ptr);
10134
10135 memprintf(&ptr, "%s\nOpenSSL library supports SNI : "
10136#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
10137 "yes"
10138#else
10139#ifdef OPENSSL_NO_TLSEXT
10140 "no (because of OPENSSL_NO_TLSEXT)"
10141#else
10142 "no (version might be too old, 0.9.8f min needed)"
10143#endif
10144#endif
10145 "", ptr);
10146
Emmanuel Hocdetf80bc242017-07-12 14:25:38 +020010147 memprintf(&ptr, "%s\nOpenSSL library supports :", ptr);
10148 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
10149 if (methodVersions[i].option)
10150 memprintf(&ptr, "%s %s", ptr, methodVersions[i].name);
Emmanuel Hocdet50e25e12017-03-24 15:20:03 +010010151
Willy Tarreauc2c0b612016-12-21 19:23:20 +010010152 hap_register_build_opts(ptr, 1);
Willy Tarreau80713382018-11-26 10:19:54 +010010153}
Willy Tarreauc2c0b612016-12-21 19:23:20 +010010154
Willy Tarreau80713382018-11-26 10:19:54 +010010155INITCALL0(STG_REGISTER, ssl_register_build_options);
Remi Gacogne4f902b82015-05-28 16:23:00 +020010156
Emeric Brun46591952012-05-18 15:47:34 +020010157
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020010158#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +000010159void ssl_free_engines(void) {
10160 struct ssl_engine_list *wl, *wlb;
10161 /* free up engine list */
10162 list_for_each_entry_safe(wl, wlb, &openssl_engines, list) {
10163 ENGINE_finish(wl->e);
10164 ENGINE_free(wl->e);
10165 LIST_DEL(&wl->list);
10166 free(wl);
10167 }
10168}
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020010169#endif
Christopher Faulet31af49d2015-06-09 17:29:50 +020010170
Remi Gacogned3a23c32015-05-28 16:39:47 +020010171#ifndef OPENSSL_NO_DH
Grant Zhang872f9c22017-01-21 01:10:18 +000010172void ssl_free_dh(void) {
10173 if (local_dh_1024) {
10174 DH_free(local_dh_1024);
10175 local_dh_1024 = NULL;
10176 }
10177 if (local_dh_2048) {
10178 DH_free(local_dh_2048);
10179 local_dh_2048 = NULL;
10180 }
10181 if (local_dh_4096) {
10182 DH_free(local_dh_4096);
10183 local_dh_4096 = NULL;
10184 }
Remi Gacogne47783ef2015-05-29 15:53:22 +020010185 if (global_dh) {
10186 DH_free(global_dh);
10187 global_dh = NULL;
10188 }
Grant Zhang872f9c22017-01-21 01:10:18 +000010189}
10190#endif
10191
10192__attribute__((destructor))
10193static void __ssl_sock_deinit(void)
10194{
10195#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Emeric Brun821bb9b2017-06-15 16:37:39 +020010196 if (ssl_ctx_lru_tree) {
10197 lru64_destroy(ssl_ctx_lru_tree);
Christopher Faulet2a944ee2017-11-07 10:42:54 +010010198 HA_RWLOCK_DESTROY(&ssl_ctx_lru_rwlock);
Emeric Brun821bb9b2017-06-15 16:37:39 +020010199 }
Remi Gacogned3a23c32015-05-28 16:39:47 +020010200#endif
10201
Willy Tarreau5db847a2019-05-09 14:13:35 +020010202#if (HA_OPENSSL_VERSION_NUMBER < 0x10100000L)
Remi Gacogned3a23c32015-05-28 16:39:47 +020010203 ERR_remove_state(0);
10204 ERR_free_strings();
10205
10206 EVP_cleanup();
Rosen Penev68185952018-12-14 08:47:02 -080010207#endif
Remi Gacogned3a23c32015-05-28 16:39:47 +020010208
Willy Tarreau5db847a2019-05-09 14:13:35 +020010209#if (HA_OPENSSL_VERSION_NUMBER >= 0x00907000L) && (HA_OPENSSL_VERSION_NUMBER < 0x10100000L)
Remi Gacogned3a23c32015-05-28 16:39:47 +020010210 CRYPTO_cleanup_all_ex_data();
10211#endif
Olivier Houcharda8955d52019-04-07 22:00:38 +020010212 BIO_meth_free(ha_meth);
Remi Gacogned3a23c32015-05-28 16:39:47 +020010213}
10214
10215
Emeric Brun46591952012-05-18 15:47:34 +020010216/*
10217 * Local variables:
10218 * c-indent-level: 8
10219 * c-basic-offset: 8
10220 * End:
10221 */