blob: ec961ffe44a2d6bff5e7af2063f9bc792e3bbd47 [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 */
220 int tmp_early_data; /* 1st byte of early data, if any */
221 int sent_early_data; /* Amount of early data we sent so far */
222
Olivier Houchard66ab4982019-02-26 18:37:15 +0100223};
224
225DECLARE_STATIC_POOL(ssl_sock_ctx_pool, "ssl_sock_ctx_pool", sizeof(struct ssl_sock_ctx));
226
Olivier Houchardea8dd942019-05-20 14:02:16 +0200227static struct task *ssl_sock_io_cb(struct task *, void *, unsigned short);
Olivier Houchard000694c2019-05-23 14:45:12 +0200228static int ssl_sock_handshake(struct connection *conn, unsigned int flag);
Olivier Houchardea8dd942019-05-20 14:02:16 +0200229
Olivier Houcharda8955d52019-04-07 22:00:38 +0200230/* Methods to implement OpenSSL BIO */
231static int ha_ssl_write(BIO *h, const char *buf, int num)
232{
233 struct buffer tmpbuf;
234 struct ssl_sock_ctx *ctx;
235 int ret;
236
237 ctx = BIO_get_data(h);
238 tmpbuf.size = num;
239 tmpbuf.area = (void *)(uintptr_t)buf;
240 tmpbuf.data = num;
241 tmpbuf.head = 0;
242 ret = ctx->xprt->snd_buf(ctx->conn, ctx->xprt_ctx, &tmpbuf, num, 0);
Olivier Houchardb51937e2019-05-01 17:24:36 +0200243 if (ret == 0 && !(ctx->conn->flags & (CO_FL_ERROR | CO_FL_SOCK_WR_SH))) {
Olivier Houcharda8955d52019-04-07 22:00:38 +0200244 BIO_set_retry_write(h);
Olivier Houcharda28454e2019-04-24 12:04:36 +0200245 ret = -1;
Olivier Houchardb51937e2019-05-01 17:24:36 +0200246 } else if (ret == 0)
247 BIO_clear_retry_flags(h);
Olivier Houcharda8955d52019-04-07 22:00:38 +0200248 return ret;
249}
250
251static int ha_ssl_gets(BIO *h, char *buf, int size)
252{
253
254 return 0;
255}
256
257static int ha_ssl_puts(BIO *h, const char *str)
258{
259
260 return ha_ssl_write(h, str, strlen(str));
261}
262
263static int ha_ssl_read(BIO *h, char *buf, int size)
264{
265 struct buffer tmpbuf;
266 struct ssl_sock_ctx *ctx;
267 int ret;
268
269 ctx = BIO_get_data(h);
270 tmpbuf.size = size;
271 tmpbuf.area = buf;
272 tmpbuf.data = 0;
273 tmpbuf.head = 0;
274 ret = ctx->xprt->rcv_buf(ctx->conn, ctx->xprt_ctx, &tmpbuf, size, 0);
Olivier Houchardb51937e2019-05-01 17:24:36 +0200275 if (ret == 0 && !(ctx->conn->flags & (CO_FL_ERROR | CO_FL_SOCK_RD_SH))) {
Olivier Houcharda8955d52019-04-07 22:00:38 +0200276 BIO_set_retry_read(h);
Olivier Houcharda28454e2019-04-24 12:04:36 +0200277 ret = -1;
Olivier Houchardb51937e2019-05-01 17:24:36 +0200278 } else if (ret == 0)
279 BIO_clear_retry_flags(h);
Olivier Houcharda8955d52019-04-07 22:00:38 +0200280
281 return ret;
282}
283
284static long ha_ssl_ctrl(BIO *h, int cmd, long arg1, void *arg2)
285{
286 int ret = 0;
287 switch (cmd) {
288 case BIO_CTRL_DUP:
289 case BIO_CTRL_FLUSH:
290 ret = 1;
291 break;
292 }
293 return ret;
294}
295
296static int ha_ssl_new(BIO *h)
297{
298 BIO_set_init(h, 1);
299 BIO_set_data(h, NULL);
300 BIO_clear_flags(h, ~0);
301 return 1;
302}
303
304static int ha_ssl_free(BIO *data)
305{
306
307 return 1;
308}
309
310
Willy Tarreau5db847a2019-05-09 14:13:35 +0200311#if defined(USE_THREAD) && (HA_OPENSSL_VERSION_NUMBER < 0x10100000L)
Christopher Faulet9dcf9b62017-11-13 10:34:01 +0100312
Emeric Brun821bb9b2017-06-15 16:37:39 +0200313static HA_RWLOCK_T *ssl_rwlocks;
314
315
316unsigned long ssl_id_function(void)
317{
318 return (unsigned long)tid;
319}
320
321void ssl_locking_function(int mode, int n, const char * file, int line)
322{
323 if (mode & CRYPTO_LOCK) {
324 if (mode & CRYPTO_READ)
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100325 HA_RWLOCK_RDLOCK(SSL_LOCK, &ssl_rwlocks[n]);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200326 else
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100327 HA_RWLOCK_WRLOCK(SSL_LOCK, &ssl_rwlocks[n]);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200328 }
329 else {
330 if (mode & CRYPTO_READ)
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100331 HA_RWLOCK_RDUNLOCK(SSL_LOCK, &ssl_rwlocks[n]);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200332 else
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100333 HA_RWLOCK_WRUNLOCK(SSL_LOCK, &ssl_rwlocks[n]);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200334 }
335}
336
337static int ssl_locking_init(void)
338{
339 int i;
340
341 ssl_rwlocks = malloc(sizeof(HA_RWLOCK_T)*CRYPTO_num_locks());
342 if (!ssl_rwlocks)
343 return -1;
344
345 for (i = 0 ; i < CRYPTO_num_locks() ; i++)
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100346 HA_RWLOCK_INIT(&ssl_rwlocks[i]);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200347
348 CRYPTO_set_id_callback(ssl_id_function);
349 CRYPTO_set_locking_callback(ssl_locking_function);
350
351 return 0;
352}
Christopher Faulet9dcf9b62017-11-13 10:34:01 +0100353
Emeric Brun821bb9b2017-06-15 16:37:39 +0200354#endif
355
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) {
Vincent Bernat02779b62016-04-03 13:48:43 +02001275 struct ocsp_cbk_arg *cb_arg = calloc(1, sizeof(*cb_arg));
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001276 EVP_PKEY *pkey;
yanbzhube2774d2015-12-10 15:07:30 -05001277
1278 cb_arg->is_single = 1;
1279 cb_arg->s_ocsp = iocsp;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001280
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001281 pkey = X509_get_pubkey(x);
1282 cb_arg->single_kt = EVP_PKEY_base_id(pkey);
1283 EVP_PKEY_free(pkey);
yanbzhube2774d2015-12-10 15:07:30 -05001284
1285 SSL_CTX_set_tlsext_status_cb(ctx, ssl_sock_ocsp_stapling_cbk);
1286 SSL_CTX_set_tlsext_status_arg(ctx, cb_arg);
1287 } else {
1288 /*
1289 * If the ctx has a status CB, then we have previously set an OCSP staple for this ctx
1290 * Update that cb_arg with the new cert's staple
1291 */
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001292 struct ocsp_cbk_arg *cb_arg;
yanbzhube2774d2015-12-10 15:07:30 -05001293 struct certificate_ocsp *tmp_ocsp;
1294 int index;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001295 int key_type;
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001296 EVP_PKEY *pkey;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001297
1298#ifdef SSL_CTX_get_tlsext_status_arg
1299 SSL_CTX_ctrl(ctx, SSL_CTRL_GET_TLSEXT_STATUS_REQ_CB_ARG, 0, &cb_arg);
1300#else
1301 cb_arg = ctx->tlsext_status_arg;
1302#endif
yanbzhube2774d2015-12-10 15:07:30 -05001303
1304 /*
1305 * The following few lines will convert cb_arg from a single ocsp to multi ocsp
1306 * the order of operations below matter, take care when changing it
1307 */
1308 tmp_ocsp = cb_arg->s_ocsp;
1309 index = ssl_sock_get_ocsp_arg_kt_index(cb_arg->single_kt);
1310 cb_arg->s_ocsp = NULL;
1311 cb_arg->m_ocsp[index] = tmp_ocsp;
1312 cb_arg->is_single = 0;
1313 cb_arg->single_kt = 0;
1314
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001315 pkey = X509_get_pubkey(x);
1316 key_type = EVP_PKEY_base_id(pkey);
1317 EVP_PKEY_free(pkey);
1318
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001319 index = ssl_sock_get_ocsp_arg_kt_index(key_type);
yanbzhube2774d2015-12-10 15:07:30 -05001320 if (index >= 0 && !cb_arg->m_ocsp[index])
1321 cb_arg->m_ocsp[index] = iocsp;
1322
1323 }
Emeric Brun4147b2e2014-06-16 18:36:30 +02001324
1325 ret = 0;
1326
1327 warn = NULL;
1328 if (ssl_sock_load_ocsp_response_from_file(ocsp_path, iocsp, cid, &warn)) {
1329 memprintf(&warn, "Loading '%s': %s. Content will be ignored", ocsp_path, warn ? warn : "failure");
Christopher Faulet767a84b2017-11-24 16:50:31 +01001330 ha_warning("%s.\n", warn);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001331 }
1332
1333out:
1334 if (ssl)
1335 SSL_free(ssl);
1336
1337 if (in)
1338 BIO_free(in);
1339
1340 if (xi)
1341 X509_free(xi);
1342
1343 if (cid)
1344 OCSP_CERTID_free(cid);
1345
1346 if (ocsp)
1347 free(ocsp);
1348
1349 if (warn)
1350 free(warn);
1351
1352
1353 return ret;
1354}
1355
1356#endif
1357
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02001358#ifdef OPENSSL_IS_BORINGSSL
1359static int ssl_sock_set_ocsp_response_from_file(SSL_CTX *ctx, const char *cert_path)
1360{
1361 char ocsp_path[MAXPATHLEN+1];
1362 struct stat st;
1363 int fd = -1, r = 0;
1364
1365 snprintf(ocsp_path, MAXPATHLEN+1, "%s.ocsp", cert_path);
1366 if (stat(ocsp_path, &st))
1367 return 0;
1368
1369 fd = open(ocsp_path, O_RDONLY);
1370 if (fd == -1) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001371 ha_warning("Error opening OCSP response file %s.\n", ocsp_path);
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02001372 return -1;
1373 }
1374
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001375 trash.data = 0;
1376 while (trash.data < trash.size) {
1377 r = read(fd, trash.area + trash.data, trash.size - trash.data);
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02001378 if (r < 0) {
1379 if (errno == EINTR)
1380 continue;
Christopher Faulet767a84b2017-11-24 16:50:31 +01001381 ha_warning("Error reading OCSP response from file %s.\n", ocsp_path);
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02001382 close(fd);
1383 return -1;
1384 }
1385 else if (r == 0) {
1386 break;
1387 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001388 trash.data += r;
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02001389 }
1390 close(fd);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001391 return SSL_CTX_set_ocsp_response(ctx, (const uint8_t *) trash.area,
1392 trash.data);
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02001393}
1394#endif
1395
Willy Tarreau5db847a2019-05-09 14:13:35 +02001396#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001397
1398#define CT_EXTENSION_TYPE 18
1399
1400static int sctl_ex_index = -1;
1401
1402/*
1403 * Try to parse Signed Certificate Timestamp List structure. This function
1404 * makes only basic test if the data seems like SCTL. No signature validation
1405 * is performed.
1406 */
Willy Tarreau83061a82018-07-13 11:56:34 +02001407static int ssl_sock_parse_sctl(struct buffer *sctl)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001408{
1409 int ret = 1;
1410 int len, pos, sct_len;
1411 unsigned char *data;
1412
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001413 if (sctl->data < 2)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001414 goto out;
1415
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001416 data = (unsigned char *) sctl->area;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001417 len = (data[0] << 8) | data[1];
1418
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001419 if (len + 2 != sctl->data)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001420 goto out;
1421
1422 data = data + 2;
1423 pos = 0;
1424 while (pos < len) {
1425 if (len - pos < 2)
1426 goto out;
1427
1428 sct_len = (data[pos] << 8) | data[pos + 1];
1429 if (pos + sct_len + 2 > len)
1430 goto out;
1431
1432 pos += sct_len + 2;
1433 }
1434
1435 ret = 0;
1436
1437out:
1438 return ret;
1439}
1440
Willy Tarreau83061a82018-07-13 11:56:34 +02001441static int ssl_sock_load_sctl_from_file(const char *sctl_path,
1442 struct buffer **sctl)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001443{
1444 int fd = -1;
1445 int r = 0;
1446 int ret = 1;
1447
1448 *sctl = NULL;
1449
1450 fd = open(sctl_path, O_RDONLY);
1451 if (fd == -1)
1452 goto end;
1453
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001454 trash.data = 0;
1455 while (trash.data < trash.size) {
1456 r = read(fd, trash.area + trash.data, trash.size - trash.data);
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001457 if (r < 0) {
1458 if (errno == EINTR)
1459 continue;
1460
1461 goto end;
1462 }
1463 else if (r == 0) {
1464 break;
1465 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001466 trash.data += r;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001467 }
1468
1469 ret = ssl_sock_parse_sctl(&trash);
1470 if (ret)
1471 goto end;
1472
Vincent Bernat02779b62016-04-03 13:48:43 +02001473 *sctl = calloc(1, sizeof(**sctl));
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001474 if (!chunk_dup(*sctl, &trash)) {
1475 free(*sctl);
1476 *sctl = NULL;
1477 goto end;
1478 }
1479
1480end:
1481 if (fd != -1)
1482 close(fd);
1483
1484 return ret;
1485}
1486
1487int ssl_sock_sctl_add_cbk(SSL *ssl, unsigned ext_type, const unsigned char **out, size_t *outlen, int *al, void *add_arg)
1488{
Willy Tarreau83061a82018-07-13 11:56:34 +02001489 struct buffer *sctl = add_arg;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001490
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001491 *out = (unsigned char *) sctl->area;
1492 *outlen = sctl->data;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001493
1494 return 1;
1495}
1496
1497int ssl_sock_sctl_parse_cbk(SSL *s, unsigned int ext_type, const unsigned char *in, size_t inlen, int *al, void *parse_arg)
1498{
1499 return 1;
1500}
1501
1502static int ssl_sock_load_sctl(SSL_CTX *ctx, const char *cert_path)
1503{
1504 char sctl_path[MAXPATHLEN+1];
1505 int ret = -1;
1506 struct stat st;
Willy Tarreau83061a82018-07-13 11:56:34 +02001507 struct buffer *sctl = NULL;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001508
1509 snprintf(sctl_path, MAXPATHLEN+1, "%s.sctl", cert_path);
1510
1511 if (stat(sctl_path, &st))
1512 return 1;
1513
1514 if (ssl_sock_load_sctl_from_file(sctl_path, &sctl))
1515 goto out;
1516
1517 if (!SSL_CTX_add_server_custom_ext(ctx, CT_EXTENSION_TYPE, ssl_sock_sctl_add_cbk, NULL, sctl, ssl_sock_sctl_parse_cbk, NULL)) {
1518 free(sctl);
1519 goto out;
1520 }
1521
1522 SSL_CTX_set_ex_data(ctx, sctl_ex_index, sctl);
1523
1524 ret = 0;
1525
1526out:
1527 return ret;
1528}
1529
1530#endif
1531
Emeric Brune1f38db2012-09-03 20:36:47 +02001532void ssl_sock_infocbk(const SSL *ssl, int where, int ret)
1533{
Thierry FOURNIER28962c92018-06-17 21:37:05 +02001534 struct connection *conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001535 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
Emeric Brund8b2bb52014-01-28 15:43:53 +01001536 BIO *write_bio;
Willy Tarreau622317d2015-02-27 16:36:16 +01001537 (void)ret; /* shut gcc stupid warning */
Emeric Brune1f38db2012-09-03 20:36:47 +02001538
Dirkjan Bussink526894f2019-01-21 09:35:03 -08001539#ifndef SSL_OP_NO_RENEGOTIATION
1540 /* Please note that BoringSSL defines this macro to zero so don't
1541 * change this to #if and do not assign a default value to this macro!
1542 */
Emeric Brune1f38db2012-09-03 20:36:47 +02001543 if (where & SSL_CB_HANDSHAKE_START) {
1544 /* Disable renegotiation (CVE-2009-3555) */
Olivier Houchard90084a12017-11-23 18:21:29 +01001545 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 +02001546 conn->flags |= CO_FL_ERROR;
Willy Tarreau20879a02012-12-03 16:32:10 +01001547 conn->err_code = CO_ER_SSL_RENEG;
1548 }
Emeric Brune1f38db2012-09-03 20:36:47 +02001549 }
Dirkjan Bussink526894f2019-01-21 09:35:03 -08001550#endif
Emeric Brund8b2bb52014-01-28 15:43:53 +01001551
1552 if ((where & SSL_CB_ACCEPT_LOOP) == SSL_CB_ACCEPT_LOOP) {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001553 if (!(ctx->xprt_st & SSL_SOCK_ST_FL_16K_WBFSIZE)) {
Emeric Brund8b2bb52014-01-28 15:43:53 +01001554 /* Long certificate chains optimz
1555 If write and read bios are differents, we
1556 consider that the buffering was activated,
1557 so we rise the output buffer size from 4k
1558 to 16k */
1559 write_bio = SSL_get_wbio(ssl);
1560 if (write_bio != SSL_get_rbio(ssl)) {
1561 BIO_set_write_buffer_size(write_bio, 16384);
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001562 ctx->xprt_st |= SSL_SOCK_ST_FL_16K_WBFSIZE;
Emeric Brund8b2bb52014-01-28 15:43:53 +01001563 }
1564 }
1565 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02001566}
1567
Emeric Brune64aef12012-09-21 13:15:06 +02001568/* Callback is called for each certificate of the chain during a verify
1569 ok is set to 1 if preverify detect no error on current certificate.
1570 Returns 0 to break the handshake, 1 otherwise. */
Evan Broderbe554312013-06-27 00:05:25 -07001571int ssl_sock_bind_verifycbk(int ok, X509_STORE_CTX *x_store)
Emeric Brune64aef12012-09-21 13:15:06 +02001572{
1573 SSL *ssl;
1574 struct connection *conn;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001575 struct ssl_sock_ctx *ctx;
Emeric Brun81c00f02012-09-21 14:31:21 +02001576 int err, depth;
Emeric Brune64aef12012-09-21 13:15:06 +02001577
1578 ssl = X509_STORE_CTX_get_ex_data(x_store, SSL_get_ex_data_X509_STORE_CTX_idx());
Thierry FOURNIER28962c92018-06-17 21:37:05 +02001579 conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Emeric Brune64aef12012-09-21 13:15:06 +02001580
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001581 ctx = conn->xprt_ctx;
1582
1583 ctx->xprt_st |= SSL_SOCK_ST_FL_VERIFY_DONE;
Emeric Brune64aef12012-09-21 13:15:06 +02001584
Emeric Brun81c00f02012-09-21 14:31:21 +02001585 if (ok) /* no errors */
1586 return ok;
1587
1588 depth = X509_STORE_CTX_get_error_depth(x_store);
1589 err = X509_STORE_CTX_get_error(x_store);
1590
1591 /* check if CA error needs to be ignored */
1592 if (depth > 0) {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001593 if (!SSL_SOCK_ST_TO_CA_ERROR(ctx->xprt_st)) {
1594 ctx->xprt_st |= SSL_SOCK_CA_ERROR_TO_ST(err);
1595 ctx->xprt_st |= SSL_SOCK_CAEDEPTH_TO_ST(depth);
Emeric Brunf282a812012-09-21 15:27:54 +02001596 }
1597
Willy Tarreau07d94e42018-09-20 10:57:52 +02001598 if (__objt_listener(conn->target)->bind_conf->ca_ignerr & (1ULL << err)) {
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02001599 ssl_sock_dump_errors(conn);
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001600 ERR_clear_error();
Emeric Brun81c00f02012-09-21 14:31:21 +02001601 return 1;
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001602 }
Emeric Brun81c00f02012-09-21 14:31:21 +02001603
Willy Tarreau20879a02012-12-03 16:32:10 +01001604 conn->err_code = CO_ER_SSL_CA_FAIL;
Emeric Brun81c00f02012-09-21 14:31:21 +02001605 return 0;
1606 }
1607
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001608 if (!SSL_SOCK_ST_TO_CRTERROR(ctx->xprt_st))
1609 ctx->xprt_st |= SSL_SOCK_CRTERROR_TO_ST(err);
Emeric Brunf282a812012-09-21 15:27:54 +02001610
Emeric Brun81c00f02012-09-21 14:31:21 +02001611 /* check if certificate error needs to be ignored */
Willy Tarreau07d94e42018-09-20 10:57:52 +02001612 if (__objt_listener(conn->target)->bind_conf->crt_ignerr & (1ULL << err)) {
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02001613 ssl_sock_dump_errors(conn);
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001614 ERR_clear_error();
Emeric Brun81c00f02012-09-21 14:31:21 +02001615 return 1;
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001616 }
Emeric Brun81c00f02012-09-21 14:31:21 +02001617
Willy Tarreau20879a02012-12-03 16:32:10 +01001618 conn->err_code = CO_ER_SSL_CRT_FAIL;
Emeric Brun81c00f02012-09-21 14:31:21 +02001619 return 0;
Emeric Brune64aef12012-09-21 13:15:06 +02001620}
1621
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001622static inline
1623void ssl_sock_parse_clienthello(int write_p, int version, int content_type,
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001624 const void *buf, size_t len, SSL *ssl)
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001625{
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001626 struct ssl_capture *capture;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001627 unsigned char *msg;
1628 unsigned char *end;
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001629 size_t rec_len;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001630
1631 /* This function is called for "from client" and "to server"
1632 * connections. The combination of write_p == 0 and content_type == 22
Joseph Herlant017b3da2018-11-15 09:07:59 -08001633 * is only available during "from client" connection.
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001634 */
1635
1636 /* "write_p" is set to 0 is the bytes are received messages,
1637 * otherwise it is set to 1.
1638 */
1639 if (write_p != 0)
1640 return;
1641
1642 /* content_type contains the type of message received or sent
1643 * according with the SSL/TLS protocol spec. This message is
1644 * encoded with one byte. The value 256 (two bytes) is used
1645 * for designing the SSL/TLS record layer. According with the
1646 * rfc6101, the expected message (other than 256) are:
1647 * - change_cipher_spec(20)
1648 * - alert(21)
1649 * - handshake(22)
1650 * - application_data(23)
1651 * - (255)
1652 * We are interessed by the handshake and specially the client
1653 * hello.
1654 */
1655 if (content_type != 22)
1656 return;
1657
1658 /* The message length is at least 4 bytes, containing the
1659 * message type and the message length.
1660 */
1661 if (len < 4)
1662 return;
1663
1664 /* First byte of the handshake message id the type of
1665 * message. The konwn types are:
1666 * - hello_request(0)
1667 * - client_hello(1)
1668 * - server_hello(2)
1669 * - certificate(11)
1670 * - server_key_exchange (12)
1671 * - certificate_request(13)
1672 * - server_hello_done(14)
1673 * We are interested by the client hello.
1674 */
1675 msg = (unsigned char *)buf;
1676 if (msg[0] != 1)
1677 return;
1678
1679 /* Next three bytes are the length of the message. The total length
1680 * must be this decoded length + 4. If the length given as argument
1681 * is not the same, we abort the protocol dissector.
1682 */
1683 rec_len = (msg[1] << 16) + (msg[2] << 8) + msg[3];
1684 if (len < rec_len + 4)
1685 return;
1686 msg += 4;
1687 end = msg + rec_len;
1688 if (end < msg)
1689 return;
1690
1691 /* Expect 2 bytes for protocol version (1 byte for major and 1 byte
1692 * for minor, the random, composed by 4 bytes for the unix time and
Baptiste Assmann6be139f2018-11-28 15:20:25 +01001693 * 28 bytes for unix payload. So we jump 1 + 1 + 4 + 28.
1694 */
1695 msg += 1 + 1 + 4 + 28;
1696 if (msg > end)
1697 return;
1698
1699 /* Next, is session id:
1700 * if present, we have to jump by length + 1 for the size information
1701 * if not present, we have to jump by 1 only
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001702 */
Baptiste Assmann6be139f2018-11-28 15:20:25 +01001703 if (msg[0] > 0)
1704 msg += msg[0];
1705 msg += 1;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001706 if (msg > end)
1707 return;
1708
1709 /* Next two bytes are the ciphersuite length. */
1710 if (msg + 2 > end)
1711 return;
1712 rec_len = (msg[0] << 8) + msg[1];
1713 msg += 2;
1714 if (msg + rec_len > end || msg + rec_len < msg)
1715 return;
1716
Willy Tarreaubafbe012017-11-24 17:34:44 +01001717 capture = pool_alloc_dirty(pool_head_ssl_capture);
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001718 if (!capture)
1719 return;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001720 /* Compute the xxh64 of the ciphersuite. */
1721 capture->xxh64 = XXH64(msg, rec_len, 0);
1722
1723 /* Capture the ciphersuite. */
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001724 capture->ciphersuite_len = (global_ssl.capture_cipherlist < rec_len) ?
1725 global_ssl.capture_cipherlist : rec_len;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001726 memcpy(capture->ciphersuite, msg, capture->ciphersuite_len);
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001727
1728 SSL_set_ex_data(ssl, ssl_capture_ptr_index, capture);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001729}
1730
Emeric Brun29f037d2014-04-25 19:05:36 +02001731/* Callback is called for ssl protocol analyse */
1732void ssl_sock_msgcbk(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg)
1733{
Emeric Brun29f037d2014-04-25 19:05:36 +02001734#ifdef TLS1_RT_HEARTBEAT
1735 /* test heartbeat received (write_p is set to 0
1736 for a received record) */
Willy Tarreauf51c6982014-04-25 20:02:39 +02001737 if ((content_type == TLS1_RT_HEARTBEAT) && (write_p == 0)) {
Thierry FOURNIER28962c92018-06-17 21:37:05 +02001738 struct connection *conn = SSL_get_ex_data(ssl, ssl_app_data_index);
William Lallemand7e1770b2019-05-13 14:31:34 +02001739 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
Willy Tarreauf51c6982014-04-25 20:02:39 +02001740 const unsigned char *p = buf;
1741 unsigned int payload;
1742
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001743 ctx->xprt_st |= SSL_SOCK_RECV_HEARTBEAT;
Willy Tarreauf51c6982014-04-25 20:02:39 +02001744
1745 /* Check if this is a CVE-2014-0160 exploitation attempt. */
1746 if (*p != TLS1_HB_REQUEST)
1747 return;
1748
Willy Tarreauaeed6722014-04-25 23:59:58 +02001749 if (len < 1 + 2 + 16) /* 1 type + 2 size + 0 payload + 16 padding */
Willy Tarreauf51c6982014-04-25 20:02:39 +02001750 goto kill_it;
1751
1752 payload = (p[1] * 256) + p[2];
Willy Tarreau3b2fdb62014-04-25 23:44:22 +02001753 if (3 + payload + 16 <= len)
Willy Tarreauf51c6982014-04-25 20:02:39 +02001754 return; /* OK no problem */
Willy Tarreauaeed6722014-04-25 23:59:58 +02001755 kill_it:
Willy Tarreau3b2fdb62014-04-25 23:44:22 +02001756 /* We have a clear heartbleed attack (CVE-2014-0160), the
1757 * advertised payload is larger than the advertised packet
1758 * length, so we have garbage in the buffer between the
1759 * payload and the end of the buffer (p+len). We can't know
1760 * if the SSL stack is patched, and we don't know if we can
1761 * safely wipe out the area between p+3+len and payload.
1762 * So instead, we prevent the response from being sent by
1763 * setting the max_send_fragment to 0 and we report an SSL
1764 * error, which will kill this connection. It will be reported
1765 * above as SSL_ERROR_SSL while an other handshake failure with
Willy Tarreauf51c6982014-04-25 20:02:39 +02001766 * a heartbeat message will be reported as SSL_ERROR_SYSCALL.
1767 */
Willy Tarreau3b2fdb62014-04-25 23:44:22 +02001768 ssl->max_send_fragment = 0;
Willy Tarreauf51c6982014-04-25 20:02:39 +02001769 SSLerr(SSL_F_TLS1_HEARTBEAT, SSL_R_SSL_HANDSHAKE_FAILURE);
1770 return;
1771 }
Emeric Brun29f037d2014-04-25 19:05:36 +02001772#endif
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001773 if (global_ssl.capture_cipherlist > 0)
1774 ssl_sock_parse_clienthello(write_p, version, content_type, buf, len, ssl);
Emeric Brun29f037d2014-04-25 19:05:36 +02001775}
1776
Bernard Spil13c53f82018-02-15 13:34:58 +01001777#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Olivier Houchardc7566002018-11-20 23:33:50 +01001778static int ssl_sock_srv_select_protos(SSL *s, unsigned char **out, unsigned char *outlen,
1779 const unsigned char *in, unsigned int inlen,
1780 void *arg)
1781{
1782 struct server *srv = arg;
1783
1784 if (SSL_select_next_proto(out, outlen, in, inlen, (unsigned char *)srv->ssl_ctx.npn_str,
1785 srv->ssl_ctx.npn_len) == OPENSSL_NPN_NEGOTIATED)
1786 return SSL_TLSEXT_ERR_OK;
1787 return SSL_TLSEXT_ERR_NOACK;
1788}
1789#endif
1790
1791#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02001792/* This callback is used so that the server advertises the list of
1793 * negociable protocols for NPN.
1794 */
1795static int ssl_sock_advertise_npn_protos(SSL *s, const unsigned char **data,
1796 unsigned int *len, void *arg)
1797{
Emmanuel Hocdet98263292016-12-29 18:26:15 +01001798 struct ssl_bind_conf *conf = arg;
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02001799
1800 *data = (const unsigned char *)conf->npn_str;
1801 *len = conf->npn_len;
1802 return SSL_TLSEXT_ERR_OK;
1803}
1804#endif
1805
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01001806#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02001807/* This callback is used so that the server advertises the list of
1808 * negociable protocols for ALPN.
1809 */
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01001810static int ssl_sock_advertise_alpn_protos(SSL *s, const unsigned char **out,
1811 unsigned char *outlen,
1812 const unsigned char *server,
1813 unsigned int server_len, void *arg)
Willy Tarreauab861d32013-04-02 02:30:41 +02001814{
Emmanuel Hocdet98263292016-12-29 18:26:15 +01001815 struct ssl_bind_conf *conf = arg;
Willy Tarreauab861d32013-04-02 02:30:41 +02001816
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01001817 if (SSL_select_next_proto((unsigned char**) out, outlen, (const unsigned char *)conf->alpn_str,
1818 conf->alpn_len, server, server_len) != OPENSSL_NPN_NEGOTIATED) {
1819 return SSL_TLSEXT_ERR_NOACK;
1820 }
Willy Tarreauab861d32013-04-02 02:30:41 +02001821 return SSL_TLSEXT_ERR_OK;
1822}
1823#endif
1824
Willy Tarreauc8ad3be2015-06-17 15:48:26 +02001825#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01001826#ifndef SSL_NO_GENERATE_CERTIFICATES
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001827
Christopher Faulet30548802015-06-11 13:39:32 +02001828/* Create a X509 certificate with the specified servername and serial. This
1829 * function returns a SSL_CTX object or NULL if an error occurs. */
Christopher Faulet7969a332015-10-09 11:15:03 +02001830static SSL_CTX *
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001831ssl_sock_do_create_cert(const char *servername, struct bind_conf *bind_conf, SSL *ssl)
Christopher Faulet31af49d2015-06-09 17:29:50 +02001832{
Christopher Faulet7969a332015-10-09 11:15:03 +02001833 X509 *cacert = bind_conf->ca_sign_cert;
1834 EVP_PKEY *capkey = bind_conf->ca_sign_pkey;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001835 SSL_CTX *ssl_ctx = NULL;
1836 X509 *newcrt = NULL;
1837 EVP_PKEY *pkey = NULL;
Emmanuel Hocdet15969292017-08-11 10:56:00 +02001838 SSL *tmp_ssl = NULL;
Emmanuel Hocdeta9b84022018-10-01 18:41:36 +02001839 CONF *ctmp = NULL;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001840 X509_NAME *name;
1841 const EVP_MD *digest;
1842 X509V3_CTX ctx;
1843 unsigned int i;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001844 int key_type;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001845
Christopher Faulet48a83322017-07-28 16:56:09 +02001846 /* Get the private key of the default certificate and use it */
Willy Tarreau5db847a2019-05-09 14:13:35 +02001847#if (HA_OPENSSL_VERSION_NUMBER >= 0x10002000L)
Emmanuel Hocdet15969292017-08-11 10:56:00 +02001848 pkey = SSL_CTX_get0_privatekey(bind_conf->default_ctx);
1849#else
1850 tmp_ssl = SSL_new(bind_conf->default_ctx);
1851 if (tmp_ssl)
1852 pkey = SSL_get_privatekey(tmp_ssl);
1853#endif
1854 if (!pkey)
Christopher Faulet31af49d2015-06-09 17:29:50 +02001855 goto mkcert_error;
1856
1857 /* Create the certificate */
1858 if (!(newcrt = X509_new()))
1859 goto mkcert_error;
1860
1861 /* Set version number for the certificate (X509v3) and the serial
1862 * number */
1863 if (X509_set_version(newcrt, 2L) != 1)
1864 goto mkcert_error;
Olivier Houchard2be5a4c2019-03-08 18:54:43 +01001865 ASN1_INTEGER_set(X509_get_serialNumber(newcrt), _HA_ATOMIC_ADD(&ssl_ctx_serial, 1));
Christopher Faulet31af49d2015-06-09 17:29:50 +02001866
1867 /* Set duration for the certificate */
Rosen Penev68185952018-12-14 08:47:02 -08001868 if (!X509_gmtime_adj(X509_getm_notBefore(newcrt), (long)-60*60*24) ||
1869 !X509_gmtime_adj(X509_getm_notAfter(newcrt),(long)60*60*24*365))
Christopher Faulet31af49d2015-06-09 17:29:50 +02001870 goto mkcert_error;
1871
1872 /* set public key in the certificate */
1873 if (X509_set_pubkey(newcrt, pkey) != 1)
1874 goto mkcert_error;
1875
1876 /* Set issuer name from the CA */
1877 if (!(name = X509_get_subject_name(cacert)))
1878 goto mkcert_error;
1879 if (X509_set_issuer_name(newcrt, name) != 1)
1880 goto mkcert_error;
1881
1882 /* Set the subject name using the same, but the CN */
1883 name = X509_NAME_dup(name);
1884 if (X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC,
1885 (const unsigned char *)servername,
1886 -1, -1, 0) != 1) {
1887 X509_NAME_free(name);
1888 goto mkcert_error;
1889 }
1890 if (X509_set_subject_name(newcrt, name) != 1) {
1891 X509_NAME_free(name);
1892 goto mkcert_error;
1893 }
1894 X509_NAME_free(name);
1895
1896 /* Add x509v3 extensions as specified */
Emmanuel Hocdeta9b84022018-10-01 18:41:36 +02001897 ctmp = NCONF_new(NULL);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001898 X509V3_set_ctx(&ctx, cacert, newcrt, NULL, NULL, 0);
1899 for (i = 0; i < X509V3_EXT_SIZE; i++) {
1900 X509_EXTENSION *ext;
1901
Emmanuel Hocdeta9b84022018-10-01 18:41:36 +02001902 if (!(ext = X509V3_EXT_nconf(ctmp, &ctx, x509v3_ext_names[i], x509v3_ext_values[i])))
Christopher Faulet31af49d2015-06-09 17:29:50 +02001903 goto mkcert_error;
1904 if (!X509_add_ext(newcrt, ext, -1)) {
1905 X509_EXTENSION_free(ext);
1906 goto mkcert_error;
1907 }
1908 X509_EXTENSION_free(ext);
1909 }
1910
1911 /* Sign the certificate with the CA private key */
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001912
1913 key_type = EVP_PKEY_base_id(capkey);
1914
1915 if (key_type == EVP_PKEY_DSA)
1916 digest = EVP_sha1();
1917 else if (key_type == EVP_PKEY_RSA)
Christopher Faulet31af49d2015-06-09 17:29:50 +02001918 digest = EVP_sha256();
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001919 else if (key_type == EVP_PKEY_EC)
Christopher Faulet7969a332015-10-09 11:15:03 +02001920 digest = EVP_sha256();
1921 else {
Willy Tarreau9a1ab082019-05-09 13:26:41 +02001922#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000000fL) && !defined(OPENSSL_IS_BORINGSSL)
Christopher Faulet7969a332015-10-09 11:15:03 +02001923 int nid;
1924
1925 if (EVP_PKEY_get_default_digest_nid(capkey, &nid) <= 0)
1926 goto mkcert_error;
1927 if (!(digest = EVP_get_digestbynid(nid)))
1928 goto mkcert_error;
Christopher Faulete7db2162015-10-19 13:59:24 +02001929#else
1930 goto mkcert_error;
1931#endif
Christopher Faulet7969a332015-10-09 11:15:03 +02001932 }
1933
Christopher Faulet31af49d2015-06-09 17:29:50 +02001934 if (!(X509_sign(newcrt, capkey, digest)))
1935 goto mkcert_error;
1936
1937 /* Create and set the new SSL_CTX */
1938 if (!(ssl_ctx = SSL_CTX_new(SSLv23_server_method())))
1939 goto mkcert_error;
1940 if (!SSL_CTX_use_PrivateKey(ssl_ctx, pkey))
1941 goto mkcert_error;
1942 if (!SSL_CTX_use_certificate(ssl_ctx, newcrt))
1943 goto mkcert_error;
1944 if (!SSL_CTX_check_private_key(ssl_ctx))
1945 goto mkcert_error;
1946
1947 if (newcrt) X509_free(newcrt);
Christopher Faulet7969a332015-10-09 11:15:03 +02001948
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01001949#ifndef OPENSSL_NO_DH
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001950 SSL_CTX_set_tmp_dh_callback(ssl_ctx, ssl_get_tmp_dh);
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01001951#endif
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001952#if defined(SSL_CTX_set_tmp_ecdh) && !defined(OPENSSL_NO_ECDH)
1953 {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01001954 const char *ecdhe = (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe : ECDHE_DEFAULT_CURVE);
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001955 EC_KEY *ecc;
1956 int nid;
1957
1958 if ((nid = OBJ_sn2nid(ecdhe)) == NID_undef)
1959 goto end;
1960 if (!(ecc = EC_KEY_new_by_curve_name(nid)))
1961 goto end;
1962 SSL_CTX_set_tmp_ecdh(ssl_ctx, ecc);
1963 EC_KEY_free(ecc);
1964 }
1965#endif
1966 end:
Christopher Faulet31af49d2015-06-09 17:29:50 +02001967 return ssl_ctx;
1968
1969 mkcert_error:
Emmanuel Hocdeta9b84022018-10-01 18:41:36 +02001970 if (ctmp) NCONF_free(ctmp);
Emmanuel Hocdet15969292017-08-11 10:56:00 +02001971 if (tmp_ssl) SSL_free(tmp_ssl);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001972 if (ssl_ctx) SSL_CTX_free(ssl_ctx);
1973 if (newcrt) X509_free(newcrt);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001974 return NULL;
1975}
1976
Christopher Faulet7969a332015-10-09 11:15:03 +02001977SSL_CTX *
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001978ssl_sock_create_cert(struct connection *conn, const char *servername, unsigned int key)
Christopher Faulet7969a332015-10-09 11:15:03 +02001979{
Willy Tarreau07d94e42018-09-20 10:57:52 +02001980 struct bind_conf *bind_conf = __objt_listener(conn->target)->bind_conf;
Olivier Houchard66ab4982019-02-26 18:37:15 +01001981 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001982
Olivier Houchard66ab4982019-02-26 18:37:15 +01001983 return ssl_sock_do_create_cert(servername, bind_conf, ctx->ssl);
Christopher Faulet7969a332015-10-09 11:15:03 +02001984}
1985
Christopher Faulet30548802015-06-11 13:39:32 +02001986/* Do a lookup for a certificate in the LRU cache used to store generated
Emeric Brun821bb9b2017-06-15 16:37:39 +02001987 * certificates and immediately assign it to the SSL session if not null. */
Christopher Faulet30548802015-06-11 13:39:32 +02001988SSL_CTX *
Emeric Brun821bb9b2017-06-15 16:37:39 +02001989ssl_sock_assign_generated_cert(unsigned int key, struct bind_conf *bind_conf, SSL *ssl)
Christopher Faulet30548802015-06-11 13:39:32 +02001990{
1991 struct lru64 *lru = NULL;
1992
1993 if (ssl_ctx_lru_tree) {
Willy Tarreau03f4ec42018-05-17 10:56:47 +02001994 HA_RWLOCK_WRLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001995 lru = lru64_lookup(key, ssl_ctx_lru_tree, bind_conf->ca_sign_cert, 0);
Emeric Brun821bb9b2017-06-15 16:37:39 +02001996 if (lru && lru->domain) {
1997 if (ssl)
1998 SSL_set_SSL_CTX(ssl, (SSL_CTX *)lru->data);
Willy Tarreau03f4ec42018-05-17 10:56:47 +02001999 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet30548802015-06-11 13:39:32 +02002000 return (SSL_CTX *)lru->data;
Emeric Brun821bb9b2017-06-15 16:37:39 +02002001 }
Willy Tarreau03f4ec42018-05-17 10:56:47 +02002002 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet30548802015-06-11 13:39:32 +02002003 }
2004 return NULL;
2005}
2006
Emeric Brun821bb9b2017-06-15 16:37:39 +02002007/* Same as <ssl_sock_assign_generated_cert> but without SSL session. This
2008 * function is not thread-safe, it should only be used to check if a certificate
2009 * exists in the lru cache (with no warranty it will not be removed by another
2010 * thread). It is kept for backward compatibility. */
2011SSL_CTX *
2012ssl_sock_get_generated_cert(unsigned int key, struct bind_conf *bind_conf)
2013{
2014 return ssl_sock_assign_generated_cert(key, bind_conf, NULL);
2015}
2016
Christopher Fauletd2cab922015-07-28 16:03:47 +02002017/* Set a certificate int the LRU cache used to store generated
2018 * certificate. Return 0 on success, otherwise -1 */
2019int
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002020ssl_sock_set_generated_cert(SSL_CTX *ssl_ctx, unsigned int key, struct bind_conf *bind_conf)
Christopher Faulet30548802015-06-11 13:39:32 +02002021{
2022 struct lru64 *lru = NULL;
2023
2024 if (ssl_ctx_lru_tree) {
Christopher Faulet2a944ee2017-11-07 10:42:54 +01002025 HA_RWLOCK_WRLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002026 lru = lru64_get(key, ssl_ctx_lru_tree, bind_conf->ca_sign_cert, 0);
Emeric Brun821bb9b2017-06-15 16:37:39 +02002027 if (!lru) {
Christopher Faulet2a944ee2017-11-07 10:42:54 +01002028 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Fauletd2cab922015-07-28 16:03:47 +02002029 return -1;
Emeric Brun821bb9b2017-06-15 16:37:39 +02002030 }
Christopher Faulet30548802015-06-11 13:39:32 +02002031 if (lru->domain && lru->data)
2032 lru->free((SSL_CTX *)lru->data);
Christopher Faulet7969a332015-10-09 11:15:03 +02002033 lru64_commit(lru, ssl_ctx, bind_conf->ca_sign_cert, 0, (void (*)(void *))SSL_CTX_free);
Christopher Faulet2a944ee2017-11-07 10:42:54 +01002034 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Fauletd2cab922015-07-28 16:03:47 +02002035 return 0;
Christopher Faulet30548802015-06-11 13:39:32 +02002036 }
Christopher Fauletd2cab922015-07-28 16:03:47 +02002037 return -1;
Christopher Faulet30548802015-06-11 13:39:32 +02002038}
2039
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002040/* Compute the key of the certificate. */
Christopher Faulet30548802015-06-11 13:39:32 +02002041unsigned int
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002042ssl_sock_generated_cert_key(const void *data, size_t len)
Christopher Faulet30548802015-06-11 13:39:32 +02002043{
2044 return XXH32(data, len, ssl_ctx_lru_seed);
2045}
2046
Willy Tarreau2f63ef42015-10-20 15:16:01 +02002047/* Generate a cert and immediately assign it to the SSL session so that the cert's
2048 * refcount is maintained regardless of the cert's presence in the LRU cache.
2049 */
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002050static int
Christopher Faulet7969a332015-10-09 11:15:03 +02002051ssl_sock_generate_certificate(const char *servername, struct bind_conf *bind_conf, SSL *ssl)
Christopher Faulet31af49d2015-06-09 17:29:50 +02002052{
2053 X509 *cacert = bind_conf->ca_sign_cert;
Christopher Faulet31af49d2015-06-09 17:29:50 +02002054 SSL_CTX *ssl_ctx = NULL;
2055 struct lru64 *lru = NULL;
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002056 unsigned int key;
Christopher Faulet31af49d2015-06-09 17:29:50 +02002057
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002058 key = ssl_sock_generated_cert_key(servername, strlen(servername));
Christopher Faulet31af49d2015-06-09 17:29:50 +02002059 if (ssl_ctx_lru_tree) {
Christopher Faulet2a944ee2017-11-07 10:42:54 +01002060 HA_RWLOCK_WRLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002061 lru = lru64_get(key, ssl_ctx_lru_tree, cacert, 0);
Christopher Faulet31af49d2015-06-09 17:29:50 +02002062 if (lru && lru->domain)
2063 ssl_ctx = (SSL_CTX *)lru->data;
Christopher Fauletd2cab922015-07-28 16:03:47 +02002064 if (!ssl_ctx && lru) {
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002065 ssl_ctx = ssl_sock_do_create_cert(servername, bind_conf, ssl);
Christopher Faulet31af49d2015-06-09 17:29:50 +02002066 lru64_commit(lru, ssl_ctx, cacert, 0, (void (*)(void *))SSL_CTX_free);
Christopher Fauletd2cab922015-07-28 16:03:47 +02002067 }
Willy Tarreau2f63ef42015-10-20 15:16:01 +02002068 SSL_set_SSL_CTX(ssl, ssl_ctx);
Christopher Faulet2a944ee2017-11-07 10:42:54 +01002069 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002070 return 1;
Christopher Faulet31af49d2015-06-09 17:29:50 +02002071 }
Willy Tarreau2f63ef42015-10-20 15:16:01 +02002072 else {
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002073 ssl_ctx = ssl_sock_do_create_cert(servername, bind_conf, ssl);
Willy Tarreau2f63ef42015-10-20 15:16:01 +02002074 SSL_set_SSL_CTX(ssl, ssl_ctx);
2075 /* No LRU cache, this CTX will be released as soon as the session dies */
2076 SSL_CTX_free(ssl_ctx);
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002077 return 1;
Willy Tarreau2f63ef42015-10-20 15:16:01 +02002078 }
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002079 return 0;
2080}
2081static int
2082ssl_sock_generate_certificate_from_conn(struct bind_conf *bind_conf, SSL *ssl)
2083{
2084 unsigned int key;
Thierry FOURNIER28962c92018-06-17 21:37:05 +02002085 struct connection *conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002086
2087 conn_get_to_addr(conn);
2088 if (conn->flags & CO_FL_ADDR_TO_SET) {
2089 key = ssl_sock_generated_cert_key(&conn->addr.to, get_addr_len(&conn->addr.to));
Emeric Brun821bb9b2017-06-15 16:37:39 +02002090 if (ssl_sock_assign_generated_cert(key, bind_conf, ssl))
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002091 return 1;
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002092 }
2093 return 0;
Christopher Faulet31af49d2015-06-09 17:29:50 +02002094}
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002095#endif /* !defined SSL_NO_GENERATE_CERTIFICATES */
Christopher Faulet31af49d2015-06-09 17:29:50 +02002096
Willy Tarreau9a1ab082019-05-09 13:26:41 +02002097#if (HA_OPENSSL_VERSION_NUMBER < 0x1010000fL)
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002098typedef enum { SET_CLIENT, SET_SERVER } set_context_func;
2099
2100static void ctx_set_SSLv3_func(SSL_CTX *ctx, set_context_func c)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002101{
Emmanuel Hocdet23877ab2017-07-12 12:53:02 +02002102#if SSL_OP_NO_SSLv3
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002103 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, SSLv3_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002104 : SSL_CTX_set_ssl_version(ctx, SSLv3_client_method());
2105#endif
2106}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002107static void ctx_set_TLSv10_func(SSL_CTX *ctx, set_context_func c) {
2108 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, TLSv1_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002109 : SSL_CTX_set_ssl_version(ctx, TLSv1_client_method());
2110}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002111static void ctx_set_TLSv11_func(SSL_CTX *ctx, set_context_func c) {
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002112#if SSL_OP_NO_TLSv1_1
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002113 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, TLSv1_1_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002114 : SSL_CTX_set_ssl_version(ctx, TLSv1_1_client_method());
2115#endif
2116}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002117static void ctx_set_TLSv12_func(SSL_CTX *ctx, set_context_func c) {
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002118#if SSL_OP_NO_TLSv1_2
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002119 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, TLSv1_2_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002120 : SSL_CTX_set_ssl_version(ctx, TLSv1_2_client_method());
2121#endif
2122}
Bertrand Jacquina25282b2018-08-14 00:56:13 +01002123/* TLSv1.2 is the last supported version in this context. */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002124static void ctx_set_TLSv13_func(SSL_CTX *ctx, set_context_func c) {}
2125/* Unusable in this context. */
2126static void ssl_set_SSLv3_func(SSL *ssl, set_context_func c) {}
2127static void ssl_set_TLSv10_func(SSL *ssl, set_context_func c) {}
2128static void ssl_set_TLSv11_func(SSL *ssl, set_context_func c) {}
2129static void ssl_set_TLSv12_func(SSL *ssl, set_context_func c) {}
2130static void ssl_set_TLSv13_func(SSL *ssl, set_context_func c) {}
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002131#else /* openssl >= 1.1.0 */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002132typedef enum { SET_MIN, SET_MAX } set_context_func;
2133
2134static void ctx_set_SSLv3_func(SSL_CTX *ctx, set_context_func c) {
2135 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, SSL3_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002136 : SSL_CTX_set_min_proto_version(ctx, SSL3_VERSION);
2137}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002138static void ssl_set_SSLv3_func(SSL *ssl, set_context_func c) {
2139 c == SET_MAX ? SSL_set_max_proto_version(ssl, SSL3_VERSION)
2140 : SSL_set_min_proto_version(ssl, SSL3_VERSION);
2141}
2142static void ctx_set_TLSv10_func(SSL_CTX *ctx, set_context_func c) {
2143 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002144 : SSL_CTX_set_min_proto_version(ctx, TLS1_VERSION);
2145}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002146static void ssl_set_TLSv10_func(SSL *ssl, set_context_func c) {
2147 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_VERSION)
2148 : SSL_set_min_proto_version(ssl, TLS1_VERSION);
2149}
2150static void ctx_set_TLSv11_func(SSL_CTX *ctx, set_context_func c) {
2151 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_1_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002152 : SSL_CTX_set_min_proto_version(ctx, TLS1_1_VERSION);
2153}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002154static void ssl_set_TLSv11_func(SSL *ssl, set_context_func c) {
2155 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_1_VERSION)
2156 : SSL_set_min_proto_version(ssl, TLS1_1_VERSION);
2157}
2158static void ctx_set_TLSv12_func(SSL_CTX *ctx, set_context_func c) {
2159 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_2_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002160 : SSL_CTX_set_min_proto_version(ctx, TLS1_2_VERSION);
2161}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002162static void ssl_set_TLSv12_func(SSL *ssl, set_context_func c) {
2163 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_2_VERSION)
2164 : SSL_set_min_proto_version(ssl, TLS1_2_VERSION);
2165}
2166static void ctx_set_TLSv13_func(SSL_CTX *ctx, set_context_func c) {
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002167#if SSL_OP_NO_TLSv1_3
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002168 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_3_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002169 : SSL_CTX_set_min_proto_version(ctx, TLS1_3_VERSION);
2170#endif
2171}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002172static void ssl_set_TLSv13_func(SSL *ssl, set_context_func c) {
2173#if SSL_OP_NO_TLSv1_3
2174 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_3_VERSION)
2175 : SSL_set_min_proto_version(ssl, TLS1_3_VERSION);
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002176#endif
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002177}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002178#endif
2179static void ctx_set_None_func(SSL_CTX *ctx, set_context_func c) { }
2180static void ssl_set_None_func(SSL *ssl, set_context_func c) { }
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002181
2182static struct {
2183 int option;
2184 uint16_t flag;
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002185 void (*ctx_set_version)(SSL_CTX *, set_context_func);
2186 void (*ssl_set_version)(SSL *, set_context_func);
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002187 const char *name;
2188} methodVersions[] = {
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002189 {0, 0, ctx_set_None_func, ssl_set_None_func, "NONE"}, /* CONF_TLSV_NONE */
2190 {SSL_OP_NO_SSLv3, MC_SSL_O_NO_SSLV3, ctx_set_SSLv3_func, ssl_set_SSLv3_func, "SSLv3"}, /* CONF_SSLV3 */
2191 {SSL_OP_NO_TLSv1, MC_SSL_O_NO_TLSV10, ctx_set_TLSv10_func, ssl_set_TLSv10_func, "TLSv1.0"}, /* CONF_TLSV10 */
2192 {SSL_OP_NO_TLSv1_1, MC_SSL_O_NO_TLSV11, ctx_set_TLSv11_func, ssl_set_TLSv11_func, "TLSv1.1"}, /* CONF_TLSV11 */
2193 {SSL_OP_NO_TLSv1_2, MC_SSL_O_NO_TLSV12, ctx_set_TLSv12_func, ssl_set_TLSv12_func, "TLSv1.2"}, /* CONF_TLSV12 */
2194 {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 +02002195};
2196
Emmanuel Hocdet530141f2017-03-01 18:54:56 +01002197static void ssl_sock_switchctx_set(SSL *ssl, SSL_CTX *ctx)
2198{
2199 SSL_set_verify(ssl, SSL_CTX_get_verify_mode(ctx), ssl_sock_bind_verifycbk);
2200 SSL_set_client_CA_list(ssl, SSL_dup_CA_list(SSL_CTX_get_client_CA_list(ctx)));
2201 SSL_set_SSL_CTX(ssl, ctx);
2202}
2203
Willy Tarreau5db847a2019-05-09 14:13:35 +02002204#if ((HA_OPENSSL_VERSION_NUMBER >= 0x10101000L) || defined(OPENSSL_IS_BORINGSSL))
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002205
2206static int ssl_sock_switchctx_err_cbk(SSL *ssl, int *al, void *priv)
2207{
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002208 struct bind_conf *s = priv;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002209 (void)al; /* shut gcc stupid warning */
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002210
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002211 if (SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name) || s->generate_certs)
2212 return SSL_TLSEXT_ERR_OK;
2213 return SSL_TLSEXT_ERR_NOACK;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002214}
2215
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002216#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002217static int ssl_sock_switchctx_cbk(const struct ssl_early_callback_ctx *ctx)
2218{
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002219 SSL *ssl = ctx->ssl;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002220#else
2221static int ssl_sock_switchctx_cbk(SSL *ssl, int *al, void *arg)
2222{
2223#endif
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002224 struct connection *conn;
2225 struct bind_conf *s;
2226 const uint8_t *extension_data;
2227 size_t extension_len;
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002228 int has_rsa_sig = 0, has_ecdsa_sig = 0;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002229
2230 char *wildp = NULL;
2231 const uint8_t *servername;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002232 size_t servername_len;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002233 struct ebmb_node *node, *n, *node_ecdsa = NULL, *node_rsa = NULL, *node_anonymous = NULL;
Olivier Houchardc2aae742017-09-22 18:26:28 +02002234 int allow_early = 0;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002235 int i;
2236
Thierry FOURNIER28962c92018-06-17 21:37:05 +02002237 conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Willy Tarreaua8825522018-10-15 13:20:07 +02002238 s = __objt_listener(conn->target)->bind_conf;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002239
Olivier Houchard9679ac92017-10-27 14:58:08 +02002240 if (s->ssl_conf.early_data)
Olivier Houchardc2aae742017-09-22 18:26:28 +02002241 allow_early = 1;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002242#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002243 if (SSL_early_callback_ctx_extension_get(ctx, TLSEXT_TYPE_server_name,
2244 &extension_data, &extension_len)) {
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002245#else
2246 if (SSL_client_hello_get0_ext(ssl, TLSEXT_TYPE_server_name, &extension_data, &extension_len)) {
2247#endif
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002248 /*
2249 * The server_name extension was given too much extensibility when it
2250 * was written, so parsing the normal case is a bit complex.
2251 */
2252 size_t len;
2253 if (extension_len <= 2)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002254 goto abort;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002255 /* Extract the length of the supplied list of names. */
2256 len = (*extension_data++) << 8;
2257 len |= *extension_data++;
2258 if (len + 2 != extension_len)
2259 goto abort;
2260 /*
2261 * The list in practice only has a single element, so we only consider
2262 * the first one.
2263 */
2264 if (len == 0 || *extension_data++ != TLSEXT_NAMETYPE_host_name)
2265 goto abort;
2266 extension_len = len - 1;
2267 /* Now we can finally pull out the byte array with the actual hostname. */
2268 if (extension_len <= 2)
2269 goto abort;
2270 len = (*extension_data++) << 8;
2271 len |= *extension_data++;
2272 if (len == 0 || len + 2 > extension_len || len > TLSEXT_MAXLEN_host_name
2273 || memchr(extension_data, 0, len) != NULL)
2274 goto abort;
2275 servername = extension_data;
2276 servername_len = len;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002277 } else {
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002278#if (!defined SSL_NO_GENERATE_CERTIFICATES)
2279 if (s->generate_certs && ssl_sock_generate_certificate_from_conn(s, ssl)) {
Olivier Houchardc2aae742017-09-22 18:26:28 +02002280 goto allow_early;
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002281 }
2282#endif
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002283 /* without SNI extension, is the default_ctx (need SSL_TLSEXT_ERR_NOACK) */
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002284 if (!s->strict_sni) {
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002285 ssl_sock_switchctx_set(ssl, s->default_ctx);
Olivier Houchardc2aae742017-09-22 18:26:28 +02002286 goto allow_early;
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002287 }
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002288 goto abort;
2289 }
2290
2291 /* extract/check clientHello informations */
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002292#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002293 if (SSL_early_callback_ctx_extension_get(ctx, TLSEXT_TYPE_signature_algorithms, &extension_data, &extension_len)) {
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002294#else
2295 if (SSL_client_hello_get0_ext(ssl, TLSEXT_TYPE_signature_algorithms, &extension_data, &extension_len)) {
2296#endif
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002297 uint8_t sign;
2298 size_t len;
2299 if (extension_len < 2)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002300 goto abort;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002301 len = (*extension_data++) << 8;
2302 len |= *extension_data++;
2303 if (len + 2 != extension_len)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002304 goto abort;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002305 if (len % 2 != 0)
2306 goto abort;
2307 for (; len > 0; len -= 2) {
2308 extension_data++; /* hash */
2309 sign = *extension_data++;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002310 switch (sign) {
2311 case TLSEXT_signature_rsa:
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002312 has_rsa_sig = 1;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002313 break;
2314 case TLSEXT_signature_ecdsa:
2315 has_ecdsa_sig = 1;
2316 break;
2317 default:
2318 continue;
2319 }
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002320 if (has_ecdsa_sig && has_rsa_sig)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002321 break;
2322 }
2323 } else {
Bertrand Jacquina25282b2018-08-14 00:56:13 +01002324 /* without TLSEXT_TYPE_signature_algorithms extension (< TLSv1.2) */
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002325 has_rsa_sig = 1;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002326 }
2327 if (has_ecdsa_sig) { /* in very rare case: has ecdsa sign but not a ECDSA cipher */
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002328 const SSL_CIPHER *cipher;
2329 size_t len;
2330 const uint8_t *cipher_suites;
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002331 has_ecdsa_sig = 0;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002332#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002333 len = ctx->cipher_suites_len;
2334 cipher_suites = ctx->cipher_suites;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002335#else
2336 len = SSL_client_hello_get0_ciphers(ssl, &cipher_suites);
2337#endif
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002338 if (len % 2 != 0)
2339 goto abort;
2340 for (; len != 0; len -= 2, cipher_suites += 2) {
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002341#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002342 uint16_t cipher_suite = (cipher_suites[0] << 8) | cipher_suites[1];
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002343 cipher = SSL_get_cipher_by_value(cipher_suite);
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002344#else
2345 cipher = SSL_CIPHER_find(ssl, cipher_suites);
2346#endif
Emmanuel Hocdet019f9b12017-10-02 17:12:06 +02002347 if (cipher && SSL_CIPHER_get_auth_nid(cipher) == NID_auth_ecdsa) {
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002348 has_ecdsa_sig = 1;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002349 break;
2350 }
2351 }
2352 }
2353
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002354 for (i = 0; i < trash.size && i < servername_len; i++) {
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002355 trash.area[i] = tolower(servername[i]);
2356 if (!wildp && (trash.area[i] == '.'))
2357 wildp = &trash.area[i];
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002358 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002359 trash.area[i] = 0;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002360
2361 /* lookup in full qualified names */
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002362 node = ebst_lookup(&s->sni_ctx, trash.area);
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002363
2364 /* lookup a not neg filter */
2365 for (n = node; n; n = ebmb_next_dup(n)) {
2366 if (!container_of(n, struct sni_ctx, name)->neg) {
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002367 switch(container_of(n, struct sni_ctx, name)->kinfo.sig) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002368 case TLSEXT_signature_ecdsa:
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002369 if (!node_ecdsa)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002370 node_ecdsa = n;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002371 break;
2372 case TLSEXT_signature_rsa:
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002373 if (!node_rsa)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002374 node_rsa = n;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002375 break;
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002376 default: /* TLSEXT_signature_anonymous|dsa */
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002377 if (!node_anonymous)
2378 node_anonymous = n;
2379 break;
2380 }
2381 }
2382 }
2383 if (wildp) {
2384 /* lookup in wildcards names */
2385 node = ebst_lookup(&s->sni_w_ctx, wildp);
2386 for (n = node; n; n = ebmb_next_dup(n)) {
2387 if (!container_of(n, struct sni_ctx, name)->neg) {
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002388 switch(container_of(n, struct sni_ctx, name)->kinfo.sig) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002389 case TLSEXT_signature_ecdsa:
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002390 if (!node_ecdsa)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002391 node_ecdsa = n;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002392 break;
2393 case TLSEXT_signature_rsa:
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002394 if (!node_rsa)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002395 node_rsa = n;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002396 break;
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002397 default: /* TLSEXT_signature_anonymous|dsa */
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002398 if (!node_anonymous)
2399 node_anonymous = n;
2400 break;
2401 }
2402 }
2403 }
2404 }
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002405 /* select by key_signature priority order */
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002406 node = (has_ecdsa_sig && node_ecdsa) ? node_ecdsa
2407 : ((has_rsa_sig && node_rsa) ? node_rsa
2408 : (node_anonymous ? node_anonymous
2409 : (node_ecdsa ? node_ecdsa /* no ecdsa signature case (< TLSv1.2) */
2410 : node_rsa /* no rsa signature case (far far away) */
2411 )));
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002412 if (node) {
2413 /* switch ctx */
Emmanuel Hocdet43664762017-08-09 18:26:20 +02002414 struct ssl_bind_conf *conf = container_of(node, struct sni_ctx, name)->conf;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002415 ssl_sock_switchctx_set(ssl, container_of(node, struct sni_ctx, name)->ctx);
Olivier Houchard35a63cc2017-11-02 19:04:38 +01002416 if (conf) {
2417 methodVersions[conf->ssl_methods.min].ssl_set_version(ssl, SET_MIN);
2418 methodVersions[conf->ssl_methods.max].ssl_set_version(ssl, SET_MAX);
2419 if (conf->early_data)
2420 allow_early = 1;
2421 }
2422 goto allow_early;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002423 }
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002424#if (!defined SSL_NO_GENERATE_CERTIFICATES)
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002425 if (s->generate_certs && ssl_sock_generate_certificate(trash.area, s, ssl)) {
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002426 /* switch ctx done in ssl_sock_generate_certificate */
Olivier Houchardc2aae742017-09-22 18:26:28 +02002427 goto allow_early;
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002428 }
2429#endif
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002430 if (!s->strict_sni) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002431 /* no certificate match, is the default_ctx */
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002432 ssl_sock_switchctx_set(ssl, s->default_ctx);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002433 }
Olivier Houchardc2aae742017-09-22 18:26:28 +02002434allow_early:
2435#ifdef OPENSSL_IS_BORINGSSL
2436 if (allow_early)
2437 SSL_set_early_data_enabled(ssl, 1);
2438#else
2439 if (!allow_early)
2440 SSL_set_max_early_data(ssl, 0);
2441#endif
2442 return 1;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002443 abort:
2444 /* abort handshake (was SSL_TLSEXT_ERR_ALERT_FATAL) */
2445 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002446#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002447 return ssl_select_cert_error;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002448#else
2449 *al = SSL_AD_UNRECOGNIZED_NAME;
2450 return 0;
2451#endif
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002452}
2453
2454#else /* OPENSSL_IS_BORINGSSL */
2455
Emeric Brunfc0421f2012-09-07 17:30:07 +02002456/* Sets the SSL ctx of <ssl> to match the advertised server name. Returns a
2457 * warning when no match is found, which implies the default (first) cert
2458 * will keep being used.
2459 */
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002460static int ssl_sock_switchctx_cbk(SSL *ssl, int *al, void *priv)
Emeric Brunfc0421f2012-09-07 17:30:07 +02002461{
2462 const char *servername;
2463 const char *wildp = NULL;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002464 struct ebmb_node *node, *n;
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002465 struct bind_conf *s = priv;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002466 int i;
2467 (void)al; /* shut gcc stupid warning */
2468
2469 servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
Emmanuel Hocdet65623372013-01-24 17:17:15 +01002470 if (!servername) {
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002471#if (!defined SSL_NO_GENERATE_CERTIFICATES)
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002472 if (s->generate_certs && ssl_sock_generate_certificate_from_conn(s, ssl))
2473 return SSL_TLSEXT_ERR_OK;
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002474#endif
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002475 if (s->strict_sni)
2476 return SSL_TLSEXT_ERR_ALERT_FATAL;
2477 ssl_sock_switchctx_set(ssl, s->default_ctx);
2478 return SSL_TLSEXT_ERR_NOACK;
Emmanuel Hocdet65623372013-01-24 17:17:15 +01002479 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02002480
Willy Tarreau19d14ef2012-10-29 16:51:55 +01002481 for (i = 0; i < trash.size; i++) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02002482 if (!servername[i])
2483 break;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002484 trash.area[i] = tolower(servername[i]);
2485 if (!wildp && (trash.area[i] == '.'))
2486 wildp = &trash.area[i];
Emeric Brunfc0421f2012-09-07 17:30:07 +02002487 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002488 trash.area[i] = 0;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002489
2490 /* lookup in full qualified names */
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002491 node = ebst_lookup(&s->sni_ctx, trash.area);
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002492
2493 /* lookup a not neg filter */
2494 for (n = node; n; n = ebmb_next_dup(n)) {
2495 if (!container_of(n, struct sni_ctx, name)->neg) {
2496 node = n;
2497 break;
Emmanuel Hocdet65623372013-01-24 17:17:15 +01002498 }
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002499 }
2500 if (!node && wildp) {
2501 /* lookup in wildcards names */
Emeric Brunfc0421f2012-09-07 17:30:07 +02002502 node = ebst_lookup(&s->sni_w_ctx, wildp);
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002503 }
2504 if (!node || container_of(node, struct sni_ctx, name)->neg) {
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002505#if (!defined SSL_NO_GENERATE_CERTIFICATES)
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002506 if (s->generate_certs && ssl_sock_generate_certificate(servername, s, ssl)) {
2507 /* switch ctx done in ssl_sock_generate_certificate */
Christopher Faulet31af49d2015-06-09 17:29:50 +02002508 return SSL_TLSEXT_ERR_OK;
2509 }
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002510#endif
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002511 if (s->strict_sni)
2512 return SSL_TLSEXT_ERR_ALERT_FATAL;
2513 ssl_sock_switchctx_set(ssl, s->default_ctx);
2514 return SSL_TLSEXT_ERR_OK;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002515 }
2516
2517 /* switch ctx */
Emmanuel Hocdet530141f2017-03-01 18:54:56 +01002518 ssl_sock_switchctx_set(ssl, container_of(node, struct sni_ctx, name)->ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02002519 return SSL_TLSEXT_ERR_OK;
2520}
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002521#endif /* (!) OPENSSL_IS_BORINGSSL */
Emeric Brunfc0421f2012-09-07 17:30:07 +02002522#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
2523
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002524#ifndef OPENSSL_NO_DH
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002525
2526static DH * ssl_get_dh_1024(void)
2527{
Remi Gacogned3a341a2015-05-29 16:26:17 +02002528 static unsigned char dh1024_p[]={
2529 0xFA,0xF9,0x2A,0x22,0x2A,0xA7,0x7F,0xE1,0x67,0x4E,0x53,0xF7,
2530 0x56,0x13,0xC3,0xB1,0xE3,0x29,0x6B,0x66,0x31,0x6A,0x7F,0xB3,
2531 0xC2,0x68,0x6B,0xCB,0x1D,0x57,0x39,0x1D,0x1F,0xFF,0x1C,0xC9,
2532 0xA6,0xA4,0x98,0x82,0x31,0x5D,0x25,0xFF,0x8A,0xE0,0x73,0x96,
2533 0x81,0xC8,0x83,0x79,0xC1,0x5A,0x04,0xF8,0x37,0x0D,0xA8,0x3D,
2534 0xAE,0x74,0xBC,0xDB,0xB6,0xA4,0x75,0xD9,0x71,0x8A,0xA0,0x17,
2535 0x9E,0x2D,0xC8,0xA8,0xDF,0x2C,0x5F,0x82,0x95,0xF8,0x92,0x9B,
2536 0xA7,0x33,0x5F,0x89,0x71,0xC8,0x2D,0x6B,0x18,0x86,0xC4,0x94,
2537 0x22,0xA5,0x52,0x8D,0xF6,0xF6,0xD2,0x37,0x92,0x0F,0xA5,0xCC,
2538 0xDB,0x7B,0x1D,0x3D,0xA1,0x31,0xB7,0x80,0x8F,0x0B,0x67,0x5E,
2539 0x36,0xA5,0x60,0x0C,0xF1,0x95,0x33,0x8B,
2540 };
2541 static unsigned char dh1024_g[]={
2542 0x02,
2543 };
2544
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002545 BIGNUM *p;
2546 BIGNUM *g;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002547 DH *dh = DH_new();
2548 if (dh) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002549 p = BN_bin2bn(dh1024_p, sizeof dh1024_p, NULL);
2550 g = BN_bin2bn(dh1024_g, sizeof dh1024_g, NULL);
Remi Gacogned3a341a2015-05-29 16:26:17 +02002551
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002552 if (!p || !g) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002553 DH_free(dh);
2554 dh = NULL;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002555 } else {
2556 DH_set0_pqg(dh, p, NULL, g);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002557 }
2558 }
2559 return dh;
2560}
2561
2562static DH *ssl_get_dh_2048(void)
2563{
Remi Gacogned3a341a2015-05-29 16:26:17 +02002564 static unsigned char dh2048_p[]={
2565 0xEC,0x86,0xF8,0x70,0xA0,0x33,0x16,0xEC,0x05,0x1A,0x73,0x59,
2566 0xCD,0x1F,0x8B,0xF8,0x29,0xE4,0xD2,0xCF,0x52,0xDD,0xC2,0x24,
2567 0x8D,0xB5,0x38,0x9A,0xFB,0x5C,0xA4,0xE4,0xB2,0xDA,0xCE,0x66,
2568 0x50,0x74,0xA6,0x85,0x4D,0x4B,0x1D,0x30,0xB8,0x2B,0xF3,0x10,
2569 0xE9,0xA7,0x2D,0x05,0x71,0xE7,0x81,0xDF,0x8B,0x59,0x52,0x3B,
2570 0x5F,0x43,0x0B,0x68,0xF1,0xDB,0x07,0xBE,0x08,0x6B,0x1B,0x23,
2571 0xEE,0x4D,0xCC,0x9E,0x0E,0x43,0xA0,0x1E,0xDF,0x43,0x8C,0xEC,
2572 0xBE,0xBE,0x90,0xB4,0x51,0x54,0xB9,0x2F,0x7B,0x64,0x76,0x4E,
2573 0x5D,0xD4,0x2E,0xAE,0xC2,0x9E,0xAE,0x51,0x43,0x59,0xC7,0x77,
2574 0x9C,0x50,0x3C,0x0E,0xED,0x73,0x04,0x5F,0xF1,0x4C,0x76,0x2A,
2575 0xD8,0xF8,0xCF,0xFC,0x34,0x40,0xD1,0xB4,0x42,0x61,0x84,0x66,
2576 0x42,0x39,0x04,0xF8,0x68,0xB2,0x62,0xD7,0x55,0xED,0x1B,0x74,
2577 0x75,0x91,0xE0,0xC5,0x69,0xC1,0x31,0x5C,0xDB,0x7B,0x44,0x2E,
2578 0xCE,0x84,0x58,0x0D,0x1E,0x66,0x0C,0xC8,0x44,0x9E,0xFD,0x40,
2579 0x08,0x67,0x5D,0xFB,0xA7,0x76,0x8F,0x00,0x11,0x87,0xE9,0x93,
2580 0xF9,0x7D,0xC4,0xBC,0x74,0x55,0x20,0xD4,0x4A,0x41,0x2F,0x43,
2581 0x42,0x1A,0xC1,0xF2,0x97,0x17,0x49,0x27,0x37,0x6B,0x2F,0x88,
2582 0x7E,0x1C,0xA0,0xA1,0x89,0x92,0x27,0xD9,0x56,0x5A,0x71,0xC1,
2583 0x56,0x37,0x7E,0x3A,0x9D,0x05,0xE7,0xEE,0x5D,0x8F,0x82,0x17,
2584 0xBC,0xE9,0xC2,0x93,0x30,0x82,0xF9,0xF4,0xC9,0xAE,0x49,0xDB,
2585 0xD0,0x54,0xB4,0xD9,0x75,0x4D,0xFA,0x06,0xB8,0xD6,0x38,0x41,
2586 0xB7,0x1F,0x77,0xF3,
2587 };
2588 static unsigned char dh2048_g[]={
2589 0x02,
2590 };
2591
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002592 BIGNUM *p;
2593 BIGNUM *g;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002594 DH *dh = DH_new();
2595 if (dh) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002596 p = BN_bin2bn(dh2048_p, sizeof dh2048_p, NULL);
2597 g = BN_bin2bn(dh2048_g, sizeof dh2048_g, NULL);
Remi Gacogned3a341a2015-05-29 16:26:17 +02002598
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002599 if (!p || !g) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002600 DH_free(dh);
2601 dh = NULL;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002602 } else {
2603 DH_set0_pqg(dh, p, NULL, g);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002604 }
2605 }
2606 return dh;
2607}
2608
2609static DH *ssl_get_dh_4096(void)
2610{
Remi Gacogned3a341a2015-05-29 16:26:17 +02002611 static unsigned char dh4096_p[]={
2612 0xDE,0x16,0x94,0xCD,0x99,0x58,0x07,0xF1,0xF7,0x32,0x96,0x11,
2613 0x04,0x82,0xD4,0x84,0x72,0x80,0x99,0x06,0xCA,0xF0,0xA3,0x68,
2614 0x07,0xCE,0x64,0x50,0xE7,0x74,0x45,0x20,0x80,0x5E,0x4D,0xAD,
2615 0xA5,0xB6,0xED,0xFA,0x80,0x6C,0x3B,0x35,0xC4,0x9A,0x14,0x6B,
2616 0x32,0xBB,0xFD,0x1F,0x17,0x8E,0xB7,0x1F,0xD6,0xFA,0x3F,0x7B,
2617 0xEE,0x16,0xA5,0x62,0x33,0x0D,0xED,0xBC,0x4E,0x58,0xE5,0x47,
2618 0x4D,0xE9,0xAB,0x8E,0x38,0xD3,0x6E,0x90,0x57,0xE3,0x22,0x15,
2619 0x33,0xBD,0xF6,0x43,0x45,0xB5,0x10,0x0A,0xBE,0x2C,0xB4,0x35,
2620 0xB8,0x53,0x8D,0xAD,0xFB,0xA7,0x1F,0x85,0x58,0x41,0x7A,0x79,
2621 0x20,0x68,0xB3,0xE1,0x3D,0x08,0x76,0xBF,0x86,0x0D,0x49,0xE3,
2622 0x82,0x71,0x8C,0xB4,0x8D,0x81,0x84,0xD4,0xE7,0xBE,0x91,0xDC,
2623 0x26,0x39,0x48,0x0F,0x35,0xC4,0xCA,0x65,0xE3,0x40,0x93,0x52,
2624 0x76,0x58,0x7D,0xDD,0x51,0x75,0xDC,0x69,0x61,0xBF,0x47,0x2C,
2625 0x16,0x68,0x2D,0xC9,0x29,0xD3,0xE6,0xC0,0x99,0x48,0xA0,0x9A,
2626 0xC8,0x78,0xC0,0x6D,0x81,0x67,0x12,0x61,0x3F,0x71,0xBA,0x41,
2627 0x1F,0x6C,0x89,0x44,0x03,0xBA,0x3B,0x39,0x60,0xAA,0x28,0x55,
2628 0x59,0xAE,0xB8,0xFA,0xCB,0x6F,0xA5,0x1A,0xF7,0x2B,0xDD,0x52,
2629 0x8A,0x8B,0xE2,0x71,0xA6,0x5E,0x7E,0xD8,0x2E,0x18,0xE0,0x66,
2630 0xDF,0xDD,0x22,0x21,0x99,0x52,0x73,0xA6,0x33,0x20,0x65,0x0E,
2631 0x53,0xE7,0x6B,0x9B,0xC5,0xA3,0x2F,0x97,0x65,0x76,0xD3,0x47,
2632 0x23,0x77,0x12,0xB6,0x11,0x7B,0x24,0xED,0xF1,0xEF,0xC0,0xE2,
2633 0xA3,0x7E,0x67,0x05,0x3E,0x96,0x4D,0x45,0xC2,0x18,0xD1,0x73,
2634 0x9E,0x07,0xF3,0x81,0x6E,0x52,0x63,0xF6,0x20,0x76,0xB9,0x13,
2635 0xD2,0x65,0x30,0x18,0x16,0x09,0x16,0x9E,0x8F,0xF1,0xD2,0x10,
2636 0x5A,0xD3,0xD4,0xAF,0x16,0x61,0xDA,0x55,0x2E,0x18,0x5E,0x14,
2637 0x08,0x54,0x2E,0x2A,0x25,0xA2,0x1A,0x9B,0x8B,0x32,0xA9,0xFD,
2638 0xC2,0x48,0x96,0xE1,0x80,0xCA,0xE9,0x22,0x17,0xBB,0xCE,0x3E,
2639 0x9E,0xED,0xC7,0xF1,0x1F,0xEC,0x17,0x21,0xDC,0x7B,0x82,0x48,
2640 0x8E,0xBB,0x4B,0x9D,0x5B,0x04,0x04,0xDA,0xDB,0x39,0xDF,0x01,
2641 0x40,0xC3,0xAA,0x26,0x23,0x89,0x75,0xC6,0x0B,0xD0,0xA2,0x60,
2642 0x6A,0xF1,0xCC,0x65,0x18,0x98,0x1B,0x52,0xD2,0x74,0x61,0xCC,
2643 0xBD,0x60,0xAE,0xA3,0xA0,0x66,0x6A,0x16,0x34,0x92,0x3F,0x41,
2644 0x40,0x31,0x29,0xC0,0x2C,0x63,0xB2,0x07,0x8D,0xEB,0x94,0xB8,
2645 0xE8,0x47,0x92,0x52,0x93,0x6A,0x1B,0x7E,0x1A,0x61,0xB3,0x1B,
2646 0xF0,0xD6,0x72,0x9B,0xF1,0xB0,0xAF,0xBF,0x3E,0x65,0xEF,0x23,
2647 0x1D,0x6F,0xFF,0x70,0xCD,0x8A,0x4C,0x8A,0xA0,0x72,0x9D,0xBE,
2648 0xD4,0xBB,0x24,0x47,0x4A,0x68,0xB5,0xF5,0xC6,0xD5,0x7A,0xCD,
2649 0xCA,0x06,0x41,0x07,0xAD,0xC2,0x1E,0xE6,0x54,0xA7,0xAD,0x03,
2650 0xD9,0x12,0xC1,0x9C,0x13,0xB1,0xC9,0x0A,0x43,0x8E,0x1E,0x08,
2651 0xCE,0x50,0x82,0x73,0x5F,0xA7,0x55,0x1D,0xD9,0x59,0xAC,0xB5,
2652 0xEA,0x02,0x7F,0x6C,0x5B,0x74,0x96,0x98,0x67,0x24,0xA3,0x0F,
2653 0x15,0xFC,0xA9,0x7D,0x3E,0x67,0xD1,0x70,0xF8,0x97,0xF3,0x67,
2654 0xC5,0x8C,0x88,0x44,0x08,0x02,0xC7,0x2B,
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002655 };
Remi Gacogned3a341a2015-05-29 16:26:17 +02002656 static unsigned char dh4096_g[]={
2657 0x02,
2658 };
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002659
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002660 BIGNUM *p;
2661 BIGNUM *g;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002662 DH *dh = DH_new();
2663 if (dh) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002664 p = BN_bin2bn(dh4096_p, sizeof dh4096_p, NULL);
2665 g = BN_bin2bn(dh4096_g, sizeof dh4096_g, NULL);
Remi Gacogned3a341a2015-05-29 16:26:17 +02002666
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002667 if (!p || !g) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002668 DH_free(dh);
2669 dh = NULL;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002670 } else {
2671 DH_set0_pqg(dh, p, NULL, g);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002672 }
2673 }
2674 return dh;
2675}
2676
2677/* Returns Diffie-Hellman parameters matching the private key length
Willy Tarreauef934602016-12-22 23:12:01 +01002678 but not exceeding global_ssl.default_dh_param */
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002679static DH *ssl_get_tmp_dh(SSL *ssl, int export, int keylen)
2680{
2681 DH *dh = NULL;
2682 EVP_PKEY *pkey = SSL_get_privatekey(ssl);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002683 int type;
2684
2685 type = pkey ? EVP_PKEY_base_id(pkey) : EVP_PKEY_NONE;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002686
2687 /* The keylen supplied by OpenSSL can only be 512 or 1024.
2688 See ssl3_send_server_key_exchange() in ssl/s3_srvr.c
2689 */
2690 if (type == EVP_PKEY_RSA || type == EVP_PKEY_DSA) {
2691 keylen = EVP_PKEY_bits(pkey);
2692 }
2693
Willy Tarreauef934602016-12-22 23:12:01 +01002694 if (keylen > global_ssl.default_dh_param) {
2695 keylen = global_ssl.default_dh_param;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002696 }
2697
Remi Gacogned3a341a2015-05-29 16:26:17 +02002698 if (keylen >= 4096) {
Remi Gacogne8de54152014-07-15 11:36:40 +02002699 dh = local_dh_4096;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002700 }
2701 else if (keylen >= 2048) {
Remi Gacogne8de54152014-07-15 11:36:40 +02002702 dh = local_dh_2048;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002703 }
2704 else {
Remi Gacogne8de54152014-07-15 11:36:40 +02002705 dh = local_dh_1024;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002706 }
2707
2708 return dh;
2709}
2710
Remi Gacogne47783ef2015-05-29 15:53:22 +02002711static DH * ssl_sock_get_dh_from_file(const char *filename)
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002712{
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002713 DH *dh = NULL;
Remi Gacogne47783ef2015-05-29 15:53:22 +02002714 BIO *in = BIO_new(BIO_s_file());
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002715
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002716 if (in == NULL)
2717 goto end;
2718
Remi Gacogne47783ef2015-05-29 15:53:22 +02002719 if (BIO_read_filename(in, filename) <= 0)
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002720 goto end;
2721
Remi Gacogne47783ef2015-05-29 15:53:22 +02002722 dh = PEM_read_bio_DHparams(in, NULL, NULL, NULL);
2723
2724end:
2725 if (in)
2726 BIO_free(in);
2727
Emeric Brune1b4ed42018-08-16 15:14:12 +02002728 ERR_clear_error();
2729
Remi Gacogne47783ef2015-05-29 15:53:22 +02002730 return dh;
2731}
2732
2733int ssl_sock_load_global_dh_param_from_file(const char *filename)
2734{
2735 global_dh = ssl_sock_get_dh_from_file(filename);
2736
2737 if (global_dh) {
2738 return 0;
2739 }
2740
2741 return -1;
2742}
2743
Emeric Bruncfc1afe2019-10-17 13:27:40 +02002744/* Loads Diffie-Hellman parameter from a ckchs to an SSL_CTX.
2745 * If there is no DH paramater availaible in the ckchs, the global
2746 * DH parameter is loaded into the SSL_CTX and if there is no
2747 * DH parameter available in ckchs nor in global, the default
2748 * DH parameters are applied on the SSL_CTX.
2749 * Returns a bitfield containing the flags:
2750 * ERR_FATAL in any fatal error case
2751 * ERR_ALERT if a reason of the error is availabine in err
2752 * ERR_WARN if a warning is available into err
2753 * The value 0 means there is no error nor warning and
2754 * the operation succeed.
2755 */
2756static int ssl_sock_load_dh_params(SSL_CTX *ctx, const char *file, char **err)
2757 {
2758 int ret = 0;
Remi Gacogne47783ef2015-05-29 15:53:22 +02002759 DH *dh = ssl_sock_get_dh_from_file(file);
2760
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002761 if (dh) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002762 SSL_CTX_set_tmp_dh(ctx, dh);
Remi Gacogne4f902b82015-05-28 16:23:00 +02002763
2764 if (ssl_dh_ptr_index >= 0) {
2765 /* store a pointer to the DH params to avoid complaining about
2766 ssl-default-dh-param not being set for this SSL_CTX */
2767 SSL_CTX_set_ex_data(ctx, ssl_dh_ptr_index, dh);
2768 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002769 }
Remi Gacogne47783ef2015-05-29 15:53:22 +02002770 else if (global_dh) {
2771 SSL_CTX_set_tmp_dh(ctx, global_dh);
Remi Gacogne47783ef2015-05-29 15:53:22 +02002772 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002773 else {
Emeric Brun41fdb3c2013-04-26 11:05:44 +02002774 /* Clear openssl global errors stack */
2775 ERR_clear_error();
2776
Willy Tarreauef934602016-12-22 23:12:01 +01002777 if (global_ssl.default_dh_param <= 1024) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002778 /* we are limited to DH parameter of 1024 bits anyway */
Remi Gacognec7e12632016-07-02 16:26:10 +02002779 if (local_dh_1024 == NULL)
2780 local_dh_1024 = ssl_get_dh_1024();
2781
Emeric Bruncfc1afe2019-10-17 13:27:40 +02002782 if (local_dh_1024 == NULL) {
2783 memprintf(err, "%sunable to load default 1024 bits DH parameter for certificate '%s'.\n",
2784 err && *err ? *err : "", file);
2785 ret |= ERR_ALERT | ERR_FATAL;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002786 goto end;
Emeric Bruncfc1afe2019-10-17 13:27:40 +02002787 }
Willy Tarreau6e774b42014-04-25 21:35:23 +02002788
Remi Gacogne8de54152014-07-15 11:36:40 +02002789 SSL_CTX_set_tmp_dh(ctx, local_dh_1024);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002790 }
2791 else {
2792 SSL_CTX_set_tmp_dh_callback(ctx, ssl_get_tmp_dh);
2793 }
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002794 }
Emeric Brun644cde02012-12-14 11:21:13 +01002795
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002796end:
2797 if (dh)
2798 DH_free(dh);
2799
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002800 return ret;
2801}
2802#endif
2803
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002804static 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 +02002805 struct pkey_info kinfo, char *name, int order)
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002806{
2807 struct sni_ctx *sc;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002808 int wild = 0, neg = 0;
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002809 struct ebmb_node *node;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002810
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002811 if (*name == '!') {
2812 neg = 1;
2813 name++;
2814 }
2815 if (*name == '*') {
2816 wild = 1;
2817 name++;
2818 }
2819 /* !* filter is a nop */
2820 if (neg && wild)
2821 return order;
2822 if (*name) {
2823 int j, len;
2824 len = strlen(name);
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002825 for (j = 0; j < len && j < trash.size; j++)
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002826 trash.area[j] = tolower(name[j]);
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002827 if (j >= trash.size)
William Lallemand24e292c2019-10-03 23:46:33 +02002828 return -1;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002829 trash.area[j] = 0;
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002830
2831 /* Check for duplicates. */
2832 if (wild)
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002833 node = ebst_lookup(&s->sni_w_ctx, trash.area);
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002834 else
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002835 node = ebst_lookup(&s->sni_ctx, trash.area);
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002836 for (; node; node = ebmb_next_dup(node)) {
2837 sc = ebmb_entry(node, struct sni_ctx, name);
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002838 if (sc->ctx == ctx && sc->conf == conf && sc->neg == neg)
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002839 return order;
2840 }
2841
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002842 sc = malloc(sizeof(struct sni_ctx) + len + 1);
Thierry FOURNIER / OZON.IO7a3bd3b2016-10-06 10:35:29 +02002843 if (!sc)
William Lallemand24e292c2019-10-03 23:46:33 +02002844 return -1;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002845 memcpy(sc->name.key, trash.area, len + 1);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002846 sc->ctx = ctx;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01002847 sc->conf = conf;
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002848 sc->kinfo = kinfo;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002849 sc->order = order++;
2850 sc->neg = neg;
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01002851 if (kinfo.sig != TLSEXT_signature_anonymous)
2852 SSL_CTX_set_ex_data(ctx, ssl_pkey_info_index, &sc->kinfo);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002853 if (wild)
2854 ebst_insert(&s->sni_w_ctx, &sc->name);
2855 else
2856 ebst_insert(&s->sni_ctx, &sc->name);
2857 }
2858 return order;
2859}
2860
yanbzhu488a4d22015-12-01 15:16:07 -05002861
2862/* The following code is used for loading multiple crt files into
2863 * SSL_CTX's based on CN/SAN
2864 */
Willy Tarreau5db847a2019-05-09 14:13:35 +02002865#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
yanbzhu488a4d22015-12-01 15:16:07 -05002866/* This is used to preload the certifcate, private key
2867 * and Cert Chain of a file passed in via the crt
2868 * argument
2869 *
2870 * This way, we do not have to read the file multiple times
2871 */
2872struct cert_key_and_chain {
2873 X509 *cert;
2874 EVP_PKEY *key;
2875 unsigned int num_chain_certs;
2876 /* This is an array of X509 pointers */
2877 X509 **chain_certs;
2878};
2879
yanbzhu08ce6ab2015-12-02 13:01:29 -05002880#define SSL_SOCK_POSSIBLE_KT_COMBOS (1<<(SSL_SOCK_NUM_KEYTYPES))
2881
2882struct key_combo_ctx {
2883 SSL_CTX *ctx;
2884 int order;
2885};
2886
2887/* Map used for processing multiple keypairs for a single purpose
2888 *
2889 * This maps CN/SNI name to certificate type
2890 */
2891struct sni_keytype {
2892 int keytypes; /* BITMASK for keytypes */
2893 struct ebmb_node name; /* node holding the servername value */
2894};
2895
2896
yanbzhu488a4d22015-12-01 15:16:07 -05002897/* Frees the contents of a cert_key_and_chain
2898 */
2899static void ssl_sock_free_cert_key_and_chain_contents(struct cert_key_and_chain *ckch)
2900{
2901 int i;
2902
2903 if (!ckch)
2904 return;
2905
2906 /* Free the certificate and set pointer to NULL */
2907 if (ckch->cert)
2908 X509_free(ckch->cert);
2909 ckch->cert = NULL;
2910
2911 /* Free the key and set pointer to NULL */
2912 if (ckch->key)
2913 EVP_PKEY_free(ckch->key);
2914 ckch->key = NULL;
2915
2916 /* Free each certificate in the chain */
2917 for (i = 0; i < ckch->num_chain_certs; i++) {
2918 if (ckch->chain_certs[i])
2919 X509_free(ckch->chain_certs[i]);
2920 }
2921
2922 /* Free the chain obj itself and set to NULL */
2923 if (ckch->num_chain_certs > 0) {
2924 free(ckch->chain_certs);
2925 ckch->num_chain_certs = 0;
2926 ckch->chain_certs = NULL;
2927 }
2928
2929}
2930
2931/* checks if a key and cert exists in the ckch
2932 */
2933static int ssl_sock_is_ckch_valid(struct cert_key_and_chain *ckch)
2934{
2935 return (ckch->cert != NULL && ckch->key != NULL);
2936}
2937
2938
2939/* Loads the contents of a crt file (path) into a cert_key_and_chain
2940 * This allows us to carry the contents of the file without having to
2941 * read the file multiple times.
2942 *
2943 * returns:
2944 * 0 on Success
2945 * 1 on SSL Failure
2946 * 2 on file not found
2947 */
2948static int ssl_sock_load_crt_file_into_ckch(const char *path, struct cert_key_and_chain *ckch, char **err)
2949{
2950
2951 BIO *in;
2952 X509 *ca = NULL;
2953 int ret = 1;
2954
2955 ssl_sock_free_cert_key_and_chain_contents(ckch);
2956
2957 in = BIO_new(BIO_s_file());
2958 if (in == NULL)
2959 goto end;
2960
2961 if (BIO_read_filename(in, path) <= 0)
2962 goto end;
2963
yanbzhu488a4d22015-12-01 15:16:07 -05002964 /* Read Private Key */
2965 ckch->key = PEM_read_bio_PrivateKey(in, NULL, NULL, NULL);
2966 if (ckch->key == NULL) {
2967 memprintf(err, "%sunable to load private key from file '%s'.\n",
2968 err && *err ? *err : "", path);
2969 goto end;
2970 }
2971
Willy Tarreaubb137a82016-04-06 19:02:38 +02002972 /* Seek back to beginning of file */
Thierry FOURNIER / OZON.IOd44ea3f2016-10-14 00:49:21 +02002973 if (BIO_reset(in) == -1) {
2974 memprintf(err, "%san error occurred while reading the file '%s'.\n",
2975 err && *err ? *err : "", path);
2976 goto end;
2977 }
Willy Tarreaubb137a82016-04-06 19:02:38 +02002978
2979 /* Read Certificate */
2980 ckch->cert = PEM_read_bio_X509_AUX(in, NULL, NULL, NULL);
2981 if (ckch->cert == NULL) {
2982 memprintf(err, "%sunable to load certificate from file '%s'.\n",
2983 err && *err ? *err : "", path);
2984 goto end;
2985 }
2986
yanbzhu488a4d22015-12-01 15:16:07 -05002987 /* Read Certificate Chain */
2988 while ((ca = PEM_read_bio_X509(in, NULL, NULL, NULL))) {
2989 /* Grow the chain certs */
2990 ckch->num_chain_certs++;
2991 ckch->chain_certs = realloc(ckch->chain_certs, (ckch->num_chain_certs * sizeof(X509 *)));
2992
2993 /* use - 1 here since we just incremented it above */
2994 ckch->chain_certs[ckch->num_chain_certs - 1] = ca;
2995 }
2996 ret = ERR_get_error();
2997 if (ret && (ERR_GET_LIB(ret) != ERR_LIB_PEM && ERR_GET_REASON(ret) != PEM_R_NO_START_LINE)) {
2998 memprintf(err, "%sunable to load certificate chain from file '%s'.\n",
2999 err && *err ? *err : "", path);
3000 ret = 1;
3001 goto end;
3002 }
3003
3004 ret = 0;
3005
3006end:
3007
3008 ERR_clear_error();
3009 if (in)
3010 BIO_free(in);
3011
3012 /* Something went wrong in one of the reads */
3013 if (ret != 0)
3014 ssl_sock_free_cert_key_and_chain_contents(ckch);
3015
3016 return ret;
3017}
3018
3019/* Loads the info in ckch into ctx
Emeric Brun394701d2019-10-17 13:25:14 +02003020 * Returns a bitfield containing the flags:
3021 * ERR_FATAL in any fatal error case
3022 * ERR_ALERT if the reason of the error is available in err
3023 * ERR_WARN if a warning is available into err
3024 * The value 0 means there is no error nor warning and
3025 * the operation succeed.
yanbzhu488a4d22015-12-01 15:16:07 -05003026 */
3027static int ssl_sock_put_ckch_into_ctx(const char *path, const struct cert_key_and_chain *ckch, SSL_CTX *ctx, char **err)
3028{
3029 int i = 0;
Emeric Brun394701d2019-10-17 13:25:14 +02003030 int errcode = 0;
yanbzhu488a4d22015-12-01 15:16:07 -05003031
3032 if (SSL_CTX_use_PrivateKey(ctx, ckch->key) <= 0) {
3033 memprintf(err, "%sunable to load SSL private key into SSL Context '%s'.\n",
3034 err && *err ? *err : "", path);
Emeric Brun394701d2019-10-17 13:25:14 +02003035 errcode |= ERR_ALERT | ERR_FATAL;
3036 return errcode;
yanbzhu488a4d22015-12-01 15:16:07 -05003037 }
3038
3039 if (!SSL_CTX_use_certificate(ctx, ckch->cert)) {
3040 memprintf(err, "%sunable to load SSL certificate into SSL Context '%s'.\n",
3041 err && *err ? *err : "", path);
Emeric Brun394701d2019-10-17 13:25:14 +02003042 errcode |= ERR_ALERT | ERR_FATAL;
3043 goto end;
yanbzhu488a4d22015-12-01 15:16:07 -05003044 }
3045
yanbzhu488a4d22015-12-01 15:16:07 -05003046 /* Load all certs in the ckch into the ctx_chain for the ssl_ctx */
3047 for (i = 0; i < ckch->num_chain_certs; i++) {
3048 if (!SSL_CTX_add1_chain_cert(ctx, ckch->chain_certs[i])) {
yanbzhu08ce6ab2015-12-02 13:01:29 -05003049 memprintf(err, "%sunable to load chain certificate #%d into SSL Context '%s'. Make sure you are linking against Openssl >= 1.0.2.\n",
3050 err && *err ? *err : "", (i+1), path);
Emeric Brun394701d2019-10-17 13:25:14 +02003051 errcode |= ERR_ALERT | ERR_FATAL;
3052 goto end;
yanbzhu488a4d22015-12-01 15:16:07 -05003053 }
3054 }
3055
3056 if (SSL_CTX_check_private_key(ctx) <= 0) {
3057 memprintf(err, "%sinconsistencies between private key and certificate loaded from PEM file '%s'.\n",
3058 err && *err ? *err : "", path);
Emeric Brun394701d2019-10-17 13:25:14 +02003059 errcode |= ERR_ALERT | ERR_FATAL;
yanbzhu488a4d22015-12-01 15:16:07 -05003060 }
3061
Emeric Brun394701d2019-10-17 13:25:14 +02003062 end:
3063 return errcode;
yanbzhu488a4d22015-12-01 15:16:07 -05003064}
3065
yanbzhu08ce6ab2015-12-02 13:01:29 -05003066
William Lallemand4801c702019-10-04 17:36:55 +02003067static int ssl_sock_populate_sni_keytypes_hplr(const char *str, struct eb_root *sni_keytypes, int key_index)
yanbzhu08ce6ab2015-12-02 13:01:29 -05003068{
3069 struct sni_keytype *s_kt = NULL;
3070 struct ebmb_node *node;
3071 int i;
3072
3073 for (i = 0; i < trash.size; i++) {
3074 if (!str[i])
3075 break;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02003076 trash.area[i] = tolower(str[i]);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003077 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +02003078 trash.area[i] = 0;
3079 node = ebst_lookup(sni_keytypes, trash.area);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003080 if (!node) {
3081 /* CN not found in tree */
3082 s_kt = malloc(sizeof(struct sni_keytype) + i + 1);
3083 /* Using memcpy here instead of strncpy.
3084 * strncpy will cause sig_abrt errors under certain versions of gcc with -O2
3085 * See: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=60792
3086 */
William Lallemand4801c702019-10-04 17:36:55 +02003087 if (!s_kt)
3088 return -1;
3089
Willy Tarreau843b7cb2018-07-13 10:54:26 +02003090 memcpy(s_kt->name.key, trash.area, i+1);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003091 s_kt->keytypes = 0;
3092 ebst_insert(sni_keytypes, &s_kt->name);
3093 } else {
3094 /* CN found in tree */
3095 s_kt = container_of(node, struct sni_keytype, name);
3096 }
3097
3098 /* Mark that this CN has the keytype of key_index via keytypes mask */
3099 s_kt->keytypes |= 1<<key_index;
3100
William Lallemand4801c702019-10-04 17:36:55 +02003101 return 0;
3102
yanbzhu08ce6ab2015-12-02 13:01:29 -05003103}
3104
3105
3106/* Given a path that does not exist, try to check for path.rsa, path.dsa and path.ecdsa files.
3107 * If any are found, group these files into a set of SSL_CTX*
3108 * based on shared and unique CN and SAN entries. Add these SSL_CTX* to the SNI tree.
3109 *
Joseph Herlant017b3da2018-11-15 09:07:59 -08003110 * This will allow the user to explicitly group multiple cert/keys for a single purpose
yanbzhu08ce6ab2015-12-02 13:01:29 -05003111 *
Willy Tarreaub131c872019-10-16 16:42:19 +02003112 * Returns a set of ERR_* flags possibly with an error in <err>.
3113 *
yanbzhu08ce6ab2015-12-02 13:01:29 -05003114 */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003115static int ssl_sock_load_multi_cert(const char *path, struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
3116 char **sni_filter, int fcount, char **err)
yanbzhu08ce6ab2015-12-02 13:01:29 -05003117{
3118 char fp[MAXPATHLEN+1] = {0};
3119 int n = 0;
3120 int i = 0;
3121 struct cert_key_and_chain certs_and_keys[SSL_SOCK_NUM_KEYTYPES] = { {0} };
3122 struct eb_root sni_keytypes_map = { {0} };
3123 struct ebmb_node *node;
3124 struct ebmb_node *next;
3125 /* Array of SSL_CTX pointers corresponding to each possible combo
3126 * of keytypes
3127 */
3128 struct key_combo_ctx key_combos[SSL_SOCK_POSSIBLE_KT_COMBOS] = { {0} };
Willy Tarreaub131c872019-10-16 16:42:19 +02003129 int errcode = 0;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003130 X509_NAME *xname = NULL;
3131 char *str = NULL;
3132#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
3133 STACK_OF(GENERAL_NAME) *names = NULL;
3134#endif
3135
3136 /* Load all possible certs and keys */
3137 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
3138 struct stat buf;
3139
3140 snprintf(fp, sizeof(fp), "%s.%s", path, SSL_SOCK_KEYTYPE_NAMES[n]);
3141 if (stat(fp, &buf) == 0) {
3142 if (ssl_sock_load_crt_file_into_ckch(fp, &certs_and_keys[n], err) == 1) {
Willy Tarreaub131c872019-10-16 16:42:19 +02003143 errcode |= ERR_ALERT | ERR_FATAL;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003144 goto end;
3145 }
3146 }
3147 }
3148
3149 /* Process each ckch and update keytypes for each CN/SAN
3150 * for example, if CN/SAN www.a.com is associated with
3151 * certs with keytype 0 and 2, then at the end of the loop,
3152 * www.a.com will have:
3153 * keyindex = 0 | 1 | 4 = 5
3154 */
3155 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
William Lallemand4801c702019-10-04 17:36:55 +02003156 int ret;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003157
3158 if (!ssl_sock_is_ckch_valid(&certs_and_keys[n]))
3159 continue;
3160
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003161 if (fcount) {
William Lallemand4801c702019-10-04 17:36:55 +02003162 for (i = 0; i < fcount; i++) {
3163 ret = ssl_sock_populate_sni_keytypes_hplr(sni_filter[i], &sni_keytypes_map, n);
3164 if (ret < 0) {
3165 memprintf(err, "%sunable to allocate SSL context.\n",
3166 err && *err ? *err : "");
Willy Tarreaub131c872019-10-16 16:42:19 +02003167 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemand4801c702019-10-04 17:36:55 +02003168 goto end;
3169 }
3170 }
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003171 } else {
3172 /* A lot of the following code is OpenSSL boilerplate for processing CN's and SAN's,
3173 * so the line that contains logic is marked via comments
3174 */
3175 xname = X509_get_subject_name(certs_and_keys[n].cert);
3176 i = -1;
3177 while ((i = X509_NAME_get_index_by_NID(xname, NID_commonName, i)) != -1) {
3178 X509_NAME_ENTRY *entry = X509_NAME_get_entry(xname, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003179 ASN1_STRING *value;
3180 value = X509_NAME_ENTRY_get_data(entry);
3181 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003182 /* Important line is here */
William Lallemand4801c702019-10-04 17:36:55 +02003183 ret = ssl_sock_populate_sni_keytypes_hplr(str, &sni_keytypes_map, n);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003184
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003185 OPENSSL_free(str);
3186 str = NULL;
William Lallemand4801c702019-10-04 17:36:55 +02003187 if (ret < 0) {
3188 memprintf(err, "%sunable to allocate SSL context.\n",
3189 err && *err ? *err : "");
Willy Tarreaub131c872019-10-16 16:42:19 +02003190 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemand4801c702019-10-04 17:36:55 +02003191 goto end;
3192 }
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003193 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003194 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003195
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003196 /* Do the above logic for each SAN */
yanbzhu08ce6ab2015-12-02 13:01:29 -05003197#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003198 names = X509_get_ext_d2i(certs_and_keys[n].cert, NID_subject_alt_name, NULL, NULL);
3199 if (names) {
3200 for (i = 0; i < sk_GENERAL_NAME_num(names); i++) {
3201 GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003202
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003203 if (name->type == GEN_DNS) {
3204 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
3205 /* Important line is here */
William Lallemand4801c702019-10-04 17:36:55 +02003206 ret = ssl_sock_populate_sni_keytypes_hplr(str, &sni_keytypes_map, n);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003207
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003208 OPENSSL_free(str);
3209 str = NULL;
William Lallemand4801c702019-10-04 17:36:55 +02003210 if (ret < 0) {
3211 memprintf(err, "%sunable to allocate SSL context.\n",
3212 err && *err ? *err : "");
Willy Tarreaub131c872019-10-16 16:42:19 +02003213 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemand4801c702019-10-04 17:36:55 +02003214 goto end;
3215 }
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003216 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003217 }
3218 }
3219 }
3220 }
3221#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
3222 }
3223
3224 /* If no files found, return error */
3225 if (eb_is_empty(&sni_keytypes_map)) {
3226 memprintf(err, "%sunable to load SSL certificate file '%s' file does not exist.\n",
3227 err && *err ? *err : "", path);
Willy Tarreaub131c872019-10-16 16:42:19 +02003228 errcode |= ERR_ALERT | ERR_FATAL;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003229 goto end;
3230 }
3231
3232 /* We now have a map of CN/SAN to keytypes that are loaded in
3233 * Iterate through the map to create the SSL_CTX's (if needed)
3234 * and add each CTX to the SNI tree
3235 *
3236 * Some math here:
Joseph Herlant017b3da2018-11-15 09:07:59 -08003237 * There are 2^n - 1 possible combinations, each unique
yanbzhu08ce6ab2015-12-02 13:01:29 -05003238 * combination is denoted by the key in the map. Each key
3239 * has a value between 1 and 2^n - 1. Conveniently, the array
3240 * of SSL_CTX* is sized 2^n. So, we can simply use the i'th
3241 * entry in the array to correspond to the unique combo (key)
3242 * associated with i. This unique key combo (i) will be associated
3243 * with combos[i-1]
3244 */
3245
3246 node = ebmb_first(&sni_keytypes_map);
3247 while (node) {
3248 SSL_CTX *cur_ctx;
Bertrand Jacquin33423092016-11-13 16:37:13 +00003249 char cur_file[MAXPATHLEN+1];
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003250 const struct pkey_info kinfo = { .sig = TLSEXT_signature_anonymous, .bits = 0 };
yanbzhu08ce6ab2015-12-02 13:01:29 -05003251
3252 str = (char *)container_of(node, struct sni_keytype, name)->name.key;
3253 i = container_of(node, struct sni_keytype, name)->keytypes;
3254 cur_ctx = key_combos[i-1].ctx;
3255
3256 if (cur_ctx == NULL) {
3257 /* need to create SSL_CTX */
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003258 cur_ctx = SSL_CTX_new(SSLv23_server_method());
yanbzhu08ce6ab2015-12-02 13:01:29 -05003259 if (cur_ctx == NULL) {
3260 memprintf(err, "%sunable to allocate SSL context.\n",
3261 err && *err ? *err : "");
Willy Tarreaub131c872019-10-16 16:42:19 +02003262 errcode |= ERR_ALERT | ERR_FATAL;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003263 goto end;
3264 }
3265
yanbzhube2774d2015-12-10 15:07:30 -05003266 /* Load all required certs/keys/chains/OCSPs info into SSL_CTX */
yanbzhu08ce6ab2015-12-02 13:01:29 -05003267 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
3268 if (i & (1<<n)) {
3269 /* Key combo contains ckch[n] */
Bertrand Jacquin33423092016-11-13 16:37:13 +00003270 snprintf(cur_file, MAXPATHLEN+1, "%s.%s", path, SSL_SOCK_KEYTYPE_NAMES[n]);
Emeric Brun394701d2019-10-17 13:25:14 +02003271 errcode |= ssl_sock_put_ckch_into_ctx(cur_file, &certs_and_keys[n], cur_ctx, err);
3272 if (errcode & ERR_CODE) {
yanbzhu08ce6ab2015-12-02 13:01:29 -05003273 SSL_CTX_free(cur_ctx);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003274 goto end;
3275 }
yanbzhube2774d2015-12-10 15:07:30 -05003276
3277#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
3278 /* Load OCSP Info into context */
Bertrand Jacquin33423092016-11-13 16:37:13 +00003279 if (ssl_sock_load_ocsp(cur_ctx, cur_file) < 0) {
yanbzhube2774d2015-12-10 15:07:30 -05003280 if (err)
3281 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 +00003282 *err ? *err : "", cur_file);
yanbzhube2774d2015-12-10 15:07:30 -05003283 SSL_CTX_free(cur_ctx);
Willy Tarreaub131c872019-10-16 16:42:19 +02003284 errcode |= ERR_ALERT | ERR_FATAL;
yanbzhube2774d2015-12-10 15:07:30 -05003285 goto end;
3286 }
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02003287#elif (defined OPENSSL_IS_BORINGSSL)
3288 ssl_sock_set_ocsp_response_from_file(cur_ctx, cur_file);
yanbzhube2774d2015-12-10 15:07:30 -05003289#endif
yanbzhu08ce6ab2015-12-02 13:01:29 -05003290 }
3291 }
3292
3293 /* Load DH params into the ctx to support DHE keys */
3294#ifndef OPENSSL_NO_DH
3295 if (ssl_dh_ptr_index >= 0)
3296 SSL_CTX_set_ex_data(cur_ctx, ssl_dh_ptr_index, NULL);
3297
Emeric Bruncfc1afe2019-10-17 13:27:40 +02003298 errcode |= ssl_sock_load_dh_params(cur_ctx, NULL, err);
3299 if (errcode & ERR_CODE) {
yanbzhu08ce6ab2015-12-02 13:01:29 -05003300 if (err)
3301 memprintf(err, "%sunable to load DH parameters from file '%s'.\n",
3302 *err ? *err : "", path);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003303 goto end;
3304 }
3305#endif
3306
3307 /* Update key_combos */
3308 key_combos[i-1].ctx = cur_ctx;
3309 }
3310
3311 /* Update SNI Tree */
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003312 key_combos[i-1].order = ssl_sock_add_cert_sni(cur_ctx, bind_conf, ssl_conf,
William Lallemand24e292c2019-10-03 23:46:33 +02003313 kinfo, str, key_combos[i-1].order);
3314 if (key_combos[i-1].order < 0) {
3315 memprintf(err, "%sunable to create a sni context.\n", err && *err ? *err : "");
Willy Tarreaub131c872019-10-16 16:42:19 +02003316 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemand24e292c2019-10-03 23:46:33 +02003317 goto end;
3318 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003319 node = ebmb_next(node);
3320 }
3321
3322
3323 /* Mark a default context if none exists, using the ctx that has the most shared keys */
3324 if (!bind_conf->default_ctx) {
3325 for (i = SSL_SOCK_POSSIBLE_KT_COMBOS - 1; i >= 0; i--) {
3326 if (key_combos[i].ctx) {
3327 bind_conf->default_ctx = key_combos[i].ctx;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003328 bind_conf->default_ssl_conf = ssl_conf;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003329 break;
3330 }
3331 }
3332 }
3333
3334end:
3335
3336 if (names)
3337 sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
3338
3339 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++)
3340 ssl_sock_free_cert_key_and_chain_contents(&certs_and_keys[n]);
3341
3342 node = ebmb_first(&sni_keytypes_map);
3343 while (node) {
3344 next = ebmb_next(node);
3345 ebmb_delete(node);
William Lallemande92c0302019-10-04 17:24:39 +02003346 free(ebmb_entry(node, struct sni_keytype, name));
yanbzhu08ce6ab2015-12-02 13:01:29 -05003347 node = next;
3348 }
3349
Willy Tarreaub131c872019-10-16 16:42:19 +02003350 return errcode;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003351}
3352#else
3353/* This is a dummy, that just logs an error and returns error */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003354static int ssl_sock_load_multi_cert(const char *path, struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
3355 char **sni_filter, int fcount, char **err)
yanbzhu08ce6ab2015-12-02 13:01:29 -05003356{
3357 memprintf(err, "%sunable to stat SSL certificate from file '%s' : %s.\n",
3358 err && *err ? *err : "", path, strerror(errno));
3359 return 1;
3360}
3361
Willy Tarreau9a1ab082019-05-09 13:26:41 +02003362#endif /* #if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL: Support for loading multiple certs into a single SSL_CTX */
yanbzhu488a4d22015-12-01 15:16:07 -05003363
Emeric Brunfc0421f2012-09-07 17:30:07 +02003364/* Loads a certificate key and CA chain from a file. Returns 0 on error, -1 if
3365 * an early error happens and the caller must call SSL_CTX_free() by itelf.
3366 */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003367static int ssl_sock_load_cert_chain_file(SSL_CTX *ctx, const char *file, struct bind_conf *s,
3368 struct ssl_bind_conf *ssl_conf, char **sni_filter, int fcount)
Emeric Brunfc0421f2012-09-07 17:30:07 +02003369{
3370 BIO *in;
3371 X509 *x = NULL, *ca;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02003372 int i, err;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003373 int ret = -1;
3374 int order = 0;
3375 X509_NAME *xname;
3376 char *str;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003377 pem_password_cb *passwd_cb;
3378 void *passwd_cb_userdata;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003379 EVP_PKEY *pkey;
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003380 struct pkey_info kinfo = { .sig = TLSEXT_signature_anonymous, .bits = 0 };
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003381
Emeric Brunfc0421f2012-09-07 17:30:07 +02003382#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
3383 STACK_OF(GENERAL_NAME) *names;
3384#endif
3385
3386 in = BIO_new(BIO_s_file());
3387 if (in == NULL)
3388 goto end;
3389
3390 if (BIO_read_filename(in, file) <= 0)
3391 goto end;
3392
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003393
3394 passwd_cb = SSL_CTX_get_default_passwd_cb(ctx);
3395 passwd_cb_userdata = SSL_CTX_get_default_passwd_cb_userdata(ctx);
3396
3397 x = PEM_read_bio_X509_AUX(in, NULL, passwd_cb, passwd_cb_userdata);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003398 if (x == NULL)
3399 goto end;
3400
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003401 pkey = X509_get_pubkey(x);
3402 if (pkey) {
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003403 kinfo.bits = EVP_PKEY_bits(pkey);
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003404 switch(EVP_PKEY_base_id(pkey)) {
3405 case EVP_PKEY_RSA:
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003406 kinfo.sig = TLSEXT_signature_rsa;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003407 break;
3408 case EVP_PKEY_EC:
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003409 kinfo.sig = TLSEXT_signature_ecdsa;
3410 break;
3411 case EVP_PKEY_DSA:
3412 kinfo.sig = TLSEXT_signature_dsa;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003413 break;
3414 }
3415 EVP_PKEY_free(pkey);
3416 }
3417
Emeric Brun50bcecc2013-04-22 13:05:23 +02003418 if (fcount) {
William Lallemand24e292c2019-10-03 23:46:33 +02003419 while (fcount--) {
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003420 order = ssl_sock_add_cert_sni(ctx, s, ssl_conf, kinfo, sni_filter[fcount], order);
William Lallemand24e292c2019-10-03 23:46:33 +02003421 if (order < 0)
3422 goto end;
3423 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003424 }
3425 else {
Emeric Brunfc0421f2012-09-07 17:30:07 +02003426#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003427 names = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL);
3428 if (names) {
3429 for (i = 0; i < sk_GENERAL_NAME_num(names); i++) {
3430 GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i);
3431 if (name->type == GEN_DNS) {
3432 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003433 order = ssl_sock_add_cert_sni(ctx, s, ssl_conf, kinfo, str, order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003434 OPENSSL_free(str);
William Lallemand24e292c2019-10-03 23:46:33 +02003435 if (order < 0)
3436 goto end;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003437 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003438 }
3439 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003440 sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003441 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003442#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003443 xname = X509_get_subject_name(x);
3444 i = -1;
3445 while ((i = X509_NAME_get_index_by_NID(xname, NID_commonName, i)) != -1) {
3446 X509_NAME_ENTRY *entry = X509_NAME_get_entry(xname, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003447 ASN1_STRING *value;
3448
3449 value = X509_NAME_ENTRY_get_data(entry);
3450 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003451 order = ssl_sock_add_cert_sni(ctx, s, ssl_conf, kinfo, str, order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003452 OPENSSL_free(str);
William Lallemand24e292c2019-10-03 23:46:33 +02003453 if (order < 0)
3454 goto end;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003455 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003456 }
3457 }
3458
3459 ret = 0; /* the caller must not free the SSL_CTX argument anymore */
3460 if (!SSL_CTX_use_certificate(ctx, x))
3461 goto end;
3462
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003463#ifdef SSL_CTX_clear_extra_chain_certs
3464 SSL_CTX_clear_extra_chain_certs(ctx);
3465#else
Emeric Brunfc0421f2012-09-07 17:30:07 +02003466 if (ctx->extra_certs != NULL) {
3467 sk_X509_pop_free(ctx->extra_certs, X509_free);
3468 ctx->extra_certs = NULL;
3469 }
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003470#endif
Emeric Brunfc0421f2012-09-07 17:30:07 +02003471
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003472 while ((ca = PEM_read_bio_X509(in, NULL, passwd_cb, passwd_cb_userdata))) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02003473 if (!SSL_CTX_add_extra_chain_cert(ctx, ca)) {
3474 X509_free(ca);
3475 goto end;
3476 }
3477 }
3478
3479 err = ERR_get_error();
3480 if (!err || (ERR_GET_LIB(err) == ERR_LIB_PEM && ERR_GET_REASON(err) == PEM_R_NO_START_LINE)) {
3481 /* we successfully reached the last cert in the file */
3482 ret = 1;
3483 }
3484 ERR_clear_error();
3485
3486end:
3487 if (x)
3488 X509_free(x);
3489
3490 if (in)
3491 BIO_free(in);
3492
3493 return ret;
3494}
3495
Willy Tarreaub131c872019-10-16 16:42:19 +02003496/* Returns a set of ERR_* flags possibly with an error in <err>. */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003497static int ssl_sock_load_cert_file(const char *path, struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
3498 char **sni_filter, int fcount, char **err)
Emeric Brunfc0421f2012-09-07 17:30:07 +02003499{
Emeric Bruncfc1afe2019-10-17 13:27:40 +02003500 int errcode = 0;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003501 int ret;
3502 SSL_CTX *ctx;
3503
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003504 ctx = SSL_CTX_new(SSLv23_server_method());
Emeric Brunfc0421f2012-09-07 17:30:07 +02003505 if (!ctx) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02003506 memprintf(err, "%sunable to allocate SSL context for cert '%s'.\n",
3507 err && *err ? *err : "", path);
Willy Tarreaub131c872019-10-16 16:42:19 +02003508 return ERR_ALERT | ERR_FATAL;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003509 }
3510
3511 if (SSL_CTX_use_PrivateKey_file(ctx, path, SSL_FILETYPE_PEM) <= 0) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02003512 memprintf(err, "%sunable to load SSL private key from PEM file '%s'.\n",
3513 err && *err ? *err : "", path);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003514 SSL_CTX_free(ctx);
Willy Tarreaub131c872019-10-16 16:42:19 +02003515 return ERR_ALERT | ERR_FATAL;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003516 }
3517
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003518 ret = ssl_sock_load_cert_chain_file(ctx, path, bind_conf, ssl_conf, sni_filter, fcount);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003519 if (ret <= 0) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02003520 memprintf(err, "%sunable to load SSL certificate from PEM file '%s'.\n",
3521 err && *err ? *err : "", path);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003522 if (ret < 0) /* serious error, must do that ourselves */
3523 SSL_CTX_free(ctx);
Willy Tarreaub131c872019-10-16 16:42:19 +02003524 return ERR_ALERT | ERR_FATAL;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003525 }
Emeric Brun61694ab2012-10-26 13:35:33 +02003526
3527 if (SSL_CTX_check_private_key(ctx) <= 0) {
3528 memprintf(err, "%sinconsistencies between private key and certificate loaded from PEM file '%s'.\n",
3529 err && *err ? *err : "", path);
Willy Tarreaub131c872019-10-16 16:42:19 +02003530 return ERR_ALERT | ERR_FATAL;
Emeric Brun61694ab2012-10-26 13:35:33 +02003531 }
3532
Emeric Brunfc0421f2012-09-07 17:30:07 +02003533 /* we must not free the SSL_CTX anymore below, since it's already in
3534 * the tree, so it will be discovered and cleaned in time.
3535 */
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02003536#ifndef OPENSSL_NO_DH
Remi Gacogne4f902b82015-05-28 16:23:00 +02003537 /* store a NULL pointer to indicate we have not yet loaded
3538 a custom DH param file */
3539 if (ssl_dh_ptr_index >= 0) {
3540 SSL_CTX_set_ex_data(ctx, ssl_dh_ptr_index, NULL);
3541 }
3542
Emeric Bruncfc1afe2019-10-17 13:27:40 +02003543 errcode |= ssl_sock_load_dh_params(ctx, path, err);
3544 if (errcode & ERR_CODE) {
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02003545 if (err)
3546 memprintf(err, "%sunable to load DH parameters from file '%s'.\n",
3547 *err ? *err : "", path);
Emeric Bruncfc1afe2019-10-17 13:27:40 +02003548 return errcode;
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02003549 }
3550#endif
3551
Lukas Tribuse4e30f72014-12-09 16:32:51 +01003552#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
Emeric Brun4147b2e2014-06-16 18:36:30 +02003553 ret = ssl_sock_load_ocsp(ctx, path);
3554 if (ret < 0) {
3555 if (err)
3556 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",
3557 *err ? *err : "", path);
Willy Tarreaub131c872019-10-16 16:42:19 +02003558 return ERR_ALERT | ERR_FATAL;
Emeric Brun4147b2e2014-06-16 18:36:30 +02003559 }
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02003560#elif (defined OPENSSL_IS_BORINGSSL)
3561 ssl_sock_set_ocsp_response_from_file(ctx, path);
Emeric Brun4147b2e2014-06-16 18:36:30 +02003562#endif
3563
Willy Tarreau5db847a2019-05-09 14:13:35 +02003564#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01003565 if (sctl_ex_index >= 0) {
3566 ret = ssl_sock_load_sctl(ctx, path);
3567 if (ret < 0) {
3568 if (err)
3569 memprintf(err, "%s '%s.sctl' is present but cannot be read or parsed'.\n",
3570 *err ? *err : "", path);
Willy Tarreaub131c872019-10-16 16:42:19 +02003571 return ERR_ALERT | ERR_FATAL;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01003572 }
3573 }
3574#endif
3575
Emeric Brunfc0421f2012-09-07 17:30:07 +02003576#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
Willy Tarreau2a65ff02012-09-13 17:54:29 +02003577 if (bind_conf->default_ctx) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02003578 memprintf(err, "%sthis version of openssl cannot load multiple SSL certificates.\n",
3579 err && *err ? *err : "");
Willy Tarreaub131c872019-10-16 16:42:19 +02003580 return ERR_ALERT | ERR_FATAL;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003581 }
3582#endif
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003583 if (!bind_conf->default_ctx) {
Willy Tarreau2a65ff02012-09-13 17:54:29 +02003584 bind_conf->default_ctx = ctx;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003585 bind_conf->default_ssl_conf = ssl_conf;
3586 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003587
Emeric Bruncfc1afe2019-10-17 13:27:40 +02003588 return errcode;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003589}
3590
Willy Tarreaub131c872019-10-16 16:42:19 +02003591
3592/* Returns a set of ERR_* flags possibly with an error in <err>. */
Willy Tarreau03209342016-12-22 17:08:28 +01003593int ssl_sock_load_cert(char *path, struct bind_conf *bind_conf, char **err)
Emeric Brunfc0421f2012-09-07 17:30:07 +02003594{
Cyril Bonté3180f7b2015-01-25 00:16:08 +01003595 struct dirent **de_list;
3596 int i, n;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003597 DIR *dir;
3598 struct stat buf;
Willy Tarreauee2663b2012-12-06 11:36:59 +01003599 char *end;
3600 char fp[MAXPATHLEN+1];
Emeric Brunfc0421f2012-09-07 17:30:07 +02003601 int cfgerr = 0;
Willy Tarreau9a1ab082019-05-09 13:26:41 +02003602#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
yanbzhu63ea8462015-12-09 13:35:14 -05003603 int is_bundle;
3604 int j;
3605#endif
Emeric Brunfc0421f2012-09-07 17:30:07 +02003606
yanbzhu08ce6ab2015-12-02 13:01:29 -05003607 if (stat(path, &buf) == 0) {
3608 dir = opendir(path);
3609 if (!dir)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003610 return ssl_sock_load_cert_file(path, bind_conf, NULL, NULL, 0, err);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003611
yanbzhu08ce6ab2015-12-02 13:01:29 -05003612 /* strip trailing slashes, including first one */
3613 for (end = path + strlen(path) - 1; end >= path && *end == '/'; end--)
3614 *end = 0;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003615
yanbzhu08ce6ab2015-12-02 13:01:29 -05003616 n = scandir(path, &de_list, 0, alphasort);
3617 if (n < 0) {
3618 memprintf(err, "%sunable to scan directory '%s' : %s.\n",
3619 err && *err ? *err : "", path, strerror(errno));
Willy Tarreaub131c872019-10-16 16:42:19 +02003620 cfgerr |= ERR_ALERT | ERR_FATAL;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003621 }
3622 else {
3623 for (i = 0; i < n; i++) {
3624 struct dirent *de = de_list[i];
Emeric Brun2aab7222014-06-18 18:15:09 +02003625
yanbzhu08ce6ab2015-12-02 13:01:29 -05003626 end = strrchr(de->d_name, '.');
3627 if (end && (!strcmp(end, ".issuer") || !strcmp(end, ".ocsp") || !strcmp(end, ".sctl")))
3628 goto ignore_entry;
Cyril Bonté3180f7b2015-01-25 00:16:08 +01003629
yanbzhu08ce6ab2015-12-02 13:01:29 -05003630 snprintf(fp, sizeof(fp), "%s/%s", path, de->d_name);
3631 if (stat(fp, &buf) != 0) {
3632 memprintf(err, "%sunable to stat SSL certificate from file '%s' : %s.\n",
3633 err && *err ? *err : "", fp, strerror(errno));
Willy Tarreaub131c872019-10-16 16:42:19 +02003634 cfgerr |= ERR_ALERT | ERR_FATAL;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003635 goto ignore_entry;
3636 }
3637 if (!S_ISREG(buf.st_mode))
3638 goto ignore_entry;
yanbzhu63ea8462015-12-09 13:35:14 -05003639
Willy Tarreau9a1ab082019-05-09 13:26:41 +02003640#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
yanbzhu63ea8462015-12-09 13:35:14 -05003641 is_bundle = 0;
3642 /* Check if current entry in directory is part of a multi-cert bundle */
3643
3644 if (end) {
3645 for (j = 0; j < SSL_SOCK_NUM_KEYTYPES; j++) {
3646 if (!strcmp(end + 1, SSL_SOCK_KEYTYPE_NAMES[j])) {
3647 is_bundle = 1;
3648 break;
3649 }
3650 }
3651
3652 if (is_bundle) {
3653 char dp[MAXPATHLEN+1] = {0}; /* this will be the filename w/o the keytype */
3654 int dp_len;
3655
3656 dp_len = end - de->d_name;
3657 snprintf(dp, dp_len + 1, "%s", de->d_name);
3658
3659 /* increment i and free de until we get to a non-bundle cert
3660 * Note here that we look at de_list[i + 1] before freeing de
3661 * this is important since ignore_entry will free de
3662 */
3663 while (i + 1 < n && !strncmp(de_list[i + 1]->d_name, dp, dp_len)) {
3664 free(de);
3665 i++;
3666 de = de_list[i];
3667 }
3668
3669 snprintf(fp, sizeof(fp), "%s/%s", path, dp);
Willy Tarreaub131c872019-10-16 16:42:19 +02003670 cfgerr |= ssl_sock_load_multi_cert(fp, bind_conf, NULL, NULL, 0, err);
yanbzhu63ea8462015-12-09 13:35:14 -05003671
3672 /* Successfully processed the bundle */
3673 goto ignore_entry;
3674 }
3675 }
3676
3677#endif
Willy Tarreaub131c872019-10-16 16:42:19 +02003678 cfgerr |= ssl_sock_load_cert_file(fp, bind_conf, NULL, NULL, 0, err);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003679ignore_entry:
3680 free(de);
Cyril Bonté3180f7b2015-01-25 00:16:08 +01003681 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003682 free(de_list);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003683 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003684 closedir(dir);
3685 return cfgerr;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003686 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003687
Willy Tarreaub131c872019-10-16 16:42:19 +02003688 cfgerr |= ssl_sock_load_multi_cert(path, bind_conf, NULL, NULL, 0, err);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003689
Emeric Brunfc0421f2012-09-07 17:30:07 +02003690 return cfgerr;
3691}
3692
Thierry Fournier383085f2013-01-24 14:15:43 +01003693/* Make sure openssl opens /dev/urandom before the chroot. The work is only
3694 * done once. Zero is returned if the operation fails. No error is returned
3695 * if the random is said as not implemented, because we expect that openssl
3696 * will use another method once needed.
3697 */
3698static int ssl_initialize_random()
3699{
3700 unsigned char random;
3701 static int random_initialized = 0;
3702
3703 if (!random_initialized && RAND_bytes(&random, 1) != 0)
3704 random_initialized = 1;
3705
3706 return random_initialized;
3707}
3708
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003709/* release ssl bind conf */
3710void ssl_sock_free_ssl_conf(struct ssl_bind_conf *conf)
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003711{
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003712 if (conf) {
Bernard Spil13c53f82018-02-15 13:34:58 +01003713#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003714 free(conf->npn_str);
3715 conf->npn_str = NULL;
3716#endif
3717#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
3718 free(conf->alpn_str);
3719 conf->alpn_str = NULL;
3720#endif
3721 free(conf->ca_file);
3722 conf->ca_file = NULL;
3723 free(conf->crl_file);
3724 conf->crl_file = NULL;
3725 free(conf->ciphers);
3726 conf->ciphers = NULL;
Emmanuel Hocdet839af572019-05-14 16:27:35 +02003727#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02003728 free(conf->ciphersuites);
3729 conf->ciphersuites = NULL;
3730#endif
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01003731 free(conf->curves);
3732 conf->curves = NULL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003733 free(conf->ecdhe);
3734 conf->ecdhe = NULL;
3735 }
3736}
3737
Willy Tarreaub131c872019-10-16 16:42:19 +02003738/* Returns a set of ERR_* flags possibly with an error in <err>. */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003739int ssl_sock_load_cert_list_file(char *file, struct bind_conf *bind_conf, struct proxy *curproxy, char **err)
3740{
3741 char thisline[CRT_LINESIZE];
3742 char path[MAXPATHLEN+1];
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003743 FILE *f;
yanbzhu1b04e5b2015-12-02 13:54:14 -05003744 struct stat buf;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003745 int linenum = 0;
3746 int cfgerr = 0;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003747
Willy Tarreauad1731d2013-04-02 17:35:58 +02003748 if ((f = fopen(file, "r")) == NULL) {
3749 memprintf(err, "cannot open file '%s' : %s", file, strerror(errno));
Willy Tarreaub131c872019-10-16 16:42:19 +02003750 return ERR_ALERT | ERR_FATAL;
Willy Tarreauad1731d2013-04-02 17:35:58 +02003751 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003752
3753 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003754 int arg, newarg, cur_arg, i, ssl_b = 0, ssl_e = 0;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003755 char *end;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003756 char *args[MAX_CRT_ARGS + 1];
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003757 char *line = thisline;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003758 char *crt_path;
3759 struct ssl_bind_conf *ssl_conf = NULL;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003760
3761 linenum++;
3762 end = line + strlen(line);
3763 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
3764 /* Check if we reached the limit and the last char is not \n.
3765 * Watch out for the last line without the terminating '\n'!
3766 */
Willy Tarreauad1731d2013-04-02 17:35:58 +02003767 memprintf(err, "line %d too long in file '%s', limit is %d characters",
3768 linenum, file, (int)sizeof(thisline)-1);
Willy Tarreaub131c872019-10-16 16:42:19 +02003769 cfgerr |= ERR_ALERT | ERR_FATAL;
Willy Tarreauad1731d2013-04-02 17:35:58 +02003770 break;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003771 }
3772
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003773 arg = 0;
Emeric Brun50bcecc2013-04-22 13:05:23 +02003774 newarg = 1;
3775 while (*line) {
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003776 if (*line == '#' || *line == '\n' || *line == '\r') {
3777 /* end of string, end of loop */
3778 *line = 0;
3779 break;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003780 } else if (isspace(*line)) {
Emeric Brun50bcecc2013-04-22 13:05:23 +02003781 newarg = 1;
3782 *line = 0;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003783 } else if (*line == '[') {
3784 if (ssl_b) {
3785 memprintf(err, "too many '[' on line %d in file '%s'.", linenum, file);
Willy Tarreaub131c872019-10-16 16:42:19 +02003786 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003787 break;
3788 }
3789 if (!arg) {
3790 memprintf(err, "file must start with a cert on line %d in file '%s'", linenum, file);
Willy Tarreaub131c872019-10-16 16:42:19 +02003791 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003792 break;
3793 }
3794 ssl_b = arg;
3795 newarg = 1;
3796 *line = 0;
3797 } else if (*line == ']') {
3798 if (ssl_e) {
3799 memprintf(err, "too many ']' on line %d in file '%s'.", linenum, file);
Willy Tarreaub131c872019-10-16 16:42:19 +02003800 cfgerr |= ERR_ALERT | ERR_FATAL;
Emeric Brun50bcecc2013-04-22 13:05:23 +02003801 break;
3802 }
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003803 if (!ssl_b) {
3804 memprintf(err, "missing '[' in line %d in file '%s'.", linenum, file);
Willy Tarreaub131c872019-10-16 16:42:19 +02003805 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003806 break;
3807 }
3808 ssl_e = arg;
3809 newarg = 1;
3810 *line = 0;
3811 } else if (newarg) {
3812 if (arg == MAX_CRT_ARGS) {
3813 memprintf(err, "too many args on line %d in file '%s'.", linenum, file);
Willy Tarreaub131c872019-10-16 16:42:19 +02003814 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003815 break;
3816 }
Emeric Brun50bcecc2013-04-22 13:05:23 +02003817 newarg = 0;
3818 args[arg++] = line;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003819 }
Emeric Brun50bcecc2013-04-22 13:05:23 +02003820 line++;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003821 }
Willy Tarreaub131c872019-10-16 16:42:19 +02003822 if (cfgerr & ERR_CODE)
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02003823 break;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003824 args[arg++] = line;
Willy Tarreauad1731d2013-04-02 17:35:58 +02003825
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003826 /* empty line */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003827 if (!*args[0])
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003828 continue;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003829
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003830 crt_path = args[0];
3831 if (*crt_path != '/' && global_ssl.crt_base) {
3832 if ((strlen(global_ssl.crt_base) + 1 + strlen(crt_path)) > MAXPATHLEN) {
3833 memprintf(err, "'%s' : path too long on line %d in file '%s'",
3834 crt_path, 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 snprintf(path, sizeof(path), "%s/%s", global_ssl.crt_base, crt_path);
3839 crt_path = path;
3840 }
3841
3842 ssl_conf = calloc(1, sizeof *ssl_conf);
3843 cur_arg = ssl_b ? ssl_b : 1;
3844 while (cur_arg < ssl_e) {
3845 newarg = 0;
3846 for (i = 0; ssl_bind_kws[i].kw != NULL; i++) {
3847 if (strcmp(ssl_bind_kws[i].kw, args[cur_arg]) == 0) {
3848 newarg = 1;
Willy Tarreaub131c872019-10-16 16:42:19 +02003849 cfgerr |= ssl_bind_kws[i].parse(args, cur_arg, curproxy, ssl_conf, err);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003850 if (cur_arg + 1 + ssl_bind_kws[i].skip > ssl_e) {
3851 memprintf(err, "ssl args out of '[]' for %s on line %d in file '%s'",
3852 args[cur_arg], linenum, file);
Willy Tarreaub131c872019-10-16 16:42:19 +02003853 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003854 }
3855 cur_arg += 1 + ssl_bind_kws[i].skip;
3856 break;
3857 }
3858 }
3859 if (!cfgerr && !newarg) {
3860 memprintf(err, "unknown ssl keyword %s on line %d in file '%s'.",
3861 args[cur_arg], linenum, file);
Willy Tarreaub131c872019-10-16 16:42:19 +02003862 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003863 break;
3864 }
3865 }
Willy Tarreaub131c872019-10-16 16:42:19 +02003866
3867 if (cfgerr & ERR_CODE) {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003868 ssl_sock_free_ssl_conf(ssl_conf);
3869 free(ssl_conf);
3870 ssl_conf = NULL;
3871 break;
3872 }
3873
3874 if (stat(crt_path, &buf) == 0) {
Willy Tarreaub131c872019-10-16 16:42:19 +02003875 cfgerr |= ssl_sock_load_cert_file(crt_path, bind_conf, ssl_conf,
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003876 &args[cur_arg], arg - cur_arg - 1, err);
Willy Tarreaub131c872019-10-16 16:42:19 +02003877 } else {
3878 cfgerr |= ssl_sock_load_multi_cert(crt_path, bind_conf, ssl_conf,
3879 &args[cur_arg], arg - cur_arg - 1, err);
yanbzhu1b04e5b2015-12-02 13:54:14 -05003880 }
3881
Willy Tarreaub131c872019-10-16 16:42:19 +02003882 if (cfgerr & ERR_CODE) {
Willy Tarreauad1731d2013-04-02 17:35:58 +02003883 memprintf(err, "error processing line %d in file '%s' : %s", linenum, file, *err);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003884 break;
Willy Tarreauad1731d2013-04-02 17:35:58 +02003885 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003886 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003887 fclose(f);
3888 return cfgerr;
3889}
3890
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003891/* Create an initial CTX used to start the SSL connection before switchctx */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003892static int
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003893ssl_sock_initial_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02003894{
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01003895 SSL_CTX *ctx = NULL;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003896 long options =
Emeric Brunfc0421f2012-09-07 17:30:07 +02003897 SSL_OP_ALL | /* all known workarounds for bugs */
3898 SSL_OP_NO_SSLv2 |
3899 SSL_OP_NO_COMPRESSION |
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02003900 SSL_OP_SINGLE_DH_USE |
Emeric Brun2b58d042012-09-20 17:10:03 +02003901 SSL_OP_SINGLE_ECDH_USE |
Emeric Brun3c4bc6e2012-10-04 18:44:19 +02003902 SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION |
Lukas Tribus926594f2018-05-18 17:55:57 +02003903 SSL_OP_PRIORITIZE_CHACHA |
Emeric Brun3c4bc6e2012-10-04 18:44:19 +02003904 SSL_OP_CIPHER_SERVER_PREFERENCE;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003905 long mode =
Emeric Brunfc0421f2012-09-07 17:30:07 +02003906 SSL_MODE_ENABLE_PARTIAL_WRITE |
3907 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
Willy Tarreau396a1862014-11-13 14:06:52 +01003908 SSL_MODE_RELEASE_BUFFERS |
3909 SSL_MODE_SMALL_BUFFERS;
Emmanuel Hocdet43664762017-08-09 18:26:20 +02003910 struct tls_version_filter *conf_ssl_methods = &bind_conf->ssl_conf.ssl_methods;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003911 int i, min, max, hole;
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003912 int flags = MC_SSL_O_ALL;
3913 int cfgerr = 0;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01003914
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003915 ctx = SSL_CTX_new(SSLv23_server_method());
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003916 bind_conf->initial_ctx = ctx;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003917
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003918 if (conf_ssl_methods->flags && (conf_ssl_methods->min || conf_ssl_methods->max))
Christopher Faulet767a84b2017-11-24 16:50:31 +01003919 ha_warning("Proxy '%s': no-sslv3/no-tlsv1x are ignored for bind '%s' at [%s:%d]. "
3920 "Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
3921 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003922 else
3923 flags = conf_ssl_methods->flags;
3924
Emmanuel Hocdetbd695fe2017-05-15 15:53:41 +02003925 min = conf_ssl_methods->min;
3926 max = conf_ssl_methods->max;
3927 /* start with TLSv10 to remove SSLv3 per default */
3928 if (!min && (!max || max >= CONF_TLSV10))
3929 min = CONF_TLSV10;
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02003930 /* Real min and max should be determinate with configuration and openssl's capabilities */
Emmanuel Hocdetbd695fe2017-05-15 15:53:41 +02003931 if (min)
3932 flags |= (methodVersions[min].flag - 1);
3933 if (max)
3934 flags |= ~((methodVersions[max].flag << 1) - 1);
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02003935 /* find min, max and holes */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003936 min = max = CONF_TLSV_NONE;
3937 hole = 0;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003938 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003939 /* version is in openssl && version not disable in configuration */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003940 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003941 if (min) {
3942 if (hole) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003943 ha_warning("Proxy '%s': SSL/TLS versions range not contiguous for bind '%s' at [%s:%d]. "
3944 "Hole find for %s. Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
3945 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line,
3946 methodVersions[hole].name);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003947 hole = 0;
3948 }
3949 max = i;
3950 }
3951 else {
3952 min = max = i;
3953 }
3954 }
3955 else {
3956 if (min)
3957 hole = i;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003958 }
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003959 if (!min) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003960 ha_alert("Proxy '%s': all SSL/TLS versions are disabled for bind '%s' at [%s:%d].\n",
3961 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003962 cfgerr += 1;
3963 }
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02003964 /* save real min/max in bind_conf */
3965 conf_ssl_methods->min = min;
3966 conf_ssl_methods->max = max;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003967
Willy Tarreau9a1ab082019-05-09 13:26:41 +02003968#if (HA_OPENSSL_VERSION_NUMBER < 0x1010000fL)
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003969 /* Keep force-xxx implementation as it is in older haproxy. It's a
Joseph Herlant017b3da2018-11-15 09:07:59 -08003970 precautionary measure to avoid any surprise with older openssl version. */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003971 if (min == max)
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02003972 methodVersions[min].ctx_set_version(ctx, SET_SERVER);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003973 else
3974 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
3975 if (flags & methodVersions[i].flag)
3976 options |= methodVersions[i].option;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003977#else /* openssl >= 1.1.0 */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003978 /* set the max_version is required to cap TLS version or activate new TLS (v1.3) */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02003979 methodVersions[min].ctx_set_version(ctx, SET_MIN);
3980 methodVersions[max].ctx_set_version(ctx, SET_MAX);
Emeric Brunfa5c5c82017-04-28 16:19:51 +02003981#endif
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003982
3983 if (bind_conf->ssl_options & BC_SSL_O_NO_TLS_TICKETS)
3984 options |= SSL_OP_NO_TICKET;
3985 if (bind_conf->ssl_options & BC_SSL_O_PREF_CLIE_CIPH)
3986 options &= ~SSL_OP_CIPHER_SERVER_PREFERENCE;
Dirkjan Bussink526894f2019-01-21 09:35:03 -08003987
3988#ifdef SSL_OP_NO_RENEGOTIATION
3989 options |= SSL_OP_NO_RENEGOTIATION;
3990#endif
3991
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003992 SSL_CTX_set_options(ctx, options);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00003993
Willy Tarreau5db847a2019-05-09 14:13:35 +02003994#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00003995 if (global_ssl.async)
3996 mode |= SSL_MODE_ASYNC;
3997#endif
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003998 SSL_CTX_set_mode(ctx, mode);
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01003999 if (global_ssl.life_time)
4000 SSL_CTX_set_timeout(ctx, global_ssl.life_time);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004001
4002#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
4003#ifdef OPENSSL_IS_BORINGSSL
4004 SSL_CTX_set_select_certificate_cb(ctx, ssl_sock_switchctx_cbk);
4005 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_err_cbk);
Willy Tarreau5db847a2019-05-09 14:13:35 +02004006#elif (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Olivier Houchard51088ce2019-01-02 18:46:41 +01004007 if (bind_conf->ssl_conf.early_data) {
4008 SSL_CTX_set_options(ctx, SSL_OP_NO_ANTI_REPLAY);
4009 SSL_CTX_set_max_early_data(ctx, global.tune.bufsize - global.tune.maxrewrite);
4010 }
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02004011 SSL_CTX_set_client_hello_cb(ctx, ssl_sock_switchctx_cbk, NULL);
4012 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_err_cbk);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004013#else
4014 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_cbk);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004015#endif
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02004016 SSL_CTX_set_tlsext_servername_arg(ctx, bind_conf);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004017#endif
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004018 return cfgerr;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004019}
4020
William Lallemand4f45bb92017-10-30 20:08:51 +01004021
4022static inline void sh_ssl_sess_free_blocks(struct shared_block *first, struct shared_block *block)
4023{
4024 if (first == block) {
4025 struct sh_ssl_sess_hdr *sh_ssl_sess = (struct sh_ssl_sess_hdr *)first->data;
4026 if (first->len > 0)
4027 sh_ssl_sess_tree_delete(sh_ssl_sess);
4028 }
4029}
4030
4031/* return first block from sh_ssl_sess */
4032static inline struct shared_block *sh_ssl_sess_first_block(struct sh_ssl_sess_hdr *sh_ssl_sess)
4033{
4034 return (struct shared_block *)((unsigned char *)sh_ssl_sess - ((struct shared_block *)NULL)->data);
4035
4036}
4037
4038/* store a session into the cache
4039 * s_id : session id padded with zero to SSL_MAX_SSL_SESSION_ID_LENGTH
4040 * data: asn1 encoded session
4041 * data_len: asn1 encoded session length
4042 * Returns 1 id session was stored (else 0)
4043 */
4044static int sh_ssl_sess_store(unsigned char *s_id, unsigned char *data, int data_len)
4045{
4046 struct shared_block *first;
4047 struct sh_ssl_sess_hdr *sh_ssl_sess, *oldsh_ssl_sess;
4048
Frédéric Lécaille0bec8072018-10-22 17:55:57 +02004049 first = shctx_row_reserve_hot(ssl_shctx, NULL, data_len + sizeof(struct sh_ssl_sess_hdr));
William Lallemand4f45bb92017-10-30 20:08:51 +01004050 if (!first) {
4051 /* Could not retrieve enough free blocks to store that session */
4052 return 0;
4053 }
4054
4055 /* STORE the key in the first elem */
4056 sh_ssl_sess = (struct sh_ssl_sess_hdr *)first->data;
4057 memcpy(sh_ssl_sess->key_data, s_id, SSL_MAX_SSL_SESSION_ID_LENGTH);
4058 first->len = sizeof(struct sh_ssl_sess_hdr);
4059
4060 /* it returns the already existing node
4061 or current node if none, never returns null */
4062 oldsh_ssl_sess = sh_ssl_sess_tree_insert(sh_ssl_sess);
4063 if (oldsh_ssl_sess != sh_ssl_sess) {
4064 /* NOTE: Row couldn't be in use because we lock read & write function */
4065 /* release the reserved row */
4066 shctx_row_dec_hot(ssl_shctx, first);
4067 /* replace the previous session already in the tree */
4068 sh_ssl_sess = oldsh_ssl_sess;
4069 /* ignore the previous session data, only use the header */
4070 first = sh_ssl_sess_first_block(sh_ssl_sess);
4071 shctx_row_inc_hot(ssl_shctx, first);
4072 first->len = sizeof(struct sh_ssl_sess_hdr);
4073 }
4074
Frédéric Lécaille0bec8072018-10-22 17:55:57 +02004075 if (shctx_row_data_append(ssl_shctx, first, NULL, data, data_len) < 0) {
William Lallemand99b90af2018-01-03 19:15:51 +01004076 shctx_row_dec_hot(ssl_shctx, first);
William Lallemand4f45bb92017-10-30 20:08:51 +01004077 return 0;
William Lallemand99b90af2018-01-03 19:15:51 +01004078 }
4079
4080 shctx_row_dec_hot(ssl_shctx, first);
William Lallemand4f45bb92017-10-30 20:08:51 +01004081
4082 return 1;
4083}
William Lallemanded0b5ad2017-10-30 19:36:36 +01004084
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004085/* SSL callback used when a new session is created while connecting to a server */
4086static int ssl_sess_new_srv_cb(SSL *ssl, SSL_SESSION *sess)
4087{
Thierry FOURNIER28962c92018-06-17 21:37:05 +02004088 struct connection *conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Olivier Houcharde6060c52017-11-16 17:42:52 +01004089 struct server *s;
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004090
Willy Tarreau07d94e42018-09-20 10:57:52 +02004091 s = __objt_server(conn->target);
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004092
Olivier Houcharde6060c52017-11-16 17:42:52 +01004093 if (!(s->ssl_ctx.options & SRV_SSL_O_NO_REUSE)) {
4094 int len;
4095 unsigned char *ptr;
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004096
Olivier Houcharde6060c52017-11-16 17:42:52 +01004097 len = i2d_SSL_SESSION(sess, NULL);
4098 if (s->ssl_ctx.reused_sess[tid].ptr && s->ssl_ctx.reused_sess[tid].allocated_size >= len) {
4099 ptr = s->ssl_ctx.reused_sess[tid].ptr;
4100 } else {
4101 free(s->ssl_ctx.reused_sess[tid].ptr);
4102 ptr = s->ssl_ctx.reused_sess[tid].ptr = malloc(len);
4103 s->ssl_ctx.reused_sess[tid].allocated_size = len;
4104 }
4105 if (s->ssl_ctx.reused_sess[tid].ptr) {
4106 s->ssl_ctx.reused_sess[tid].size = i2d_SSL_SESSION(sess,
4107 &ptr);
4108 }
4109 } else {
4110 free(s->ssl_ctx.reused_sess[tid].ptr);
4111 s->ssl_ctx.reused_sess[tid].ptr = NULL;
4112 }
4113
4114 return 0;
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004115}
4116
Olivier Houcharde6060c52017-11-16 17:42:52 +01004117
William Lallemanded0b5ad2017-10-30 19:36:36 +01004118/* SSL callback used on new session creation */
William Lallemand4f45bb92017-10-30 20:08:51 +01004119int sh_ssl_sess_new_cb(SSL *ssl, SSL_SESSION *sess)
William Lallemanded0b5ad2017-10-30 19:36:36 +01004120{
4121 unsigned char encsess[SHSESS_MAX_DATA_LEN]; /* encoded session */
4122 unsigned char encid[SSL_MAX_SSL_SESSION_ID_LENGTH]; /* encoded id */
4123 unsigned char *p;
4124 int data_len;
4125 unsigned int sid_length, sid_ctx_length;
4126 const unsigned char *sid_data;
4127 const unsigned char *sid_ctx_data;
4128
4129 /* Session id is already stored in to key and session id is known
4130 * so we dont store it to keep size.
4131 */
4132
4133 sid_data = SSL_SESSION_get_id(sess, &sid_length);
4134 sid_ctx_data = SSL_SESSION_get0_id_context(sess, &sid_ctx_length);
4135 SSL_SESSION_set1_id(sess, sid_data, 0);
4136 SSL_SESSION_set1_id_context(sess, sid_ctx_data, 0);
4137
4138 /* check if buffer is large enough for the ASN1 encoded session */
4139 data_len = i2d_SSL_SESSION(sess, NULL);
4140 if (data_len > SHSESS_MAX_DATA_LEN)
4141 goto err;
4142
4143 p = encsess;
4144
4145 /* process ASN1 session encoding before the lock */
4146 i2d_SSL_SESSION(sess, &p);
4147
4148 memcpy(encid, sid_data, sid_length);
4149 if (sid_length < SSL_MAX_SSL_SESSION_ID_LENGTH)
4150 memset(encid + sid_length, 0, SSL_MAX_SSL_SESSION_ID_LENGTH-sid_length);
4151
William Lallemanda3c77cf2017-10-30 23:44:40 +01004152 shctx_lock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004153 /* store to cache */
William Lallemand4f45bb92017-10-30 20:08:51 +01004154 sh_ssl_sess_store(encid, encsess, data_len);
William Lallemanda3c77cf2017-10-30 23:44:40 +01004155 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004156err:
4157 /* reset original length values */
4158 SSL_SESSION_set1_id(sess, sid_data, sid_length);
4159 SSL_SESSION_set1_id_context(sess, sid_ctx_data, sid_ctx_length);
4160
4161 return 0; /* do not increment session reference count */
4162}
4163
4164/* SSL callback used on lookup an existing session cause none found in internal cache */
William Lallemand4f45bb92017-10-30 20:08:51 +01004165SSL_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 +01004166{
William Lallemand4f45bb92017-10-30 20:08:51 +01004167 struct sh_ssl_sess_hdr *sh_ssl_sess;
William Lallemanded0b5ad2017-10-30 19:36:36 +01004168 unsigned char data[SHSESS_MAX_DATA_LEN], *p;
4169 unsigned char tmpkey[SSL_MAX_SSL_SESSION_ID_LENGTH];
William Lallemanded0b5ad2017-10-30 19:36:36 +01004170 SSL_SESSION *sess;
William Lallemand4f45bb92017-10-30 20:08:51 +01004171 struct shared_block *first;
William Lallemanded0b5ad2017-10-30 19:36:36 +01004172
4173 global.shctx_lookups++;
4174
4175 /* allow the session to be freed automatically by openssl */
4176 *do_copy = 0;
4177
4178 /* tree key is zeros padded sessionid */
4179 if (key_len < SSL_MAX_SSL_SESSION_ID_LENGTH) {
4180 memcpy(tmpkey, key, key_len);
4181 memset(tmpkey + key_len, 0, SSL_MAX_SSL_SESSION_ID_LENGTH - key_len);
4182 key = tmpkey;
4183 }
4184
4185 /* lock cache */
William Lallemanda3c77cf2017-10-30 23:44:40 +01004186 shctx_lock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004187
4188 /* lookup for session */
William Lallemand4f45bb92017-10-30 20:08:51 +01004189 sh_ssl_sess = sh_ssl_sess_tree_lookup(key);
4190 if (!sh_ssl_sess) {
William Lallemanded0b5ad2017-10-30 19:36:36 +01004191 /* no session found: unlock cache and exit */
William Lallemanda3c77cf2017-10-30 23:44:40 +01004192 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004193 global.shctx_misses++;
4194 return NULL;
4195 }
4196
William Lallemand4f45bb92017-10-30 20:08:51 +01004197 /* sh_ssl_sess (shared_block->data) is at the end of shared_block */
4198 first = sh_ssl_sess_first_block(sh_ssl_sess);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004199
William Lallemand4f45bb92017-10-30 20:08:51 +01004200 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 +01004201
William Lallemanda3c77cf2017-10-30 23:44:40 +01004202 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004203
4204 /* decode ASN1 session */
4205 p = data;
William Lallemand4f45bb92017-10-30 20:08:51 +01004206 sess = d2i_SSL_SESSION(NULL, (const unsigned char **)&p, first->len-sizeof(struct sh_ssl_sess_hdr));
William Lallemanded0b5ad2017-10-30 19:36:36 +01004207 /* Reset session id and session id contenxt */
4208 if (sess) {
4209 SSL_SESSION_set1_id(sess, key, key_len);
4210 SSL_SESSION_set1_id_context(sess, (const unsigned char *)SHCTX_APPNAME, strlen(SHCTX_APPNAME));
4211 }
4212
4213 return sess;
4214}
4215
William Lallemand4f45bb92017-10-30 20:08:51 +01004216
William Lallemanded0b5ad2017-10-30 19:36:36 +01004217/* SSL callback used to signal session is no more used in internal cache */
William Lallemand4f45bb92017-10-30 20:08:51 +01004218void sh_ssl_sess_remove_cb(SSL_CTX *ctx, SSL_SESSION *sess)
William Lallemanded0b5ad2017-10-30 19:36:36 +01004219{
William Lallemand4f45bb92017-10-30 20:08:51 +01004220 struct sh_ssl_sess_hdr *sh_ssl_sess;
William Lallemanded0b5ad2017-10-30 19:36:36 +01004221 unsigned char tmpkey[SSL_MAX_SSL_SESSION_ID_LENGTH];
4222 unsigned int sid_length;
4223 const unsigned char *sid_data;
4224 (void)ctx;
4225
4226 sid_data = SSL_SESSION_get_id(sess, &sid_length);
4227 /* tree key is zeros padded sessionid */
4228 if (sid_length < SSL_MAX_SSL_SESSION_ID_LENGTH) {
4229 memcpy(tmpkey, sid_data, sid_length);
4230 memset(tmpkey+sid_length, 0, SSL_MAX_SSL_SESSION_ID_LENGTH - sid_length);
4231 sid_data = tmpkey;
4232 }
4233
William Lallemanda3c77cf2017-10-30 23:44:40 +01004234 shctx_lock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004235
4236 /* lookup for session */
William Lallemand4f45bb92017-10-30 20:08:51 +01004237 sh_ssl_sess = sh_ssl_sess_tree_lookup(sid_data);
4238 if (sh_ssl_sess) {
William Lallemanded0b5ad2017-10-30 19:36:36 +01004239 /* free session */
William Lallemand4f45bb92017-10-30 20:08:51 +01004240 sh_ssl_sess_tree_delete(sh_ssl_sess);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004241 }
4242
4243 /* unlock cache */
William Lallemanda3c77cf2017-10-30 23:44:40 +01004244 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004245}
4246
4247/* Set session cache mode to server and disable openssl internal cache.
4248 * Set shared cache callbacks on an ssl context.
4249 * Shared context MUST be firstly initialized */
William Lallemand4f45bb92017-10-30 20:08:51 +01004250void ssl_set_shctx(SSL_CTX *ctx)
William Lallemanded0b5ad2017-10-30 19:36:36 +01004251{
4252 SSL_CTX_set_session_id_context(ctx, (const unsigned char *)SHCTX_APPNAME, strlen(SHCTX_APPNAME));
4253
4254 if (!ssl_shctx) {
4255 SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF);
4256 return;
4257 }
4258
4259 SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_SERVER |
4260 SSL_SESS_CACHE_NO_INTERNAL |
4261 SSL_SESS_CACHE_NO_AUTO_CLEAR);
4262
4263 /* Set callbacks */
William Lallemand4f45bb92017-10-30 20:08:51 +01004264 SSL_CTX_sess_set_new_cb(ctx, sh_ssl_sess_new_cb);
4265 SSL_CTX_sess_set_get_cb(ctx, sh_ssl_sess_get_cb);
4266 SSL_CTX_sess_set_remove_cb(ctx, sh_ssl_sess_remove_cb);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004267}
4268
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004269int ssl_sock_prepare_ctx(struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf, SSL_CTX *ctx)
4270{
4271 struct proxy *curproxy = bind_conf->frontend;
4272 int cfgerr = 0;
4273 int verify = SSL_VERIFY_NONE;
Willy Tarreau5d4cafb2018-01-04 18:55:19 +01004274 struct ssl_bind_conf __maybe_unused *ssl_conf_cur;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004275 const char *conf_ciphers;
Emmanuel Hocdet839af572019-05-14 16:27:35 +02004276#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02004277 const char *conf_ciphersuites;
4278#endif
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004279 const char *conf_curves = NULL;
Emeric Brunfc0421f2012-09-07 17:30:07 +02004280
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02004281 if (ssl_conf) {
4282 struct tls_version_filter *conf_ssl_methods = &ssl_conf->ssl_methods;
4283 int i, min, max;
4284 int flags = MC_SSL_O_ALL;
4285
4286 /* Real min and max should be determinate with configuration and openssl's capabilities */
Emmanuel Hocdet43664762017-08-09 18:26:20 +02004287 min = conf_ssl_methods->min ? conf_ssl_methods->min : bind_conf->ssl_conf.ssl_methods.min;
4288 max = conf_ssl_methods->max ? conf_ssl_methods->max : bind_conf->ssl_conf.ssl_methods.max;
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02004289 if (min)
4290 flags |= (methodVersions[min].flag - 1);
4291 if (max)
4292 flags |= ~((methodVersions[max].flag << 1) - 1);
4293 min = max = CONF_TLSV_NONE;
4294 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
4295 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
4296 if (min)
4297 max = i;
4298 else
4299 min = max = i;
4300 }
4301 /* save real min/max */
4302 conf_ssl_methods->min = min;
4303 conf_ssl_methods->max = max;
4304 if (!min) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004305 ha_alert("Proxy '%s': all SSL/TLS versions are disabled for bind '%s' at [%s:%d].\n",
4306 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02004307 cfgerr += 1;
4308 }
4309 }
4310
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004311 switch ((ssl_conf && ssl_conf->verify) ? ssl_conf->verify : bind_conf->ssl_conf.verify) {
Emeric Brun850efd52014-01-29 12:24:34 +01004312 case SSL_SOCK_VERIFY_NONE:
4313 verify = SSL_VERIFY_NONE;
4314 break;
4315 case SSL_SOCK_VERIFY_OPTIONAL:
4316 verify = SSL_VERIFY_PEER;
4317 break;
4318 case SSL_SOCK_VERIFY_REQUIRED:
4319 verify = SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
4320 break;
4321 }
4322 SSL_CTX_set_verify(ctx, verify, ssl_sock_bind_verifycbk);
4323 if (verify & SSL_VERIFY_PEER) {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004324 char *ca_file = (ssl_conf && ssl_conf->ca_file) ? ssl_conf->ca_file : bind_conf->ssl_conf.ca_file;
4325 char *crl_file = (ssl_conf && ssl_conf->crl_file) ? ssl_conf->crl_file : bind_conf->ssl_conf.crl_file;
4326 if (ca_file) {
Emeric Brund94b3fe2012-09-20 18:23:56 +02004327 /* load CAfile to verify */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004328 if (!SSL_CTX_load_verify_locations(ctx, ca_file, NULL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004329 ha_alert("Proxy '%s': unable to load CA file '%s' for bind '%s' at [%s:%d].\n",
4330 curproxy->id, ca_file, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brund94b3fe2012-09-20 18:23:56 +02004331 cfgerr++;
4332 }
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02004333 if (!((ssl_conf && ssl_conf->no_ca_names) || bind_conf->ssl_conf.no_ca_names)) {
4334 /* set CA names for client cert request, function returns void */
4335 SSL_CTX_set_client_CA_list(ctx, SSL_load_client_CA_file(ca_file));
4336 }
Emeric Brund94b3fe2012-09-20 18:23:56 +02004337 }
Emeric Brun850efd52014-01-29 12:24:34 +01004338 else {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004339 ha_alert("Proxy '%s': verify is enabled but no CA file specified for bind '%s' at [%s:%d].\n",
4340 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brun850efd52014-01-29 12:24:34 +01004341 cfgerr++;
4342 }
Emeric Brun051cdab2012-10-02 19:25:50 +02004343#ifdef X509_V_FLAG_CRL_CHECK
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004344 if (crl_file) {
Emeric Brund94b3fe2012-09-20 18:23:56 +02004345 X509_STORE *store = SSL_CTX_get_cert_store(ctx);
4346
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004347 if (!store || !X509_STORE_load_locations(store, crl_file, NULL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004348 ha_alert("Proxy '%s': unable to configure CRL file '%s' for bind '%s' at [%s:%d].\n",
4349 curproxy->id, crl_file, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brund94b3fe2012-09-20 18:23:56 +02004350 cfgerr++;
4351 }
Emeric Brun561e5742012-10-02 15:20:55 +02004352 else {
4353 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
4354 }
Emeric Brund94b3fe2012-09-20 18:23:56 +02004355 }
Emeric Brun051cdab2012-10-02 19:25:50 +02004356#endif
Emeric Brun644cde02012-12-14 11:21:13 +01004357 ERR_clear_error();
Emeric Brund94b3fe2012-09-20 18:23:56 +02004358 }
Nenad Merdanovic05552d42015-02-27 19:56:49 +01004359#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
Nenad Merdanovic146defa2015-05-09 08:46:00 +02004360 if(bind_conf->keys_ref) {
Nenad Merdanovic05552d42015-02-27 19:56:49 +01004361 if (!SSL_CTX_set_tlsext_ticket_key_cb(ctx, ssl_tlsext_ticket_key_cb)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004362 ha_alert("Proxy '%s': unable to set callback for TLS ticket validation for bind '%s' at [%s:%d].\n",
4363 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Nenad Merdanovic05552d42015-02-27 19:56:49 +01004364 cfgerr++;
4365 }
4366 }
4367#endif
4368
William Lallemand4f45bb92017-10-30 20:08:51 +01004369 ssl_set_shctx(ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004370 conf_ciphers = (ssl_conf && ssl_conf->ciphers) ? ssl_conf->ciphers : bind_conf->ssl_conf.ciphers;
4371 if (conf_ciphers &&
4372 !SSL_CTX_set_cipher_list(ctx, conf_ciphers)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004373 ha_alert("Proxy '%s': unable to set SSL cipher list to '%s' for bind '%s' at [%s:%d].\n",
4374 curproxy->id, conf_ciphers, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004375 cfgerr++;
4376 }
4377
Emmanuel Hocdet839af572019-05-14 16:27:35 +02004378#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02004379 conf_ciphersuites = (ssl_conf && ssl_conf->ciphersuites) ? ssl_conf->ciphersuites : bind_conf->ssl_conf.ciphersuites;
4380 if (conf_ciphersuites &&
4381 !SSL_CTX_set_ciphersuites(ctx, conf_ciphersuites)) {
4382 ha_alert("Proxy '%s': unable to set TLS 1.3 cipher suites to '%s' for bind '%s' at [%s:%d].\n",
4383 curproxy->id, conf_ciphersuites, bind_conf->arg, bind_conf->file, bind_conf->line);
4384 cfgerr++;
4385 }
4386#endif
4387
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01004388#ifndef OPENSSL_NO_DH
Remi Gacogne47783ef2015-05-29 15:53:22 +02004389 /* If tune.ssl.default-dh-param has not been set,
4390 neither has ssl-default-dh-file and no static DH
4391 params were in the certificate file. */
Willy Tarreauef934602016-12-22 23:12:01 +01004392 if (global_ssl.default_dh_param == 0 &&
Remi Gacogne47783ef2015-05-29 15:53:22 +02004393 global_dh == NULL &&
Remi Gacogne4f902b82015-05-28 16:23:00 +02004394 (ssl_dh_ptr_index == -1 ||
4395 SSL_CTX_get_ex_data(ctx, ssl_dh_ptr_index) == NULL)) {
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01004396 STACK_OF(SSL_CIPHER) * ciphers = NULL;
4397 const SSL_CIPHER * cipher = NULL;
4398 char cipher_description[128];
4399 /* The description of ciphers using an Ephemeral Diffie Hellman key exchange
4400 contains " Kx=DH " or " Kx=DH(". Beware of " Kx=DH/",
4401 which is not ephemeral DH. */
4402 const char dhe_description[] = " Kx=DH ";
4403 const char dhe_export_description[] = " Kx=DH(";
4404 int idx = 0;
4405 int dhe_found = 0;
4406 SSL *ssl = NULL;
Lukas Tribus90132722014-08-18 00:56:33 +02004407
Remi Gacogne23d5d372014-10-10 17:04:26 +02004408 ssl = SSL_new(ctx);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004409
Remi Gacogne23d5d372014-10-10 17:04:26 +02004410 if (ssl) {
4411 ciphers = SSL_get_ciphers(ssl);
4412
4413 if (ciphers) {
4414 for (idx = 0; idx < sk_SSL_CIPHER_num(ciphers); idx++) {
4415 cipher = sk_SSL_CIPHER_value(ciphers, idx);
4416 if (SSL_CIPHER_description(cipher, cipher_description, sizeof (cipher_description)) == cipher_description) {
4417 if (strstr(cipher_description, dhe_description) != NULL ||
4418 strstr(cipher_description, dhe_export_description) != NULL) {
4419 dhe_found = 1;
4420 break;
4421 }
Remi Gacognec1eab8c2014-06-12 18:20:11 +02004422 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004423 }
4424 }
Remi Gacogne23d5d372014-10-10 17:04:26 +02004425 SSL_free(ssl);
4426 ssl = NULL;
Lukas Tribus90132722014-08-18 00:56:33 +02004427 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004428
Lukas Tribus90132722014-08-18 00:56:33 +02004429 if (dhe_found) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004430 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 +02004431 }
4432
Willy Tarreauef934602016-12-22 23:12:01 +01004433 global_ssl.default_dh_param = 1024;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004434 }
Remi Gacogne8de54152014-07-15 11:36:40 +02004435
Willy Tarreauef934602016-12-22 23:12:01 +01004436 if (global_ssl.default_dh_param >= 1024) {
Remi Gacogne8de54152014-07-15 11:36:40 +02004437 if (local_dh_1024 == NULL) {
4438 local_dh_1024 = ssl_get_dh_1024();
4439 }
Willy Tarreauef934602016-12-22 23:12:01 +01004440 if (global_ssl.default_dh_param >= 2048) {
Remi Gacogne8de54152014-07-15 11:36:40 +02004441 if (local_dh_2048 == NULL) {
4442 local_dh_2048 = ssl_get_dh_2048();
4443 }
Willy Tarreauef934602016-12-22 23:12:01 +01004444 if (global_ssl.default_dh_param >= 4096) {
Remi Gacogne8de54152014-07-15 11:36:40 +02004445 if (local_dh_4096 == NULL) {
4446 local_dh_4096 = ssl_get_dh_4096();
4447 }
Remi Gacogne8de54152014-07-15 11:36:40 +02004448 }
4449 }
4450 }
4451#endif /* OPENSSL_NO_DH */
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004452
Emeric Brunfc0421f2012-09-07 17:30:07 +02004453 SSL_CTX_set_info_callback(ctx, ssl_sock_infocbk);
Willy Tarreau9a1ab082019-05-09 13:26:41 +02004454#if HA_OPENSSL_VERSION_NUMBER >= 0x00907000L
Emeric Brun29f037d2014-04-25 19:05:36 +02004455 SSL_CTX_set_msg_callback(ctx, ssl_sock_msgcbk);
Willy Tarreau5cbe4ef2014-05-08 22:45:11 +02004456#endif
Emeric Brun29f037d2014-04-25 19:05:36 +02004457
Bernard Spil13c53f82018-02-15 13:34:58 +01004458#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004459 ssl_conf_cur = NULL;
4460 if (ssl_conf && ssl_conf->npn_str)
4461 ssl_conf_cur = ssl_conf;
4462 else if (bind_conf->ssl_conf.npn_str)
4463 ssl_conf_cur = &bind_conf->ssl_conf;
4464 if (ssl_conf_cur)
4465 SSL_CTX_set_next_protos_advertised_cb(ctx, ssl_sock_advertise_npn_protos, ssl_conf_cur);
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02004466#endif
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01004467#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004468 ssl_conf_cur = NULL;
4469 if (ssl_conf && ssl_conf->alpn_str)
4470 ssl_conf_cur = ssl_conf;
4471 else if (bind_conf->ssl_conf.alpn_str)
4472 ssl_conf_cur = &bind_conf->ssl_conf;
4473 if (ssl_conf_cur)
4474 SSL_CTX_set_alpn_select_cb(ctx, ssl_sock_advertise_alpn_protos, ssl_conf_cur);
Willy Tarreauab861d32013-04-02 02:30:41 +02004475#endif
Willy Tarreau9a1ab082019-05-09 13:26:41 +02004476#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004477 conf_curves = (ssl_conf && ssl_conf->curves) ? ssl_conf->curves : bind_conf->ssl_conf.curves;
4478 if (conf_curves) {
4479 if (!SSL_CTX_set1_curves_list(ctx, conf_curves)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004480 ha_alert("Proxy '%s': unable to set SSL curves list to '%s' for bind '%s' at [%s:%d].\n",
4481 curproxy->id, conf_curves, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004482 cfgerr++;
4483 }
Emmanuel Hocdeta52bb152017-03-20 11:11:49 +01004484#if defined(SSL_CTX_set_ecdh_auto)
4485 (void)SSL_CTX_set_ecdh_auto(ctx, 1);
4486#endif
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004487 }
4488#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02004489#if defined(SSL_CTX_set_tmp_ecdh) && !defined(OPENSSL_NO_ECDH)
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004490 if (!conf_curves) {
Emeric Brun2b58d042012-09-20 17:10:03 +02004491 int i;
4492 EC_KEY *ecdh;
Willy Tarreau9a1ab082019-05-09 13:26:41 +02004493#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004494 const char *ecdhe = (ssl_conf && ssl_conf->ecdhe) ? ssl_conf->ecdhe :
Olivier Houchardc2aae742017-09-22 18:26:28 +02004495 (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe :
4496 NULL);
4497
4498 if (ecdhe == NULL) {
4499 SSL_CTX_set_dh_auto(ctx, 1);
4500 return cfgerr;
4501 }
4502#else
4503 const char *ecdhe = (ssl_conf && ssl_conf->ecdhe) ? ssl_conf->ecdhe :
4504 (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe :
4505 ECDHE_DEFAULT_CURVE);
4506#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02004507
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004508 i = OBJ_sn2nid(ecdhe);
Emeric Brun2b58d042012-09-20 17:10:03 +02004509 if (!i || ((ecdh = EC_KEY_new_by_curve_name(i)) == NULL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004510 ha_alert("Proxy '%s': unable to set elliptic named curve to '%s' for bind '%s' at [%s:%d].\n",
4511 curproxy->id, ecdhe, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brun2b58d042012-09-20 17:10:03 +02004512 cfgerr++;
4513 }
4514 else {
4515 SSL_CTX_set_tmp_ecdh(ctx, ecdh);
4516 EC_KEY_free(ecdh);
4517 }
4518 }
4519#endif
4520
Emeric Brunfc0421f2012-09-07 17:30:07 +02004521 return cfgerr;
4522}
4523
Evan Broderbe554312013-06-27 00:05:25 -07004524static int ssl_sock_srv_hostcheck(const char *pattern, const char *hostname)
4525{
4526 const char *pattern_wildcard, *pattern_left_label_end, *hostname_left_label_end;
4527 size_t prefixlen, suffixlen;
4528
4529 /* Trivial case */
4530 if (strcmp(pattern, hostname) == 0)
4531 return 1;
4532
Evan Broderbe554312013-06-27 00:05:25 -07004533 /* The rest of this logic is based on RFC 6125, section 6.4.3
4534 * (http://tools.ietf.org/html/rfc6125#section-6.4.3) */
4535
Emeric Bruna848dae2013-10-08 11:27:28 +02004536 pattern_wildcard = NULL;
4537 pattern_left_label_end = pattern;
4538 while (*pattern_left_label_end != '.') {
4539 switch (*pattern_left_label_end) {
4540 case 0:
4541 /* End of label not found */
4542 return 0;
4543 case '*':
4544 /* If there is more than one wildcards */
4545 if (pattern_wildcard)
4546 return 0;
4547 pattern_wildcard = pattern_left_label_end;
4548 break;
4549 }
4550 pattern_left_label_end++;
4551 }
4552
4553 /* If it's not trivial and there is no wildcard, it can't
4554 * match */
4555 if (!pattern_wildcard)
Evan Broderbe554312013-06-27 00:05:25 -07004556 return 0;
4557
4558 /* Make sure all labels match except the leftmost */
4559 hostname_left_label_end = strchr(hostname, '.');
4560 if (!hostname_left_label_end
4561 || strcmp(pattern_left_label_end, hostname_left_label_end) != 0)
4562 return 0;
4563
4564 /* Make sure the leftmost label of the hostname is long enough
4565 * that the wildcard can match */
Emeric Brun369da852013-10-08 11:39:35 +02004566 if (hostname_left_label_end - hostname < (pattern_left_label_end - pattern) - 1)
Evan Broderbe554312013-06-27 00:05:25 -07004567 return 0;
4568
4569 /* Finally compare the string on either side of the
4570 * wildcard */
4571 prefixlen = pattern_wildcard - pattern;
4572 suffixlen = pattern_left_label_end - (pattern_wildcard + 1);
Emeric Bruna848dae2013-10-08 11:27:28 +02004573 if ((prefixlen && (memcmp(pattern, hostname, prefixlen) != 0))
4574 || (suffixlen && (memcmp(pattern_wildcard + 1, hostname_left_label_end - suffixlen, suffixlen) != 0)))
Evan Broderbe554312013-06-27 00:05:25 -07004575 return 0;
4576
4577 return 1;
4578}
4579
4580static int ssl_sock_srv_verifycbk(int ok, X509_STORE_CTX *ctx)
4581{
4582 SSL *ssl;
4583 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01004584 struct ssl_sock_ctx *ssl_ctx;
Willy Tarreau2ab88672017-07-05 18:23:03 +02004585 const char *servername;
Willy Tarreau71d058c2017-07-26 20:09:56 +02004586 const char *sni;
Evan Broderbe554312013-06-27 00:05:25 -07004587
4588 int depth;
4589 X509 *cert;
4590 STACK_OF(GENERAL_NAME) *alt_names;
4591 int i;
4592 X509_NAME *cert_subject;
4593 char *str;
4594
4595 if (ok == 0)
4596 return ok;
4597
4598 ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
Thierry FOURNIER28962c92018-06-17 21:37:05 +02004599 conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Olivier Houchard66ab4982019-02-26 18:37:15 +01004600 ssl_ctx = conn->xprt_ctx;
Evan Broderbe554312013-06-27 00:05:25 -07004601
Willy Tarreauad92a9a2017-07-28 11:38:41 +02004602 /* We're checking if the provided hostnames match the desired one. The
4603 * desired hostname comes from the SNI we presented if any, or if not
4604 * provided then it may have been explicitly stated using a "verifyhost"
4605 * directive. If neither is set, we don't care about the name so the
4606 * verification is OK.
Willy Tarreau2ab88672017-07-05 18:23:03 +02004607 */
Olivier Houchard66ab4982019-02-26 18:37:15 +01004608 servername = SSL_get_servername(ssl_ctx->ssl, TLSEXT_NAMETYPE_host_name);
Willy Tarreau71d058c2017-07-26 20:09:56 +02004609 sni = servername;
Willy Tarreau2ab88672017-07-05 18:23:03 +02004610 if (!servername) {
Willy Tarreau07d94e42018-09-20 10:57:52 +02004611 servername = __objt_server(conn->target)->ssl_ctx.verify_host;
Willy Tarreau2ab88672017-07-05 18:23:03 +02004612 if (!servername)
4613 return ok;
4614 }
Evan Broderbe554312013-06-27 00:05:25 -07004615
4616 /* We only need to verify the CN on the actual server cert,
4617 * not the indirect CAs */
4618 depth = X509_STORE_CTX_get_error_depth(ctx);
4619 if (depth != 0)
4620 return ok;
4621
4622 /* At this point, the cert is *not* OK unless we can find a
4623 * hostname match */
4624 ok = 0;
4625
4626 cert = X509_STORE_CTX_get_current_cert(ctx);
4627 /* It seems like this might happen if verify peer isn't set */
4628 if (!cert)
4629 return ok;
4630
4631 alt_names = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
4632 if (alt_names) {
4633 for (i = 0; !ok && i < sk_GENERAL_NAME_num(alt_names); i++) {
4634 GENERAL_NAME *name = sk_GENERAL_NAME_value(alt_names, i);
4635 if (name->type == GEN_DNS) {
Willy Tarreau9a1ab082019-05-09 13:26:41 +02004636#if HA_OPENSSL_VERSION_NUMBER < 0x00907000L
Emeric Bruna33410c2013-09-17 15:47:48 +02004637 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.ia5) >= 0) {
4638#else
Evan Broderbe554312013-06-27 00:05:25 -07004639 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
Emeric Bruna33410c2013-09-17 15:47:48 +02004640#endif
Evan Broderbe554312013-06-27 00:05:25 -07004641 ok = ssl_sock_srv_hostcheck(str, servername);
4642 OPENSSL_free(str);
4643 }
4644 }
4645 }
Emeric Brun4ad50a42013-09-17 15:19:54 +02004646 sk_GENERAL_NAME_pop_free(alt_names, GENERAL_NAME_free);
Evan Broderbe554312013-06-27 00:05:25 -07004647 }
4648
4649 cert_subject = X509_get_subject_name(cert);
4650 i = -1;
4651 while (!ok && (i = X509_NAME_get_index_by_NID(cert_subject, NID_commonName, i)) != -1) {
4652 X509_NAME_ENTRY *entry = X509_NAME_get_entry(cert_subject, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02004653 ASN1_STRING *value;
4654 value = X509_NAME_ENTRY_get_data(entry);
4655 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
Evan Broderbe554312013-06-27 00:05:25 -07004656 ok = ssl_sock_srv_hostcheck(str, servername);
4657 OPENSSL_free(str);
4658 }
4659 }
4660
Willy Tarreau71d058c2017-07-26 20:09:56 +02004661 /* report the mismatch and indicate if SNI was used or not */
4662 if (!ok && !conn->err_code)
4663 conn->err_code = sni ? CO_ER_SSL_MISMATCH_SNI : CO_ER_SSL_MISMATCH;
Evan Broderbe554312013-06-27 00:05:25 -07004664 return ok;
4665}
4666
Emeric Brun94324a42012-10-11 14:00:19 +02004667/* prepare ssl context from servers options. Returns an error count */
Willy Tarreau03209342016-12-22 17:08:28 +01004668int ssl_sock_prepare_srv_ctx(struct server *srv)
Emeric Brun94324a42012-10-11 14:00:19 +02004669{
Willy Tarreau03209342016-12-22 17:08:28 +01004670 struct proxy *curproxy = srv->proxy;
Emeric Brun94324a42012-10-11 14:00:19 +02004671 int cfgerr = 0;
Remi Gacogneaf5c3da2014-05-19 10:29:58 +02004672 long options =
Emeric Brun94324a42012-10-11 14:00:19 +02004673 SSL_OP_ALL | /* all known workarounds for bugs */
4674 SSL_OP_NO_SSLv2 |
4675 SSL_OP_NO_COMPRESSION;
Remi Gacogneaf5c3da2014-05-19 10:29:58 +02004676 long mode =
Emeric Brun94324a42012-10-11 14:00:19 +02004677 SSL_MODE_ENABLE_PARTIAL_WRITE |
4678 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
Willy Tarreau396a1862014-11-13 14:06:52 +01004679 SSL_MODE_RELEASE_BUFFERS |
4680 SSL_MODE_SMALL_BUFFERS;
Emeric Brun850efd52014-01-29 12:24:34 +01004681 int verify = SSL_VERIFY_NONE;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004682 SSL_CTX *ctx = NULL;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004683 struct tls_version_filter *conf_ssl_methods = &srv->ssl_ctx.methods;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004684 int i, min, max, hole;
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004685 int flags = MC_SSL_O_ALL;
Emeric Brun94324a42012-10-11 14:00:19 +02004686
Thierry Fournier383085f2013-01-24 14:15:43 +01004687 /* Make sure openssl opens /dev/urandom before the chroot */
4688 if (!ssl_initialize_random()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004689 ha_alert("OpenSSL random data generator initialization failed.\n");
Thierry Fournier383085f2013-01-24 14:15:43 +01004690 cfgerr++;
4691 }
4692
Willy Tarreaufce03112015-01-15 21:32:40 +01004693 /* Automatic memory computations need to know we use SSL there */
4694 global.ssl_used_backend = 1;
4695
4696 /* Initiate SSL context for current server */
Emeric Brun821bb9b2017-06-15 16:37:39 +02004697 if (!srv->ssl_ctx.reused_sess) {
Olivier Houcharde6060c52017-11-16 17:42:52 +01004698 if ((srv->ssl_ctx.reused_sess = calloc(1, global.nbthread*sizeof(*srv->ssl_ctx.reused_sess))) == NULL) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004699 ha_alert("Proxy '%s', server '%s' [%s:%d] out of memory.\n",
4700 curproxy->id, srv->id,
4701 srv->conf.file, srv->conf.line);
Emeric Brun821bb9b2017-06-15 16:37:39 +02004702 cfgerr++;
4703 return cfgerr;
4704 }
4705 }
Emeric Brun94324a42012-10-11 14:00:19 +02004706 if (srv->use_ssl)
4707 srv->xprt = &ssl_sock;
4708 if (srv->check.use_ssl)
Cyril Bonté9ce13112014-11-15 22:41:27 +01004709 srv->check.xprt = &ssl_sock;
Emeric Brun94324a42012-10-11 14:00:19 +02004710
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004711 ctx = SSL_CTX_new(SSLv23_client_method());
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004712 if (!ctx) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004713 ha_alert("config : %s '%s', server '%s': unable to allocate ssl context.\n",
4714 proxy_type_str(curproxy), curproxy->id,
4715 srv->id);
Emeric Brun94324a42012-10-11 14:00:19 +02004716 cfgerr++;
4717 return cfgerr;
4718 }
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004719
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004720 if (conf_ssl_methods->flags && (conf_ssl_methods->min || conf_ssl_methods->max))
Christopher Faulet767a84b2017-11-24 16:50:31 +01004721 ha_warning("config : %s '%s': no-sslv3/no-tlsv1x are ignored for server '%s'. "
4722 "Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
4723 proxy_type_str(curproxy), curproxy->id, srv->id);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004724 else
4725 flags = conf_ssl_methods->flags;
4726
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004727 /* Real min and max should be determinate with configuration and openssl's capabilities */
4728 if (conf_ssl_methods->min)
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004729 flags |= (methodVersions[conf_ssl_methods->min].flag - 1);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004730 if (conf_ssl_methods->max)
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004731 flags |= ~((methodVersions[conf_ssl_methods->max].flag << 1) - 1);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004732
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004733 /* find min, max and holes */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004734 min = max = CONF_TLSV_NONE;
4735 hole = 0;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004736 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004737 /* version is in openssl && version not disable in configuration */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004738 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004739 if (min) {
4740 if (hole) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004741 ha_warning("config : %s '%s': SSL/TLS versions range not contiguous for server '%s'. "
4742 "Hole find for %s. Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
4743 proxy_type_str(curproxy), curproxy->id, srv->id,
4744 methodVersions[hole].name);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004745 hole = 0;
4746 }
4747 max = i;
4748 }
4749 else {
4750 min = max = i;
4751 }
4752 }
4753 else {
4754 if (min)
4755 hole = i;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004756 }
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004757 if (!min) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004758 ha_alert("config : %s '%s': all SSL/TLS versions are disabled for server '%s'.\n",
4759 proxy_type_str(curproxy), curproxy->id, srv->id);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004760 cfgerr += 1;
4761 }
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004762
Willy Tarreau9a1ab082019-05-09 13:26:41 +02004763#if (HA_OPENSSL_VERSION_NUMBER < 0x1010000fL)
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004764 /* Keep force-xxx implementation as it is in older haproxy. It's a
Joseph Herlant017b3da2018-11-15 09:07:59 -08004765 precautionary measure to avoid any surprise with older openssl version. */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004766 if (min == max)
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004767 methodVersions[min].ctx_set_version(ctx, SET_CLIENT);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004768 else
4769 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
4770 if (flags & methodVersions[i].flag)
4771 options |= methodVersions[i].option;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004772#else /* openssl >= 1.1.0 */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004773 /* set the max_version is required to cap TLS version or activate new TLS (v1.3) */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004774 methodVersions[min].ctx_set_version(ctx, SET_MIN);
4775 methodVersions[max].ctx_set_version(ctx, SET_MAX);
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004776#endif
4777
4778 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLS_TICKETS)
4779 options |= SSL_OP_NO_TICKET;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004780 SSL_CTX_set_options(ctx, options);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004781
Willy Tarreau5db847a2019-05-09 14:13:35 +02004782#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004783 if (global_ssl.async)
4784 mode |= SSL_MODE_ASYNC;
4785#endif
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004786 SSL_CTX_set_mode(ctx, mode);
4787 srv->ssl_ctx.ctx = ctx;
4788
Emeric Bruna7aa3092012-10-26 12:58:00 +02004789 if (srv->ssl_ctx.client_crt) {
4790 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 +01004791 ha_alert("config : %s '%s', server '%s': unable to load SSL private key from PEM file '%s'.\n",
4792 proxy_type_str(curproxy), curproxy->id,
4793 srv->id, srv->ssl_ctx.client_crt);
Emeric Bruna7aa3092012-10-26 12:58:00 +02004794 cfgerr++;
4795 }
4796 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 +01004797 ha_alert("config : %s '%s', server '%s': unable to load ssl certificate from PEM file '%s'.\n",
4798 proxy_type_str(curproxy), curproxy->id,
4799 srv->id, srv->ssl_ctx.client_crt);
Emeric Bruna7aa3092012-10-26 12:58:00 +02004800 cfgerr++;
4801 }
4802 else if (SSL_CTX_check_private_key(srv->ssl_ctx.ctx) <= 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004803 ha_alert("config : %s '%s', server '%s': inconsistencies between private key and certificate loaded from PEM file '%s'.\n",
4804 proxy_type_str(curproxy), curproxy->id,
4805 srv->id, srv->ssl_ctx.client_crt);
Emeric Bruna7aa3092012-10-26 12:58:00 +02004806 cfgerr++;
4807 }
4808 }
Emeric Brun94324a42012-10-11 14:00:19 +02004809
Emeric Brun850efd52014-01-29 12:24:34 +01004810 if (global.ssl_server_verify == SSL_SERVER_VERIFY_REQUIRED)
4811 verify = SSL_VERIFY_PEER;
Emeric Brun850efd52014-01-29 12:24:34 +01004812 switch (srv->ssl_ctx.verify) {
4813 case SSL_SOCK_VERIFY_NONE:
4814 verify = SSL_VERIFY_NONE;
4815 break;
4816 case SSL_SOCK_VERIFY_REQUIRED:
4817 verify = SSL_VERIFY_PEER;
4818 break;
4819 }
Evan Broderbe554312013-06-27 00:05:25 -07004820 SSL_CTX_set_verify(srv->ssl_ctx.ctx,
Emeric Brun850efd52014-01-29 12:24:34 +01004821 verify,
Willy Tarreau2ab88672017-07-05 18:23:03 +02004822 (srv->ssl_ctx.verify_host || (verify & SSL_VERIFY_PEER)) ? ssl_sock_srv_verifycbk : NULL);
Emeric Brun850efd52014-01-29 12:24:34 +01004823 if (verify & SSL_VERIFY_PEER) {
Emeric Brunef42d922012-10-11 16:11:36 +02004824 if (srv->ssl_ctx.ca_file) {
4825 /* load CAfile to verify */
4826 if (!SSL_CTX_load_verify_locations(srv->ssl_ctx.ctx, srv->ssl_ctx.ca_file, NULL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004827 ha_alert("Proxy '%s', server '%s' [%s:%d] unable to load CA file '%s'.\n",
4828 curproxy->id, srv->id,
4829 srv->conf.file, srv->conf.line, srv->ssl_ctx.ca_file);
Emeric Brunef42d922012-10-11 16:11:36 +02004830 cfgerr++;
4831 }
4832 }
Emeric Brun850efd52014-01-29 12:24:34 +01004833 else {
4834 if (global.ssl_server_verify == SSL_SERVER_VERIFY_REQUIRED)
Christopher Faulet767a84b2017-11-24 16:50:31 +01004835 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",
4836 curproxy->id, srv->id,
4837 srv->conf.file, srv->conf.line);
Emeric Brun850efd52014-01-29 12:24:34 +01004838 else
Christopher Faulet767a84b2017-11-24 16:50:31 +01004839 ha_alert("Proxy '%s', server '%s' [%s:%d] verify is enabled but no CA file specified.\n",
4840 curproxy->id, srv->id,
4841 srv->conf.file, srv->conf.line);
Emeric Brun850efd52014-01-29 12:24:34 +01004842 cfgerr++;
4843 }
Emeric Brunef42d922012-10-11 16:11:36 +02004844#ifdef X509_V_FLAG_CRL_CHECK
4845 if (srv->ssl_ctx.crl_file) {
4846 X509_STORE *store = SSL_CTX_get_cert_store(srv->ssl_ctx.ctx);
4847
4848 if (!store || !X509_STORE_load_locations(store, srv->ssl_ctx.crl_file, NULL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004849 ha_alert("Proxy '%s', server '%s' [%s:%d] unable to configure CRL file '%s'.\n",
4850 curproxy->id, srv->id,
4851 srv->conf.file, srv->conf.line, srv->ssl_ctx.crl_file);
Emeric Brunef42d922012-10-11 16:11:36 +02004852 cfgerr++;
4853 }
4854 else {
4855 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
4856 }
4857 }
4858#endif
4859 }
4860
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004861 SSL_CTX_set_session_cache_mode(srv->ssl_ctx.ctx, SSL_SESS_CACHE_CLIENT |
4862 SSL_SESS_CACHE_NO_INTERNAL_STORE);
4863 SSL_CTX_sess_set_new_cb(srv->ssl_ctx.ctx, ssl_sess_new_srv_cb);
Emeric Brun94324a42012-10-11 14:00:19 +02004864 if (srv->ssl_ctx.ciphers &&
4865 !SSL_CTX_set_cipher_list(srv->ssl_ctx.ctx, srv->ssl_ctx.ciphers)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004866 ha_alert("Proxy '%s', server '%s' [%s:%d] : unable to set SSL cipher list to '%s'.\n",
4867 curproxy->id, srv->id,
4868 srv->conf.file, srv->conf.line, srv->ssl_ctx.ciphers);
Emeric Brun94324a42012-10-11 14:00:19 +02004869 cfgerr++;
4870 }
Dirkjan Bussink415150f2018-09-14 11:14:21 +02004871
Emmanuel Hocdet839af572019-05-14 16:27:35 +02004872#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02004873 if (srv->ssl_ctx.ciphersuites &&
Pierre Cheynierbc34cd12019-03-21 16:15:47 +00004874 !SSL_CTX_set_ciphersuites(srv->ssl_ctx.ctx, srv->ssl_ctx.ciphersuites)) {
Dirkjan Bussink415150f2018-09-14 11:14:21 +02004875 ha_alert("Proxy '%s', server '%s' [%s:%d] : unable to set TLS 1.3 cipher suites to '%s'.\n",
4876 curproxy->id, srv->id,
4877 srv->conf.file, srv->conf.line, srv->ssl_ctx.ciphersuites);
4878 cfgerr++;
4879 }
4880#endif
Olivier Houchardc7566002018-11-20 23:33:50 +01004881#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
4882 if (srv->ssl_ctx.npn_str)
4883 SSL_CTX_set_next_proto_select_cb(ctx, ssl_sock_srv_select_protos, srv);
4884#endif
4885#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
4886 if (srv->ssl_ctx.alpn_str)
4887 SSL_CTX_set_alpn_protos(ctx, (unsigned char *)srv->ssl_ctx.alpn_str, srv->ssl_ctx.alpn_len);
4888#endif
4889
Emeric Brun94324a42012-10-11 14:00:19 +02004890
4891 return cfgerr;
4892}
4893
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004894/* Walks down the two trees in bind_conf and prepares all certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +02004895 * be NULL, in which case nothing is done. Returns the number of errors
4896 * encountered.
4897 */
Willy Tarreau03209342016-12-22 17:08:28 +01004898int ssl_sock_prepare_all_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02004899{
4900 struct ebmb_node *node;
4901 struct sni_ctx *sni;
4902 int err = 0;
4903
Willy Tarreaufce03112015-01-15 21:32:40 +01004904 /* Automatic memory computations need to know we use SSL there */
4905 global.ssl_used_frontend = 1;
4906
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004907 /* Make sure openssl opens /dev/urandom before the chroot */
4908 if (!ssl_initialize_random()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004909 ha_alert("OpenSSL random data generator initialization failed.\n");
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004910 err++;
4911 }
4912 /* Create initial_ctx used to start the ssl connection before do switchctx */
4913 if (!bind_conf->initial_ctx) {
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004914 err += ssl_sock_initial_ctx(bind_conf);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004915 /* It should not be necessary to call this function, but it's
4916 necessary first to check and move all initialisation related
4917 to initial_ctx in ssl_sock_initial_ctx. */
4918 err += ssl_sock_prepare_ctx(bind_conf, NULL, bind_conf->initial_ctx);
4919 }
Emeric Brun0bed9942014-10-30 19:25:24 +01004920 if (bind_conf->default_ctx)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004921 err += ssl_sock_prepare_ctx(bind_conf, bind_conf->default_ssl_conf, bind_conf->default_ctx);
Emeric Brun0bed9942014-10-30 19:25:24 +01004922
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004923 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004924 while (node) {
4925 sni = ebmb_entry(node, struct sni_ctx, name);
Emeric Brun0bed9942014-10-30 19:25:24 +01004926 if (!sni->order && sni->ctx != bind_conf->default_ctx)
4927 /* only initialize the CTX on its first occurrence and
4928 if it is not the default_ctx */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004929 err += ssl_sock_prepare_ctx(bind_conf, sni->conf, sni->ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004930 node = ebmb_next(node);
4931 }
4932
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004933 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004934 while (node) {
4935 sni = ebmb_entry(node, struct sni_ctx, name);
Emeric Brun0bed9942014-10-30 19:25:24 +01004936 if (!sni->order && sni->ctx != bind_conf->default_ctx)
4937 /* only initialize the CTX on its first occurrence and
4938 if it is not the default_ctx */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004939 err += ssl_sock_prepare_ctx(bind_conf, sni->conf, sni->ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004940 node = ebmb_next(node);
4941 }
4942 return err;
4943}
4944
Willy Tarreau55d37912016-12-21 23:38:39 +01004945/* Prepares all the contexts for a bind_conf and allocates the shared SSL
4946 * context if needed. Returns < 0 on error, 0 on success. The warnings and
4947 * alerts are directly emitted since the rest of the stack does it below.
4948 */
4949int ssl_sock_prepare_bind_conf(struct bind_conf *bind_conf)
4950{
4951 struct proxy *px = bind_conf->frontend;
4952 int alloc_ctx;
4953 int err;
4954
4955 if (!bind_conf->is_ssl) {
4956 if (bind_conf->default_ctx) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004957 ha_warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
4958 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreau55d37912016-12-21 23:38:39 +01004959 }
4960 return 0;
4961 }
4962 if (!bind_conf->default_ctx) {
Emmanuel Hocdetaa0d6372017-08-09 11:24:25 +02004963 if (bind_conf->strict_sni && !bind_conf->generate_certs) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004964 ha_warning("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d], ssl connections will fail (use 'crt').\n",
4965 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetaa0d6372017-08-09 11:24:25 +02004966 }
4967 else {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004968 ha_alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
4969 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetaa0d6372017-08-09 11:24:25 +02004970 return -1;
4971 }
Willy Tarreau55d37912016-12-21 23:38:39 +01004972 }
William Lallemandc61c0b32017-12-04 18:46:39 +01004973 if (!ssl_shctx && global.tune.sslcachesize) {
William Lallemandc3cd35f2017-11-28 11:04:43 +01004974 alloc_ctx = shctx_init(&ssl_shctx, global.tune.sslcachesize,
Frédéric Lécailleb7838af2018-10-22 16:21:39 +02004975 sizeof(struct sh_ssl_sess_hdr) + SHSESS_BLOCK_MIN_SIZE, -1,
William Lallemandc3cd35f2017-11-28 11:04:43 +01004976 sizeof(*sh_ssl_sess_tree),
4977 ((global.nbthread > 1) || (!global_ssl.private_cache && (global.nbproc > 1))) ? 1 : 0);
Frédéric Lécaille4c8aa112018-10-25 20:22:46 +02004978 if (alloc_ctx <= 0) {
William Lallemandc3cd35f2017-11-28 11:04:43 +01004979 if (alloc_ctx == SHCTX_E_INIT_LOCK)
4980 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");
4981 else
4982 ha_alert("Unable to allocate SSL session cache.\n");
4983 return -1;
4984 }
4985 /* free block callback */
4986 ssl_shctx->free_block = sh_ssl_sess_free_blocks;
4987 /* init the root tree within the extra space */
4988 sh_ssl_sess_tree = (void *)ssl_shctx + sizeof(struct shared_context);
4989 *sh_ssl_sess_tree = EB_ROOT_UNIQUE;
Willy Tarreau55d37912016-12-21 23:38:39 +01004990 }
Willy Tarreau55d37912016-12-21 23:38:39 +01004991 err = 0;
4992 /* initialize all certificate contexts */
4993 err += ssl_sock_prepare_all_ctx(bind_conf);
4994
4995 /* initialize CA variables if the certificates generation is enabled */
4996 err += ssl_sock_load_ca(bind_conf);
4997
4998 return -err;
4999}
Christopher Faulet77fe80c2015-07-29 13:02:40 +02005000
5001/* release ssl context allocated for servers. */
5002void ssl_sock_free_srv_ctx(struct server *srv)
5003{
Olivier Houchardc7566002018-11-20 23:33:50 +01005004#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
5005 if (srv->ssl_ctx.alpn_str)
5006 free(srv->ssl_ctx.alpn_str);
5007#endif
Lukas Tribusda95fd92018-11-25 13:21:27 +01005008#ifdef OPENSSL_NPN_NEGOTIATED
Olivier Houchardc7566002018-11-20 23:33:50 +01005009 if (srv->ssl_ctx.npn_str)
5010 free(srv->ssl_ctx.npn_str);
Lukas Tribus7706b852018-11-26 22:57:17 +01005011#endif
Christopher Faulet77fe80c2015-07-29 13:02:40 +02005012 if (srv->ssl_ctx.ctx)
5013 SSL_CTX_free(srv->ssl_ctx.ctx);
5014}
5015
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005016/* Walks down the two trees in bind_conf and frees all the certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +02005017 * be NULL, in which case nothing is done. The default_ctx is nullified too.
5018 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005019void ssl_sock_free_all_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02005020{
5021 struct ebmb_node *node, *back;
5022 struct sni_ctx *sni;
5023
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005024 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02005025 while (node) {
5026 sni = ebmb_entry(node, struct sni_ctx, name);
5027 back = ebmb_next(node);
5028 ebmb_delete(node);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005029 if (!sni->order) { /* only free the CTX on its first occurrence */
Emeric Brunfc0421f2012-09-07 17:30:07 +02005030 SSL_CTX_free(sni->ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005031 ssl_sock_free_ssl_conf(sni->conf);
5032 free(sni->conf);
5033 sni->conf = NULL;
5034 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02005035 free(sni);
5036 node = back;
5037 }
5038
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005039 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02005040 while (node) {
5041 sni = ebmb_entry(node, struct sni_ctx, name);
5042 back = ebmb_next(node);
5043 ebmb_delete(node);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005044 if (!sni->order) { /* only free the CTX on its first occurrence */
Emeric Brunfc0421f2012-09-07 17:30:07 +02005045 SSL_CTX_free(sni->ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005046 ssl_sock_free_ssl_conf(sni->conf);
5047 free(sni->conf);
5048 sni->conf = NULL;
5049 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02005050 free(sni);
5051 node = back;
5052 }
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01005053 SSL_CTX_free(bind_conf->initial_ctx);
5054 bind_conf->initial_ctx = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005055 bind_conf->default_ctx = NULL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005056 bind_conf->default_ssl_conf = NULL;
Emeric Brune1f38db2012-09-03 20:36:47 +02005057}
5058
Willy Tarreau795cdab2016-12-22 17:30:54 +01005059/* Destroys all the contexts for a bind_conf. This is used during deinit(). */
5060void ssl_sock_destroy_bind_conf(struct bind_conf *bind_conf)
5061{
5062 ssl_sock_free_ca(bind_conf);
5063 ssl_sock_free_all_ctx(bind_conf);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005064 ssl_sock_free_ssl_conf(&bind_conf->ssl_conf);
Willy Tarreau795cdab2016-12-22 17:30:54 +01005065 free(bind_conf->ca_sign_file);
5066 free(bind_conf->ca_sign_pass);
Willy Tarreau17b4aa12018-07-17 10:05:32 +02005067 if (bind_conf->keys_ref && !--bind_conf->keys_ref->refcount) {
Willy Tarreau795cdab2016-12-22 17:30:54 +01005068 free(bind_conf->keys_ref->filename);
5069 free(bind_conf->keys_ref->tlskeys);
5070 LIST_DEL(&bind_conf->keys_ref->list);
5071 free(bind_conf->keys_ref);
5072 }
5073 bind_conf->keys_ref = NULL;
Willy Tarreau795cdab2016-12-22 17:30:54 +01005074 bind_conf->ca_sign_pass = NULL;
5075 bind_conf->ca_sign_file = NULL;
Willy Tarreau795cdab2016-12-22 17:30:54 +01005076}
5077
Christopher Faulet31af49d2015-06-09 17:29:50 +02005078/* Load CA cert file and private key used to generate certificates */
5079int
Willy Tarreau03209342016-12-22 17:08:28 +01005080ssl_sock_load_ca(struct bind_conf *bind_conf)
Christopher Faulet31af49d2015-06-09 17:29:50 +02005081{
Willy Tarreau03209342016-12-22 17:08:28 +01005082 struct proxy *px = bind_conf->frontend;
Christopher Faulet31af49d2015-06-09 17:29:50 +02005083 FILE *fp;
5084 X509 *cacert = NULL;
5085 EVP_PKEY *capkey = NULL;
5086 int err = 0;
5087
Christopher Fauletf8bb0ce2017-09-15 09:52:49 +02005088 if (!bind_conf->generate_certs)
Christopher Faulet31af49d2015-06-09 17:29:50 +02005089 return err;
5090
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005091#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Emeric Brun821bb9b2017-06-15 16:37:39 +02005092 if (global_ssl.ctx_cache) {
Willy Tarreauef934602016-12-22 23:12:01 +01005093 ssl_ctx_lru_tree = lru64_new(global_ssl.ctx_cache);
Emeric Brun821bb9b2017-06-15 16:37:39 +02005094 }
Christopher Fauletd2cab922015-07-28 16:03:47 +02005095 ssl_ctx_lru_seed = (unsigned int)time(NULL);
Emeric Brun821bb9b2017-06-15 16:37:39 +02005096 ssl_ctx_serial = now_ms;
Willy Tarreaua84c2672015-10-09 12:10:13 +02005097#endif
Christopher Fauletd2cab922015-07-28 16:03:47 +02005098
Christopher Faulet31af49d2015-06-09 17:29:50 +02005099 if (!bind_conf->ca_sign_file) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005100 ha_alert("Proxy '%s': cannot enable certificate generation, "
5101 "no CA certificate File configured at [%s:%d].\n",
5102 px->id, bind_conf->file, bind_conf->line);
Christopher Faulet31af49d2015-06-09 17:29:50 +02005103 goto load_error;
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005104 }
Christopher Faulet31af49d2015-06-09 17:29:50 +02005105
5106 /* read in the CA certificate */
5107 if (!(fp = fopen(bind_conf->ca_sign_file, "r"))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005108 ha_alert("Proxy '%s': Failed to read CA certificate file '%s' at [%s:%d].\n",
5109 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Faulet31af49d2015-06-09 17:29:50 +02005110 goto load_error;
5111 }
5112 if (!(cacert = PEM_read_X509(fp, NULL, NULL, NULL))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005113 ha_alert("Proxy '%s': Failed to read CA certificate file '%s' at [%s:%d].\n",
5114 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005115 goto read_error;
Christopher Faulet31af49d2015-06-09 17:29:50 +02005116 }
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005117 rewind(fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02005118 if (!(capkey = PEM_read_PrivateKey(fp, NULL, NULL, bind_conf->ca_sign_pass))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005119 ha_alert("Proxy '%s': Failed to read CA private key file '%s' at [%s:%d].\n",
5120 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005121 goto read_error;
Christopher Faulet31af49d2015-06-09 17:29:50 +02005122 }
Christopher Faulet31af49d2015-06-09 17:29:50 +02005123
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005124 fclose (fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02005125 bind_conf->ca_sign_cert = cacert;
5126 bind_conf->ca_sign_pkey = capkey;
5127 return err;
5128
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005129 read_error:
5130 fclose (fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02005131 if (capkey) EVP_PKEY_free(capkey);
5132 if (cacert) X509_free(cacert);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005133 load_error:
5134 bind_conf->generate_certs = 0;
5135 err++;
Christopher Faulet31af49d2015-06-09 17:29:50 +02005136 return err;
5137}
5138
5139/* Release CA cert and private key used to generate certificated */
5140void
5141ssl_sock_free_ca(struct bind_conf *bind_conf)
5142{
Christopher Faulet31af49d2015-06-09 17:29:50 +02005143 if (bind_conf->ca_sign_pkey)
5144 EVP_PKEY_free(bind_conf->ca_sign_pkey);
5145 if (bind_conf->ca_sign_cert)
5146 X509_free(bind_conf->ca_sign_cert);
Willy Tarreau94ff03a2016-12-22 17:57:46 +01005147 bind_conf->ca_sign_pkey = NULL;
5148 bind_conf->ca_sign_cert = NULL;
Christopher Faulet31af49d2015-06-09 17:29:50 +02005149}
5150
Emeric Brun46591952012-05-18 15:47:34 +02005151/*
5152 * This function is called if SSL * context is not yet allocated. The function
5153 * is designed to be called before any other data-layer operation and sets the
5154 * handshake flag on the connection. It is safe to call it multiple times.
5155 * It returns 0 on success and -1 in error case.
5156 */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005157static int ssl_sock_init(struct connection *conn, void **xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02005158{
Olivier Houchard66ab4982019-02-26 18:37:15 +01005159 struct ssl_sock_ctx *ctx;
Emeric Brun46591952012-05-18 15:47:34 +02005160 /* already initialized */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005161 if (*xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02005162 return 0;
5163
Willy Tarreau3c728722014-01-23 13:50:42 +01005164 if (!conn_ctrl_ready(conn))
Willy Tarreauf79c8172013-10-21 16:30:56 +02005165 return 0;
5166
Olivier Houchard66ab4982019-02-26 18:37:15 +01005167 ctx = pool_alloc(ssl_sock_ctx_pool);
5168 if (!ctx) {
5169 conn->err_code = CO_ER_SSL_NO_MEM;
5170 return -1;
5171 }
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02005172 ctx->wait_event.tasklet = tasklet_new();
5173 if (!ctx->wait_event.tasklet) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02005174 conn->err_code = CO_ER_SSL_NO_MEM;
5175 pool_free(ssl_sock_ctx_pool, ctx);
5176 return -1;
5177 }
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02005178 ctx->wait_event.tasklet->process = ssl_sock_io_cb;
5179 ctx->wait_event.tasklet->context = ctx;
Olivier Houchardea8dd942019-05-20 14:02:16 +02005180 ctx->wait_event.events = 0;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01005181 ctx->sent_early_data = 0;
5182 ctx->tmp_early_data = -1;
Olivier Houcharda8955d52019-04-07 22:00:38 +02005183 ctx->conn = conn;
Olivier Houchard81284e62019-06-06 13:21:23 +02005184 ctx->send_wait = NULL;
5185 ctx->recv_wait = NULL;
Emeric Brun87cfd662019-09-06 15:36:02 +02005186 ctx->xprt_st = 0;
5187 ctx->xprt_ctx = NULL;
Olivier Houcharda8955d52019-04-07 22:00:38 +02005188
5189 /* Only work with sockets for now, this should be adapted when we'll
5190 * add QUIC support.
5191 */
5192 ctx->xprt = xprt_get(XPRT_RAW);
Olivier Houchard19afb272019-05-23 18:24:07 +02005193 if (ctx->xprt->init) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02005194 if (ctx->xprt->init(conn, &ctx->xprt_ctx) != 0)
5195 goto err;
Olivier Houchard19afb272019-05-23 18:24:07 +02005196 }
Olivier Houchard66ab4982019-02-26 18:37:15 +01005197
Willy Tarreau20879a02012-12-03 16:32:10 +01005198 if (global.maxsslconn && sslconns >= global.maxsslconn) {
5199 conn->err_code = CO_ER_SSL_TOO_MANY;
Olivier Houchardea8dd942019-05-20 14:02:16 +02005200 goto err;
Willy Tarreau20879a02012-12-03 16:32:10 +01005201 }
Willy Tarreau403edff2012-09-06 11:58:37 +02005202
Emeric Brun46591952012-05-18 15:47:34 +02005203 /* If it is in client mode initiate SSL session
5204 in connect state otherwise accept state */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01005205 if (objt_server(conn->target)) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005206 int may_retry = 1;
5207
5208 retry_connect:
Emeric Brun46591952012-05-18 15:47:34 +02005209 /* Alloc a new SSL session ctx */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005210 ctx->ssl = SSL_new(__objt_server(conn->target)->ssl_ctx.ctx);
5211 if (!ctx->ssl) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005212 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005213 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005214 goto retry_connect;
5215 }
Willy Tarreau20879a02012-12-03 16:32:10 +01005216 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01005217 goto err;
Willy Tarreau20879a02012-12-03 16:32:10 +01005218 }
Olivier Houcharda8955d52019-04-07 22:00:38 +02005219 ctx->bio = BIO_new(ha_meth);
5220 if (!ctx->bio) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005221 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005222 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005223 goto retry_connect;
5224 }
Emeric Brun55476152014-11-12 17:35:37 +01005225 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01005226 goto err;
Emeric Brun55476152014-11-12 17:35:37 +01005227 }
Olivier Houcharda8955d52019-04-07 22:00:38 +02005228 BIO_set_data(ctx->bio, ctx);
Olivier Houcharda8955d52019-04-07 22:00:38 +02005229 SSL_set_bio(ctx->ssl, ctx->bio, ctx->bio);
Emeric Brun46591952012-05-18 15:47:34 +02005230
Evan Broderbe554312013-06-27 00:05:25 -07005231 /* set connection pointer */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005232 if (!SSL_set_ex_data(ctx->ssl, ssl_app_data_index, conn)) {
5233 SSL_free(ctx->ssl);
5234 ctx->ssl = NULL;
Emeric Brun55476152014-11-12 17:35:37 +01005235 conn->xprt_ctx = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005236 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005237 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005238 goto retry_connect;
5239 }
Emeric Brun55476152014-11-12 17:35:37 +01005240 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01005241 goto err;
Emeric Brun55476152014-11-12 17:35:37 +01005242 }
5243
Olivier Houchard66ab4982019-02-26 18:37:15 +01005244 SSL_set_connect_state(ctx->ssl);
Willy Tarreau07d94e42018-09-20 10:57:52 +02005245 if (__objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr) {
5246 const unsigned char *ptr = __objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr;
5247 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 +01005248 if (sess && !SSL_set_session(ctx->ssl, sess)) {
Olivier Houcharde6060c52017-11-16 17:42:52 +01005249 SSL_SESSION_free(sess);
Willy Tarreau07d94e42018-09-20 10:57:52 +02005250 free(__objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr);
5251 __objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr = NULL;
Olivier Houcharde6060c52017-11-16 17:42:52 +01005252 } else if (sess) {
5253 SSL_SESSION_free(sess);
Emeric Brun55476152014-11-12 17:35:37 +01005254 }
5255 }
Evan Broderbe554312013-06-27 00:05:25 -07005256
Emeric Brun46591952012-05-18 15:47:34 +02005257 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +02005258 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Willy Tarreau403edff2012-09-06 11:58:37 +02005259
Olivier Houchard2be5a4c2019-03-08 18:54:43 +01005260 _HA_ATOMIC_ADD(&sslconns, 1);
5261 _HA_ATOMIC_ADD(&totalsslconns, 1);
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005262 *xprt_ctx = ctx;
Olivier Houchardea8dd942019-05-20 14:02:16 +02005263 /* Start the handshake */
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02005264 tasklet_wakeup(ctx->wait_event.tasklet);
Olivier Houchardea8dd942019-05-20 14:02:16 +02005265 if (conn->flags & CO_FL_ERROR)
5266 goto err;
Emeric Brun46591952012-05-18 15:47:34 +02005267 return 0;
5268 }
Willy Tarreau3fdb3662012-11-12 00:42:33 +01005269 else if (objt_listener(conn->target)) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005270 int may_retry = 1;
5271
5272 retry_accept:
Emeric Brun46591952012-05-18 15:47:34 +02005273 /* Alloc a new SSL session ctx */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005274 ctx->ssl = SSL_new(__objt_listener(conn->target)->bind_conf->initial_ctx);
5275 if (!ctx->ssl) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005276 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005277 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005278 goto retry_accept;
5279 }
Willy Tarreau20879a02012-12-03 16:32:10 +01005280 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01005281 goto err;
Willy Tarreau20879a02012-12-03 16:32:10 +01005282 }
Emeric Brun46591952012-05-18 15:47:34 +02005283
Olivier Houcharda8955d52019-04-07 22:00:38 +02005284 ctx->bio = BIO_new(ha_meth);
5285 if (!ctx->bio) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005286 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005287 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005288 goto retry_accept;
5289 }
Emeric Brun55476152014-11-12 17:35:37 +01005290 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01005291 goto err;
Emeric Brun55476152014-11-12 17:35:37 +01005292 }
Olivier Houcharda8955d52019-04-07 22:00:38 +02005293 BIO_set_data(ctx->bio, ctx);
Olivier Houcharda8955d52019-04-07 22:00:38 +02005294 SSL_set_bio(ctx->ssl, ctx->bio, ctx->bio);
Emeric Brun46591952012-05-18 15:47:34 +02005295
Emeric Brune1f38db2012-09-03 20:36:47 +02005296 /* set connection pointer */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005297 if (!SSL_set_ex_data(ctx->ssl, ssl_app_data_index, conn)) {
5298 SSL_free(ctx->ssl);
5299 ctx->ssl = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005300 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005301 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005302 goto retry_accept;
5303 }
Emeric Brun55476152014-11-12 17:35:37 +01005304 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01005305 goto err;
Emeric Brun55476152014-11-12 17:35:37 +01005306 }
5307
Olivier Houchard66ab4982019-02-26 18:37:15 +01005308 SSL_set_accept_state(ctx->ssl);
Emeric Brune1f38db2012-09-03 20:36:47 +02005309
Emeric Brun46591952012-05-18 15:47:34 +02005310 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +02005311 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Emmanuel Hocdet510fce52019-08-05 18:04:16 +02005312#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Olivier Houchardc2aae742017-09-22 18:26:28 +02005313 conn->flags |= CO_FL_EARLY_SSL_HS;
5314#endif
Willy Tarreau403edff2012-09-06 11:58:37 +02005315
Olivier Houchard2be5a4c2019-03-08 18:54:43 +01005316 _HA_ATOMIC_ADD(&sslconns, 1);
5317 _HA_ATOMIC_ADD(&totalsslconns, 1);
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005318 *xprt_ctx = ctx;
Olivier Houchardea8dd942019-05-20 14:02:16 +02005319 /* Start the handshake */
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02005320 tasklet_wakeup(ctx->wait_event.tasklet);
Olivier Houchardea8dd942019-05-20 14:02:16 +02005321 if (conn->flags & CO_FL_ERROR)
5322 goto err;
Emeric Brun46591952012-05-18 15:47:34 +02005323 return 0;
5324 }
5325 /* don't know how to handle such a target */
Willy Tarreau20879a02012-12-03 16:32:10 +01005326 conn->err_code = CO_ER_SSL_NO_TARGET;
Olivier Houchard66ab4982019-02-26 18:37:15 +01005327err:
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02005328 if (ctx && ctx->wait_event.tasklet)
5329 tasklet_free(ctx->wait_event.tasklet);
Olivier Houchard66ab4982019-02-26 18:37:15 +01005330 pool_free(ssl_sock_ctx_pool, ctx);
Emeric Brun46591952012-05-18 15:47:34 +02005331 return -1;
5332}
5333
5334
5335/* This is the callback which is used when an SSL handshake is pending. It
5336 * updates the FD status if it wants some polling before being called again.
5337 * It returns 0 if it fails in a fatal way or needs to poll to go further,
5338 * otherwise it returns non-zero and removes itself from the connection's
5339 * flags (the bit is provided in <flag> by the caller).
5340 */
Olivier Houchard000694c2019-05-23 14:45:12 +02005341static int ssl_sock_handshake(struct connection *conn, unsigned int flag)
Emeric Brun46591952012-05-18 15:47:34 +02005342{
Olivier Houchard66ab4982019-02-26 18:37:15 +01005343 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
Emeric Brun46591952012-05-18 15:47:34 +02005344 int ret;
5345
Willy Tarreau3c728722014-01-23 13:50:42 +01005346 if (!conn_ctrl_ready(conn))
Willy Tarreauf79c8172013-10-21 16:30:56 +02005347 return 0;
5348
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005349 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02005350 goto out_error;
5351
Willy Tarreau5db847a2019-05-09 14:13:35 +02005352#if HA_OPENSSL_VERSION_NUMBER >= 0x10101000L
Olivier Houchardc2aae742017-09-22 18:26:28 +02005353 /*
5354 * Check if we have early data. If we do, we have to read them
5355 * before SSL_do_handshake() is called, And there's no way to
5356 * detect early data, except to try to read them
5357 */
5358 if (conn->flags & CO_FL_EARLY_SSL_HS) {
5359 size_t read_data;
5360
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01005361 ret = SSL_read_early_data(ctx->ssl, &ctx->tmp_early_data,
Olivier Houchardc2aae742017-09-22 18:26:28 +02005362 1, &read_data);
5363 if (ret == SSL_READ_EARLY_DATA_ERROR)
5364 goto check_error;
5365 if (ret == SSL_READ_EARLY_DATA_SUCCESS) {
5366 conn->flags &= ~(CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN);
5367 return 1;
5368 } else
5369 conn->flags &= ~CO_FL_EARLY_SSL_HS;
5370 }
5371#endif
Emeric Brun674b7432012-11-08 19:21:55 +01005372 /* If we use SSL_do_handshake to process a reneg initiated by
5373 * the remote peer, it sometimes returns SSL_ERROR_SSL.
5374 * Usually SSL_write and SSL_read are used and process implicitly
5375 * the reneg handshake.
5376 * Here we use SSL_peek as a workaround for reneg.
5377 */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005378 if ((conn->flags & CO_FL_CONNECTED) && SSL_renegotiate_pending(ctx->ssl)) {
Emeric Brun674b7432012-11-08 19:21:55 +01005379 char c;
5380
Olivier Houchard66ab4982019-02-26 18:37:15 +01005381 ret = SSL_peek(ctx->ssl, &c, 1);
Emeric Brun674b7432012-11-08 19:21:55 +01005382 if (ret <= 0) {
5383 /* handshake may have not been completed, let's find why */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005384 ret = SSL_get_error(ctx->ssl, ret);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005385
Emeric Brun674b7432012-11-08 19:21:55 +01005386 if (ret == SSL_ERROR_WANT_WRITE) {
5387 /* SSL handshake needs to write, L4 connection may not be ready */
Olivier Houchard03abf2d2019-05-28 10:12:02 +02005388 if (!(ctx->wait_event.events & SUB_RETRY_SEND))
Olivier Houchardea8dd942019-05-20 14:02:16 +02005389 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_SEND, &ctx->wait_event);
Emeric Brun674b7432012-11-08 19:21:55 +01005390 return 0;
5391 }
5392 else if (ret == SSL_ERROR_WANT_READ) {
5393 /* handshake may have been completed but we have
5394 * no more data to read.
5395 */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005396 if (!SSL_renegotiate_pending(ctx->ssl)) {
Emeric Brun674b7432012-11-08 19:21:55 +01005397 ret = 1;
5398 goto reneg_ok;
5399 }
5400 /* SSL handshake needs to read, L4 connection is ready */
Olivier Houchard03abf2d2019-05-28 10:12:02 +02005401 if (!(ctx->wait_event.events & SUB_RETRY_RECV))
Olivier Houchardea8dd942019-05-20 14:02:16 +02005402 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_RECV, &ctx->wait_event);
Emeric Brun674b7432012-11-08 19:21:55 +01005403 return 0;
5404 }
Willy Tarreau5db847a2019-05-09 14:13:35 +02005405#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005406 else if (ret == SSL_ERROR_WANT_ASYNC) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02005407 ssl_async_process_fds(ctx);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005408 return 0;
5409 }
5410#endif
Emeric Brun674b7432012-11-08 19:21:55 +01005411 else if (ret == SSL_ERROR_SYSCALL) {
5412 /* if errno is null, then connection was successfully established */
5413 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
5414 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Willy Tarreau20879a02012-12-03 16:32:10 +01005415 if (!conn->err_code) {
Lukas Tribus5db881f2019-07-08 14:29:15 +02005416#if defined(OPENSSL_IS_BORINGSSL) || defined(LIBRESSL_VERSION_NUMBER)
5417 /* do not handle empty handshakes in BoringSSL or LibreSSL */
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005418 conn->err_code = CO_ER_SSL_HANDSHAKE;
5419#else
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005420 int empty_handshake;
Willy Tarreau5db847a2019-05-09 14:13:35 +02005421#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL)
Lukas Tribus5db881f2019-07-08 14:29:15 +02005422 /* use SSL_get_state() in OpenSSL >= 1.1.0; SSL_state() is broken */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005423 OSSL_HANDSHAKE_STATE state = SSL_get_state((SSL *)ctx->ssl);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005424 empty_handshake = state == TLS_ST_BEFORE;
5425#else
Lukas Tribus5db881f2019-07-08 14:29:15 +02005426 /* access packet_length directly in OpenSSL <= 1.0.2; SSL_state() is broken */
5427 empty_handshake = !ctx->ssl->packet_length;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005428#endif
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005429 if (empty_handshake) {
Emeric Brun29f037d2014-04-25 19:05:36 +02005430 if (!errno) {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01005431 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emeric Brun29f037d2014-04-25 19:05:36 +02005432 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5433 else
5434 conn->err_code = CO_ER_SSL_EMPTY;
5435 }
5436 else {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01005437 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emeric Brun29f037d2014-04-25 19:05:36 +02005438 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5439 else
5440 conn->err_code = CO_ER_SSL_ABORT;
5441 }
5442 }
5443 else {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01005444 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emeric Brun29f037d2014-04-25 19:05:36 +02005445 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
Willy Tarreau20879a02012-12-03 16:32:10 +01005446 else
Emeric Brun29f037d2014-04-25 19:05:36 +02005447 conn->err_code = CO_ER_SSL_HANDSHAKE;
5448 }
Lukas Tribus5db881f2019-07-08 14:29:15 +02005449#endif /* BoringSSL or LibreSSL */
Willy Tarreau20879a02012-12-03 16:32:10 +01005450 }
Emeric Brun674b7432012-11-08 19:21:55 +01005451 goto out_error;
5452 }
5453 else {
5454 /* Fail on all other handshake errors */
5455 /* Note: OpenSSL may leave unread bytes in the socket's
5456 * buffer, causing an RST to be emitted upon close() on
5457 * TCP sockets. We first try to drain possibly pending
5458 * data to avoid this as much as possible.
5459 */
Willy Tarreaud85c4852015-03-13 00:40:28 +01005460 conn_sock_drain(conn);
Willy Tarreau20879a02012-12-03 16:32:10 +01005461 if (!conn->err_code)
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01005462 conn->err_code = (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT) ?
Willy Tarreauf51c6982014-04-25 20:02:39 +02005463 CO_ER_SSL_KILLED_HB : CO_ER_SSL_HANDSHAKE;
Emeric Brun674b7432012-11-08 19:21:55 +01005464 goto out_error;
5465 }
5466 }
5467 /* read some data: consider handshake completed */
5468 goto reneg_ok;
5469 }
Olivier Houchard66ab4982019-02-26 18:37:15 +01005470 ret = SSL_do_handshake(ctx->ssl);
Olivier Houchardc2aae742017-09-22 18:26:28 +02005471check_error:
Emeric Brun46591952012-05-18 15:47:34 +02005472 if (ret != 1) {
5473 /* handshake did not complete, let's find why */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005474 ret = SSL_get_error(ctx->ssl, ret);
Emeric Brun46591952012-05-18 15:47:34 +02005475
5476 if (ret == SSL_ERROR_WANT_WRITE) {
5477 /* SSL handshake needs to write, L4 connection may not be ready */
Olivier Houchard03abf2d2019-05-28 10:12:02 +02005478 if (!(ctx->wait_event.events & SUB_RETRY_SEND))
Olivier Houchardea8dd942019-05-20 14:02:16 +02005479 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_SEND, &ctx->wait_event);
Emeric Brun46591952012-05-18 15:47:34 +02005480 return 0;
5481 }
5482 else if (ret == SSL_ERROR_WANT_READ) {
5483 /* SSL handshake needs to read, L4 connection is ready */
Olivier Houchardea8dd942019-05-20 14:02:16 +02005484 if (!(ctx->wait_event.events & SUB_RETRY_RECV))
Olivier Houchardea8dd942019-05-20 14:02:16 +02005485 ctx->xprt->subscribe(conn, ctx->xprt_ctx,
5486 SUB_RETRY_RECV, &ctx->wait_event);
Emeric Brun46591952012-05-18 15:47:34 +02005487 return 0;
5488 }
Willy Tarreau5db847a2019-05-09 14:13:35 +02005489#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005490 else if (ret == SSL_ERROR_WANT_ASYNC) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02005491 ssl_async_process_fds(ctx);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005492 return 0;
5493 }
5494#endif
Willy Tarreau89230192012-09-28 20:22:13 +02005495 else if (ret == SSL_ERROR_SYSCALL) {
5496 /* if errno is null, then connection was successfully established */
5497 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
5498 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005499 if (!conn->err_code) {
Lukas Tribus5db881f2019-07-08 14:29:15 +02005500#if defined(OPENSSL_IS_BORINGSSL) || defined(LIBRESSL_VERSION_NUMBER)
5501 /* do not handle empty handshakes in BoringSSL or LibreSSL */
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005502 conn->err_code = CO_ER_SSL_HANDSHAKE;
5503#else
5504 int empty_handshake;
Willy Tarreau5db847a2019-05-09 14:13:35 +02005505#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL)
Lukas Tribus5db881f2019-07-08 14:29:15 +02005506 /* use SSL_get_state() in OpenSSL >= 1.1.0; SSL_state() is broken */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005507 OSSL_HANDSHAKE_STATE state = SSL_get_state(ctx->ssl);
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005508 empty_handshake = state == TLS_ST_BEFORE;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005509#else
Lukas Tribus5db881f2019-07-08 14:29:15 +02005510 /* access packet_length directly in OpenSSL <= 1.0.2; SSL_state() is broken */
5511 empty_handshake = !ctx->ssl->packet_length;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005512#endif
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005513 if (empty_handshake) {
5514 if (!errno) {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01005515 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005516 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5517 else
5518 conn->err_code = CO_ER_SSL_EMPTY;
5519 }
5520 else {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01005521 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005522 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5523 else
5524 conn->err_code = CO_ER_SSL_ABORT;
5525 }
Emeric Brun29f037d2014-04-25 19:05:36 +02005526 }
5527 else {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01005528 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emeric Brun29f037d2014-04-25 19:05:36 +02005529 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5530 else
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005531 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun29f037d2014-04-25 19:05:36 +02005532 }
Lukas Tribus5db881f2019-07-08 14:29:15 +02005533#endif /* BoringSSL or LibreSSL */
Emeric Brun29f037d2014-04-25 19:05:36 +02005534 }
Willy Tarreau89230192012-09-28 20:22:13 +02005535 goto out_error;
5536 }
Emeric Brun46591952012-05-18 15:47:34 +02005537 else {
5538 /* Fail on all other handshake errors */
Willy Tarreau566dc552012-10-19 20:52:18 +02005539 /* Note: OpenSSL may leave unread bytes in the socket's
5540 * buffer, causing an RST to be emitted upon close() on
5541 * TCP sockets. We first try to drain possibly pending
5542 * data to avoid this as much as possible.
5543 */
Willy Tarreaud85c4852015-03-13 00:40:28 +01005544 conn_sock_drain(conn);
Willy Tarreau20879a02012-12-03 16:32:10 +01005545 if (!conn->err_code)
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01005546 conn->err_code = (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT) ?
Willy Tarreauf51c6982014-04-25 20:02:39 +02005547 CO_ER_SSL_KILLED_HB : CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02005548 goto out_error;
5549 }
5550 }
Willy Tarreau5db847a2019-05-09 14:13:35 +02005551#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Olivier Houchard522eea72017-11-03 16:27:47 +01005552 else {
5553 /*
5554 * If the server refused the early data, we have to send a
5555 * 425 to the client, as we no longer have the data to sent
5556 * them again.
5557 */
5558 if ((conn->flags & CO_FL_EARLY_DATA) && (objt_server(conn->target))) {
Olivier Houchard66ab4982019-02-26 18:37:15 +01005559 if (SSL_get_early_data_status(ctx->ssl) == SSL_EARLY_DATA_REJECTED) {
Olivier Houchard522eea72017-11-03 16:27:47 +01005560 conn->err_code = CO_ER_SSL_EARLY_FAILED;
5561 goto out_error;
5562 }
5563 }
5564 }
5565#endif
5566
Emeric Brun46591952012-05-18 15:47:34 +02005567
Emeric Brun674b7432012-11-08 19:21:55 +01005568reneg_ok:
Emeric Brunb5e42a82017-06-06 12:35:14 +00005569
Willy Tarreau5db847a2019-05-09 14:13:35 +02005570#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00005571 /* ASYNC engine API doesn't support moving read/write
5572 * buffers. So we disable ASYNC mode right after
5573 * the handshake to avoid buffer oveflows.
5574 */
5575 if (global_ssl.async)
Olivier Houchard66ab4982019-02-26 18:37:15 +01005576 SSL_clear_mode(ctx->ssl, SSL_MODE_ASYNC);
Emeric Brunb5e42a82017-06-06 12:35:14 +00005577#endif
Emeric Brun46591952012-05-18 15:47:34 +02005578 /* Handshake succeeded */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005579 if (!SSL_session_reused(ctx->ssl)) {
Willy Tarreau0c9c2722014-05-28 12:28:58 +02005580 if (objt_server(conn->target)) {
5581 update_freq_ctr(&global.ssl_be_keys_per_sec, 1);
5582 if (global.ssl_be_keys_per_sec.curr_ctr > global.ssl_be_keys_max)
5583 global.ssl_be_keys_max = global.ssl_be_keys_per_sec.curr_ctr;
Emeric Brun46591952012-05-18 15:47:34 +02005584 }
Willy Tarreau0c9c2722014-05-28 12:28:58 +02005585 else {
5586 update_freq_ctr(&global.ssl_fe_keys_per_sec, 1);
5587 if (global.ssl_fe_keys_per_sec.curr_ctr > global.ssl_fe_keys_max)
5588 global.ssl_fe_keys_max = global.ssl_fe_keys_per_sec.curr_ctr;
5589 }
Emeric Brun46591952012-05-18 15:47:34 +02005590 }
5591
5592 /* The connection is now established at both layers, it's time to leave */
5593 conn->flags &= ~(flag | CO_FL_WAIT_L4_CONN | CO_FL_WAIT_L6_CONN);
5594 return 1;
5595
5596 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01005597 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02005598 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01005599 ERR_clear_error();
5600
Emeric Brun9fa89732012-10-04 17:09:56 +02005601 /* free resumed session if exists */
Willy Tarreau07d94e42018-09-20 10:57:52 +02005602 if (objt_server(conn->target) && __objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr) {
5603 free(__objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr);
5604 __objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr = NULL;
Emeric Brun9fa89732012-10-04 17:09:56 +02005605 }
5606
Emeric Brun46591952012-05-18 15:47:34 +02005607 /* Fail on all other handshake errors */
5608 conn->flags |= CO_FL_ERROR;
Willy Tarreau20879a02012-12-03 16:32:10 +01005609 if (!conn->err_code)
5610 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02005611 return 0;
5612}
5613
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005614static int ssl_subscribe(struct connection *conn, void *xprt_ctx, int event_type, void *param)
Olivier Houcharddf357842019-03-21 16:30:07 +01005615{
Olivier Houchardea8dd942019-05-20 14:02:16 +02005616 struct wait_event *sw;
5617 struct ssl_sock_ctx *ctx = xprt_ctx;
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005618
Olivier Houcharda37eb6a2019-06-24 18:57:39 +02005619 if (!ctx)
5620 return -1;
5621
Olivier Houchardea8dd942019-05-20 14:02:16 +02005622 if (event_type & SUB_RETRY_RECV) {
5623 sw = param;
5624 BUG_ON(ctx->recv_wait != NULL || (sw->events & SUB_RETRY_RECV));
5625 sw->events |= SUB_RETRY_RECV;
5626 ctx->recv_wait = sw;
5627 if (!(conn->flags & CO_FL_SSL_WAIT_HS) &&
5628 !(ctx->wait_event.events & SUB_RETRY_RECV))
5629 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_RECV, &ctx->wait_event);
5630 event_type &= ~SUB_RETRY_RECV;
5631 }
5632 if (event_type & SUB_RETRY_SEND) {
5633sw = param;
5634 BUG_ON(ctx->send_wait != NULL || (sw->events & SUB_RETRY_SEND));
5635 sw->events |= SUB_RETRY_SEND;
5636 ctx->send_wait = sw;
5637 if (!(conn->flags & CO_FL_SSL_WAIT_HS) &&
5638 !(ctx->wait_event.events & SUB_RETRY_SEND))
5639 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_SEND, &ctx->wait_event);
5640 event_type &= ~SUB_RETRY_SEND;
5641
5642 }
5643 if (event_type != 0)
5644 return -1;
5645 return 0;
Olivier Houcharddf357842019-03-21 16:30:07 +01005646}
5647
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005648static int ssl_unsubscribe(struct connection *conn, void *xprt_ctx, int event_type, void *param)
Olivier Houcharddf357842019-03-21 16:30:07 +01005649{
Olivier Houchardea8dd942019-05-20 14:02:16 +02005650 struct wait_event *sw;
5651 struct ssl_sock_ctx *ctx = xprt_ctx;
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005652
Olivier Houchardea8dd942019-05-20 14:02:16 +02005653 if (event_type & SUB_RETRY_RECV) {
5654 sw = param;
5655 BUG_ON(ctx->recv_wait != sw);
5656 ctx->recv_wait = NULL;
5657 sw->events &= ~SUB_RETRY_RECV;
5658 /* If we subscribed, and we're not doing the handshake,
5659 * then we subscribed because the upper layer asked for it,
5660 * as the upper layer is no longer interested, we can
5661 * unsubscribe too.
5662 */
5663 if (!(ctx->conn->flags & CO_FL_SSL_WAIT_HS) &&
5664 (ctx->wait_event.events & SUB_RETRY_RECV))
5665 conn_unsubscribe(conn, ctx->xprt_ctx, SUB_RETRY_RECV,
5666 &ctx->wait_event);
5667 }
5668 if (event_type & SUB_RETRY_SEND) {
5669 sw = param;
5670 BUG_ON(ctx->send_wait != sw);
5671 ctx->send_wait = NULL;
5672 sw->events &= ~SUB_RETRY_SEND;
5673 if (!(ctx->conn->flags & CO_FL_SSL_WAIT_HS) &&
5674 (ctx->wait_event.events & SUB_RETRY_SEND))
5675 conn_unsubscribe(conn, ctx->xprt_ctx, SUB_RETRY_SEND,
5676 &ctx->wait_event);
5677
5678 }
5679
5680 return 0;
Olivier Houcharddf357842019-03-21 16:30:07 +01005681}
5682
Olivier Houchard2e055482019-05-27 19:50:12 +02005683/* Use the provided XPRT as an underlying XPRT, and provide the old one.
5684 * Returns 0 on success, and non-zero on failure.
5685 */
5686static 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)
5687{
5688 struct ssl_sock_ctx *ctx = xprt_ctx;
5689
5690 if (oldxprt_ops != NULL)
5691 *oldxprt_ops = ctx->xprt;
5692 if (oldxprt_ctx != NULL)
5693 *oldxprt_ctx = ctx->xprt_ctx;
5694 ctx->xprt = toadd_ops;
5695 ctx->xprt_ctx = toadd_ctx;
5696 return 0;
5697}
5698
Olivier Houchard5149b592019-05-23 17:47:36 +02005699/* Remove the specified xprt. If if it our underlying XPRT, remove it and
5700 * return 0, otherwise just call the remove_xprt method from the underlying
5701 * XPRT.
5702 */
5703static int ssl_remove_xprt(struct connection *conn, void *xprt_ctx, void *toremove_ctx, const struct xprt_ops *newops, void *newctx)
5704{
5705 struct ssl_sock_ctx *ctx = xprt_ctx;
5706
5707 if (ctx->xprt_ctx == toremove_ctx) {
5708 ctx->xprt_ctx = newctx;
5709 ctx->xprt = newops;
5710 return 0;
5711 }
5712 return (ctx->xprt->remove_xprt(conn, ctx->xprt_ctx, toremove_ctx, newops, newctx));
5713}
5714
Olivier Houchardea8dd942019-05-20 14:02:16 +02005715static struct task *ssl_sock_io_cb(struct task *t, void *context, unsigned short state)
5716{
5717 struct ssl_sock_ctx *ctx = context;
5718
5719 /* First if we're doing an handshake, try that */
5720 if (ctx->conn->flags & CO_FL_SSL_WAIT_HS)
5721 ssl_sock_handshake(ctx->conn, CO_FL_SSL_WAIT_HS);
5722 /* If we had an error, or the handshake is done and I/O is available,
5723 * let the upper layer know.
5724 * If no mux was set up yet, and nobody subscribed, then call
5725 * xprt_done_cb() ourself if it's set, or destroy the connection,
5726 * we can't be sure conn_fd_handler() will be called again.
5727 */
5728 if ((ctx->conn->flags & CO_FL_ERROR) ||
5729 !(ctx->conn->flags & CO_FL_SSL_WAIT_HS)) {
5730 int ret = 0;
5731 int woke = 0;
5732
5733 /* On error, wake any waiter */
5734 if (ctx->recv_wait) {
5735 ctx->recv_wait->events &= ~SUB_RETRY_RECV;
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02005736 tasklet_wakeup(ctx->recv_wait->tasklet);
Olivier Houchardea8dd942019-05-20 14:02:16 +02005737 ctx->recv_wait = NULL;
5738 woke = 1;
5739 }
5740 if (ctx->send_wait) {
5741 ctx->send_wait->events &= ~SUB_RETRY_SEND;
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02005742 tasklet_wakeup(ctx->send_wait->tasklet);
Olivier Houchardea8dd942019-05-20 14:02:16 +02005743 ctx->send_wait = NULL;
5744 woke = 1;
5745 }
5746 /* If we're the first xprt for the connection, let the
5747 * upper layers know. If xprt_done_cb() is set, call it,
5748 * otherwise, we should have a mux, so call its wake
5749 * method if we didn't woke a tasklet already.
5750 */
5751 if (ctx->conn->xprt_ctx == ctx) {
5752 if (ctx->conn->xprt_done_cb)
5753 ret = ctx->conn->xprt_done_cb(ctx->conn);
5754 if (ret >= 0 && !woke && ctx->conn->mux && ctx->conn->mux->wake)
5755 ctx->conn->mux->wake(ctx->conn);
5756 return NULL;
5757 }
5758 }
5759 return NULL;
5760}
5761
Emeric Brun46591952012-05-18 15:47:34 +02005762/* Receive up to <count> bytes from connection <conn>'s socket and store them
Willy Tarreauabf08d92014-01-14 11:31:27 +01005763 * into buffer <buf>. Only one call to recv() is performed, unless the
Emeric Brun46591952012-05-18 15:47:34 +02005764 * buffer wraps, in which case a second call may be performed. The connection's
5765 * flags are updated with whatever special event is detected (error, read0,
5766 * empty). The caller is responsible for taking care of those events and
5767 * avoiding the call if inappropriate. The function does not call the
5768 * connection's polling update function, so the caller is responsible for this.
5769 */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005770static 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 +02005771{
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005772 struct ssl_sock_ctx *ctx = xprt_ctx;
Willy Tarreaubfc4d772018-07-18 11:22:03 +02005773 ssize_t ret;
5774 size_t try, done = 0;
Emeric Brun46591952012-05-18 15:47:34 +02005775
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005776 conn_refresh_polling_flags(conn);
5777
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005778 if (!ctx)
Emeric Brun46591952012-05-18 15:47:34 +02005779 goto out_error;
5780
5781 if (conn->flags & CO_FL_HANDSHAKE)
5782 /* a handshake was requested */
5783 return 0;
5784
Emeric Brun46591952012-05-18 15:47:34 +02005785 /* read the largest possible block. For this, we perform only one call
5786 * to recv() unless the buffer wraps and we exactly fill the first hunk,
5787 * in which case we accept to do it once again. A new attempt is made on
5788 * EINTR too.
5789 */
Willy Tarreau00b0fb92014-01-17 11:09:40 +01005790 while (count > 0) {
Olivier Houchardc2aae742017-09-22 18:26:28 +02005791 int need_out = 0;
5792
Willy Tarreau591d4452018-06-15 17:21:00 +02005793 try = b_contig_space(buf);
5794 if (!try)
5795 break;
5796
Willy Tarreauabf08d92014-01-14 11:31:27 +01005797 if (try > count)
5798 try = count;
Willy Tarreau591d4452018-06-15 17:21:00 +02005799
Olivier Houchardc2aae742017-09-22 18:26:28 +02005800 if (((conn->flags & (CO_FL_EARLY_SSL_HS | CO_FL_EARLY_DATA)) == CO_FL_EARLY_SSL_HS) &&
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01005801 ctx->tmp_early_data != -1) {
5802 *b_tail(buf) = ctx->tmp_early_data;
Olivier Houchardc2aae742017-09-22 18:26:28 +02005803 done++;
5804 try--;
5805 count--;
Olivier Houchardacd14032018-06-28 18:17:23 +02005806 b_add(buf, 1);
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01005807 ctx->tmp_early_data = -1;
Olivier Houchardc2aae742017-09-22 18:26:28 +02005808 continue;
5809 }
Willy Tarreauabf08d92014-01-14 11:31:27 +01005810
Willy Tarreau5db847a2019-05-09 14:13:35 +02005811#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Olivier Houchardc2aae742017-09-22 18:26:28 +02005812 if (conn->flags & CO_FL_EARLY_SSL_HS) {
5813 size_t read_length;
5814
Olivier Houchard66ab4982019-02-26 18:37:15 +01005815 ret = SSL_read_early_data(ctx->ssl,
Willy Tarreau8f9c72d2018-06-07 18:46:28 +02005816 b_tail(buf), try, &read_length);
Olivier Houchard522eea72017-11-03 16:27:47 +01005817 if (ret == SSL_READ_EARLY_DATA_SUCCESS &&
5818 read_length > 0)
Olivier Houchardc2aae742017-09-22 18:26:28 +02005819 conn->flags |= CO_FL_EARLY_DATA;
5820 if (ret == SSL_READ_EARLY_DATA_SUCCESS ||
5821 ret == SSL_READ_EARLY_DATA_FINISH) {
5822 if (ret == SSL_READ_EARLY_DATA_FINISH) {
5823 /*
5824 * We're done reading the early data,
5825 * let's make the handshake
5826 */
5827 conn->flags &= ~CO_FL_EARLY_SSL_HS;
5828 conn->flags |= CO_FL_SSL_WAIT_HS;
5829 need_out = 1;
Olivier Houchard965e84e2019-06-15 20:59:30 +02005830 /* Now initiate the handshake */
5831 tasklet_wakeup(ctx->wait_event.tasklet);
Olivier Houchardc2aae742017-09-22 18:26:28 +02005832 if (read_length == 0)
5833 break;
5834 }
5835 ret = read_length;
5836 }
5837 } else
5838#endif
Olivier Houchard66ab4982019-02-26 18:37:15 +01005839 ret = SSL_read(ctx->ssl, b_tail(buf), try);
Emmanuel Hocdet510fce52019-08-05 18:04:16 +02005840
Emeric Brune1f38db2012-09-03 20:36:47 +02005841 if (conn->flags & CO_FL_ERROR) {
5842 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01005843 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02005844 }
Emeric Brun46591952012-05-18 15:47:34 +02005845 if (ret > 0) {
Olivier Houchardacd14032018-06-28 18:17:23 +02005846 b_add(buf, ret);
Emeric Brun46591952012-05-18 15:47:34 +02005847 done += ret;
Emeric Brun46591952012-05-18 15:47:34 +02005848 count -= ret;
Emeric Brun46591952012-05-18 15:47:34 +02005849 }
Emeric Brun46591952012-05-18 15:47:34 +02005850 else {
Olivier Houchard66ab4982019-02-26 18:37:15 +01005851 ret = SSL_get_error(ctx->ssl, ret);
Emeric Brun46591952012-05-18 15:47:34 +02005852 if (ret == SSL_ERROR_WANT_WRITE) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01005853 /* handshake is running, and it needs to enable write */
Emeric Brun46591952012-05-18 15:47:34 +02005854 conn->flags |= CO_FL_SSL_WAIT_HS;
Olivier Houchardea8dd942019-05-20 14:02:16 +02005855 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_SEND, &ctx->wait_event);
Willy Tarreau5db847a2019-05-09 14:13:35 +02005856#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00005857 /* Async mode can be re-enabled, because we're leaving data state.*/
5858 if (global_ssl.async)
Olivier Houchard66ab4982019-02-26 18:37:15 +01005859 SSL_set_mode(ctx->ssl, SSL_MODE_ASYNC);
Emeric Brunb5e42a82017-06-06 12:35:14 +00005860#endif
Emeric Brun46591952012-05-18 15:47:34 +02005861 break;
5862 }
5863 else if (ret == SSL_ERROR_WANT_READ) {
Olivier Houchard66ab4982019-02-26 18:37:15 +01005864 if (SSL_renegotiate_pending(ctx->ssl)) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02005865 ctx->xprt->subscribe(conn, ctx->xprt_ctx,
5866 SUB_RETRY_RECV,
5867 &ctx->wait_event);
Emeric Brun282a76a2012-11-08 18:02:56 +01005868 /* handshake is running, and it may need to re-enable read */
5869 conn->flags |= CO_FL_SSL_WAIT_HS;
Willy Tarreau5db847a2019-05-09 14:13:35 +02005870#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00005871 /* Async mode can be re-enabled, because we're leaving data state.*/
5872 if (global_ssl.async)
Olivier Houchard66ab4982019-02-26 18:37:15 +01005873 SSL_set_mode(ctx->ssl, SSL_MODE_ASYNC);
Emeric Brunb5e42a82017-06-06 12:35:14 +00005874#endif
Emeric Brun282a76a2012-11-08 18:02:56 +01005875 break;
5876 }
Emeric Brun46591952012-05-18 15:47:34 +02005877 break;
Olivier Houchardc2aae742017-09-22 18:26:28 +02005878 } else if (ret == SSL_ERROR_ZERO_RETURN)
5879 goto read0;
Christopher Faulet4ac77a92018-02-19 14:25:15 +01005880 /* For SSL_ERROR_SYSCALL, make sure to clear the error
5881 * stack before shutting down the connection for
5882 * reading. */
Olivier Houchard7e2e5052018-02-13 15:17:23 +01005883 if (ret == SSL_ERROR_SYSCALL && (!errno || errno == EAGAIN))
5884 goto clear_ssl_error;
Emeric Brun46591952012-05-18 15:47:34 +02005885 /* otherwise it's a real error */
5886 goto out_error;
5887 }
Olivier Houchardc2aae742017-09-22 18:26:28 +02005888 if (need_out)
5889 break;
Emeric Brun46591952012-05-18 15:47:34 +02005890 }
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005891 leave:
Emeric Brun46591952012-05-18 15:47:34 +02005892 return done;
5893
Christopher Faulet4ac77a92018-02-19 14:25:15 +01005894 clear_ssl_error:
5895 /* Clear openssl global errors stack */
5896 ssl_sock_dump_errors(conn);
5897 ERR_clear_error();
Emeric Brun46591952012-05-18 15:47:34 +02005898 read0:
5899 conn_sock_read0(conn);
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005900 goto leave;
Christopher Faulet4ac77a92018-02-19 14:25:15 +01005901
Emeric Brun46591952012-05-18 15:47:34 +02005902 out_error:
Olivier Houchard7e2e5052018-02-13 15:17:23 +01005903 conn->flags |= CO_FL_ERROR;
Emeric Brun644cde02012-12-14 11:21:13 +01005904 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02005905 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01005906 ERR_clear_error();
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005907 goto leave;
Emeric Brun46591952012-05-18 15:47:34 +02005908}
5909
5910
Willy Tarreau787db9a2018-06-14 18:31:46 +02005911/* Send up to <count> pending bytes from buffer <buf> to connection <conn>'s
5912 * socket. <flags> may contain some CO_SFL_* flags to hint the system about
5913 * other pending data for example, but this flag is ignored at the moment.
Emeric Brun46591952012-05-18 15:47:34 +02005914 * Only one call to send() is performed, unless the buffer wraps, in which case
5915 * a second call may be performed. The connection's flags are updated with
5916 * whatever special event is detected (error, empty). The caller is responsible
5917 * for taking care of those events and avoiding the call if inappropriate. The
5918 * function does not call the connection's polling update function, so the caller
Willy Tarreau787db9a2018-06-14 18:31:46 +02005919 * is responsible for this. The buffer's output is not adjusted, it's up to the
5920 * caller to take care of this. It's up to the caller to update the buffer's
5921 * contents based on the return value.
Emeric Brun46591952012-05-18 15:47:34 +02005922 */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005923static 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 +02005924{
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005925 struct ssl_sock_ctx *ctx = xprt_ctx;
Willy Tarreau787db9a2018-06-14 18:31:46 +02005926 ssize_t ret;
5927 size_t try, done;
Emeric Brun46591952012-05-18 15:47:34 +02005928
5929 done = 0;
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005930 conn_refresh_polling_flags(conn);
Emeric Brun46591952012-05-18 15:47:34 +02005931
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005932 if (!ctx)
Emeric Brun46591952012-05-18 15:47:34 +02005933 goto out_error;
5934
Olivier Houchard010941f2019-05-03 20:56:19 +02005935 if (conn->flags & (CO_FL_HANDSHAKE | CO_FL_EARLY_SSL_HS))
Emeric Brun46591952012-05-18 15:47:34 +02005936 /* a handshake was requested */
5937 return 0;
5938
5939 /* send the largest possible block. For this we perform only one call
5940 * to send() unless the buffer wraps and we exactly fill the first hunk,
5941 * in which case we accept to do it once again.
5942 */
Willy Tarreau787db9a2018-06-14 18:31:46 +02005943 while (count) {
Willy Tarreau5db847a2019-05-09 14:13:35 +02005944#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Olivier Houchardc2aae742017-09-22 18:26:28 +02005945 size_t written_data;
5946#endif
5947
Willy Tarreau787db9a2018-06-14 18:31:46 +02005948 try = b_contig_data(buf, done);
5949 if (try > count)
5950 try = count;
Willy Tarreaubfd59462013-02-21 07:46:09 +01005951
Willy Tarreau7bed9452014-02-02 02:00:24 +01005952 if (!(flags & CO_SFL_STREAMER) &&
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01005953 !(ctx->xprt_st & SSL_SOCK_SEND_UNLIMITED) &&
Willy Tarreauef934602016-12-22 23:12:01 +01005954 global_ssl.max_record && try > global_ssl.max_record) {
5955 try = global_ssl.max_record;
Willy Tarreau518cedd2014-02-17 15:43:01 +01005956 }
5957 else {
5958 /* we need to keep the information about the fact that
5959 * we're not limiting the upcoming send(), because if it
5960 * fails, we'll have to retry with at least as many data.
5961 */
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01005962 ctx->xprt_st |= SSL_SOCK_SEND_UNLIMITED;
Willy Tarreau518cedd2014-02-17 15:43:01 +01005963 }
Willy Tarreaubfd59462013-02-21 07:46:09 +01005964
Willy Tarreau5db847a2019-05-09 14:13:35 +02005965#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Olivier Houchard010941f2019-05-03 20:56:19 +02005966 if (!SSL_is_init_finished(ctx->ssl) && conn_is_back(conn)) {
Olivier Houchardc2aae742017-09-22 18:26:28 +02005967 unsigned int max_early;
5968
Olivier Houchard522eea72017-11-03 16:27:47 +01005969 if (objt_listener(conn->target))
Olivier Houchard66ab4982019-02-26 18:37:15 +01005970 max_early = SSL_get_max_early_data(ctx->ssl);
Olivier Houchard522eea72017-11-03 16:27:47 +01005971 else {
Olivier Houchard66ab4982019-02-26 18:37:15 +01005972 if (SSL_get0_session(ctx->ssl))
5973 max_early = SSL_SESSION_get_max_early_data(SSL_get0_session(ctx->ssl));
Olivier Houchard522eea72017-11-03 16:27:47 +01005974 else
5975 max_early = 0;
5976 }
5977
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01005978 if (try + ctx->sent_early_data > max_early) {
5979 try -= (try + ctx->sent_early_data) - max_early;
Olivier Houchard522eea72017-11-03 16:27:47 +01005980 if (try <= 0) {
Olivier Houchard010941f2019-05-03 20:56:19 +02005981 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Olivier Houchard965e84e2019-06-15 20:59:30 +02005982 tasklet_wakeup(ctx->wait_event.tasklet);
Olivier Houchardc2aae742017-09-22 18:26:28 +02005983 break;
Olivier Houchard522eea72017-11-03 16:27:47 +01005984 }
Olivier Houchardc2aae742017-09-22 18:26:28 +02005985 }
Olivier Houchard66ab4982019-02-26 18:37:15 +01005986 ret = SSL_write_early_data(ctx->ssl, b_peek(buf, done), try, &written_data);
Olivier Houchardc2aae742017-09-22 18:26:28 +02005987 if (ret == 1) {
5988 ret = written_data;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01005989 ctx->sent_early_data += ret;
Olivier Houchard965e84e2019-06-15 20:59:30 +02005990 if (objt_server(conn->target)) {
Olivier Houchard522eea72017-11-03 16:27:47 +01005991 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN | CO_FL_EARLY_DATA;
Olivier Houchard965e84e2019-06-15 20:59:30 +02005992 /* Initiate the handshake, now */
5993 tasklet_wakeup(ctx->wait_event.tasklet);
5994 }
Olivier Houchard522eea72017-11-03 16:27:47 +01005995
Olivier Houchardc2aae742017-09-22 18:26:28 +02005996 }
5997
5998 } else
5999#endif
Olivier Houchard66ab4982019-02-26 18:37:15 +01006000 ret = SSL_write(ctx->ssl, b_peek(buf, done), try);
Willy Tarreau518cedd2014-02-17 15:43:01 +01006001
Emeric Brune1f38db2012-09-03 20:36:47 +02006002 if (conn->flags & CO_FL_ERROR) {
6003 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01006004 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02006005 }
Emeric Brun46591952012-05-18 15:47:34 +02006006 if (ret > 0) {
Olivier Houchardf24502b2019-01-17 19:09:11 +01006007 /* A send succeeded, so we can consier ourself connected */
6008 conn->flags |= CO_FL_CONNECTED;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006009 ctx->xprt_st &= ~SSL_SOCK_SEND_UNLIMITED;
Willy Tarreau787db9a2018-06-14 18:31:46 +02006010 count -= ret;
Emeric Brun46591952012-05-18 15:47:34 +02006011 done += ret;
Emeric Brun46591952012-05-18 15:47:34 +02006012 }
6013 else {
Olivier Houchard66ab4982019-02-26 18:37:15 +01006014 ret = SSL_get_error(ctx->ssl, ret);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006015
Emeric Brun46591952012-05-18 15:47:34 +02006016 if (ret == SSL_ERROR_WANT_WRITE) {
Olivier Houchard66ab4982019-02-26 18:37:15 +01006017 if (SSL_renegotiate_pending(ctx->ssl)) {
Emeric Brun282a76a2012-11-08 18:02:56 +01006018 /* handshake is running, and it may need to re-enable write */
6019 conn->flags |= CO_FL_SSL_WAIT_HS;
Olivier Houchardea8dd942019-05-20 14:02:16 +02006020 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_SEND, &ctx->wait_event);
Willy Tarreau5db847a2019-05-09 14:13:35 +02006021#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00006022 /* Async mode can be re-enabled, because we're leaving data state.*/
6023 if (global_ssl.async)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006024 SSL_set_mode(ctx->ssl, SSL_MODE_ASYNC);
Emeric Brunb5e42a82017-06-06 12:35:14 +00006025#endif
Emeric Brun282a76a2012-11-08 18:02:56 +01006026 break;
6027 }
Olivier Houchardea8dd942019-05-20 14:02:16 +02006028
Emeric Brun46591952012-05-18 15:47:34 +02006029 break;
6030 }
6031 else if (ret == SSL_ERROR_WANT_READ) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01006032 /* handshake is running, and it needs to enable read */
Emeric Brun46591952012-05-18 15:47:34 +02006033 conn->flags |= CO_FL_SSL_WAIT_HS;
Olivier Houchardea8dd942019-05-20 14:02:16 +02006034 ctx->xprt->subscribe(conn, ctx->xprt_ctx,
6035 SUB_RETRY_RECV,
6036 &ctx->wait_event);
Willy Tarreau5db847a2019-05-09 14:13:35 +02006037#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00006038 /* Async mode can be re-enabled, because we're leaving data state.*/
6039 if (global_ssl.async)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006040 SSL_set_mode(ctx->ssl, SSL_MODE_ASYNC);
Emeric Brunb5e42a82017-06-06 12:35:14 +00006041#endif
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006042 break;
6043 }
Emeric Brun46591952012-05-18 15:47:34 +02006044 goto out_error;
6045 }
6046 }
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02006047 leave:
Emeric Brun46591952012-05-18 15:47:34 +02006048 return done;
6049
6050 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01006051 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02006052 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01006053 ERR_clear_error();
6054
Emeric Brun46591952012-05-18 15:47:34 +02006055 conn->flags |= CO_FL_ERROR;
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02006056 goto leave;
Emeric Brun46591952012-05-18 15:47:34 +02006057}
6058
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006059static void ssl_sock_close(struct connection *conn, void *xprt_ctx) {
Emeric Brun46591952012-05-18 15:47:34 +02006060
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006061 struct ssl_sock_ctx *ctx = xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006062
Olivier Houchardea8dd942019-05-20 14:02:16 +02006063
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006064 if (ctx) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02006065 if (ctx->wait_event.events != 0)
6066 ctx->xprt->unsubscribe(ctx->conn, ctx->xprt_ctx,
6067 ctx->wait_event.events,
6068 &ctx->wait_event);
6069 if (ctx->send_wait) {
6070 ctx->send_wait->events &= ~SUB_RETRY_SEND;
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02006071 tasklet_wakeup(ctx->send_wait->tasklet);
Olivier Houchardea8dd942019-05-20 14:02:16 +02006072 }
6073 if (ctx->recv_wait) {
6074 ctx->recv_wait->events &= ~SUB_RETRY_RECV;
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02006075 tasklet_wakeup(ctx->recv_wait->tasklet);
Olivier Houchardea8dd942019-05-20 14:02:16 +02006076 }
Olivier Houchard692c1d02019-05-23 18:41:47 +02006077 if (ctx->xprt->close)
6078 ctx->xprt->close(conn, ctx->xprt_ctx);
Willy Tarreau5db847a2019-05-09 14:13:35 +02006079#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brun3854e012017-05-17 20:42:48 +02006080 if (global_ssl.async) {
6081 OSSL_ASYNC_FD all_fd[32], afd;
6082 size_t num_all_fds = 0;
6083 int i;
6084
Olivier Houchard66ab4982019-02-26 18:37:15 +01006085 SSL_get_all_async_fds(ctx->ssl, NULL, &num_all_fds);
Emeric Brun3854e012017-05-17 20:42:48 +02006086 if (num_all_fds > 32) {
6087 send_log(NULL, LOG_EMERG, "haproxy: openssl returns too many async fds. It seems a bug. Process may crash\n");
6088 return;
6089 }
6090
Olivier Houchard66ab4982019-02-26 18:37:15 +01006091 SSL_get_all_async_fds(ctx->ssl, all_fd, &num_all_fds);
Emeric Brun3854e012017-05-17 20:42:48 +02006092
6093 /* If an async job is pending, we must try to
6094 to catch the end using polling before calling
6095 SSL_free */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006096 if (num_all_fds && SSL_waiting_for_async(ctx->ssl)) {
Emeric Brun3854e012017-05-17 20:42:48 +02006097 for (i=0 ; i < num_all_fds ; i++) {
6098 /* switch on an handler designed to
6099 * handle the SSL_free
6100 */
6101 afd = all_fd[i];
6102 fdtab[afd].iocb = ssl_async_fd_free;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006103 fdtab[afd].owner = ctx->ssl;
Emeric Brun3854e012017-05-17 20:42:48 +02006104 fd_want_recv(afd);
Emeric Brunce9e01c2017-05-31 10:02:53 +00006105 /* To ensure that the fd cache won't be used
6106 * and we'll catch a real RD event.
6107 */
6108 fd_cant_recv(afd);
Emeric Brun3854e012017-05-17 20:42:48 +02006109 }
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02006110 tasklet_free(ctx->wait_event.tasklet);
Olivier Houchard66ab4982019-02-26 18:37:15 +01006111 pool_free(ssl_sock_ctx_pool, ctx);
Olivier Houchard2be5a4c2019-03-08 18:54:43 +01006112 _HA_ATOMIC_ADD(&jobs, 1);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006113 return;
6114 }
Emeric Brun3854e012017-05-17 20:42:48 +02006115 /* Else we can remove the fds from the fdtab
6116 * and call SSL_free.
6117 * note: we do a fd_remove and not a delete
6118 * because the fd is owned by the engine.
6119 * the engine is responsible to close
6120 */
6121 for (i=0 ; i < num_all_fds ; i++)
6122 fd_remove(all_fd[i]);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006123 }
6124#endif
Olivier Houchard66ab4982019-02-26 18:37:15 +01006125 SSL_free(ctx->ssl);
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02006126 tasklet_free(ctx->wait_event.tasklet);
Olivier Houchard66ab4982019-02-26 18:37:15 +01006127 pool_free(ssl_sock_ctx_pool, ctx);
Olivier Houchard2be5a4c2019-03-08 18:54:43 +01006128 _HA_ATOMIC_SUB(&sslconns, 1);
Emeric Brun46591952012-05-18 15:47:34 +02006129 }
Emeric Brun46591952012-05-18 15:47:34 +02006130}
6131
6132/* This function tries to perform a clean shutdown on an SSL connection, and in
6133 * any case, flags the connection as reusable if no handshake was in progress.
6134 */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006135static void ssl_sock_shutw(struct connection *conn, void *xprt_ctx, int clean)
Emeric Brun46591952012-05-18 15:47:34 +02006136{
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006137 struct ssl_sock_ctx *ctx = xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006138
Emeric Brun46591952012-05-18 15:47:34 +02006139 if (conn->flags & CO_FL_HANDSHAKE)
6140 return;
Emmanuel Hocdet405ff312017-01-08 14:07:39 +01006141 if (!clean)
6142 /* don't sent notify on SSL_shutdown */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006143 SSL_set_quiet_shutdown(ctx->ssl, 1);
Emeric Brun46591952012-05-18 15:47:34 +02006144 /* no handshake was in progress, try a clean ssl shutdown */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006145 if (SSL_shutdown(ctx->ssl) <= 0) {
Emeric Brun644cde02012-12-14 11:21:13 +01006146 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02006147 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01006148 ERR_clear_error();
6149 }
Emeric Brun46591952012-05-18 15:47:34 +02006150}
6151
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01006152/* used for ppv2 pkey alog (can be used for logging) */
Willy Tarreau83061a82018-07-13 11:56:34 +02006153int ssl_sock_get_pkey_algo(struct connection *conn, struct buffer *out)
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01006154{
Christopher Faulet4517b0c2019-09-10 10:12:03 +02006155 struct ssl_sock_ctx *ctx;
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01006156 struct pkey_info *pkinfo;
6157 int bits = 0;
6158 int sig = TLSEXT_signature_anonymous;
6159 int len = -1;
6160
6161 if (!ssl_sock_is_ssl(conn))
6162 return 0;
Christopher Faulet4517b0c2019-09-10 10:12:03 +02006163 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006164 pkinfo = SSL_CTX_get_ex_data(SSL_get_SSL_CTX(ctx->ssl), ssl_pkey_info_index);
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01006165 if (pkinfo) {
6166 sig = pkinfo->sig;
6167 bits = pkinfo->bits;
6168 } else {
6169 /* multicert and generated cert have no pkey info */
6170 X509 *crt;
6171 EVP_PKEY *pkey;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006172 crt = SSL_get_certificate(ctx->ssl);
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01006173 if (!crt)
6174 return 0;
6175 pkey = X509_get_pubkey(crt);
6176 if (pkey) {
6177 bits = EVP_PKEY_bits(pkey);
6178 switch(EVP_PKEY_base_id(pkey)) {
6179 case EVP_PKEY_RSA:
6180 sig = TLSEXT_signature_rsa;
6181 break;
6182 case EVP_PKEY_EC:
6183 sig = TLSEXT_signature_ecdsa;
6184 break;
6185 case EVP_PKEY_DSA:
6186 sig = TLSEXT_signature_dsa;
6187 break;
6188 }
6189 EVP_PKEY_free(pkey);
6190 }
6191 }
6192
6193 switch(sig) {
6194 case TLSEXT_signature_rsa:
6195 len = chunk_printf(out, "RSA%d", bits);
6196 break;
6197 case TLSEXT_signature_ecdsa:
6198 len = chunk_printf(out, "EC%d", bits);
6199 break;
6200 case TLSEXT_signature_dsa:
6201 len = chunk_printf(out, "DSA%d", bits);
6202 break;
6203 default:
6204 return 0;
6205 }
6206 if (len < 0)
6207 return 0;
6208 return 1;
6209}
6210
Emmanuel Hocdet283e0042017-11-02 14:05:23 +01006211/* used for ppv2 cert signature (can be used for logging) */
6212const char *ssl_sock_get_cert_sig(struct connection *conn)
6213{
Christopher Faulet4517b0c2019-09-10 10:12:03 +02006214 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006215
Emmanuel Hocdet283e0042017-11-02 14:05:23 +01006216 __OPENSSL_110_CONST__ ASN1_OBJECT *algorithm;
6217 X509 *crt;
6218
6219 if (!ssl_sock_is_ssl(conn))
6220 return NULL;
Christopher Faulet4517b0c2019-09-10 10:12:03 +02006221 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006222 crt = SSL_get_certificate(ctx->ssl);
Emmanuel Hocdet283e0042017-11-02 14:05:23 +01006223 if (!crt)
6224 return NULL;
6225 X509_ALGOR_get0(&algorithm, NULL, NULL, X509_get0_tbs_sigalg(crt));
6226 return OBJ_nid2sn(OBJ_obj2nid(algorithm));
6227}
6228
Emmanuel Hocdet253c3b72018-02-01 18:29:59 +01006229/* used for ppv2 authority */
6230const char *ssl_sock_get_sni(struct connection *conn)
6231{
6232#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Christopher Faulet4517b0c2019-09-10 10:12:03 +02006233 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006234
Emmanuel Hocdet253c3b72018-02-01 18:29:59 +01006235 if (!ssl_sock_is_ssl(conn))
6236 return NULL;
Christopher Faulet4517b0c2019-09-10 10:12:03 +02006237 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006238 return SSL_get_servername(ctx->ssl, TLSEXT_NAMETYPE_host_name);
Emmanuel Hocdet253c3b72018-02-01 18:29:59 +01006239#else
Olivier Houchard66ab4982019-02-26 18:37:15 +01006240 return NULL;
Emmanuel Hocdet253c3b72018-02-01 18:29:59 +01006241#endif
6242}
6243
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02006244/* used for logging/ppv2, may be changed for a sample fetch later */
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02006245const char *ssl_sock_get_cipher_name(struct connection *conn)
6246{
Christopher Faulet4517b0c2019-09-10 10:12:03 +02006247 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006248
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02006249 if (!ssl_sock_is_ssl(conn))
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02006250 return NULL;
Christopher Faulet4517b0c2019-09-10 10:12:03 +02006251 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006252 return SSL_get_cipher_name(ctx->ssl);
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02006253}
6254
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02006255/* used for logging/ppv2, may be changed for a sample fetch later */
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02006256const char *ssl_sock_get_proto_version(struct connection *conn)
6257{
Christopher Faulet4517b0c2019-09-10 10:12:03 +02006258 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006259
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02006260 if (!ssl_sock_is_ssl(conn))
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02006261 return NULL;
Christopher Faulet4517b0c2019-09-10 10:12:03 +02006262 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006263 return SSL_get_version(ctx->ssl);
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02006264}
6265
Willy Tarreau8d598402012-10-22 17:58:39 +02006266/* Extract a serial from a cert, and copy it to a chunk.
6267 * Returns 1 if serial is found and copied, 0 if no serial found and
6268 * -1 if output is not large enough.
6269 */
6270static int
Willy Tarreau83061a82018-07-13 11:56:34 +02006271ssl_sock_get_serial(X509 *crt, struct buffer *out)
Willy Tarreau8d598402012-10-22 17:58:39 +02006272{
6273 ASN1_INTEGER *serial;
6274
6275 serial = X509_get_serialNumber(crt);
6276 if (!serial)
6277 return 0;
6278
6279 if (out->size < serial->length)
6280 return -1;
6281
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006282 memcpy(out->area, serial->data, serial->length);
6283 out->data = serial->length;
Willy Tarreau8d598402012-10-22 17:58:39 +02006284 return 1;
6285}
6286
Emeric Brun43e79582014-10-29 19:03:26 +01006287/* Extract a cert to der, and copy it to a chunk.
Joseph Herlant017b3da2018-11-15 09:07:59 -08006288 * Returns 1 if the cert is found and copied, 0 on der conversion failure
6289 * and -1 if the output is not large enough.
Emeric Brun43e79582014-10-29 19:03:26 +01006290 */
6291static int
Willy Tarreau83061a82018-07-13 11:56:34 +02006292ssl_sock_crt2der(X509 *crt, struct buffer *out)
Emeric Brun43e79582014-10-29 19:03:26 +01006293{
6294 int len;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006295 unsigned char *p = (unsigned char *) out->area;;
Emeric Brun43e79582014-10-29 19:03:26 +01006296
6297 len =i2d_X509(crt, NULL);
6298 if (len <= 0)
6299 return 1;
6300
6301 if (out->size < len)
6302 return -1;
6303
6304 i2d_X509(crt,&p);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006305 out->data = len;
Emeric Brun43e79582014-10-29 19:03:26 +01006306 return 1;
6307}
6308
Emeric Brunce5ad802012-10-22 14:11:22 +02006309
Willy Tarreau83061a82018-07-13 11:56:34 +02006310/* Copy Date in ASN1_UTCTIME format in struct buffer out.
Emeric Brunce5ad802012-10-22 14:11:22 +02006311 * Returns 1 if serial is found and copied, 0 if no valid time found
6312 * and -1 if output is not large enough.
6313 */
6314static int
Willy Tarreau83061a82018-07-13 11:56:34 +02006315ssl_sock_get_time(ASN1_TIME *tm, struct buffer *out)
Emeric Brunce5ad802012-10-22 14:11:22 +02006316{
6317 if (tm->type == V_ASN1_GENERALIZEDTIME) {
6318 ASN1_GENERALIZEDTIME *gentm = (ASN1_GENERALIZEDTIME *)tm;
6319
6320 if (gentm->length < 12)
6321 return 0;
6322 if (gentm->data[0] != 0x32 || gentm->data[1] != 0x30)
6323 return 0;
6324 if (out->size < gentm->length-2)
6325 return -1;
6326
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006327 memcpy(out->area, gentm->data+2, gentm->length-2);
6328 out->data = gentm->length-2;
Emeric Brunce5ad802012-10-22 14:11:22 +02006329 return 1;
6330 }
6331 else if (tm->type == V_ASN1_UTCTIME) {
6332 ASN1_UTCTIME *utctm = (ASN1_UTCTIME *)tm;
6333
6334 if (utctm->length < 10)
6335 return 0;
6336 if (utctm->data[0] >= 0x35)
6337 return 0;
6338 if (out->size < utctm->length)
6339 return -1;
6340
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006341 memcpy(out->area, utctm->data, utctm->length);
6342 out->data = utctm->length;
Emeric Brunce5ad802012-10-22 14:11:22 +02006343 return 1;
6344 }
6345
6346 return 0;
6347}
6348
Emeric Brun87855892012-10-17 17:39:35 +02006349/* Extract an entry from a X509_NAME and copy its value to an output chunk.
6350 * Returns 1 if entry found, 0 if entry not found, or -1 if output not large enough.
6351 */
6352static int
Willy Tarreau83061a82018-07-13 11:56:34 +02006353ssl_sock_get_dn_entry(X509_NAME *a, const struct buffer *entry, int pos,
6354 struct buffer *out)
Emeric Brun87855892012-10-17 17:39:35 +02006355{
6356 X509_NAME_ENTRY *ne;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006357 ASN1_OBJECT *obj;
6358 ASN1_STRING *data;
6359 const unsigned char *data_ptr;
6360 int data_len;
Emeric Brun87855892012-10-17 17:39:35 +02006361 int i, j, n;
6362 int cur = 0;
6363 const char *s;
6364 char tmp[128];
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006365 int name_count;
6366
6367 name_count = X509_NAME_entry_count(a);
Emeric Brun87855892012-10-17 17:39:35 +02006368
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006369 out->data = 0;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006370 for (i = 0; i < name_count; i++) {
Emeric Brun87855892012-10-17 17:39:35 +02006371 if (pos < 0)
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006372 j = (name_count-1) - i;
Emeric Brun87855892012-10-17 17:39:35 +02006373 else
6374 j = i;
6375
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006376 ne = X509_NAME_get_entry(a, j);
6377 obj = X509_NAME_ENTRY_get_object(ne);
6378 data = X509_NAME_ENTRY_get_data(ne);
6379 data_ptr = ASN1_STRING_get0_data(data);
6380 data_len = ASN1_STRING_length(data);
6381 n = OBJ_obj2nid(obj);
Emeric Brun87855892012-10-17 17:39:35 +02006382 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006383 i2t_ASN1_OBJECT(tmp, sizeof(tmp), obj);
Emeric Brun87855892012-10-17 17:39:35 +02006384 s = tmp;
6385 }
6386
6387 if (chunk_strcasecmp(entry, s) != 0)
6388 continue;
6389
6390 if (pos < 0)
6391 cur--;
6392 else
6393 cur++;
6394
6395 if (cur != pos)
6396 continue;
6397
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006398 if (data_len > out->size)
Emeric Brun87855892012-10-17 17:39:35 +02006399 return -1;
6400
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006401 memcpy(out->area, data_ptr, data_len);
6402 out->data = data_len;
Emeric Brun87855892012-10-17 17:39:35 +02006403 return 1;
6404 }
6405
6406 return 0;
6407
6408}
6409
6410/* Extract and format full DN from a X509_NAME and copy result into a chunk
6411 * Returns 1 if dn entries exits, 0 if no dn entry found or -1 if output is not large enough.
6412 */
6413static int
Willy Tarreau83061a82018-07-13 11:56:34 +02006414ssl_sock_get_dn_oneline(X509_NAME *a, struct buffer *out)
Emeric Brun87855892012-10-17 17:39:35 +02006415{
6416 X509_NAME_ENTRY *ne;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006417 ASN1_OBJECT *obj;
6418 ASN1_STRING *data;
6419 const unsigned char *data_ptr;
6420 int data_len;
Emeric Brun87855892012-10-17 17:39:35 +02006421 int i, n, ln;
6422 int l = 0;
6423 const char *s;
6424 char *p;
6425 char tmp[128];
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006426 int name_count;
6427
6428
6429 name_count = X509_NAME_entry_count(a);
Emeric Brun87855892012-10-17 17:39:35 +02006430
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006431 out->data = 0;
6432 p = out->area;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006433 for (i = 0; i < name_count; i++) {
6434 ne = X509_NAME_get_entry(a, i);
6435 obj = X509_NAME_ENTRY_get_object(ne);
6436 data = X509_NAME_ENTRY_get_data(ne);
6437 data_ptr = ASN1_STRING_get0_data(data);
6438 data_len = ASN1_STRING_length(data);
6439 n = OBJ_obj2nid(obj);
Emeric Brun87855892012-10-17 17:39:35 +02006440 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006441 i2t_ASN1_OBJECT(tmp, sizeof(tmp), obj);
Emeric Brun87855892012-10-17 17:39:35 +02006442 s = tmp;
6443 }
6444 ln = strlen(s);
6445
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006446 l += 1 + ln + 1 + data_len;
Emeric Brun87855892012-10-17 17:39:35 +02006447 if (l > out->size)
6448 return -1;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006449 out->data = l;
Emeric Brun87855892012-10-17 17:39:35 +02006450
6451 *(p++)='/';
6452 memcpy(p, s, ln);
6453 p += ln;
6454 *(p++)='=';
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006455 memcpy(p, data_ptr, data_len);
6456 p += data_len;
Emeric Brun87855892012-10-17 17:39:35 +02006457 }
6458
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006459 if (!out->data)
Emeric Brun87855892012-10-17 17:39:35 +02006460 return 0;
6461
6462 return 1;
6463}
6464
Olivier Houchardab28a322018-12-21 19:45:40 +01006465void ssl_sock_set_alpn(struct connection *conn, const unsigned char *alpn, int len)
6466{
6467#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Christopher Faulet4517b0c2019-09-10 10:12:03 +02006468 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006469
Olivier Houchardaa2ecea2019-06-28 14:10:33 +02006470 if (!ssl_sock_is_ssl(conn))
6471 return;
Christopher Faulet4517b0c2019-09-10 10:12:03 +02006472 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006473 SSL_set_alpn_protos(ctx->ssl, alpn, len);
Olivier Houchardab28a322018-12-21 19:45:40 +01006474#endif
6475}
6476
Willy Tarreau119a4082016-12-22 21:58:38 +01006477/* Sets advertised SNI for outgoing connections. Please set <hostname> to NULL
6478 * to disable SNI.
6479 */
Willy Tarreau63076412015-07-10 11:33:32 +02006480void ssl_sock_set_servername(struct connection *conn, const char *hostname)
6481{
6482#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Christopher Faulet4517b0c2019-09-10 10:12:03 +02006483 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006484
Willy Tarreau119a4082016-12-22 21:58:38 +01006485 char *prev_name;
6486
Willy Tarreau63076412015-07-10 11:33:32 +02006487 if (!ssl_sock_is_ssl(conn))
6488 return;
Christopher Faulet4517b0c2019-09-10 10:12:03 +02006489 ctx = conn->xprt_ctx;
Willy Tarreau63076412015-07-10 11:33:32 +02006490
Willy Tarreau119a4082016-12-22 21:58:38 +01006491 /* if the SNI changes, we must destroy the reusable context so that a
6492 * new connection will present a new SNI. As an optimization we could
6493 * later imagine having a small cache of ssl_ctx to hold a few SNI per
6494 * server.
6495 */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006496 prev_name = (char *)SSL_get_servername(ctx->ssl, TLSEXT_NAMETYPE_host_name);
Willy Tarreau119a4082016-12-22 21:58:38 +01006497 if ((!prev_name && hostname) ||
6498 (prev_name && (!hostname || strcmp(hostname, prev_name) != 0)))
Olivier Houchard66ab4982019-02-26 18:37:15 +01006499 SSL_set_session(ctx->ssl, NULL);
Willy Tarreau119a4082016-12-22 21:58:38 +01006500
Olivier Houchard66ab4982019-02-26 18:37:15 +01006501 SSL_set_tlsext_host_name(ctx->ssl, hostname);
Willy Tarreau63076412015-07-10 11:33:32 +02006502#endif
6503}
6504
Emeric Brun0abf8362014-06-24 18:26:41 +02006505/* Extract peer certificate's common name into the chunk dest
6506 * Returns
6507 * the len of the extracted common name
6508 * or 0 if no CN found in DN
6509 * or -1 on error case (i.e. no peer certificate)
6510 */
Willy Tarreau83061a82018-07-13 11:56:34 +02006511int ssl_sock_get_remote_common_name(struct connection *conn,
6512 struct buffer *dest)
David Safb76832014-05-08 23:42:08 -04006513{
Christopher Faulet4517b0c2019-09-10 10:12:03 +02006514 struct ssl_sock_ctx *ctx;
David Safb76832014-05-08 23:42:08 -04006515 X509 *crt = NULL;
6516 X509_NAME *name;
David Safb76832014-05-08 23:42:08 -04006517 const char find_cn[] = "CN";
Willy Tarreau83061a82018-07-13 11:56:34 +02006518 const struct buffer find_cn_chunk = {
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006519 .area = (char *)&find_cn,
6520 .data = sizeof(find_cn)-1
David Safb76832014-05-08 23:42:08 -04006521 };
Emeric Brun0abf8362014-06-24 18:26:41 +02006522 int result = -1;
David Safb76832014-05-08 23:42:08 -04006523
6524 if (!ssl_sock_is_ssl(conn))
Emeric Brun0abf8362014-06-24 18:26:41 +02006525 goto out;
Christopher Faulet4517b0c2019-09-10 10:12:03 +02006526 ctx = conn->xprt_ctx;
David Safb76832014-05-08 23:42:08 -04006527
6528 /* SSL_get_peer_certificate, it increase X509 * ref count */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006529 crt = SSL_get_peer_certificate(ctx->ssl);
David Safb76832014-05-08 23:42:08 -04006530 if (!crt)
6531 goto out;
6532
6533 name = X509_get_subject_name(crt);
6534 if (!name)
6535 goto out;
David Safb76832014-05-08 23:42:08 -04006536
Emeric Brun0abf8362014-06-24 18:26:41 +02006537 result = ssl_sock_get_dn_entry(name, &find_cn_chunk, 1, dest);
6538out:
David Safb76832014-05-08 23:42:08 -04006539 if (crt)
6540 X509_free(crt);
6541
6542 return result;
6543}
6544
Dave McCowan328fb582014-07-30 10:39:13 -04006545/* returns 1 if client passed a certificate for this session, 0 if not */
6546int ssl_sock_get_cert_used_sess(struct connection *conn)
6547{
Christopher Faulet4517b0c2019-09-10 10:12:03 +02006548 struct ssl_sock_ctx *ctx;
Dave McCowan328fb582014-07-30 10:39:13 -04006549 X509 *crt = NULL;
6550
6551 if (!ssl_sock_is_ssl(conn))
6552 return 0;
Christopher Faulet4517b0c2019-09-10 10:12:03 +02006553 ctx = conn->xprt_ctx;
Dave McCowan328fb582014-07-30 10:39:13 -04006554
6555 /* SSL_get_peer_certificate, it increase X509 * ref count */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006556 crt = SSL_get_peer_certificate(ctx->ssl);
Dave McCowan328fb582014-07-30 10:39:13 -04006557 if (!crt)
6558 return 0;
6559
6560 X509_free(crt);
6561 return 1;
6562}
6563
6564/* returns 1 if client passed a certificate for this connection, 0 if not */
6565int ssl_sock_get_cert_used_conn(struct connection *conn)
David Safb76832014-05-08 23:42:08 -04006566{
Christopher Faulet4517b0c2019-09-10 10:12:03 +02006567 struct ssl_sock_ctx *ctx;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006568
David Safb76832014-05-08 23:42:08 -04006569 if (!ssl_sock_is_ssl(conn))
6570 return 0;
Christopher Faulet4517b0c2019-09-10 10:12:03 +02006571 ctx = conn->xprt_ctx;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006572 return SSL_SOCK_ST_FL_VERIFY_DONE & ctx->xprt_st ? 1 : 0;
David Safb76832014-05-08 23:42:08 -04006573}
6574
6575/* returns result from SSL verify */
6576unsigned int ssl_sock_get_verify_result(struct connection *conn)
6577{
Christopher Faulet4517b0c2019-09-10 10:12:03 +02006578 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006579
David Safb76832014-05-08 23:42:08 -04006580 if (!ssl_sock_is_ssl(conn))
6581 return (unsigned int)X509_V_ERR_APPLICATION_VERIFICATION;
Christopher Faulet4517b0c2019-09-10 10:12:03 +02006582 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006583 return (unsigned int)SSL_get_verify_result(ctx->ssl);
David Safb76832014-05-08 23:42:08 -04006584}
6585
Willy Tarreau8743f7e2016-12-04 18:44:29 +01006586/* Returns the application layer protocol name in <str> and <len> when known.
6587 * Zero is returned if the protocol name was not found, otherwise non-zero is
6588 * returned. The string is allocated in the SSL context and doesn't have to be
6589 * freed by the caller. NPN is also checked if available since older versions
6590 * of openssl (1.0.1) which are more common in field only support this one.
6591 */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006592static int ssl_sock_get_alpn(const struct connection *conn, void *xprt_ctx, const char **str, int *len)
Willy Tarreau8743f7e2016-12-04 18:44:29 +01006593{
Olivier Houchard66ab4982019-02-26 18:37:15 +01006594#if defined(TLSEXT_TYPE_application_layer_protocol_negotiation) || \
6595 defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006596 struct ssl_sock_ctx *ctx = xprt_ctx;
6597 if (!ctx)
Willy Tarreau8743f7e2016-12-04 18:44:29 +01006598 return 0;
6599
6600 *str = NULL;
6601
6602#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Olivier Houchard66ab4982019-02-26 18:37:15 +01006603 SSL_get0_alpn_selected(ctx->ssl, (const unsigned char **)str, (unsigned *)len);
Willy Tarreau8743f7e2016-12-04 18:44:29 +01006604 if (*str)
6605 return 1;
6606#endif
Bernard Spil13c53f82018-02-15 13:34:58 +01006607#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006608 SSL_get0_next_proto_negotiated(ctx->ssl, (const unsigned char **)str, (unsigned *)len);
Willy Tarreau8743f7e2016-12-04 18:44:29 +01006609 if (*str)
6610 return 1;
6611#endif
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006612#endif
Willy Tarreau8743f7e2016-12-04 18:44:29 +01006613 return 0;
6614}
6615
Willy Tarreau7875d092012-09-10 08:20:03 +02006616/***** Below are some sample fetching functions for ACL/patterns *****/
6617
Olivier Houchardccaa7de2017-10-02 11:51:03 +02006618static int
6619smp_fetch_ssl_fc_has_early(const struct arg *args, struct sample *smp, const char *kw, void *private)
6620{
6621 struct connection *conn;
6622
6623 conn = objt_conn(smp->sess->origin);
6624 if (!conn || conn->xprt != &ssl_sock)
6625 return 0;
6626
6627 smp->flags = 0;
6628 smp->data.type = SMP_T_BOOL;
Emmanuel Hocdetbb8643c2019-08-07 14:44:49 +02006629#ifdef OPENSSL_IS_BORINGSSL
6630 {
6631 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
6632 smp->data.u.sint = (SSL_in_early_data(ctx->ssl) &&
6633 SSL_early_data_accepted(ctx->ssl));
6634 }
6635#else
Olivier Houchard25ae45a2017-11-29 19:51:19 +01006636 smp->data.u.sint = ((conn->flags & CO_FL_EARLY_DATA) &&
6637 (conn->flags & (CO_FL_EARLY_SSL_HS | CO_FL_HANDSHAKE))) ? 1 : 0;
Emmanuel Hocdetbb8643c2019-08-07 14:44:49 +02006638#endif
Olivier Houchardccaa7de2017-10-02 11:51:03 +02006639 return 1;
6640}
6641
Emeric Brune64aef12012-09-21 13:15:06 +02006642/* boolean, returns true if client cert was present */
6643static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006644smp_fetch_ssl_fc_has_crt(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brune64aef12012-09-21 13:15:06 +02006645{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006646 struct connection *conn;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006647 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006648
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006649 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006650 if (!conn || conn->xprt != &ssl_sock)
Emeric Brune64aef12012-09-21 13:15:06 +02006651 return 0;
6652
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006653 ctx = conn->xprt_ctx;
6654
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006655 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brune64aef12012-09-21 13:15:06 +02006656 smp->flags |= SMP_F_MAY_CHANGE;
6657 return 0;
6658 }
6659
6660 smp->flags = 0;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006661 smp->data.type = SMP_T_BOOL;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006662 smp->data.u.sint = SSL_SOCK_ST_FL_VERIFY_DONE & ctx->xprt_st ? 1 : 0;
Emeric Brune64aef12012-09-21 13:15:06 +02006663
6664 return 1;
6665}
6666
Emeric Brun43e79582014-10-29 19:03:26 +01006667/* binary, returns a certificate in a binary chunk (der/raw).
6668 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6669 * should be use.
6670 */
6671static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006672smp_fetch_ssl_x_der(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun43e79582014-10-29 19:03:26 +01006673{
6674 int cert_peer = (kw[4] == 'c') ? 1 : 0;
6675 X509 *crt = NULL;
6676 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02006677 struct buffer *smp_trash;
Emeric Brun43e79582014-10-29 19:03:26 +01006678 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006679 struct ssl_sock_ctx *ctx;
Emeric Brun43e79582014-10-29 19:03:26 +01006680
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006681 conn = objt_conn(smp->sess->origin);
Emeric Brun43e79582014-10-29 19:03:26 +01006682 if (!conn || conn->xprt != &ssl_sock)
6683 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006684 ctx = conn->xprt_ctx;
Emeric Brun43e79582014-10-29 19:03:26 +01006685
6686 if (!(conn->flags & CO_FL_CONNECTED)) {
6687 smp->flags |= SMP_F_MAY_CHANGE;
6688 return 0;
6689 }
6690
6691 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006692 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brun43e79582014-10-29 19:03:26 +01006693 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01006694 crt = SSL_get_certificate(ctx->ssl);
Emeric Brun43e79582014-10-29 19:03:26 +01006695
6696 if (!crt)
6697 goto out;
6698
6699 smp_trash = get_trash_chunk();
6700 if (ssl_sock_crt2der(crt, smp_trash) <= 0)
6701 goto out;
6702
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006703 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006704 smp->data.type = SMP_T_BIN;
Emeric Brun43e79582014-10-29 19:03:26 +01006705 ret = 1;
6706out:
6707 /* SSL_get_peer_certificate, it increase X509 * ref count */
6708 if (cert_peer && crt)
6709 X509_free(crt);
6710 return ret;
6711}
6712
Emeric Brunba841a12014-04-30 17:05:08 +02006713/* binary, returns serial of certificate in a binary chunk.
6714 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6715 * should be use.
6716 */
Willy Tarreau8d598402012-10-22 17:58:39 +02006717static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006718smp_fetch_ssl_x_serial(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau8d598402012-10-22 17:58:39 +02006719{
Emeric Brunba841a12014-04-30 17:05:08 +02006720 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Willy Tarreau8d598402012-10-22 17:58:39 +02006721 X509 *crt = NULL;
6722 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02006723 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006724 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006725 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006726
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006727 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006728 if (!conn || conn->xprt != &ssl_sock)
Willy Tarreau8d598402012-10-22 17:58:39 +02006729 return 0;
6730
Olivier Houchard66ab4982019-02-26 18:37:15 +01006731 ctx = conn->xprt_ctx;
6732
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006733 if (!(conn->flags & CO_FL_CONNECTED)) {
Willy Tarreau8d598402012-10-22 17:58:39 +02006734 smp->flags |= SMP_F_MAY_CHANGE;
6735 return 0;
6736 }
6737
Emeric Brunba841a12014-04-30 17:05:08 +02006738 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006739 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02006740 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01006741 crt = SSL_get_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02006742
Willy Tarreau8d598402012-10-22 17:58:39 +02006743 if (!crt)
6744 goto out;
6745
Willy Tarreau47ca5452012-12-23 20:22:19 +01006746 smp_trash = get_trash_chunk();
Willy Tarreau8d598402012-10-22 17:58:39 +02006747 if (ssl_sock_get_serial(crt, smp_trash) <= 0)
6748 goto out;
6749
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006750 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006751 smp->data.type = SMP_T_BIN;
Willy Tarreau8d598402012-10-22 17:58:39 +02006752 ret = 1;
6753out:
Emeric Brunba841a12014-04-30 17:05:08 +02006754 /* SSL_get_peer_certificate, it increase X509 * ref count */
6755 if (cert_peer && crt)
Willy Tarreau8d598402012-10-22 17:58:39 +02006756 X509_free(crt);
6757 return ret;
6758}
Emeric Brune64aef12012-09-21 13:15:06 +02006759
Emeric Brunba841a12014-04-30 17:05:08 +02006760/* binary, returns the client certificate's SHA-1 fingerprint (SHA-1 hash of DER-encoded certificate) in a binary chunk.
6761 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6762 * should be use.
6763 */
James Votha051b4a2013-05-14 20:37:59 +02006764static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006765smp_fetch_ssl_x_sha1(const struct arg *args, struct sample *smp, const char *kw, void *private)
James Votha051b4a2013-05-14 20:37:59 +02006766{
Emeric Brunba841a12014-04-30 17:05:08 +02006767 int cert_peer = (kw[4] == 'c') ? 1 : 0;
James Votha051b4a2013-05-14 20:37:59 +02006768 X509 *crt = NULL;
6769 const EVP_MD *digest;
6770 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02006771 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006772 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006773 struct ssl_sock_ctx *ctx;
James Votha051b4a2013-05-14 20:37:59 +02006774
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006775 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006776 if (!conn || conn->xprt != &ssl_sock)
6777 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006778 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006779
6780 if (!(conn->flags & CO_FL_CONNECTED)) {
James Votha051b4a2013-05-14 20:37:59 +02006781 smp->flags |= SMP_F_MAY_CHANGE;
6782 return 0;
6783 }
6784
Emeric Brunba841a12014-04-30 17:05:08 +02006785 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006786 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02006787 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01006788 crt = SSL_get_certificate(ctx->ssl);
James Votha051b4a2013-05-14 20:37:59 +02006789 if (!crt)
6790 goto out;
6791
6792 smp_trash = get_trash_chunk();
6793 digest = EVP_sha1();
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006794 X509_digest(crt, digest, (unsigned char *) smp_trash->area,
6795 (unsigned int *)&smp_trash->data);
James Votha051b4a2013-05-14 20:37:59 +02006796
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006797 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006798 smp->data.type = SMP_T_BIN;
James Votha051b4a2013-05-14 20:37:59 +02006799 ret = 1;
6800out:
Emeric Brunba841a12014-04-30 17:05:08 +02006801 /* SSL_get_peer_certificate, it increase X509 * ref count */
6802 if (cert_peer && crt)
James Votha051b4a2013-05-14 20:37:59 +02006803 X509_free(crt);
6804 return ret;
6805}
6806
Emeric Brunba841a12014-04-30 17:05:08 +02006807/* string, returns certificate's notafter date in ASN1_UTCTIME format.
6808 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6809 * should be use.
6810 */
Emeric Brunce5ad802012-10-22 14:11:22 +02006811static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006812smp_fetch_ssl_x_notafter(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunce5ad802012-10-22 14:11:22 +02006813{
Emeric Brunba841a12014-04-30 17:05:08 +02006814 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brunce5ad802012-10-22 14:11:22 +02006815 X509 *crt = NULL;
6816 int ret = 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;
Emeric Brunce5ad802012-10-22 14:11:22 +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)) {
Emeric Brunce5ad802012-10-22 14:11:22 +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);
Emeric Brunce5ad802012-10-22 14:11:22 +02006835 if (!crt)
6836 goto out;
6837
Willy Tarreau47ca5452012-12-23 20:22:19 +01006838 smp_trash = get_trash_chunk();
Rosen Penev68185952018-12-14 08:47:02 -08006839 if (ssl_sock_get_time(X509_getm_notAfter(crt), smp_trash) <= 0)
Emeric Brunce5ad802012-10-22 14:11:22 +02006840 goto out;
6841
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_STR;
Emeric Brunce5ad802012-10-22 14:11:22 +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)
Emeric Brunce5ad802012-10-22 14:11:22 +02006848 X509_free(crt);
6849 return ret;
6850}
6851
Emeric Brunba841a12014-04-30 17:05:08 +02006852/* string, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. of certificate's issuer
6853 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6854 * should be use.
6855 */
Emeric Brun87855892012-10-17 17:39:35 +02006856static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006857smp_fetch_ssl_x_i_dn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun87855892012-10-17 17:39:35 +02006858{
Emeric Brunba841a12014-04-30 17:05:08 +02006859 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun87855892012-10-17 17:39:35 +02006860 X509 *crt = NULL;
6861 X509_NAME *name;
6862 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02006863 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006864 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006865 struct ssl_sock_ctx *ctx;
Emeric Brun87855892012-10-17 17:39:35 +02006866
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006867 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006868 if (!conn || conn->xprt != &ssl_sock)
6869 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006870 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006871
6872 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02006873 smp->flags |= SMP_F_MAY_CHANGE;
6874 return 0;
6875 }
6876
Emeric Brunba841a12014-04-30 17:05:08 +02006877 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006878 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02006879 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01006880 crt = SSL_get_certificate(ctx->ssl);
Emeric Brun87855892012-10-17 17:39:35 +02006881 if (!crt)
6882 goto out;
6883
6884 name = X509_get_issuer_name(crt);
6885 if (!name)
6886 goto out;
6887
Willy Tarreau47ca5452012-12-23 20:22:19 +01006888 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02006889 if (args && args[0].type == ARGT_STR) {
6890 int pos = 1;
6891
6892 if (args[1].type == ARGT_SINT)
6893 pos = args[1].data.sint;
Emeric Brun87855892012-10-17 17:39:35 +02006894
6895 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
6896 goto out;
6897 }
6898 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
6899 goto out;
6900
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006901 smp->data.type = SMP_T_STR;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006902 smp->data.u.str = *smp_trash;
Emeric Brun87855892012-10-17 17:39:35 +02006903 ret = 1;
6904out:
Emeric Brunba841a12014-04-30 17:05:08 +02006905 /* SSL_get_peer_certificate, it increase X509 * ref count */
6906 if (cert_peer && crt)
Emeric Brun87855892012-10-17 17:39:35 +02006907 X509_free(crt);
6908 return ret;
6909}
6910
Emeric Brunba841a12014-04-30 17:05:08 +02006911/* string, returns notbefore date in ASN1_UTCTIME format.
6912 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6913 * should be use.
6914 */
Emeric Brunce5ad802012-10-22 14:11:22 +02006915static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006916smp_fetch_ssl_x_notbefore(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunce5ad802012-10-22 14:11:22 +02006917{
Emeric Brunba841a12014-04-30 17:05:08 +02006918 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brunce5ad802012-10-22 14:11:22 +02006919 X509 *crt = NULL;
6920 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02006921 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006922 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006923 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006924
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006925 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006926 if (!conn || conn->xprt != &ssl_sock)
Emeric Brunce5ad802012-10-22 14:11:22 +02006927 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006928 ctx = conn->xprt_ctx;
Emeric Brunce5ad802012-10-22 14:11:22 +02006929
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006930 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02006931 smp->flags |= SMP_F_MAY_CHANGE;
6932 return 0;
6933 }
6934
Emeric Brunba841a12014-04-30 17:05:08 +02006935 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006936 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02006937 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01006938 crt = SSL_get_certificate(ctx->ssl);
Emeric Brunce5ad802012-10-22 14:11:22 +02006939 if (!crt)
6940 goto out;
6941
Willy Tarreau47ca5452012-12-23 20:22:19 +01006942 smp_trash = get_trash_chunk();
Rosen Penev68185952018-12-14 08:47:02 -08006943 if (ssl_sock_get_time(X509_getm_notBefore(crt), smp_trash) <= 0)
Emeric Brunce5ad802012-10-22 14:11:22 +02006944 goto out;
6945
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006946 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006947 smp->data.type = SMP_T_STR;
Emeric Brunce5ad802012-10-22 14:11:22 +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 Brunce5ad802012-10-22 14:11:22 +02006952 X509_free(crt);
6953 return ret;
6954}
6955
Emeric Brunba841a12014-04-30 17:05:08 +02006956/* string, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. of certificate's subject
6957 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6958 * should be use.
6959 */
Emeric Brun87855892012-10-17 17:39:35 +02006960static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006961smp_fetch_ssl_x_s_dn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun87855892012-10-17 17:39:35 +02006962{
Emeric Brunba841a12014-04-30 17:05:08 +02006963 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun87855892012-10-17 17:39:35 +02006964 X509 *crt = NULL;
6965 X509_NAME *name;
6966 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02006967 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006968 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006969 struct ssl_sock_ctx *ctx;
Emeric Brun87855892012-10-17 17:39:35 +02006970
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006971 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006972 if (!conn || conn->xprt != &ssl_sock)
6973 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006974 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006975
6976 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02006977 smp->flags |= SMP_F_MAY_CHANGE;
6978 return 0;
6979 }
6980
Emeric Brunba841a12014-04-30 17:05:08 +02006981 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006982 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02006983 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01006984 crt = SSL_get_certificate(ctx->ssl);
Emeric Brun87855892012-10-17 17:39:35 +02006985 if (!crt)
6986 goto out;
6987
6988 name = X509_get_subject_name(crt);
6989 if (!name)
6990 goto out;
6991
Willy Tarreau47ca5452012-12-23 20:22:19 +01006992 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02006993 if (args && args[0].type == ARGT_STR) {
6994 int pos = 1;
6995
6996 if (args[1].type == ARGT_SINT)
6997 pos = args[1].data.sint;
Emeric Brun87855892012-10-17 17:39:35 +02006998
6999 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
7000 goto out;
7001 }
7002 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
7003 goto out;
7004
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007005 smp->data.type = SMP_T_STR;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007006 smp->data.u.str = *smp_trash;
Emeric Brun87855892012-10-17 17:39:35 +02007007 ret = 1;
7008out:
Emeric Brunba841a12014-04-30 17:05:08 +02007009 /* SSL_get_peer_certificate, it increase X509 * ref count */
7010 if (cert_peer && crt)
Emeric Brun87855892012-10-17 17:39:35 +02007011 X509_free(crt);
7012 return ret;
7013}
Emeric Brun9143d372012-12-20 15:44:16 +01007014
7015/* integer, returns true if current session use a client certificate */
7016static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007017smp_fetch_ssl_c_used(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun9143d372012-12-20 15:44:16 +01007018{
7019 X509 *crt;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007020 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007021 struct ssl_sock_ctx *ctx;
Emeric Brun9143d372012-12-20 15:44:16 +01007022
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007023 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007024 if (!conn || conn->xprt != &ssl_sock)
7025 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007026 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007027
7028 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun9143d372012-12-20 15:44:16 +01007029 smp->flags |= SMP_F_MAY_CHANGE;
7030 return 0;
7031 }
7032
7033 /* SSL_get_peer_certificate returns a ptr on allocated X509 struct */
Olivier Houchard66ab4982019-02-26 18:37:15 +01007034 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brun9143d372012-12-20 15:44:16 +01007035 if (crt) {
7036 X509_free(crt);
7037 }
7038
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007039 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007040 smp->data.u.sint = (crt != NULL);
Emeric Brun9143d372012-12-20 15:44:16 +01007041 return 1;
7042}
7043
Emeric Brunba841a12014-04-30 17:05:08 +02007044/* integer, returns the certificate version
7045 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7046 * should be use.
7047 */
Emeric Bruna7359fd2012-10-17 15:03:11 +02007048static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007049smp_fetch_ssl_x_version(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Bruna7359fd2012-10-17 15:03:11 +02007050{
Emeric Brunba841a12014-04-30 17:05:08 +02007051 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Bruna7359fd2012-10-17 15:03:11 +02007052 X509 *crt;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007053 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007054 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007055
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007056 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007057 if (!conn || conn->xprt != &ssl_sock)
Emeric Bruna7359fd2012-10-17 15:03:11 +02007058 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007059 ctx = conn->xprt_ctx;
Emeric Bruna7359fd2012-10-17 15:03:11 +02007060
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007061 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Bruna7359fd2012-10-17 15:03:11 +02007062 smp->flags |= SMP_F_MAY_CHANGE;
7063 return 0;
7064 }
7065
Emeric Brunba841a12014-04-30 17:05:08 +02007066 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007067 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007068 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007069 crt = SSL_get_certificate(ctx->ssl);
Emeric Bruna7359fd2012-10-17 15:03:11 +02007070 if (!crt)
7071 return 0;
7072
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007073 smp->data.u.sint = (unsigned int)(1 + X509_get_version(crt));
Emeric Brunba841a12014-04-30 17:05:08 +02007074 /* SSL_get_peer_certificate increase X509 * ref count */
7075 if (cert_peer)
7076 X509_free(crt);
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007077 smp->data.type = SMP_T_SINT;
Emeric Bruna7359fd2012-10-17 15:03:11 +02007078
7079 return 1;
7080}
7081
Emeric Brunba841a12014-04-30 17:05:08 +02007082/* string, returns the certificate's signature algorithm.
7083 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7084 * should be use.
7085 */
Emeric Brun7f56e742012-10-19 18:15:40 +02007086static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007087smp_fetch_ssl_x_sig_alg(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun7f56e742012-10-19 18:15:40 +02007088{
Emeric Brunba841a12014-04-30 17:05:08 +02007089 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun7f56e742012-10-19 18:15:40 +02007090 X509 *crt;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007091 __OPENSSL_110_CONST__ ASN1_OBJECT *algorithm;
Emeric Brun7f56e742012-10-19 18:15:40 +02007092 int nid;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007093 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007094 struct ssl_sock_ctx *ctx;
Emeric Brun7f56e742012-10-19 18:15:40 +02007095
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007096 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007097 if (!conn || conn->xprt != &ssl_sock)
7098 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007099 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007100
7101 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun7f56e742012-10-19 18:15:40 +02007102 smp->flags |= SMP_F_MAY_CHANGE;
7103 return 0;
7104 }
7105
Emeric Brunba841a12014-04-30 17:05:08 +02007106 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007107 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007108 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007109 crt = SSL_get_certificate(ctx->ssl);
Emeric Brun7f56e742012-10-19 18:15:40 +02007110 if (!crt)
7111 return 0;
7112
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007113 X509_ALGOR_get0(&algorithm, NULL, NULL, X509_get0_tbs_sigalg(crt));
7114 nid = OBJ_obj2nid(algorithm);
Emeric Brun7f56e742012-10-19 18:15:40 +02007115
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007116 smp->data.u.str.area = (char *)OBJ_nid2sn(nid);
7117 if (!smp->data.u.str.area) {
Emeric Brunba841a12014-04-30 17:05:08 +02007118 /* SSL_get_peer_certificate increase X509 * ref count */
7119 if (cert_peer)
7120 X509_free(crt);
Emeric Brun7f56e742012-10-19 18:15:40 +02007121 return 0;
Emeric Brun9bf3ba22013-10-07 14:31:44 +02007122 }
Emeric Brun7f56e742012-10-19 18:15:40 +02007123
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007124 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01007125 smp->flags |= SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007126 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brunba841a12014-04-30 17:05:08 +02007127 /* SSL_get_peer_certificate increase X509 * ref count */
7128 if (cert_peer)
7129 X509_free(crt);
Emeric Brun7f56e742012-10-19 18:15:40 +02007130
7131 return 1;
7132}
7133
Emeric Brunba841a12014-04-30 17:05:08 +02007134/* string, returns the certificate's key algorithm.
7135 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7136 * should be use.
7137 */
Emeric Brun521a0112012-10-22 12:22:55 +02007138static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007139smp_fetch_ssl_x_key_alg(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun521a0112012-10-22 12:22:55 +02007140{
Emeric Brunba841a12014-04-30 17:05:08 +02007141 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun521a0112012-10-22 12:22:55 +02007142 X509 *crt;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007143 ASN1_OBJECT *algorithm;
Emeric Brun521a0112012-10-22 12:22:55 +02007144 int nid;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007145 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007146 struct ssl_sock_ctx *ctx;
Emeric Brun521a0112012-10-22 12:22:55 +02007147
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007148 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007149 if (!conn || conn->xprt != &ssl_sock)
7150 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007151 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007152
7153 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun521a0112012-10-22 12:22:55 +02007154 smp->flags |= SMP_F_MAY_CHANGE;
7155 return 0;
7156 }
7157
Emeric Brunba841a12014-04-30 17:05:08 +02007158 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007159 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007160 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007161 crt = SSL_get_certificate(ctx->ssl);
Emeric Brun521a0112012-10-22 12:22:55 +02007162 if (!crt)
7163 return 0;
7164
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007165 X509_PUBKEY_get0_param(&algorithm, NULL, NULL, NULL, X509_get_X509_PUBKEY(crt));
7166 nid = OBJ_obj2nid(algorithm);
Emeric Brun521a0112012-10-22 12:22:55 +02007167
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007168 smp->data.u.str.area = (char *)OBJ_nid2sn(nid);
7169 if (!smp->data.u.str.area) {
Emeric Brunba841a12014-04-30 17:05:08 +02007170 /* SSL_get_peer_certificate increase X509 * ref count */
7171 if (cert_peer)
7172 X509_free(crt);
Emeric Brun521a0112012-10-22 12:22:55 +02007173 return 0;
Emeric Brun9bf3ba22013-10-07 14:31:44 +02007174 }
Emeric Brun521a0112012-10-22 12:22:55 +02007175
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007176 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01007177 smp->flags |= SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007178 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brunba841a12014-04-30 17:05:08 +02007179 if (cert_peer)
7180 X509_free(crt);
Emeric Brun521a0112012-10-22 12:22:55 +02007181
7182 return 1;
7183}
7184
Emeric Brun645ae792014-04-30 14:21:06 +02007185/* boolean, returns true if front conn. transport layer is SSL.
7186 * This function is also usable on backend conn if the fetch keyword 5th
7187 * char is 'b'.
7188 */
Willy Tarreau7875d092012-09-10 08:20:03 +02007189static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007190smp_fetch_ssl_fc(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02007191{
Emeric Bruneb8def92018-02-19 15:59:48 +01007192 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7193 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007194
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007195 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007196 smp->data.u.sint = (conn && conn->xprt == &ssl_sock);
Willy Tarreau7875d092012-09-10 08:20:03 +02007197 return 1;
7198}
7199
Emeric Brun2525b6b2012-10-18 15:59:43 +02007200/* boolean, returns true if client present a SNI */
Willy Tarreau7875d092012-09-10 08:20:03 +02007201static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007202smp_fetch_ssl_fc_has_sni(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02007203{
7204#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007205 struct connection *conn = objt_conn(smp->sess->origin);
Olivier Houchard66ab4982019-02-26 18:37:15 +01007206 struct ssl_sock_ctx *ctx = conn ? conn->xprt_ctx : NULL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007207
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007208 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007209 smp->data.u.sint = (conn && conn->xprt == &ssl_sock) &&
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007210 conn->xprt_ctx &&
Olivier Houchard66ab4982019-02-26 18:37:15 +01007211 SSL_get_servername(ctx->ssl, TLSEXT_NAMETYPE_host_name) != NULL;
Willy Tarreau7875d092012-09-10 08:20:03 +02007212 return 1;
7213#else
7214 return 0;
7215#endif
7216}
7217
Emeric Brun74f7ffa2018-02-19 16:14:12 +01007218/* boolean, returns true if client session has been resumed.
7219 * This function is also usable on backend conn if the fetch keyword 5th
7220 * char is 'b'.
7221 */
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02007222static int
7223smp_fetch_ssl_fc_is_resumed(const struct arg *args, struct sample *smp, const char *kw, void *private)
7224{
Emeric Brun74f7ffa2018-02-19 16:14:12 +01007225 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7226 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007227 struct ssl_sock_ctx *ctx = conn ? conn->xprt_ctx : NULL;
Emeric Brun74f7ffa2018-02-19 16:14:12 +01007228
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02007229
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007230 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007231 smp->data.u.sint = (conn && conn->xprt == &ssl_sock) &&
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02007232 conn->xprt_ctx &&
Olivier Houchard66ab4982019-02-26 18:37:15 +01007233 SSL_session_reused(ctx->ssl);
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02007234 return 1;
7235}
7236
Emeric Brun645ae792014-04-30 14:21:06 +02007237/* string, returns the used cipher if front conn. transport layer is SSL.
7238 * This function is also usable on backend conn if the fetch keyword 5th
7239 * char is 'b'.
7240 */
Emeric Brun589fcad2012-10-16 14:13:26 +02007241static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007242smp_fetch_ssl_fc_cipher(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02007243{
Emeric Bruneb8def92018-02-19 15:59:48 +01007244 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7245 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007246 struct ssl_sock_ctx *ctx;
Emeric Brun589fcad2012-10-16 14:13:26 +02007247
Willy Tarreaube508f12016-03-10 11:47:01 +01007248 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007249 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02007250 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007251 ctx = conn->xprt_ctx;
Emeric Brun589fcad2012-10-16 14:13:26 +02007252
Olivier Houchard66ab4982019-02-26 18:37:15 +01007253 smp->data.u.str.area = (char *)SSL_get_cipher_name(ctx->ssl);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007254 if (!smp->data.u.str.area)
Emeric Brun589fcad2012-10-16 14:13:26 +02007255 return 0;
7256
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007257 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01007258 smp->flags |= SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007259 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brun589fcad2012-10-16 14:13:26 +02007260
7261 return 1;
7262}
7263
Emeric Brun645ae792014-04-30 14:21:06 +02007264/* integer, returns the algoritm's keysize if front conn. transport layer
7265 * is SSL.
7266 * This function is also usable on backend conn if the fetch keyword 5th
7267 * char is 'b'.
7268 */
Emeric Brun589fcad2012-10-16 14:13:26 +02007269static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007270smp_fetch_ssl_fc_alg_keysize(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02007271{
Emeric Bruneb8def92018-02-19 15:59:48 +01007272 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7273 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007274 struct ssl_sock_ctx *ctx;
Willy Tarreaue237fe12016-03-10 17:05:28 +01007275 int sint;
Willy Tarreaube508f12016-03-10 11:47:01 +01007276
Emeric Brun589fcad2012-10-16 14:13:26 +02007277 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007278 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02007279 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007280 ctx = conn->xprt_ctx;
Emeric Brun589fcad2012-10-16 14:13:26 +02007281
Olivier Houchard66ab4982019-02-26 18:37:15 +01007282 if (!SSL_get_cipher_bits(ctx->ssl, &sint))
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007283 return 0;
7284
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007285 smp->data.u.sint = sint;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007286 smp->data.type = SMP_T_SINT;
Emeric Brun589fcad2012-10-16 14:13:26 +02007287
7288 return 1;
7289}
7290
Emeric Brun645ae792014-04-30 14:21:06 +02007291/* integer, returns the used keysize if front conn. transport layer is SSL.
7292 * This function is also usable on backend conn if the fetch keyword 5th
7293 * char is 'b'.
7294 */
Emeric Brun589fcad2012-10-16 14:13:26 +02007295static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007296smp_fetch_ssl_fc_use_keysize(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02007297{
Emeric Bruneb8def92018-02-19 15:59:48 +01007298 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7299 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007300 struct ssl_sock_ctx *ctx;
Willy Tarreaube508f12016-03-10 11:47:01 +01007301
Emeric Brun589fcad2012-10-16 14:13:26 +02007302 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007303 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7304 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007305 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007306
Olivier Houchard66ab4982019-02-26 18:37:15 +01007307 smp->data.u.sint = (unsigned int)SSL_get_cipher_bits(ctx->ssl, NULL);
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007308 if (!smp->data.u.sint)
Emeric Brun589fcad2012-10-16 14:13:26 +02007309 return 0;
7310
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007311 smp->data.type = SMP_T_SINT;
Emeric Brun589fcad2012-10-16 14:13:26 +02007312
7313 return 1;
7314}
7315
Bernard Spil13c53f82018-02-15 13:34:58 +01007316#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Willy Tarreau7875d092012-09-10 08:20:03 +02007317static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007318smp_fetch_ssl_fc_npn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreaua33c6542012-10-15 13:19:06 +02007319{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007320 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007321 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007322
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01007323 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007324 smp->data.type = SMP_T_STR;
Willy Tarreaua33c6542012-10-15 13:19:06 +02007325
Olivier Houchard6b77f492018-11-22 18:18:29 +01007326 conn = (kw[4] != 'b' ) ? objt_conn(smp->sess->origin) :
7327 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007328 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7329 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007330 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007331
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007332 smp->data.u.str.area = NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007333 SSL_get0_next_proto_negotiated(ctx->ssl,
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007334 (const unsigned char **)&smp->data.u.str.area,
7335 (unsigned *)&smp->data.u.str.data);
Willy Tarreaua33c6542012-10-15 13:19:06 +02007336
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007337 if (!smp->data.u.str.area)
Willy Tarreaua33c6542012-10-15 13:19:06 +02007338 return 0;
7339
7340 return 1;
Willy Tarreaua33c6542012-10-15 13:19:06 +02007341}
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02007342#endif
Willy Tarreaua33c6542012-10-15 13:19:06 +02007343
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01007344#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02007345static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007346smp_fetch_ssl_fc_alpn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreauab861d32013-04-02 02:30:41 +02007347{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007348 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007349 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007350
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01007351 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007352 smp->data.type = SMP_T_STR;
Willy Tarreauab861d32013-04-02 02:30:41 +02007353
Olivier Houchard6b77f492018-11-22 18:18:29 +01007354 conn = (kw[4] != 'b' ) ? objt_conn(smp->sess->origin) :
7355 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
7356
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007357 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Willy Tarreauab861d32013-04-02 02:30:41 +02007358 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007359 ctx = conn->xprt_ctx;
Willy Tarreauab861d32013-04-02 02:30:41 +02007360
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007361 smp->data.u.str.area = NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007362 SSL_get0_alpn_selected(ctx->ssl,
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007363 (const unsigned char **)&smp->data.u.str.area,
7364 (unsigned *)&smp->data.u.str.data);
Willy Tarreauab861d32013-04-02 02:30:41 +02007365
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007366 if (!smp->data.u.str.area)
Willy Tarreauab861d32013-04-02 02:30:41 +02007367 return 0;
7368
7369 return 1;
7370}
7371#endif
7372
Emeric Brun645ae792014-04-30 14:21:06 +02007373/* string, returns the used protocol if front conn. transport layer is SSL.
7374 * This function is also usable on backend conn if the fetch keyword 5th
7375 * char is 'b'.
7376 */
Willy Tarreaua33c6542012-10-15 13:19:06 +02007377static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007378smp_fetch_ssl_fc_protocol(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02007379{
Emeric Bruneb8def92018-02-19 15:59:48 +01007380 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7381 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007382 struct ssl_sock_ctx *ctx;
Willy Tarreaube508f12016-03-10 11:47:01 +01007383
Emeric Brun589fcad2012-10-16 14:13:26 +02007384 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007385 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7386 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007387 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007388
Olivier Houchard66ab4982019-02-26 18:37:15 +01007389 smp->data.u.str.area = (char *)SSL_get_version(ctx->ssl);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007390 if (!smp->data.u.str.area)
Emeric Brun589fcad2012-10-16 14:13:26 +02007391 return 0;
7392
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007393 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01007394 smp->flags = SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007395 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brun589fcad2012-10-16 14:13:26 +02007396
7397 return 1;
7398}
7399
Willy Tarreau87b09662015-04-03 00:22:06 +02007400/* binary, returns the SSL stream id if front conn. transport layer is SSL.
Emeric Brun645ae792014-04-30 14:21:06 +02007401 * This function is also usable on backend conn if the fetch keyword 5th
7402 * char is 'b'.
7403 */
Willy Tarreau9a1ab082019-05-09 13:26:41 +02007404#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
Emeric Brun589fcad2012-10-16 14:13:26 +02007405static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007406smp_fetch_ssl_fc_session_id(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunfe68f682012-10-16 14:59:28 +02007407{
Emeric Bruneb8def92018-02-19 15:59:48 +01007408 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7409 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaue237fe12016-03-10 17:05:28 +01007410 SSL_SESSION *ssl_sess;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007411 struct ssl_sock_ctx *ctx;
Willy Tarreaube508f12016-03-10 11:47:01 +01007412
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01007413 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007414 smp->data.type = SMP_T_BIN;
Emeric Brunfe68f682012-10-16 14:59:28 +02007415
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007416 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7417 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007418 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007419
Olivier Houchard66ab4982019-02-26 18:37:15 +01007420 ssl_sess = SSL_get_session(ctx->ssl);
Willy Tarreau192252e2015-04-04 01:47:55 +02007421 if (!ssl_sess)
Emeric Brunfe68f682012-10-16 14:59:28 +02007422 return 0;
7423
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007424 smp->data.u.str.area = (char *)SSL_SESSION_get_id(ssl_sess,
7425 (unsigned int *)&smp->data.u.str.data);
7426 if (!smp->data.u.str.area || !smp->data.u.str.data)
Emeric Brunfe68f682012-10-16 14:59:28 +02007427 return 0;
7428
7429 return 1;
Emeric Brunfe68f682012-10-16 14:59:28 +02007430}
Patrick Hemmer41966772018-04-28 19:15:48 -04007431#endif
7432
Emeric Brunfe68f682012-10-16 14:59:28 +02007433
Emmanuel Hocdet839af572019-05-14 16:27:35 +02007434#if HA_OPENSSL_VERSION_NUMBER >= 0x10100000L
Patrick Hemmere0275472018-04-28 19:15:51 -04007435static int
Patrick Hemmer65674662019-06-04 08:13:03 -04007436smp_fetch_ssl_fc_random(const struct arg *args, struct sample *smp, const char *kw, void *private)
7437{
7438 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7439 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
7440 struct buffer *data;
7441 struct ssl_sock_ctx *ctx;
7442
7443 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7444 return 0;
7445 ctx = conn->xprt_ctx;
7446
7447 data = get_trash_chunk();
7448 if (kw[7] == 'c')
7449 data->data = SSL_get_client_random(ctx->ssl,
7450 (unsigned char *) data->area,
7451 data->size);
7452 else
7453 data->data = SSL_get_server_random(ctx->ssl,
7454 (unsigned char *) data->area,
7455 data->size);
7456 if (!data->data)
7457 return 0;
7458
7459 smp->flags = 0;
7460 smp->data.type = SMP_T_BIN;
7461 smp->data.u.str = *data;
7462
7463 return 1;
7464}
7465
7466static int
Patrick Hemmere0275472018-04-28 19:15:51 -04007467smp_fetch_ssl_fc_session_key(const struct arg *args, struct sample *smp, const char *kw, void *private)
7468{
7469 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7470 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
7471 SSL_SESSION *ssl_sess;
Willy Tarreau83061a82018-07-13 11:56:34 +02007472 struct buffer *data;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007473 struct ssl_sock_ctx *ctx;
Patrick Hemmere0275472018-04-28 19:15:51 -04007474
7475 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7476 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007477 ctx = conn->xprt_ctx;
Patrick Hemmere0275472018-04-28 19:15:51 -04007478
Olivier Houchard66ab4982019-02-26 18:37:15 +01007479 ssl_sess = SSL_get_session(ctx->ssl);
Patrick Hemmere0275472018-04-28 19:15:51 -04007480 if (!ssl_sess)
7481 return 0;
7482
7483 data = get_trash_chunk();
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007484 data->data = SSL_SESSION_get_master_key(ssl_sess,
7485 (unsigned char *) data->area,
7486 data->size);
7487 if (!data->data)
Patrick Hemmere0275472018-04-28 19:15:51 -04007488 return 0;
7489
7490 smp->flags = 0;
7491 smp->data.type = SMP_T_BIN;
7492 smp->data.u.str = *data;
7493
7494 return 1;
7495}
7496#endif
7497
Patrick Hemmer41966772018-04-28 19:15:48 -04007498#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emeric Brunfe68f682012-10-16 14:59:28 +02007499static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007500smp_fetch_ssl_fc_sni(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02007501{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007502 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007503 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007504
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01007505 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007506 smp->data.type = SMP_T_STR;
Willy Tarreau7875d092012-09-10 08:20:03 +02007507
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007508 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007509 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7510 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007511 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007512
Olivier Houchard66ab4982019-02-26 18:37:15 +01007513 smp->data.u.str.area = (char *)SSL_get_servername(ctx->ssl, TLSEXT_NAMETYPE_host_name);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007514 if (!smp->data.u.str.area)
Willy Tarreau3e394c92012-09-14 23:56:58 +02007515 return 0;
7516
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007517 smp->data.u.str.data = strlen(smp->data.u.str.area);
Willy Tarreau7875d092012-09-10 08:20:03 +02007518 return 1;
Willy Tarreau7875d092012-09-10 08:20:03 +02007519}
Patrick Hemmer41966772018-04-28 19:15:48 -04007520#endif
Willy Tarreau7875d092012-09-10 08:20:03 +02007521
David Sc1ad52e2014-04-08 18:48:47 -04007522static int
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007523smp_fetch_ssl_fc_cl_bin(const struct arg *args, struct sample *smp, const char *kw, void *private)
7524{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007525 struct connection *conn;
7526 struct ssl_capture *capture;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007527 struct ssl_sock_ctx *ctx;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007528
7529 conn = objt_conn(smp->sess->origin);
7530 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7531 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007532 ctx = conn->xprt_ctx;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007533
Olivier Houchard66ab4982019-02-26 18:37:15 +01007534 capture = SSL_get_ex_data(ctx->ssl, ssl_capture_ptr_index);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007535 if (!capture)
7536 return 0;
7537
7538 smp->flags = SMP_F_CONST;
7539 smp->data.type = SMP_T_BIN;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007540 smp->data.u.str.area = capture->ciphersuite;
7541 smp->data.u.str.data = capture->ciphersuite_len;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007542 return 1;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007543}
7544
7545static int
7546smp_fetch_ssl_fc_cl_hex(const struct arg *args, struct sample *smp, const char *kw, void *private)
7547{
Willy Tarreau83061a82018-07-13 11:56:34 +02007548 struct buffer *data;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007549
7550 if (!smp_fetch_ssl_fc_cl_bin(args, smp, kw, private))
7551 return 0;
7552
7553 data = get_trash_chunk();
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007554 dump_binary(data, smp->data.u.str.area, smp->data.u.str.data);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007555 smp->data.type = SMP_T_BIN;
7556 smp->data.u.str = *data;
7557 return 1;
7558}
7559
7560static int
7561smp_fetch_ssl_fc_cl_xxh64(const struct arg *args, struct sample *smp, const char *kw, void *private)
7562{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007563 struct connection *conn;
7564 struct ssl_capture *capture;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007565 struct ssl_sock_ctx *ctx;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007566
7567 conn = objt_conn(smp->sess->origin);
7568 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7569 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007570 ctx = conn->xprt_ctx;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007571
Olivier Houchard66ab4982019-02-26 18:37:15 +01007572 capture = SSL_get_ex_data(ctx->ssl, ssl_capture_ptr_index);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007573 if (!capture)
7574 return 0;
7575
7576 smp->data.type = SMP_T_SINT;
7577 smp->data.u.sint = capture->xxh64;
7578 return 1;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007579}
7580
7581static int
7582smp_fetch_ssl_fc_cl_str(const struct arg *args, struct sample *smp, const char *kw, void *private)
7583{
Willy Tarreau5db847a2019-05-09 14:13:35 +02007584#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL)
Willy Tarreau83061a82018-07-13 11:56:34 +02007585 struct buffer *data;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007586 int i;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007587
7588 if (!smp_fetch_ssl_fc_cl_bin(args, smp, kw, private))
7589 return 0;
7590
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007591 data = get_trash_chunk();
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007592 for (i = 0; i + 1 < smp->data.u.str.data; i += 2) {
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02007593 const char *str;
7594 const SSL_CIPHER *cipher;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007595 const unsigned char *bin = (const unsigned char *) smp->data.u.str.area + i;
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02007596 uint16_t id = (bin[0] << 8) | bin[1];
7597#if defined(OPENSSL_IS_BORINGSSL)
7598 cipher = SSL_get_cipher_by_value(id);
7599#else
Willy Tarreaub7290772018-10-15 11:01:59 +02007600 struct connection *conn = __objt_conn(smp->sess->origin);
Olivier Houchard66ab4982019-02-26 18:37:15 +01007601 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
7602 cipher = SSL_CIPHER_find(ctx->ssl, bin);
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02007603#endif
7604 str = SSL_CIPHER_get_name(cipher);
7605 if (!str || strcmp(str, "(NONE)") == 0)
7606 chunk_appendf(data, "%sUNKNOWN(%04x)", i == 0 ? "" : ",", id);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007607 else
7608 chunk_appendf(data, "%s%s", i == 0 ? "" : ",", str);
7609 }
7610 smp->data.type = SMP_T_STR;
7611 smp->data.u.str = *data;
7612 return 1;
7613#else
7614 return smp_fetch_ssl_fc_cl_xxh64(args, smp, kw, private);
7615#endif
7616}
7617
Willy Tarreau9a1ab082019-05-09 13:26:41 +02007618#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007619static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007620smp_fetch_ssl_fc_unique_id(const struct arg *args, struct sample *smp, const char *kw, void *private)
David Sc1ad52e2014-04-08 18:48:47 -04007621{
Emeric Bruneb8def92018-02-19 15:59:48 +01007622 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7623 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
David Sc1ad52e2014-04-08 18:48:47 -04007624 int finished_len;
Willy Tarreau83061a82018-07-13 11:56:34 +02007625 struct buffer *finished_trash;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007626 struct ssl_sock_ctx *ctx;
David Sc1ad52e2014-04-08 18:48:47 -04007627
7628 smp->flags = 0;
David Sc1ad52e2014-04-08 18:48:47 -04007629 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7630 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007631 ctx = conn->xprt_ctx;
David Sc1ad52e2014-04-08 18:48:47 -04007632
7633 if (!(conn->flags & CO_FL_CONNECTED)) {
7634 smp->flags |= SMP_F_MAY_CHANGE;
7635 return 0;
7636 }
7637
7638 finished_trash = get_trash_chunk();
Olivier Houchard66ab4982019-02-26 18:37:15 +01007639 if (!SSL_session_reused(ctx->ssl))
7640 finished_len = SSL_get_peer_finished(ctx->ssl,
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007641 finished_trash->area,
7642 finished_trash->size);
David Sc1ad52e2014-04-08 18:48:47 -04007643 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007644 finished_len = SSL_get_finished(ctx->ssl,
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007645 finished_trash->area,
7646 finished_trash->size);
David Sc1ad52e2014-04-08 18:48:47 -04007647
7648 if (!finished_len)
7649 return 0;
7650
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007651 finished_trash->data = finished_len;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007652 smp->data.u.str = *finished_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007653 smp->data.type = SMP_T_BIN;
David Sc1ad52e2014-04-08 18:48:47 -04007654
7655 return 1;
David Sc1ad52e2014-04-08 18:48:47 -04007656}
Patrick Hemmer41966772018-04-28 19:15:48 -04007657#endif
David Sc1ad52e2014-04-08 18:48:47 -04007658
Emeric Brun2525b6b2012-10-18 15:59:43 +02007659/* integer, returns the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02007660static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007661smp_fetch_ssl_c_ca_err(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunf282a812012-09-21 15:27:54 +02007662{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007663 struct connection *conn;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007664 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007665
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007666 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007667 if (!conn || conn->xprt != &ssl_sock)
7668 return 0;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007669 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007670
7671 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02007672 smp->flags = SMP_F_MAY_CHANGE;
7673 return 0;
7674 }
7675
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007676 smp->data.type = SMP_T_SINT;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007677 smp->data.u.sint = (unsigned long long int)SSL_SOCK_ST_TO_CA_ERROR(ctx->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02007678 smp->flags = 0;
7679
7680 return 1;
7681}
7682
Emeric Brun2525b6b2012-10-18 15:59:43 +02007683/* integer, returns the depth of the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02007684static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007685smp_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 +02007686{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007687 struct connection *conn;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007688 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007689
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007690 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007691 if (!conn || conn->xprt != &ssl_sock)
Emeric Brunf282a812012-09-21 15:27:54 +02007692 return 0;
7693
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007694 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02007695 smp->flags = SMP_F_MAY_CHANGE;
7696 return 0;
7697 }
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007698 ctx = conn->xprt_ctx;
Emeric Brunf282a812012-09-21 15:27:54 +02007699
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007700 smp->data.type = SMP_T_SINT;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007701 smp->data.u.sint = (long long int)SSL_SOCK_ST_TO_CAEDEPTH(ctx->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02007702 smp->flags = 0;
7703
7704 return 1;
7705}
7706
Emeric Brun2525b6b2012-10-18 15:59:43 +02007707/* integer, returns the first verify error on client certificate */
Emeric Brunf282a812012-09-21 15:27:54 +02007708static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007709smp_fetch_ssl_c_err(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunf282a812012-09-21 15:27:54 +02007710{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007711 struct connection *conn;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007712 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007713
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007714 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007715 if (!conn || conn->xprt != &ssl_sock)
7716 return 0;
7717
7718 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02007719 smp->flags = SMP_F_MAY_CHANGE;
7720 return 0;
7721 }
7722
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007723 ctx = conn->xprt_ctx;
7724
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007725 smp->data.type = SMP_T_SINT;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007726 smp->data.u.sint = (long long int)SSL_SOCK_ST_TO_CRTERROR(ctx->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02007727 smp->flags = 0;
7728
7729 return 1;
7730}
7731
Emeric Brun2525b6b2012-10-18 15:59:43 +02007732/* integer, returns the verify result on client cert */
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02007733static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007734smp_fetch_ssl_c_verify(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02007735{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007736 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007737 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007738
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007739 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007740 if (!conn || conn->xprt != &ssl_sock)
7741 return 0;
7742
7743 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02007744 smp->flags = SMP_F_MAY_CHANGE;
7745 return 0;
7746 }
7747
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007748 if (!conn->xprt_ctx)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02007749 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007750 ctx = conn->xprt_ctx;
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02007751
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007752 smp->data.type = SMP_T_SINT;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007753 smp->data.u.sint = (long long int)SSL_get_verify_result(ctx->ssl);
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02007754 smp->flags = 0;
7755
7756 return 1;
7757}
7758
Emeric Brunfb510ea2012-10-05 12:00:26 +02007759/* parse the "ca-file" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007760static 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 +02007761{
7762 if (!*args[cur_arg + 1]) {
7763 if (err)
7764 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
7765 return ERR_ALERT | ERR_FATAL;
7766 }
7767
Willy Tarreauef934602016-12-22 23:12:01 +01007768 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
7769 memprintf(&conf->ca_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02007770 else
7771 memprintf(&conf->ca_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02007772
Emeric Brund94b3fe2012-09-20 18:23:56 +02007773 return 0;
7774}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007775static int bind_parse_ca_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7776{
7777 return ssl_bind_parse_ca_file(args, cur_arg, px, &conf->ssl_conf, err);
7778}
Emeric Brund94b3fe2012-09-20 18:23:56 +02007779
Christopher Faulet31af49d2015-06-09 17:29:50 +02007780/* parse the "ca-sign-file" bind keyword */
7781static int bind_parse_ca_sign_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7782{
7783 if (!*args[cur_arg + 1]) {
7784 if (err)
7785 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
7786 return ERR_ALERT | ERR_FATAL;
7787 }
7788
Willy Tarreauef934602016-12-22 23:12:01 +01007789 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
7790 memprintf(&conf->ca_sign_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Christopher Faulet31af49d2015-06-09 17:29:50 +02007791 else
7792 memprintf(&conf->ca_sign_file, "%s", args[cur_arg + 1]);
7793
7794 return 0;
7795}
7796
Bertrand Jacquinff13c062016-11-13 16:37:11 +00007797/* parse the "ca-sign-pass" bind keyword */
Christopher Faulet31af49d2015-06-09 17:29:50 +02007798static int bind_parse_ca_sign_pass(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7799{
7800 if (!*args[cur_arg + 1]) {
7801 if (err)
7802 memprintf(err, "'%s' : missing CAkey password", args[cur_arg]);
7803 return ERR_ALERT | ERR_FATAL;
7804 }
7805 memprintf(&conf->ca_sign_pass, "%s", args[cur_arg + 1]);
7806 return 0;
7807}
7808
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007809/* parse the "ciphers" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007810static 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 +02007811{
7812 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02007813 memprintf(err, "'%s' : missing cipher suite", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007814 return ERR_ALERT | ERR_FATAL;
7815 }
7816
Emeric Brun76d88952012-10-05 15:47:31 +02007817 free(conf->ciphers);
Willy Tarreau4348fad2012-09-20 16:48:07 +02007818 conf->ciphers = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007819 return 0;
7820}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007821static int bind_parse_ciphers(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7822{
7823 return ssl_bind_parse_ciphers(args, cur_arg, px, &conf->ssl_conf, err);
7824}
Dirkjan Bussink415150f2018-09-14 11:14:21 +02007825
Emmanuel Hocdet839af572019-05-14 16:27:35 +02007826#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02007827/* parse the "ciphersuites" bind keyword */
7828static int ssl_bind_parse_ciphersuites(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
7829{
7830 if (!*args[cur_arg + 1]) {
7831 memprintf(err, "'%s' : missing cipher suite", args[cur_arg]);
7832 return ERR_ALERT | ERR_FATAL;
7833 }
7834
7835 free(conf->ciphersuites);
7836 conf->ciphersuites = strdup(args[cur_arg + 1]);
7837 return 0;
7838}
7839static int bind_parse_ciphersuites(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7840{
7841 return ssl_bind_parse_ciphersuites(args, cur_arg, px, &conf->ssl_conf, err);
7842}
7843#endif
7844
Willy Tarreaub131c872019-10-16 16:42:19 +02007845/* parse the "crt" bind keyword. Returns a set of ERR_* flags possibly with an error in <err>. */
Willy Tarreau4348fad2012-09-20 16:48:07 +02007846static 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 +02007847{
Willy Tarreau38011032013-08-13 16:59:39 +02007848 char path[MAXPATHLEN];
Willy Tarreaub75d6922014-04-14 18:05:41 +02007849
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007850 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02007851 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007852 return ERR_ALERT | ERR_FATAL;
7853 }
7854
Willy Tarreauef934602016-12-22 23:12:01 +01007855 if ((*args[cur_arg + 1] != '/' ) && global_ssl.crt_base) {
7856 if ((strlen(global_ssl.crt_base) + 1 + strlen(args[cur_arg + 1]) + 1) > MAXPATHLEN) {
Emeric Brunc8e8d122012-10-02 18:42:10 +02007857 memprintf(err, "'%s' : path too long", args[cur_arg]);
7858 return ERR_ALERT | ERR_FATAL;
7859 }
Willy Tarreauef934602016-12-22 23:12:01 +01007860 snprintf(path, sizeof(path), "%s/%s", global_ssl.crt_base, args[cur_arg + 1]);
Willy Tarreaub131c872019-10-16 16:42:19 +02007861 return ssl_sock_load_cert(path, conf, err);
Emeric Brunc8e8d122012-10-02 18:42:10 +02007862 }
7863
Willy Tarreaub131c872019-10-16 16:42:19 +02007864 return ssl_sock_load_cert(args[cur_arg + 1], conf, err);
Emeric Brund94b3fe2012-09-20 18:23:56 +02007865}
7866
Willy Tarreaub131c872019-10-16 16:42:19 +02007867/* 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 +01007868static int bind_parse_crt_list(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7869{
Willy Tarreaub131c872019-10-16 16:42:19 +02007870 int err_code;
7871
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01007872 if (!*args[cur_arg + 1]) {
7873 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
7874 return ERR_ALERT | ERR_FATAL;
7875 }
7876
Willy Tarreaub131c872019-10-16 16:42:19 +02007877 err_code = ssl_sock_load_cert_list_file(args[cur_arg + 1], conf, px, err);
7878 if (err_code)
Willy Tarreauad1731d2013-04-02 17:35:58 +02007879 memprintf(err, "'%s' : %s", args[cur_arg], *err);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01007880
Willy Tarreaub131c872019-10-16 16:42:19 +02007881 return err_code;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01007882}
7883
Emeric Brunfb510ea2012-10-05 12:00:26 +02007884/* parse the "crl-file" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007885static 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 +02007886{
Emeric Brun051cdab2012-10-02 19:25:50 +02007887#ifndef X509_V_FLAG_CRL_CHECK
7888 if (err)
7889 memprintf(err, "'%s' : library does not support CRL verify", args[cur_arg]);
7890 return ERR_ALERT | ERR_FATAL;
7891#else
Emeric Brund94b3fe2012-09-20 18:23:56 +02007892 if (!*args[cur_arg + 1]) {
7893 if (err)
7894 memprintf(err, "'%s' : missing CRLfile path", args[cur_arg]);
7895 return ERR_ALERT | ERR_FATAL;
7896 }
Emeric Brun2b58d042012-09-20 17:10:03 +02007897
Willy Tarreauef934602016-12-22 23:12:01 +01007898 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
7899 memprintf(&conf->crl_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02007900 else
7901 memprintf(&conf->crl_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02007902
Emeric Brun2b58d042012-09-20 17:10:03 +02007903 return 0;
Emeric Brun051cdab2012-10-02 19:25:50 +02007904#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02007905}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007906static int bind_parse_crl_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7907{
7908 return ssl_bind_parse_crl_file(args, cur_arg, px, &conf->ssl_conf, err);
7909}
Emeric Brun2b58d042012-09-20 17:10:03 +02007910
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01007911/* parse the "curves" bind keyword keyword */
7912static int ssl_bind_parse_curves(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
7913{
Willy Tarreau9a1ab082019-05-09 13:26:41 +02007914#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01007915 if (!*args[cur_arg + 1]) {
7916 if (err)
7917 memprintf(err, "'%s' : missing curve suite", args[cur_arg]);
7918 return ERR_ALERT | ERR_FATAL;
7919 }
7920 conf->curves = strdup(args[cur_arg + 1]);
7921 return 0;
7922#else
7923 if (err)
7924 memprintf(err, "'%s' : library does not support curve suite", args[cur_arg]);
7925 return ERR_ALERT | ERR_FATAL;
7926#endif
7927}
7928static int bind_parse_curves(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7929{
7930 return ssl_bind_parse_curves(args, cur_arg, px, &conf->ssl_conf, err);
7931}
7932
Bertrand Jacquinff13c062016-11-13 16:37:11 +00007933/* parse the "ecdhe" bind keyword keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007934static 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 +02007935{
Willy Tarreau9a1ab082019-05-09 13:26:41 +02007936#if HA_OPENSSL_VERSION_NUMBER < 0x0090800fL
Emeric Brun2b58d042012-09-20 17:10:03 +02007937 if (err)
7938 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (too old)", args[cur_arg]);
7939 return ERR_ALERT | ERR_FATAL;
7940#elif defined(OPENSSL_NO_ECDH)
7941 if (err)
7942 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (disabled via OPENSSL_NO_ECDH)", args[cur_arg]);
7943 return ERR_ALERT | ERR_FATAL;
7944#else
7945 if (!*args[cur_arg + 1]) {
7946 if (err)
7947 memprintf(err, "'%s' : missing named curve", args[cur_arg]);
7948 return ERR_ALERT | ERR_FATAL;
7949 }
7950
7951 conf->ecdhe = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007952
7953 return 0;
Emeric Brun2b58d042012-09-20 17:10:03 +02007954#endif
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007955}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007956static int bind_parse_ecdhe(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7957{
7958 return ssl_bind_parse_ecdhe(args, cur_arg, px, &conf->ssl_conf, err);
7959}
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007960
Bertrand Jacquinff13c062016-11-13 16:37:11 +00007961/* parse the "crt-ignore-err" and "ca-ignore-err" bind keywords */
Emeric Brun81c00f02012-09-21 14:31:21 +02007962static int bind_parse_ignore_err(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7963{
7964 int code;
7965 char *p = args[cur_arg + 1];
7966 unsigned long long *ignerr = &conf->crt_ignerr;
7967
7968 if (!*p) {
7969 if (err)
7970 memprintf(err, "'%s' : missing error IDs list", args[cur_arg]);
7971 return ERR_ALERT | ERR_FATAL;
7972 }
7973
7974 if (strcmp(args[cur_arg], "ca-ignore-err") == 0)
7975 ignerr = &conf->ca_ignerr;
7976
7977 if (strcmp(p, "all") == 0) {
7978 *ignerr = ~0ULL;
7979 return 0;
7980 }
7981
7982 while (p) {
7983 code = atoi(p);
7984 if ((code <= 0) || (code > 63)) {
7985 if (err)
7986 memprintf(err, "'%s' : ID '%d' out of range (1..63) in error IDs list '%s'",
7987 args[cur_arg], code, args[cur_arg + 1]);
7988 return ERR_ALERT | ERR_FATAL;
7989 }
7990 *ignerr |= 1ULL << code;
7991 p = strchr(p, ',');
7992 if (p)
7993 p++;
7994 }
7995
Emeric Brun2cb7ae52012-10-05 14:14:21 +02007996 return 0;
7997}
7998
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007999/* parse tls_method_options "no-xxx" and "force-xxx" */
8000static int parse_tls_method_options(char *arg, struct tls_version_filter *methods, char **err)
Emeric Brun2cb7ae52012-10-05 14:14:21 +02008001{
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008002 uint16_t v;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008003 char *p;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008004 p = strchr(arg, '-');
8005 if (!p)
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008006 goto fail;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008007 p++;
8008 if (!strcmp(p, "sslv3"))
8009 v = CONF_SSLV3;
8010 else if (!strcmp(p, "tlsv10"))
8011 v = CONF_TLSV10;
8012 else if (!strcmp(p, "tlsv11"))
8013 v = CONF_TLSV11;
8014 else if (!strcmp(p, "tlsv12"))
8015 v = CONF_TLSV12;
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +02008016 else if (!strcmp(p, "tlsv13"))
8017 v = CONF_TLSV13;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008018 else
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008019 goto fail;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008020 if (!strncmp(arg, "no-", 3))
8021 methods->flags |= methodVersions[v].flag;
8022 else if (!strncmp(arg, "force-", 6))
8023 methods->min = methods->max = v;
8024 else
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008025 goto fail;
Emeric Brun2d0c4822012-10-02 13:45:20 +02008026 return 0;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008027 fail:
8028 if (err)
8029 memprintf(err, "'%s' : option not implemented", arg);
8030 return ERR_ALERT | ERR_FATAL;
Emeric Brun2d0c4822012-10-02 13:45:20 +02008031}
8032
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008033static 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 +02008034{
Emmanuel Hocdet43664762017-08-09 18:26:20 +02008035 return parse_tls_method_options(args[cur_arg], &conf->ssl_conf.ssl_methods, err);
Emeric Brun2cb7ae52012-10-05 14:14:21 +02008036}
8037
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008038static 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 +02008039{
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008040 return parse_tls_method_options(args[*cur_arg], &newsrv->ssl_ctx.methods, err);
8041}
8042
8043/* parse tls_method min/max: "ssl-min-ver" and "ssl-max-ver" */
8044static int parse_tls_method_minmax(char **args, int cur_arg, struct tls_version_filter *methods, char **err)
8045{
8046 uint16_t i, v = 0;
8047 char *argv = args[cur_arg + 1];
8048 if (!*argv) {
8049 if (err)
8050 memprintf(err, "'%s' : missing the ssl/tls version", args[cur_arg]);
8051 return ERR_ALERT | ERR_FATAL;
8052 }
8053 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
8054 if (!strcmp(argv, methodVersions[i].name))
8055 v = i;
8056 if (!v) {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008057 if (err)
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008058 memprintf(err, "'%s' : unknown ssl/tls version", args[cur_arg + 1]);
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008059 return ERR_ALERT | ERR_FATAL;
8060 }
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008061 if (!strcmp("ssl-min-ver", args[cur_arg]))
8062 methods->min = v;
8063 else if (!strcmp("ssl-max-ver", args[cur_arg]))
8064 methods->max = v;
8065 else {
8066 if (err)
8067 memprintf(err, "'%s' : option not implemented", args[cur_arg]);
8068 return ERR_ALERT | ERR_FATAL;
8069 }
Emeric Brun2cb7ae52012-10-05 14:14:21 +02008070 return 0;
Emeric Brun2cb7ae52012-10-05 14:14:21 +02008071}
Emeric Brun2cb7ae52012-10-05 14:14:21 +02008072
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02008073static int ssl_bind_parse_tls_method_minmax(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
8074{
Willy Tarreau9a1ab082019-05-09 13:26:41 +02008075#if (HA_OPENSSL_VERSION_NUMBER < 0x10101000L) && !defined(OPENSSL_IS_BORINGSSL)
Christopher Faulet767a84b2017-11-24 16:50:31 +01008076 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 +02008077#endif
8078 return parse_tls_method_minmax(args, cur_arg, &conf->ssl_methods, err);
8079}
8080
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008081static int bind_parse_tls_method_minmax(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8082{
Emmanuel Hocdet43664762017-08-09 18:26:20 +02008083 return parse_tls_method_minmax(args, cur_arg, &conf->ssl_conf.ssl_methods, err);
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008084}
8085
8086static int srv_parse_tls_method_minmax(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8087{
8088 return parse_tls_method_minmax(args, *cur_arg, &newsrv->ssl_ctx.methods, err);
8089}
8090
Emeric Brun2d0c4822012-10-02 13:45:20 +02008091/* parse the "no-tls-tickets" bind keyword */
Emmanuel Hocdet4608ed92017-01-20 13:06:27 +01008092static 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 +02008093{
Emeric Brun89675492012-10-05 13:48:26 +02008094 conf->ssl_options |= BC_SSL_O_NO_TLS_TICKETS;
Emeric Brun81c00f02012-09-21 14:31:21 +02008095 return 0;
8096}
Emeric Brun2d0c4822012-10-02 13:45:20 +02008097
Olivier Houchardc2aae742017-09-22 18:26:28 +02008098/* parse the "allow-0rtt" bind keyword */
8099static int ssl_bind_parse_allow_0rtt(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
8100{
8101 conf->early_data = 1;
8102 return 0;
8103}
8104
8105static int bind_parse_allow_0rtt(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8106{
Olivier Houchard9679ac92017-10-27 14:58:08 +02008107 conf->ssl_conf.early_data = 1;
Olivier Houchardc2aae742017-09-22 18:26:28 +02008108 return 0;
8109}
8110
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02008111/* parse the "npn" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008112static 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 +02008113{
Bernard Spil13c53f82018-02-15 13:34:58 +01008114#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02008115 char *p1, *p2;
8116
8117 if (!*args[cur_arg + 1]) {
8118 memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[cur_arg]);
8119 return ERR_ALERT | ERR_FATAL;
8120 }
8121
8122 free(conf->npn_str);
8123
Willy Tarreau3724da12016-02-12 17:11:12 +01008124 /* the NPN string is built as a suite of (<len> <name>)*,
8125 * so we reuse each comma to store the next <len> and need
8126 * one more for the end of the string.
8127 */
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02008128 conf->npn_len = strlen(args[cur_arg + 1]) + 1;
Willy Tarreau3724da12016-02-12 17:11:12 +01008129 conf->npn_str = calloc(1, conf->npn_len + 1);
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02008130 memcpy(conf->npn_str + 1, args[cur_arg + 1], conf->npn_len);
8131
8132 /* replace commas with the name length */
8133 p1 = conf->npn_str;
8134 p2 = p1 + 1;
8135 while (1) {
8136 p2 = memchr(p1 + 1, ',', conf->npn_str + conf->npn_len - (p1 + 1));
8137 if (!p2)
8138 p2 = p1 + 1 + strlen(p1 + 1);
8139
8140 if (p2 - (p1 + 1) > 255) {
8141 *p2 = '\0';
8142 memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
8143 return ERR_ALERT | ERR_FATAL;
8144 }
8145
8146 *p1 = p2 - (p1 + 1);
8147 p1 = p2;
8148
8149 if (!*p2)
8150 break;
8151
8152 *(p2++) = '\0';
8153 }
8154 return 0;
8155#else
8156 if (err)
8157 memprintf(err, "'%s' : library does not support TLS NPN extension", args[cur_arg]);
8158 return ERR_ALERT | ERR_FATAL;
8159#endif
8160}
8161
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008162static int bind_parse_npn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8163{
8164 return ssl_bind_parse_npn(args, cur_arg, px, &conf->ssl_conf, err);
8165}
8166
Willy Tarreauab861d32013-04-02 02:30:41 +02008167/* parse the "alpn" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008168static 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 +02008169{
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01008170#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02008171 char *p1, *p2;
8172
8173 if (!*args[cur_arg + 1]) {
8174 memprintf(err, "'%s' : missing the comma-delimited ALPN protocol suite", args[cur_arg]);
8175 return ERR_ALERT | ERR_FATAL;
8176 }
8177
8178 free(conf->alpn_str);
8179
Marcoen Hirschbergbef60912016-02-12 17:05:24 +01008180 /* the ALPN string is built as a suite of (<len> <name>)*,
8181 * so we reuse each comma to store the next <len> and need
8182 * one more for the end of the string.
8183 */
Willy Tarreauab861d32013-04-02 02:30:41 +02008184 conf->alpn_len = strlen(args[cur_arg + 1]) + 1;
Marcoen Hirschbergbef60912016-02-12 17:05:24 +01008185 conf->alpn_str = calloc(1, conf->alpn_len + 1);
Willy Tarreauab861d32013-04-02 02:30:41 +02008186 memcpy(conf->alpn_str + 1, args[cur_arg + 1], conf->alpn_len);
8187
8188 /* replace commas with the name length */
8189 p1 = conf->alpn_str;
8190 p2 = p1 + 1;
8191 while (1) {
8192 p2 = memchr(p1 + 1, ',', conf->alpn_str + conf->alpn_len - (p1 + 1));
8193 if (!p2)
8194 p2 = p1 + 1 + strlen(p1 + 1);
8195
8196 if (p2 - (p1 + 1) > 255) {
8197 *p2 = '\0';
8198 memprintf(err, "'%s' : ALPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
8199 return ERR_ALERT | ERR_FATAL;
8200 }
8201
8202 *p1 = p2 - (p1 + 1);
8203 p1 = p2;
8204
8205 if (!*p2)
8206 break;
8207
8208 *(p2++) = '\0';
8209 }
8210 return 0;
8211#else
8212 if (err)
8213 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[cur_arg]);
8214 return ERR_ALERT | ERR_FATAL;
8215#endif
8216}
8217
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008218static int bind_parse_alpn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8219{
8220 return ssl_bind_parse_alpn(args, cur_arg, px, &conf->ssl_conf, err);
8221}
8222
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008223/* parse the "ssl" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02008224static 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 +02008225{
Willy Tarreau71a8c7c2016-12-21 22:04:54 +01008226 conf->xprt = &ssl_sock;
Willy Tarreau4348fad2012-09-20 16:48:07 +02008227 conf->is_ssl = 1;
Emeric Brun76d88952012-10-05 15:47:31 +02008228
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008229 if (global_ssl.listen_default_ciphers && !conf->ssl_conf.ciphers)
8230 conf->ssl_conf.ciphers = strdup(global_ssl.listen_default_ciphers);
Emmanuel Hocdet839af572019-05-14 16:27:35 +02008231#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02008232 if (global_ssl.listen_default_ciphersuites && !conf->ssl_conf.ciphersuites)
8233 conf->ssl_conf.ciphersuites = strdup(global_ssl.listen_default_ciphersuites);
8234#endif
Emmanuel Hocdet4608ed92017-01-20 13:06:27 +01008235 conf->ssl_options |= global_ssl.listen_default_ssloptions;
Emmanuel Hocdet43664762017-08-09 18:26:20 +02008236 conf->ssl_conf.ssl_methods.flags |= global_ssl.listen_default_sslmethods.flags;
8237 if (!conf->ssl_conf.ssl_methods.min)
8238 conf->ssl_conf.ssl_methods.min = global_ssl.listen_default_sslmethods.min;
8239 if (!conf->ssl_conf.ssl_methods.max)
8240 conf->ssl_conf.ssl_methods.max = global_ssl.listen_default_sslmethods.max;
Emeric Brun76d88952012-10-05 15:47:31 +02008241
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008242 return 0;
8243}
8244
Lukas Tribus53ae85c2017-05-04 15:45:40 +00008245/* parse the "prefer-client-ciphers" bind keyword */
8246static int bind_parse_pcc(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8247{
8248 conf->ssl_options |= BC_SSL_O_PREF_CLIE_CIPH;
8249 return 0;
8250}
8251
Christopher Faulet31af49d2015-06-09 17:29:50 +02008252/* parse the "generate-certificates" bind keyword */
8253static int bind_parse_generate_certs(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8254{
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01008255#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Christopher Faulet31af49d2015-06-09 17:29:50 +02008256 conf->generate_certs = 1;
8257#else
8258 memprintf(err, "%sthis version of openssl cannot generate SSL certificates.\n",
8259 err && *err ? *err : "");
8260#endif
8261 return 0;
8262}
8263
Emmanuel Hocdet65623372013-01-24 17:17:15 +01008264/* parse the "strict-sni" bind keyword */
8265static int bind_parse_strict_sni(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8266{
8267 conf->strict_sni = 1;
8268 return 0;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008269}
8270
8271/* parse the "tls-ticket-keys" bind keyword */
8272static int bind_parse_tls_ticket_keys(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8273{
8274#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
8275 FILE *f;
8276 int i = 0;
8277 char thisline[LINESIZE];
Nenad Merdanovic146defa2015-05-09 08:46:00 +02008278 struct tls_keys_ref *keys_ref;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008279
8280 if (!*args[cur_arg + 1]) {
8281 if (err)
8282 memprintf(err, "'%s' : missing TLS ticket keys file path", args[cur_arg]);
8283 return ERR_ALERT | ERR_FATAL;
8284 }
8285
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02008286 keys_ref = tlskeys_ref_lookup(args[cur_arg + 1]);
Willy Tarreau17b4aa12018-07-17 10:05:32 +02008287 if (keys_ref) {
8288 keys_ref->refcount++;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02008289 conf->keys_ref = keys_ref;
8290 return 0;
8291 }
8292
Vincent Bernat02779b62016-04-03 13:48:43 +02008293 keys_ref = malloc(sizeof(*keys_ref));
Emeric Brun09852f72019-01-10 10:51:13 +01008294 if (!keys_ref) {
8295 if (err)
8296 memprintf(err, "'%s' : allocation error", args[cur_arg+1]);
8297 return ERR_ALERT | ERR_FATAL;
8298 }
8299
Emeric Brun9e754772019-01-10 17:51:55 +01008300 keys_ref->tlskeys = malloc(TLS_TICKETS_NO * sizeof(union tls_sess_key));
Emeric Brun09852f72019-01-10 10:51:13 +01008301 if (!keys_ref->tlskeys) {
8302 free(keys_ref);
8303 if (err)
8304 memprintf(err, "'%s' : allocation error", args[cur_arg+1]);
8305 return ERR_ALERT | ERR_FATAL;
8306 }
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008307
8308 if ((f = fopen(args[cur_arg + 1], "r")) == NULL) {
Emeric Brun09852f72019-01-10 10:51:13 +01008309 free(keys_ref->tlskeys);
8310 free(keys_ref);
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008311 if (err)
8312 memprintf(err, "'%s' : unable to load ssl tickets keys file", args[cur_arg+1]);
8313 return ERR_ALERT | ERR_FATAL;
8314 }
8315
Nenad Merdanovic146defa2015-05-09 08:46:00 +02008316 keys_ref->filename = strdup(args[cur_arg + 1]);
Emeric Brun09852f72019-01-10 10:51:13 +01008317 if (!keys_ref->filename) {
8318 free(keys_ref->tlskeys);
8319 free(keys_ref);
8320 if (err)
8321 memprintf(err, "'%s' : allocation error", args[cur_arg+1]);
8322 return ERR_ALERT | ERR_FATAL;
8323 }
Nenad Merdanovic146defa2015-05-09 08:46:00 +02008324
Emeric Brun9e754772019-01-10 17:51:55 +01008325 keys_ref->key_size_bits = 0;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008326 while (fgets(thisline, sizeof(thisline), f) != NULL) {
8327 int len = strlen(thisline);
Emeric Brun9e754772019-01-10 17:51:55 +01008328 int dec_size;
8329
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008330 /* Strip newline characters from the end */
8331 if(thisline[len - 1] == '\n')
8332 thisline[--len] = 0;
8333
8334 if(thisline[len - 1] == '\r')
8335 thisline[--len] = 0;
8336
Emeric Brun9e754772019-01-10 17:51:55 +01008337 dec_size = base64dec(thisline, len, (char *) (keys_ref->tlskeys + i % TLS_TICKETS_NO), sizeof(union tls_sess_key));
8338 if (dec_size < 0) {
Emeric Brun09852f72019-01-10 10:51:13 +01008339 free(keys_ref->filename);
8340 free(keys_ref->tlskeys);
8341 free(keys_ref);
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008342 if (err)
8343 memprintf(err, "'%s' : unable to decode base64 key on line %d", args[cur_arg+1], i + 1);
mildis16aa0152016-06-22 17:46:29 +02008344 fclose(f);
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008345 return ERR_ALERT | ERR_FATAL;
8346 }
Emeric Brun9e754772019-01-10 17:51:55 +01008347 else if (!keys_ref->key_size_bits && (dec_size == sizeof(struct tls_sess_key_128))) {
8348 keys_ref->key_size_bits = 128;
8349 }
8350 else if (!keys_ref->key_size_bits && (dec_size == sizeof(struct tls_sess_key_256))) {
8351 keys_ref->key_size_bits = 256;
8352 }
8353 else if (((dec_size != sizeof(struct tls_sess_key_128)) && (dec_size != sizeof(struct tls_sess_key_256)))
8354 || ((dec_size == sizeof(struct tls_sess_key_128) && (keys_ref->key_size_bits != 128)))
8355 || ((dec_size == sizeof(struct tls_sess_key_256) && (keys_ref->key_size_bits != 256)))) {
8356 free(keys_ref->filename);
8357 free(keys_ref->tlskeys);
8358 free(keys_ref);
8359 if (err)
8360 memprintf(err, "'%s' : wrong sized key on line %d", args[cur_arg+1], i + 1);
8361 fclose(f);
8362 return ERR_ALERT | ERR_FATAL;
8363 }
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008364 i++;
8365 }
8366
8367 if (i < TLS_TICKETS_NO) {
Emeric Brun09852f72019-01-10 10:51:13 +01008368 free(keys_ref->filename);
8369 free(keys_ref->tlskeys);
8370 free(keys_ref);
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008371 if (err)
8372 memprintf(err, "'%s' : please supply at least %d keys in the tls-tickets-file", args[cur_arg+1], TLS_TICKETS_NO);
mildis16aa0152016-06-22 17:46:29 +02008373 fclose(f);
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008374 return ERR_ALERT | ERR_FATAL;
8375 }
8376
8377 fclose(f);
8378
8379 /* Use penultimate key for encryption, handle when TLS_TICKETS_NO = 1 */
Nenad Merdanovic17891152016-03-25 22:16:57 +01008380 i -= 2;
8381 keys_ref->tls_ticket_enc_index = i < 0 ? 0 : i % TLS_TICKETS_NO;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02008382 keys_ref->unique_id = -1;
Willy Tarreau17b4aa12018-07-17 10:05:32 +02008383 keys_ref->refcount = 1;
Christopher Faulet16f45c82018-02-16 11:23:49 +01008384 HA_RWLOCK_INIT(&keys_ref->lock);
Nenad Merdanovic146defa2015-05-09 08:46:00 +02008385 conf->keys_ref = keys_ref;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008386
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02008387 LIST_ADD(&tlskeys_reference, &keys_ref->list);
8388
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008389 return 0;
8390#else
8391 if (err)
8392 memprintf(err, "'%s' : TLS ticket callback extension not supported", args[cur_arg]);
8393 return ERR_ALERT | ERR_FATAL;
8394#endif /* SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB */
Emmanuel Hocdet65623372013-01-24 17:17:15 +01008395}
8396
Emeric Brund94b3fe2012-09-20 18:23:56 +02008397/* parse the "verify" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008398static 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 +02008399{
8400 if (!*args[cur_arg + 1]) {
8401 if (err)
8402 memprintf(err, "'%s' : missing verify method", args[cur_arg]);
8403 return ERR_ALERT | ERR_FATAL;
8404 }
8405
8406 if (strcmp(args[cur_arg + 1], "none") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01008407 conf->verify = SSL_SOCK_VERIFY_NONE;
Emeric Brund94b3fe2012-09-20 18:23:56 +02008408 else if (strcmp(args[cur_arg + 1], "optional") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01008409 conf->verify = SSL_SOCK_VERIFY_OPTIONAL;
Emeric Brund94b3fe2012-09-20 18:23:56 +02008410 else if (strcmp(args[cur_arg + 1], "required") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01008411 conf->verify = SSL_SOCK_VERIFY_REQUIRED;
Emeric Brund94b3fe2012-09-20 18:23:56 +02008412 else {
8413 if (err)
8414 memprintf(err, "'%s' : unknown verify method '%s', only 'none', 'optional', and 'required' are supported\n",
8415 args[cur_arg], args[cur_arg + 1]);
8416 return ERR_ALERT | ERR_FATAL;
8417 }
8418
8419 return 0;
8420}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008421static int bind_parse_verify(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8422{
8423 return ssl_bind_parse_verify(args, cur_arg, px, &conf->ssl_conf, err);
8424}
Emeric Brund94b3fe2012-09-20 18:23:56 +02008425
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02008426/* parse the "no-ca-names" bind keyword */
8427static int ssl_bind_parse_no_ca_names(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
8428{
8429 conf->no_ca_names = 1;
8430 return 0;
8431}
8432static int bind_parse_no_ca_names(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8433{
8434 return ssl_bind_parse_no_ca_names(args, cur_arg, px, &conf->ssl_conf, err);
8435}
8436
Willy Tarreau92faadf2012-10-10 23:04:25 +02008437/************** "server" keywords ****************/
8438
Olivier Houchardc7566002018-11-20 23:33:50 +01008439/* parse the "npn" bind keyword */
8440static int srv_parse_npn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8441{
8442#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
8443 char *p1, *p2;
8444
8445 if (!*args[*cur_arg + 1]) {
8446 memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[*cur_arg]);
8447 return ERR_ALERT | ERR_FATAL;
8448 }
8449
8450 free(newsrv->ssl_ctx.npn_str);
8451
8452 /* the NPN string is built as a suite of (<len> <name>)*,
8453 * so we reuse each comma to store the next <len> and need
8454 * one more for the end of the string.
8455 */
8456 newsrv->ssl_ctx.npn_len = strlen(args[*cur_arg + 1]) + 1;
8457 newsrv->ssl_ctx.npn_str = calloc(1, newsrv->ssl_ctx.npn_len + 1);
8458 memcpy(newsrv->ssl_ctx.npn_str + 1, args[*cur_arg + 1],
8459 newsrv->ssl_ctx.npn_len);
8460
8461 /* replace commas with the name length */
8462 p1 = newsrv->ssl_ctx.npn_str;
8463 p2 = p1 + 1;
8464 while (1) {
8465 p2 = memchr(p1 + 1, ',', newsrv->ssl_ctx.npn_str +
8466 newsrv->ssl_ctx.npn_len - (p1 + 1));
8467 if (!p2)
8468 p2 = p1 + 1 + strlen(p1 + 1);
8469
8470 if (p2 - (p1 + 1) > 255) {
8471 *p2 = '\0';
8472 memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[*cur_arg], p1 + 1);
8473 return ERR_ALERT | ERR_FATAL;
8474 }
8475
8476 *p1 = p2 - (p1 + 1);
8477 p1 = p2;
8478
8479 if (!*p2)
8480 break;
8481
8482 *(p2++) = '\0';
8483 }
8484 return 0;
8485#else
8486 if (err)
8487 memprintf(err, "'%s' : library does not support TLS NPN extension", args[*cur_arg]);
8488 return ERR_ALERT | ERR_FATAL;
8489#endif
8490}
8491
Olivier Houchard92150142018-12-21 19:47:01 +01008492/* parse the "alpn" or the "check-alpn" server keyword */
Olivier Houchardc7566002018-11-20 23:33:50 +01008493static int srv_parse_alpn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8494{
8495#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
8496 char *p1, *p2;
Olivier Houchard92150142018-12-21 19:47:01 +01008497 char **alpn_str;
8498 int *alpn_len;
Olivier Houchardc7566002018-11-20 23:33:50 +01008499
Olivier Houchard92150142018-12-21 19:47:01 +01008500 if (*args[*cur_arg] == 'c') {
8501 alpn_str = &newsrv->check.alpn_str;
8502 alpn_len = &newsrv->check.alpn_len;
8503 } else {
8504 alpn_str = &newsrv->ssl_ctx.alpn_str;
8505 alpn_len = &newsrv->ssl_ctx.alpn_len;
8506
8507 }
Olivier Houchardc7566002018-11-20 23:33:50 +01008508 if (!*args[*cur_arg + 1]) {
8509 memprintf(err, "'%s' : missing the comma-delimited ALPN protocol suite", args[*cur_arg]);
8510 return ERR_ALERT | ERR_FATAL;
8511 }
8512
Olivier Houchard92150142018-12-21 19:47:01 +01008513 free(*alpn_str);
Olivier Houchardc7566002018-11-20 23:33:50 +01008514
8515 /* the ALPN string is built as a suite of (<len> <name>)*,
8516 * so we reuse each comma to store the next <len> and need
8517 * one more for the end of the string.
8518 */
Olivier Houchard92150142018-12-21 19:47:01 +01008519 *alpn_len = strlen(args[*cur_arg + 1]) + 1;
8520 *alpn_str = calloc(1, *alpn_len + 1);
8521 memcpy(*alpn_str + 1, args[*cur_arg + 1], *alpn_len);
Olivier Houchardc7566002018-11-20 23:33:50 +01008522
8523 /* replace commas with the name length */
Olivier Houchard92150142018-12-21 19:47:01 +01008524 p1 = *alpn_str;
Olivier Houchardc7566002018-11-20 23:33:50 +01008525 p2 = p1 + 1;
8526 while (1) {
Olivier Houchard92150142018-12-21 19:47:01 +01008527 p2 = memchr(p1 + 1, ',', *alpn_str + *alpn_len - (p1 + 1));
Olivier Houchardc7566002018-11-20 23:33:50 +01008528 if (!p2)
8529 p2 = p1 + 1 + strlen(p1 + 1);
8530
8531 if (p2 - (p1 + 1) > 255) {
8532 *p2 = '\0';
8533 memprintf(err, "'%s' : ALPN protocol name too long : '%s'", args[*cur_arg], p1 + 1);
8534 return ERR_ALERT | ERR_FATAL;
8535 }
8536
8537 *p1 = p2 - (p1 + 1);
8538 p1 = p2;
8539
8540 if (!*p2)
8541 break;
8542
8543 *(p2++) = '\0';
8544 }
8545 return 0;
8546#else
8547 if (err)
8548 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[*cur_arg]);
8549 return ERR_ALERT | ERR_FATAL;
8550#endif
8551}
8552
Emeric Brunef42d922012-10-11 16:11:36 +02008553/* parse the "ca-file" server keyword */
8554static int srv_parse_ca_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8555{
8556 if (!*args[*cur_arg + 1]) {
8557 if (err)
8558 memprintf(err, "'%s' : missing CAfile path", args[*cur_arg]);
8559 return ERR_ALERT | ERR_FATAL;
8560 }
8561
Willy Tarreauef934602016-12-22 23:12:01 +01008562 if ((*args[*cur_arg + 1] != '/') && global_ssl.ca_base)
8563 memprintf(&newsrv->ssl_ctx.ca_file, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02008564 else
8565 memprintf(&newsrv->ssl_ctx.ca_file, "%s", args[*cur_arg + 1]);
8566
8567 return 0;
8568}
8569
Olivier Houchard9130a962017-10-17 17:33:43 +02008570/* parse the "check-sni" server keyword */
8571static int srv_parse_check_sni(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8572{
8573 if (!*args[*cur_arg + 1]) {
8574 if (err)
8575 memprintf(err, "'%s' : missing SNI", args[*cur_arg]);
8576 return ERR_ALERT | ERR_FATAL;
8577 }
8578
8579 newsrv->check.sni = strdup(args[*cur_arg + 1]);
8580 if (!newsrv->check.sni) {
8581 memprintf(err, "'%s' : failed to allocate memory", args[*cur_arg]);
8582 return ERR_ALERT | ERR_FATAL;
8583 }
8584 return 0;
8585
8586}
8587
Willy Tarreau92faadf2012-10-10 23:04:25 +02008588/* parse the "check-ssl" server keyword */
8589static int srv_parse_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8590{
8591 newsrv->check.use_ssl = 1;
Willy Tarreauef934602016-12-22 23:12:01 +01008592 if (global_ssl.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
8593 newsrv->ssl_ctx.ciphers = strdup(global_ssl.connect_default_ciphers);
Emmanuel Hocdet839af572019-05-14 16:27:35 +02008594#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02008595 if (global_ssl.connect_default_ciphersuites && !newsrv->ssl_ctx.ciphersuites)
8596 newsrv->ssl_ctx.ciphersuites = strdup(global_ssl.connect_default_ciphersuites);
8597#endif
Willy Tarreauef934602016-12-22 23:12:01 +01008598 newsrv->ssl_ctx.options |= global_ssl.connect_default_ssloptions;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008599 newsrv->ssl_ctx.methods.flags |= global_ssl.connect_default_sslmethods.flags;
8600 if (!newsrv->ssl_ctx.methods.min)
8601 newsrv->ssl_ctx.methods.min = global_ssl.connect_default_sslmethods.min;
8602 if (!newsrv->ssl_ctx.methods.max)
8603 newsrv->ssl_ctx.methods.max = global_ssl.connect_default_sslmethods.max;
8604
Willy Tarreau92faadf2012-10-10 23:04:25 +02008605 return 0;
8606}
8607
8608/* parse the "ciphers" server keyword */
8609static int srv_parse_ciphers(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8610{
8611 if (!*args[*cur_arg + 1]) {
8612 memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
8613 return ERR_ALERT | ERR_FATAL;
8614 }
8615
8616 free(newsrv->ssl_ctx.ciphers);
8617 newsrv->ssl_ctx.ciphers = strdup(args[*cur_arg + 1]);
8618 return 0;
8619}
Dirkjan Bussink415150f2018-09-14 11:14:21 +02008620
Emmanuel Hocdet839af572019-05-14 16:27:35 +02008621#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02008622/* parse the "ciphersuites" server keyword */
8623static int srv_parse_ciphersuites(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8624{
8625 if (!*args[*cur_arg + 1]) {
8626 memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
8627 return ERR_ALERT | ERR_FATAL;
8628 }
8629
8630 free(newsrv->ssl_ctx.ciphersuites);
8631 newsrv->ssl_ctx.ciphersuites = strdup(args[*cur_arg + 1]);
8632 return 0;
8633}
8634#endif
Willy Tarreau92faadf2012-10-10 23:04:25 +02008635
Emeric Brunef42d922012-10-11 16:11:36 +02008636/* parse the "crl-file" server keyword */
8637static int srv_parse_crl_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8638{
8639#ifndef X509_V_FLAG_CRL_CHECK
8640 if (err)
8641 memprintf(err, "'%s' : library does not support CRL verify", args[*cur_arg]);
8642 return ERR_ALERT | ERR_FATAL;
8643#else
8644 if (!*args[*cur_arg + 1]) {
8645 if (err)
8646 memprintf(err, "'%s' : missing CRLfile path", args[*cur_arg]);
8647 return ERR_ALERT | ERR_FATAL;
8648 }
8649
Willy Tarreauef934602016-12-22 23:12:01 +01008650 if ((*args[*cur_arg + 1] != '/') && global_ssl.ca_base)
8651 memprintf(&newsrv->ssl_ctx.crl_file, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02008652 else
8653 memprintf(&newsrv->ssl_ctx.crl_file, "%s", args[*cur_arg + 1]);
8654
8655 return 0;
8656#endif
8657}
8658
Emeric Bruna7aa3092012-10-26 12:58:00 +02008659/* parse the "crt" server keyword */
8660static int srv_parse_crt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8661{
8662 if (!*args[*cur_arg + 1]) {
8663 if (err)
8664 memprintf(err, "'%s' : missing certificate file path", args[*cur_arg]);
8665 return ERR_ALERT | ERR_FATAL;
8666 }
8667
Willy Tarreauef934602016-12-22 23:12:01 +01008668 if ((*args[*cur_arg + 1] != '/') && global_ssl.crt_base)
Christopher Fauletff3a41e2017-11-23 09:13:32 +01008669 memprintf(&newsrv->ssl_ctx.client_crt, "%s/%s", global_ssl.crt_base, args[*cur_arg + 1]);
Emeric Bruna7aa3092012-10-26 12:58:00 +02008670 else
8671 memprintf(&newsrv->ssl_ctx.client_crt, "%s", args[*cur_arg + 1]);
8672
8673 return 0;
8674}
Emeric Brunef42d922012-10-11 16:11:36 +02008675
Frédéric Lécaille340ae602017-03-13 10:38:04 +01008676/* parse the "no-check-ssl" server keyword */
8677static int srv_parse_no_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8678{
8679 newsrv->check.use_ssl = 0;
8680 free(newsrv->ssl_ctx.ciphers);
8681 newsrv->ssl_ctx.ciphers = NULL;
8682 newsrv->ssl_ctx.options &= ~global_ssl.connect_default_ssloptions;
8683 return 0;
8684}
8685
Frédéric Lécaillee892c4c2017-03-13 12:08:01 +01008686/* parse the "no-send-proxy-v2-ssl" server keyword */
8687static int srv_parse_no_send_proxy_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8688{
8689 newsrv->pp_opts &= ~SRV_PP_V2;
8690 newsrv->pp_opts &= ~SRV_PP_V2_SSL;
8691 return 0;
8692}
8693
8694/* parse the "no-send-proxy-v2-ssl-cn" server keyword */
8695static int srv_parse_no_send_proxy_cn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8696{
8697 newsrv->pp_opts &= ~SRV_PP_V2;
8698 newsrv->pp_opts &= ~SRV_PP_V2_SSL;
8699 newsrv->pp_opts &= ~SRV_PP_V2_SSL_CN;
8700 return 0;
8701}
8702
Frédéric Lécaillee381d762017-03-13 11:54:17 +01008703/* parse the "no-ssl" server keyword */
8704static int srv_parse_no_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8705{
8706 newsrv->use_ssl = 0;
8707 free(newsrv->ssl_ctx.ciphers);
8708 newsrv->ssl_ctx.ciphers = NULL;
8709 return 0;
8710}
8711
Olivier Houchard522eea72017-11-03 16:27:47 +01008712/* parse the "allow-0rtt" server keyword */
8713static int srv_parse_allow_0rtt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8714{
8715 newsrv->ssl_ctx.options |= SRV_SSL_O_EARLY_DATA;
8716 return 0;
8717}
8718
Willy Tarreau2a3fb1c2015-02-05 16:47:07 +01008719/* parse the "no-ssl-reuse" server keyword */
8720static int srv_parse_no_ssl_reuse(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8721{
8722 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_REUSE;
8723 return 0;
8724}
8725
Emeric Brunf9c5c472012-10-11 15:28:34 +02008726/* parse the "no-tls-tickets" server keyword */
8727static int srv_parse_no_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8728{
8729 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLS_TICKETS;
8730 return 0;
8731}
David Safb76832014-05-08 23:42:08 -04008732/* parse the "send-proxy-v2-ssl" server keyword */
8733static int srv_parse_send_proxy_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8734{
8735 newsrv->pp_opts |= SRV_PP_V2;
8736 newsrv->pp_opts |= SRV_PP_V2_SSL;
8737 return 0;
8738}
8739
8740/* parse the "send-proxy-v2-ssl-cn" server keyword */
8741static int srv_parse_send_proxy_cn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8742{
8743 newsrv->pp_opts |= SRV_PP_V2;
8744 newsrv->pp_opts |= SRV_PP_V2_SSL;
8745 newsrv->pp_opts |= SRV_PP_V2_SSL_CN;
8746 return 0;
8747}
Emeric Brunf9c5c472012-10-11 15:28:34 +02008748
Willy Tarreau732eac42015-07-09 11:40:25 +02008749/* parse the "sni" server keyword */
8750static int srv_parse_sni(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8751{
8752#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
8753 memprintf(err, "'%s' : the current SSL library doesn't support the SNI TLS extension", args[*cur_arg]);
8754 return ERR_ALERT | ERR_FATAL;
8755#else
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01008756 char *arg;
Willy Tarreau732eac42015-07-09 11:40:25 +02008757
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01008758 arg = args[*cur_arg + 1];
8759 if (!*arg) {
Willy Tarreau732eac42015-07-09 11:40:25 +02008760 memprintf(err, "'%s' : missing sni expression", args[*cur_arg]);
8761 return ERR_ALERT | ERR_FATAL;
8762 }
8763
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01008764 free(newsrv->sni_expr);
8765 newsrv->sni_expr = strdup(arg);
Willy Tarreau732eac42015-07-09 11:40:25 +02008766
Willy Tarreau732eac42015-07-09 11:40:25 +02008767 return 0;
8768#endif
8769}
8770
Willy Tarreau92faadf2012-10-10 23:04:25 +02008771/* parse the "ssl" server keyword */
8772static int srv_parse_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8773{
8774 newsrv->use_ssl = 1;
Willy Tarreauef934602016-12-22 23:12:01 +01008775 if (global_ssl.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
8776 newsrv->ssl_ctx.ciphers = strdup(global_ssl.connect_default_ciphers);
Emmanuel Hocdet839af572019-05-14 16:27:35 +02008777#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02008778 if (global_ssl.connect_default_ciphersuites && !newsrv->ssl_ctx.ciphersuites)
8779 newsrv->ssl_ctx.ciphersuites = strdup(global_ssl.connect_default_ciphersuites);
8780#endif
Willy Tarreau92faadf2012-10-10 23:04:25 +02008781 return 0;
8782}
8783
Frédéric Lécaille2cfcdbe2017-03-13 11:32:20 +01008784/* parse the "ssl-reuse" server keyword */
8785static int srv_parse_ssl_reuse(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8786{
8787 newsrv->ssl_ctx.options &= ~SRV_SSL_O_NO_REUSE;
8788 return 0;
8789}
8790
Frédéric Lécaille2cfcdbe2017-03-13 11:32:20 +01008791/* parse the "tls-tickets" server keyword */
8792static int srv_parse_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8793{
8794 newsrv->ssl_ctx.options &= ~SRV_SSL_O_NO_TLS_TICKETS;
8795 return 0;
8796}
8797
Emeric Brunef42d922012-10-11 16:11:36 +02008798/* parse the "verify" server keyword */
8799static int srv_parse_verify(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8800{
8801 if (!*args[*cur_arg + 1]) {
8802 if (err)
8803 memprintf(err, "'%s' : missing verify method", args[*cur_arg]);
8804 return ERR_ALERT | ERR_FATAL;
8805 }
8806
8807 if (strcmp(args[*cur_arg + 1], "none") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01008808 newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_NONE;
Emeric Brunef42d922012-10-11 16:11:36 +02008809 else if (strcmp(args[*cur_arg + 1], "required") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01008810 newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_REQUIRED;
Emeric Brunef42d922012-10-11 16:11:36 +02008811 else {
8812 if (err)
8813 memprintf(err, "'%s' : unknown verify method '%s', only 'none' and 'required' are supported\n",
8814 args[*cur_arg], args[*cur_arg + 1]);
8815 return ERR_ALERT | ERR_FATAL;
8816 }
8817
Evan Broderbe554312013-06-27 00:05:25 -07008818 return 0;
8819}
8820
8821/* parse the "verifyhost" server keyword */
8822static int srv_parse_verifyhost(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8823{
8824 if (!*args[*cur_arg + 1]) {
8825 if (err)
8826 memprintf(err, "'%s' : missing hostname to verify against", args[*cur_arg]);
8827 return ERR_ALERT | ERR_FATAL;
8828 }
8829
Frédéric Lécaille273f3212017-03-13 15:52:01 +01008830 free(newsrv->ssl_ctx.verify_host);
Evan Broderbe554312013-06-27 00:05:25 -07008831 newsrv->ssl_ctx.verify_host = strdup(args[*cur_arg + 1]);
8832
Emeric Brunef42d922012-10-11 16:11:36 +02008833 return 0;
8834}
8835
Emeric Brun2c86cbf2014-10-30 15:56:50 +01008836/* parse the "ssl-default-bind-options" keyword in global section */
8837static int ssl_parse_default_bind_options(char **args, int section_type, struct proxy *curpx,
8838 struct proxy *defpx, const char *file, int line,
8839 char **err) {
8840 int i = 1;
8841
8842 if (*(args[i]) == 0) {
8843 memprintf(err, "global statement '%s' expects an option as an argument.", args[0]);
8844 return -1;
8845 }
8846 while (*(args[i])) {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008847 if (!strcmp(args[i], "no-tls-tickets"))
Willy Tarreauef934602016-12-22 23:12:01 +01008848 global_ssl.listen_default_ssloptions |= BC_SSL_O_NO_TLS_TICKETS;
Lukas Tribus53ae85c2017-05-04 15:45:40 +00008849 else if (!strcmp(args[i], "prefer-client-ciphers"))
8850 global_ssl.listen_default_ssloptions |= BC_SSL_O_PREF_CLIE_CIPH;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008851 else if (!strcmp(args[i], "ssl-min-ver") || !strcmp(args[i], "ssl-max-ver")) {
8852 if (!parse_tls_method_minmax(args, i, &global_ssl.listen_default_sslmethods, err))
8853 i++;
8854 else {
8855 memprintf(err, "%s on global statement '%s'.", *err, args[0]);
8856 return -1;
8857 }
8858 }
8859 else if (parse_tls_method_options(args[i], &global_ssl.listen_default_sslmethods, err)) {
Emeric Brun2c86cbf2014-10-30 15:56:50 +01008860 memprintf(err, "unknown option '%s' on global statement '%s'.", args[i], args[0]);
8861 return -1;
8862 }
8863 i++;
8864 }
8865 return 0;
8866}
8867
8868/* parse the "ssl-default-server-options" keyword in global section */
8869static int ssl_parse_default_server_options(char **args, int section_type, struct proxy *curpx,
8870 struct proxy *defpx, const char *file, int line,
8871 char **err) {
8872 int i = 1;
8873
8874 if (*(args[i]) == 0) {
8875 memprintf(err, "global statement '%s' expects an option as an argument.", args[0]);
8876 return -1;
8877 }
8878 while (*(args[i])) {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008879 if (!strcmp(args[i], "no-tls-tickets"))
Willy Tarreauef934602016-12-22 23:12:01 +01008880 global_ssl.connect_default_ssloptions |= SRV_SSL_O_NO_TLS_TICKETS;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008881 else if (!strcmp(args[i], "ssl-min-ver") || !strcmp(args[i], "ssl-max-ver")) {
8882 if (!parse_tls_method_minmax(args, i, &global_ssl.connect_default_sslmethods, err))
8883 i++;
8884 else {
8885 memprintf(err, "%s on global statement '%s'.", *err, args[0]);
8886 return -1;
8887 }
8888 }
8889 else if (parse_tls_method_options(args[i], &global_ssl.connect_default_sslmethods, err)) {
Emeric Brun2c86cbf2014-10-30 15:56:50 +01008890 memprintf(err, "unknown option '%s' on global statement '%s'.", args[i], args[0]);
8891 return -1;
8892 }
8893 i++;
8894 }
8895 return 0;
8896}
8897
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01008898/* parse the "ca-base" / "crt-base" keywords in global section.
8899 * Returns <0 on alert, >0 on warning, 0 on success.
8900 */
8901static int ssl_parse_global_ca_crt_base(char **args, int section_type, struct proxy *curpx,
8902 struct proxy *defpx, const char *file, int line,
8903 char **err)
8904{
8905 char **target;
8906
Willy Tarreauef934602016-12-22 23:12:01 +01008907 target = (args[0][1] == 'a') ? &global_ssl.ca_base : &global_ssl.crt_base;
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01008908
8909 if (too_many_args(1, args, err, NULL))
8910 return -1;
8911
8912 if (*target) {
8913 memprintf(err, "'%s' already specified.", args[0]);
8914 return -1;
8915 }
8916
8917 if (*(args[1]) == 0) {
8918 memprintf(err, "global statement '%s' expects a directory path as an argument.", args[0]);
8919 return -1;
8920 }
8921 *target = strdup(args[1]);
8922 return 0;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00008923}
8924
8925/* parse the "ssl-mode-async" keyword in global section.
8926 * Returns <0 on alert, >0 on warning, 0 on success.
8927 */
8928static int ssl_parse_global_ssl_async(char **args, int section_type, struct proxy *curpx,
8929 struct proxy *defpx, const char *file, int line,
8930 char **err)
8931{
Willy Tarreau5db847a2019-05-09 14:13:35 +02008932#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00008933 global_ssl.async = 1;
Emeric Brunece0c332017-12-06 13:51:49 +01008934 global.ssl_used_async_engines = nb_engines;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00008935 return 0;
8936#else
8937 memprintf(err, "'%s': openssl library does not support async mode", args[0]);
8938 return -1;
8939#endif
8940}
8941
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008942#ifndef OPENSSL_NO_ENGINE
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00008943static int ssl_check_async_engine_count(void) {
8944 int err_code = 0;
8945
Emeric Brun3854e012017-05-17 20:42:48 +02008946 if (global_ssl.async && (openssl_engines_initialized > 32)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01008947 ha_alert("ssl-mode-async only supports a maximum of 32 engines.\n");
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00008948 err_code = ERR_ABORT;
8949 }
8950 return err_code;
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01008951}
8952
Grant Zhang872f9c22017-01-21 01:10:18 +00008953/* parse the "ssl-engine" keyword in global section.
8954 * Returns <0 on alert, >0 on warning, 0 on success.
8955 */
8956static int ssl_parse_global_ssl_engine(char **args, int section_type, struct proxy *curpx,
8957 struct proxy *defpx, const char *file, int line,
8958 char **err)
8959{
8960 char *algo;
8961 int ret = -1;
8962
8963 if (*(args[1]) == 0) {
8964 memprintf(err, "global statement '%s' expects a valid engine name as an argument.", args[0]);
8965 return ret;
8966 }
8967
8968 if (*(args[2]) == 0) {
8969 /* if no list of algorithms is given, it defaults to ALL */
8970 algo = strdup("ALL");
8971 goto add_engine;
8972 }
8973
8974 /* otherwise the expected format is ssl-engine <engine_name> algo <list of algo> */
8975 if (strcmp(args[2], "algo") != 0) {
8976 memprintf(err, "global statement '%s' expects to have algo keyword.", args[0]);
8977 return ret;
8978 }
8979
8980 if (*(args[3]) == 0) {
8981 memprintf(err, "global statement '%s' expects algorithm names as an argument.", args[0]);
8982 return ret;
8983 }
8984 algo = strdup(args[3]);
8985
8986add_engine:
8987 if (ssl_init_single_engine(args[1], algo)==0) {
8988 openssl_engines_initialized++;
8989 ret = 0;
8990 }
8991 free(algo);
8992 return ret;
8993}
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008994#endif
Grant Zhang872f9c22017-01-21 01:10:18 +00008995
Willy Tarreauf22e9682016-12-21 23:23:19 +01008996/* parse the "ssl-default-bind-ciphers" / "ssl-default-server-ciphers" keywords
8997 * in global section. Returns <0 on alert, >0 on warning, 0 on success.
8998 */
8999static int ssl_parse_global_ciphers(char **args, int section_type, struct proxy *curpx,
9000 struct proxy *defpx, const char *file, int line,
9001 char **err)
9002{
9003 char **target;
9004
Willy Tarreauef934602016-12-22 23:12:01 +01009005 target = (args[0][12] == 'b') ? &global_ssl.listen_default_ciphers : &global_ssl.connect_default_ciphers;
Willy Tarreauf22e9682016-12-21 23:23:19 +01009006
9007 if (too_many_args(1, args, err, NULL))
9008 return -1;
9009
9010 if (*(args[1]) == 0) {
9011 memprintf(err, "global statement '%s' expects a cipher suite as an argument.", args[0]);
9012 return -1;
9013 }
9014
9015 free(*target);
9016 *target = strdup(args[1]);
9017 return 0;
9018}
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009019
Emmanuel Hocdet839af572019-05-14 16:27:35 +02009020#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009021/* parse the "ssl-default-bind-ciphersuites" / "ssl-default-server-ciphersuites" keywords
9022 * in global section. Returns <0 on alert, >0 on warning, 0 on success.
9023 */
9024static int ssl_parse_global_ciphersuites(char **args, int section_type, struct proxy *curpx,
9025 struct proxy *defpx, const char *file, int line,
9026 char **err)
9027{
9028 char **target;
9029
9030 target = (args[0][12] == 'b') ? &global_ssl.listen_default_ciphersuites : &global_ssl.connect_default_ciphersuites;
9031
9032 if (too_many_args(1, args, err, NULL))
9033 return -1;
9034
9035 if (*(args[1]) == 0) {
9036 memprintf(err, "global statement '%s' expects a cipher suite as an argument.", args[0]);
9037 return -1;
9038 }
9039
9040 free(*target);
9041 *target = strdup(args[1]);
9042 return 0;
9043}
9044#endif
Willy Tarreauf22e9682016-12-21 23:23:19 +01009045
Willy Tarreau9ceda382016-12-21 23:13:03 +01009046/* parse various global tune.ssl settings consisting in positive integers.
9047 * Returns <0 on alert, >0 on warning, 0 on success.
9048 */
9049static int ssl_parse_global_int(char **args, int section_type, struct proxy *curpx,
9050 struct proxy *defpx, const char *file, int line,
9051 char **err)
9052{
9053 int *target;
9054
9055 if (strcmp(args[0], "tune.ssl.cachesize") == 0)
9056 target = &global.tune.sslcachesize;
9057 else if (strcmp(args[0], "tune.ssl.maxrecord") == 0)
Willy Tarreauef934602016-12-22 23:12:01 +01009058 target = (int *)&global_ssl.max_record;
Willy Tarreau9ceda382016-12-21 23:13:03 +01009059 else if (strcmp(args[0], "tune.ssl.ssl-ctx-cache-size") == 0)
Willy Tarreauef934602016-12-22 23:12:01 +01009060 target = &global_ssl.ctx_cache;
Willy Tarreau0bea58d2016-12-21 23:17:25 +01009061 else if (strcmp(args[0], "maxsslconn") == 0)
9062 target = &global.maxsslconn;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01009063 else if (strcmp(args[0], "tune.ssl.capture-cipherlist-size") == 0)
9064 target = &global_ssl.capture_cipherlist;
Willy Tarreau9ceda382016-12-21 23:13:03 +01009065 else {
9066 memprintf(err, "'%s' keyword not unhandled (please report this bug).", args[0]);
9067 return -1;
9068 }
9069
9070 if (too_many_args(1, args, err, NULL))
9071 return -1;
9072
9073 if (*(args[1]) == 0) {
9074 memprintf(err, "'%s' expects an integer argument.", args[0]);
9075 return -1;
9076 }
9077
9078 *target = atoi(args[1]);
9079 if (*target < 0) {
9080 memprintf(err, "'%s' expects a positive numeric value.", args[0]);
9081 return -1;
9082 }
9083 return 0;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01009084}
9085
9086static int ssl_parse_global_capture_cipherlist(char **args, int section_type, struct proxy *curpx,
9087 struct proxy *defpx, const char *file, int line,
9088 char **err)
9089{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01009090 int ret;
9091
9092 ret = ssl_parse_global_int(args, section_type, curpx, defpx, file, line, err);
9093 if (ret != 0)
9094 return ret;
9095
Willy Tarreaubafbe012017-11-24 17:34:44 +01009096 if (pool_head_ssl_capture) {
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01009097 memprintf(err, "'%s' is already configured.", args[0]);
9098 return -1;
9099 }
9100
Willy Tarreaubafbe012017-11-24 17:34:44 +01009101 pool_head_ssl_capture = create_pool("ssl-capture", sizeof(struct ssl_capture) + global_ssl.capture_cipherlist, MEM_F_SHARED);
9102 if (!pool_head_ssl_capture) {
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01009103 memprintf(err, "Out of memory error.");
9104 return -1;
9105 }
9106 return 0;
Willy Tarreau9ceda382016-12-21 23:13:03 +01009107}
9108
9109/* parse "ssl.force-private-cache".
9110 * Returns <0 on alert, >0 on warning, 0 on success.
9111 */
9112static int ssl_parse_global_private_cache(char **args, int section_type, struct proxy *curpx,
9113 struct proxy *defpx, const char *file, int line,
9114 char **err)
9115{
9116 if (too_many_args(0, args, err, NULL))
9117 return -1;
9118
Willy Tarreauef934602016-12-22 23:12:01 +01009119 global_ssl.private_cache = 1;
Willy Tarreau9ceda382016-12-21 23:13:03 +01009120 return 0;
9121}
9122
9123/* parse "ssl.lifetime".
9124 * Returns <0 on alert, >0 on warning, 0 on success.
9125 */
9126static int ssl_parse_global_lifetime(char **args, int section_type, struct proxy *curpx,
9127 struct proxy *defpx, const char *file, int line,
9128 char **err)
9129{
9130 const char *res;
9131
9132 if (too_many_args(1, args, err, NULL))
9133 return -1;
9134
9135 if (*(args[1]) == 0) {
9136 memprintf(err, "'%s' expects ssl sessions <lifetime> in seconds as argument.", args[0]);
9137 return -1;
9138 }
9139
Willy Tarreauef934602016-12-22 23:12:01 +01009140 res = parse_time_err(args[1], &global_ssl.life_time, TIME_UNIT_S);
Willy Tarreau9faebe32019-06-07 19:00:37 +02009141 if (res == PARSE_TIME_OVER) {
9142 memprintf(err, "timer overflow in argument '%s' to <%s> (maximum value is 2147483647 s or ~68 years).",
9143 args[1], args[0]);
9144 return -1;
9145 }
9146 else if (res == PARSE_TIME_UNDER) {
9147 memprintf(err, "timer underflow in argument '%s' to <%s> (minimum non-null value is 1 s).",
9148 args[1], args[0]);
9149 return -1;
9150 }
9151 else if (res) {
Willy Tarreau9ceda382016-12-21 23:13:03 +01009152 memprintf(err, "unexpected character '%c' in argument to <%s>.", *res, args[0]);
9153 return -1;
9154 }
9155 return 0;
9156}
9157
9158#ifndef OPENSSL_NO_DH
Willy Tarreau14e36a12016-12-21 23:28:13 +01009159/* parse "ssl-dh-param-file".
9160 * Returns <0 on alert, >0 on warning, 0 on success.
9161 */
9162static int ssl_parse_global_dh_param_file(char **args, int section_type, struct proxy *curpx,
9163 struct proxy *defpx, const char *file, int line,
9164 char **err)
9165{
9166 if (too_many_args(1, args, err, NULL))
9167 return -1;
9168
9169 if (*(args[1]) == 0) {
9170 memprintf(err, "'%s' expects a file path as an argument.", args[0]);
9171 return -1;
9172 }
9173
9174 if (ssl_sock_load_global_dh_param_from_file(args[1])) {
9175 memprintf(err, "'%s': unable to load DH parameters from file <%s>.", args[0], args[1]);
9176 return -1;
9177 }
9178 return 0;
9179}
9180
Willy Tarreau9ceda382016-12-21 23:13:03 +01009181/* parse "ssl.default-dh-param".
9182 * Returns <0 on alert, >0 on warning, 0 on success.
9183 */
9184static int ssl_parse_global_default_dh(char **args, int section_type, struct proxy *curpx,
9185 struct proxy *defpx, const char *file, int line,
9186 char **err)
9187{
9188 if (too_many_args(1, args, err, NULL))
9189 return -1;
9190
9191 if (*(args[1]) == 0) {
9192 memprintf(err, "'%s' expects an integer argument.", args[0]);
9193 return -1;
9194 }
9195
Willy Tarreauef934602016-12-22 23:12:01 +01009196 global_ssl.default_dh_param = atoi(args[1]);
9197 if (global_ssl.default_dh_param < 1024) {
Willy Tarreau9ceda382016-12-21 23:13:03 +01009198 memprintf(err, "'%s' expects a value >= 1024.", args[0]);
9199 return -1;
9200 }
9201 return 0;
9202}
9203#endif
9204
9205
William Lallemand32af2032016-10-29 18:09:35 +02009206/* This function is used with TLS ticket keys management. It permits to browse
9207 * each reference. The variable <getnext> must contain the current node,
9208 * <end> point to the root node.
9209 */
9210#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
9211static inline
9212struct tls_keys_ref *tlskeys_list_get_next(struct tls_keys_ref *getnext, struct list *end)
9213{
9214 struct tls_keys_ref *ref = getnext;
9215
9216 while (1) {
9217
9218 /* Get next list entry. */
9219 ref = LIST_NEXT(&ref->list, struct tls_keys_ref *, list);
9220
9221 /* If the entry is the last of the list, return NULL. */
9222 if (&ref->list == end)
9223 return NULL;
9224
9225 return ref;
9226 }
9227}
9228
9229static inline
9230struct tls_keys_ref *tlskeys_ref_lookup_ref(const char *reference)
9231{
9232 int id;
9233 char *error;
9234
9235 /* If the reference starts by a '#', this is numeric id. */
9236 if (reference[0] == '#') {
9237 /* Try to convert the numeric id. If the conversion fails, the lookup fails. */
9238 id = strtol(reference + 1, &error, 10);
9239 if (*error != '\0')
9240 return NULL;
9241
9242 /* Perform the unique id lookup. */
9243 return tlskeys_ref_lookupid(id);
9244 }
9245
9246 /* Perform the string lookup. */
9247 return tlskeys_ref_lookup(reference);
9248}
9249#endif
9250
9251
9252#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
9253
9254static int cli_io_handler_tlskeys_files(struct appctx *appctx);
9255
9256static inline int cli_io_handler_tlskeys_entries(struct appctx *appctx) {
9257 return cli_io_handler_tlskeys_files(appctx);
9258}
9259
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009260/* dumps all tls keys. Relies on cli.i0 (non-null = only list file names), cli.i1
9261 * (next index to be dumped), and cli.p0 (next key reference).
9262 */
William Lallemand32af2032016-10-29 18:09:35 +02009263static int cli_io_handler_tlskeys_files(struct appctx *appctx) {
9264
9265 struct stream_interface *si = appctx->owner;
9266
9267 switch (appctx->st2) {
9268 case STAT_ST_INIT:
9269 /* Display the column headers. If the message cannot be sent,
Joseph Herlant017b3da2018-11-15 09:07:59 -08009270 * quit the function with returning 0. The function is called
William Lallemand32af2032016-10-29 18:09:35 +02009271 * later and restart at the state "STAT_ST_INIT".
9272 */
9273 chunk_reset(&trash);
9274
9275 if (appctx->io_handler == cli_io_handler_tlskeys_entries)
9276 chunk_appendf(&trash, "# id secret\n");
9277 else
9278 chunk_appendf(&trash, "# id (file)\n");
9279
Willy Tarreau06d80a92017-10-19 14:32:15 +02009280 if (ci_putchk(si_ic(si), &trash) == -1) {
Willy Tarreaudb398432018-11-15 11:08:52 +01009281 si_rx_room_blk(si);
William Lallemand32af2032016-10-29 18:09:35 +02009282 return 0;
9283 }
9284
William Lallemand32af2032016-10-29 18:09:35 +02009285 /* Now, we start the browsing of the references lists.
9286 * Note that the following call to LIST_ELEM return bad pointer. The only
9287 * available field of this pointer is <list>. It is used with the function
9288 * tlskeys_list_get_next() for retruning the first available entry
9289 */
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009290 if (appctx->ctx.cli.p0 == NULL) {
9291 appctx->ctx.cli.p0 = LIST_ELEM(&tlskeys_reference, struct tls_keys_ref *, list);
9292 appctx->ctx.cli.p0 = tlskeys_list_get_next(appctx->ctx.cli.p0, &tlskeys_reference);
William Lallemand32af2032016-10-29 18:09:35 +02009293 }
9294
9295 appctx->st2 = STAT_ST_LIST;
9296 /* fall through */
9297
9298 case STAT_ST_LIST:
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009299 while (appctx->ctx.cli.p0) {
9300 struct tls_keys_ref *ref = appctx->ctx.cli.p0;
William Lallemand32af2032016-10-29 18:09:35 +02009301
9302 chunk_reset(&trash);
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009303 if (appctx->io_handler == cli_io_handler_tlskeys_entries && appctx->ctx.cli.i1 == 0)
William Lallemand32af2032016-10-29 18:09:35 +02009304 chunk_appendf(&trash, "# ");
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009305
9306 if (appctx->ctx.cli.i1 == 0)
9307 chunk_appendf(&trash, "%d (%s)\n", ref->unique_id, ref->filename);
9308
William Lallemand32af2032016-10-29 18:09:35 +02009309 if (appctx->io_handler == cli_io_handler_tlskeys_entries) {
Christopher Faulet16f45c82018-02-16 11:23:49 +01009310 int head;
9311
9312 HA_RWLOCK_RDLOCK(TLSKEYS_REF_LOCK, &ref->lock);
9313 head = ref->tls_ticket_enc_index;
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009314 while (appctx->ctx.cli.i1 < TLS_TICKETS_NO) {
Willy Tarreau83061a82018-07-13 11:56:34 +02009315 struct buffer *t2 = get_trash_chunk();
William Lallemand32af2032016-10-29 18:09:35 +02009316
9317 chunk_reset(t2);
9318 /* should never fail here because we dump only a key in the t2 buffer */
Emeric Brun9e754772019-01-10 17:51:55 +01009319 if (ref->key_size_bits == 128) {
9320 t2->data = a2base64((char *)(ref->tlskeys + (head + 2 + appctx->ctx.cli.i1) % TLS_TICKETS_NO),
9321 sizeof(struct tls_sess_key_128),
9322 t2->area, t2->size);
9323 chunk_appendf(&trash, "%d.%d %s\n", ref->unique_id, appctx->ctx.cli.i1,
9324 t2->area);
9325 }
9326 else if (ref->key_size_bits == 256) {
9327 t2->data = a2base64((char *)(ref->tlskeys + (head + 2 + appctx->ctx.cli.i1) % TLS_TICKETS_NO),
9328 sizeof(struct tls_sess_key_256),
9329 t2->area, t2->size);
9330 chunk_appendf(&trash, "%d.%d %s\n", ref->unique_id, appctx->ctx.cli.i1,
9331 t2->area);
9332 }
9333 else {
9334 /* This case should never happen */
9335 chunk_appendf(&trash, "%d.%d <unknown>\n", ref->unique_id, appctx->ctx.cli.i1);
9336 }
William Lallemand32af2032016-10-29 18:09:35 +02009337
Willy Tarreau06d80a92017-10-19 14:32:15 +02009338 if (ci_putchk(si_ic(si), &trash) == -1) {
William Lallemand32af2032016-10-29 18:09:35 +02009339 /* let's try again later from this stream. We add ourselves into
9340 * this stream's users so that it can remove us upon termination.
9341 */
Christopher Faulet16f45c82018-02-16 11:23:49 +01009342 HA_RWLOCK_RDUNLOCK(TLSKEYS_REF_LOCK, &ref->lock);
Willy Tarreaudb398432018-11-15 11:08:52 +01009343 si_rx_room_blk(si);
William Lallemand32af2032016-10-29 18:09:35 +02009344 return 0;
9345 }
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009346 appctx->ctx.cli.i1++;
William Lallemand32af2032016-10-29 18:09:35 +02009347 }
Christopher Faulet16f45c82018-02-16 11:23:49 +01009348 HA_RWLOCK_RDUNLOCK(TLSKEYS_REF_LOCK, &ref->lock);
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009349 appctx->ctx.cli.i1 = 0;
William Lallemand32af2032016-10-29 18:09:35 +02009350 }
Willy Tarreau06d80a92017-10-19 14:32:15 +02009351 if (ci_putchk(si_ic(si), &trash) == -1) {
William Lallemand32af2032016-10-29 18:09:35 +02009352 /* let's try again later from this stream. We add ourselves into
9353 * this stream's users so that it can remove us upon termination.
9354 */
Willy Tarreaudb398432018-11-15 11:08:52 +01009355 si_rx_room_blk(si);
William Lallemand32af2032016-10-29 18:09:35 +02009356 return 0;
9357 }
9358
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009359 if (appctx->ctx.cli.i0 == 0) /* don't display everything if not necessary */
William Lallemand32af2032016-10-29 18:09:35 +02009360 break;
9361
9362 /* get next list entry and check the end of the list */
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009363 appctx->ctx.cli.p0 = tlskeys_list_get_next(appctx->ctx.cli.p0, &tlskeys_reference);
William Lallemand32af2032016-10-29 18:09:35 +02009364 }
9365
9366 appctx->st2 = STAT_ST_FIN;
9367 /* fall through */
9368
9369 default:
9370 appctx->st2 = STAT_ST_FIN;
9371 return 1;
9372 }
9373 return 0;
9374}
9375
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009376/* sets cli.i0 to non-zero if only file lists should be dumped */
Aurélien Nephtaliabbf6072018-04-18 13:26:46 +02009377static int cli_parse_show_tlskeys(char **args, char *payload, struct appctx *appctx, void *private)
William Lallemand32af2032016-10-29 18:09:35 +02009378{
William Lallemand32af2032016-10-29 18:09:35 +02009379 /* no parameter, shows only file list */
9380 if (!*args[2]) {
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009381 appctx->ctx.cli.i0 = 1;
William Lallemand32af2032016-10-29 18:09:35 +02009382 appctx->io_handler = cli_io_handler_tlskeys_files;
Willy Tarreau3067bfa2016-12-05 14:50:15 +01009383 return 0;
William Lallemand32af2032016-10-29 18:09:35 +02009384 }
9385
9386 if (args[2][0] == '*') {
9387 /* list every TLS ticket keys */
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009388 appctx->ctx.cli.i0 = 1;
William Lallemand32af2032016-10-29 18:09:35 +02009389 } else {
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009390 appctx->ctx.cli.p0 = tlskeys_ref_lookup_ref(args[2]);
9391 if (!appctx->ctx.cli.p0) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02009392 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02009393 appctx->ctx.cli.msg = "'show tls-keys' unable to locate referenced filename\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01009394 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02009395 return 1;
9396 }
9397 }
William Lallemand32af2032016-10-29 18:09:35 +02009398 appctx->io_handler = cli_io_handler_tlskeys_entries;
Willy Tarreau3067bfa2016-12-05 14:50:15 +01009399 return 0;
William Lallemand32af2032016-10-29 18:09:35 +02009400}
9401
Aurélien Nephtaliabbf6072018-04-18 13:26:46 +02009402static int cli_parse_set_tlskeys(char **args, char *payload, struct appctx *appctx, void *private)
William Lallemand32af2032016-10-29 18:09:35 +02009403{
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009404 struct tls_keys_ref *ref;
Willy Tarreau1c913e42018-08-22 05:26:57 +02009405 int ret;
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009406
William Lallemand32af2032016-10-29 18:09:35 +02009407 /* Expect two parameters: the filename and the new new TLS key in encoding */
9408 if (!*args[3] || !*args[4]) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02009409 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02009410 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 +01009411 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02009412 return 1;
9413 }
9414
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009415 ref = tlskeys_ref_lookup_ref(args[3]);
9416 if (!ref) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02009417 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02009418 appctx->ctx.cli.msg = "'set ssl tls-key' unable to locate referenced filename\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01009419 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02009420 return 1;
9421 }
9422
Willy Tarreau1c913e42018-08-22 05:26:57 +02009423 ret = base64dec(args[4], strlen(args[4]), trash.area, trash.size);
Emeric Brun9e754772019-01-10 17:51:55 +01009424 if (ret < 0) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02009425 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02009426 appctx->ctx.cli.msg = "'set ssl tls-key' received invalid base64 encoded TLS key.\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01009427 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02009428 return 1;
9429 }
Emeric Brun9e754772019-01-10 17:51:55 +01009430
Willy Tarreau1c913e42018-08-22 05:26:57 +02009431 trash.data = ret;
Emeric Brun9e754772019-01-10 17:51:55 +01009432 if (ssl_sock_update_tlskey_ref(ref, &trash) < 0) {
9433 appctx->ctx.cli.severity = LOG_ERR;
9434 appctx->ctx.cli.msg = "'set ssl tls-key' received a key of wrong size.\n";
9435 appctx->st0 = CLI_ST_PRINT;
9436 return 1;
9437 }
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02009438 appctx->ctx.cli.severity = LOG_INFO;
Aurélien Nephtali6e8a41d2018-03-15 21:48:50 +01009439 appctx->ctx.cli.msg = "TLS ticket key updated!\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01009440 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02009441 return 1;
9442
9443}
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01009444#endif
William Lallemand32af2032016-10-29 18:09:35 +02009445
Aurélien Nephtaliabbf6072018-04-18 13:26:46 +02009446static int cli_parse_set_ocspresponse(char **args, char *payload, struct appctx *appctx, void *private)
William Lallemand32af2032016-10-29 18:09:35 +02009447{
9448#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
9449 char *err = NULL;
Willy Tarreau1c913e42018-08-22 05:26:57 +02009450 int i, j, ret;
Aurélien Nephtali1e0867c2018-04-18 14:04:58 +02009451
9452 if (!payload)
9453 payload = args[3];
William Lallemand32af2032016-10-29 18:09:35 +02009454
9455 /* Expect one parameter: the new response in base64 encoding */
Aurélien Nephtali1e0867c2018-04-18 14:04:58 +02009456 if (!*payload) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02009457 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02009458 appctx->ctx.cli.msg = "'set ssl ocsp-response' expects response in base64 encoding.\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01009459 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02009460 return 1;
9461 }
Aurélien Nephtali1e0867c2018-04-18 14:04:58 +02009462
9463 /* remove \r and \n from the payload */
9464 for (i = 0, j = 0; payload[i]; i++) {
9465 if (payload[i] == '\r' || payload[i] == '\n')
9466 continue;
9467 payload[j++] = payload[i];
9468 }
9469 payload[j] = 0;
William Lallemand32af2032016-10-29 18:09:35 +02009470
Willy Tarreau1c913e42018-08-22 05:26:57 +02009471 ret = base64dec(payload, j, trash.area, trash.size);
9472 if (ret < 0) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02009473 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02009474 appctx->ctx.cli.msg = "'set ssl ocsp-response' received invalid base64 encoded response.\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01009475 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02009476 return 1;
9477 }
9478
Willy Tarreau1c913e42018-08-22 05:26:57 +02009479 trash.data = ret;
William Lallemand32af2032016-10-29 18:09:35 +02009480 if (ssl_sock_update_ocsp_response(&trash, &err)) {
9481 if (err) {
9482 memprintf(&err, "%s.\n", err);
9483 appctx->ctx.cli.err = err;
Willy Tarreau3b6e5472016-11-24 15:53:53 +01009484 appctx->st0 = CLI_ST_PRINT_FREE;
William Lallemand32af2032016-10-29 18:09:35 +02009485 }
Aurélien Nephtali9a4da682018-04-16 19:02:42 +02009486 else {
9487 appctx->ctx.cli.severity = LOG_ERR;
9488 appctx->ctx.cli.msg = "Failed to update OCSP response.\n";
9489 appctx->st0 = CLI_ST_PRINT;
9490 }
William Lallemand32af2032016-10-29 18:09:35 +02009491 return 1;
9492 }
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02009493 appctx->ctx.cli.severity = LOG_INFO;
Aurélien Nephtali6e8a41d2018-03-15 21:48:50 +01009494 appctx->ctx.cli.msg = "OCSP Response updated!\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01009495 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02009496 return 1;
9497#else
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02009498 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02009499 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 +01009500 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02009501 return 1;
9502#endif
9503
Nenad Merdanovicc31499d2019-03-23 11:00:32 +01009504}
9505
Willy Tarreau86a394e2019-05-09 14:15:32 +02009506#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000100fL)
Nenad Merdanovicc31499d2019-03-23 11:00:32 +01009507static inline int sample_conv_var2smp_str(const struct arg *arg, struct sample *smp)
9508{
9509 switch (arg->type) {
9510 case ARGT_STR:
9511 smp->data.type = SMP_T_STR;
9512 smp->data.u.str = arg->data.str;
9513 return 1;
9514 case ARGT_VAR:
9515 if (!vars_get_by_desc(&arg->data.var, smp))
9516 return 0;
9517 if (!sample_casts[smp->data.type][SMP_T_STR])
9518 return 0;
9519 if (!sample_casts[smp->data.type][SMP_T_STR](smp))
9520 return 0;
9521 return 1;
9522 default:
9523 return 0;
9524 }
9525}
9526
9527static int check_aes_gcm(struct arg *args, struct sample_conv *conv,
9528 const char *file, int line, char **err)
9529{
9530 switch(args[0].data.sint) {
9531 case 128:
9532 case 192:
9533 case 256:
9534 break;
9535 default:
9536 memprintf(err, "key size must be 128, 192 or 256 (bits).");
9537 return 0;
9538 }
9539 /* Try to decode a variable. */
9540 vars_check_arg(&args[1], NULL);
9541 vars_check_arg(&args[2], NULL);
9542 vars_check_arg(&args[3], NULL);
9543 return 1;
9544}
9545
9546/* Arguements: AES size in bits, nonce, key, tag. The last three arguments are base64 encoded */
9547static int sample_conv_aes_gcm_dec(const struct arg *arg_p, struct sample *smp, void *private)
9548{
9549 struct sample nonce, key, aead_tag;
9550 struct buffer *smp_trash, *smp_trash_alloc;
9551 EVP_CIPHER_CTX *ctx;
9552 int dec_size, ret;
9553
9554 smp_set_owner(&nonce, smp->px, smp->sess, smp->strm, smp->opt);
9555 if (!sample_conv_var2smp_str(&arg_p[1], &nonce))
9556 return 0;
9557
9558 smp_set_owner(&key, smp->px, smp->sess, smp->strm, smp->opt);
9559 if (!sample_conv_var2smp_str(&arg_p[2], &key))
9560 return 0;
9561
9562 smp_set_owner(&aead_tag, smp->px, smp->sess, smp->strm, smp->opt);
9563 if (!sample_conv_var2smp_str(&arg_p[3], &aead_tag))
9564 return 0;
9565
9566 smp_trash = get_trash_chunk();
9567 smp_trash_alloc = alloc_trash_chunk();
9568 if (!smp_trash_alloc)
9569 return 0;
9570
9571 ctx = EVP_CIPHER_CTX_new();
9572
9573 if (!ctx)
9574 goto err;
9575
9576 dec_size = base64dec(nonce.data.u.str.area, nonce.data.u.str.data, smp_trash->area, smp_trash->size);
9577 if (dec_size < 0)
9578 goto err;
9579 smp_trash->data = dec_size;
9580
9581 /* Set cipher type and mode */
9582 switch(arg_p[0].data.sint) {
9583 case 128:
9584 EVP_DecryptInit_ex(ctx, EVP_aes_128_gcm(), NULL, NULL, NULL);
9585 break;
9586 case 192:
9587 EVP_DecryptInit_ex(ctx, EVP_aes_192_gcm(), NULL, NULL, NULL);
9588 break;
9589 case 256:
9590 EVP_DecryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL);
9591 break;
9592 }
9593
9594 EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, smp_trash->data, NULL);
9595
9596 /* Initialise IV */
9597 if(!EVP_DecryptInit_ex(ctx, NULL, NULL, NULL, (unsigned char *) smp_trash->area))
9598 goto err;
9599
9600 dec_size = base64dec(key.data.u.str.area, key.data.u.str.data, smp_trash->area, smp_trash->size);
9601 if (dec_size < 0)
9602 goto err;
9603 smp_trash->data = dec_size;
9604
9605 /* Initialise key */
9606 if (!EVP_DecryptInit_ex(ctx, NULL, NULL, (unsigned char *) smp_trash->area, NULL))
9607 goto err;
9608
9609 if (!EVP_DecryptUpdate(ctx, (unsigned char *) smp_trash->area, (int *) &smp_trash->data,
9610 (unsigned char *) smp->data.u.str.area, (int) smp->data.u.str.data))
9611 goto err;
9612
9613 dec_size = base64dec(aead_tag.data.u.str.area, aead_tag.data.u.str.data, smp_trash_alloc->area, smp_trash_alloc->size);
9614 if (dec_size < 0)
9615 goto err;
9616 smp_trash_alloc->data = dec_size;
9617 dec_size = smp_trash->data;
9618
9619 EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, smp_trash_alloc->data, (void *) smp_trash_alloc->area);
9620 ret = EVP_DecryptFinal_ex(ctx, (unsigned char *) smp_trash->area + smp_trash->data, (int *) &smp_trash->data);
9621
9622 if (ret <= 0)
9623 goto err;
9624
9625 smp->data.u.str.data = dec_size + smp_trash->data;
9626 smp->data.u.str.area = smp_trash->area;
9627 smp->data.type = SMP_T_BIN;
9628 smp->flags &= ~SMP_F_CONST;
9629 free_trash_chunk(smp_trash_alloc);
9630 return 1;
9631
9632err:
9633 free_trash_chunk(smp_trash_alloc);
9634 return 0;
William Lallemand32af2032016-10-29 18:09:35 +02009635}
Nenad Merdanovicc31499d2019-03-23 11:00:32 +01009636# endif
William Lallemand32af2032016-10-29 18:09:35 +02009637
9638/* register cli keywords */
9639static struct cli_kw_list cli_kws = {{ },{
9640#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
9641 { { "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 +02009642 { { "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 +02009643#endif
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01009644 { { "set", "ssl", "ocsp-response", NULL }, NULL, cli_parse_set_ocspresponse, NULL },
William Lallemand32af2032016-10-29 18:09:35 +02009645 { { NULL }, NULL, NULL, NULL }
9646}};
9647
Willy Tarreau0108d902018-11-25 19:14:37 +01009648INITCALL1(STG_REGISTER, cli_register_kw, &cli_kws);
William Lallemand32af2032016-10-29 18:09:35 +02009649
Willy Tarreau7875d092012-09-10 08:20:03 +02009650/* Note: must not be declared <const> as its list will be overwritten.
9651 * Please take care of keeping this list alphabetically sorted.
9652 */
Willy Tarreaudc13c112013-06-21 23:16:39 +02009653static struct sample_fetch_kw_list sample_fetch_keywords = {ILH, {
Emeric Brun645ae792014-04-30 14:21:06 +02009654 { "ssl_bc", smp_fetch_ssl_fc, 0, NULL, SMP_T_BOOL, SMP_USE_L5SRV },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02009655 { "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 +01009656#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Jérôme Magnine064a802018-12-03 22:21:04 +01009657 { "ssl_bc_alpn", smp_fetch_ssl_fc_alpn, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
Olivier Houchard6b77f492018-11-22 18:18:29 +01009658#endif
Emeric Brun645ae792014-04-30 14:21:06 +02009659 { "ssl_bc_cipher", smp_fetch_ssl_fc_cipher, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
Olivier Houchard6b77f492018-11-22 18:18:29 +01009660#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
9661 { "ssl_bc_npn", smp_fetch_ssl_fc_npn, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
9662#endif
Emeric Brun74f7ffa2018-02-19 16:14:12 +01009663 { "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 +02009664 { "ssl_bc_protocol", smp_fetch_ssl_fc_protocol, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
Emeric Brunb73a9b02014-04-30 18:49:19 +02009665 { "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 +02009666 { "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 +02009667#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
Emeric Brun645ae792014-04-30 14:21:06 +02009668 { "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 -04009669#endif
Emmanuel Hocdet839af572019-05-14 16:27:35 +02009670#if HA_OPENSSL_VERSION_NUMBER >= 0x10100000L
Patrick Hemmer65674662019-06-04 08:13:03 -04009671 { "ssl_bc_client_random", smp_fetch_ssl_fc_random, 0, NULL, SMP_T_BIN, SMP_USE_L5SRV },
9672 { "ssl_bc_server_random", smp_fetch_ssl_fc_random, 0, NULL, SMP_T_BIN, SMP_USE_L5SRV },
Patrick Hemmere0275472018-04-28 19:15:51 -04009673 { "ssl_bc_session_key", smp_fetch_ssl_fc_session_key, 0, NULL, SMP_T_BIN, SMP_USE_L5SRV },
9674#endif
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02009675 { "ssl_c_ca_err", smp_fetch_ssl_c_ca_err, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
9676 { "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 +01009677 { "ssl_c_der", smp_fetch_ssl_x_der, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02009678 { "ssl_c_err", smp_fetch_ssl_c_err, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Emeric Brunba841a12014-04-30 17:05:08 +02009679 { "ssl_c_i_dn", smp_fetch_ssl_x_i_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
9680 { "ssl_c_key_alg", smp_fetch_ssl_x_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
9681 { "ssl_c_notafter", smp_fetch_ssl_x_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
9682 { "ssl_c_notbefore", smp_fetch_ssl_x_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
9683 { "ssl_c_sig_alg", smp_fetch_ssl_x_sig_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
9684 { "ssl_c_s_dn", smp_fetch_ssl_x_s_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
9685 { "ssl_c_serial", smp_fetch_ssl_x_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
9686 { "ssl_c_sha1", smp_fetch_ssl_x_sha1, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +01009687 { "ssl_c_used", smp_fetch_ssl_c_used, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02009688 { "ssl_c_verify", smp_fetch_ssl_c_verify, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
9689 { "ssl_c_version", smp_fetch_ssl_x_version, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Emeric Brun43e79582014-10-29 19:03:26 +01009690 { "ssl_f_der", smp_fetch_ssl_x_der, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Emeric Brunba841a12014-04-30 17:05:08 +02009691 { "ssl_f_i_dn", smp_fetch_ssl_x_i_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
9692 { "ssl_f_key_alg", smp_fetch_ssl_x_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
9693 { "ssl_f_notafter", smp_fetch_ssl_x_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
9694 { "ssl_f_notbefore", smp_fetch_ssl_x_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
9695 { "ssl_f_sig_alg", smp_fetch_ssl_x_sig_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
9696 { "ssl_f_s_dn", smp_fetch_ssl_x_s_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
9697 { "ssl_f_serial", smp_fetch_ssl_x_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Emeric Brun55f4fa82014-04-30 17:11:25 +02009698 { "ssl_f_sha1", smp_fetch_ssl_x_sha1, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02009699 { "ssl_f_version", smp_fetch_ssl_x_version, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +01009700 { "ssl_fc", smp_fetch_ssl_fc, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02009701 { "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 +01009702 { "ssl_fc_cipher", smp_fetch_ssl_fc_cipher, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +01009703 { "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 +02009704 { "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 +01009705 { "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 +02009706 { "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 +01009707#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01009708 { "ssl_fc_npn", smp_fetch_ssl_fc_npn, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreaua33c6542012-10-15 13:19:06 +02009709#endif
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01009710#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01009711 { "ssl_fc_alpn", smp_fetch_ssl_fc_alpn, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreauab861d32013-04-02 02:30:41 +02009712#endif
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01009713 { "ssl_fc_protocol", smp_fetch_ssl_fc_protocol, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreau9a1ab082019-05-09 13:26:41 +02009714#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
Emeric Brunb73a9b02014-04-30 18:49:19 +02009715 { "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 -04009716#endif
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02009717 { "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 +02009718#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01009719 { "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 -04009720#endif
Emmanuel Hocdet839af572019-05-14 16:27:35 +02009721#if HA_OPENSSL_VERSION_NUMBER >= 0x10100000L
Patrick Hemmer65674662019-06-04 08:13:03 -04009722 { "ssl_fc_client_random", smp_fetch_ssl_fc_random, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
9723 { "ssl_fc_server_random", smp_fetch_ssl_fc_random, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Patrick Hemmere0275472018-04-28 19:15:51 -04009724 { "ssl_fc_session_key", smp_fetch_ssl_fc_session_key, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
9725#endif
Patrick Hemmer41966772018-04-28 19:15:48 -04009726#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01009727 { "ssl_fc_sni", smp_fetch_ssl_fc_sni, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Patrick Hemmer41966772018-04-28 19:15:48 -04009728#endif
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01009729 { "ssl_fc_cipherlist_bin", smp_fetch_ssl_fc_cl_bin, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
9730 { "ssl_fc_cipherlist_hex", smp_fetch_ssl_fc_cl_hex, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
9731 { "ssl_fc_cipherlist_str", smp_fetch_ssl_fc_cl_str, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
9732 { "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 +02009733 { NULL, NULL, 0, 0, 0 },
9734}};
9735
Willy Tarreau0108d902018-11-25 19:14:37 +01009736INITCALL1(STG_REGISTER, sample_register_fetches, &sample_fetch_keywords);
9737
Willy Tarreau7875d092012-09-10 08:20:03 +02009738/* Note: must not be declared <const> as its list will be overwritten.
9739 * Please take care of keeping this list alphabetically sorted.
9740 */
Willy Tarreaudc13c112013-06-21 23:16:39 +02009741static struct acl_kw_list acl_kws = {ILH, {
Thierry FOURNIERc5a4e982014-03-05 16:07:08 +01009742 { "ssl_fc_sni_end", "ssl_fc_sni", PAT_MATCH_END },
9743 { "ssl_fc_sni_reg", "ssl_fc_sni", PAT_MATCH_REG },
Willy Tarreau8ed669b2013-01-11 15:49:37 +01009744 { /* END */ },
Willy Tarreau7875d092012-09-10 08:20:03 +02009745}};
9746
Willy Tarreau0108d902018-11-25 19:14:37 +01009747INITCALL1(STG_REGISTER, acl_register_keywords, &acl_kws);
9748
Willy Tarreau79eeafa2012-09-14 07:53:05 +02009749/* Note: must not be declared <const> as its list will be overwritten.
9750 * Please take care of keeping this list alphabetically sorted, doing so helps
9751 * all code contributors.
9752 * Optional keywords are also declared with a NULL ->parse() function so that
9753 * the config parser can report an appropriate error when a known keyword was
9754 * not enabled.
9755 */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01009756static struct ssl_bind_kw ssl_bind_kws[] = {
Olivier Houchardc2aae742017-09-22 18:26:28 +02009757 { "allow-0rtt", ssl_bind_parse_allow_0rtt, 0 }, /* allow 0-RTT */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01009758 { "alpn", ssl_bind_parse_alpn, 1 }, /* set ALPN supported protocols */
9759 { "ca-file", ssl_bind_parse_ca_file, 1 }, /* set CAfile to process verify on client cert */
9760 { "ciphers", ssl_bind_parse_ciphers, 1 }, /* set SSL cipher suite */
Emmanuel Hocdet839af572019-05-14 16:27:35 +02009761#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009762 { "ciphersuites", ssl_bind_parse_ciphersuites, 1 }, /* set TLS 1.3 cipher suite */
9763#endif
Emmanuel Hocdet98263292016-12-29 18:26:15 +01009764 { "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 +01009765 { "curves", ssl_bind_parse_curves, 1 }, /* set SSL curve suite */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01009766 { "ecdhe", ssl_bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02009767 { "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 +01009768 { "npn", ssl_bind_parse_npn, 1 }, /* set NPN supported protocols */
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02009769 { "ssl-min-ver", ssl_bind_parse_tls_method_minmax,1 }, /* minimum version */
9770 { "ssl-max-ver", ssl_bind_parse_tls_method_minmax,1 }, /* maximum version */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01009771 { "verify", ssl_bind_parse_verify, 1 }, /* set SSL verify method */
9772 { NULL, NULL, 0 },
9773};
9774
Willy Tarreau0108d902018-11-25 19:14:37 +01009775/* no initcall for ssl_bind_kws, these ones are parsed in the parser loop */
9776
Willy Tarreau51fb7652012-09-18 18:24:39 +02009777static struct bind_kw_list bind_kws = { "SSL", { }, {
Olivier Houchardc2aae742017-09-22 18:26:28 +02009778 { "allow-0rtt", bind_parse_allow_0rtt, 0 }, /* Allow 0RTT */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02009779 { "alpn", bind_parse_alpn, 1 }, /* set ALPN supported protocols */
9780 { "ca-file", bind_parse_ca_file, 1 }, /* set CAfile to process verify on client cert */
9781 { "ca-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ignore on verify depth > 0 */
9782 { "ca-sign-file", bind_parse_ca_sign_file, 1 }, /* set CAFile used to generate and sign server certs */
9783 { "ca-sign-pass", bind_parse_ca_sign_pass, 1 }, /* set CAKey passphrase */
9784 { "ciphers", bind_parse_ciphers, 1 }, /* set SSL cipher suite */
Emmanuel Hocdet839af572019-05-14 16:27:35 +02009785#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009786 { "ciphersuites", bind_parse_ciphersuites, 1 }, /* set TLS 1.3 cipher suite */
9787#endif
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02009788 { "crl-file", bind_parse_crl_file, 1 }, /* set certificat revocation list file use on client cert verify */
9789 { "crt", bind_parse_crt, 1 }, /* load SSL certificates from this location */
9790 { "crt-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ingore on verify depth == 0 */
9791 { "crt-list", bind_parse_crt_list, 1 }, /* load a list of crt from this location */
9792 { "curves", bind_parse_curves, 1 }, /* set SSL curve suite */
9793 { "ecdhe", bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
9794 { "force-sslv3", bind_parse_tls_method_options, 0 }, /* force SSLv3 */
9795 { "force-tlsv10", bind_parse_tls_method_options, 0 }, /* force TLSv10 */
9796 { "force-tlsv11", bind_parse_tls_method_options, 0 }, /* force TLSv11 */
9797 { "force-tlsv12", bind_parse_tls_method_options, 0 }, /* force TLSv12 */
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +02009798 { "force-tlsv13", bind_parse_tls_method_options, 0 }, /* force TLSv13 */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02009799 { "generate-certificates", bind_parse_generate_certs, 0 }, /* enable the server certificates generation */
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02009800 { "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 +02009801 { "no-sslv3", bind_parse_tls_method_options, 0 }, /* disable SSLv3 */
9802 { "no-tlsv10", bind_parse_tls_method_options, 0 }, /* disable TLSv10 */
9803 { "no-tlsv11", bind_parse_tls_method_options, 0 }, /* disable TLSv11 */
9804 { "no-tlsv12", bind_parse_tls_method_options, 0 }, /* disable TLSv12 */
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +02009805 { "no-tlsv13", bind_parse_tls_method_options, 0 }, /* disable TLSv13 */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02009806 { "no-tls-tickets", bind_parse_no_tls_tickets, 0 }, /* disable session resumption tickets */
9807 { "ssl", bind_parse_ssl, 0 }, /* enable SSL processing */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02009808 { "ssl-min-ver", bind_parse_tls_method_minmax, 1 }, /* minimum version */
9809 { "ssl-max-ver", bind_parse_tls_method_minmax, 1 }, /* maximum version */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02009810 { "strict-sni", bind_parse_strict_sni, 0 }, /* refuse negotiation if sni doesn't match a certificate */
9811 { "tls-ticket-keys", bind_parse_tls_ticket_keys, 1 }, /* set file to load TLS ticket keys from */
9812 { "verify", bind_parse_verify, 1 }, /* set SSL verify method */
9813 { "npn", bind_parse_npn, 1 }, /* set NPN supported protocols */
9814 { "prefer-client-ciphers", bind_parse_pcc, 0 }, /* prefer client ciphers */
Willy Tarreau79eeafa2012-09-14 07:53:05 +02009815 { NULL, NULL, 0 },
9816}};
Emeric Brun46591952012-05-18 15:47:34 +02009817
Willy Tarreau0108d902018-11-25 19:14:37 +01009818INITCALL1(STG_REGISTER, bind_register_keywords, &bind_kws);
9819
Willy Tarreau92faadf2012-10-10 23:04:25 +02009820/* Note: must not be declared <const> as its list will be overwritten.
9821 * Please take care of keeping this list alphabetically sorted, doing so helps
9822 * all code contributors.
9823 * Optional keywords are also declared with a NULL ->parse() function so that
9824 * the config parser can report an appropriate error when a known keyword was
9825 * not enabled.
9826 */
9827static struct srv_kw_list srv_kws = { "SSL", { }, {
Olivier Houchard522eea72017-11-03 16:27:47 +01009828 { "allow-0rtt", srv_parse_allow_0rtt, 0, 1 }, /* Allow using early data on this server */
Olivier Houchardc7566002018-11-20 23:33:50 +01009829 { "alpn", srv_parse_alpn, 1, 1 }, /* Set ALPN supported protocols */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02009830 { "ca-file", srv_parse_ca_file, 1, 1 }, /* set CAfile to process verify server cert */
Olivier Houchard92150142018-12-21 19:47:01 +01009831 { "check-alpn", srv_parse_alpn, 1, 1 }, /* Set ALPN used for checks */
Olivier Houchard9130a962017-10-17 17:33:43 +02009832 { "check-sni", srv_parse_check_sni, 1, 1 }, /* set SNI */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02009833 { "check-ssl", srv_parse_check_ssl, 0, 1 }, /* enable SSL for health checks */
9834 { "ciphers", srv_parse_ciphers, 1, 1 }, /* select the cipher suite */
Emmanuel Hocdet839af572019-05-14 16:27:35 +02009835#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009836 { "ciphersuites", srv_parse_ciphersuites, 1, 1 }, /* select the cipher suite */
9837#endif
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02009838 { "crl-file", srv_parse_crl_file, 1, 1 }, /* set certificate revocation list file use on server cert verify */
9839 { "crt", srv_parse_crt, 1, 1 }, /* set client certificate */
9840 { "force-sslv3", srv_parse_tls_method_options, 0, 1 }, /* force SSLv3 */
9841 { "force-tlsv10", srv_parse_tls_method_options, 0, 1 }, /* force TLSv10 */
9842 { "force-tlsv11", srv_parse_tls_method_options, 0, 1 }, /* force TLSv11 */
9843 { "force-tlsv12", srv_parse_tls_method_options, 0, 1 }, /* force TLSv12 */
9844 { "force-tlsv13", srv_parse_tls_method_options, 0, 1 }, /* force TLSv13 */
9845 { "no-check-ssl", srv_parse_no_check_ssl, 0, 1 }, /* disable SSL for health checks */
9846 { "no-send-proxy-v2-ssl", srv_parse_no_send_proxy_ssl, 0, 1 }, /* do not send PROXY protocol header v2 with SSL info */
9847 { "no-send-proxy-v2-ssl-cn", srv_parse_no_send_proxy_cn, 0, 1 }, /* do not send PROXY protocol header v2 with CN */
9848 { "no-ssl", srv_parse_no_ssl, 0, 1 }, /* disable SSL processing */
9849 { "no-ssl-reuse", srv_parse_no_ssl_reuse, 0, 1 }, /* disable session reuse */
9850 { "no-sslv3", srv_parse_tls_method_options, 0, 0 }, /* disable SSLv3 */
9851 { "no-tlsv10", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv10 */
9852 { "no-tlsv11", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv11 */
9853 { "no-tlsv12", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv12 */
9854 { "no-tlsv13", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv13 */
9855 { "no-tls-tickets", srv_parse_no_tls_tickets, 0, 1 }, /* disable session resumption tickets */
Olivier Houchardc7566002018-11-20 23:33:50 +01009856 { "npn", srv_parse_npn, 1, 1 }, /* Set NPN supported protocols */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02009857 { "send-proxy-v2-ssl", srv_parse_send_proxy_ssl, 0, 1 }, /* send PROXY protocol header v2 with SSL info */
9858 { "send-proxy-v2-ssl-cn", srv_parse_send_proxy_cn, 0, 1 }, /* send PROXY protocol header v2 with CN */
9859 { "sni", srv_parse_sni, 1, 1 }, /* send SNI extension */
9860 { "ssl", srv_parse_ssl, 0, 1 }, /* enable SSL processing */
9861 { "ssl-min-ver", srv_parse_tls_method_minmax, 1, 1 }, /* minimum version */
9862 { "ssl-max-ver", srv_parse_tls_method_minmax, 1, 1 }, /* maximum version */
9863 { "ssl-reuse", srv_parse_ssl_reuse, 0, 1 }, /* enable session reuse */
9864 { "tls-tickets", srv_parse_tls_tickets, 0, 1 }, /* enable session resumption tickets */
9865 { "verify", srv_parse_verify, 1, 1 }, /* set SSL verify method */
9866 { "verifyhost", srv_parse_verifyhost, 1, 1 }, /* require that SSL cert verifies for hostname */
Willy Tarreau92faadf2012-10-10 23:04:25 +02009867 { NULL, NULL, 0, 0 },
9868}};
9869
Willy Tarreau0108d902018-11-25 19:14:37 +01009870INITCALL1(STG_REGISTER, srv_register_keywords, &srv_kws);
9871
Emeric Brun2c86cbf2014-10-30 15:56:50 +01009872static struct cfg_kw_list cfg_kws = {ILH, {
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01009873 { CFG_GLOBAL, "ca-base", ssl_parse_global_ca_crt_base },
9874 { CFG_GLOBAL, "crt-base", ssl_parse_global_ca_crt_base },
Willy Tarreau0bea58d2016-12-21 23:17:25 +01009875 { CFG_GLOBAL, "maxsslconn", ssl_parse_global_int },
Emeric Brun2c86cbf2014-10-30 15:56:50 +01009876 { CFG_GLOBAL, "ssl-default-bind-options", ssl_parse_default_bind_options },
9877 { CFG_GLOBAL, "ssl-default-server-options", ssl_parse_default_server_options },
Willy Tarreau14e36a12016-12-21 23:28:13 +01009878#ifndef OPENSSL_NO_DH
9879 { CFG_GLOBAL, "ssl-dh-param-file", ssl_parse_global_dh_param_file },
9880#endif
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00009881 { CFG_GLOBAL, "ssl-mode-async", ssl_parse_global_ssl_async },
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02009882#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +00009883 { CFG_GLOBAL, "ssl-engine", ssl_parse_global_ssl_engine },
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02009884#endif
Willy Tarreau9ceda382016-12-21 23:13:03 +01009885 { CFG_GLOBAL, "tune.ssl.cachesize", ssl_parse_global_int },
9886#ifndef OPENSSL_NO_DH
9887 { CFG_GLOBAL, "tune.ssl.default-dh-param", ssl_parse_global_default_dh },
9888#endif
9889 { CFG_GLOBAL, "tune.ssl.force-private-cache", ssl_parse_global_private_cache },
9890 { CFG_GLOBAL, "tune.ssl.lifetime", ssl_parse_global_lifetime },
9891 { CFG_GLOBAL, "tune.ssl.maxrecord", ssl_parse_global_int },
9892 { CFG_GLOBAL, "tune.ssl.ssl-ctx-cache-size", ssl_parse_global_int },
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01009893 { CFG_GLOBAL, "tune.ssl.capture-cipherlist-size", ssl_parse_global_capture_cipherlist },
Willy Tarreauf22e9682016-12-21 23:23:19 +01009894 { CFG_GLOBAL, "ssl-default-bind-ciphers", ssl_parse_global_ciphers },
9895 { CFG_GLOBAL, "ssl-default-server-ciphers", ssl_parse_global_ciphers },
Emmanuel Hocdet839af572019-05-14 16:27:35 +02009896#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009897 { CFG_GLOBAL, "ssl-default-bind-ciphersuites", ssl_parse_global_ciphersuites },
9898 { CFG_GLOBAL, "ssl-default-server-ciphersuites", ssl_parse_global_ciphersuites },
9899#endif
Emeric Brun2c86cbf2014-10-30 15:56:50 +01009900 { 0, NULL, NULL },
9901}};
9902
Willy Tarreau0108d902018-11-25 19:14:37 +01009903INITCALL1(STG_REGISTER, cfg_register_keywords, &cfg_kws);
9904
Nenad Merdanovicc31499d2019-03-23 11:00:32 +01009905/* Note: must not be declared <const> as its list will be overwritten */
9906static struct sample_conv_kw_list conv_kws = {ILH, {
Willy Tarreau86a394e2019-05-09 14:15:32 +02009907#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000100fL)
Nenad Merdanovicc31499d2019-03-23 11:00:32 +01009908 { "aes_gcm_dec", sample_conv_aes_gcm_dec, ARG4(4,SINT,STR,STR,STR), check_aes_gcm, SMP_T_BIN, SMP_T_BIN },
9909#endif
9910 { NULL, NULL, 0, 0, 0 },
9911}};
9912
9913INITCALL1(STG_REGISTER, sample_register_convs, &conv_kws);
9914
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02009915/* transport-layer operations for SSL sockets */
Willy Tarreaud9f5cca2016-12-22 21:08:52 +01009916static struct xprt_ops ssl_sock = {
Emeric Brun46591952012-05-18 15:47:34 +02009917 .snd_buf = ssl_sock_from_buf,
9918 .rcv_buf = ssl_sock_to_buf,
Olivier Houcharddf357842019-03-21 16:30:07 +01009919 .subscribe = ssl_subscribe,
9920 .unsubscribe = ssl_unsubscribe,
Olivier Houchard5149b592019-05-23 17:47:36 +02009921 .remove_xprt = ssl_remove_xprt,
Olivier Houchard2e055482019-05-27 19:50:12 +02009922 .add_xprt = ssl_add_xprt,
Emeric Brun46591952012-05-18 15:47:34 +02009923 .rcv_pipe = NULL,
9924 .snd_pipe = NULL,
9925 .shutr = NULL,
9926 .shutw = ssl_sock_shutw,
9927 .close = ssl_sock_close,
9928 .init = ssl_sock_init,
Willy Tarreau55d37912016-12-21 23:38:39 +01009929 .prepare_bind_conf = ssl_sock_prepare_bind_conf,
Willy Tarreau795cdab2016-12-22 17:30:54 +01009930 .destroy_bind_conf = ssl_sock_destroy_bind_conf,
Willy Tarreau17d45382016-12-22 21:16:08 +01009931 .prepare_srv = ssl_sock_prepare_srv_ctx,
9932 .destroy_srv = ssl_sock_free_srv_ctx,
Willy Tarreau8743f7e2016-12-04 18:44:29 +01009933 .get_alpn = ssl_sock_get_alpn,
Willy Tarreau8e0bb0a2016-11-24 16:58:12 +01009934 .name = "SSL",
Emeric Brun46591952012-05-18 15:47:34 +02009935};
9936
Olivier Houchardccaa7de2017-10-02 11:51:03 +02009937enum act_return ssl_action_wait_for_hs(struct act_rule *rule, struct proxy *px,
9938 struct session *sess, struct stream *s, int flags)
9939{
9940 struct connection *conn;
Olivier Houchard6fa63d92017-11-27 18:41:32 +01009941 struct conn_stream *cs;
Olivier Houchardccaa7de2017-10-02 11:51:03 +02009942
9943 conn = objt_conn(sess->origin);
Olivier Houchard6fa63d92017-11-27 18:41:32 +01009944 cs = objt_cs(s->si[0].end);
Olivier Houchardccaa7de2017-10-02 11:51:03 +02009945
Olivier Houchard6fa63d92017-11-27 18:41:32 +01009946 if (conn && cs) {
Olivier Houchardccaa7de2017-10-02 11:51:03 +02009947 if (conn->flags & (CO_FL_EARLY_SSL_HS | CO_FL_SSL_WAIT_HS)) {
Olivier Houchard6fa63d92017-11-27 18:41:32 +01009948 cs->flags |= CS_FL_WAIT_FOR_HS;
Olivier Houchardccaa7de2017-10-02 11:51:03 +02009949 s->req.flags |= CF_READ_NULL;
9950 return ACT_RET_YIELD;
9951 }
9952 }
9953 return (ACT_RET_CONT);
9954}
9955
9956static enum act_parse_ret ssl_parse_wait_for_hs(const char **args, int *orig_arg, struct proxy *px, struct act_rule *rule, char **err)
9957{
9958 rule->action_ptr = ssl_action_wait_for_hs;
9959
9960 return ACT_RET_PRS_OK;
9961}
9962
9963static struct action_kw_list http_req_actions = {ILH, {
9964 { "wait-for-handshake", ssl_parse_wait_for_hs },
9965 { /* END */ }
9966}};
9967
Willy Tarreau0108d902018-11-25 19:14:37 +01009968INITCALL1(STG_REGISTER, http_req_keywords_register, &http_req_actions);
9969
Willy Tarreau5db847a2019-05-09 14:13:35 +02009970#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01009971
9972static void ssl_sock_sctl_free_func(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, long argl, void *argp)
9973{
9974 if (ptr) {
9975 chunk_destroy(ptr);
9976 free(ptr);
9977 }
9978}
9979
9980#endif
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +01009981static void ssl_sock_capture_free_func(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, long argl, void *argp)
9982{
Willy Tarreaubafbe012017-11-24 17:34:44 +01009983 pool_free(pool_head_ssl_capture, ptr);
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +01009984}
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01009985
Emeric Brun46591952012-05-18 15:47:34 +02009986__attribute__((constructor))
Willy Tarreau92faadf2012-10-10 23:04:25 +02009987static void __ssl_sock_init(void)
9988{
Ilya Shipitsin0590f442019-05-25 19:30:50 +05009989#if (!defined(OPENSSL_NO_COMP) && !defined(SSL_OP_NO_COMPRESSION))
Emeric Brun46591952012-05-18 15:47:34 +02009990 STACK_OF(SSL_COMP)* cm;
Ilya Shipitsine242f3d2019-05-25 03:38:14 +05009991 int n;
Ilya Shipitsin0590f442019-05-25 19:30:50 +05009992#endif
Emeric Brun46591952012-05-18 15:47:34 +02009993
Willy Tarreauef934602016-12-22 23:12:01 +01009994 if (global_ssl.listen_default_ciphers)
9995 global_ssl.listen_default_ciphers = strdup(global_ssl.listen_default_ciphers);
9996 if (global_ssl.connect_default_ciphers)
9997 global_ssl.connect_default_ciphers = strdup(global_ssl.connect_default_ciphers);
Emmanuel Hocdet839af572019-05-14 16:27:35 +02009998#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009999 if (global_ssl.listen_default_ciphersuites)
10000 global_ssl.listen_default_ciphersuites = strdup(global_ssl.listen_default_ciphersuites);
10001 if (global_ssl.connect_default_ciphersuites)
10002 global_ssl.connect_default_ciphersuites = strdup(global_ssl.connect_default_ciphersuites);
10003#endif
Willy Tarreau610f04b2014-02-13 11:36:41 +010010004
Willy Tarreau13e14102016-12-22 20:25:26 +010010005 xprt_register(XPRT_SSL, &ssl_sock);
Willy Tarreau9a1ab082019-05-09 13:26:41 +020010006#if HA_OPENSSL_VERSION_NUMBER < 0x10100000L
Emeric Brun46591952012-05-18 15:47:34 +020010007 SSL_library_init();
Rosen Penev68185952018-12-14 08:47:02 -080010008#endif
Ilya Shipitsin0590f442019-05-25 19:30:50 +050010009#if (!defined(OPENSSL_NO_COMP) && !defined(SSL_OP_NO_COMPRESSION))
Emeric Brun46591952012-05-18 15:47:34 +020010010 cm = SSL_COMP_get_compression_methods();
Ilya Shipitsine242f3d2019-05-25 03:38:14 +050010011 n = sk_SSL_COMP_num(cm);
10012 while (n--) {
10013 (void) sk_SSL_COMP_pop(cm);
10014 }
Ilya Shipitsin0590f442019-05-25 19:30:50 +050010015#endif
Ilya Shipitsine242f3d2019-05-25 03:38:14 +050010016
Willy Tarreau5db847a2019-05-09 14:13:35 +020010017#if defined(USE_THREAD) && (HA_OPENSSL_VERSION_NUMBER < 0x10100000L)
Emeric Brun821bb9b2017-06-15 16:37:39 +020010018 ssl_locking_init();
10019#endif
Willy Tarreau5db847a2019-05-09 14:13:35 +020010020#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +010010021 sctl_ex_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, ssl_sock_sctl_free_func);
10022#endif
Thierry FOURNIER28962c92018-06-17 21:37:05 +020010023 ssl_app_data_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL);
Thierry FOURNIER16ff0502018-06-17 21:33:01 +020010024 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 +010010025 ssl_pkey_info_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, NULL);
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020010026#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +000010027 ENGINE_load_builtin_engines();
Grant Zhangfa6c7ee2017-01-14 01:42:15 +000010028 hap_register_post_check(ssl_check_async_engine_count);
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020010029#endif
Willy Tarreaud1c57502016-12-22 22:46:15 +010010030#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
10031 hap_register_post_check(tlskeys_finalize_config);
10032#endif
Willy Tarreau80713382018-11-26 10:19:54 +010010033
10034 global.ssl_session_max_cost = SSL_SESSION_MAX_COST;
10035 global.ssl_handshake_max_cost = SSL_HANDSHAKE_MAX_COST;
10036
10037#ifndef OPENSSL_NO_DH
10038 ssl_dh_ptr_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, NULL);
10039 hap_register_post_deinit(ssl_free_dh);
10040#endif
10041#ifndef OPENSSL_NO_ENGINE
10042 hap_register_post_deinit(ssl_free_engines);
10043#endif
10044 /* Load SSL string for the verbose & debug mode. */
10045 ERR_load_SSL_strings();
Olivier Houcharda8955d52019-04-07 22:00:38 +020010046 ha_meth = BIO_meth_new(0x666, "ha methods");
10047 BIO_meth_set_write(ha_meth, ha_ssl_write);
10048 BIO_meth_set_read(ha_meth, ha_ssl_read);
10049 BIO_meth_set_ctrl(ha_meth, ha_ssl_ctrl);
10050 BIO_meth_set_create(ha_meth, ha_ssl_new);
10051 BIO_meth_set_destroy(ha_meth, ha_ssl_free);
10052 BIO_meth_set_puts(ha_meth, ha_ssl_puts);
10053 BIO_meth_set_gets(ha_meth, ha_ssl_gets);
Willy Tarreau80713382018-11-26 10:19:54 +010010054}
Willy Tarreaud92aa5c2015-01-15 21:34:39 +010010055
Willy Tarreau80713382018-11-26 10:19:54 +010010056/* Compute and register the version string */
10057static void ssl_register_build_options()
10058{
10059 char *ptr = NULL;
10060 int i;
10061
Willy Tarreauc2c0b612016-12-21 19:23:20 +010010062 memprintf(&ptr, "Built with OpenSSL version : "
10063#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet50e25e12017-03-24 15:20:03 +010010064 "BoringSSL");
Willy Tarreauc2c0b612016-12-21 19:23:20 +010010065#else /* OPENSSL_IS_BORINGSSL */
10066 OPENSSL_VERSION_TEXT
10067 "\nRunning on OpenSSL version : %s%s",
Rosen Penev68185952018-12-14 08:47:02 -080010068 OpenSSL_version(OPENSSL_VERSION),
Willy Tarreau1d158ab2019-05-09 13:41:45 +020010069 ((OPENSSL_VERSION_NUMBER ^ OpenSSL_version_num()) >> 8) ? " (VERSIONS DIFFER!)" : "");
Willy Tarreauc2c0b612016-12-21 19:23:20 +010010070#endif
10071 memprintf(&ptr, "%s\nOpenSSL library supports TLS extensions : "
Willy Tarreau9a1ab082019-05-09 13:26:41 +020010072#if HA_OPENSSL_VERSION_NUMBER < 0x00907000L
Willy Tarreauc2c0b612016-12-21 19:23:20 +010010073 "no (library version too old)"
10074#elif defined(OPENSSL_NO_TLSEXT)
10075 "no (disabled via OPENSSL_NO_TLSEXT)"
10076#else
10077 "yes"
10078#endif
10079 "", ptr);
10080
10081 memprintf(&ptr, "%s\nOpenSSL library supports SNI : "
10082#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
10083 "yes"
10084#else
10085#ifdef OPENSSL_NO_TLSEXT
10086 "no (because of OPENSSL_NO_TLSEXT)"
10087#else
10088 "no (version might be too old, 0.9.8f min needed)"
10089#endif
10090#endif
10091 "", ptr);
10092
Emmanuel Hocdetf80bc242017-07-12 14:25:38 +020010093 memprintf(&ptr, "%s\nOpenSSL library supports :", ptr);
10094 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
10095 if (methodVersions[i].option)
10096 memprintf(&ptr, "%s %s", ptr, methodVersions[i].name);
Emmanuel Hocdet50e25e12017-03-24 15:20:03 +010010097
Willy Tarreauc2c0b612016-12-21 19:23:20 +010010098 hap_register_build_opts(ptr, 1);
Willy Tarreau80713382018-11-26 10:19:54 +010010099}
Willy Tarreauc2c0b612016-12-21 19:23:20 +010010100
Willy Tarreau80713382018-11-26 10:19:54 +010010101INITCALL0(STG_REGISTER, ssl_register_build_options);
Remi Gacogne4f902b82015-05-28 16:23:00 +020010102
Emeric Brun46591952012-05-18 15:47:34 +020010103
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020010104#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +000010105void ssl_free_engines(void) {
10106 struct ssl_engine_list *wl, *wlb;
10107 /* free up engine list */
10108 list_for_each_entry_safe(wl, wlb, &openssl_engines, list) {
10109 ENGINE_finish(wl->e);
10110 ENGINE_free(wl->e);
10111 LIST_DEL(&wl->list);
10112 free(wl);
10113 }
10114}
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020010115#endif
Christopher Faulet31af49d2015-06-09 17:29:50 +020010116
Remi Gacogned3a23c32015-05-28 16:39:47 +020010117#ifndef OPENSSL_NO_DH
Grant Zhang872f9c22017-01-21 01:10:18 +000010118void ssl_free_dh(void) {
10119 if (local_dh_1024) {
10120 DH_free(local_dh_1024);
10121 local_dh_1024 = NULL;
10122 }
10123 if (local_dh_2048) {
10124 DH_free(local_dh_2048);
10125 local_dh_2048 = NULL;
10126 }
10127 if (local_dh_4096) {
10128 DH_free(local_dh_4096);
10129 local_dh_4096 = NULL;
10130 }
Remi Gacogne47783ef2015-05-29 15:53:22 +020010131 if (global_dh) {
10132 DH_free(global_dh);
10133 global_dh = NULL;
10134 }
Grant Zhang872f9c22017-01-21 01:10:18 +000010135}
10136#endif
10137
10138__attribute__((destructor))
10139static void __ssl_sock_deinit(void)
10140{
10141#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Emeric Brun821bb9b2017-06-15 16:37:39 +020010142 if (ssl_ctx_lru_tree) {
10143 lru64_destroy(ssl_ctx_lru_tree);
Christopher Faulet2a944ee2017-11-07 10:42:54 +010010144 HA_RWLOCK_DESTROY(&ssl_ctx_lru_rwlock);
Emeric Brun821bb9b2017-06-15 16:37:39 +020010145 }
Remi Gacogned3a23c32015-05-28 16:39:47 +020010146#endif
10147
Willy Tarreau5db847a2019-05-09 14:13:35 +020010148#if (HA_OPENSSL_VERSION_NUMBER < 0x10100000L)
Remi Gacogned3a23c32015-05-28 16:39:47 +020010149 ERR_remove_state(0);
10150 ERR_free_strings();
10151
10152 EVP_cleanup();
Rosen Penev68185952018-12-14 08:47:02 -080010153#endif
Remi Gacogned3a23c32015-05-28 16:39:47 +020010154
Willy Tarreau5db847a2019-05-09 14:13:35 +020010155#if (HA_OPENSSL_VERSION_NUMBER >= 0x00907000L) && (HA_OPENSSL_VERSION_NUMBER < 0x10100000L)
Remi Gacogned3a23c32015-05-28 16:39:47 +020010156 CRYPTO_cleanup_all_ex_data();
10157#endif
Olivier Houcharda8955d52019-04-07 22:00:38 +020010158 BIO_meth_free(ha_meth);
Remi Gacogned3a23c32015-05-28 16:39:47 +020010159}
10160
10161
Emeric Brun46591952012-05-18 15:47:34 +020010162/*
10163 * Local variables:
10164 * c-indent-level: 8
10165 * c-basic-offset: 8
10166 * End:
10167 */