blob: 62b9de95c399914b630caeff01eefd452199f84f [file] [log] [blame]
yanbzhu08ce6ab2015-12-02 13:01:29 -05001
Emeric Brun46591952012-05-18 15:47:34 +02002/*
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02003 * SSL/TLS transport layer over SOCK_STREAM sockets
Emeric Brun46591952012-05-18 15:47:34 +02004 *
5 * Copyright (C) 2012 EXCELIANCE, Emeric Brun <ebrun@exceliance.fr>
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version
10 * 2 of the License, or (at your option) any later version.
11 *
Willy Tarreau69845df2012-09-10 09:43:09 +020012 * Acknowledgement:
13 * We'd like to specially thank the Stud project authors for a very clean
14 * and well documented code which helped us understand how the OpenSSL API
15 * ought to be used in non-blocking mode. This is one difficult part which
16 * is not easy to get from the OpenSSL doc, and reading the Stud code made
17 * it much more obvious than the examples in the OpenSSL package. Keep up
18 * the good works, guys !
19 *
20 * Stud is an extremely efficient and scalable SSL/TLS proxy which combines
21 * particularly well with haproxy. For more info about this project, visit :
22 * https://github.com/bumptech/stud
23 *
Emeric Brun46591952012-05-18 15:47:34 +020024 */
25
Willy Tarreau8d164dc2019-05-10 09:35:00 +020026/* Note: do NOT include openssl/xxx.h here, do it in openssl-compat.h */
Emeric Brun46591952012-05-18 15:47:34 +020027#define _GNU_SOURCE
Emeric Brunfc0421f2012-09-07 17:30:07 +020028#include <ctype.h>
29#include <dirent.h>
Emeric Brun46591952012-05-18 15:47:34 +020030#include <errno.h>
31#include <fcntl.h>
32#include <stdio.h>
33#include <stdlib.h>
Emeric Brunfc0421f2012-09-07 17:30:07 +020034#include <string.h>
35#include <unistd.h>
Emeric Brun46591952012-05-18 15:47:34 +020036
37#include <sys/socket.h>
38#include <sys/stat.h>
39#include <sys/types.h>
Christopher Faulet31af49d2015-06-09 17:29:50 +020040#include <netdb.h>
Emeric Brun46591952012-05-18 15:47:34 +020041#include <netinet/tcp.h>
42
Christopher Faulet31af49d2015-06-09 17:29:50 +020043#include <import/lru.h>
44#include <import/xxhash.h>
45
Emeric Brun46591952012-05-18 15:47:34 +020046#include <common/buffer.h>
Willy Tarreau843b7cb2018-07-13 10:54:26 +020047#include <common/chunk.h>
Emeric Brun46591952012-05-18 15:47:34 +020048#include <common/compat.h>
49#include <common/config.h>
50#include <common/debug.h>
Willy Tarreau79eeafa2012-09-14 07:53:05 +020051#include <common/errors.h>
Willy Tarreau0108d902018-11-25 19:14:37 +010052#include <common/initcall.h>
Willy Tarreau55994562019-05-09 14:52:44 +020053#include <common/openssl-compat.h>
Emeric Brun46591952012-05-18 15:47:34 +020054#include <common/standard.h>
55#include <common/ticks.h>
56#include <common/time.h>
Emeric Brun2c86cbf2014-10-30 15:56:50 +010057#include <common/cfgparse.h>
Nenad Merdanovic05552d42015-02-27 19:56:49 +010058#include <common/base64.h>
Emeric Brun46591952012-05-18 15:47:34 +020059
Emeric Brunfc0421f2012-09-07 17:30:07 +020060#include <ebsttree.h>
61
William Lallemand32af2032016-10-29 18:09:35 +020062#include <types/applet.h>
63#include <types/cli.h>
Emeric Brunfc0421f2012-09-07 17:30:07 +020064#include <types/global.h>
65#include <types/ssl_sock.h>
William Lallemand32af2032016-10-29 18:09:35 +020066#include <types/stats.h>
Emeric Brunfc0421f2012-09-07 17:30:07 +020067
Willy Tarreau7875d092012-09-10 08:20:03 +020068#include <proto/acl.h>
69#include <proto/arg.h>
William Lallemand32af2032016-10-29 18:09:35 +020070#include <proto/channel.h>
Emeric Brun46591952012-05-18 15:47:34 +020071#include <proto/connection.h>
William Lallemand32af2032016-10-29 18:09:35 +020072#include <proto/cli.h>
Emeric Brun46591952012-05-18 15:47:34 +020073#include <proto/fd.h>
74#include <proto/freq_ctr.h>
75#include <proto/frontend.h>
Willy Tarreau61c112a2018-10-02 16:43:32 +020076#include <proto/http_rules.h>
Willy Tarreau79eeafa2012-09-14 07:53:05 +020077#include <proto/listener.h>
Thierry FOURNIERed66c292013-11-28 11:05:19 +010078#include <proto/pattern.h>
Christopher Faulet31af49d2015-06-09 17:29:50 +020079#include <proto/proto_tcp.h>
Christopher Fauletfc9cfe42019-07-16 14:54:53 +020080#include <proto/http_ana.h>
Willy Tarreau92faadf2012-10-10 23:04:25 +020081#include <proto/server.h>
William Lallemand32af2032016-10-29 18:09:35 +020082#include <proto/stream_interface.h>
Emeric Brun46591952012-05-18 15:47:34 +020083#include <proto/log.h>
Emeric Brun94324a42012-10-11 14:00:19 +020084#include <proto/proxy.h>
Emeric Brunfc0421f2012-09-07 17:30:07 +020085#include <proto/shctx.h>
Emeric Brun46591952012-05-18 15:47:34 +020086#include <proto/ssl_sock.h>
Willy Tarreau9ad7bd42015-04-03 19:19:59 +020087#include <proto/stream.h>
Emeric Brun46591952012-05-18 15:47:34 +020088#include <proto/task.h>
Nenad Merdanovicc31499d2019-03-23 11:00:32 +010089#include <proto/vars.h>
Emeric Brun46591952012-05-18 15:47:34 +020090
Willy Tarreau9356dac2019-05-10 09:22:53 +020091/* ***** READ THIS before adding code here! *****
92 *
93 * Due to API incompatibilities between multiple OpenSSL versions and their
94 * derivatives, it's often tempting to add macros to (re-)define certain
95 * symbols. Please do not do this here, and do it in common/openssl-compat.h
96 * exclusively so that the whole code consistently uses the same macros.
97 *
98 * Whenever possible if a macro is missing in certain versions, it's better
99 * to conditionally define it in openssl-compat.h than using lots of ifdefs.
100 */
101
Willy Tarreau518cedd2014-02-17 15:43:01 +0100102/* Warning, these are bits, not integers! */
Emeric Brune64aef12012-09-21 13:15:06 +0200103#define SSL_SOCK_ST_FL_VERIFY_DONE 0x00000001
Emeric Brund8b2bb52014-01-28 15:43:53 +0100104#define SSL_SOCK_ST_FL_16K_WBFSIZE 0x00000002
Willy Tarreau518cedd2014-02-17 15:43:01 +0100105#define SSL_SOCK_SEND_UNLIMITED 0x00000004
Emeric Brun29f037d2014-04-25 19:05:36 +0200106#define SSL_SOCK_RECV_HEARTBEAT 0x00000008
107
Emeric Brunf282a812012-09-21 15:27:54 +0200108/* bits 0xFFFF0000 are reserved to store verify errors */
109
110/* Verify errors macros */
111#define SSL_SOCK_CA_ERROR_TO_ST(e) (((e > 63) ? 63 : e) << (16))
112#define SSL_SOCK_CAEDEPTH_TO_ST(d) (((d > 15) ? 15 : d) << (6+16))
113#define SSL_SOCK_CRTERROR_TO_ST(e) (((e > 63) ? 63 : e) << (4+6+16))
114
115#define SSL_SOCK_ST_TO_CA_ERROR(s) ((s >> (16)) & 63)
116#define SSL_SOCK_ST_TO_CAEDEPTH(s) ((s >> (6+16)) & 15)
117#define SSL_SOCK_ST_TO_CRTERROR(s) ((s >> (4+6+16)) & 63)
Emeric Brune64aef12012-09-21 13:15:06 +0200118
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200119/* ssl_methods flags for ssl options */
120#define MC_SSL_O_ALL 0x0000
121#define MC_SSL_O_NO_SSLV3 0x0001 /* disable SSLv3 */
122#define MC_SSL_O_NO_TLSV10 0x0002 /* disable TLSv10 */
123#define MC_SSL_O_NO_TLSV11 0x0004 /* disable TLSv11 */
124#define MC_SSL_O_NO_TLSV12 0x0008 /* disable TLSv12 */
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +0200125#define MC_SSL_O_NO_TLSV13 0x0010 /* disable TLSv13 */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200126
127/* ssl_methods versions */
128enum {
129 CONF_TLSV_NONE = 0,
130 CONF_TLSV_MIN = 1,
131 CONF_SSLV3 = 1,
132 CONF_TLSV10 = 2,
133 CONF_TLSV11 = 3,
134 CONF_TLSV12 = 4,
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +0200135 CONF_TLSV13 = 5,
136 CONF_TLSV_MAX = 5,
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200137};
138
Emeric Brun850efd52014-01-29 12:24:34 +0100139/* server and bind verify method, it uses a global value as default */
140enum {
141 SSL_SOCK_VERIFY_DEFAULT = 0,
142 SSL_SOCK_VERIFY_REQUIRED = 1,
143 SSL_SOCK_VERIFY_OPTIONAL = 2,
144 SSL_SOCK_VERIFY_NONE = 3,
145};
146
William Lallemand3f85c9a2017-10-09 16:30:50 +0200147
Willy Tarreau71b734c2014-01-28 15:19:44 +0100148int sslconns = 0;
149int totalsslconns = 0;
Willy Tarreaud9f5cca2016-12-22 21:08:52 +0100150static struct xprt_ops ssl_sock;
Emeric Brunece0c332017-12-06 13:51:49 +0100151int nb_engines = 0;
Emeric Brune1f38db2012-09-03 20:36:47 +0200152
Willy Tarreauef934602016-12-22 23:12:01 +0100153static struct {
154 char *crt_base; /* base directory path for certificates */
155 char *ca_base; /* base directory path for CAs and CRLs */
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000156 int async; /* whether we use ssl async mode */
Willy Tarreauef934602016-12-22 23:12:01 +0100157
158 char *listen_default_ciphers;
159 char *connect_default_ciphers;
Emmanuel Hocdet839af572019-05-14 16:27:35 +0200160#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +0200161 char *listen_default_ciphersuites;
162 char *connect_default_ciphersuites;
163#endif
Willy Tarreauef934602016-12-22 23:12:01 +0100164 int listen_default_ssloptions;
165 int connect_default_ssloptions;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200166 struct tls_version_filter listen_default_sslmethods;
167 struct tls_version_filter connect_default_sslmethods;
Willy Tarreauef934602016-12-22 23:12:01 +0100168
169 int private_cache; /* Force to use a private session cache even if nbproc > 1 */
170 unsigned int life_time; /* SSL session lifetime in seconds */
171 unsigned int max_record; /* SSL max record size */
172 unsigned int default_dh_param; /* SSL maximum DH parameter size */
173 int ctx_cache; /* max number of entries in the ssl_ctx cache. */
Thierry FOURNIER5bf77322017-02-25 12:45:22 +0100174 int capture_cipherlist; /* Size of the cipherlist buffer. */
Willy Tarreauef934602016-12-22 23:12:01 +0100175} global_ssl = {
176#ifdef LISTEN_DEFAULT_CIPHERS
177 .listen_default_ciphers = LISTEN_DEFAULT_CIPHERS,
178#endif
179#ifdef CONNECT_DEFAULT_CIPHERS
180 .connect_default_ciphers = CONNECT_DEFAULT_CIPHERS,
181#endif
Emmanuel Hocdet839af572019-05-14 16:27:35 +0200182#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +0200183#ifdef LISTEN_DEFAULT_CIPHERSUITES
184 .listen_default_ciphersuites = LISTEN_DEFAULT_CIPHERSUITES,
185#endif
186#ifdef CONNECT_DEFAULT_CIPHERSUITES
187 .connect_default_ciphersuites = CONNECT_DEFAULT_CIPHERSUITES,
188#endif
189#endif
Willy Tarreauef934602016-12-22 23:12:01 +0100190 .listen_default_ssloptions = BC_SSL_O_NONE,
191 .connect_default_ssloptions = SRV_SSL_O_NONE,
192
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200193 .listen_default_sslmethods.flags = MC_SSL_O_ALL,
194 .listen_default_sslmethods.min = CONF_TLSV_NONE,
195 .listen_default_sslmethods.max = CONF_TLSV_NONE,
196 .connect_default_sslmethods.flags = MC_SSL_O_ALL,
197 .connect_default_sslmethods.min = CONF_TLSV_NONE,
198 .connect_default_sslmethods.max = CONF_TLSV_NONE,
199
Willy Tarreauef934602016-12-22 23:12:01 +0100200#ifdef DEFAULT_SSL_MAX_RECORD
201 .max_record = DEFAULT_SSL_MAX_RECORD,
202#endif
203 .default_dh_param = SSL_DEFAULT_DH_PARAM,
204 .ctx_cache = DEFAULT_SSL_CTX_CACHE,
Thierry FOURNIER5bf77322017-02-25 12:45:22 +0100205 .capture_cipherlist = 0,
Willy Tarreauef934602016-12-22 23:12:01 +0100206};
207
Olivier Houcharda8955d52019-04-07 22:00:38 +0200208static BIO_METHOD *ha_meth;
209
Olivier Houchard66ab4982019-02-26 18:37:15 +0100210struct ssl_sock_ctx {
Olivier Houcharda8955d52019-04-07 22:00:38 +0200211 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +0100212 SSL *ssl;
Olivier Houcharda8955d52019-04-07 22:00:38 +0200213 BIO *bio;
Olivier Houchard5149b592019-05-23 17:47:36 +0200214 const struct xprt_ops *xprt;
Olivier Houchard66ab4982019-02-26 18:37:15 +0100215 void *xprt_ctx;
Olivier Houchardea8dd942019-05-20 14:02:16 +0200216 struct wait_event wait_event;
217 struct wait_event *recv_wait;
218 struct wait_event *send_wait;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +0100219 int xprt_st; /* transport layer state, initialized to zero */
220 int tmp_early_data; /* 1st byte of early data, if any */
221 int sent_early_data; /* Amount of early data we sent so far */
222
Olivier Houchard66ab4982019-02-26 18:37:15 +0100223};
224
225DECLARE_STATIC_POOL(ssl_sock_ctx_pool, "ssl_sock_ctx_pool", sizeof(struct ssl_sock_ctx));
226
Olivier Houchardea8dd942019-05-20 14:02:16 +0200227static struct task *ssl_sock_io_cb(struct task *, void *, unsigned short);
Olivier Houchard000694c2019-05-23 14:45:12 +0200228static int ssl_sock_handshake(struct connection *conn, unsigned int flag);
Olivier Houchardea8dd942019-05-20 14:02:16 +0200229
Olivier Houcharda8955d52019-04-07 22:00:38 +0200230/* Methods to implement OpenSSL BIO */
231static int ha_ssl_write(BIO *h, const char *buf, int num)
232{
233 struct buffer tmpbuf;
234 struct ssl_sock_ctx *ctx;
235 int ret;
236
237 ctx = BIO_get_data(h);
238 tmpbuf.size = num;
239 tmpbuf.area = (void *)(uintptr_t)buf;
240 tmpbuf.data = num;
241 tmpbuf.head = 0;
242 ret = ctx->xprt->snd_buf(ctx->conn, ctx->xprt_ctx, &tmpbuf, num, 0);
Olivier Houchardb51937e2019-05-01 17:24:36 +0200243 if (ret == 0 && !(ctx->conn->flags & (CO_FL_ERROR | CO_FL_SOCK_WR_SH))) {
Olivier Houcharda8955d52019-04-07 22:00:38 +0200244 BIO_set_retry_write(h);
Olivier Houcharda28454e2019-04-24 12:04:36 +0200245 ret = -1;
Olivier Houchardb51937e2019-05-01 17:24:36 +0200246 } else if (ret == 0)
247 BIO_clear_retry_flags(h);
Olivier Houcharda8955d52019-04-07 22:00:38 +0200248 return ret;
249}
250
251static int ha_ssl_gets(BIO *h, char *buf, int size)
252{
253
254 return 0;
255}
256
257static int ha_ssl_puts(BIO *h, const char *str)
258{
259
260 return ha_ssl_write(h, str, strlen(str));
261}
262
263static int ha_ssl_read(BIO *h, char *buf, int size)
264{
265 struct buffer tmpbuf;
266 struct ssl_sock_ctx *ctx;
267 int ret;
268
269 ctx = BIO_get_data(h);
270 tmpbuf.size = size;
271 tmpbuf.area = buf;
272 tmpbuf.data = 0;
273 tmpbuf.head = 0;
274 ret = ctx->xprt->rcv_buf(ctx->conn, ctx->xprt_ctx, &tmpbuf, size, 0);
Olivier Houchardb51937e2019-05-01 17:24:36 +0200275 if (ret == 0 && !(ctx->conn->flags & (CO_FL_ERROR | CO_FL_SOCK_RD_SH))) {
Olivier Houcharda8955d52019-04-07 22:00:38 +0200276 BIO_set_retry_read(h);
Olivier Houcharda28454e2019-04-24 12:04:36 +0200277 ret = -1;
Olivier Houchardb51937e2019-05-01 17:24:36 +0200278 } else if (ret == 0)
279 BIO_clear_retry_flags(h);
Olivier Houcharda8955d52019-04-07 22:00:38 +0200280
281 return ret;
282}
283
284static long ha_ssl_ctrl(BIO *h, int cmd, long arg1, void *arg2)
285{
286 int ret = 0;
287 switch (cmd) {
288 case BIO_CTRL_DUP:
289 case BIO_CTRL_FLUSH:
290 ret = 1;
291 break;
292 }
293 return ret;
294}
295
296static int ha_ssl_new(BIO *h)
297{
298 BIO_set_init(h, 1);
299 BIO_set_data(h, NULL);
300 BIO_clear_flags(h, ~0);
301 return 1;
302}
303
304static int ha_ssl_free(BIO *data)
305{
306
307 return 1;
308}
309
310
Willy Tarreau5db847a2019-05-09 14:13:35 +0200311#if defined(USE_THREAD) && (HA_OPENSSL_VERSION_NUMBER < 0x10100000L)
Christopher Faulet9dcf9b62017-11-13 10:34:01 +0100312
Emeric Brun821bb9b2017-06-15 16:37:39 +0200313static HA_RWLOCK_T *ssl_rwlocks;
314
315
316unsigned long ssl_id_function(void)
317{
318 return (unsigned long)tid;
319}
320
321void ssl_locking_function(int mode, int n, const char * file, int line)
322{
323 if (mode & CRYPTO_LOCK) {
324 if (mode & CRYPTO_READ)
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100325 HA_RWLOCK_RDLOCK(SSL_LOCK, &ssl_rwlocks[n]);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200326 else
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100327 HA_RWLOCK_WRLOCK(SSL_LOCK, &ssl_rwlocks[n]);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200328 }
329 else {
330 if (mode & CRYPTO_READ)
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100331 HA_RWLOCK_RDUNLOCK(SSL_LOCK, &ssl_rwlocks[n]);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200332 else
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100333 HA_RWLOCK_WRUNLOCK(SSL_LOCK, &ssl_rwlocks[n]);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200334 }
335}
336
337static int ssl_locking_init(void)
338{
339 int i;
340
341 ssl_rwlocks = malloc(sizeof(HA_RWLOCK_T)*CRYPTO_num_locks());
342 if (!ssl_rwlocks)
343 return -1;
344
345 for (i = 0 ; i < CRYPTO_num_locks() ; i++)
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100346 HA_RWLOCK_INIT(&ssl_rwlocks[i]);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200347
348 CRYPTO_set_id_callback(ssl_id_function);
349 CRYPTO_set_locking_callback(ssl_locking_function);
350
351 return 0;
352}
Christopher Faulet9dcf9b62017-11-13 10:34:01 +0100353
Emeric Brun821bb9b2017-06-15 16:37:39 +0200354#endif
355
William Lallemand150bfa82019-09-19 17:12:49 +0200356__decl_hathreads(HA_SPINLOCK_T ckch_lock);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200357
William Lallemandbc6ca7c2019-10-29 23:48:19 +0100358/* Uncommitted CKCH transaction */
359
360static struct {
361 struct ckch_store *new_ckchs;
362 struct ckch_store *old_ckchs;
363 char *path;
364} ckchs_transaction;
365
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +0100366/* This memory pool is used for capturing clienthello parameters. */
Thierry FOURNIER5bf77322017-02-25 12:45:22 +0100367struct ssl_capture {
Thierry FOURNIER5bf77322017-02-25 12:45:22 +0100368 unsigned long long int xxh64;
369 unsigned char ciphersuite_len;
370 char ciphersuite[0];
371};
Willy Tarreaubafbe012017-11-24 17:34:44 +0100372struct pool_head *pool_head_ssl_capture = NULL;
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +0100373static int ssl_capture_ptr_index = -1;
Thierry FOURNIER28962c92018-06-17 21:37:05 +0200374static int ssl_app_data_index = -1;
Willy Tarreauef934602016-12-22 23:12:01 +0100375
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200376#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
377struct list tlskeys_reference = LIST_HEAD_INIT(tlskeys_reference);
378#endif
379
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +0200380#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +0000381static unsigned int openssl_engines_initialized;
382struct list openssl_engines = LIST_HEAD_INIT(openssl_engines);
383struct ssl_engine_list {
384 struct list list;
385 ENGINE *e;
386};
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +0200387#endif
Grant Zhang872f9c22017-01-21 01:10:18 +0000388
Remi Gacogne8de54152014-07-15 11:36:40 +0200389#ifndef OPENSSL_NO_DH
Remi Gacogne4f902b82015-05-28 16:23:00 +0200390static int ssl_dh_ptr_index = -1;
Remi Gacogne47783ef2015-05-29 15:53:22 +0200391static DH *global_dh = NULL;
Remi Gacogne8de54152014-07-15 11:36:40 +0200392static DH *local_dh_1024 = NULL;
393static DH *local_dh_2048 = NULL;
394static DH *local_dh_4096 = NULL;
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +0100395static DH *ssl_get_tmp_dh(SSL *ssl, int export, int keylen);
Remi Gacogne8de54152014-07-15 11:36:40 +0200396#endif /* OPENSSL_NO_DH */
397
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100398#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Christopher Faulet31af49d2015-06-09 17:29:50 +0200399/* X509V3 Extensions that will be added on generated certificates */
400#define X509V3_EXT_SIZE 5
401static char *x509v3_ext_names[X509V3_EXT_SIZE] = {
402 "basicConstraints",
403 "nsComment",
404 "subjectKeyIdentifier",
405 "authorityKeyIdentifier",
406 "keyUsage",
407};
408static char *x509v3_ext_values[X509V3_EXT_SIZE] = {
409 "CA:FALSE",
410 "\"OpenSSL Generated Certificate\"",
411 "hash",
412 "keyid,issuer:always",
413 "nonRepudiation,digitalSignature,keyEncipherment"
414};
Christopher Faulet31af49d2015-06-09 17:29:50 +0200415/* LRU cache to store generated certificate */
416static struct lru64_head *ssl_ctx_lru_tree = NULL;
417static unsigned int ssl_ctx_lru_seed = 0;
Emeric Brun821bb9b2017-06-15 16:37:39 +0200418static unsigned int ssl_ctx_serial;
Willy Tarreau86abe442018-11-25 20:12:18 +0100419__decl_rwlock(ssl_ctx_lru_rwlock);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200420
Willy Tarreauc8ad3be2015-06-17 15:48:26 +0200421#endif // SSL_CTRL_SET_TLSEXT_HOSTNAME
422
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100423static struct ssl_bind_kw ssl_bind_kws[];
424
Willy Tarreau9a1ab082019-05-09 13:26:41 +0200425#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
yanbzhube2774d2015-12-10 15:07:30 -0500426/* The order here matters for picking a default context,
427 * keep the most common keytype at the bottom of the list
428 */
429const char *SSL_SOCK_KEYTYPE_NAMES[] = {
430 "dsa",
431 "ecdsa",
432 "rsa"
433};
434#define SSL_SOCK_NUM_KEYTYPES 3
Willy Tarreau30da7ad2015-12-14 11:28:33 +0100435#else
436#define SSL_SOCK_NUM_KEYTYPES 1
yanbzhube2774d2015-12-10 15:07:30 -0500437#endif
438
William Lallemandc3cd35f2017-11-28 11:04:43 +0100439static struct shared_context *ssl_shctx = NULL; /* ssl shared session cache */
William Lallemand4f45bb92017-10-30 20:08:51 +0100440static struct eb_root *sh_ssl_sess_tree; /* ssl shared session tree */
441
442#define sh_ssl_sess_tree_delete(s) ebmb_delete(&(s)->key);
443
444#define sh_ssl_sess_tree_insert(s) (struct sh_ssl_sess_hdr *)ebmb_insert(sh_ssl_sess_tree, \
445 &(s)->key, SSL_MAX_SSL_SESSION_ID_LENGTH);
446
447#define sh_ssl_sess_tree_lookup(k) (struct sh_ssl_sess_hdr *)ebmb_lookup(sh_ssl_sess_tree, \
448 (k), SSL_MAX_SSL_SESSION_ID_LENGTH);
William Lallemand3f85c9a2017-10-09 16:30:50 +0200449
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100450/*
451 * This function gives the detail of the SSL error. It is used only
452 * if the debug mode and the verbose mode are activated. It dump all
453 * the SSL error until the stack was empty.
454 */
455static forceinline void ssl_sock_dump_errors(struct connection *conn)
456{
457 unsigned long ret;
458
459 if (unlikely(global.mode & MODE_DEBUG)) {
460 while(1) {
461 ret = ERR_get_error();
462 if (ret == 0)
463 return;
464 fprintf(stderr, "fd[%04x] OpenSSL error[0x%lx] %s: %s\n",
Willy Tarreau585744b2017-08-24 14:31:19 +0200465 (unsigned short)conn->handle.fd, ret,
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100466 ERR_func_error_string(ret), ERR_reason_error_string(ret));
467 }
468 }
469}
470
yanbzhube2774d2015-12-10 15:07:30 -0500471
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +0200472#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +0000473static int ssl_init_single_engine(const char *engine_id, const char *def_algorithms)
474{
475 int err_code = ERR_ABORT;
476 ENGINE *engine;
477 struct ssl_engine_list *el;
478
479 /* grab the structural reference to the engine */
480 engine = ENGINE_by_id(engine_id);
481 if (engine == NULL) {
Christopher Faulet767a84b2017-11-24 16:50:31 +0100482 ha_alert("ssl-engine %s: failed to get structural reference\n", engine_id);
Grant Zhang872f9c22017-01-21 01:10:18 +0000483 goto fail_get;
484 }
485
486 if (!ENGINE_init(engine)) {
487 /* the engine couldn't initialise, release it */
Christopher Faulet767a84b2017-11-24 16:50:31 +0100488 ha_alert("ssl-engine %s: failed to initialize\n", engine_id);
Grant Zhang872f9c22017-01-21 01:10:18 +0000489 goto fail_init;
490 }
491
492 if (ENGINE_set_default_string(engine, def_algorithms) == 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +0100493 ha_alert("ssl-engine %s: failed on ENGINE_set_default_string\n", engine_id);
Grant Zhang872f9c22017-01-21 01:10:18 +0000494 goto fail_set_method;
495 }
496
497 el = calloc(1, sizeof(*el));
498 el->e = engine;
499 LIST_ADD(&openssl_engines, &el->list);
Emeric Brunece0c332017-12-06 13:51:49 +0100500 nb_engines++;
501 if (global_ssl.async)
502 global.ssl_used_async_engines = nb_engines;
Grant Zhang872f9c22017-01-21 01:10:18 +0000503 return 0;
504
505fail_set_method:
506 /* release the functional reference from ENGINE_init() */
507 ENGINE_finish(engine);
508
509fail_init:
510 /* release the structural reference from ENGINE_by_id() */
511 ENGINE_free(engine);
512
513fail_get:
514 return err_code;
515}
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +0200516#endif
Grant Zhang872f9c22017-01-21 01:10:18 +0000517
Willy Tarreau5db847a2019-05-09 14:13:35 +0200518#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brun3854e012017-05-17 20:42:48 +0200519/*
520 * openssl async fd handler
521 */
Emeric Brund0e095c2019-04-19 17:15:28 +0200522void ssl_async_fd_handler(int fd)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000523{
Olivier Houchardea8dd942019-05-20 14:02:16 +0200524 struct ssl_sock_ctx *ctx = fdtab[fd].owner;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000525
Emeric Brun3854e012017-05-17 20:42:48 +0200526 /* fd is an async enfine fd, we must stop
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000527 * to poll this fd until it is requested
528 */
Emeric Brunbbc16542017-06-02 15:54:06 +0000529 fd_stop_recv(fd);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000530 fd_cant_recv(fd);
531
532 /* crypto engine is available, let's notify the associated
533 * connection that it can pursue its processing.
534 */
Olivier Houchard03abf2d2019-05-28 10:12:02 +0200535 ssl_sock_io_cb(NULL, ctx, 0);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000536}
537
Emeric Brun3854e012017-05-17 20:42:48 +0200538/*
539 * openssl async delayed SSL_free handler
540 */
Emeric Brund0e095c2019-04-19 17:15:28 +0200541void ssl_async_fd_free(int fd)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000542{
543 SSL *ssl = fdtab[fd].owner;
Emeric Brun3854e012017-05-17 20:42:48 +0200544 OSSL_ASYNC_FD all_fd[32];
545 size_t num_all_fds = 0;
546 int i;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000547
Emeric Brun3854e012017-05-17 20:42:48 +0200548 /* We suppose that the async job for a same SSL *
549 * are serialized. So if we are awake it is
550 * because the running job has just finished
551 * and we can remove all async fds safely
552 */
553 SSL_get_all_async_fds(ssl, NULL, &num_all_fds);
554 if (num_all_fds > 32) {
555 send_log(NULL, LOG_EMERG, "haproxy: openssl returns too many async fds. It seems a bug. Process may crash\n");
556 return;
557 }
558
559 SSL_get_all_async_fds(ssl, all_fd, &num_all_fds);
560 for (i=0 ; i < num_all_fds ; i++)
561 fd_remove(all_fd[i]);
562
563 /* Now we can safely call SSL_free, no more pending job in engines */
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000564 SSL_free(ssl);
Olivier Houchard2be5a4c2019-03-08 18:54:43 +0100565 _HA_ATOMIC_SUB(&sslconns, 1);
566 _HA_ATOMIC_SUB(&jobs, 1);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000567}
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000568/*
Emeric Brun3854e012017-05-17 20:42:48 +0200569 * function used to manage a returned SSL_ERROR_WANT_ASYNC
570 * and enable/disable polling for async fds
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000571 */
Olivier Houchardea8dd942019-05-20 14:02:16 +0200572static inline void ssl_async_process_fds(struct ssl_sock_ctx *ctx)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000573{
Willy Tarreaua9786b62018-01-25 07:22:13 +0100574 OSSL_ASYNC_FD add_fd[32];
Emeric Brun3854e012017-05-17 20:42:48 +0200575 OSSL_ASYNC_FD del_fd[32];
Olivier Houchardea8dd942019-05-20 14:02:16 +0200576 SSL *ssl = ctx->ssl;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000577 size_t num_add_fds = 0;
578 size_t num_del_fds = 0;
Emeric Brun3854e012017-05-17 20:42:48 +0200579 int i;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000580
581 SSL_get_changed_async_fds(ssl, NULL, &num_add_fds, NULL,
582 &num_del_fds);
Emeric Brun3854e012017-05-17 20:42:48 +0200583 if (num_add_fds > 32 || num_del_fds > 32) {
584 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 +0000585 return;
586 }
587
Emeric Brun3854e012017-05-17 20:42:48 +0200588 SSL_get_changed_async_fds(ssl, add_fd, &num_add_fds, del_fd, &num_del_fds);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000589
Emeric Brun3854e012017-05-17 20:42:48 +0200590 /* We remove unused fds from the fdtab */
591 for (i=0 ; i < num_del_fds ; i++)
592 fd_remove(del_fd[i]);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000593
Emeric Brun3854e012017-05-17 20:42:48 +0200594 /* We add new fds to the fdtab */
595 for (i=0 ; i < num_add_fds ; i++) {
Olivier Houchardea8dd942019-05-20 14:02:16 +0200596 fd_insert(add_fd[i], ctx, ssl_async_fd_handler, tid_bit);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000597 }
598
Emeric Brun3854e012017-05-17 20:42:48 +0200599 num_add_fds = 0;
600 SSL_get_all_async_fds(ssl, NULL, &num_add_fds);
601 if (num_add_fds > 32) {
602 send_log(NULL, LOG_EMERG, "haproxy: openssl returns too many async fds. It seems a bug. Process may crash\n");
603 return;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000604 }
Emeric Brun3854e012017-05-17 20:42:48 +0200605
606 /* We activate the polling for all known async fds */
607 SSL_get_all_async_fds(ssl, add_fd, &num_add_fds);
Emeric Brunce9e01c2017-05-31 10:02:53 +0000608 for (i=0 ; i < num_add_fds ; i++) {
Emeric Brun3854e012017-05-17 20:42:48 +0200609 fd_want_recv(add_fd[i]);
Emeric Brunce9e01c2017-05-31 10:02:53 +0000610 /* To ensure that the fd cache won't be used
611 * We'll prefer to catch a real RD event
612 * because handling an EAGAIN on this fd will
613 * result in a context switch and also
614 * some engines uses a fd in blocking mode.
615 */
616 fd_cant_recv(add_fd[i]);
617 }
Emeric Brun3854e012017-05-17 20:42:48 +0200618
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000619}
620#endif
621
William Lallemand104a7a62019-10-14 14:14:59 +0200622#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
Emeric Brun4f3c87a2014-06-20 15:46:13 +0200623/*
624 * This function returns the number of seconds elapsed
625 * since the Epoch, 1970-01-01 00:00:00 +0000 (UTC) and the
626 * date presented un ASN1_GENERALIZEDTIME.
627 *
628 * In parsing error case, it returns -1.
629 */
630static long asn1_generalizedtime_to_epoch(ASN1_GENERALIZEDTIME *d)
631{
632 long epoch;
633 char *p, *end;
634 const unsigned short month_offset[12] = {
635 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
636 };
637 int year, month;
638
639 if (!d || (d->type != V_ASN1_GENERALIZEDTIME)) return -1;
640
641 p = (char *)d->data;
642 end = p + d->length;
643
644 if (end - p < 4) return -1;
645 year = 1000 * (p[0] - '0') + 100 * (p[1] - '0') + 10 * (p[2] - '0') + p[3] - '0';
646 p += 4;
647 if (end - p < 2) return -1;
648 month = 10 * (p[0] - '0') + p[1] - '0';
649 if (month < 1 || month > 12) return -1;
650 /* Compute the number of seconds since 1 jan 1970 and the beginning of current month
651 We consider leap years and the current month (<marsh or not) */
652 epoch = ( ((year - 1970) * 365)
653 + ((year - (month < 3)) / 4 - (year - (month < 3)) / 100 + (year - (month < 3)) / 400)
654 - ((1970 - 1) / 4 - (1970 - 1) / 100 + (1970 - 1) / 400)
655 + month_offset[month-1]
656 ) * 24 * 60 * 60;
657 p += 2;
658 if (end - p < 2) return -1;
659 /* Add the number of seconds of completed days of current month */
660 epoch += (10 * (p[0] - '0') + p[1] - '0' - 1) * 24 * 60 * 60;
661 p += 2;
662 if (end - p < 2) return -1;
663 /* Add the completed hours of the current day */
664 epoch += (10 * (p[0] - '0') + p[1] - '0') * 60 * 60;
665 p += 2;
666 if (end - p < 2) return -1;
667 /* Add the completed minutes of the current hour */
668 epoch += (10 * (p[0] - '0') + p[1] - '0') * 60;
669 p += 2;
670 if (p == end) return -1;
671 /* Test if there is available seconds */
672 if (p[0] < '0' || p[0] > '9')
673 goto nosec;
674 if (end - p < 2) return -1;
675 /* Add the seconds of the current minute */
676 epoch += 10 * (p[0] - '0') + p[1] - '0';
677 p += 2;
678 if (p == end) return -1;
679 /* Ignore seconds float part if present */
680 if (p[0] == '.') {
681 do {
682 if (++p == end) return -1;
683 } while (p[0] >= '0' && p[0] <= '9');
684 }
685
686nosec:
687 if (p[0] == 'Z') {
688 if (end - p != 1) return -1;
689 return epoch;
690 }
691 else if (p[0] == '+') {
692 if (end - p != 5) return -1;
693 /* Apply timezone offset */
Frederik Deweerdt953917a2017-10-16 07:37:31 -0700694 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 +0200695 }
696 else if (p[0] == '-') {
697 if (end - p != 5) return -1;
698 /* Apply timezone offset */
Frederik Deweerdt953917a2017-10-16 07:37:31 -0700699 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 +0200700 }
701
702 return -1;
703}
704
William Lallemand104a7a62019-10-14 14:14:59 +0200705/*
706 * struct alignment works here such that the key.key is the same as key_data
707 * Do not change the placement of key_data
708 */
709struct certificate_ocsp {
710 struct ebmb_node key;
711 unsigned char key_data[OCSP_MAX_CERTID_ASN1_LENGTH];
712 struct buffer response;
713 long expire;
714};
715
716struct ocsp_cbk_arg {
717 int is_single;
718 int single_kt;
719 union {
720 struct certificate_ocsp *s_ocsp;
721 /*
722 * m_ocsp will have multiple entries dependent on key type
723 * Entry 0 - DSA
724 * Entry 1 - ECDSA
725 * Entry 2 - RSA
726 */
727 struct certificate_ocsp *m_ocsp[SSL_SOCK_NUM_KEYTYPES];
728 };
729};
730
Emeric Brun1d3865b2014-06-20 15:37:32 +0200731static struct eb_root cert_ocsp_tree = EB_ROOT_UNIQUE;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200732
733/* This function starts to check if the OCSP response (in DER format) contained
734 * in chunk 'ocsp_response' is valid (else exits on error).
735 * If 'cid' is not NULL, it will be compared to the OCSP certificate ID
736 * contained in the OCSP Response and exits on error if no match.
737 * If it's a valid OCSP Response:
738 * If 'ocsp' is not NULL, the chunk is copied in the OCSP response's container
739 * pointed by 'ocsp'.
740 * If 'ocsp' is NULL, the function looks up into the OCSP response's
741 * containers tree (using as index the ASN1 form of the OCSP Certificate ID extracted
742 * from the response) and exits on error if not found. Finally, If an OCSP response is
743 * already present in the container, it will be overwritten.
744 *
745 * Note: OCSP response containing more than one OCSP Single response is not
746 * considered valid.
747 *
748 * Returns 0 on success, 1 in error case.
749 */
Willy Tarreau83061a82018-07-13 11:56:34 +0200750static int ssl_sock_load_ocsp_response(struct buffer *ocsp_response,
751 struct certificate_ocsp *ocsp,
752 OCSP_CERTID *cid, char **err)
Emeric Brun4147b2e2014-06-16 18:36:30 +0200753{
754 OCSP_RESPONSE *resp;
755 OCSP_BASICRESP *bs = NULL;
756 OCSP_SINGLERESP *sr;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200757 OCSP_CERTID *id;
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200758 unsigned char *p = (unsigned char *) ocsp_response->area;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200759 int rc , count_sr;
Emeric Brun13a6b482014-06-20 15:44:34 +0200760 ASN1_GENERALIZEDTIME *revtime, *thisupd, *nextupd = NULL;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200761 int reason;
762 int ret = 1;
763
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200764 resp = d2i_OCSP_RESPONSE(NULL, (const unsigned char **)&p,
765 ocsp_response->data);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200766 if (!resp) {
767 memprintf(err, "Unable to parse OCSP response");
768 goto out;
769 }
770
771 rc = OCSP_response_status(resp);
772 if (rc != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
773 memprintf(err, "OCSP response status not successful");
774 goto out;
775 }
776
777 bs = OCSP_response_get1_basic(resp);
778 if (!bs) {
779 memprintf(err, "Failed to get basic response from OCSP Response");
780 goto out;
781 }
782
783 count_sr = OCSP_resp_count(bs);
784 if (count_sr > 1) {
785 memprintf(err, "OCSP response ignored because contains multiple single responses (%d)", count_sr);
786 goto out;
787 }
788
789 sr = OCSP_resp_get0(bs, 0);
790 if (!sr) {
791 memprintf(err, "Failed to get OCSP single response");
792 goto out;
793 }
794
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200795 id = (OCSP_CERTID*)OCSP_SINGLERESP_get0_id(sr);
796
Emeric Brun4147b2e2014-06-16 18:36:30 +0200797 rc = OCSP_single_get0_status(sr, &reason, &revtime, &thisupd, &nextupd);
Emmanuel Hocdetef607052017-10-24 14:57:16 +0200798 if (rc != V_OCSP_CERTSTATUS_GOOD && rc != V_OCSP_CERTSTATUS_REVOKED) {
Emmanuel Hocdet872085c2017-10-10 15:18:52 +0200799 memprintf(err, "OCSP single response: certificate status is unknown");
Emeric Brun4147b2e2014-06-16 18:36:30 +0200800 goto out;
801 }
802
Emeric Brun13a6b482014-06-20 15:44:34 +0200803 if (!nextupd) {
804 memprintf(err, "OCSP single response: missing nextupdate");
805 goto out;
806 }
807
Emeric Brunc8b27b62014-06-19 14:16:17 +0200808 rc = OCSP_check_validity(thisupd, nextupd, OCSP_MAX_RESPONSE_TIME_SKEW, -1);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200809 if (!rc) {
810 memprintf(err, "OCSP single response: no longer valid.");
811 goto out;
812 }
813
814 if (cid) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200815 if (OCSP_id_cmp(id, cid)) {
Emeric Brun4147b2e2014-06-16 18:36:30 +0200816 memprintf(err, "OCSP single response: Certificate ID does not match certificate and issuer");
817 goto out;
818 }
819 }
820
821 if (!ocsp) {
822 unsigned char key[OCSP_MAX_CERTID_ASN1_LENGTH];
823 unsigned char *p;
824
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200825 rc = i2d_OCSP_CERTID(id, NULL);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200826 if (!rc) {
827 memprintf(err, "OCSP single response: Unable to encode Certificate ID");
828 goto out;
829 }
830
831 if (rc > OCSP_MAX_CERTID_ASN1_LENGTH) {
832 memprintf(err, "OCSP single response: Certificate ID too long");
833 goto out;
834 }
835
836 p = key;
837 memset(key, 0, OCSP_MAX_CERTID_ASN1_LENGTH);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200838 i2d_OCSP_CERTID(id, &p);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200839 ocsp = (struct certificate_ocsp *)ebmb_lookup(&cert_ocsp_tree, key, OCSP_MAX_CERTID_ASN1_LENGTH);
840 if (!ocsp) {
841 memprintf(err, "OCSP single response: Certificate ID does not match any certificate or issuer");
842 goto out;
843 }
844 }
845
846 /* According to comments on "chunk_dup", the
847 previous chunk buffer will be freed */
848 if (!chunk_dup(&ocsp->response, ocsp_response)) {
849 memprintf(err, "OCSP response: Memory allocation error");
850 goto out;
851 }
852
Emeric Brun4f3c87a2014-06-20 15:46:13 +0200853 ocsp->expire = asn1_generalizedtime_to_epoch(nextupd) - OCSP_MAX_RESPONSE_TIME_SKEW;
854
Emeric Brun4147b2e2014-06-16 18:36:30 +0200855 ret = 0;
856out:
Janusz Dziemidowicz8d710492017-03-08 16:59:41 +0100857 ERR_clear_error();
858
Emeric Brun4147b2e2014-06-16 18:36:30 +0200859 if (bs)
860 OCSP_BASICRESP_free(bs);
861
862 if (resp)
863 OCSP_RESPONSE_free(resp);
864
865 return ret;
866}
867/*
868 * External function use to update the OCSP response in the OCSP response's
869 * containers tree. The chunk 'ocsp_response' must contain the OCSP response
870 * to update in DER format.
871 *
872 * Returns 0 on success, 1 in error case.
873 */
Willy Tarreau83061a82018-07-13 11:56:34 +0200874int ssl_sock_update_ocsp_response(struct buffer *ocsp_response, char **err)
Emeric Brun4147b2e2014-06-16 18:36:30 +0200875{
876 return ssl_sock_load_ocsp_response(ocsp_response, NULL, NULL, err);
877}
878
William Lallemand4a660132019-10-14 14:51:41 +0200879#endif
880
881#if ((defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP) || defined OPENSSL_IS_BORINGSSL)
Emeric Brun4147b2e2014-06-16 18:36:30 +0200882/*
883 * This function load the OCSP Resonse in DER format contained in file at
William Lallemand3b5f3602019-10-16 18:05:05 +0200884 * path 'ocsp_path' or base64 in a buffer <buf>
Emeric Brun4147b2e2014-06-16 18:36:30 +0200885 *
886 * Returns 0 on success, 1 in error case.
887 */
William Lallemand3b5f3602019-10-16 18:05:05 +0200888static int ssl_sock_load_ocsp_response_from_file(const char *ocsp_path, char *buf, struct cert_key_and_chain *ckch, char **err)
Emeric Brun4147b2e2014-06-16 18:36:30 +0200889{
890 int fd = -1;
891 int r = 0;
892 int ret = 1;
William Lallemand3b5f3602019-10-16 18:05:05 +0200893 struct buffer *ocsp_response;
894 struct buffer *src = NULL;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200895
William Lallemand3b5f3602019-10-16 18:05:05 +0200896 if (buf) {
897 int i, j;
898 /* if it's from a buffer it will be base64 */
Emeric Brun4147b2e2014-06-16 18:36:30 +0200899
William Lallemand3b5f3602019-10-16 18:05:05 +0200900 /* remove \r and \n from the payload */
901 for (i = 0, j = 0; buf[i]; i++) {
902 if (buf[i] == '\r' || buf[i] == '\n')
Emeric Brun4147b2e2014-06-16 18:36:30 +0200903 continue;
William Lallemand3b5f3602019-10-16 18:05:05 +0200904 buf[j++] = buf[i];
905 }
906 buf[j] = 0;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200907
William Lallemand3b5f3602019-10-16 18:05:05 +0200908 ret = base64dec(buf, j, trash.area, trash.size);
909 if (ret < 0) {
910 memprintf(err, "Error reading OCSP response in base64 format");
Emeric Brun4147b2e2014-06-16 18:36:30 +0200911 goto end;
912 }
William Lallemand3b5f3602019-10-16 18:05:05 +0200913 trash.data = ret;
914 src = &trash;
915 } else {
916 fd = open(ocsp_path, O_RDONLY);
917 if (fd == -1) {
918 memprintf(err, "Error opening OCSP response file");
919 goto end;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200920 }
William Lallemand3b5f3602019-10-16 18:05:05 +0200921
922 trash.data = 0;
923 while (trash.data < trash.size) {
924 r = read(fd, trash.area + trash.data, trash.size - trash.data);
925 if (r < 0) {
926 if (errno == EINTR)
927 continue;
928
929 memprintf(err, "Error reading OCSP response from file");
930 goto end;
931 }
932 else if (r == 0) {
933 break;
934 }
935 trash.data += r;
936 }
937 close(fd);
938 fd = -1;
939 src = &trash;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200940 }
941
William Lallemand3b5f3602019-10-16 18:05:05 +0200942 ocsp_response = calloc(1, sizeof(*ocsp_response));
943 if (!chunk_dup(ocsp_response, src)) {
944 free(ocsp_response);
945 ocsp_response = NULL;
William Lallemand246c0242019-10-11 08:59:13 +0200946 goto end;
947 }
948
William Lallemand3b5f3602019-10-16 18:05:05 +0200949 ckch->ocsp_response = ocsp_response;
William Lallemande0f48ae2019-10-15 13:44:57 +0200950 ret = 0;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200951end:
952 if (fd != -1)
953 close(fd);
954
955 return ret;
956}
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100957#endif
Emeric Brun4147b2e2014-06-16 18:36:30 +0200958
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100959#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
960static 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)
961{
Christopher Faulet16f45c82018-02-16 11:23:49 +0100962 struct tls_keys_ref *ref;
Emeric Brun9e754772019-01-10 17:51:55 +0100963 union tls_sess_key *keys;
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100964 struct connection *conn;
965 int head;
966 int i;
Christopher Faulet16f45c82018-02-16 11:23:49 +0100967 int ret = -1; /* error by default */
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100968
Thierry FOURNIER28962c92018-06-17 21:37:05 +0200969 conn = SSL_get_ex_data(s, ssl_app_data_index);
Willy Tarreau07d94e42018-09-20 10:57:52 +0200970 ref = __objt_listener(conn->target)->bind_conf->keys_ref;
Christopher Faulet16f45c82018-02-16 11:23:49 +0100971 HA_RWLOCK_RDLOCK(TLSKEYS_REF_LOCK, &ref->lock);
972
973 keys = ref->tlskeys;
974 head = ref->tls_ticket_enc_index;
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100975
976 if (enc) {
977 memcpy(key_name, keys[head].name, 16);
978
979 if(!RAND_pseudo_bytes(iv, EVP_MAX_IV_LENGTH))
Christopher Faulet16f45c82018-02-16 11:23:49 +0100980 goto end;
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100981
Emeric Brun9e754772019-01-10 17:51:55 +0100982 if (ref->key_size_bits == 128) {
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100983
Emeric Brun9e754772019-01-10 17:51:55 +0100984 if(!EVP_EncryptInit_ex(ectx, EVP_aes_128_cbc(), NULL, keys[head].key_128.aes_key, iv))
985 goto end;
986
Willy Tarreau9356dac2019-05-10 09:22:53 +0200987 HMAC_Init_ex(hctx, keys[head].key_128.hmac_key, 16, TLS_TICKET_HASH_FUNCT(), NULL);
Emeric Brun9e754772019-01-10 17:51:55 +0100988 ret = 1;
989 }
990 else if (ref->key_size_bits == 256 ) {
991
992 if(!EVP_EncryptInit_ex(ectx, EVP_aes_256_cbc(), NULL, keys[head].key_256.aes_key, iv))
993 goto end;
994
Willy Tarreau9356dac2019-05-10 09:22:53 +0200995 HMAC_Init_ex(hctx, keys[head].key_256.hmac_key, 32, TLS_TICKET_HASH_FUNCT(), NULL);
Emeric Brun9e754772019-01-10 17:51:55 +0100996 ret = 1;
997 }
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100998 } else {
999 for (i = 0; i < TLS_TICKETS_NO; i++) {
1000 if (!memcmp(key_name, keys[(head + i) % TLS_TICKETS_NO].name, 16))
1001 goto found;
1002 }
Christopher Faulet16f45c82018-02-16 11:23:49 +01001003 ret = 0;
1004 goto end;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01001005
Christopher Faulet16f45c82018-02-16 11:23:49 +01001006 found:
Emeric Brun9e754772019-01-10 17:51:55 +01001007 if (ref->key_size_bits == 128) {
Willy Tarreau9356dac2019-05-10 09:22:53 +02001008 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 +01001009 if(!EVP_DecryptInit_ex(ectx, EVP_aes_128_cbc(), NULL, keys[(head + i) % TLS_TICKETS_NO].key_128.aes_key, iv))
1010 goto end;
1011 /* 2 for key renewal, 1 if current key is still valid */
1012 ret = i ? 2 : 1;
1013 }
1014 else if (ref->key_size_bits == 256) {
Willy Tarreau9356dac2019-05-10 09:22:53 +02001015 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 +01001016 if(!EVP_DecryptInit_ex(ectx, EVP_aes_256_cbc(), NULL, keys[(head + i) % TLS_TICKETS_NO].key_256.aes_key, iv))
1017 goto end;
1018 /* 2 for key renewal, 1 if current key is still valid */
1019 ret = i ? 2 : 1;
1020 }
Nenad Merdanovic05552d42015-02-27 19:56:49 +01001021 }
Emeric Brun9e754772019-01-10 17:51:55 +01001022
Christopher Faulet16f45c82018-02-16 11:23:49 +01001023 end:
1024 HA_RWLOCK_RDUNLOCK(TLSKEYS_REF_LOCK, &ref->lock);
1025 return ret;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02001026}
1027
1028struct tls_keys_ref *tlskeys_ref_lookup(const char *filename)
1029{
1030 struct tls_keys_ref *ref;
1031
1032 list_for_each_entry(ref, &tlskeys_reference, list)
1033 if (ref->filename && strcmp(filename, ref->filename) == 0)
1034 return ref;
1035 return NULL;
1036}
1037
1038struct tls_keys_ref *tlskeys_ref_lookupid(int unique_id)
1039{
1040 struct tls_keys_ref *ref;
1041
1042 list_for_each_entry(ref, &tlskeys_reference, list)
1043 if (ref->unique_id == unique_id)
1044 return ref;
1045 return NULL;
1046}
1047
Emeric Brun9e754772019-01-10 17:51:55 +01001048/* Update the key into ref: if keysize doesnt
1049 * match existing ones, this function returns -1
1050 * else it returns 0 on success.
1051 */
1052int ssl_sock_update_tlskey_ref(struct tls_keys_ref *ref,
Willy Tarreau83061a82018-07-13 11:56:34 +02001053 struct buffer *tlskey)
Christopher Faulet16f45c82018-02-16 11:23:49 +01001054{
Emeric Brun9e754772019-01-10 17:51:55 +01001055 if (ref->key_size_bits == 128) {
1056 if (tlskey->data != sizeof(struct tls_sess_key_128))
1057 return -1;
1058 }
1059 else if (ref->key_size_bits == 256) {
1060 if (tlskey->data != sizeof(struct tls_sess_key_256))
1061 return -1;
1062 }
1063 else
1064 return -1;
1065
Christopher Faulet16f45c82018-02-16 11:23:49 +01001066 HA_RWLOCK_WRLOCK(TLSKEYS_REF_LOCK, &ref->lock);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001067 memcpy((char *) (ref->tlskeys + ((ref->tls_ticket_enc_index + 2) % TLS_TICKETS_NO)),
1068 tlskey->area, tlskey->data);
Christopher Faulet16f45c82018-02-16 11:23:49 +01001069 ref->tls_ticket_enc_index = (ref->tls_ticket_enc_index + 1) % TLS_TICKETS_NO;
1070 HA_RWLOCK_WRUNLOCK(TLSKEYS_REF_LOCK, &ref->lock);
Emeric Brun9e754772019-01-10 17:51:55 +01001071
1072 return 0;
Christopher Faulet16f45c82018-02-16 11:23:49 +01001073}
1074
Willy Tarreau83061a82018-07-13 11:56:34 +02001075int ssl_sock_update_tlskey(char *filename, struct buffer *tlskey, char **err)
Christopher Faulet16f45c82018-02-16 11:23:49 +01001076{
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02001077 struct tls_keys_ref *ref = tlskeys_ref_lookup(filename);
1078
1079 if(!ref) {
1080 memprintf(err, "Unable to locate the referenced filename: %s", filename);
1081 return 1;
1082 }
Emeric Brun9e754772019-01-10 17:51:55 +01001083 if (ssl_sock_update_tlskey_ref(ref, tlskey) < 0) {
1084 memprintf(err, "Invalid key size");
1085 return 1;
1086 }
1087
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02001088 return 0;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01001089}
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02001090
1091/* This function finalize the configuration parsing. Its set all the
Willy Tarreaud1c57502016-12-22 22:46:15 +01001092 * automatic ids. It's called just after the basic checks. It returns
1093 * 0 on success otherwise ERR_*.
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02001094 */
Willy Tarreaud1c57502016-12-22 22:46:15 +01001095static int tlskeys_finalize_config(void)
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02001096{
1097 int i = 0;
1098 struct tls_keys_ref *ref, *ref2, *ref3;
1099 struct list tkr = LIST_HEAD_INIT(tkr);
1100
1101 list_for_each_entry(ref, &tlskeys_reference, list) {
1102 if (ref->unique_id == -1) {
1103 /* Look for the first free id. */
1104 while (1) {
1105 list_for_each_entry(ref2, &tlskeys_reference, list) {
1106 if (ref2->unique_id == i) {
1107 i++;
1108 break;
1109 }
1110 }
1111 if (&ref2->list == &tlskeys_reference)
1112 break;
1113 }
1114
1115 /* Uses the unique id and increment it for the next entry. */
1116 ref->unique_id = i;
1117 i++;
1118 }
1119 }
1120
1121 /* This sort the reference list by id. */
1122 list_for_each_entry_safe(ref, ref2, &tlskeys_reference, list) {
1123 LIST_DEL(&ref->list);
1124 list_for_each_entry(ref3, &tkr, list) {
1125 if (ref->unique_id < ref3->unique_id) {
1126 LIST_ADDQ(&ref3->list, &ref->list);
1127 break;
1128 }
1129 }
1130 if (&ref3->list == &tkr)
1131 LIST_ADDQ(&tkr, &ref->list);
1132 }
1133
1134 /* swap root */
1135 LIST_ADD(&tkr, &tlskeys_reference);
1136 LIST_DEL(&tkr);
Willy Tarreaud1c57502016-12-22 22:46:15 +01001137 return 0;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02001138}
Nenad Merdanovic05552d42015-02-27 19:56:49 +01001139#endif /* SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB */
1140
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01001141#ifndef OPENSSL_NO_OCSP
yanbzhube2774d2015-12-10 15:07:30 -05001142int ssl_sock_get_ocsp_arg_kt_index(int evp_keytype)
1143{
1144 switch (evp_keytype) {
1145 case EVP_PKEY_RSA:
1146 return 2;
1147 case EVP_PKEY_DSA:
1148 return 0;
1149 case EVP_PKEY_EC:
1150 return 1;
1151 }
1152
1153 return -1;
1154}
1155
Emeric Brun4147b2e2014-06-16 18:36:30 +02001156/*
1157 * Callback used to set OCSP status extension content in server hello.
1158 */
1159int ssl_sock_ocsp_stapling_cbk(SSL *ssl, void *arg)
1160{
yanbzhube2774d2015-12-10 15:07:30 -05001161 struct certificate_ocsp *ocsp;
1162 struct ocsp_cbk_arg *ocsp_arg;
1163 char *ssl_buf;
1164 EVP_PKEY *ssl_pkey;
1165 int key_type;
1166 int index;
1167
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02001168 ocsp_arg = arg;
yanbzhube2774d2015-12-10 15:07:30 -05001169
1170 ssl_pkey = SSL_get_privatekey(ssl);
1171 if (!ssl_pkey)
1172 return SSL_TLSEXT_ERR_NOACK;
1173
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001174 key_type = EVP_PKEY_base_id(ssl_pkey);
yanbzhube2774d2015-12-10 15:07:30 -05001175
1176 if (ocsp_arg->is_single && ocsp_arg->single_kt == key_type)
1177 ocsp = ocsp_arg->s_ocsp;
1178 else {
1179 /* For multiple certs per context, we have to find the correct OCSP response based on
1180 * the certificate type
1181 */
1182 index = ssl_sock_get_ocsp_arg_kt_index(key_type);
1183
1184 if (index < 0)
1185 return SSL_TLSEXT_ERR_NOACK;
1186
1187 ocsp = ocsp_arg->m_ocsp[index];
1188
1189 }
Emeric Brun4147b2e2014-06-16 18:36:30 +02001190
1191 if (!ocsp ||
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001192 !ocsp->response.area ||
1193 !ocsp->response.data ||
Emeric Brun4f3c87a2014-06-20 15:46:13 +02001194 (ocsp->expire < now.tv_sec))
Emeric Brun4147b2e2014-06-16 18:36:30 +02001195 return SSL_TLSEXT_ERR_NOACK;
1196
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001197 ssl_buf = OPENSSL_malloc(ocsp->response.data);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001198 if (!ssl_buf)
1199 return SSL_TLSEXT_ERR_NOACK;
1200
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001201 memcpy(ssl_buf, ocsp->response.area, ocsp->response.data);
1202 SSL_set_tlsext_status_ocsp_resp(ssl, ssl_buf, ocsp->response.data);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001203
1204 return SSL_TLSEXT_ERR_OK;
1205}
1206
William Lallemand4a660132019-10-14 14:51:41 +02001207#endif
1208
1209#if ((defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP) || defined OPENSSL_IS_BORINGSSL)
Emeric Brun4147b2e2014-06-16 18:36:30 +02001210/*
1211 * This function enables the handling of OCSP status extension on 'ctx' if a
William Lallemand246c0242019-10-11 08:59:13 +02001212 * ocsp_response buffer was found in the cert_key_and_chain. To enable OCSP
1213 * status extension, the issuer's certificate is mandatory. It should be
1214 * present in ckch->ocsp_issuer.
Emeric Brun4147b2e2014-06-16 18:36:30 +02001215 *
William Lallemand246c0242019-10-11 08:59:13 +02001216 * In addition, the ckch->ocsp_reponse buffer is loaded as a DER format of an
1217 * OCSP response. If file is empty or content is not a valid OCSP response,
1218 * OCSP status extension is enabled but OCSP response is ignored (a warning is
1219 * displayed).
Emeric Brun4147b2e2014-06-16 18:36:30 +02001220 *
1221 * Returns 1 if no ".ocsp" file found, 0 if OCSP status extension is
Joseph Herlant017b3da2018-11-15 09:07:59 -08001222 * successfully enabled, or -1 in other error case.
Emeric Brun4147b2e2014-06-16 18:36:30 +02001223 */
William Lallemand4a660132019-10-14 14:51:41 +02001224#ifndef OPENSSL_IS_BORINGSSL
William Lallemand246c0242019-10-11 08:59:13 +02001225static int ssl_sock_load_ocsp(SSL_CTX *ctx, const struct cert_key_and_chain *ckch)
Emeric Brun4147b2e2014-06-16 18:36:30 +02001226{
William Lallemand246c0242019-10-11 08:59:13 +02001227 X509 *x = NULL, *issuer = NULL;
Emeric Brun4147b2e2014-06-16 18:36:30 +02001228 OCSP_CERTID *cid = NULL;
Emeric Brun4147b2e2014-06-16 18:36:30 +02001229 int i, ret = -1;
Emeric Brun4147b2e2014-06-16 18:36:30 +02001230 struct certificate_ocsp *ocsp = NULL, *iocsp;
1231 char *warn = NULL;
1232 unsigned char *p;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001233 void (*callback) (void);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001234
Emeric Brun4147b2e2014-06-16 18:36:30 +02001235
William Lallemand246c0242019-10-11 08:59:13 +02001236 x = ckch->cert;
Emeric Brun4147b2e2014-06-16 18:36:30 +02001237 if (!x)
1238 goto out;
1239
William Lallemand246c0242019-10-11 08:59:13 +02001240 issuer = ckch->ocsp_issuer;
1241 if (!issuer)
1242 goto out;
Emeric Brun4147b2e2014-06-16 18:36:30 +02001243
1244 cid = OCSP_cert_to_id(0, x, issuer);
1245 if (!cid)
1246 goto out;
1247
1248 i = i2d_OCSP_CERTID(cid, NULL);
1249 if (!i || (i > OCSP_MAX_CERTID_ASN1_LENGTH))
1250 goto out;
1251
Vincent Bernat02779b62016-04-03 13:48:43 +02001252 ocsp = calloc(1, sizeof(*ocsp));
Emeric Brun4147b2e2014-06-16 18:36:30 +02001253 if (!ocsp)
1254 goto out;
1255
1256 p = ocsp->key_data;
1257 i2d_OCSP_CERTID(cid, &p);
1258
1259 iocsp = (struct certificate_ocsp *)ebmb_insert(&cert_ocsp_tree, &ocsp->key, OCSP_MAX_CERTID_ASN1_LENGTH);
1260 if (iocsp == ocsp)
1261 ocsp = NULL;
1262
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001263#ifndef SSL_CTX_get_tlsext_status_cb
1264# define SSL_CTX_get_tlsext_status_cb(ctx, cb) \
1265 *cb = (void (*) (void))ctx->tlsext_status_cb;
1266#endif
1267 SSL_CTX_get_tlsext_status_cb(ctx, &callback);
1268
1269 if (!callback) {
Vincent Bernat02779b62016-04-03 13:48:43 +02001270 struct ocsp_cbk_arg *cb_arg = calloc(1, sizeof(*cb_arg));
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001271 EVP_PKEY *pkey;
yanbzhube2774d2015-12-10 15:07:30 -05001272
1273 cb_arg->is_single = 1;
1274 cb_arg->s_ocsp = iocsp;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001275
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001276 pkey = X509_get_pubkey(x);
1277 cb_arg->single_kt = EVP_PKEY_base_id(pkey);
1278 EVP_PKEY_free(pkey);
yanbzhube2774d2015-12-10 15:07:30 -05001279
1280 SSL_CTX_set_tlsext_status_cb(ctx, ssl_sock_ocsp_stapling_cbk);
1281 SSL_CTX_set_tlsext_status_arg(ctx, cb_arg);
1282 } else {
1283 /*
1284 * If the ctx has a status CB, then we have previously set an OCSP staple for this ctx
1285 * Update that cb_arg with the new cert's staple
1286 */
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001287 struct ocsp_cbk_arg *cb_arg;
yanbzhube2774d2015-12-10 15:07:30 -05001288 struct certificate_ocsp *tmp_ocsp;
1289 int index;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001290 int key_type;
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001291 EVP_PKEY *pkey;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001292
1293#ifdef SSL_CTX_get_tlsext_status_arg
1294 SSL_CTX_ctrl(ctx, SSL_CTRL_GET_TLSEXT_STATUS_REQ_CB_ARG, 0, &cb_arg);
1295#else
1296 cb_arg = ctx->tlsext_status_arg;
1297#endif
yanbzhube2774d2015-12-10 15:07:30 -05001298
1299 /*
1300 * The following few lines will convert cb_arg from a single ocsp to multi ocsp
1301 * the order of operations below matter, take care when changing it
1302 */
1303 tmp_ocsp = cb_arg->s_ocsp;
1304 index = ssl_sock_get_ocsp_arg_kt_index(cb_arg->single_kt);
1305 cb_arg->s_ocsp = NULL;
1306 cb_arg->m_ocsp[index] = tmp_ocsp;
1307 cb_arg->is_single = 0;
1308 cb_arg->single_kt = 0;
1309
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001310 pkey = X509_get_pubkey(x);
1311 key_type = EVP_PKEY_base_id(pkey);
1312 EVP_PKEY_free(pkey);
1313
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001314 index = ssl_sock_get_ocsp_arg_kt_index(key_type);
yanbzhube2774d2015-12-10 15:07:30 -05001315 if (index >= 0 && !cb_arg->m_ocsp[index])
1316 cb_arg->m_ocsp[index] = iocsp;
1317
1318 }
Emeric Brun4147b2e2014-06-16 18:36:30 +02001319
1320 ret = 0;
1321
1322 warn = NULL;
William Lallemand246c0242019-10-11 08:59:13 +02001323 if (ssl_sock_load_ocsp_response(ckch->ocsp_response, ocsp, cid, &warn)) {
William Lallemand3b5f3602019-10-16 18:05:05 +02001324 memprintf(&warn, "Loading: %s. Content will be ignored", warn ? warn : "failure");
Christopher Faulet767a84b2017-11-24 16:50:31 +01001325 ha_warning("%s.\n", warn);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001326 }
1327
1328out:
Emeric Brun4147b2e2014-06-16 18:36:30 +02001329 if (cid)
1330 OCSP_CERTID_free(cid);
1331
1332 if (ocsp)
1333 free(ocsp);
1334
1335 if (warn)
1336 free(warn);
1337
Emeric Brun4147b2e2014-06-16 18:36:30 +02001338 return ret;
1339}
William Lallemand4a660132019-10-14 14:51:41 +02001340#else /* OPENSSL_IS_BORINGSSL */
1341static int ssl_sock_load_ocsp(SSL_CTX *ctx, const struct cert_key_and_chain *ckch)
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02001342{
William Lallemand4a660132019-10-14 14:51:41 +02001343 return SSL_CTX_set_ocsp_response(ctx, (const uint8_t *)ckch->ocsp_response->area, ckch->ocsp_response->data);
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02001344}
1345#endif
1346
William Lallemand4a660132019-10-14 14:51:41 +02001347#endif
1348
1349
Willy Tarreau5db847a2019-05-09 14:13:35 +02001350#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001351
1352#define CT_EXTENSION_TYPE 18
1353
1354static int sctl_ex_index = -1;
1355
1356/*
1357 * Try to parse Signed Certificate Timestamp List structure. This function
1358 * makes only basic test if the data seems like SCTL. No signature validation
1359 * is performed.
1360 */
Willy Tarreau83061a82018-07-13 11:56:34 +02001361static int ssl_sock_parse_sctl(struct buffer *sctl)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001362{
1363 int ret = 1;
1364 int len, pos, sct_len;
1365 unsigned char *data;
1366
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001367 if (sctl->data < 2)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001368 goto out;
1369
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001370 data = (unsigned char *) sctl->area;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001371 len = (data[0] << 8) | data[1];
1372
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001373 if (len + 2 != sctl->data)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001374 goto out;
1375
1376 data = data + 2;
1377 pos = 0;
1378 while (pos < len) {
1379 if (len - pos < 2)
1380 goto out;
1381
1382 sct_len = (data[pos] << 8) | data[pos + 1];
1383 if (pos + sct_len + 2 > len)
1384 goto out;
1385
1386 pos += sct_len + 2;
1387 }
1388
1389 ret = 0;
1390
1391out:
1392 return ret;
1393}
1394
William Lallemand0dfae6c2019-10-16 18:06:58 +02001395/* Try to load a sctl from a buffer <buf> if not NULL, or read the file <sctl_path>
1396 * It fills the ckch->sctl buffer
1397 * return 0 on success or != 0 on failure */
1398static int ssl_sock_load_sctl_from_file(const char *sctl_path, char *buf, struct cert_key_and_chain *ckch, char **err)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001399{
1400 int fd = -1;
1401 int r = 0;
1402 int ret = 1;
William Lallemand0dfae6c2019-10-16 18:06:58 +02001403 struct buffer tmp;
1404 struct buffer *src;
1405 struct buffer *sctl;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001406
William Lallemand0dfae6c2019-10-16 18:06:58 +02001407 if (buf) {
1408 tmp.area = buf;
1409 tmp.data = strlen(buf);
1410 tmp.size = tmp.data + 1;
1411 src = &tmp;
1412 } else {
1413 fd = open(sctl_path, O_RDONLY);
1414 if (fd == -1)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001415 goto end;
William Lallemand0dfae6c2019-10-16 18:06:58 +02001416
1417 trash.data = 0;
1418 while (trash.data < trash.size) {
1419 r = read(fd, trash.area + trash.data, trash.size - trash.data);
1420 if (r < 0) {
1421 if (errno == EINTR)
1422 continue;
1423 goto end;
1424 }
1425 else if (r == 0) {
1426 break;
1427 }
1428 trash.data += r;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001429 }
William Lallemand0dfae6c2019-10-16 18:06:58 +02001430 src = &trash;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001431 }
1432
William Lallemand0dfae6c2019-10-16 18:06:58 +02001433 ret = ssl_sock_parse_sctl(src);
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001434 if (ret)
1435 goto end;
1436
William Lallemand0dfae6c2019-10-16 18:06:58 +02001437 sctl = calloc(1, sizeof(*sctl));
1438 if (!chunk_dup(sctl, src)) {
1439 free(sctl);
1440 sctl = NULL;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001441 goto end;
1442 }
William Lallemand0dfae6c2019-10-16 18:06:58 +02001443 ret = 0;
1444 /* TODO: free the previous SCTL in the ckch */
1445 ckch->sctl = sctl;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001446
1447end:
1448 if (fd != -1)
1449 close(fd);
1450
1451 return ret;
1452}
1453
1454int ssl_sock_sctl_add_cbk(SSL *ssl, unsigned ext_type, const unsigned char **out, size_t *outlen, int *al, void *add_arg)
1455{
Willy Tarreau83061a82018-07-13 11:56:34 +02001456 struct buffer *sctl = add_arg;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001457
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001458 *out = (unsigned char *) sctl->area;
1459 *outlen = sctl->data;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001460
1461 return 1;
1462}
1463
1464int ssl_sock_sctl_parse_cbk(SSL *s, unsigned int ext_type, const unsigned char *in, size_t inlen, int *al, void *parse_arg)
1465{
1466 return 1;
1467}
1468
William Lallemanda17f4112019-10-10 15:16:44 +02001469static int ssl_sock_load_sctl(SSL_CTX *ctx, struct buffer *sctl)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001470{
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001471 int ret = -1;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001472
William Lallemanda17f4112019-10-10 15:16:44 +02001473 if (!SSL_CTX_add_server_custom_ext(ctx, CT_EXTENSION_TYPE, ssl_sock_sctl_add_cbk, NULL, sctl, ssl_sock_sctl_parse_cbk, NULL))
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001474 goto out;
1475
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001476 SSL_CTX_set_ex_data(ctx, sctl_ex_index, sctl);
1477
1478 ret = 0;
1479
1480out:
1481 return ret;
1482}
1483
1484#endif
1485
Emeric Brune1f38db2012-09-03 20:36:47 +02001486void ssl_sock_infocbk(const SSL *ssl, int where, int ret)
1487{
Thierry FOURNIER28962c92018-06-17 21:37:05 +02001488 struct connection *conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001489 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
Emeric Brund8b2bb52014-01-28 15:43:53 +01001490 BIO *write_bio;
Willy Tarreau622317d2015-02-27 16:36:16 +01001491 (void)ret; /* shut gcc stupid warning */
Emeric Brune1f38db2012-09-03 20:36:47 +02001492
Dirkjan Bussink526894f2019-01-21 09:35:03 -08001493#ifndef SSL_OP_NO_RENEGOTIATION
1494 /* Please note that BoringSSL defines this macro to zero so don't
1495 * change this to #if and do not assign a default value to this macro!
1496 */
Emeric Brune1f38db2012-09-03 20:36:47 +02001497 if (where & SSL_CB_HANDSHAKE_START) {
1498 /* Disable renegotiation (CVE-2009-3555) */
Olivier Houchard90084a12017-11-23 18:21:29 +01001499 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 +02001500 conn->flags |= CO_FL_ERROR;
Willy Tarreau20879a02012-12-03 16:32:10 +01001501 conn->err_code = CO_ER_SSL_RENEG;
1502 }
Emeric Brune1f38db2012-09-03 20:36:47 +02001503 }
Dirkjan Bussink526894f2019-01-21 09:35:03 -08001504#endif
Emeric Brund8b2bb52014-01-28 15:43:53 +01001505
1506 if ((where & SSL_CB_ACCEPT_LOOP) == SSL_CB_ACCEPT_LOOP) {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001507 if (!(ctx->xprt_st & SSL_SOCK_ST_FL_16K_WBFSIZE)) {
Emeric Brund8b2bb52014-01-28 15:43:53 +01001508 /* Long certificate chains optimz
1509 If write and read bios are differents, we
1510 consider that the buffering was activated,
1511 so we rise the output buffer size from 4k
1512 to 16k */
1513 write_bio = SSL_get_wbio(ssl);
1514 if (write_bio != SSL_get_rbio(ssl)) {
1515 BIO_set_write_buffer_size(write_bio, 16384);
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001516 ctx->xprt_st |= SSL_SOCK_ST_FL_16K_WBFSIZE;
Emeric Brund8b2bb52014-01-28 15:43:53 +01001517 }
1518 }
1519 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02001520}
1521
Emeric Brune64aef12012-09-21 13:15:06 +02001522/* Callback is called for each certificate of the chain during a verify
1523 ok is set to 1 if preverify detect no error on current certificate.
1524 Returns 0 to break the handshake, 1 otherwise. */
Evan Broderbe554312013-06-27 00:05:25 -07001525int ssl_sock_bind_verifycbk(int ok, X509_STORE_CTX *x_store)
Emeric Brune64aef12012-09-21 13:15:06 +02001526{
1527 SSL *ssl;
1528 struct connection *conn;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001529 struct ssl_sock_ctx *ctx;
Emeric Brun81c00f02012-09-21 14:31:21 +02001530 int err, depth;
Emeric Brune64aef12012-09-21 13:15:06 +02001531
1532 ssl = X509_STORE_CTX_get_ex_data(x_store, SSL_get_ex_data_X509_STORE_CTX_idx());
Thierry FOURNIER28962c92018-06-17 21:37:05 +02001533 conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Emeric Brune64aef12012-09-21 13:15:06 +02001534
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001535 ctx = conn->xprt_ctx;
1536
1537 ctx->xprt_st |= SSL_SOCK_ST_FL_VERIFY_DONE;
Emeric Brune64aef12012-09-21 13:15:06 +02001538
Emeric Brun81c00f02012-09-21 14:31:21 +02001539 if (ok) /* no errors */
1540 return ok;
1541
1542 depth = X509_STORE_CTX_get_error_depth(x_store);
1543 err = X509_STORE_CTX_get_error(x_store);
1544
1545 /* check if CA error needs to be ignored */
1546 if (depth > 0) {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001547 if (!SSL_SOCK_ST_TO_CA_ERROR(ctx->xprt_st)) {
1548 ctx->xprt_st |= SSL_SOCK_CA_ERROR_TO_ST(err);
1549 ctx->xprt_st |= SSL_SOCK_CAEDEPTH_TO_ST(depth);
Emeric Brunf282a812012-09-21 15:27:54 +02001550 }
1551
Willy Tarreau07d94e42018-09-20 10:57:52 +02001552 if (__objt_listener(conn->target)->bind_conf->ca_ignerr & (1ULL << err)) {
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02001553 ssl_sock_dump_errors(conn);
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001554 ERR_clear_error();
Emeric Brun81c00f02012-09-21 14:31:21 +02001555 return 1;
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001556 }
Emeric Brun81c00f02012-09-21 14:31:21 +02001557
Willy Tarreau20879a02012-12-03 16:32:10 +01001558 conn->err_code = CO_ER_SSL_CA_FAIL;
Emeric Brun81c00f02012-09-21 14:31:21 +02001559 return 0;
1560 }
1561
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001562 if (!SSL_SOCK_ST_TO_CRTERROR(ctx->xprt_st))
1563 ctx->xprt_st |= SSL_SOCK_CRTERROR_TO_ST(err);
Emeric Brunf282a812012-09-21 15:27:54 +02001564
Emeric Brun81c00f02012-09-21 14:31:21 +02001565 /* check if certificate error needs to be ignored */
Willy Tarreau07d94e42018-09-20 10:57:52 +02001566 if (__objt_listener(conn->target)->bind_conf->crt_ignerr & (1ULL << err)) {
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02001567 ssl_sock_dump_errors(conn);
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001568 ERR_clear_error();
Emeric Brun81c00f02012-09-21 14:31:21 +02001569 return 1;
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001570 }
Emeric Brun81c00f02012-09-21 14:31:21 +02001571
Willy Tarreau20879a02012-12-03 16:32:10 +01001572 conn->err_code = CO_ER_SSL_CRT_FAIL;
Emeric Brun81c00f02012-09-21 14:31:21 +02001573 return 0;
Emeric Brune64aef12012-09-21 13:15:06 +02001574}
1575
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001576static inline
1577void ssl_sock_parse_clienthello(int write_p, int version, int content_type,
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001578 const void *buf, size_t len, SSL *ssl)
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001579{
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001580 struct ssl_capture *capture;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001581 unsigned char *msg;
1582 unsigned char *end;
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001583 size_t rec_len;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001584
1585 /* This function is called for "from client" and "to server"
1586 * connections. The combination of write_p == 0 and content_type == 22
Joseph Herlant017b3da2018-11-15 09:07:59 -08001587 * is only available during "from client" connection.
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001588 */
1589
1590 /* "write_p" is set to 0 is the bytes are received messages,
1591 * otherwise it is set to 1.
1592 */
1593 if (write_p != 0)
1594 return;
1595
1596 /* content_type contains the type of message received or sent
1597 * according with the SSL/TLS protocol spec. This message is
1598 * encoded with one byte. The value 256 (two bytes) is used
1599 * for designing the SSL/TLS record layer. According with the
1600 * rfc6101, the expected message (other than 256) are:
1601 * - change_cipher_spec(20)
1602 * - alert(21)
1603 * - handshake(22)
1604 * - application_data(23)
1605 * - (255)
1606 * We are interessed by the handshake and specially the client
1607 * hello.
1608 */
1609 if (content_type != 22)
1610 return;
1611
1612 /* The message length is at least 4 bytes, containing the
1613 * message type and the message length.
1614 */
1615 if (len < 4)
1616 return;
1617
1618 /* First byte of the handshake message id the type of
1619 * message. The konwn types are:
1620 * - hello_request(0)
1621 * - client_hello(1)
1622 * - server_hello(2)
1623 * - certificate(11)
1624 * - server_key_exchange (12)
1625 * - certificate_request(13)
1626 * - server_hello_done(14)
1627 * We are interested by the client hello.
1628 */
1629 msg = (unsigned char *)buf;
1630 if (msg[0] != 1)
1631 return;
1632
1633 /* Next three bytes are the length of the message. The total length
1634 * must be this decoded length + 4. If the length given as argument
1635 * is not the same, we abort the protocol dissector.
1636 */
1637 rec_len = (msg[1] << 16) + (msg[2] << 8) + msg[3];
1638 if (len < rec_len + 4)
1639 return;
1640 msg += 4;
1641 end = msg + rec_len;
1642 if (end < msg)
1643 return;
1644
1645 /* Expect 2 bytes for protocol version (1 byte for major and 1 byte
1646 * for minor, the random, composed by 4 bytes for the unix time and
Baptiste Assmann6be139f2018-11-28 15:20:25 +01001647 * 28 bytes for unix payload. So we jump 1 + 1 + 4 + 28.
1648 */
1649 msg += 1 + 1 + 4 + 28;
1650 if (msg > end)
1651 return;
1652
1653 /* Next, is session id:
1654 * if present, we have to jump by length + 1 for the size information
1655 * if not present, we have to jump by 1 only
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001656 */
Baptiste Assmann6be139f2018-11-28 15:20:25 +01001657 if (msg[0] > 0)
1658 msg += msg[0];
1659 msg += 1;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001660 if (msg > end)
1661 return;
1662
1663 /* Next two bytes are the ciphersuite length. */
1664 if (msg + 2 > end)
1665 return;
1666 rec_len = (msg[0] << 8) + msg[1];
1667 msg += 2;
1668 if (msg + rec_len > end || msg + rec_len < msg)
1669 return;
1670
Willy Tarreaubafbe012017-11-24 17:34:44 +01001671 capture = pool_alloc_dirty(pool_head_ssl_capture);
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001672 if (!capture)
1673 return;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001674 /* Compute the xxh64 of the ciphersuite. */
1675 capture->xxh64 = XXH64(msg, rec_len, 0);
1676
1677 /* Capture the ciphersuite. */
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001678 capture->ciphersuite_len = (global_ssl.capture_cipherlist < rec_len) ?
1679 global_ssl.capture_cipherlist : rec_len;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001680 memcpy(capture->ciphersuite, msg, capture->ciphersuite_len);
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001681
1682 SSL_set_ex_data(ssl, ssl_capture_ptr_index, capture);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001683}
1684
Emeric Brun29f037d2014-04-25 19:05:36 +02001685/* Callback is called for ssl protocol analyse */
1686void ssl_sock_msgcbk(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg)
1687{
Emeric Brun29f037d2014-04-25 19:05:36 +02001688#ifdef TLS1_RT_HEARTBEAT
1689 /* test heartbeat received (write_p is set to 0
1690 for a received record) */
Willy Tarreauf51c6982014-04-25 20:02:39 +02001691 if ((content_type == TLS1_RT_HEARTBEAT) && (write_p == 0)) {
Thierry FOURNIER28962c92018-06-17 21:37:05 +02001692 struct connection *conn = SSL_get_ex_data(ssl, ssl_app_data_index);
William Lallemand7e1770b2019-05-13 14:31:34 +02001693 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
Willy Tarreauf51c6982014-04-25 20:02:39 +02001694 const unsigned char *p = buf;
1695 unsigned int payload;
1696
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001697 ctx->xprt_st |= SSL_SOCK_RECV_HEARTBEAT;
Willy Tarreauf51c6982014-04-25 20:02:39 +02001698
1699 /* Check if this is a CVE-2014-0160 exploitation attempt. */
1700 if (*p != TLS1_HB_REQUEST)
1701 return;
1702
Willy Tarreauaeed6722014-04-25 23:59:58 +02001703 if (len < 1 + 2 + 16) /* 1 type + 2 size + 0 payload + 16 padding */
Willy Tarreauf51c6982014-04-25 20:02:39 +02001704 goto kill_it;
1705
1706 payload = (p[1] * 256) + p[2];
Willy Tarreau3b2fdb62014-04-25 23:44:22 +02001707 if (3 + payload + 16 <= len)
Willy Tarreauf51c6982014-04-25 20:02:39 +02001708 return; /* OK no problem */
Willy Tarreauaeed6722014-04-25 23:59:58 +02001709 kill_it:
Willy Tarreau3b2fdb62014-04-25 23:44:22 +02001710 /* We have a clear heartbleed attack (CVE-2014-0160), the
1711 * advertised payload is larger than the advertised packet
1712 * length, so we have garbage in the buffer between the
1713 * payload and the end of the buffer (p+len). We can't know
1714 * if the SSL stack is patched, and we don't know if we can
1715 * safely wipe out the area between p+3+len and payload.
1716 * So instead, we prevent the response from being sent by
1717 * setting the max_send_fragment to 0 and we report an SSL
1718 * error, which will kill this connection. It will be reported
1719 * above as SSL_ERROR_SSL while an other handshake failure with
Willy Tarreauf51c6982014-04-25 20:02:39 +02001720 * a heartbeat message will be reported as SSL_ERROR_SYSCALL.
1721 */
Willy Tarreau3b2fdb62014-04-25 23:44:22 +02001722 ssl->max_send_fragment = 0;
Willy Tarreauf51c6982014-04-25 20:02:39 +02001723 SSLerr(SSL_F_TLS1_HEARTBEAT, SSL_R_SSL_HANDSHAKE_FAILURE);
1724 return;
1725 }
Emeric Brun29f037d2014-04-25 19:05:36 +02001726#endif
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001727 if (global_ssl.capture_cipherlist > 0)
1728 ssl_sock_parse_clienthello(write_p, version, content_type, buf, len, ssl);
Emeric Brun29f037d2014-04-25 19:05:36 +02001729}
1730
Bernard Spil13c53f82018-02-15 13:34:58 +01001731#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Olivier Houchardc7566002018-11-20 23:33:50 +01001732static int ssl_sock_srv_select_protos(SSL *s, unsigned char **out, unsigned char *outlen,
1733 const unsigned char *in, unsigned int inlen,
1734 void *arg)
1735{
1736 struct server *srv = arg;
1737
1738 if (SSL_select_next_proto(out, outlen, in, inlen, (unsigned char *)srv->ssl_ctx.npn_str,
1739 srv->ssl_ctx.npn_len) == OPENSSL_NPN_NEGOTIATED)
1740 return SSL_TLSEXT_ERR_OK;
1741 return SSL_TLSEXT_ERR_NOACK;
1742}
1743#endif
1744
1745#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02001746/* This callback is used so that the server advertises the list of
1747 * negociable protocols for NPN.
1748 */
1749static int ssl_sock_advertise_npn_protos(SSL *s, const unsigned char **data,
1750 unsigned int *len, void *arg)
1751{
Emmanuel Hocdet98263292016-12-29 18:26:15 +01001752 struct ssl_bind_conf *conf = arg;
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02001753
1754 *data = (const unsigned char *)conf->npn_str;
1755 *len = conf->npn_len;
1756 return SSL_TLSEXT_ERR_OK;
1757}
1758#endif
1759
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01001760#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02001761/* This callback is used so that the server advertises the list of
1762 * negociable protocols for ALPN.
1763 */
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01001764static int ssl_sock_advertise_alpn_protos(SSL *s, const unsigned char **out,
1765 unsigned char *outlen,
1766 const unsigned char *server,
1767 unsigned int server_len, void *arg)
Willy Tarreauab861d32013-04-02 02:30:41 +02001768{
Emmanuel Hocdet98263292016-12-29 18:26:15 +01001769 struct ssl_bind_conf *conf = arg;
Willy Tarreauab861d32013-04-02 02:30:41 +02001770
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01001771 if (SSL_select_next_proto((unsigned char**) out, outlen, (const unsigned char *)conf->alpn_str,
1772 conf->alpn_len, server, server_len) != OPENSSL_NPN_NEGOTIATED) {
1773 return SSL_TLSEXT_ERR_NOACK;
1774 }
Willy Tarreauab861d32013-04-02 02:30:41 +02001775 return SSL_TLSEXT_ERR_OK;
1776}
1777#endif
1778
Willy Tarreauc8ad3be2015-06-17 15:48:26 +02001779#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01001780#ifndef SSL_NO_GENERATE_CERTIFICATES
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001781
Christopher Faulet30548802015-06-11 13:39:32 +02001782/* Create a X509 certificate with the specified servername and serial. This
1783 * function returns a SSL_CTX object or NULL if an error occurs. */
Christopher Faulet7969a332015-10-09 11:15:03 +02001784static SSL_CTX *
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001785ssl_sock_do_create_cert(const char *servername, struct bind_conf *bind_conf, SSL *ssl)
Christopher Faulet31af49d2015-06-09 17:29:50 +02001786{
Christopher Faulet7969a332015-10-09 11:15:03 +02001787 X509 *cacert = bind_conf->ca_sign_cert;
1788 EVP_PKEY *capkey = bind_conf->ca_sign_pkey;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001789 SSL_CTX *ssl_ctx = NULL;
1790 X509 *newcrt = NULL;
1791 EVP_PKEY *pkey = NULL;
Emmanuel Hocdet15969292017-08-11 10:56:00 +02001792 SSL *tmp_ssl = NULL;
Emmanuel Hocdeta9b84022018-10-01 18:41:36 +02001793 CONF *ctmp = NULL;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001794 X509_NAME *name;
1795 const EVP_MD *digest;
1796 X509V3_CTX ctx;
1797 unsigned int i;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001798 int key_type;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001799
Christopher Faulet48a83322017-07-28 16:56:09 +02001800 /* Get the private key of the default certificate and use it */
Willy Tarreau5db847a2019-05-09 14:13:35 +02001801#if (HA_OPENSSL_VERSION_NUMBER >= 0x10002000L)
Emmanuel Hocdet15969292017-08-11 10:56:00 +02001802 pkey = SSL_CTX_get0_privatekey(bind_conf->default_ctx);
1803#else
1804 tmp_ssl = SSL_new(bind_conf->default_ctx);
1805 if (tmp_ssl)
1806 pkey = SSL_get_privatekey(tmp_ssl);
1807#endif
1808 if (!pkey)
Christopher Faulet31af49d2015-06-09 17:29:50 +02001809 goto mkcert_error;
1810
1811 /* Create the certificate */
1812 if (!(newcrt = X509_new()))
1813 goto mkcert_error;
1814
1815 /* Set version number for the certificate (X509v3) and the serial
1816 * number */
1817 if (X509_set_version(newcrt, 2L) != 1)
1818 goto mkcert_error;
Olivier Houchard2be5a4c2019-03-08 18:54:43 +01001819 ASN1_INTEGER_set(X509_get_serialNumber(newcrt), _HA_ATOMIC_ADD(&ssl_ctx_serial, 1));
Christopher Faulet31af49d2015-06-09 17:29:50 +02001820
1821 /* Set duration for the certificate */
Rosen Penev68185952018-12-14 08:47:02 -08001822 if (!X509_gmtime_adj(X509_getm_notBefore(newcrt), (long)-60*60*24) ||
1823 !X509_gmtime_adj(X509_getm_notAfter(newcrt),(long)60*60*24*365))
Christopher Faulet31af49d2015-06-09 17:29:50 +02001824 goto mkcert_error;
1825
1826 /* set public key in the certificate */
1827 if (X509_set_pubkey(newcrt, pkey) != 1)
1828 goto mkcert_error;
1829
1830 /* Set issuer name from the CA */
1831 if (!(name = X509_get_subject_name(cacert)))
1832 goto mkcert_error;
1833 if (X509_set_issuer_name(newcrt, name) != 1)
1834 goto mkcert_error;
1835
1836 /* Set the subject name using the same, but the CN */
1837 name = X509_NAME_dup(name);
1838 if (X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC,
1839 (const unsigned char *)servername,
1840 -1, -1, 0) != 1) {
1841 X509_NAME_free(name);
1842 goto mkcert_error;
1843 }
1844 if (X509_set_subject_name(newcrt, name) != 1) {
1845 X509_NAME_free(name);
1846 goto mkcert_error;
1847 }
1848 X509_NAME_free(name);
1849
1850 /* Add x509v3 extensions as specified */
Emmanuel Hocdeta9b84022018-10-01 18:41:36 +02001851 ctmp = NCONF_new(NULL);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001852 X509V3_set_ctx(&ctx, cacert, newcrt, NULL, NULL, 0);
1853 for (i = 0; i < X509V3_EXT_SIZE; i++) {
1854 X509_EXTENSION *ext;
1855
Emmanuel Hocdeta9b84022018-10-01 18:41:36 +02001856 if (!(ext = X509V3_EXT_nconf(ctmp, &ctx, x509v3_ext_names[i], x509v3_ext_values[i])))
Christopher Faulet31af49d2015-06-09 17:29:50 +02001857 goto mkcert_error;
1858 if (!X509_add_ext(newcrt, ext, -1)) {
1859 X509_EXTENSION_free(ext);
1860 goto mkcert_error;
1861 }
1862 X509_EXTENSION_free(ext);
1863 }
1864
1865 /* Sign the certificate with the CA private key */
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001866
1867 key_type = EVP_PKEY_base_id(capkey);
1868
1869 if (key_type == EVP_PKEY_DSA)
1870 digest = EVP_sha1();
1871 else if (key_type == EVP_PKEY_RSA)
Christopher Faulet31af49d2015-06-09 17:29:50 +02001872 digest = EVP_sha256();
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001873 else if (key_type == EVP_PKEY_EC)
Christopher Faulet7969a332015-10-09 11:15:03 +02001874 digest = EVP_sha256();
1875 else {
Willy Tarreau9a1ab082019-05-09 13:26:41 +02001876#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000000fL) && !defined(OPENSSL_IS_BORINGSSL)
Christopher Faulet7969a332015-10-09 11:15:03 +02001877 int nid;
1878
1879 if (EVP_PKEY_get_default_digest_nid(capkey, &nid) <= 0)
1880 goto mkcert_error;
1881 if (!(digest = EVP_get_digestbynid(nid)))
1882 goto mkcert_error;
Christopher Faulete7db2162015-10-19 13:59:24 +02001883#else
1884 goto mkcert_error;
1885#endif
Christopher Faulet7969a332015-10-09 11:15:03 +02001886 }
1887
Christopher Faulet31af49d2015-06-09 17:29:50 +02001888 if (!(X509_sign(newcrt, capkey, digest)))
1889 goto mkcert_error;
1890
1891 /* Create and set the new SSL_CTX */
1892 if (!(ssl_ctx = SSL_CTX_new(SSLv23_server_method())))
1893 goto mkcert_error;
1894 if (!SSL_CTX_use_PrivateKey(ssl_ctx, pkey))
1895 goto mkcert_error;
1896 if (!SSL_CTX_use_certificate(ssl_ctx, newcrt))
1897 goto mkcert_error;
1898 if (!SSL_CTX_check_private_key(ssl_ctx))
1899 goto mkcert_error;
1900
1901 if (newcrt) X509_free(newcrt);
Christopher Faulet7969a332015-10-09 11:15:03 +02001902
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01001903#ifndef OPENSSL_NO_DH
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001904 SSL_CTX_set_tmp_dh_callback(ssl_ctx, ssl_get_tmp_dh);
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01001905#endif
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001906#if defined(SSL_CTX_set_tmp_ecdh) && !defined(OPENSSL_NO_ECDH)
1907 {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01001908 const char *ecdhe = (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe : ECDHE_DEFAULT_CURVE);
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001909 EC_KEY *ecc;
1910 int nid;
1911
1912 if ((nid = OBJ_sn2nid(ecdhe)) == NID_undef)
1913 goto end;
1914 if (!(ecc = EC_KEY_new_by_curve_name(nid)))
1915 goto end;
1916 SSL_CTX_set_tmp_ecdh(ssl_ctx, ecc);
1917 EC_KEY_free(ecc);
1918 }
1919#endif
1920 end:
Christopher Faulet31af49d2015-06-09 17:29:50 +02001921 return ssl_ctx;
1922
1923 mkcert_error:
Emmanuel Hocdeta9b84022018-10-01 18:41:36 +02001924 if (ctmp) NCONF_free(ctmp);
Emmanuel Hocdet15969292017-08-11 10:56:00 +02001925 if (tmp_ssl) SSL_free(tmp_ssl);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001926 if (ssl_ctx) SSL_CTX_free(ssl_ctx);
1927 if (newcrt) X509_free(newcrt);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001928 return NULL;
1929}
1930
Christopher Faulet7969a332015-10-09 11:15:03 +02001931SSL_CTX *
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001932ssl_sock_create_cert(struct connection *conn, const char *servername, unsigned int key)
Christopher Faulet7969a332015-10-09 11:15:03 +02001933{
Willy Tarreau07d94e42018-09-20 10:57:52 +02001934 struct bind_conf *bind_conf = __objt_listener(conn->target)->bind_conf;
Olivier Houchard66ab4982019-02-26 18:37:15 +01001935 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001936
Olivier Houchard66ab4982019-02-26 18:37:15 +01001937 return ssl_sock_do_create_cert(servername, bind_conf, ctx->ssl);
Christopher Faulet7969a332015-10-09 11:15:03 +02001938}
1939
Christopher Faulet30548802015-06-11 13:39:32 +02001940/* Do a lookup for a certificate in the LRU cache used to store generated
Emeric Brun821bb9b2017-06-15 16:37:39 +02001941 * certificates and immediately assign it to the SSL session if not null. */
Christopher Faulet30548802015-06-11 13:39:32 +02001942SSL_CTX *
Emeric Brun821bb9b2017-06-15 16:37:39 +02001943ssl_sock_assign_generated_cert(unsigned int key, struct bind_conf *bind_conf, SSL *ssl)
Christopher Faulet30548802015-06-11 13:39:32 +02001944{
1945 struct lru64 *lru = NULL;
1946
1947 if (ssl_ctx_lru_tree) {
Willy Tarreau03f4ec42018-05-17 10:56:47 +02001948 HA_RWLOCK_WRLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001949 lru = lru64_lookup(key, ssl_ctx_lru_tree, bind_conf->ca_sign_cert, 0);
Emeric Brun821bb9b2017-06-15 16:37:39 +02001950 if (lru && lru->domain) {
1951 if (ssl)
1952 SSL_set_SSL_CTX(ssl, (SSL_CTX *)lru->data);
Willy Tarreau03f4ec42018-05-17 10:56:47 +02001953 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet30548802015-06-11 13:39:32 +02001954 return (SSL_CTX *)lru->data;
Emeric Brun821bb9b2017-06-15 16:37:39 +02001955 }
Willy Tarreau03f4ec42018-05-17 10:56:47 +02001956 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet30548802015-06-11 13:39:32 +02001957 }
1958 return NULL;
1959}
1960
Emeric Brun821bb9b2017-06-15 16:37:39 +02001961/* Same as <ssl_sock_assign_generated_cert> but without SSL session. This
1962 * function is not thread-safe, it should only be used to check if a certificate
1963 * exists in the lru cache (with no warranty it will not be removed by another
1964 * thread). It is kept for backward compatibility. */
1965SSL_CTX *
1966ssl_sock_get_generated_cert(unsigned int key, struct bind_conf *bind_conf)
1967{
1968 return ssl_sock_assign_generated_cert(key, bind_conf, NULL);
1969}
1970
Christopher Fauletd2cab922015-07-28 16:03:47 +02001971/* Set a certificate int the LRU cache used to store generated
1972 * certificate. Return 0 on success, otherwise -1 */
1973int
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001974ssl_sock_set_generated_cert(SSL_CTX *ssl_ctx, unsigned int key, struct bind_conf *bind_conf)
Christopher Faulet30548802015-06-11 13:39:32 +02001975{
1976 struct lru64 *lru = NULL;
1977
1978 if (ssl_ctx_lru_tree) {
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001979 HA_RWLOCK_WRLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001980 lru = lru64_get(key, ssl_ctx_lru_tree, bind_conf->ca_sign_cert, 0);
Emeric Brun821bb9b2017-06-15 16:37:39 +02001981 if (!lru) {
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001982 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Fauletd2cab922015-07-28 16:03:47 +02001983 return -1;
Emeric Brun821bb9b2017-06-15 16:37:39 +02001984 }
Christopher Faulet30548802015-06-11 13:39:32 +02001985 if (lru->domain && lru->data)
1986 lru->free((SSL_CTX *)lru->data);
Christopher Faulet7969a332015-10-09 11:15:03 +02001987 lru64_commit(lru, ssl_ctx, bind_conf->ca_sign_cert, 0, (void (*)(void *))SSL_CTX_free);
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001988 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Fauletd2cab922015-07-28 16:03:47 +02001989 return 0;
Christopher Faulet30548802015-06-11 13:39:32 +02001990 }
Christopher Fauletd2cab922015-07-28 16:03:47 +02001991 return -1;
Christopher Faulet30548802015-06-11 13:39:32 +02001992}
1993
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001994/* Compute the key of the certificate. */
Christopher Faulet30548802015-06-11 13:39:32 +02001995unsigned int
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001996ssl_sock_generated_cert_key(const void *data, size_t len)
Christopher Faulet30548802015-06-11 13:39:32 +02001997{
1998 return XXH32(data, len, ssl_ctx_lru_seed);
1999}
2000
Willy Tarreau2f63ef42015-10-20 15:16:01 +02002001/* Generate a cert and immediately assign it to the SSL session so that the cert's
2002 * refcount is maintained regardless of the cert's presence in the LRU cache.
2003 */
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002004static int
Christopher Faulet7969a332015-10-09 11:15:03 +02002005ssl_sock_generate_certificate(const char *servername, struct bind_conf *bind_conf, SSL *ssl)
Christopher Faulet31af49d2015-06-09 17:29:50 +02002006{
2007 X509 *cacert = bind_conf->ca_sign_cert;
Christopher Faulet31af49d2015-06-09 17:29:50 +02002008 SSL_CTX *ssl_ctx = NULL;
2009 struct lru64 *lru = NULL;
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002010 unsigned int key;
Christopher Faulet31af49d2015-06-09 17:29:50 +02002011
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002012 key = ssl_sock_generated_cert_key(servername, strlen(servername));
Christopher Faulet31af49d2015-06-09 17:29:50 +02002013 if (ssl_ctx_lru_tree) {
Christopher Faulet2a944ee2017-11-07 10:42:54 +01002014 HA_RWLOCK_WRLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002015 lru = lru64_get(key, ssl_ctx_lru_tree, cacert, 0);
Christopher Faulet31af49d2015-06-09 17:29:50 +02002016 if (lru && lru->domain)
2017 ssl_ctx = (SSL_CTX *)lru->data;
Christopher Fauletd2cab922015-07-28 16:03:47 +02002018 if (!ssl_ctx && lru) {
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002019 ssl_ctx = ssl_sock_do_create_cert(servername, bind_conf, ssl);
Christopher Faulet31af49d2015-06-09 17:29:50 +02002020 lru64_commit(lru, ssl_ctx, cacert, 0, (void (*)(void *))SSL_CTX_free);
Christopher Fauletd2cab922015-07-28 16:03:47 +02002021 }
Willy Tarreau2f63ef42015-10-20 15:16:01 +02002022 SSL_set_SSL_CTX(ssl, ssl_ctx);
Christopher Faulet2a944ee2017-11-07 10:42:54 +01002023 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002024 return 1;
Christopher Faulet31af49d2015-06-09 17:29:50 +02002025 }
Willy Tarreau2f63ef42015-10-20 15:16:01 +02002026 else {
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002027 ssl_ctx = ssl_sock_do_create_cert(servername, bind_conf, ssl);
Willy Tarreau2f63ef42015-10-20 15:16:01 +02002028 SSL_set_SSL_CTX(ssl, ssl_ctx);
2029 /* No LRU cache, this CTX will be released as soon as the session dies */
2030 SSL_CTX_free(ssl_ctx);
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002031 return 1;
Willy Tarreau2f63ef42015-10-20 15:16:01 +02002032 }
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002033 return 0;
2034}
2035static int
2036ssl_sock_generate_certificate_from_conn(struct bind_conf *bind_conf, SSL *ssl)
2037{
2038 unsigned int key;
Thierry FOURNIER28962c92018-06-17 21:37:05 +02002039 struct connection *conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002040
Willy Tarreauf5bdb642019-07-17 11:29:32 +02002041 if (conn_get_dst(conn)) {
Willy Tarreau085a1512019-07-17 14:47:35 +02002042 key = ssl_sock_generated_cert_key(conn->dst, get_addr_len(conn->dst));
Emeric Brun821bb9b2017-06-15 16:37:39 +02002043 if (ssl_sock_assign_generated_cert(key, bind_conf, ssl))
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002044 return 1;
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002045 }
2046 return 0;
Christopher Faulet31af49d2015-06-09 17:29:50 +02002047}
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002048#endif /* !defined SSL_NO_GENERATE_CERTIFICATES */
Christopher Faulet31af49d2015-06-09 17:29:50 +02002049
Willy Tarreau9a1ab082019-05-09 13:26:41 +02002050#if (HA_OPENSSL_VERSION_NUMBER < 0x1010000fL)
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002051typedef enum { SET_CLIENT, SET_SERVER } set_context_func;
2052
2053static void ctx_set_SSLv3_func(SSL_CTX *ctx, set_context_func c)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002054{
Emmanuel Hocdet23877ab2017-07-12 12:53:02 +02002055#if SSL_OP_NO_SSLv3
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002056 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, SSLv3_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002057 : SSL_CTX_set_ssl_version(ctx, SSLv3_client_method());
2058#endif
2059}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002060static void ctx_set_TLSv10_func(SSL_CTX *ctx, set_context_func c) {
2061 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, TLSv1_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002062 : SSL_CTX_set_ssl_version(ctx, TLSv1_client_method());
2063}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002064static void ctx_set_TLSv11_func(SSL_CTX *ctx, set_context_func c) {
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002065#if SSL_OP_NO_TLSv1_1
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002066 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, TLSv1_1_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002067 : SSL_CTX_set_ssl_version(ctx, TLSv1_1_client_method());
2068#endif
2069}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002070static void ctx_set_TLSv12_func(SSL_CTX *ctx, set_context_func c) {
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002071#if SSL_OP_NO_TLSv1_2
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002072 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, TLSv1_2_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002073 : SSL_CTX_set_ssl_version(ctx, TLSv1_2_client_method());
2074#endif
2075}
Bertrand Jacquina25282b2018-08-14 00:56:13 +01002076/* TLSv1.2 is the last supported version in this context. */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002077static void ctx_set_TLSv13_func(SSL_CTX *ctx, set_context_func c) {}
2078/* Unusable in this context. */
2079static void ssl_set_SSLv3_func(SSL *ssl, set_context_func c) {}
2080static void ssl_set_TLSv10_func(SSL *ssl, set_context_func c) {}
2081static void ssl_set_TLSv11_func(SSL *ssl, set_context_func c) {}
2082static void ssl_set_TLSv12_func(SSL *ssl, set_context_func c) {}
2083static void ssl_set_TLSv13_func(SSL *ssl, set_context_func c) {}
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002084#else /* openssl >= 1.1.0 */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002085typedef enum { SET_MIN, SET_MAX } set_context_func;
2086
2087static void ctx_set_SSLv3_func(SSL_CTX *ctx, set_context_func c) {
2088 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, SSL3_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002089 : SSL_CTX_set_min_proto_version(ctx, SSL3_VERSION);
2090}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002091static void ssl_set_SSLv3_func(SSL *ssl, set_context_func c) {
2092 c == SET_MAX ? SSL_set_max_proto_version(ssl, SSL3_VERSION)
2093 : SSL_set_min_proto_version(ssl, SSL3_VERSION);
2094}
2095static void ctx_set_TLSv10_func(SSL_CTX *ctx, set_context_func c) {
2096 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002097 : SSL_CTX_set_min_proto_version(ctx, TLS1_VERSION);
2098}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002099static void ssl_set_TLSv10_func(SSL *ssl, set_context_func c) {
2100 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_VERSION)
2101 : SSL_set_min_proto_version(ssl, TLS1_VERSION);
2102}
2103static void ctx_set_TLSv11_func(SSL_CTX *ctx, set_context_func c) {
2104 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_1_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002105 : SSL_CTX_set_min_proto_version(ctx, TLS1_1_VERSION);
2106}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002107static void ssl_set_TLSv11_func(SSL *ssl, set_context_func c) {
2108 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_1_VERSION)
2109 : SSL_set_min_proto_version(ssl, TLS1_1_VERSION);
2110}
2111static void ctx_set_TLSv12_func(SSL_CTX *ctx, set_context_func c) {
2112 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_2_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002113 : SSL_CTX_set_min_proto_version(ctx, TLS1_2_VERSION);
2114}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002115static void ssl_set_TLSv12_func(SSL *ssl, set_context_func c) {
2116 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_2_VERSION)
2117 : SSL_set_min_proto_version(ssl, TLS1_2_VERSION);
2118}
2119static void ctx_set_TLSv13_func(SSL_CTX *ctx, set_context_func c) {
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002120#if SSL_OP_NO_TLSv1_3
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002121 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_3_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002122 : SSL_CTX_set_min_proto_version(ctx, TLS1_3_VERSION);
2123#endif
2124}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002125static void ssl_set_TLSv13_func(SSL *ssl, set_context_func c) {
2126#if SSL_OP_NO_TLSv1_3
2127 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_3_VERSION)
2128 : SSL_set_min_proto_version(ssl, TLS1_3_VERSION);
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002129#endif
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002130}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002131#endif
2132static void ctx_set_None_func(SSL_CTX *ctx, set_context_func c) { }
2133static void ssl_set_None_func(SSL *ssl, set_context_func c) { }
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002134
2135static struct {
2136 int option;
2137 uint16_t flag;
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002138 void (*ctx_set_version)(SSL_CTX *, set_context_func);
2139 void (*ssl_set_version)(SSL *, set_context_func);
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002140 const char *name;
2141} methodVersions[] = {
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002142 {0, 0, ctx_set_None_func, ssl_set_None_func, "NONE"}, /* CONF_TLSV_NONE */
2143 {SSL_OP_NO_SSLv3, MC_SSL_O_NO_SSLV3, ctx_set_SSLv3_func, ssl_set_SSLv3_func, "SSLv3"}, /* CONF_SSLV3 */
2144 {SSL_OP_NO_TLSv1, MC_SSL_O_NO_TLSV10, ctx_set_TLSv10_func, ssl_set_TLSv10_func, "TLSv1.0"}, /* CONF_TLSV10 */
2145 {SSL_OP_NO_TLSv1_1, MC_SSL_O_NO_TLSV11, ctx_set_TLSv11_func, ssl_set_TLSv11_func, "TLSv1.1"}, /* CONF_TLSV11 */
2146 {SSL_OP_NO_TLSv1_2, MC_SSL_O_NO_TLSV12, ctx_set_TLSv12_func, ssl_set_TLSv12_func, "TLSv1.2"}, /* CONF_TLSV12 */
2147 {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 +02002148};
2149
Emmanuel Hocdet530141f2017-03-01 18:54:56 +01002150static void ssl_sock_switchctx_set(SSL *ssl, SSL_CTX *ctx)
2151{
2152 SSL_set_verify(ssl, SSL_CTX_get_verify_mode(ctx), ssl_sock_bind_verifycbk);
2153 SSL_set_client_CA_list(ssl, SSL_dup_CA_list(SSL_CTX_get_client_CA_list(ctx)));
2154 SSL_set_SSL_CTX(ssl, ctx);
2155}
2156
Willy Tarreau5db847a2019-05-09 14:13:35 +02002157#if ((HA_OPENSSL_VERSION_NUMBER >= 0x10101000L) || defined(OPENSSL_IS_BORINGSSL))
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002158
2159static int ssl_sock_switchctx_err_cbk(SSL *ssl, int *al, void *priv)
2160{
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002161 struct bind_conf *s = priv;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002162 (void)al; /* shut gcc stupid warning */
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002163
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002164 if (SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name) || s->generate_certs)
2165 return SSL_TLSEXT_ERR_OK;
2166 return SSL_TLSEXT_ERR_NOACK;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002167}
2168
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002169#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002170static int ssl_sock_switchctx_cbk(const struct ssl_early_callback_ctx *ctx)
2171{
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002172 SSL *ssl = ctx->ssl;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002173#else
2174static int ssl_sock_switchctx_cbk(SSL *ssl, int *al, void *arg)
2175{
2176#endif
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002177 struct connection *conn;
2178 struct bind_conf *s;
2179 const uint8_t *extension_data;
2180 size_t extension_len;
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002181 int has_rsa_sig = 0, has_ecdsa_sig = 0;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002182
2183 char *wildp = NULL;
2184 const uint8_t *servername;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002185 size_t servername_len;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002186 struct ebmb_node *node, *n, *node_ecdsa = NULL, *node_rsa = NULL, *node_anonymous = NULL;
Olivier Houchardc2aae742017-09-22 18:26:28 +02002187 int allow_early = 0;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002188 int i;
2189
Thierry FOURNIER28962c92018-06-17 21:37:05 +02002190 conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Willy Tarreaua8825522018-10-15 13:20:07 +02002191 s = __objt_listener(conn->target)->bind_conf;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002192
Olivier Houchard9679ac92017-10-27 14:58:08 +02002193 if (s->ssl_conf.early_data)
Olivier Houchardc2aae742017-09-22 18:26:28 +02002194 allow_early = 1;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002195#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002196 if (SSL_early_callback_ctx_extension_get(ctx, TLSEXT_TYPE_server_name,
2197 &extension_data, &extension_len)) {
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002198#else
2199 if (SSL_client_hello_get0_ext(ssl, TLSEXT_TYPE_server_name, &extension_data, &extension_len)) {
2200#endif
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002201 /*
2202 * The server_name extension was given too much extensibility when it
2203 * was written, so parsing the normal case is a bit complex.
2204 */
2205 size_t len;
2206 if (extension_len <= 2)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002207 goto abort;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002208 /* Extract the length of the supplied list of names. */
2209 len = (*extension_data++) << 8;
2210 len |= *extension_data++;
2211 if (len + 2 != extension_len)
2212 goto abort;
2213 /*
2214 * The list in practice only has a single element, so we only consider
2215 * the first one.
2216 */
2217 if (len == 0 || *extension_data++ != TLSEXT_NAMETYPE_host_name)
2218 goto abort;
2219 extension_len = len - 1;
2220 /* Now we can finally pull out the byte array with the actual hostname. */
2221 if (extension_len <= 2)
2222 goto abort;
2223 len = (*extension_data++) << 8;
2224 len |= *extension_data++;
2225 if (len == 0 || len + 2 > extension_len || len > TLSEXT_MAXLEN_host_name
2226 || memchr(extension_data, 0, len) != NULL)
2227 goto abort;
2228 servername = extension_data;
2229 servername_len = len;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002230 } else {
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002231#if (!defined SSL_NO_GENERATE_CERTIFICATES)
2232 if (s->generate_certs && ssl_sock_generate_certificate_from_conn(s, ssl)) {
Olivier Houchardc2aae742017-09-22 18:26:28 +02002233 goto allow_early;
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002234 }
2235#endif
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002236 /* without SNI extension, is the default_ctx (need SSL_TLSEXT_ERR_NOACK) */
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002237 if (!s->strict_sni) {
William Lallemand21724f02019-11-04 17:56:13 +01002238 HA_RWLOCK_RDLOCK(SNI_LOCK, &s->sni_lock);
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002239 ssl_sock_switchctx_set(ssl, s->default_ctx);
William Lallemand21724f02019-11-04 17:56:13 +01002240 HA_RWLOCK_RDUNLOCK(SNI_LOCK, &s->sni_lock);
Olivier Houchardc2aae742017-09-22 18:26:28 +02002241 goto allow_early;
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002242 }
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002243 goto abort;
2244 }
2245
2246 /* extract/check clientHello informations */
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002247#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002248 if (SSL_early_callback_ctx_extension_get(ctx, TLSEXT_TYPE_signature_algorithms, &extension_data, &extension_len)) {
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002249#else
2250 if (SSL_client_hello_get0_ext(ssl, TLSEXT_TYPE_signature_algorithms, &extension_data, &extension_len)) {
2251#endif
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002252 uint8_t sign;
2253 size_t len;
2254 if (extension_len < 2)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002255 goto abort;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002256 len = (*extension_data++) << 8;
2257 len |= *extension_data++;
2258 if (len + 2 != extension_len)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002259 goto abort;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002260 if (len % 2 != 0)
2261 goto abort;
2262 for (; len > 0; len -= 2) {
2263 extension_data++; /* hash */
2264 sign = *extension_data++;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002265 switch (sign) {
2266 case TLSEXT_signature_rsa:
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002267 has_rsa_sig = 1;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002268 break;
2269 case TLSEXT_signature_ecdsa:
2270 has_ecdsa_sig = 1;
2271 break;
2272 default:
2273 continue;
2274 }
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002275 if (has_ecdsa_sig && has_rsa_sig)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002276 break;
2277 }
2278 } else {
Bertrand Jacquina25282b2018-08-14 00:56:13 +01002279 /* without TLSEXT_TYPE_signature_algorithms extension (< TLSv1.2) */
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002280 has_rsa_sig = 1;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002281 }
2282 if (has_ecdsa_sig) { /* in very rare case: has ecdsa sign but not a ECDSA cipher */
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002283 const SSL_CIPHER *cipher;
2284 size_t len;
2285 const uint8_t *cipher_suites;
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002286 has_ecdsa_sig = 0;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002287#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002288 len = ctx->cipher_suites_len;
2289 cipher_suites = ctx->cipher_suites;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002290#else
2291 len = SSL_client_hello_get0_ciphers(ssl, &cipher_suites);
2292#endif
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002293 if (len % 2 != 0)
2294 goto abort;
2295 for (; len != 0; len -= 2, cipher_suites += 2) {
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002296#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002297 uint16_t cipher_suite = (cipher_suites[0] << 8) | cipher_suites[1];
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002298 cipher = SSL_get_cipher_by_value(cipher_suite);
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002299#else
2300 cipher = SSL_CIPHER_find(ssl, cipher_suites);
2301#endif
Emmanuel Hocdet019f9b12017-10-02 17:12:06 +02002302 if (cipher && SSL_CIPHER_get_auth_nid(cipher) == NID_auth_ecdsa) {
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002303 has_ecdsa_sig = 1;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002304 break;
2305 }
2306 }
2307 }
2308
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002309 for (i = 0; i < trash.size && i < servername_len; i++) {
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002310 trash.area[i] = tolower(servername[i]);
2311 if (!wildp && (trash.area[i] == '.'))
2312 wildp = &trash.area[i];
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002313 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002314 trash.area[i] = 0;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002315
William Lallemand150bfa82019-09-19 17:12:49 +02002316 HA_RWLOCK_RDLOCK(SNI_LOCK, &s->sni_lock);
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002317 /* lookup in full qualified names */
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002318 node = ebst_lookup(&s->sni_ctx, trash.area);
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002319
2320 /* lookup a not neg filter */
2321 for (n = node; n; n = ebmb_next_dup(n)) {
2322 if (!container_of(n, struct sni_ctx, name)->neg) {
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002323 switch(container_of(n, struct sni_ctx, name)->kinfo.sig) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002324 case TLSEXT_signature_ecdsa:
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002325 if (!node_ecdsa)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002326 node_ecdsa = n;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002327 break;
2328 case TLSEXT_signature_rsa:
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002329 if (!node_rsa)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002330 node_rsa = n;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002331 break;
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002332 default: /* TLSEXT_signature_anonymous|dsa */
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002333 if (!node_anonymous)
2334 node_anonymous = n;
2335 break;
2336 }
2337 }
2338 }
2339 if (wildp) {
2340 /* lookup in wildcards names */
2341 node = ebst_lookup(&s->sni_w_ctx, wildp);
2342 for (n = node; n; n = ebmb_next_dup(n)) {
2343 if (!container_of(n, struct sni_ctx, name)->neg) {
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002344 switch(container_of(n, struct sni_ctx, name)->kinfo.sig) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002345 case TLSEXT_signature_ecdsa:
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002346 if (!node_ecdsa)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002347 node_ecdsa = n;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002348 break;
2349 case TLSEXT_signature_rsa:
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002350 if (!node_rsa)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002351 node_rsa = n;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002352 break;
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002353 default: /* TLSEXT_signature_anonymous|dsa */
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002354 if (!node_anonymous)
2355 node_anonymous = n;
2356 break;
2357 }
2358 }
2359 }
2360 }
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002361 /* select by key_signature priority order */
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002362 node = (has_ecdsa_sig && node_ecdsa) ? node_ecdsa
2363 : ((has_rsa_sig && node_rsa) ? node_rsa
2364 : (node_anonymous ? node_anonymous
2365 : (node_ecdsa ? node_ecdsa /* no ecdsa signature case (< TLSv1.2) */
2366 : node_rsa /* no rsa signature case (far far away) */
2367 )));
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002368 if (node) {
2369 /* switch ctx */
Emmanuel Hocdet43664762017-08-09 18:26:20 +02002370 struct ssl_bind_conf *conf = container_of(node, struct sni_ctx, name)->conf;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002371 ssl_sock_switchctx_set(ssl, container_of(node, struct sni_ctx, name)->ctx);
Olivier Houchard35a63cc2017-11-02 19:04:38 +01002372 if (conf) {
2373 methodVersions[conf->ssl_methods.min].ssl_set_version(ssl, SET_MIN);
2374 methodVersions[conf->ssl_methods.max].ssl_set_version(ssl, SET_MAX);
2375 if (conf->early_data)
2376 allow_early = 1;
2377 }
William Lallemand02010472019-10-18 11:02:19 +02002378 HA_RWLOCK_RDUNLOCK(SNI_LOCK, &s->sni_lock);
Olivier Houchard35a63cc2017-11-02 19:04:38 +01002379 goto allow_early;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002380 }
William Lallemand150bfa82019-09-19 17:12:49 +02002381
William Lallemand02010472019-10-18 11:02:19 +02002382 HA_RWLOCK_RDUNLOCK(SNI_LOCK, &s->sni_lock);
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002383#if (!defined SSL_NO_GENERATE_CERTIFICATES)
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002384 if (s->generate_certs && ssl_sock_generate_certificate(trash.area, s, ssl)) {
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002385 /* switch ctx done in ssl_sock_generate_certificate */
Olivier Houchardc2aae742017-09-22 18:26:28 +02002386 goto allow_early;
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002387 }
2388#endif
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002389 if (!s->strict_sni) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002390 /* no certificate match, is the default_ctx */
William Lallemand21724f02019-11-04 17:56:13 +01002391 HA_RWLOCK_RDLOCK(SNI_LOCK, &s->sni_lock);
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002392 ssl_sock_switchctx_set(ssl, s->default_ctx);
William Lallemand21724f02019-11-04 17:56:13 +01002393 HA_RWLOCK_RDUNLOCK(SNI_LOCK, &s->sni_lock);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002394 }
Olivier Houchardc2aae742017-09-22 18:26:28 +02002395allow_early:
2396#ifdef OPENSSL_IS_BORINGSSL
2397 if (allow_early)
2398 SSL_set_early_data_enabled(ssl, 1);
2399#else
2400 if (!allow_early)
2401 SSL_set_max_early_data(ssl, 0);
2402#endif
2403 return 1;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002404 abort:
2405 /* abort handshake (was SSL_TLSEXT_ERR_ALERT_FATAL) */
2406 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002407#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002408 return ssl_select_cert_error;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002409#else
2410 *al = SSL_AD_UNRECOGNIZED_NAME;
2411 return 0;
2412#endif
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002413}
2414
2415#else /* OPENSSL_IS_BORINGSSL */
2416
Emeric Brunfc0421f2012-09-07 17:30:07 +02002417/* Sets the SSL ctx of <ssl> to match the advertised server name. Returns a
2418 * warning when no match is found, which implies the default (first) cert
2419 * will keep being used.
2420 */
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002421static int ssl_sock_switchctx_cbk(SSL *ssl, int *al, void *priv)
Emeric Brunfc0421f2012-09-07 17:30:07 +02002422{
2423 const char *servername;
2424 const char *wildp = NULL;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002425 struct ebmb_node *node, *n;
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002426 struct bind_conf *s = priv;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002427 int i;
2428 (void)al; /* shut gcc stupid warning */
2429
2430 servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
Emmanuel Hocdet65623372013-01-24 17:17:15 +01002431 if (!servername) {
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002432#if (!defined SSL_NO_GENERATE_CERTIFICATES)
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002433 if (s->generate_certs && ssl_sock_generate_certificate_from_conn(s, ssl))
2434 return SSL_TLSEXT_ERR_OK;
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002435#endif
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002436 if (s->strict_sni)
2437 return SSL_TLSEXT_ERR_ALERT_FATAL;
William Lallemand21724f02019-11-04 17:56:13 +01002438 HA_RWLOCK_RDLOCK(SNI_LOCK, &s->sni_lock);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002439 ssl_sock_switchctx_set(ssl, s->default_ctx);
William Lallemand21724f02019-11-04 17:56:13 +01002440 HA_RWLOCK_RDUNLOCK(SNI_LOCK, &s->sni_lock);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002441 return SSL_TLSEXT_ERR_NOACK;
Emmanuel Hocdet65623372013-01-24 17:17:15 +01002442 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02002443
Willy Tarreau19d14ef2012-10-29 16:51:55 +01002444 for (i = 0; i < trash.size; i++) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02002445 if (!servername[i])
2446 break;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002447 trash.area[i] = tolower(servername[i]);
2448 if (!wildp && (trash.area[i] == '.'))
2449 wildp = &trash.area[i];
Emeric Brunfc0421f2012-09-07 17:30:07 +02002450 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002451 trash.area[i] = 0;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002452
William Lallemand150bfa82019-09-19 17:12:49 +02002453 HA_RWLOCK_RDLOCK(SNI_LOCK, &s->sni_lock);
Emmanuel Hocdetc5fdf0f2019-11-04 15:49:46 +01002454 node = NULL;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002455 /* lookup in full qualified names */
Emmanuel Hocdetc5fdf0f2019-11-04 15:49:46 +01002456 for (n = ebst_lookup(&s->sni_ctx, trash.area); n; n = ebmb_next_dup(n)) {
2457 /* lookup a not neg filter */
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002458 if (!container_of(n, struct sni_ctx, name)->neg) {
2459 node = n;
2460 break;
Emmanuel Hocdet65623372013-01-24 17:17:15 +01002461 }
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002462 }
2463 if (!node && wildp) {
2464 /* lookup in wildcards names */
Emmanuel Hocdetc5fdf0f2019-11-04 15:49:46 +01002465 for (n = ebst_lookup(&s->sni_w_ctx, wildp); n; n = ebmb_next_dup(n)) {
2466 /* lookup a not neg filter */
2467 if (!container_of(n, struct sni_ctx, name)->neg) {
2468 node = n;
2469 break;
2470 }
2471 }
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002472 }
Emmanuel Hocdetc5fdf0f2019-11-04 15:49:46 +01002473 if (!node) {
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002474#if (!defined SSL_NO_GENERATE_CERTIFICATES)
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002475 if (s->generate_certs && ssl_sock_generate_certificate(servername, s, ssl)) {
2476 /* switch ctx done in ssl_sock_generate_certificate */
William Lallemand150bfa82019-09-19 17:12:49 +02002477 HA_RWLOCK_RDUNLOCK(SNI_LOCK, &s->sni_lock);
Christopher Faulet31af49d2015-06-09 17:29:50 +02002478 return SSL_TLSEXT_ERR_OK;
2479 }
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002480#endif
William Lallemand21724f02019-11-04 17:56:13 +01002481 if (s->strict_sni) {
2482 HA_RWLOCK_RDUNLOCK(SNI_LOCK, &s->sni_lock);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002483 return SSL_TLSEXT_ERR_ALERT_FATAL;
William Lallemand21724f02019-11-04 17:56:13 +01002484 }
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002485 ssl_sock_switchctx_set(ssl, s->default_ctx);
William Lallemand21724f02019-11-04 17:56:13 +01002486 HA_RWLOCK_RDUNLOCK(SNI_LOCK, &s->sni_lock);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002487 return SSL_TLSEXT_ERR_OK;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002488 }
2489
2490 /* switch ctx */
Emmanuel Hocdet530141f2017-03-01 18:54:56 +01002491 ssl_sock_switchctx_set(ssl, container_of(node, struct sni_ctx, name)->ctx);
William Lallemand150bfa82019-09-19 17:12:49 +02002492 HA_RWLOCK_RDUNLOCK(SNI_LOCK, &s->sni_lock);
Emeric Brunfc0421f2012-09-07 17:30:07 +02002493 return SSL_TLSEXT_ERR_OK;
2494}
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002495#endif /* (!) OPENSSL_IS_BORINGSSL */
Emeric Brunfc0421f2012-09-07 17:30:07 +02002496#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
2497
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002498#ifndef OPENSSL_NO_DH
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002499
2500static DH * ssl_get_dh_1024(void)
2501{
Remi Gacogned3a341a2015-05-29 16:26:17 +02002502 static unsigned char dh1024_p[]={
2503 0xFA,0xF9,0x2A,0x22,0x2A,0xA7,0x7F,0xE1,0x67,0x4E,0x53,0xF7,
2504 0x56,0x13,0xC3,0xB1,0xE3,0x29,0x6B,0x66,0x31,0x6A,0x7F,0xB3,
2505 0xC2,0x68,0x6B,0xCB,0x1D,0x57,0x39,0x1D,0x1F,0xFF,0x1C,0xC9,
2506 0xA6,0xA4,0x98,0x82,0x31,0x5D,0x25,0xFF,0x8A,0xE0,0x73,0x96,
2507 0x81,0xC8,0x83,0x79,0xC1,0x5A,0x04,0xF8,0x37,0x0D,0xA8,0x3D,
2508 0xAE,0x74,0xBC,0xDB,0xB6,0xA4,0x75,0xD9,0x71,0x8A,0xA0,0x17,
2509 0x9E,0x2D,0xC8,0xA8,0xDF,0x2C,0x5F,0x82,0x95,0xF8,0x92,0x9B,
2510 0xA7,0x33,0x5F,0x89,0x71,0xC8,0x2D,0x6B,0x18,0x86,0xC4,0x94,
2511 0x22,0xA5,0x52,0x8D,0xF6,0xF6,0xD2,0x37,0x92,0x0F,0xA5,0xCC,
2512 0xDB,0x7B,0x1D,0x3D,0xA1,0x31,0xB7,0x80,0x8F,0x0B,0x67,0x5E,
2513 0x36,0xA5,0x60,0x0C,0xF1,0x95,0x33,0x8B,
2514 };
2515 static unsigned char dh1024_g[]={
2516 0x02,
2517 };
2518
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002519 BIGNUM *p;
2520 BIGNUM *g;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002521 DH *dh = DH_new();
2522 if (dh) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002523 p = BN_bin2bn(dh1024_p, sizeof dh1024_p, NULL);
2524 g = BN_bin2bn(dh1024_g, sizeof dh1024_g, NULL);
Remi Gacogned3a341a2015-05-29 16:26:17 +02002525
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002526 if (!p || !g) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002527 DH_free(dh);
2528 dh = NULL;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002529 } else {
2530 DH_set0_pqg(dh, p, NULL, g);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002531 }
2532 }
2533 return dh;
2534}
2535
2536static DH *ssl_get_dh_2048(void)
2537{
Remi Gacogned3a341a2015-05-29 16:26:17 +02002538 static unsigned char dh2048_p[]={
2539 0xEC,0x86,0xF8,0x70,0xA0,0x33,0x16,0xEC,0x05,0x1A,0x73,0x59,
2540 0xCD,0x1F,0x8B,0xF8,0x29,0xE4,0xD2,0xCF,0x52,0xDD,0xC2,0x24,
2541 0x8D,0xB5,0x38,0x9A,0xFB,0x5C,0xA4,0xE4,0xB2,0xDA,0xCE,0x66,
2542 0x50,0x74,0xA6,0x85,0x4D,0x4B,0x1D,0x30,0xB8,0x2B,0xF3,0x10,
2543 0xE9,0xA7,0x2D,0x05,0x71,0xE7,0x81,0xDF,0x8B,0x59,0x52,0x3B,
2544 0x5F,0x43,0x0B,0x68,0xF1,0xDB,0x07,0xBE,0x08,0x6B,0x1B,0x23,
2545 0xEE,0x4D,0xCC,0x9E,0x0E,0x43,0xA0,0x1E,0xDF,0x43,0x8C,0xEC,
2546 0xBE,0xBE,0x90,0xB4,0x51,0x54,0xB9,0x2F,0x7B,0x64,0x76,0x4E,
2547 0x5D,0xD4,0x2E,0xAE,0xC2,0x9E,0xAE,0x51,0x43,0x59,0xC7,0x77,
2548 0x9C,0x50,0x3C,0x0E,0xED,0x73,0x04,0x5F,0xF1,0x4C,0x76,0x2A,
2549 0xD8,0xF8,0xCF,0xFC,0x34,0x40,0xD1,0xB4,0x42,0x61,0x84,0x66,
2550 0x42,0x39,0x04,0xF8,0x68,0xB2,0x62,0xD7,0x55,0xED,0x1B,0x74,
2551 0x75,0x91,0xE0,0xC5,0x69,0xC1,0x31,0x5C,0xDB,0x7B,0x44,0x2E,
2552 0xCE,0x84,0x58,0x0D,0x1E,0x66,0x0C,0xC8,0x44,0x9E,0xFD,0x40,
2553 0x08,0x67,0x5D,0xFB,0xA7,0x76,0x8F,0x00,0x11,0x87,0xE9,0x93,
2554 0xF9,0x7D,0xC4,0xBC,0x74,0x55,0x20,0xD4,0x4A,0x41,0x2F,0x43,
2555 0x42,0x1A,0xC1,0xF2,0x97,0x17,0x49,0x27,0x37,0x6B,0x2F,0x88,
2556 0x7E,0x1C,0xA0,0xA1,0x89,0x92,0x27,0xD9,0x56,0x5A,0x71,0xC1,
2557 0x56,0x37,0x7E,0x3A,0x9D,0x05,0xE7,0xEE,0x5D,0x8F,0x82,0x17,
2558 0xBC,0xE9,0xC2,0x93,0x30,0x82,0xF9,0xF4,0xC9,0xAE,0x49,0xDB,
2559 0xD0,0x54,0xB4,0xD9,0x75,0x4D,0xFA,0x06,0xB8,0xD6,0x38,0x41,
2560 0xB7,0x1F,0x77,0xF3,
2561 };
2562 static unsigned char dh2048_g[]={
2563 0x02,
2564 };
2565
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002566 BIGNUM *p;
2567 BIGNUM *g;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002568 DH *dh = DH_new();
2569 if (dh) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002570 p = BN_bin2bn(dh2048_p, sizeof dh2048_p, NULL);
2571 g = BN_bin2bn(dh2048_g, sizeof dh2048_g, NULL);
Remi Gacogned3a341a2015-05-29 16:26:17 +02002572
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002573 if (!p || !g) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002574 DH_free(dh);
2575 dh = NULL;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002576 } else {
2577 DH_set0_pqg(dh, p, NULL, g);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002578 }
2579 }
2580 return dh;
2581}
2582
2583static DH *ssl_get_dh_4096(void)
2584{
Remi Gacogned3a341a2015-05-29 16:26:17 +02002585 static unsigned char dh4096_p[]={
2586 0xDE,0x16,0x94,0xCD,0x99,0x58,0x07,0xF1,0xF7,0x32,0x96,0x11,
2587 0x04,0x82,0xD4,0x84,0x72,0x80,0x99,0x06,0xCA,0xF0,0xA3,0x68,
2588 0x07,0xCE,0x64,0x50,0xE7,0x74,0x45,0x20,0x80,0x5E,0x4D,0xAD,
2589 0xA5,0xB6,0xED,0xFA,0x80,0x6C,0x3B,0x35,0xC4,0x9A,0x14,0x6B,
2590 0x32,0xBB,0xFD,0x1F,0x17,0x8E,0xB7,0x1F,0xD6,0xFA,0x3F,0x7B,
2591 0xEE,0x16,0xA5,0x62,0x33,0x0D,0xED,0xBC,0x4E,0x58,0xE5,0x47,
2592 0x4D,0xE9,0xAB,0x8E,0x38,0xD3,0x6E,0x90,0x57,0xE3,0x22,0x15,
2593 0x33,0xBD,0xF6,0x43,0x45,0xB5,0x10,0x0A,0xBE,0x2C,0xB4,0x35,
2594 0xB8,0x53,0x8D,0xAD,0xFB,0xA7,0x1F,0x85,0x58,0x41,0x7A,0x79,
2595 0x20,0x68,0xB3,0xE1,0x3D,0x08,0x76,0xBF,0x86,0x0D,0x49,0xE3,
2596 0x82,0x71,0x8C,0xB4,0x8D,0x81,0x84,0xD4,0xE7,0xBE,0x91,0xDC,
2597 0x26,0x39,0x48,0x0F,0x35,0xC4,0xCA,0x65,0xE3,0x40,0x93,0x52,
2598 0x76,0x58,0x7D,0xDD,0x51,0x75,0xDC,0x69,0x61,0xBF,0x47,0x2C,
2599 0x16,0x68,0x2D,0xC9,0x29,0xD3,0xE6,0xC0,0x99,0x48,0xA0,0x9A,
2600 0xC8,0x78,0xC0,0x6D,0x81,0x67,0x12,0x61,0x3F,0x71,0xBA,0x41,
2601 0x1F,0x6C,0x89,0x44,0x03,0xBA,0x3B,0x39,0x60,0xAA,0x28,0x55,
2602 0x59,0xAE,0xB8,0xFA,0xCB,0x6F,0xA5,0x1A,0xF7,0x2B,0xDD,0x52,
2603 0x8A,0x8B,0xE2,0x71,0xA6,0x5E,0x7E,0xD8,0x2E,0x18,0xE0,0x66,
2604 0xDF,0xDD,0x22,0x21,0x99,0x52,0x73,0xA6,0x33,0x20,0x65,0x0E,
2605 0x53,0xE7,0x6B,0x9B,0xC5,0xA3,0x2F,0x97,0x65,0x76,0xD3,0x47,
2606 0x23,0x77,0x12,0xB6,0x11,0x7B,0x24,0xED,0xF1,0xEF,0xC0,0xE2,
2607 0xA3,0x7E,0x67,0x05,0x3E,0x96,0x4D,0x45,0xC2,0x18,0xD1,0x73,
2608 0x9E,0x07,0xF3,0x81,0x6E,0x52,0x63,0xF6,0x20,0x76,0xB9,0x13,
2609 0xD2,0x65,0x30,0x18,0x16,0x09,0x16,0x9E,0x8F,0xF1,0xD2,0x10,
2610 0x5A,0xD3,0xD4,0xAF,0x16,0x61,0xDA,0x55,0x2E,0x18,0x5E,0x14,
2611 0x08,0x54,0x2E,0x2A,0x25,0xA2,0x1A,0x9B,0x8B,0x32,0xA9,0xFD,
2612 0xC2,0x48,0x96,0xE1,0x80,0xCA,0xE9,0x22,0x17,0xBB,0xCE,0x3E,
2613 0x9E,0xED,0xC7,0xF1,0x1F,0xEC,0x17,0x21,0xDC,0x7B,0x82,0x48,
2614 0x8E,0xBB,0x4B,0x9D,0x5B,0x04,0x04,0xDA,0xDB,0x39,0xDF,0x01,
2615 0x40,0xC3,0xAA,0x26,0x23,0x89,0x75,0xC6,0x0B,0xD0,0xA2,0x60,
2616 0x6A,0xF1,0xCC,0x65,0x18,0x98,0x1B,0x52,0xD2,0x74,0x61,0xCC,
2617 0xBD,0x60,0xAE,0xA3,0xA0,0x66,0x6A,0x16,0x34,0x92,0x3F,0x41,
2618 0x40,0x31,0x29,0xC0,0x2C,0x63,0xB2,0x07,0x8D,0xEB,0x94,0xB8,
2619 0xE8,0x47,0x92,0x52,0x93,0x6A,0x1B,0x7E,0x1A,0x61,0xB3,0x1B,
2620 0xF0,0xD6,0x72,0x9B,0xF1,0xB0,0xAF,0xBF,0x3E,0x65,0xEF,0x23,
2621 0x1D,0x6F,0xFF,0x70,0xCD,0x8A,0x4C,0x8A,0xA0,0x72,0x9D,0xBE,
2622 0xD4,0xBB,0x24,0x47,0x4A,0x68,0xB5,0xF5,0xC6,0xD5,0x7A,0xCD,
2623 0xCA,0x06,0x41,0x07,0xAD,0xC2,0x1E,0xE6,0x54,0xA7,0xAD,0x03,
2624 0xD9,0x12,0xC1,0x9C,0x13,0xB1,0xC9,0x0A,0x43,0x8E,0x1E,0x08,
2625 0xCE,0x50,0x82,0x73,0x5F,0xA7,0x55,0x1D,0xD9,0x59,0xAC,0xB5,
2626 0xEA,0x02,0x7F,0x6C,0x5B,0x74,0x96,0x98,0x67,0x24,0xA3,0x0F,
2627 0x15,0xFC,0xA9,0x7D,0x3E,0x67,0xD1,0x70,0xF8,0x97,0xF3,0x67,
2628 0xC5,0x8C,0x88,0x44,0x08,0x02,0xC7,0x2B,
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002629 };
Remi Gacogned3a341a2015-05-29 16:26:17 +02002630 static unsigned char dh4096_g[]={
2631 0x02,
2632 };
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002633
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002634 BIGNUM *p;
2635 BIGNUM *g;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002636 DH *dh = DH_new();
2637 if (dh) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002638 p = BN_bin2bn(dh4096_p, sizeof dh4096_p, NULL);
2639 g = BN_bin2bn(dh4096_g, sizeof dh4096_g, NULL);
Remi Gacogned3a341a2015-05-29 16:26:17 +02002640
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002641 if (!p || !g) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002642 DH_free(dh);
2643 dh = NULL;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002644 } else {
2645 DH_set0_pqg(dh, p, NULL, g);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002646 }
2647 }
2648 return dh;
2649}
2650
2651/* Returns Diffie-Hellman parameters matching the private key length
Willy Tarreauef934602016-12-22 23:12:01 +01002652 but not exceeding global_ssl.default_dh_param */
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002653static DH *ssl_get_tmp_dh(SSL *ssl, int export, int keylen)
2654{
2655 DH *dh = NULL;
2656 EVP_PKEY *pkey = SSL_get_privatekey(ssl);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002657 int type;
2658
2659 type = pkey ? EVP_PKEY_base_id(pkey) : EVP_PKEY_NONE;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002660
2661 /* The keylen supplied by OpenSSL can only be 512 or 1024.
2662 See ssl3_send_server_key_exchange() in ssl/s3_srvr.c
2663 */
2664 if (type == EVP_PKEY_RSA || type == EVP_PKEY_DSA) {
2665 keylen = EVP_PKEY_bits(pkey);
2666 }
2667
Willy Tarreauef934602016-12-22 23:12:01 +01002668 if (keylen > global_ssl.default_dh_param) {
2669 keylen = global_ssl.default_dh_param;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002670 }
2671
Remi Gacogned3a341a2015-05-29 16:26:17 +02002672 if (keylen >= 4096) {
Remi Gacogne8de54152014-07-15 11:36:40 +02002673 dh = local_dh_4096;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002674 }
2675 else if (keylen >= 2048) {
Remi Gacogne8de54152014-07-15 11:36:40 +02002676 dh = local_dh_2048;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002677 }
2678 else {
Remi Gacogne8de54152014-07-15 11:36:40 +02002679 dh = local_dh_1024;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002680 }
2681
2682 return dh;
2683}
2684
Remi Gacogne47783ef2015-05-29 15:53:22 +02002685static DH * ssl_sock_get_dh_from_file(const char *filename)
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002686{
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002687 DH *dh = NULL;
Remi Gacogne47783ef2015-05-29 15:53:22 +02002688 BIO *in = BIO_new(BIO_s_file());
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002689
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002690 if (in == NULL)
2691 goto end;
2692
Remi Gacogne47783ef2015-05-29 15:53:22 +02002693 if (BIO_read_filename(in, filename) <= 0)
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002694 goto end;
2695
Remi Gacogne47783ef2015-05-29 15:53:22 +02002696 dh = PEM_read_bio_DHparams(in, NULL, NULL, NULL);
2697
2698end:
2699 if (in)
2700 BIO_free(in);
2701
Emeric Brune1b4ed42018-08-16 15:14:12 +02002702 ERR_clear_error();
2703
Remi Gacogne47783ef2015-05-29 15:53:22 +02002704 return dh;
2705}
2706
2707int ssl_sock_load_global_dh_param_from_file(const char *filename)
2708{
2709 global_dh = ssl_sock_get_dh_from_file(filename);
2710
2711 if (global_dh) {
2712 return 0;
2713 }
2714
2715 return -1;
2716}
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002717#endif
2718
William Lallemand9117de92019-10-04 00:29:42 +02002719/* Alloc and init a ckch_inst */
2720static struct ckch_inst *ckch_inst_new()
2721{
2722 struct ckch_inst *ckch_inst;
2723
2724 ckch_inst = calloc(1, sizeof *ckch_inst);
2725 if (ckch_inst)
2726 LIST_INIT(&ckch_inst->sni_ctx);
2727
2728 return ckch_inst;
2729}
2730
2731
2732/* This function allocates a sni_ctx and adds it to the ckch_inst */
William Lallemand1d29c742019-10-04 00:53:29 +02002733static int ckch_inst_add_cert_sni(SSL_CTX *ctx, struct ckch_inst *ckch_inst,
William Lallemand9117de92019-10-04 00:29:42 +02002734 struct bind_conf *s, struct ssl_bind_conf *conf,
2735 struct pkey_info kinfo, char *name, int order)
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002736{
2737 struct sni_ctx *sc;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002738 int wild = 0, neg = 0;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002739
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002740 if (*name == '!') {
2741 neg = 1;
2742 name++;
2743 }
2744 if (*name == '*') {
2745 wild = 1;
2746 name++;
2747 }
2748 /* !* filter is a nop */
2749 if (neg && wild)
2750 return order;
2751 if (*name) {
2752 int j, len;
2753 len = strlen(name);
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002754 for (j = 0; j < len && j < trash.size; j++)
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002755 trash.area[j] = tolower(name[j]);
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002756 if (j >= trash.size)
William Lallemandfe49bb32019-10-03 23:46:33 +02002757 return -1;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002758 trash.area[j] = 0;
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002759
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002760 sc = malloc(sizeof(struct sni_ctx) + len + 1);
Thierry FOURNIER / OZON.IO7a3bd3b2016-10-06 10:35:29 +02002761 if (!sc)
William Lallemandfe49bb32019-10-03 23:46:33 +02002762 return -1;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002763 memcpy(sc->name.key, trash.area, len + 1);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002764 sc->ctx = ctx;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01002765 sc->conf = conf;
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002766 sc->kinfo = kinfo;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002767 sc->order = order++;
2768 sc->neg = neg;
William Lallemand1d29c742019-10-04 00:53:29 +02002769 sc->wild = wild;
2770 sc->name.node.leaf_p = NULL;
William Lallemand1d29c742019-10-04 00:53:29 +02002771 LIST_ADDQ(&ckch_inst->sni_ctx, &sc->by_ckch_inst);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002772 }
2773 return order;
2774}
2775
William Lallemand6af03992019-07-23 15:00:54 +02002776/*
William Lallemand1d29c742019-10-04 00:53:29 +02002777 * Insert the sni_ctxs that are listed in the ckch_inst, in the bind_conf's sni_ctx tree
2778 * This function can't return an error.
2779 *
2780 * *CAUTION*: The caller must lock the sni tree if called in multithreading mode
2781 */
2782static void ssl_sock_load_cert_sni(struct ckch_inst *ckch_inst, struct bind_conf *bind_conf)
2783{
2784
2785 struct sni_ctx *sc0, *sc0b, *sc1;
2786 struct ebmb_node *node;
William Lallemand21724f02019-11-04 17:56:13 +01002787 int def = 0;
William Lallemand1d29c742019-10-04 00:53:29 +02002788
2789 list_for_each_entry_safe(sc0, sc0b, &ckch_inst->sni_ctx, by_ckch_inst) {
2790
2791 /* ignore if sc0 was already inserted in a tree */
2792 if (sc0->name.node.leaf_p)
2793 continue;
2794
2795 /* Check for duplicates. */
2796 if (sc0->wild)
2797 node = ebst_lookup(&bind_conf->sni_w_ctx, (char *)sc0->name.key);
2798 else
2799 node = ebst_lookup(&bind_conf->sni_ctx, (char *)sc0->name.key);
2800
2801 for (; node; node = ebmb_next_dup(node)) {
2802 sc1 = ebmb_entry(node, struct sni_ctx, name);
2803 if (sc1->ctx == sc0->ctx && sc1->conf == sc0->conf
2804 && sc1->neg == sc0->neg && sc1->wild == sc0->wild) {
2805 /* it's a duplicate, we should remove and free it */
2806 LIST_DEL(&sc0->by_ckch_inst);
2807 free(sc0);
2808 sc0 = NULL;
William Lallemande15029b2019-10-14 10:46:58 +02002809 break;
William Lallemand1d29c742019-10-04 00:53:29 +02002810 }
2811 }
2812
2813 /* if duplicate, ignore the insertion */
2814 if (!sc0)
2815 continue;
2816
2817 if (sc0->wild)
2818 ebst_insert(&bind_conf->sni_w_ctx, &sc0->name);
2819 else
2820 ebst_insert(&bind_conf->sni_ctx, &sc0->name);
William Lallemand21724f02019-11-04 17:56:13 +01002821
2822 /* replace the default_ctx if required with the first ctx */
2823 if (ckch_inst->is_default && !def) {
2824 /* we don't need to free the default_ctx because the refcount was not incremented */
2825 bind_conf->default_ctx = sc0->ctx;
2826 def = 1;
2827 }
William Lallemand1d29c742019-10-04 00:53:29 +02002828 }
2829}
2830
2831/*
William Lallemande3af8fb2019-10-08 11:36:53 +02002832 * tree used to store the ckchs ordered by filename/bundle name
William Lallemand6af03992019-07-23 15:00:54 +02002833 */
William Lallemande3af8fb2019-10-08 11:36:53 +02002834struct eb_root ckchs_tree = EB_ROOT_UNIQUE;
William Lallemand6af03992019-07-23 15:00:54 +02002835
William Lallemandfa892222019-07-23 16:06:08 +02002836
Emeric Brun7a883362019-10-17 13:27:40 +02002837/* Loads Diffie-Hellman parameter from a ckchs to an SSL_CTX.
2838 * If there is no DH paramater availaible in the ckchs, the global
2839 * DH parameter is loaded into the SSL_CTX and if there is no
2840 * DH parameter available in ckchs nor in global, the default
2841 * DH parameters are applied on the SSL_CTX.
2842 * Returns a bitfield containing the flags:
2843 * ERR_FATAL in any fatal error case
2844 * ERR_ALERT if a reason of the error is availabine in err
2845 * ERR_WARN if a warning is available into err
2846 * The value 0 means there is no error nor warning and
2847 * the operation succeed.
2848 */
William Lallemandfa892222019-07-23 16:06:08 +02002849#ifndef OPENSSL_NO_DH
Emeric Brun7a883362019-10-17 13:27:40 +02002850static int ssl_sock_load_dh_params(SSL_CTX *ctx, const struct cert_key_and_chain *ckch,
2851 const char *path, char **err)
William Lallemandfa892222019-07-23 16:06:08 +02002852{
Emeric Brun7a883362019-10-17 13:27:40 +02002853 int ret = 0;
William Lallemandfa892222019-07-23 16:06:08 +02002854 DH *dh = NULL;
2855
William Lallemanda8c73742019-07-31 18:31:34 +02002856 if (ckch && ckch->dh) {
William Lallemandfa892222019-07-23 16:06:08 +02002857 dh = ckch->dh;
Emeric Bruna9363eb2019-10-17 14:53:03 +02002858 if (!SSL_CTX_set_tmp_dh(ctx, dh)) {
2859 memprintf(err, "%sunable to load the DH parameter specified in '%s'",
2860 err && *err ? *err : "", path);
2861#if defined(SSL_CTX_set_dh_auto)
2862 SSL_CTX_set_dh_auto(ctx, 1);
2863 memprintf(err, "%s, SSL library will use an automatically generated DH parameter.\n",
2864 err && *err ? *err : "");
2865#else
2866 memprintf(err, "%s, DH ciphers won't be available.\n",
2867 err && *err ? *err : "");
2868#endif
2869 ret |= ERR_WARN;
2870 goto end;
2871 }
William Lallemandfa892222019-07-23 16:06:08 +02002872
2873 if (ssl_dh_ptr_index >= 0) {
2874 /* store a pointer to the DH params to avoid complaining about
2875 ssl-default-dh-param not being set for this SSL_CTX */
2876 SSL_CTX_set_ex_data(ctx, ssl_dh_ptr_index, dh);
2877 }
2878 }
2879 else if (global_dh) {
Emeric Bruna9363eb2019-10-17 14:53:03 +02002880 if (!SSL_CTX_set_tmp_dh(ctx, global_dh)) {
2881 memprintf(err, "%sunable to use the global DH parameter for certificate '%s'",
2882 err && *err ? *err : "", path);
2883#if defined(SSL_CTX_set_dh_auto)
2884 SSL_CTX_set_dh_auto(ctx, 1);
2885 memprintf(err, "%s, SSL library will use an automatically generated DH parameter.\n",
2886 err && *err ? *err : "");
2887#else
2888 memprintf(err, "%s, DH ciphers won't be available.\n",
2889 err && *err ? *err : "");
2890#endif
2891 ret |= ERR_WARN;
2892 goto end;
2893 }
William Lallemandfa892222019-07-23 16:06:08 +02002894 }
2895 else {
2896 /* Clear openssl global errors stack */
2897 ERR_clear_error();
2898
2899 if (global_ssl.default_dh_param <= 1024) {
2900 /* we are limited to DH parameter of 1024 bits anyway */
2901 if (local_dh_1024 == NULL)
2902 local_dh_1024 = ssl_get_dh_1024();
2903
Emeric Brun7a883362019-10-17 13:27:40 +02002904 if (local_dh_1024 == NULL) {
2905 memprintf(err, "%sunable to load default 1024 bits DH parameter for certificate '%s'.\n",
2906 err && *err ? *err : "", path);
2907 ret |= ERR_ALERT | ERR_FATAL;
William Lallemandfa892222019-07-23 16:06:08 +02002908 goto end;
Emeric Brun7a883362019-10-17 13:27:40 +02002909 }
William Lallemandfa892222019-07-23 16:06:08 +02002910
Emeric Bruna9363eb2019-10-17 14:53:03 +02002911 if (!SSL_CTX_set_tmp_dh(ctx, local_dh_1024)) {
2912 memprintf(err, "%sunable to load default 1024 bits DH parameter for certificate '%s'.\n",
2913 err && *err ? *err : "", path);
2914#if defined(SSL_CTX_set_dh_auto)
2915 SSL_CTX_set_dh_auto(ctx, 1);
2916 memprintf(err, "%s, SSL library will use an automatically generated DH parameter.\n",
2917 err && *err ? *err : "");
2918#else
2919 memprintf(err, "%s, DH ciphers won't be available.\n",
2920 err && *err ? *err : "");
2921#endif
2922 ret |= ERR_WARN;
2923 goto end;
2924 }
William Lallemandfa892222019-07-23 16:06:08 +02002925 }
2926 else {
2927 SSL_CTX_set_tmp_dh_callback(ctx, ssl_get_tmp_dh);
2928 }
William Lallemandfa892222019-07-23 16:06:08 +02002929 }
2930
2931end:
William Lallemandfa892222019-07-23 16:06:08 +02002932 return ret;
2933}
2934#endif
yanbzhu08ce6ab2015-12-02 13:01:29 -05002935
yanbzhu488a4d22015-12-01 15:16:07 -05002936/* Frees the contents of a cert_key_and_chain
2937 */
2938static void ssl_sock_free_cert_key_and_chain_contents(struct cert_key_and_chain *ckch)
2939{
yanbzhu488a4d22015-12-01 15:16:07 -05002940 if (!ckch)
2941 return;
2942
2943 /* Free the certificate and set pointer to NULL */
2944 if (ckch->cert)
2945 X509_free(ckch->cert);
2946 ckch->cert = NULL;
2947
2948 /* Free the key and set pointer to NULL */
2949 if (ckch->key)
2950 EVP_PKEY_free(ckch->key);
2951 ckch->key = NULL;
2952
2953 /* Free each certificate in the chain */
Emmanuel Hocdet9246f8b2018-11-30 16:00:21 +01002954 if (ckch->chain)
2955 sk_X509_pop_free(ckch->chain, X509_free);
2956 ckch->chain = NULL;
yanbzhu488a4d22015-12-01 15:16:07 -05002957
William Lallemand455af502019-10-17 18:04:45 +02002958 if (ckch->dh)
2959 DH_free(ckch->dh);
2960 ckch->dh = NULL;
2961
2962 if (ckch->sctl) {
2963 free(ckch->sctl->area);
2964 ckch->sctl->area = NULL;
2965 free(ckch->sctl);
2966 ckch->sctl = NULL;
2967 }
2968
2969 if (ckch->ocsp_response) {
2970 free(ckch->ocsp_response->area);
2971 ckch->ocsp_response->area = NULL;
2972 free(ckch->ocsp_response);
2973 ckch->ocsp_response = NULL;
2974 }
yanbzhu488a4d22015-12-01 15:16:07 -05002975}
2976
William Lallemand8d0f8932019-10-17 18:03:58 +02002977/*
2978 *
2979 * This function copy a cert_key_and_chain in memory
2980 *
2981 * It's used to try to apply changes on a ckch before committing them, because
2982 * most of the time it's not possible to revert those changes
2983 *
2984 * Return a the dst or NULL
2985 */
2986static struct cert_key_and_chain *ssl_sock_copy_cert_key_and_chain(struct cert_key_and_chain *src,
2987 struct cert_key_and_chain *dst)
2988{
2989 if (src->cert) {
2990 dst->cert = src->cert;
2991 X509_up_ref(src->cert);
2992 }
2993
2994 if (src->key) {
2995 dst->key = src->key;
2996 EVP_PKEY_up_ref(src->key);
2997 }
2998
2999 if (src->chain) {
3000 dst->chain = X509_chain_up_ref(src->chain);
3001 }
3002
3003 if (src->dh) {
3004 DH_up_ref(src->dh);
3005 dst->dh = src->dh;
3006 }
3007
3008 if (src->sctl) {
3009 struct buffer *sctl;
3010
3011 sctl = calloc(1, sizeof(*sctl));
3012 if (!chunk_dup(sctl, src->sctl)) {
3013 free(sctl);
3014 sctl = NULL;
3015 goto error;
3016 }
3017 dst->sctl = sctl;
3018 }
3019
3020 if (src->ocsp_response) {
3021 struct buffer *ocsp_response;
3022
3023 ocsp_response = calloc(1, sizeof(*ocsp_response));
3024 if (!chunk_dup(ocsp_response, src->ocsp_response)) {
3025 free(ocsp_response);
3026 ocsp_response = NULL;
3027 goto error;
3028 }
3029 dst->ocsp_response = ocsp_response;
3030 }
3031
3032 if (src->ocsp_issuer) {
3033 X509_up_ref(src->ocsp_issuer);
3034 dst->ocsp_issuer = src->ocsp_issuer;
3035 }
3036
3037 return dst;
3038
3039error:
3040
3041 /* free everything */
3042 ssl_sock_free_cert_key_and_chain_contents(dst);
3043
3044 return NULL;
3045}
3046
3047
yanbzhu488a4d22015-12-01 15:16:07 -05003048/* checks if a key and cert exists in the ckch
3049 */
William Lallemand1633e392019-09-30 12:58:13 +02003050#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
yanbzhu488a4d22015-12-01 15:16:07 -05003051static int ssl_sock_is_ckch_valid(struct cert_key_and_chain *ckch)
3052{
3053 return (ckch->cert != NULL && ckch->key != NULL);
3054}
William Lallemand1633e392019-09-30 12:58:13 +02003055#endif
yanbzhu488a4d22015-12-01 15:16:07 -05003056
William Lallemandf9568fc2019-10-16 18:27:58 +02003057/*
3058 * return 0 on success or != 0 on failure
3059 */
3060static int ssl_sock_load_issuer_file_into_ckch(const char *path, char *buf, struct cert_key_and_chain *ckch, char **err)
3061{
3062 int ret = 1;
3063 BIO *in = NULL;
3064 X509 *issuer;
3065
3066 if (buf) {
3067 /* reading from a buffer */
3068 in = BIO_new_mem_buf(buf, -1);
3069 if (in == NULL) {
3070 memprintf(err, "%sCan't allocate memory\n", err && *err ? *err : "");
3071 goto end;
3072 }
3073
3074 } else {
3075 /* reading from a file */
3076 in = BIO_new(BIO_s_file());
3077 if (in == NULL)
3078 goto end;
3079
3080 if (BIO_read_filename(in, path) <= 0)
3081 goto end;
3082 }
3083
3084 issuer = PEM_read_bio_X509_AUX(in, NULL, NULL, NULL);
3085 if (!issuer) {
3086 memprintf(err, "%s'%s' cannot be read or parsed'.\n",
3087 *err ? *err : "", path);
3088 goto end;
3089 }
3090 ret = 0;
3091 ckch->ocsp_issuer = issuer;
3092
3093end:
3094
3095 ERR_clear_error();
3096 if (in)
3097 BIO_free(in);
3098
3099 return ret;
3100}
3101
William Lallemand96a9c972019-10-17 11:56:17 +02003102
3103/*
3104 * Try to load a PEM file from a <path> or a buffer <buf>
3105 * The PEM must contain at least a Private Key and a Certificate,
3106 * It could contain a DH and a certificate chain.
yanbzhu488a4d22015-12-01 15:16:07 -05003107 *
William Lallemand96a9c972019-10-17 11:56:17 +02003108 * If it failed you should not attempt to use the ckch but free it.
3109 *
3110 * Return 0 on success or != 0 on failure
yanbzhu488a4d22015-12-01 15:16:07 -05003111 */
William Lallemand96a9c972019-10-17 11:56:17 +02003112static int ssl_sock_load_pem_into_ckch(const char *path, char *buf, struct cert_key_and_chain *ckch , char **err)
yanbzhu488a4d22015-12-01 15:16:07 -05003113{
William Lallemandf11365b2019-09-19 14:25:58 +02003114 BIO *in = NULL;
yanbzhu488a4d22015-12-01 15:16:07 -05003115 int ret = 1;
Emmanuel Hocdet83cbd3c2019-10-25 11:55:03 +02003116 X509 *ca;
William Lallemand96a9c972019-10-17 11:56:17 +02003117 X509 *cert = NULL;
3118 EVP_PKEY *key = NULL;
3119 DH *dh;
3120
3121 if (buf) {
3122 /* reading from a buffer */
3123 in = BIO_new_mem_buf(buf, -1);
3124 if (in == NULL) {
3125 memprintf(err, "%sCan't allocate memory\n", err && *err ? *err : "");
3126 goto end;
3127 }
yanbzhu488a4d22015-12-01 15:16:07 -05003128
William Lallemand96a9c972019-10-17 11:56:17 +02003129 } else {
3130 /* reading from a file */
William Lallemandf11365b2019-09-19 14:25:58 +02003131 in = BIO_new(BIO_s_file());
3132 if (in == NULL)
3133 goto end;
yanbzhu488a4d22015-12-01 15:16:07 -05003134
William Lallemandf11365b2019-09-19 14:25:58 +02003135 if (BIO_read_filename(in, path) <= 0)
3136 goto end;
William Lallemandf11365b2019-09-19 14:25:58 +02003137 }
yanbzhu488a4d22015-12-01 15:16:07 -05003138
yanbzhu488a4d22015-12-01 15:16:07 -05003139 /* Read Private Key */
William Lallemand96a9c972019-10-17 11:56:17 +02003140 key = PEM_read_bio_PrivateKey(in, NULL, NULL, NULL);
3141 if (key == NULL) {
yanbzhu488a4d22015-12-01 15:16:07 -05003142 memprintf(err, "%sunable to load private key from file '%s'.\n",
William Lallemand96a9c972019-10-17 11:56:17 +02003143 err && *err ? *err : "", path);
yanbzhu488a4d22015-12-01 15:16:07 -05003144 goto end;
3145 }
3146
Emmanuel Hocdet54227d82019-07-30 17:04:01 +02003147#ifndef OPENSSL_NO_DH
William Lallemandfa892222019-07-23 16:06:08 +02003148 /* Seek back to beginning of file */
3149 if (BIO_reset(in) == -1) {
3150 memprintf(err, "%san error occurred while reading the file '%s'.\n",
3151 err && *err ? *err : "", path);
3152 goto end;
3153 }
3154
William Lallemand96a9c972019-10-17 11:56:17 +02003155 dh = PEM_read_bio_DHparams(in, NULL, NULL, NULL);
3156 /* no need to return an error there, dh is not mandatory */
3157
3158 if (dh) {
3159 if (ckch->dh)
3160 DH_free(ckch->dh);
3161 ckch->dh = dh;
3162 }
3163
Emmanuel Hocdet54227d82019-07-30 17:04:01 +02003164#endif
William Lallemandfa892222019-07-23 16:06:08 +02003165
Willy Tarreaubb137a82016-04-06 19:02:38 +02003166 /* Seek back to beginning of file */
Thierry FOURNIER / OZON.IOd44ea3f2016-10-14 00:49:21 +02003167 if (BIO_reset(in) == -1) {
3168 memprintf(err, "%san error occurred while reading the file '%s'.\n",
3169 err && *err ? *err : "", path);
3170 goto end;
3171 }
Willy Tarreaubb137a82016-04-06 19:02:38 +02003172
3173 /* Read Certificate */
William Lallemand96a9c972019-10-17 11:56:17 +02003174 cert = PEM_read_bio_X509_AUX(in, NULL, NULL, NULL);
3175 if (cert == NULL) {
Willy Tarreaubb137a82016-04-06 19:02:38 +02003176 memprintf(err, "%sunable to load certificate from file '%s'.\n",
William Lallemand96a9c972019-10-17 11:56:17 +02003177 err && *err ? *err : "", path);
Willy Tarreaubb137a82016-04-06 19:02:38 +02003178 goto end;
3179 }
3180
William Lallemand96a9c972019-10-17 11:56:17 +02003181 if (!X509_check_private_key(cert, key)) {
Emmanuel Hocdet03e09f32019-07-30 14:21:25 +02003182 memprintf(err, "%sinconsistencies between private key and certificate loaded from PEM file '%s'.\n",
William Lallemand96a9c972019-10-17 11:56:17 +02003183 err && *err ? *err : "", path);
Emmanuel Hocdet03e09f32019-07-30 14:21:25 +02003184 goto end;
3185 }
3186
William Lallemand96a9c972019-10-17 11:56:17 +02003187 /* Key and Cert are good, we can use them in the ckch */
3188 if (ckch->key) /* free the previous key */
3189 EVP_PKEY_free(ckch->key);
3190 ckch->key = key;
Emmanuel Hocdet83cbd3c2019-10-25 11:55:03 +02003191 key = NULL;
William Lallemand96a9c972019-10-17 11:56:17 +02003192
3193 if (ckch->cert) /* free the previous cert */
3194 X509_free(ckch->cert);
3195 ckch->cert = cert;
Emmanuel Hocdet83cbd3c2019-10-25 11:55:03 +02003196 cert = NULL;
William Lallemand96a9c972019-10-17 11:56:17 +02003197
3198 /* Look for a Certificate Chain */
3199 ca = PEM_read_bio_X509(in, NULL, NULL, NULL);
3200 if (ca) {
3201 /* there is a chain a in the PEM, clean the previous one in the CKCH */
3202 if (ckch->chain) /* free the previous chain */
3203 sk_X509_pop_free(ckch->chain, X509_free);
3204 ckch->chain = sk_X509_new_null();
3205 if (!sk_X509_push(ckch->chain, ca)) {
3206 X509_free(ca);
3207 goto end;
3208 }
3209 }
3210 /* look for other crt in the chain */
Emmanuel Hocdet9246f8b2018-11-30 16:00:21 +01003211 while ((ca = PEM_read_bio_X509(in, NULL, NULL, NULL)))
3212 if (!sk_X509_push(ckch->chain, ca)) {
3213 X509_free(ca);
3214 goto end;
3215 }
yanbzhu488a4d22015-12-01 15:16:07 -05003216
Emmanuel Hocdeted17f472019-10-24 18:28:33 +02003217 /* no chain */
3218 if (ckch->chain == NULL) {
3219 ckch->chain = sk_X509_new_null();
3220 }
3221
yanbzhu488a4d22015-12-01 15:16:07 -05003222 ret = ERR_get_error();
3223 if (ret && (ERR_GET_LIB(ret) != ERR_LIB_PEM && ERR_GET_REASON(ret) != PEM_R_NO_START_LINE)) {
3224 memprintf(err, "%sunable to load certificate chain from file '%s'.\n",
William Lallemand96a9c972019-10-17 11:56:17 +02003225 err && *err ? *err : "", path);
yanbzhu488a4d22015-12-01 15:16:07 -05003226 goto end;
William Lallemand246c0242019-10-11 08:59:13 +02003227 }
3228
3229 ret = 0;
3230
William Lallemand96a9c972019-10-17 11:56:17 +02003231end:
William Lallemand246c0242019-10-11 08:59:13 +02003232
3233 ERR_clear_error();
William Lallemand96a9c972019-10-17 11:56:17 +02003234 if (in)
William Lallemand246c0242019-10-11 08:59:13 +02003235 BIO_free(in);
Emmanuel Hocdet83cbd3c2019-10-25 11:55:03 +02003236 if (key)
3237 EVP_PKEY_free(key);
3238 if (cert)
3239 X509_free(cert);
William Lallemanda17f4112019-10-10 15:16:44 +02003240
William Lallemand96a9c972019-10-17 11:56:17 +02003241 return ret;
3242}
3243
3244/*
3245 * Try to load in a ckch every files related to a ckch.
3246 * (PEM, sctl, ocsp, issuer etc.)
3247 *
3248 * This function is only used to load files during the configuration parsing,
3249 * it is not used with the CLI.
3250 *
3251 * This allows us to carry the contents of the file without having to read the
3252 * file multiple times. The caller must call
3253 * ssl_sock_free_cert_key_and_chain_contents.
3254 *
3255 * returns:
3256 * 0 on Success
3257 * 1 on SSL Failure
3258 */
3259static int ssl_sock_load_files_into_ckch(const char *path, struct cert_key_and_chain *ckch, char **err)
3260{
3261 int ret = 1;
3262
3263 /* try to load the PEM */
3264 if (ssl_sock_load_pem_into_ckch(path, NULL, ckch , err) != 0) {
3265 goto end;
3266 }
3267
William Lallemanda17f4112019-10-10 15:16:44 +02003268#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
3269 /* try to load the sctl file */
3270 {
3271 char fp[MAXPATHLEN+1];
3272 struct stat st;
3273
3274 snprintf(fp, MAXPATHLEN+1, "%s.sctl", path);
3275 if (stat(fp, &st) == 0) {
William Lallemand0dfae6c2019-10-16 18:06:58 +02003276 if (ssl_sock_load_sctl_from_file(fp, NULL, ckch, err)) {
William Lallemanda17f4112019-10-10 15:16:44 +02003277 memprintf(err, "%s '%s.sctl' is present but cannot be read or parsed'.\n",
3278 *err ? *err : "", fp);
3279 ret = 1;
3280 goto end;
3281 }
3282 }
3283 }
3284#endif
yanbzhu488a4d22015-12-01 15:16:07 -05003285
William Lallemand246c0242019-10-11 08:59:13 +02003286 /* try to load an ocsp response file */
3287 {
3288 char fp[MAXPATHLEN+1];
3289 struct stat st;
3290
3291 snprintf(fp, MAXPATHLEN+1, "%s.ocsp", path);
3292 if (stat(fp, &st) == 0) {
William Lallemand3b5f3602019-10-16 18:05:05 +02003293 if (ssl_sock_load_ocsp_response_from_file(fp, NULL, ckch, err)) {
William Lallemand246c0242019-10-11 08:59:13 +02003294 ret = 1;
3295 goto end;
3296 }
3297 }
3298 }
3299
Emmanuel Hocdeteaad5cc2019-10-25 12:19:00 +02003300#ifndef OPENSSL_IS_BORINGSSL /* Useless for BoringSSL */
William Lallemand246c0242019-10-11 08:59:13 +02003301 if (ckch->ocsp_response) {
3302 X509 *issuer;
3303 int i;
3304
3305 /* check if one of the certificate of the chain is the issuer */
3306 for (i = 0; i < sk_X509_num(ckch->chain); i++) {
3307 issuer = sk_X509_value(ckch->chain, i);
3308 if (X509_check_issued(issuer, ckch->cert) == X509_V_OK) {
3309 ckch->ocsp_issuer = issuer;
3310 break;
3311 } else
3312 issuer = NULL;
3313 }
3314
3315 /* if no issuer was found, try to load an issuer from the .issuer */
3316 if (!issuer) {
3317 struct stat st;
3318 char fp[MAXPATHLEN+1];
3319
3320 snprintf(fp, MAXPATHLEN+1, "%s.issuer", path);
3321 if (stat(fp, &st) == 0) {
William Lallemandf9568fc2019-10-16 18:27:58 +02003322 if (ssl_sock_load_issuer_file_into_ckch(fp, NULL, ckch, err)) {
William Lallemand246c0242019-10-11 08:59:13 +02003323 ret = 1;
3324 goto end;
3325 }
3326
3327 if (X509_check_issued(ckch->ocsp_issuer, ckch->cert) != X509_V_OK) {
William Lallemand786188f2019-10-15 10:05:37 +02003328 memprintf(err, "%s '%s' is not an issuer'.\n",
William Lallemand246c0242019-10-11 08:59:13 +02003329 *err ? *err : "", fp);
3330 ret = 1;
3331 goto end;
3332 }
3333 } else {
3334 memprintf(err, "%sNo issuer found, cannot use the OCSP response'.\n",
3335 *err ? *err : "");
3336 ret = 1;
3337 goto end;
3338 }
3339 }
3340 }
Emmanuel Hocdeteaad5cc2019-10-25 12:19:00 +02003341#endif
William Lallemand246c0242019-10-11 08:59:13 +02003342
yanbzhu488a4d22015-12-01 15:16:07 -05003343 ret = 0;
3344
3345end:
3346
3347 ERR_clear_error();
yanbzhu488a4d22015-12-01 15:16:07 -05003348
3349 /* Something went wrong in one of the reads */
3350 if (ret != 0)
3351 ssl_sock_free_cert_key_and_chain_contents(ckch);
3352
3353 return ret;
3354}
3355
3356/* Loads the info in ckch into ctx
Emeric Bruna96b5822019-10-17 13:25:14 +02003357 * Returns a bitfield containing the flags:
3358 * ERR_FATAL in any fatal error case
3359 * ERR_ALERT if the reason of the error is available in err
3360 * ERR_WARN if a warning is available into err
3361 * The value 0 means there is no error nor warning and
3362 * the operation succeed.
yanbzhu488a4d22015-12-01 15:16:07 -05003363 */
3364static int ssl_sock_put_ckch_into_ctx(const char *path, const struct cert_key_and_chain *ckch, SSL_CTX *ctx, char **err)
3365{
Emeric Bruna96b5822019-10-17 13:25:14 +02003366 int errcode = 0;
3367
yanbzhu488a4d22015-12-01 15:16:07 -05003368 if (SSL_CTX_use_PrivateKey(ctx, ckch->key) <= 0) {
3369 memprintf(err, "%sunable to load SSL private key into SSL Context '%s'.\n",
3370 err && *err ? *err : "", path);
Emeric Bruna96b5822019-10-17 13:25:14 +02003371 errcode |= ERR_ALERT | ERR_FATAL;
3372 return errcode;
yanbzhu488a4d22015-12-01 15:16:07 -05003373 }
3374
3375 if (!SSL_CTX_use_certificate(ctx, ckch->cert)) {
3376 memprintf(err, "%sunable to load SSL certificate into SSL Context '%s'.\n",
3377 err && *err ? *err : "", path);
Emeric Bruna96b5822019-10-17 13:25:14 +02003378 errcode |= ERR_ALERT | ERR_FATAL;
3379 goto end;
yanbzhu488a4d22015-12-01 15:16:07 -05003380 }
3381
yanbzhu488a4d22015-12-01 15:16:07 -05003382 /* Load all certs in the ckch into the ctx_chain for the ssl_ctx */
Emmanuel Hocdet1c65fdd2018-12-03 18:07:44 +01003383#ifdef SSL_CTX_set1_chain
Emmanuel Hocdet9246f8b2018-11-30 16:00:21 +01003384 if (!SSL_CTX_set1_chain(ctx, ckch->chain)) {
3385 memprintf(err, "%sunable to load chain certificate into SSL Context '%s'. Make sure you are linking against Openssl >= 1.0.2.\n",
3386 err && *err ? *err : "", path);
Emeric Bruna96b5822019-10-17 13:25:14 +02003387 errcode |= ERR_ALERT | ERR_FATAL;
3388 goto end;
yanbzhu488a4d22015-12-01 15:16:07 -05003389 }
Emmanuel Hocdet1c65fdd2018-12-03 18:07:44 +01003390#else
3391 { /* legacy compat (< openssl 1.0.2) */
3392 X509 *ca;
3393 while ((ca = sk_X509_shift(ckch->chain)))
3394 if (!SSL_CTX_add_extra_chain_cert(ctx, ca)) {
3395 memprintf(err, "%sunable to load chain certificate into SSL Context '%s'.\n",
3396 err && *err ? *err : "", path);
3397 X509_free(ca);
Emeric Bruna96b5822019-10-17 13:25:14 +02003398 errcode |= ERR_ALERT | ERR_FATAL;
3399 goto end;
Emmanuel Hocdet1c65fdd2018-12-03 18:07:44 +01003400 }
3401 }
3402#endif
yanbzhu488a4d22015-12-01 15:16:07 -05003403
William Lallemandfa892222019-07-23 16:06:08 +02003404#ifndef OPENSSL_NO_DH
3405 /* store a NULL pointer to indicate we have not yet loaded
3406 a custom DH param file */
3407 if (ssl_dh_ptr_index >= 0) {
3408 SSL_CTX_set_ex_data(ctx, ssl_dh_ptr_index, NULL);
3409 }
3410
Emeric Brun7a883362019-10-17 13:27:40 +02003411 errcode |= ssl_sock_load_dh_params(ctx, ckch, path, err);
3412 if (errcode & ERR_CODE) {
William Lallemandfa892222019-07-23 16:06:08 +02003413 memprintf(err, "%sunable to load DH parameters from file '%s'.\n",
3414 err && *err ? *err : "", path);
Emeric Bruna96b5822019-10-17 13:25:14 +02003415 goto end;
William Lallemandfa892222019-07-23 16:06:08 +02003416 }
3417#endif
3418
William Lallemanda17f4112019-10-10 15:16:44 +02003419#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
3420 if (sctl_ex_index >= 0 && ckch->sctl) {
3421 if (ssl_sock_load_sctl(ctx, ckch->sctl) < 0) {
3422 memprintf(err, "%s '%s.sctl' is present but cannot be read or parsed'.\n",
3423 *err ? *err : "", path);
Emeric Bruna96b5822019-10-17 13:25:14 +02003424 errcode |= ERR_ALERT | ERR_FATAL;
3425 goto end;
William Lallemanda17f4112019-10-10 15:16:44 +02003426 }
3427 }
3428#endif
3429
William Lallemand4a660132019-10-14 14:51:41 +02003430#if ((defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP) || defined OPENSSL_IS_BORINGSSL)
William Lallemand246c0242019-10-11 08:59:13 +02003431 /* Load OCSP Info into context */
3432 if (ckch->ocsp_response) {
3433 if (ssl_sock_load_ocsp(ctx, ckch) < 0) {
3434 if (err)
3435 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",
3436 *err ? *err : "", path);
Emeric Bruna96b5822019-10-17 13:25:14 +02003437 errcode |= ERR_ALERT | ERR_FATAL;
3438 goto end;
William Lallemand246c0242019-10-11 08:59:13 +02003439 }
3440 }
William Lallemand246c0242019-10-11 08:59:13 +02003441#endif
3442
Emeric Bruna96b5822019-10-17 13:25:14 +02003443 end:
3444 return errcode;
yanbzhu488a4d22015-12-01 15:16:07 -05003445}
3446
William Lallemandc4ecddf2019-07-31 16:50:08 +02003447#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
yanbzhu08ce6ab2015-12-02 13:01:29 -05003448
William Lallemand28a8fce2019-10-04 17:36:55 +02003449static int ssl_sock_populate_sni_keytypes_hplr(const char *str, struct eb_root *sni_keytypes, int key_index)
yanbzhu08ce6ab2015-12-02 13:01:29 -05003450{
3451 struct sni_keytype *s_kt = NULL;
3452 struct ebmb_node *node;
3453 int i;
3454
3455 for (i = 0; i < trash.size; i++) {
3456 if (!str[i])
3457 break;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02003458 trash.area[i] = tolower(str[i]);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003459 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +02003460 trash.area[i] = 0;
3461 node = ebst_lookup(sni_keytypes, trash.area);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003462 if (!node) {
3463 /* CN not found in tree */
3464 s_kt = malloc(sizeof(struct sni_keytype) + i + 1);
3465 /* Using memcpy here instead of strncpy.
3466 * strncpy will cause sig_abrt errors under certain versions of gcc with -O2
3467 * See: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=60792
3468 */
William Lallemand28a8fce2019-10-04 17:36:55 +02003469 if (!s_kt)
3470 return -1;
3471
Willy Tarreau843b7cb2018-07-13 10:54:26 +02003472 memcpy(s_kt->name.key, trash.area, i+1);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003473 s_kt->keytypes = 0;
3474 ebst_insert(sni_keytypes, &s_kt->name);
3475 } else {
3476 /* CN found in tree */
3477 s_kt = container_of(node, struct sni_keytype, name);
3478 }
3479
3480 /* Mark that this CN has the keytype of key_index via keytypes mask */
3481 s_kt->keytypes |= 1<<key_index;
3482
William Lallemand28a8fce2019-10-04 17:36:55 +02003483 return 0;
3484
yanbzhu08ce6ab2015-12-02 13:01:29 -05003485}
3486
William Lallemandc4ecddf2019-07-31 16:50:08 +02003487#endif
William Lallemand8c1cdde2019-10-18 10:58:14 +02003488/*
3489 * Free a ckch_store and its ckch(s)
3490 * The linked ckch_inst are not free'd
3491 */
3492void ckchs_free(struct ckch_store *ckchs)
3493{
3494 if (!ckchs)
3495 return;
3496
3497#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
3498 if (ckchs->multi) {
3499 int n;
3500
3501 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++)
3502 ssl_sock_free_cert_key_and_chain_contents(&ckchs->ckch[n]);
3503 } else
3504#endif
3505 {
3506 ssl_sock_free_cert_key_and_chain_contents(ckchs->ckch);
3507 ckchs->ckch = NULL;
3508 }
3509
3510 free(ckchs);
3511}
3512
3513/* allocate and duplicate a ckch_store
3514 * Return a new ckch_store or NULL */
3515static struct ckch_store *ckchs_dup(const struct ckch_store *src)
3516{
3517 struct ckch_store *dst;
3518 int pathlen;
3519
3520 pathlen = strlen(src->path);
3521 dst = calloc(1, sizeof(*dst) + pathlen + 1);
3522 if (!dst)
3523 return NULL;
3524 /* copy previous key */
3525 memcpy(dst->path, src->path, pathlen + 1);
3526 dst->multi = src->multi;
3527 LIST_INIT(&dst->ckch_inst);
3528
3529 dst->ckch = calloc((src->multi ? SSL_SOCK_NUM_KEYTYPES : 1), sizeof(*dst->ckch));
3530 if (!dst->ckch)
3531 goto error;
3532
3533#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
3534 if (src->multi) {
3535 int n;
3536
3537 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
3538 if (&src->ckch[n]) {
3539 if (!ssl_sock_copy_cert_key_and_chain(&src->ckch[n], &dst->ckch[n]))
3540 goto error;
3541 }
3542 }
3543 } else
3544#endif
3545 {
3546 if (!ssl_sock_copy_cert_key_and_chain(src->ckch, dst->ckch))
3547 goto error;
3548 }
3549
3550 return dst;
3551
3552error:
3553 ckchs_free(dst);
3554
3555 return NULL;
3556}
William Lallemandc4ecddf2019-07-31 16:50:08 +02003557
William Lallemand36b84632019-07-18 19:28:17 +02003558/*
William Lallemande3af8fb2019-10-08 11:36:53 +02003559 * lookup a path into the ckchs tree.
William Lallemand6af03992019-07-23 15:00:54 +02003560 */
William Lallemande3af8fb2019-10-08 11:36:53 +02003561static inline struct ckch_store *ckchs_lookup(char *path)
William Lallemand6af03992019-07-23 15:00:54 +02003562{
3563 struct ebmb_node *eb;
3564
William Lallemande3af8fb2019-10-08 11:36:53 +02003565 eb = ebst_lookup(&ckchs_tree, path);
William Lallemand6af03992019-07-23 15:00:54 +02003566 if (!eb)
3567 return NULL;
3568
William Lallemande3af8fb2019-10-08 11:36:53 +02003569 return ebmb_entry(eb, struct ckch_store, node);
William Lallemand6af03992019-07-23 15:00:54 +02003570}
3571
3572/*
William Lallemande3af8fb2019-10-08 11:36:53 +02003573 * This function allocate a ckch_store and populate it with certificates from files.
William Lallemand36b84632019-07-18 19:28:17 +02003574 */
William Lallemande3af8fb2019-10-08 11:36:53 +02003575static struct ckch_store *ckchs_load_cert_file(char *path, int multi, char **err)
William Lallemand36b84632019-07-18 19:28:17 +02003576{
William Lallemande3af8fb2019-10-08 11:36:53 +02003577 struct ckch_store *ckchs;
William Lallemand36b84632019-07-18 19:28:17 +02003578
William Lallemande3af8fb2019-10-08 11:36:53 +02003579 ckchs = calloc(1, sizeof(*ckchs) + strlen(path) + 1);
3580 if (!ckchs) {
William Lallemand36b84632019-07-18 19:28:17 +02003581 memprintf(err, "%sunable to allocate memory.\n", err && *err ? *err : "");
3582 goto end;
3583 }
William Lallemande3af8fb2019-10-08 11:36:53 +02003584 ckchs->ckch = calloc(1, sizeof(*ckchs->ckch) * (multi ? SSL_SOCK_NUM_KEYTYPES : 1));
William Lallemand36b84632019-07-18 19:28:17 +02003585
William Lallemande3af8fb2019-10-08 11:36:53 +02003586 if (!ckchs->ckch) {
William Lallemand36b84632019-07-18 19:28:17 +02003587 memprintf(err, "%sunable to allocate memory.\n", err && *err ? *err : "");
3588 goto end;
3589 }
3590
William Lallemand9117de92019-10-04 00:29:42 +02003591 LIST_INIT(&ckchs->ckch_inst);
3592
William Lallemand36b84632019-07-18 19:28:17 +02003593 if (!multi) {
3594
William Lallemand96a9c972019-10-17 11:56:17 +02003595 if (ssl_sock_load_files_into_ckch(path, ckchs->ckch, err) == 1)
William Lallemand36b84632019-07-18 19:28:17 +02003596 goto end;
3597
William Lallemande3af8fb2019-10-08 11:36:53 +02003598 /* insert into the ckchs tree */
3599 memcpy(ckchs->path, path, strlen(path) + 1);
3600 ebst_insert(&ckchs_tree, &ckchs->node);
William Lallemand36b84632019-07-18 19:28:17 +02003601 } else {
3602 int found = 0;
William Lallemandc4ecddf2019-07-31 16:50:08 +02003603#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
3604 char fp[MAXPATHLEN+1] = {0};
3605 int n = 0;
William Lallemand36b84632019-07-18 19:28:17 +02003606
3607 /* Load all possible certs and keys */
3608 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
3609 struct stat buf;
3610 snprintf(fp, sizeof(fp), "%s.%s", path, SSL_SOCK_KEYTYPE_NAMES[n]);
3611 if (stat(fp, &buf) == 0) {
William Lallemand96a9c972019-10-17 11:56:17 +02003612 if (ssl_sock_load_files_into_ckch(fp, &ckchs->ckch[n], err) == 1)
William Lallemand36b84632019-07-18 19:28:17 +02003613 goto end;
3614 found = 1;
William Lallemande3af8fb2019-10-08 11:36:53 +02003615 ckchs->multi = 1;
William Lallemand36b84632019-07-18 19:28:17 +02003616 }
3617 }
William Lallemandc4ecddf2019-07-31 16:50:08 +02003618#endif
William Lallemand36b84632019-07-18 19:28:17 +02003619
3620 if (!found) {
William Lallemand6e5f2ce2019-08-01 14:43:20 +02003621 memprintf(err, "%sDidn't find any certificate for bundle '%s'.\n", err && *err ? *err : "", path);
William Lallemand36b84632019-07-18 19:28:17 +02003622 goto end;
3623 }
William Lallemande3af8fb2019-10-08 11:36:53 +02003624 /* insert into the ckchs tree */
3625 memcpy(ckchs->path, path, strlen(path) + 1);
3626 ebst_insert(&ckchs_tree, &ckchs->node);
William Lallemand36b84632019-07-18 19:28:17 +02003627 }
William Lallemande3af8fb2019-10-08 11:36:53 +02003628 return ckchs;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003629
William Lallemand36b84632019-07-18 19:28:17 +02003630end:
William Lallemande3af8fb2019-10-08 11:36:53 +02003631 if (ckchs) {
3632 free(ckchs->ckch);
3633 ebmb_delete(&ckchs->node);
William Lallemand6af03992019-07-23 15:00:54 +02003634 }
3635
William Lallemande3af8fb2019-10-08 11:36:53 +02003636 free(ckchs);
William Lallemand36b84632019-07-18 19:28:17 +02003637
3638 return NULL;
3639}
3640
William Lallemandc4ecddf2019-07-31 16:50:08 +02003641#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
3642
William Lallemand36b84632019-07-18 19:28:17 +02003643/*
William Lallemande3af8fb2019-10-08 11:36:53 +02003644 * Take a ckch_store which contains a multi-certificate bundle.
William Lallemand36b84632019-07-18 19:28:17 +02003645 * Group these certificates into a set of SSL_CTX*
yanbzhu08ce6ab2015-12-02 13:01:29 -05003646 * based on shared and unique CN and SAN entries. Add these SSL_CTX* to the SNI tree.
3647 *
Joseph Herlant017b3da2018-11-15 09:07:59 -08003648 * This will allow the user to explicitly group multiple cert/keys for a single purpose
yanbzhu08ce6ab2015-12-02 13:01:29 -05003649 *
Emeric Brun054563d2019-10-17 13:16:58 +02003650 * Returns a bitfield containing the flags:
3651 * ERR_FATAL in any fatal error case
3652 * ERR_ALERT if the reason of the error is available in err
3653 * ERR_WARN if a warning is available into err
William Lallemand36b84632019-07-18 19:28:17 +02003654 *
yanbzhu08ce6ab2015-12-02 13:01:29 -05003655 */
Emeric Brun054563d2019-10-17 13:16:58 +02003656static int ckch_inst_new_load_multi_store(const char *path, struct ckch_store *ckchs,
3657 struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
3658 char **sni_filter, int fcount, struct ckch_inst **ckchi, char **err)
yanbzhu08ce6ab2015-12-02 13:01:29 -05003659{
William Lallemand36b84632019-07-18 19:28:17 +02003660 int i = 0, n = 0;
3661 struct cert_key_and_chain *certs_and_keys;
William Lallemand4b989f22019-10-04 18:36:55 +02003662 struct eb_root sni_keytypes_map = EB_ROOT;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003663 struct ebmb_node *node;
3664 struct ebmb_node *next;
3665 /* Array of SSL_CTX pointers corresponding to each possible combo
3666 * of keytypes
3667 */
3668 struct key_combo_ctx key_combos[SSL_SOCK_POSSIBLE_KT_COMBOS] = { {0} };
Emeric Brun054563d2019-10-17 13:16:58 +02003669 int errcode = 0;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003670 X509_NAME *xname = NULL;
3671 char *str = NULL;
3672#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
3673 STACK_OF(GENERAL_NAME) *names = NULL;
3674#endif
William Lallemand614ca0d2019-10-07 13:52:11 +02003675 struct ckch_inst *ckch_inst;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003676
Emeric Brun054563d2019-10-17 13:16:58 +02003677 *ckchi = NULL;
3678
William Lallemande3af8fb2019-10-08 11:36:53 +02003679 if (!ckchs || !ckchs->ckch || !ckchs->multi) {
William Lallemand36b84632019-07-18 19:28:17 +02003680 memprintf(err, "%sunable to load SSL certificate file '%s' file does not exist.\n",
3681 err && *err ? *err : "", path);
Emeric Brun054563d2019-10-17 13:16:58 +02003682 return ERR_ALERT | ERR_FATAL;
William Lallemand614ca0d2019-10-07 13:52:11 +02003683 }
3684
3685 ckch_inst = ckch_inst_new();
3686 if (!ckch_inst) {
3687 memprintf(err, "%sunable to allocate SSL context for cert '%s'.\n",
3688 err && *err ? *err : "", path);
Emeric Brun054563d2019-10-17 13:16:58 +02003689 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemand614ca0d2019-10-07 13:52:11 +02003690 goto end;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003691 }
3692
William Lallemande3af8fb2019-10-08 11:36:53 +02003693 certs_and_keys = ckchs->ckch;
William Lallemand36b84632019-07-18 19:28:17 +02003694
William Lallemand150bfa82019-09-19 17:12:49 +02003695 /* at least one of the instances is using filters during the config
3696 * parsing, that's ok to inherit this during loading on CLI */
3697 ckchs->filters = !!fcount;
3698
yanbzhu08ce6ab2015-12-02 13:01:29 -05003699 /* Process each ckch and update keytypes for each CN/SAN
3700 * for example, if CN/SAN www.a.com is associated with
3701 * certs with keytype 0 and 2, then at the end of the loop,
3702 * www.a.com will have:
3703 * keyindex = 0 | 1 | 4 = 5
3704 */
3705 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
William Lallemand28a8fce2019-10-04 17:36:55 +02003706 int ret;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003707
3708 if (!ssl_sock_is_ckch_valid(&certs_and_keys[n]))
3709 continue;
3710
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003711 if (fcount) {
William Lallemand28a8fce2019-10-04 17:36:55 +02003712 for (i = 0; i < fcount; i++) {
3713 ret = ssl_sock_populate_sni_keytypes_hplr(sni_filter[i], &sni_keytypes_map, n);
3714 if (ret < 0) {
3715 memprintf(err, "%sunable to allocate SSL context.\n",
3716 err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02003717 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemand28a8fce2019-10-04 17:36:55 +02003718 goto end;
3719 }
3720 }
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003721 } else {
3722 /* A lot of the following code is OpenSSL boilerplate for processing CN's and SAN's,
3723 * so the line that contains logic is marked via comments
3724 */
3725 xname = X509_get_subject_name(certs_and_keys[n].cert);
3726 i = -1;
3727 while ((i = X509_NAME_get_index_by_NID(xname, NID_commonName, i)) != -1) {
3728 X509_NAME_ENTRY *entry = X509_NAME_get_entry(xname, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003729 ASN1_STRING *value;
3730 value = X509_NAME_ENTRY_get_data(entry);
3731 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003732 /* Important line is here */
William Lallemand28a8fce2019-10-04 17:36:55 +02003733 ret = ssl_sock_populate_sni_keytypes_hplr(str, &sni_keytypes_map, n);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003734
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003735 OPENSSL_free(str);
3736 str = NULL;
William Lallemand28a8fce2019-10-04 17:36:55 +02003737 if (ret < 0) {
3738 memprintf(err, "%sunable to allocate SSL context.\n",
3739 err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02003740 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemand28a8fce2019-10-04 17:36:55 +02003741 goto end;
3742 }
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003743 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003744 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003745
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003746 /* Do the above logic for each SAN */
yanbzhu08ce6ab2015-12-02 13:01:29 -05003747#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003748 names = X509_get_ext_d2i(certs_and_keys[n].cert, NID_subject_alt_name, NULL, NULL);
3749 if (names) {
3750 for (i = 0; i < sk_GENERAL_NAME_num(names); i++) {
3751 GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003752
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003753 if (name->type == GEN_DNS) {
3754 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
3755 /* Important line is here */
William Lallemand28a8fce2019-10-04 17:36:55 +02003756 ret = ssl_sock_populate_sni_keytypes_hplr(str, &sni_keytypes_map, n);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003757
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003758 OPENSSL_free(str);
3759 str = NULL;
William Lallemand28a8fce2019-10-04 17:36:55 +02003760 if (ret < 0) {
3761 memprintf(err, "%sunable to allocate SSL context.\n",
3762 err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02003763 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemand28a8fce2019-10-04 17:36:55 +02003764 goto end;
3765 }
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003766 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003767 }
3768 }
3769 }
3770 }
3771#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
3772 }
3773
3774 /* If no files found, return error */
3775 if (eb_is_empty(&sni_keytypes_map)) {
3776 memprintf(err, "%sunable to load SSL certificate file '%s' file does not exist.\n",
3777 err && *err ? *err : "", path);
Emeric Brun054563d2019-10-17 13:16:58 +02003778 errcode |= ERR_ALERT | ERR_FATAL;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003779 goto end;
3780 }
3781
3782 /* We now have a map of CN/SAN to keytypes that are loaded in
3783 * Iterate through the map to create the SSL_CTX's (if needed)
3784 * and add each CTX to the SNI tree
3785 *
3786 * Some math here:
Joseph Herlant017b3da2018-11-15 09:07:59 -08003787 * There are 2^n - 1 possible combinations, each unique
yanbzhu08ce6ab2015-12-02 13:01:29 -05003788 * combination is denoted by the key in the map. Each key
3789 * has a value between 1 and 2^n - 1. Conveniently, the array
3790 * of SSL_CTX* is sized 2^n. So, we can simply use the i'th
3791 * entry in the array to correspond to the unique combo (key)
3792 * associated with i. This unique key combo (i) will be associated
3793 * with combos[i-1]
3794 */
3795
3796 node = ebmb_first(&sni_keytypes_map);
3797 while (node) {
3798 SSL_CTX *cur_ctx;
Bertrand Jacquin33423092016-11-13 16:37:13 +00003799 char cur_file[MAXPATHLEN+1];
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003800 const struct pkey_info kinfo = { .sig = TLSEXT_signature_anonymous, .bits = 0 };
yanbzhu08ce6ab2015-12-02 13:01:29 -05003801
3802 str = (char *)container_of(node, struct sni_keytype, name)->name.key;
3803 i = container_of(node, struct sni_keytype, name)->keytypes;
3804 cur_ctx = key_combos[i-1].ctx;
3805
3806 if (cur_ctx == NULL) {
3807 /* need to create SSL_CTX */
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003808 cur_ctx = SSL_CTX_new(SSLv23_server_method());
yanbzhu08ce6ab2015-12-02 13:01:29 -05003809 if (cur_ctx == NULL) {
3810 memprintf(err, "%sunable to allocate SSL context.\n",
3811 err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02003812 errcode |= ERR_ALERT | ERR_FATAL;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003813 goto end;
3814 }
3815
yanbzhube2774d2015-12-10 15:07:30 -05003816 /* Load all required certs/keys/chains/OCSPs info into SSL_CTX */
yanbzhu08ce6ab2015-12-02 13:01:29 -05003817 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
3818 if (i & (1<<n)) {
3819 /* Key combo contains ckch[n] */
Bertrand Jacquin33423092016-11-13 16:37:13 +00003820 snprintf(cur_file, MAXPATHLEN+1, "%s.%s", path, SSL_SOCK_KEYTYPE_NAMES[n]);
Emeric Bruna96b5822019-10-17 13:25:14 +02003821 errcode |= ssl_sock_put_ckch_into_ctx(cur_file, &certs_and_keys[n], cur_ctx, err);
3822 if (errcode & ERR_CODE)
yanbzhu08ce6ab2015-12-02 13:01:29 -05003823 goto end;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003824 }
3825 }
3826
yanbzhu08ce6ab2015-12-02 13:01:29 -05003827 /* Update key_combos */
3828 key_combos[i-1].ctx = cur_ctx;
3829 }
3830
3831 /* Update SNI Tree */
William Lallemand9117de92019-10-04 00:29:42 +02003832
William Lallemand1d29c742019-10-04 00:53:29 +02003833 key_combos[i-1].order = ckch_inst_add_cert_sni(cur_ctx, ckch_inst, bind_conf, ssl_conf,
William Lallemandfe49bb32019-10-03 23:46:33 +02003834 kinfo, str, key_combos[i-1].order);
3835 if (key_combos[i-1].order < 0) {
3836 memprintf(err, "%sunable to create a sni context.\n", err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02003837 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemandfe49bb32019-10-03 23:46:33 +02003838 goto end;
3839 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003840 node = ebmb_next(node);
3841 }
3842
3843
3844 /* Mark a default context if none exists, using the ctx that has the most shared keys */
3845 if (!bind_conf->default_ctx) {
3846 for (i = SSL_SOCK_POSSIBLE_KT_COMBOS - 1; i >= 0; i--) {
3847 if (key_combos[i].ctx) {
3848 bind_conf->default_ctx = key_combos[i].ctx;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003849 bind_conf->default_ssl_conf = ssl_conf;
William Lallemand21724f02019-11-04 17:56:13 +01003850 ckch_inst->is_default = 1;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003851 break;
3852 }
3853 }
3854 }
3855
William Lallemand614ca0d2019-10-07 13:52:11 +02003856 ckch_inst->bind_conf = bind_conf;
William Lallemand150bfa82019-09-19 17:12:49 +02003857 ckch_inst->ssl_conf = ssl_conf;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003858end:
3859
3860 if (names)
3861 sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
3862
yanbzhu08ce6ab2015-12-02 13:01:29 -05003863 node = ebmb_first(&sni_keytypes_map);
3864 while (node) {
3865 next = ebmb_next(node);
3866 ebmb_delete(node);
William Lallemand8ed5b962019-10-04 17:24:39 +02003867 free(ebmb_entry(node, struct sni_keytype, name));
yanbzhu08ce6ab2015-12-02 13:01:29 -05003868 node = next;
3869 }
3870
Emeric Brun054563d2019-10-17 13:16:58 +02003871 if (errcode & ERR_CODE && ckch_inst) {
William Lallemand0c6d12f2019-10-04 18:38:51 +02003872 struct sni_ctx *sc0, *sc0b;
3873
3874 /* free the SSL_CTX in case of error */
3875 for (i = 0; i < SSL_SOCK_POSSIBLE_KT_COMBOS; i++) {
3876 if (key_combos[i].ctx)
3877 SSL_CTX_free(key_combos[i].ctx);
3878 }
3879
3880 /* free the sni_ctx in case of error */
3881 list_for_each_entry_safe(sc0, sc0b, &ckch_inst->sni_ctx, by_ckch_inst) {
3882
3883 ebmb_delete(&sc0->name);
3884 LIST_DEL(&sc0->by_ckch_inst);
3885 free(sc0);
3886 }
William Lallemand614ca0d2019-10-07 13:52:11 +02003887 free(ckch_inst);
3888 ckch_inst = NULL;
William Lallemand0c6d12f2019-10-04 18:38:51 +02003889 }
3890
Emeric Brun054563d2019-10-17 13:16:58 +02003891 *ckchi = ckch_inst;
3892 return errcode;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003893}
3894#else
3895/* This is a dummy, that just logs an error and returns error */
Emeric Brun054563d2019-10-17 13:16:58 +02003896static int ckch_inst_new_load_multi_store(const char *path, struct ckch_store *ckchs,
3897 struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
3898 char **sni_filter, int fcount, struct ckch_inst **ckchi, char **err)
yanbzhu08ce6ab2015-12-02 13:01:29 -05003899{
3900 memprintf(err, "%sunable to stat SSL certificate from file '%s' : %s.\n",
3901 err && *err ? *err : "", path, strerror(errno));
Emeric Brun054563d2019-10-17 13:16:58 +02003902 return ERR_ALERT | ERR_FATAL;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003903}
3904
Willy Tarreau9a1ab082019-05-09 13:26:41 +02003905#endif /* #if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL: Support for loading multiple certs into a single SSL_CTX */
yanbzhu488a4d22015-12-01 15:16:07 -05003906
William Lallemand614ca0d2019-10-07 13:52:11 +02003907/*
3908 * This function allocate a ckch_inst and create its snis
Emeric Brun054563d2019-10-17 13:16:58 +02003909 *
3910 * Returns a bitfield containing the flags:
3911 * ERR_FATAL in any fatal error case
3912 * ERR_ALERT if the reason of the error is available in err
3913 * ERR_WARN if a warning is available into err
William Lallemand614ca0d2019-10-07 13:52:11 +02003914 */
Emeric Brun054563d2019-10-17 13:16:58 +02003915static int ckch_inst_new_load_store(const char *path, struct ckch_store *ckchs, struct bind_conf *bind_conf,
3916 struct ssl_bind_conf *ssl_conf, char **sni_filter, int fcount, struct ckch_inst **ckchi, char **err)
Emeric Brunfc0421f2012-09-07 17:30:07 +02003917{
William Lallemandc9402072019-05-15 15:33:54 +02003918 SSL_CTX *ctx;
William Lallemandc9402072019-05-15 15:33:54 +02003919 int i;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003920 int order = 0;
3921 X509_NAME *xname;
3922 char *str;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003923 EVP_PKEY *pkey;
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003924 struct pkey_info kinfo = { .sig = TLSEXT_signature_anonymous, .bits = 0 };
Emeric Brunfc0421f2012-09-07 17:30:07 +02003925#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
3926 STACK_OF(GENERAL_NAME) *names;
3927#endif
William Lallemand36b84632019-07-18 19:28:17 +02003928 struct cert_key_and_chain *ckch;
William Lallemand614ca0d2019-10-07 13:52:11 +02003929 struct ckch_inst *ckch_inst = NULL;
Emeric Brun054563d2019-10-17 13:16:58 +02003930 int errcode = 0;
3931
3932 *ckchi = NULL;
William Lallemanda59191b2019-05-15 16:08:56 +02003933
William Lallemande3af8fb2019-10-08 11:36:53 +02003934 if (!ckchs || !ckchs->ckch)
Emeric Brun054563d2019-10-17 13:16:58 +02003935 return ERR_FATAL;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003936
William Lallemande3af8fb2019-10-08 11:36:53 +02003937 ckch = ckchs->ckch;
William Lallemand36b84632019-07-18 19:28:17 +02003938
William Lallemand150bfa82019-09-19 17:12:49 +02003939 /* at least one of the instances is using filters during the config
3940 * parsing, that's ok to inherit this during loading on CLI */
3941 ckchs->filters = !!fcount;
3942
William Lallemandc9402072019-05-15 15:33:54 +02003943 ctx = SSL_CTX_new(SSLv23_server_method());
3944 if (!ctx) {
3945 memprintf(err, "%sunable to allocate SSL context for cert '%s'.\n",
3946 err && *err ? *err : "", path);
Emeric Brun054563d2019-10-17 13:16:58 +02003947 errcode |= ERR_ALERT | ERR_FATAL;
3948 goto error;
William Lallemandc9402072019-05-15 15:33:54 +02003949 }
3950
Emeric Bruna96b5822019-10-17 13:25:14 +02003951 errcode |= ssl_sock_put_ckch_into_ctx(path, ckch, ctx, err);
3952 if (errcode & ERR_CODE)
William Lallemand614ca0d2019-10-07 13:52:11 +02003953 goto error;
William Lallemand614ca0d2019-10-07 13:52:11 +02003954
3955 ckch_inst = ckch_inst_new();
3956 if (!ckch_inst) {
3957 memprintf(err, "%sunable to allocate SSL context for cert '%s'.\n",
3958 err && *err ? *err : "", path);
Emeric Brun054563d2019-10-17 13:16:58 +02003959 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemandd9199372019-10-04 15:37:05 +02003960 goto error;
William Lallemandc9402072019-05-15 15:33:54 +02003961 }
3962
William Lallemand36b84632019-07-18 19:28:17 +02003963 pkey = X509_get_pubkey(ckch->cert);
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003964 if (pkey) {
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003965 kinfo.bits = EVP_PKEY_bits(pkey);
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003966 switch(EVP_PKEY_base_id(pkey)) {
3967 case EVP_PKEY_RSA:
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003968 kinfo.sig = TLSEXT_signature_rsa;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003969 break;
3970 case EVP_PKEY_EC:
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003971 kinfo.sig = TLSEXT_signature_ecdsa;
3972 break;
3973 case EVP_PKEY_DSA:
3974 kinfo.sig = TLSEXT_signature_dsa;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003975 break;
3976 }
3977 EVP_PKEY_free(pkey);
3978 }
3979
Emeric Brun50bcecc2013-04-22 13:05:23 +02003980 if (fcount) {
William Lallemandfe49bb32019-10-03 23:46:33 +02003981 while (fcount--) {
William Lallemand1d29c742019-10-04 00:53:29 +02003982 order = ckch_inst_add_cert_sni(ctx, ckch_inst, bind_conf, ssl_conf, kinfo, sni_filter[fcount], order);
William Lallemandfe49bb32019-10-03 23:46:33 +02003983 if (order < 0) {
3984 memprintf(err, "%sunable to create a sni context.\n", err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02003985 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemandd9199372019-10-04 15:37:05 +02003986 goto error;
William Lallemandfe49bb32019-10-03 23:46:33 +02003987 }
3988 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003989 }
3990 else {
Emeric Brunfc0421f2012-09-07 17:30:07 +02003991#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
William Lallemand36b84632019-07-18 19:28:17 +02003992 names = X509_get_ext_d2i(ckch->cert, NID_subject_alt_name, NULL, NULL);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003993 if (names) {
3994 for (i = 0; i < sk_GENERAL_NAME_num(names); i++) {
3995 GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i);
3996 if (name->type == GEN_DNS) {
3997 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
William Lallemand1d29c742019-10-04 00:53:29 +02003998 order = ckch_inst_add_cert_sni(ctx, ckch_inst, bind_conf, ssl_conf, kinfo, str, order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003999 OPENSSL_free(str);
William Lallemandfe49bb32019-10-03 23:46:33 +02004000 if (order < 0) {
4001 memprintf(err, "%sunable to create a sni context.\n", err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02004002 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemandd9199372019-10-04 15:37:05 +02004003 goto error;
William Lallemandfe49bb32019-10-03 23:46:33 +02004004 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004005 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004006 }
4007 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004008 sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004009 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004010#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
William Lallemand36b84632019-07-18 19:28:17 +02004011 xname = X509_get_subject_name(ckch->cert);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004012 i = -1;
4013 while ((i = X509_NAME_get_index_by_NID(xname, NID_commonName, i)) != -1) {
4014 X509_NAME_ENTRY *entry = X509_NAME_get_entry(xname, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02004015 ASN1_STRING *value;
4016
4017 value = X509_NAME_ENTRY_get_data(entry);
4018 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
William Lallemand1d29c742019-10-04 00:53:29 +02004019 order = ckch_inst_add_cert_sni(ctx, ckch_inst, bind_conf, ssl_conf, kinfo, str, order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004020 OPENSSL_free(str);
William Lallemandfe49bb32019-10-03 23:46:33 +02004021 if (order < 0) {
4022 memprintf(err, "%sunable to create a sni context.\n", err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02004023 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemandd9199372019-10-04 15:37:05 +02004024 goto error;
William Lallemandfe49bb32019-10-03 23:46:33 +02004025 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004026 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004027 }
4028 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004029 /* we must not free the SSL_CTX anymore below, since it's already in
4030 * the tree, so it will be discovered and cleaned in time.
4031 */
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02004032
Emeric Brunfc0421f2012-09-07 17:30:07 +02004033#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004034 if (bind_conf->default_ctx) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02004035 memprintf(err, "%sthis version of openssl cannot load multiple SSL certificates.\n",
4036 err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02004037 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemandd9199372019-10-04 15:37:05 +02004038 goto error;
Emeric Brunfc0421f2012-09-07 17:30:07 +02004039 }
4040#endif
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004041 if (!bind_conf->default_ctx) {
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004042 bind_conf->default_ctx = ctx;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004043 bind_conf->default_ssl_conf = ssl_conf;
William Lallemand21724f02019-11-04 17:56:13 +01004044 ckch_inst->is_default = 1;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004045 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004046
William Lallemand9117de92019-10-04 00:29:42 +02004047 /* everything succeed, the ckch instance can be used */
4048 ckch_inst->bind_conf = bind_conf;
William Lallemand150bfa82019-09-19 17:12:49 +02004049 ckch_inst->ssl_conf = ssl_conf;
William Lallemand9117de92019-10-04 00:29:42 +02004050
Emeric Brun054563d2019-10-17 13:16:58 +02004051 *ckchi = ckch_inst;
4052 return errcode;
William Lallemandd9199372019-10-04 15:37:05 +02004053
4054error:
4055 /* free the allocated sni_ctxs */
William Lallemand614ca0d2019-10-07 13:52:11 +02004056 if (ckch_inst) {
William Lallemandd9199372019-10-04 15:37:05 +02004057 struct sni_ctx *sc0, *sc0b;
4058
4059 list_for_each_entry_safe(sc0, sc0b, &ckch_inst->sni_ctx, by_ckch_inst) {
4060
4061 ebmb_delete(&sc0->name);
4062 LIST_DEL(&sc0->by_ckch_inst);
4063 free(sc0);
4064 }
William Lallemand614ca0d2019-10-07 13:52:11 +02004065 free(ckch_inst);
4066 ckch_inst = NULL;
William Lallemandd9199372019-10-04 15:37:05 +02004067 }
4068 /* We only created 1 SSL_CTX so we can free it there */
4069 SSL_CTX_free(ctx);
4070
Emeric Brun054563d2019-10-17 13:16:58 +02004071 return errcode;
Emeric Brunfc0421f2012-09-07 17:30:07 +02004072}
4073
Willy Tarreau8c5414a2019-10-16 17:06:25 +02004074/* Returns a set of ERR_* flags possibly with an error in <err>. */
William Lallemand614ca0d2019-10-07 13:52:11 +02004075static int ssl_sock_load_ckchs(const char *path, struct ckch_store *ckchs,
4076 struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
4077 char **sni_filter, int fcount, char **err)
4078{
4079 struct ckch_inst *ckch_inst = NULL;
Emeric Brun054563d2019-10-17 13:16:58 +02004080 int errcode = 0;
William Lallemand614ca0d2019-10-07 13:52:11 +02004081
4082 /* we found the ckchs in the tree, we can use it directly */
4083 if (ckchs->multi)
Emeric Brun054563d2019-10-17 13:16:58 +02004084 errcode |= ckch_inst_new_load_multi_store(path, ckchs, bind_conf, ssl_conf, sni_filter, fcount, &ckch_inst, err);
William Lallemand614ca0d2019-10-07 13:52:11 +02004085 else
Emeric Brun054563d2019-10-17 13:16:58 +02004086 errcode |= ckch_inst_new_load_store(path, ckchs, bind_conf, ssl_conf, sni_filter, fcount, &ckch_inst, err);
William Lallemand614ca0d2019-10-07 13:52:11 +02004087
Emeric Brun054563d2019-10-17 13:16:58 +02004088 if (errcode & ERR_CODE)
4089 return errcode;
William Lallemand614ca0d2019-10-07 13:52:11 +02004090
4091 ssl_sock_load_cert_sni(ckch_inst, bind_conf);
4092
4093 /* succeed, add the instance to the ckch_store's list of instance */
4094 LIST_ADDQ(&ckchs->ckch_inst, &ckch_inst->by_ckchs);
Emeric Brun054563d2019-10-17 13:16:58 +02004095 return errcode;
William Lallemand614ca0d2019-10-07 13:52:11 +02004096}
4097
4098
Willy Tarreaubbc91962019-10-16 16:42:19 +02004099/* Returns a set of ERR_* flags possibly with an error in <err>. */
Willy Tarreau03209342016-12-22 17:08:28 +01004100int ssl_sock_load_cert(char *path, struct bind_conf *bind_conf, char **err)
Emeric Brunfc0421f2012-09-07 17:30:07 +02004101{
Cyril Bonté3180f7b2015-01-25 00:16:08 +01004102 struct dirent **de_list;
4103 int i, n;
Emeric Brunfc0421f2012-09-07 17:30:07 +02004104 DIR *dir;
4105 struct stat buf;
Willy Tarreauee2663b2012-12-06 11:36:59 +01004106 char *end;
4107 char fp[MAXPATHLEN+1];
Emeric Brunfc0421f2012-09-07 17:30:07 +02004108 int cfgerr = 0;
William Lallemande3af8fb2019-10-08 11:36:53 +02004109 struct ckch_store *ckchs;
Willy Tarreau9a1ab082019-05-09 13:26:41 +02004110#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
yanbzhu63ea8462015-12-09 13:35:14 -05004111 int is_bundle;
4112 int j;
4113#endif
William Lallemande3af8fb2019-10-08 11:36:53 +02004114 if ((ckchs = ckchs_lookup(path))) {
William Lallemande3af8fb2019-10-08 11:36:53 +02004115 /* we found the ckchs in the tree, we can use it directly */
Willy Tarreau8c5414a2019-10-16 17:06:25 +02004116 return ssl_sock_load_ckchs(path, ckchs, bind_conf, NULL, NULL, 0, err);
William Lallemand6af03992019-07-23 15:00:54 +02004117 }
4118
yanbzhu08ce6ab2015-12-02 13:01:29 -05004119 if (stat(path, &buf) == 0) {
4120 dir = opendir(path);
William Lallemand36b84632019-07-18 19:28:17 +02004121 if (!dir) {
William Lallemande3af8fb2019-10-08 11:36:53 +02004122 ckchs = ckchs_load_cert_file(path, 0, err);
4123 if (!ckchs)
Willy Tarreaubbc91962019-10-16 16:42:19 +02004124 return ERR_ALERT | ERR_FATAL;
4125
Willy Tarreau8c5414a2019-10-16 17:06:25 +02004126 return ssl_sock_load_ckchs(path, ckchs, bind_conf, NULL, NULL, 0, err);
William Lallemand36b84632019-07-18 19:28:17 +02004127 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004128
yanbzhu08ce6ab2015-12-02 13:01:29 -05004129 /* strip trailing slashes, including first one */
4130 for (end = path + strlen(path) - 1; end >= path && *end == '/'; end--)
4131 *end = 0;
Emeric Brunfc0421f2012-09-07 17:30:07 +02004132
yanbzhu08ce6ab2015-12-02 13:01:29 -05004133 n = scandir(path, &de_list, 0, alphasort);
4134 if (n < 0) {
4135 memprintf(err, "%sunable to scan directory '%s' : %s.\n",
4136 err && *err ? *err : "", path, strerror(errno));
Willy Tarreaubbc91962019-10-16 16:42:19 +02004137 cfgerr |= ERR_ALERT | ERR_FATAL;
yanbzhu08ce6ab2015-12-02 13:01:29 -05004138 }
4139 else {
4140 for (i = 0; i < n; i++) {
4141 struct dirent *de = de_list[i];
Emeric Brun2aab7222014-06-18 18:15:09 +02004142
yanbzhu08ce6ab2015-12-02 13:01:29 -05004143 end = strrchr(de->d_name, '.');
4144 if (end && (!strcmp(end, ".issuer") || !strcmp(end, ".ocsp") || !strcmp(end, ".sctl")))
4145 goto ignore_entry;
Cyril Bonté3180f7b2015-01-25 00:16:08 +01004146
yanbzhu08ce6ab2015-12-02 13:01:29 -05004147 snprintf(fp, sizeof(fp), "%s/%s", path, de->d_name);
4148 if (stat(fp, &buf) != 0) {
4149 memprintf(err, "%sunable to stat SSL certificate from file '%s' : %s.\n",
4150 err && *err ? *err : "", fp, strerror(errno));
Willy Tarreaubbc91962019-10-16 16:42:19 +02004151 cfgerr |= ERR_ALERT | ERR_FATAL;
yanbzhu08ce6ab2015-12-02 13:01:29 -05004152 goto ignore_entry;
4153 }
4154 if (!S_ISREG(buf.st_mode))
4155 goto ignore_entry;
yanbzhu63ea8462015-12-09 13:35:14 -05004156
Willy Tarreau9a1ab082019-05-09 13:26:41 +02004157#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
yanbzhu63ea8462015-12-09 13:35:14 -05004158 is_bundle = 0;
4159 /* Check if current entry in directory is part of a multi-cert bundle */
4160
4161 if (end) {
4162 for (j = 0; j < SSL_SOCK_NUM_KEYTYPES; j++) {
4163 if (!strcmp(end + 1, SSL_SOCK_KEYTYPE_NAMES[j])) {
4164 is_bundle = 1;
4165 break;
4166 }
4167 }
4168
4169 if (is_bundle) {
yanbzhu63ea8462015-12-09 13:35:14 -05004170 int dp_len;
4171
4172 dp_len = end - de->d_name;
yanbzhu63ea8462015-12-09 13:35:14 -05004173
4174 /* increment i and free de until we get to a non-bundle cert
4175 * Note here that we look at de_list[i + 1] before freeing de
Willy Tarreau05800522019-10-29 10:48:50 +01004176 * this is important since ignore_entry will free de. This also
4177 * guarantees that de->d_name continues to hold the same prefix.
yanbzhu63ea8462015-12-09 13:35:14 -05004178 */
Willy Tarreau05800522019-10-29 10:48:50 +01004179 while (i + 1 < n && !strncmp(de_list[i + 1]->d_name, de->d_name, dp_len)) {
yanbzhu63ea8462015-12-09 13:35:14 -05004180 free(de);
4181 i++;
4182 de = de_list[i];
4183 }
4184
Willy Tarreau05800522019-10-29 10:48:50 +01004185 snprintf(fp, sizeof(fp), "%s/%.*s", path, dp_len, de->d_name);
William Lallemande3af8fb2019-10-08 11:36:53 +02004186 if ((ckchs = ckchs_lookup(fp)) == NULL)
4187 ckchs = ckchs_load_cert_file(fp, 1, err);
4188 if (!ckchs)
Willy Tarreaubbc91962019-10-16 16:42:19 +02004189 cfgerr |= ERR_ALERT | ERR_FATAL;
Willy Tarreau8c5414a2019-10-16 17:06:25 +02004190 else
4191 cfgerr |= ssl_sock_load_ckchs(path, ckchs, bind_conf, NULL, NULL, 0, err);
yanbzhu63ea8462015-12-09 13:35:14 -05004192 /* Successfully processed the bundle */
4193 goto ignore_entry;
4194 }
4195 }
4196
4197#endif
William Lallemande3af8fb2019-10-08 11:36:53 +02004198 if ((ckchs = ckchs_lookup(fp)) == NULL)
4199 ckchs = ckchs_load_cert_file(fp, 0, err);
4200 if (!ckchs)
Willy Tarreaubbc91962019-10-16 16:42:19 +02004201 cfgerr |= ERR_ALERT | ERR_FATAL;
William Lallemand614ca0d2019-10-07 13:52:11 +02004202 else
Willy Tarreau8c5414a2019-10-16 17:06:25 +02004203 cfgerr |= ssl_sock_load_ckchs(path, ckchs, bind_conf, NULL, NULL, 0, err);
William Lallemand36b84632019-07-18 19:28:17 +02004204
yanbzhu08ce6ab2015-12-02 13:01:29 -05004205ignore_entry:
4206 free(de);
Cyril Bonté3180f7b2015-01-25 00:16:08 +01004207 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05004208 free(de_list);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004209 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05004210 closedir(dir);
4211 return cfgerr;
Emeric Brunfc0421f2012-09-07 17:30:07 +02004212 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05004213
William Lallemande3af8fb2019-10-08 11:36:53 +02004214 ckchs = ckchs_load_cert_file(path, 1, err);
4215 if (!ckchs)
Willy Tarreaubbc91962019-10-16 16:42:19 +02004216 return ERR_ALERT | ERR_FATAL;
4217
Willy Tarreau8c5414a2019-10-16 17:06:25 +02004218 cfgerr |= ssl_sock_load_ckchs(path, ckchs, bind_conf, NULL, NULL, 0, err);
yanbzhu08ce6ab2015-12-02 13:01:29 -05004219
Emeric Brunfc0421f2012-09-07 17:30:07 +02004220 return cfgerr;
4221}
4222
Thierry Fournier383085f2013-01-24 14:15:43 +01004223/* Make sure openssl opens /dev/urandom before the chroot. The work is only
4224 * done once. Zero is returned if the operation fails. No error is returned
4225 * if the random is said as not implemented, because we expect that openssl
4226 * will use another method once needed.
4227 */
4228static int ssl_initialize_random()
4229{
4230 unsigned char random;
4231 static int random_initialized = 0;
4232
4233 if (!random_initialized && RAND_bytes(&random, 1) != 0)
4234 random_initialized = 1;
4235
4236 return random_initialized;
4237}
4238
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004239/* release ssl bind conf */
4240void ssl_sock_free_ssl_conf(struct ssl_bind_conf *conf)
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004241{
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004242 if (conf) {
Bernard Spil13c53f82018-02-15 13:34:58 +01004243#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004244 free(conf->npn_str);
4245 conf->npn_str = NULL;
4246#endif
4247#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
4248 free(conf->alpn_str);
4249 conf->alpn_str = NULL;
4250#endif
4251 free(conf->ca_file);
4252 conf->ca_file = NULL;
4253 free(conf->crl_file);
4254 conf->crl_file = NULL;
4255 free(conf->ciphers);
4256 conf->ciphers = NULL;
Emmanuel Hocdet839af572019-05-14 16:27:35 +02004257#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02004258 free(conf->ciphersuites);
4259 conf->ciphersuites = NULL;
4260#endif
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004261 free(conf->curves);
4262 conf->curves = NULL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004263 free(conf->ecdhe);
4264 conf->ecdhe = NULL;
4265 }
4266}
4267
Willy Tarreaubbc91962019-10-16 16:42:19 +02004268/* Returns a set of ERR_* flags possibly with an error in <err>. */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004269int ssl_sock_load_cert_list_file(char *file, struct bind_conf *bind_conf, struct proxy *curproxy, char **err)
4270{
4271 char thisline[CRT_LINESIZE];
4272 char path[MAXPATHLEN+1];
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004273 FILE *f;
yanbzhu1b04e5b2015-12-02 13:54:14 -05004274 struct stat buf;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004275 int linenum = 0;
4276 int cfgerr = 0;
William Lallemande3af8fb2019-10-08 11:36:53 +02004277 struct ckch_store *ckchs;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004278
Willy Tarreauad1731d2013-04-02 17:35:58 +02004279 if ((f = fopen(file, "r")) == NULL) {
4280 memprintf(err, "cannot open file '%s' : %s", file, strerror(errno));
Willy Tarreaubbc91962019-10-16 16:42:19 +02004281 return ERR_ALERT | ERR_FATAL;
Willy Tarreauad1731d2013-04-02 17:35:58 +02004282 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004283
4284 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004285 int arg, newarg, cur_arg, i, ssl_b = 0, ssl_e = 0;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004286 char *end;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004287 char *args[MAX_CRT_ARGS + 1];
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004288 char *line = thisline;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004289 char *crt_path;
4290 struct ssl_bind_conf *ssl_conf = NULL;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004291
4292 linenum++;
4293 end = line + strlen(line);
4294 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
4295 /* Check if we reached the limit and the last char is not \n.
4296 * Watch out for the last line without the terminating '\n'!
4297 */
Willy Tarreauad1731d2013-04-02 17:35:58 +02004298 memprintf(err, "line %d too long in file '%s', limit is %d characters",
4299 linenum, file, (int)sizeof(thisline)-1);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004300 cfgerr |= ERR_ALERT | ERR_FATAL;
Willy Tarreauad1731d2013-04-02 17:35:58 +02004301 break;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004302 }
4303
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004304 arg = 0;
Emeric Brun50bcecc2013-04-22 13:05:23 +02004305 newarg = 1;
4306 while (*line) {
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004307 if (*line == '#' || *line == '\n' || *line == '\r') {
4308 /* end of string, end of loop */
4309 *line = 0;
4310 break;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004311 } else if (isspace(*line)) {
Emeric Brun50bcecc2013-04-22 13:05:23 +02004312 newarg = 1;
4313 *line = 0;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004314 } else if (*line == '[') {
4315 if (ssl_b) {
4316 memprintf(err, "too many '[' on line %d in file '%s'.", linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004317 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004318 break;
4319 }
4320 if (!arg) {
4321 memprintf(err, "file must start with a cert on line %d in file '%s'", linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004322 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004323 break;
4324 }
4325 ssl_b = arg;
4326 newarg = 1;
4327 *line = 0;
4328 } else if (*line == ']') {
4329 if (ssl_e) {
4330 memprintf(err, "too many ']' on line %d in file '%s'.", linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004331 cfgerr |= ERR_ALERT | ERR_FATAL;
Emeric Brun50bcecc2013-04-22 13:05:23 +02004332 break;
4333 }
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004334 if (!ssl_b) {
4335 memprintf(err, "missing '[' in line %d in file '%s'.", linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004336 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004337 break;
4338 }
4339 ssl_e = arg;
4340 newarg = 1;
4341 *line = 0;
4342 } else if (newarg) {
4343 if (arg == MAX_CRT_ARGS) {
4344 memprintf(err, "too many args on line %d in file '%s'.", linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004345 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004346 break;
4347 }
Emeric Brun50bcecc2013-04-22 13:05:23 +02004348 newarg = 0;
4349 args[arg++] = line;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004350 }
Emeric Brun50bcecc2013-04-22 13:05:23 +02004351 line++;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004352 }
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02004353 if (cfgerr)
4354 break;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004355 args[arg++] = line;
Willy Tarreauad1731d2013-04-02 17:35:58 +02004356
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004357 /* empty line */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004358 if (!*args[0])
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004359 continue;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004360
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004361 crt_path = args[0];
4362 if (*crt_path != '/' && global_ssl.crt_base) {
4363 if ((strlen(global_ssl.crt_base) + 1 + strlen(crt_path)) > MAXPATHLEN) {
4364 memprintf(err, "'%s' : path too long on line %d in file '%s'",
4365 crt_path, linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004366 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004367 break;
4368 }
4369 snprintf(path, sizeof(path), "%s/%s", global_ssl.crt_base, crt_path);
4370 crt_path = path;
4371 }
4372
4373 ssl_conf = calloc(1, sizeof *ssl_conf);
4374 cur_arg = ssl_b ? ssl_b : 1;
4375 while (cur_arg < ssl_e) {
4376 newarg = 0;
4377 for (i = 0; ssl_bind_kws[i].kw != NULL; i++) {
4378 if (strcmp(ssl_bind_kws[i].kw, args[cur_arg]) == 0) {
4379 newarg = 1;
Willy Tarreaubbc91962019-10-16 16:42:19 +02004380 cfgerr |= ssl_bind_kws[i].parse(args, cur_arg, curproxy, ssl_conf, err);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004381 if (cur_arg + 1 + ssl_bind_kws[i].skip > ssl_e) {
4382 memprintf(err, "ssl args out of '[]' for %s on line %d in file '%s'",
4383 args[cur_arg], linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004384 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004385 }
4386 cur_arg += 1 + ssl_bind_kws[i].skip;
4387 break;
4388 }
4389 }
4390 if (!cfgerr && !newarg) {
4391 memprintf(err, "unknown ssl keyword %s on line %d in file '%s'.",
4392 args[cur_arg], linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004393 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004394 break;
4395 }
4396 }
Willy Tarreaubbc91962019-10-16 16:42:19 +02004397
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004398 if (cfgerr) {
4399 ssl_sock_free_ssl_conf(ssl_conf);
4400 free(ssl_conf);
4401 ssl_conf = NULL;
4402 break;
4403 }
4404
William Lallemande3af8fb2019-10-08 11:36:53 +02004405 if ((ckchs = ckchs_lookup(crt_path)) == NULL) {
William Lallemandeed4bf22019-10-10 11:38:13 +02004406 if (stat(crt_path, &buf) == 0)
William Lallemande3af8fb2019-10-08 11:36:53 +02004407 ckchs = ckchs_load_cert_file(crt_path, 0, err);
Emmanuel Hocdet1503e052019-07-31 18:30:33 +02004408 else
William Lallemande3af8fb2019-10-08 11:36:53 +02004409 ckchs = ckchs_load_cert_file(crt_path, 1, err);
yanbzhu1b04e5b2015-12-02 13:54:14 -05004410 }
4411
Willy Tarreau8c5414a2019-10-16 17:06:25 +02004412 if (!ckchs)
Willy Tarreaubbc91962019-10-16 16:42:19 +02004413 cfgerr |= ERR_ALERT | ERR_FATAL;
Willy Tarreau8c5414a2019-10-16 17:06:25 +02004414 else
4415 cfgerr |= ssl_sock_load_ckchs(crt_path, ckchs, bind_conf, ssl_conf, &args[cur_arg], arg - cur_arg - 1, err);
William Lallemandeed4bf22019-10-10 11:38:13 +02004416
Willy Tarreauad1731d2013-04-02 17:35:58 +02004417 if (cfgerr) {
4418 memprintf(err, "error processing line %d in file '%s' : %s", linenum, file, *err);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004419 break;
Willy Tarreauad1731d2013-04-02 17:35:58 +02004420 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004421 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004422 fclose(f);
4423 return cfgerr;
4424}
4425
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004426/* Create an initial CTX used to start the SSL connection before switchctx */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004427static int
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004428ssl_sock_initial_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02004429{
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004430 SSL_CTX *ctx = NULL;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004431 long options =
Emeric Brunfc0421f2012-09-07 17:30:07 +02004432 SSL_OP_ALL | /* all known workarounds for bugs */
4433 SSL_OP_NO_SSLv2 |
4434 SSL_OP_NO_COMPRESSION |
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02004435 SSL_OP_SINGLE_DH_USE |
Emeric Brun2b58d042012-09-20 17:10:03 +02004436 SSL_OP_SINGLE_ECDH_USE |
Emeric Brun3c4bc6e2012-10-04 18:44:19 +02004437 SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION |
Lukas Tribus926594f2018-05-18 17:55:57 +02004438 SSL_OP_PRIORITIZE_CHACHA |
Emeric Brun3c4bc6e2012-10-04 18:44:19 +02004439 SSL_OP_CIPHER_SERVER_PREFERENCE;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004440 long mode =
Emeric Brunfc0421f2012-09-07 17:30:07 +02004441 SSL_MODE_ENABLE_PARTIAL_WRITE |
4442 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
Willy Tarreau396a1862014-11-13 14:06:52 +01004443 SSL_MODE_RELEASE_BUFFERS |
4444 SSL_MODE_SMALL_BUFFERS;
Emmanuel Hocdet43664762017-08-09 18:26:20 +02004445 struct tls_version_filter *conf_ssl_methods = &bind_conf->ssl_conf.ssl_methods;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004446 int i, min, max, hole;
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004447 int flags = MC_SSL_O_ALL;
4448 int cfgerr = 0;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004449
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004450 ctx = SSL_CTX_new(SSLv23_server_method());
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004451 bind_conf->initial_ctx = ctx;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004452
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004453 if (conf_ssl_methods->flags && (conf_ssl_methods->min || conf_ssl_methods->max))
Christopher Faulet767a84b2017-11-24 16:50:31 +01004454 ha_warning("Proxy '%s': no-sslv3/no-tlsv1x are ignored for bind '%s' at [%s:%d]. "
4455 "Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
4456 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004457 else
4458 flags = conf_ssl_methods->flags;
4459
Emmanuel Hocdetbd695fe2017-05-15 15:53:41 +02004460 min = conf_ssl_methods->min;
4461 max = conf_ssl_methods->max;
4462 /* start with TLSv10 to remove SSLv3 per default */
4463 if (!min && (!max || max >= CONF_TLSV10))
4464 min = CONF_TLSV10;
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004465 /* Real min and max should be determinate with configuration and openssl's capabilities */
Emmanuel Hocdetbd695fe2017-05-15 15:53:41 +02004466 if (min)
4467 flags |= (methodVersions[min].flag - 1);
4468 if (max)
4469 flags |= ~((methodVersions[max].flag << 1) - 1);
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004470 /* find min, max and holes */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004471 min = max = CONF_TLSV_NONE;
4472 hole = 0;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004473 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004474 /* version is in openssl && version not disable in configuration */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004475 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004476 if (min) {
4477 if (hole) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004478 ha_warning("Proxy '%s': SSL/TLS versions range not contiguous for bind '%s' at [%s:%d]. "
4479 "Hole find for %s. Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
4480 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line,
4481 methodVersions[hole].name);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004482 hole = 0;
4483 }
4484 max = i;
4485 }
4486 else {
4487 min = max = i;
4488 }
4489 }
4490 else {
4491 if (min)
4492 hole = i;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004493 }
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004494 if (!min) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004495 ha_alert("Proxy '%s': all SSL/TLS versions are disabled for bind '%s' at [%s:%d].\n",
4496 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004497 cfgerr += 1;
4498 }
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02004499 /* save real min/max in bind_conf */
4500 conf_ssl_methods->min = min;
4501 conf_ssl_methods->max = max;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004502
Willy Tarreau9a1ab082019-05-09 13:26:41 +02004503#if (HA_OPENSSL_VERSION_NUMBER < 0x1010000fL)
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004504 /* Keep force-xxx implementation as it is in older haproxy. It's a
Joseph Herlant017b3da2018-11-15 09:07:59 -08004505 precautionary measure to avoid any surprise with older openssl version. */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004506 if (min == max)
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004507 methodVersions[min].ctx_set_version(ctx, SET_SERVER);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004508 else
4509 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
4510 if (flags & methodVersions[i].flag)
4511 options |= methodVersions[i].option;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004512#else /* openssl >= 1.1.0 */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004513 /* set the max_version is required to cap TLS version or activate new TLS (v1.3) */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004514 methodVersions[min].ctx_set_version(ctx, SET_MIN);
4515 methodVersions[max].ctx_set_version(ctx, SET_MAX);
Emeric Brunfa5c5c82017-04-28 16:19:51 +02004516#endif
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004517
4518 if (bind_conf->ssl_options & BC_SSL_O_NO_TLS_TICKETS)
4519 options |= SSL_OP_NO_TICKET;
4520 if (bind_conf->ssl_options & BC_SSL_O_PREF_CLIE_CIPH)
4521 options &= ~SSL_OP_CIPHER_SERVER_PREFERENCE;
Dirkjan Bussink526894f2019-01-21 09:35:03 -08004522
4523#ifdef SSL_OP_NO_RENEGOTIATION
4524 options |= SSL_OP_NO_RENEGOTIATION;
4525#endif
4526
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004527 SSL_CTX_set_options(ctx, options);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004528
Willy Tarreau5db847a2019-05-09 14:13:35 +02004529#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004530 if (global_ssl.async)
4531 mode |= SSL_MODE_ASYNC;
4532#endif
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004533 SSL_CTX_set_mode(ctx, mode);
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004534 if (global_ssl.life_time)
4535 SSL_CTX_set_timeout(ctx, global_ssl.life_time);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004536
4537#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
4538#ifdef OPENSSL_IS_BORINGSSL
4539 SSL_CTX_set_select_certificate_cb(ctx, ssl_sock_switchctx_cbk);
4540 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_err_cbk);
Willy Tarreau5db847a2019-05-09 14:13:35 +02004541#elif (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Olivier Houchard51088ce2019-01-02 18:46:41 +01004542 if (bind_conf->ssl_conf.early_data) {
4543 SSL_CTX_set_options(ctx, SSL_OP_NO_ANTI_REPLAY);
4544 SSL_CTX_set_max_early_data(ctx, global.tune.bufsize - global.tune.maxrewrite);
4545 }
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02004546 SSL_CTX_set_client_hello_cb(ctx, ssl_sock_switchctx_cbk, NULL);
4547 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_err_cbk);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004548#else
4549 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_cbk);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004550#endif
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02004551 SSL_CTX_set_tlsext_servername_arg(ctx, bind_conf);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004552#endif
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004553 return cfgerr;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004554}
4555
William Lallemand4f45bb92017-10-30 20:08:51 +01004556
4557static inline void sh_ssl_sess_free_blocks(struct shared_block *first, struct shared_block *block)
4558{
4559 if (first == block) {
4560 struct sh_ssl_sess_hdr *sh_ssl_sess = (struct sh_ssl_sess_hdr *)first->data;
4561 if (first->len > 0)
4562 sh_ssl_sess_tree_delete(sh_ssl_sess);
4563 }
4564}
4565
4566/* return first block from sh_ssl_sess */
4567static inline struct shared_block *sh_ssl_sess_first_block(struct sh_ssl_sess_hdr *sh_ssl_sess)
4568{
4569 return (struct shared_block *)((unsigned char *)sh_ssl_sess - ((struct shared_block *)NULL)->data);
4570
4571}
4572
4573/* store a session into the cache
4574 * s_id : session id padded with zero to SSL_MAX_SSL_SESSION_ID_LENGTH
4575 * data: asn1 encoded session
4576 * data_len: asn1 encoded session length
4577 * Returns 1 id session was stored (else 0)
4578 */
4579static int sh_ssl_sess_store(unsigned char *s_id, unsigned char *data, int data_len)
4580{
4581 struct shared_block *first;
4582 struct sh_ssl_sess_hdr *sh_ssl_sess, *oldsh_ssl_sess;
4583
Frédéric Lécaille0bec8072018-10-22 17:55:57 +02004584 first = shctx_row_reserve_hot(ssl_shctx, NULL, data_len + sizeof(struct sh_ssl_sess_hdr));
William Lallemand4f45bb92017-10-30 20:08:51 +01004585 if (!first) {
4586 /* Could not retrieve enough free blocks to store that session */
4587 return 0;
4588 }
4589
4590 /* STORE the key in the first elem */
4591 sh_ssl_sess = (struct sh_ssl_sess_hdr *)first->data;
4592 memcpy(sh_ssl_sess->key_data, s_id, SSL_MAX_SSL_SESSION_ID_LENGTH);
4593 first->len = sizeof(struct sh_ssl_sess_hdr);
4594
4595 /* it returns the already existing node
4596 or current node if none, never returns null */
4597 oldsh_ssl_sess = sh_ssl_sess_tree_insert(sh_ssl_sess);
4598 if (oldsh_ssl_sess != sh_ssl_sess) {
4599 /* NOTE: Row couldn't be in use because we lock read & write function */
4600 /* release the reserved row */
4601 shctx_row_dec_hot(ssl_shctx, first);
4602 /* replace the previous session already in the tree */
4603 sh_ssl_sess = oldsh_ssl_sess;
4604 /* ignore the previous session data, only use the header */
4605 first = sh_ssl_sess_first_block(sh_ssl_sess);
4606 shctx_row_inc_hot(ssl_shctx, first);
4607 first->len = sizeof(struct sh_ssl_sess_hdr);
4608 }
4609
Frédéric Lécaille0bec8072018-10-22 17:55:57 +02004610 if (shctx_row_data_append(ssl_shctx, first, NULL, data, data_len) < 0) {
William Lallemand99b90af2018-01-03 19:15:51 +01004611 shctx_row_dec_hot(ssl_shctx, first);
William Lallemand4f45bb92017-10-30 20:08:51 +01004612 return 0;
William Lallemand99b90af2018-01-03 19:15:51 +01004613 }
4614
4615 shctx_row_dec_hot(ssl_shctx, first);
William Lallemand4f45bb92017-10-30 20:08:51 +01004616
4617 return 1;
4618}
William Lallemanded0b5ad2017-10-30 19:36:36 +01004619
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004620/* SSL callback used when a new session is created while connecting to a server */
4621static int ssl_sess_new_srv_cb(SSL *ssl, SSL_SESSION *sess)
4622{
Thierry FOURNIER28962c92018-06-17 21:37:05 +02004623 struct connection *conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Olivier Houcharde6060c52017-11-16 17:42:52 +01004624 struct server *s;
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004625
Willy Tarreau07d94e42018-09-20 10:57:52 +02004626 s = __objt_server(conn->target);
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004627
Olivier Houcharde6060c52017-11-16 17:42:52 +01004628 if (!(s->ssl_ctx.options & SRV_SSL_O_NO_REUSE)) {
4629 int len;
4630 unsigned char *ptr;
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004631
Olivier Houcharde6060c52017-11-16 17:42:52 +01004632 len = i2d_SSL_SESSION(sess, NULL);
4633 if (s->ssl_ctx.reused_sess[tid].ptr && s->ssl_ctx.reused_sess[tid].allocated_size >= len) {
4634 ptr = s->ssl_ctx.reused_sess[tid].ptr;
4635 } else {
4636 free(s->ssl_ctx.reused_sess[tid].ptr);
4637 ptr = s->ssl_ctx.reused_sess[tid].ptr = malloc(len);
4638 s->ssl_ctx.reused_sess[tid].allocated_size = len;
4639 }
4640 if (s->ssl_ctx.reused_sess[tid].ptr) {
4641 s->ssl_ctx.reused_sess[tid].size = i2d_SSL_SESSION(sess,
4642 &ptr);
4643 }
4644 } else {
4645 free(s->ssl_ctx.reused_sess[tid].ptr);
4646 s->ssl_ctx.reused_sess[tid].ptr = NULL;
4647 }
4648
4649 return 0;
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004650}
4651
Olivier Houcharde6060c52017-11-16 17:42:52 +01004652
William Lallemanded0b5ad2017-10-30 19:36:36 +01004653/* SSL callback used on new session creation */
William Lallemand4f45bb92017-10-30 20:08:51 +01004654int sh_ssl_sess_new_cb(SSL *ssl, SSL_SESSION *sess)
William Lallemanded0b5ad2017-10-30 19:36:36 +01004655{
4656 unsigned char encsess[SHSESS_MAX_DATA_LEN]; /* encoded session */
4657 unsigned char encid[SSL_MAX_SSL_SESSION_ID_LENGTH]; /* encoded id */
4658 unsigned char *p;
4659 int data_len;
Emeric Bruneb469652019-10-08 18:27:37 +02004660 unsigned int sid_length;
William Lallemanded0b5ad2017-10-30 19:36:36 +01004661 const unsigned char *sid_data;
William Lallemanded0b5ad2017-10-30 19:36:36 +01004662
4663 /* Session id is already stored in to key and session id is known
4664 * so we dont store it to keep size.
Emeric Bruneb469652019-10-08 18:27:37 +02004665 * note: SSL_SESSION_set1_id is using
4666 * a memcpy so we need to use a different pointer
4667 * than sid_data or sid_ctx_data to avoid valgrind
4668 * complaining.
William Lallemanded0b5ad2017-10-30 19:36:36 +01004669 */
4670
4671 sid_data = SSL_SESSION_get_id(sess, &sid_length);
Emeric Bruneb469652019-10-08 18:27:37 +02004672
4673 /* copy value in an other buffer */
4674 memcpy(encid, sid_data, sid_length);
4675
4676 /* pad with 0 */
4677 if (sid_length < SSL_MAX_SSL_SESSION_ID_LENGTH)
4678 memset(encid + sid_length, 0, SSL_MAX_SSL_SESSION_ID_LENGTH-sid_length);
4679
4680 /* force length to zero to avoid ASN1 encoding */
4681 SSL_SESSION_set1_id(sess, encid, 0);
4682
4683 /* force length to zero to avoid ASN1 encoding */
4684 SSL_SESSION_set1_id_context(sess, (const unsigned char *)SHCTX_APPNAME, 0);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004685
4686 /* check if buffer is large enough for the ASN1 encoded session */
4687 data_len = i2d_SSL_SESSION(sess, NULL);
4688 if (data_len > SHSESS_MAX_DATA_LEN)
4689 goto err;
4690
4691 p = encsess;
4692
4693 /* process ASN1 session encoding before the lock */
4694 i2d_SSL_SESSION(sess, &p);
4695
William Lallemanded0b5ad2017-10-30 19:36:36 +01004696
William Lallemanda3c77cf2017-10-30 23:44:40 +01004697 shctx_lock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004698 /* store to cache */
William Lallemand4f45bb92017-10-30 20:08:51 +01004699 sh_ssl_sess_store(encid, encsess, data_len);
William Lallemanda3c77cf2017-10-30 23:44:40 +01004700 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004701err:
4702 /* reset original length values */
Emeric Bruneb469652019-10-08 18:27:37 +02004703 SSL_SESSION_set1_id(sess, encid, sid_length);
4704 SSL_SESSION_set1_id_context(sess, (const unsigned char *)SHCTX_APPNAME, strlen(SHCTX_APPNAME));
William Lallemanded0b5ad2017-10-30 19:36:36 +01004705
4706 return 0; /* do not increment session reference count */
4707}
4708
4709/* SSL callback used on lookup an existing session cause none found in internal cache */
William Lallemand4f45bb92017-10-30 20:08:51 +01004710SSL_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 +01004711{
William Lallemand4f45bb92017-10-30 20:08:51 +01004712 struct sh_ssl_sess_hdr *sh_ssl_sess;
William Lallemanded0b5ad2017-10-30 19:36:36 +01004713 unsigned char data[SHSESS_MAX_DATA_LEN], *p;
4714 unsigned char tmpkey[SSL_MAX_SSL_SESSION_ID_LENGTH];
William Lallemanded0b5ad2017-10-30 19:36:36 +01004715 SSL_SESSION *sess;
William Lallemand4f45bb92017-10-30 20:08:51 +01004716 struct shared_block *first;
William Lallemanded0b5ad2017-10-30 19:36:36 +01004717
4718 global.shctx_lookups++;
4719
4720 /* allow the session to be freed automatically by openssl */
4721 *do_copy = 0;
4722
4723 /* tree key is zeros padded sessionid */
4724 if (key_len < SSL_MAX_SSL_SESSION_ID_LENGTH) {
4725 memcpy(tmpkey, key, key_len);
4726 memset(tmpkey + key_len, 0, SSL_MAX_SSL_SESSION_ID_LENGTH - key_len);
4727 key = tmpkey;
4728 }
4729
4730 /* lock cache */
William Lallemanda3c77cf2017-10-30 23:44:40 +01004731 shctx_lock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004732
4733 /* lookup for session */
William Lallemand4f45bb92017-10-30 20:08:51 +01004734 sh_ssl_sess = sh_ssl_sess_tree_lookup(key);
4735 if (!sh_ssl_sess) {
William Lallemanded0b5ad2017-10-30 19:36:36 +01004736 /* no session found: unlock cache and exit */
William Lallemanda3c77cf2017-10-30 23:44:40 +01004737 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004738 global.shctx_misses++;
4739 return NULL;
4740 }
4741
William Lallemand4f45bb92017-10-30 20:08:51 +01004742 /* sh_ssl_sess (shared_block->data) is at the end of shared_block */
4743 first = sh_ssl_sess_first_block(sh_ssl_sess);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004744
William Lallemand4f45bb92017-10-30 20:08:51 +01004745 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 +01004746
William Lallemanda3c77cf2017-10-30 23:44:40 +01004747 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004748
4749 /* decode ASN1 session */
4750 p = data;
William Lallemand4f45bb92017-10-30 20:08:51 +01004751 sess = d2i_SSL_SESSION(NULL, (const unsigned char **)&p, first->len-sizeof(struct sh_ssl_sess_hdr));
William Lallemanded0b5ad2017-10-30 19:36:36 +01004752 /* Reset session id and session id contenxt */
4753 if (sess) {
4754 SSL_SESSION_set1_id(sess, key, key_len);
4755 SSL_SESSION_set1_id_context(sess, (const unsigned char *)SHCTX_APPNAME, strlen(SHCTX_APPNAME));
4756 }
4757
4758 return sess;
4759}
4760
William Lallemand4f45bb92017-10-30 20:08:51 +01004761
William Lallemanded0b5ad2017-10-30 19:36:36 +01004762/* SSL callback used to signal session is no more used in internal cache */
William Lallemand4f45bb92017-10-30 20:08:51 +01004763void sh_ssl_sess_remove_cb(SSL_CTX *ctx, SSL_SESSION *sess)
William Lallemanded0b5ad2017-10-30 19:36:36 +01004764{
William Lallemand4f45bb92017-10-30 20:08:51 +01004765 struct sh_ssl_sess_hdr *sh_ssl_sess;
William Lallemanded0b5ad2017-10-30 19:36:36 +01004766 unsigned char tmpkey[SSL_MAX_SSL_SESSION_ID_LENGTH];
4767 unsigned int sid_length;
4768 const unsigned char *sid_data;
4769 (void)ctx;
4770
4771 sid_data = SSL_SESSION_get_id(sess, &sid_length);
4772 /* tree key is zeros padded sessionid */
4773 if (sid_length < SSL_MAX_SSL_SESSION_ID_LENGTH) {
4774 memcpy(tmpkey, sid_data, sid_length);
4775 memset(tmpkey+sid_length, 0, SSL_MAX_SSL_SESSION_ID_LENGTH - sid_length);
4776 sid_data = tmpkey;
4777 }
4778
William Lallemanda3c77cf2017-10-30 23:44:40 +01004779 shctx_lock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004780
4781 /* lookup for session */
William Lallemand4f45bb92017-10-30 20:08:51 +01004782 sh_ssl_sess = sh_ssl_sess_tree_lookup(sid_data);
4783 if (sh_ssl_sess) {
William Lallemanded0b5ad2017-10-30 19:36:36 +01004784 /* free session */
William Lallemand4f45bb92017-10-30 20:08:51 +01004785 sh_ssl_sess_tree_delete(sh_ssl_sess);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004786 }
4787
4788 /* unlock cache */
William Lallemanda3c77cf2017-10-30 23:44:40 +01004789 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004790}
4791
4792/* Set session cache mode to server and disable openssl internal cache.
4793 * Set shared cache callbacks on an ssl context.
4794 * Shared context MUST be firstly initialized */
William Lallemand4f45bb92017-10-30 20:08:51 +01004795void ssl_set_shctx(SSL_CTX *ctx)
William Lallemanded0b5ad2017-10-30 19:36:36 +01004796{
4797 SSL_CTX_set_session_id_context(ctx, (const unsigned char *)SHCTX_APPNAME, strlen(SHCTX_APPNAME));
4798
4799 if (!ssl_shctx) {
4800 SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF);
4801 return;
4802 }
4803
4804 SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_SERVER |
4805 SSL_SESS_CACHE_NO_INTERNAL |
4806 SSL_SESS_CACHE_NO_AUTO_CLEAR);
4807
4808 /* Set callbacks */
William Lallemand4f45bb92017-10-30 20:08:51 +01004809 SSL_CTX_sess_set_new_cb(ctx, sh_ssl_sess_new_cb);
4810 SSL_CTX_sess_set_get_cb(ctx, sh_ssl_sess_get_cb);
4811 SSL_CTX_sess_set_remove_cb(ctx, sh_ssl_sess_remove_cb);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004812}
4813
William Lallemand8b453912019-11-21 15:48:10 +01004814/*
4815 * This function applies the SSL configuration on a SSL_CTX
4816 * It returns an error code and fills the <err> buffer
4817 */
4818int ssl_sock_prepare_ctx(struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf, SSL_CTX *ctx, char **err)
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004819{
4820 struct proxy *curproxy = bind_conf->frontend;
4821 int cfgerr = 0;
4822 int verify = SSL_VERIFY_NONE;
Willy Tarreau5d4cafb2018-01-04 18:55:19 +01004823 struct ssl_bind_conf __maybe_unused *ssl_conf_cur;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004824 const char *conf_ciphers;
Emmanuel Hocdet839af572019-05-14 16:27:35 +02004825#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02004826 const char *conf_ciphersuites;
4827#endif
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004828 const char *conf_curves = NULL;
Emeric Brunfc0421f2012-09-07 17:30:07 +02004829
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02004830 if (ssl_conf) {
4831 struct tls_version_filter *conf_ssl_methods = &ssl_conf->ssl_methods;
4832 int i, min, max;
4833 int flags = MC_SSL_O_ALL;
4834
4835 /* Real min and max should be determinate with configuration and openssl's capabilities */
Emmanuel Hocdet43664762017-08-09 18:26:20 +02004836 min = conf_ssl_methods->min ? conf_ssl_methods->min : bind_conf->ssl_conf.ssl_methods.min;
4837 max = conf_ssl_methods->max ? conf_ssl_methods->max : bind_conf->ssl_conf.ssl_methods.max;
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02004838 if (min)
4839 flags |= (methodVersions[min].flag - 1);
4840 if (max)
4841 flags |= ~((methodVersions[max].flag << 1) - 1);
4842 min = max = CONF_TLSV_NONE;
4843 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
4844 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
4845 if (min)
4846 max = i;
4847 else
4848 min = max = i;
4849 }
4850 /* save real min/max */
4851 conf_ssl_methods->min = min;
4852 conf_ssl_methods->max = max;
4853 if (!min) {
William Lallemand8b453912019-11-21 15:48:10 +01004854 if (err)
4855 memprintf(err, "%sProxy '%s': all SSL/TLS versions are disabled for bind '%s' at [%s:%d].\n",
4856 *err ? *err : "", bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
4857 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02004858 }
4859 }
4860
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004861 switch ((ssl_conf && ssl_conf->verify) ? ssl_conf->verify : bind_conf->ssl_conf.verify) {
Emeric Brun850efd52014-01-29 12:24:34 +01004862 case SSL_SOCK_VERIFY_NONE:
4863 verify = SSL_VERIFY_NONE;
4864 break;
4865 case SSL_SOCK_VERIFY_OPTIONAL:
4866 verify = SSL_VERIFY_PEER;
4867 break;
4868 case SSL_SOCK_VERIFY_REQUIRED:
4869 verify = SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
4870 break;
4871 }
4872 SSL_CTX_set_verify(ctx, verify, ssl_sock_bind_verifycbk);
4873 if (verify & SSL_VERIFY_PEER) {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004874 char *ca_file = (ssl_conf && ssl_conf->ca_file) ? ssl_conf->ca_file : bind_conf->ssl_conf.ca_file;
4875 char *crl_file = (ssl_conf && ssl_conf->crl_file) ? ssl_conf->crl_file : bind_conf->ssl_conf.crl_file;
4876 if (ca_file) {
Emeric Brund94b3fe2012-09-20 18:23:56 +02004877 /* load CAfile to verify */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004878 if (!SSL_CTX_load_verify_locations(ctx, ca_file, NULL)) {
William Lallemand8b453912019-11-21 15:48:10 +01004879 if (err)
4880 memprintf(err, "%sProxy '%s': unable to load CA file '%s' for bind '%s' at [%s:%d].\n",
4881 *err ? *err : "", curproxy->id, ca_file, bind_conf->arg, bind_conf->file, bind_conf->line);
4882 cfgerr |= ERR_ALERT | ERR_FATAL;
Emeric Brund94b3fe2012-09-20 18:23:56 +02004883 }
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02004884 if (!((ssl_conf && ssl_conf->no_ca_names) || bind_conf->ssl_conf.no_ca_names)) {
4885 /* set CA names for client cert request, function returns void */
4886 SSL_CTX_set_client_CA_list(ctx, SSL_load_client_CA_file(ca_file));
4887 }
Emeric Brund94b3fe2012-09-20 18:23:56 +02004888 }
Emeric Brun850efd52014-01-29 12:24:34 +01004889 else {
William Lallemand8b453912019-11-21 15:48:10 +01004890 if (err)
4891 memprintf(err, "%sProxy '%s': verify is enabled but no CA file specified for bind '%s' at [%s:%d].\n",
4892 *err ? *err : "", curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
4893 cfgerr |= ERR_ALERT | ERR_FATAL;
Emeric Brun850efd52014-01-29 12:24:34 +01004894 }
Emeric Brun051cdab2012-10-02 19:25:50 +02004895#ifdef X509_V_FLAG_CRL_CHECK
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004896 if (crl_file) {
Emeric Brund94b3fe2012-09-20 18:23:56 +02004897 X509_STORE *store = SSL_CTX_get_cert_store(ctx);
4898
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004899 if (!store || !X509_STORE_load_locations(store, crl_file, NULL)) {
William Lallemand8b453912019-11-21 15:48:10 +01004900 if (err)
4901 memprintf(err, "%sProxy '%s': unable to configure CRL file '%s' for bind '%s' at [%s:%d].\n",
4902 *err ? *err : "", curproxy->id, crl_file, bind_conf->arg, bind_conf->file, bind_conf->line);
4903 cfgerr |= ERR_ALERT | ERR_FATAL;
Emeric Brund94b3fe2012-09-20 18:23:56 +02004904 }
Emeric Brun561e5742012-10-02 15:20:55 +02004905 else {
4906 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
4907 }
Emeric Brund94b3fe2012-09-20 18:23:56 +02004908 }
Emeric Brun051cdab2012-10-02 19:25:50 +02004909#endif
Emeric Brun644cde02012-12-14 11:21:13 +01004910 ERR_clear_error();
Emeric Brund94b3fe2012-09-20 18:23:56 +02004911 }
Nenad Merdanovic05552d42015-02-27 19:56:49 +01004912#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
Nenad Merdanovic146defa2015-05-09 08:46:00 +02004913 if(bind_conf->keys_ref) {
Nenad Merdanovic05552d42015-02-27 19:56:49 +01004914 if (!SSL_CTX_set_tlsext_ticket_key_cb(ctx, ssl_tlsext_ticket_key_cb)) {
William Lallemand8b453912019-11-21 15:48:10 +01004915 if (err)
4916 memprintf(err, "%sProxy '%s': unable to set callback for TLS ticket validation for bind '%s' at [%s:%d].\n",
4917 *err ? *err : "", curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
4918 cfgerr |= ERR_ALERT | ERR_FATAL;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01004919 }
4920 }
4921#endif
4922
William Lallemand4f45bb92017-10-30 20:08:51 +01004923 ssl_set_shctx(ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004924 conf_ciphers = (ssl_conf && ssl_conf->ciphers) ? ssl_conf->ciphers : bind_conf->ssl_conf.ciphers;
4925 if (conf_ciphers &&
4926 !SSL_CTX_set_cipher_list(ctx, conf_ciphers)) {
William Lallemand8b453912019-11-21 15:48:10 +01004927 if (err)
4928 memprintf(err, "%sProxy '%s': unable to set SSL cipher list to '%s' for bind '%s' at [%s:%d].\n",
4929 *err ? *err : "", curproxy->id, conf_ciphers, bind_conf->arg, bind_conf->file, bind_conf->line);
4930 cfgerr |= ERR_ALERT | ERR_FATAL;
Emeric Brunfc0421f2012-09-07 17:30:07 +02004931 }
4932
Emmanuel Hocdet839af572019-05-14 16:27:35 +02004933#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02004934 conf_ciphersuites = (ssl_conf && ssl_conf->ciphersuites) ? ssl_conf->ciphersuites : bind_conf->ssl_conf.ciphersuites;
4935 if (conf_ciphersuites &&
4936 !SSL_CTX_set_ciphersuites(ctx, conf_ciphersuites)) {
William Dauchy5f1fa7d2019-11-23 21:14:33 +01004937 if (err)
4938 memprintf(err, "%sProxy '%s': unable to set TLS 1.3 cipher suites to '%s' for bind '%s' at [%s:%d].\n",
4939 *err ? *err : "", curproxy->id, conf_ciphersuites, bind_conf->arg, bind_conf->file, bind_conf->line);
William Lallemand8b453912019-11-21 15:48:10 +01004940 cfgerr |= ERR_ALERT | ERR_FATAL;
Dirkjan Bussink415150f2018-09-14 11:14:21 +02004941 }
4942#endif
4943
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01004944#ifndef OPENSSL_NO_DH
Remi Gacogne47783ef2015-05-29 15:53:22 +02004945 /* If tune.ssl.default-dh-param has not been set,
4946 neither has ssl-default-dh-file and no static DH
4947 params were in the certificate file. */
Willy Tarreauef934602016-12-22 23:12:01 +01004948 if (global_ssl.default_dh_param == 0 &&
Remi Gacogne47783ef2015-05-29 15:53:22 +02004949 global_dh == NULL &&
Remi Gacogne4f902b82015-05-28 16:23:00 +02004950 (ssl_dh_ptr_index == -1 ||
4951 SSL_CTX_get_ex_data(ctx, ssl_dh_ptr_index) == NULL)) {
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01004952 STACK_OF(SSL_CIPHER) * ciphers = NULL;
4953 const SSL_CIPHER * cipher = NULL;
4954 char cipher_description[128];
4955 /* The description of ciphers using an Ephemeral Diffie Hellman key exchange
4956 contains " Kx=DH " or " Kx=DH(". Beware of " Kx=DH/",
4957 which is not ephemeral DH. */
4958 const char dhe_description[] = " Kx=DH ";
4959 const char dhe_export_description[] = " Kx=DH(";
4960 int idx = 0;
4961 int dhe_found = 0;
4962 SSL *ssl = NULL;
Lukas Tribus90132722014-08-18 00:56:33 +02004963
Remi Gacogne23d5d372014-10-10 17:04:26 +02004964 ssl = SSL_new(ctx);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004965
Remi Gacogne23d5d372014-10-10 17:04:26 +02004966 if (ssl) {
4967 ciphers = SSL_get_ciphers(ssl);
4968
4969 if (ciphers) {
4970 for (idx = 0; idx < sk_SSL_CIPHER_num(ciphers); idx++) {
4971 cipher = sk_SSL_CIPHER_value(ciphers, idx);
4972 if (SSL_CIPHER_description(cipher, cipher_description, sizeof (cipher_description)) == cipher_description) {
4973 if (strstr(cipher_description, dhe_description) != NULL ||
4974 strstr(cipher_description, dhe_export_description) != NULL) {
4975 dhe_found = 1;
4976 break;
4977 }
Remi Gacognec1eab8c2014-06-12 18:20:11 +02004978 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004979 }
4980 }
Remi Gacogne23d5d372014-10-10 17:04:26 +02004981 SSL_free(ssl);
4982 ssl = NULL;
Lukas Tribus90132722014-08-18 00:56:33 +02004983 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004984
Lukas Tribus90132722014-08-18 00:56:33 +02004985 if (dhe_found) {
William Lallemand8b453912019-11-21 15:48:10 +01004986 if (err)
4987 memprintf(err, "%sSetting 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", *err ? *err : "");
4988 cfgerr |= ERR_WARN;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004989 }
4990
Willy Tarreauef934602016-12-22 23:12:01 +01004991 global_ssl.default_dh_param = 1024;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004992 }
Remi Gacogne8de54152014-07-15 11:36:40 +02004993
Willy Tarreauef934602016-12-22 23:12:01 +01004994 if (global_ssl.default_dh_param >= 1024) {
Remi Gacogne8de54152014-07-15 11:36:40 +02004995 if (local_dh_1024 == NULL) {
4996 local_dh_1024 = ssl_get_dh_1024();
4997 }
Willy Tarreauef934602016-12-22 23:12:01 +01004998 if (global_ssl.default_dh_param >= 2048) {
Remi Gacogne8de54152014-07-15 11:36:40 +02004999 if (local_dh_2048 == NULL) {
5000 local_dh_2048 = ssl_get_dh_2048();
5001 }
Willy Tarreauef934602016-12-22 23:12:01 +01005002 if (global_ssl.default_dh_param >= 4096) {
Remi Gacogne8de54152014-07-15 11:36:40 +02005003 if (local_dh_4096 == NULL) {
5004 local_dh_4096 = ssl_get_dh_4096();
5005 }
Remi Gacogne8de54152014-07-15 11:36:40 +02005006 }
5007 }
5008 }
5009#endif /* OPENSSL_NO_DH */
Remi Gacognef46cd6e2014-06-12 14:58:40 +02005010
Emeric Brunfc0421f2012-09-07 17:30:07 +02005011 SSL_CTX_set_info_callback(ctx, ssl_sock_infocbk);
Willy Tarreau9a1ab082019-05-09 13:26:41 +02005012#if HA_OPENSSL_VERSION_NUMBER >= 0x00907000L
Emeric Brun29f037d2014-04-25 19:05:36 +02005013 SSL_CTX_set_msg_callback(ctx, ssl_sock_msgcbk);
Willy Tarreau5cbe4ef2014-05-08 22:45:11 +02005014#endif
Emeric Brun29f037d2014-04-25 19:05:36 +02005015
Bernard Spil13c53f82018-02-15 13:34:58 +01005016#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005017 ssl_conf_cur = NULL;
5018 if (ssl_conf && ssl_conf->npn_str)
5019 ssl_conf_cur = ssl_conf;
5020 else if (bind_conf->ssl_conf.npn_str)
5021 ssl_conf_cur = &bind_conf->ssl_conf;
5022 if (ssl_conf_cur)
5023 SSL_CTX_set_next_protos_advertised_cb(ctx, ssl_sock_advertise_npn_protos, ssl_conf_cur);
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02005024#endif
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01005025#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005026 ssl_conf_cur = NULL;
5027 if (ssl_conf && ssl_conf->alpn_str)
5028 ssl_conf_cur = ssl_conf;
5029 else if (bind_conf->ssl_conf.alpn_str)
5030 ssl_conf_cur = &bind_conf->ssl_conf;
5031 if (ssl_conf_cur)
5032 SSL_CTX_set_alpn_select_cb(ctx, ssl_sock_advertise_alpn_protos, ssl_conf_cur);
Willy Tarreauab861d32013-04-02 02:30:41 +02005033#endif
Lukas Tribusd14b49c2019-11-24 18:20:40 +01005034#if ((HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL) || defined(LIBRESSL_VERSION_NUMBER))
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01005035 conf_curves = (ssl_conf && ssl_conf->curves) ? ssl_conf->curves : bind_conf->ssl_conf.curves;
5036 if (conf_curves) {
5037 if (!SSL_CTX_set1_curves_list(ctx, conf_curves)) {
William Dauchy5f1fa7d2019-11-23 21:14:33 +01005038 if (err)
5039 memprintf(err, "%sProxy '%s': unable to set SSL curves list to '%s' for bind '%s' at [%s:%d].\n",
5040 *err ? *err : "", curproxy->id, conf_curves, bind_conf->arg, bind_conf->file, bind_conf->line);
William Lallemand8b453912019-11-21 15:48:10 +01005041 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01005042 }
Emmanuel Hocdeta52bb152017-03-20 11:11:49 +01005043#if defined(SSL_CTX_set_ecdh_auto)
5044 (void)SSL_CTX_set_ecdh_auto(ctx, 1);
5045#endif
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01005046 }
5047#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02005048#if defined(SSL_CTX_set_tmp_ecdh) && !defined(OPENSSL_NO_ECDH)
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01005049 if (!conf_curves) {
Emeric Brun2b58d042012-09-20 17:10:03 +02005050 int i;
5051 EC_KEY *ecdh;
Willy Tarreau9a1ab082019-05-09 13:26:41 +02005052#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005053 const char *ecdhe = (ssl_conf && ssl_conf->ecdhe) ? ssl_conf->ecdhe :
Olivier Houchardc2aae742017-09-22 18:26:28 +02005054 (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe :
5055 NULL);
5056
5057 if (ecdhe == NULL) {
Eric Salama3c8bde82019-11-20 11:33:40 +01005058 (void)SSL_CTX_set_ecdh_auto(ctx, 1);
Olivier Houchardc2aae742017-09-22 18:26:28 +02005059 return cfgerr;
5060 }
5061#else
5062 const char *ecdhe = (ssl_conf && ssl_conf->ecdhe) ? ssl_conf->ecdhe :
5063 (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe :
5064 ECDHE_DEFAULT_CURVE);
5065#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02005066
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005067 i = OBJ_sn2nid(ecdhe);
Emeric Brun2b58d042012-09-20 17:10:03 +02005068 if (!i || ((ecdh = EC_KEY_new_by_curve_name(i)) == NULL)) {
William Dauchy5f1fa7d2019-11-23 21:14:33 +01005069 if (err)
5070 memprintf(err, "%sProxy '%s': unable to set elliptic named curve to '%s' for bind '%s' at [%s:%d].\n",
5071 *err ? *err : "", curproxy->id, ecdhe, bind_conf->arg, bind_conf->file, bind_conf->line);
William Lallemand8b453912019-11-21 15:48:10 +01005072 cfgerr |= ERR_ALERT | ERR_FATAL;
Emeric Brun2b58d042012-09-20 17:10:03 +02005073 }
5074 else {
5075 SSL_CTX_set_tmp_ecdh(ctx, ecdh);
5076 EC_KEY_free(ecdh);
5077 }
5078 }
5079#endif
5080
Emeric Brunfc0421f2012-09-07 17:30:07 +02005081 return cfgerr;
5082}
5083
Evan Broderbe554312013-06-27 00:05:25 -07005084static int ssl_sock_srv_hostcheck(const char *pattern, const char *hostname)
5085{
5086 const char *pattern_wildcard, *pattern_left_label_end, *hostname_left_label_end;
5087 size_t prefixlen, suffixlen;
5088
5089 /* Trivial case */
5090 if (strcmp(pattern, hostname) == 0)
5091 return 1;
5092
Evan Broderbe554312013-06-27 00:05:25 -07005093 /* The rest of this logic is based on RFC 6125, section 6.4.3
5094 * (http://tools.ietf.org/html/rfc6125#section-6.4.3) */
5095
Emeric Bruna848dae2013-10-08 11:27:28 +02005096 pattern_wildcard = NULL;
5097 pattern_left_label_end = pattern;
5098 while (*pattern_left_label_end != '.') {
5099 switch (*pattern_left_label_end) {
5100 case 0:
5101 /* End of label not found */
5102 return 0;
5103 case '*':
5104 /* If there is more than one wildcards */
5105 if (pattern_wildcard)
5106 return 0;
5107 pattern_wildcard = pattern_left_label_end;
5108 break;
5109 }
5110 pattern_left_label_end++;
5111 }
5112
5113 /* If it's not trivial and there is no wildcard, it can't
5114 * match */
5115 if (!pattern_wildcard)
Evan Broderbe554312013-06-27 00:05:25 -07005116 return 0;
5117
5118 /* Make sure all labels match except the leftmost */
5119 hostname_left_label_end = strchr(hostname, '.');
5120 if (!hostname_left_label_end
5121 || strcmp(pattern_left_label_end, hostname_left_label_end) != 0)
5122 return 0;
5123
5124 /* Make sure the leftmost label of the hostname is long enough
5125 * that the wildcard can match */
Emeric Brun369da852013-10-08 11:39:35 +02005126 if (hostname_left_label_end - hostname < (pattern_left_label_end - pattern) - 1)
Evan Broderbe554312013-06-27 00:05:25 -07005127 return 0;
5128
5129 /* Finally compare the string on either side of the
5130 * wildcard */
5131 prefixlen = pattern_wildcard - pattern;
5132 suffixlen = pattern_left_label_end - (pattern_wildcard + 1);
Emeric Bruna848dae2013-10-08 11:27:28 +02005133 if ((prefixlen && (memcmp(pattern, hostname, prefixlen) != 0))
5134 || (suffixlen && (memcmp(pattern_wildcard + 1, hostname_left_label_end - suffixlen, suffixlen) != 0)))
Evan Broderbe554312013-06-27 00:05:25 -07005135 return 0;
5136
5137 return 1;
5138}
5139
5140static int ssl_sock_srv_verifycbk(int ok, X509_STORE_CTX *ctx)
5141{
5142 SSL *ssl;
5143 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01005144 struct ssl_sock_ctx *ssl_ctx;
Willy Tarreau2ab88672017-07-05 18:23:03 +02005145 const char *servername;
Willy Tarreau71d058c2017-07-26 20:09:56 +02005146 const char *sni;
Evan Broderbe554312013-06-27 00:05:25 -07005147
5148 int depth;
5149 X509 *cert;
5150 STACK_OF(GENERAL_NAME) *alt_names;
5151 int i;
5152 X509_NAME *cert_subject;
5153 char *str;
5154
5155 if (ok == 0)
5156 return ok;
5157
5158 ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
Thierry FOURNIER28962c92018-06-17 21:37:05 +02005159 conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Olivier Houchard66ab4982019-02-26 18:37:15 +01005160 ssl_ctx = conn->xprt_ctx;
Evan Broderbe554312013-06-27 00:05:25 -07005161
Willy Tarreauad92a9a2017-07-28 11:38:41 +02005162 /* We're checking if the provided hostnames match the desired one. The
5163 * desired hostname comes from the SNI we presented if any, or if not
5164 * provided then it may have been explicitly stated using a "verifyhost"
5165 * directive. If neither is set, we don't care about the name so the
5166 * verification is OK.
Willy Tarreau2ab88672017-07-05 18:23:03 +02005167 */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005168 servername = SSL_get_servername(ssl_ctx->ssl, TLSEXT_NAMETYPE_host_name);
Willy Tarreau71d058c2017-07-26 20:09:56 +02005169 sni = servername;
Willy Tarreau2ab88672017-07-05 18:23:03 +02005170 if (!servername) {
Willy Tarreau07d94e42018-09-20 10:57:52 +02005171 servername = __objt_server(conn->target)->ssl_ctx.verify_host;
Willy Tarreau2ab88672017-07-05 18:23:03 +02005172 if (!servername)
5173 return ok;
5174 }
Evan Broderbe554312013-06-27 00:05:25 -07005175
5176 /* We only need to verify the CN on the actual server cert,
5177 * not the indirect CAs */
5178 depth = X509_STORE_CTX_get_error_depth(ctx);
5179 if (depth != 0)
5180 return ok;
5181
5182 /* At this point, the cert is *not* OK unless we can find a
5183 * hostname match */
5184 ok = 0;
5185
5186 cert = X509_STORE_CTX_get_current_cert(ctx);
5187 /* It seems like this might happen if verify peer isn't set */
5188 if (!cert)
5189 return ok;
5190
5191 alt_names = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
5192 if (alt_names) {
5193 for (i = 0; !ok && i < sk_GENERAL_NAME_num(alt_names); i++) {
5194 GENERAL_NAME *name = sk_GENERAL_NAME_value(alt_names, i);
5195 if (name->type == GEN_DNS) {
Willy Tarreau9a1ab082019-05-09 13:26:41 +02005196#if HA_OPENSSL_VERSION_NUMBER < 0x00907000L
Emeric Bruna33410c2013-09-17 15:47:48 +02005197 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.ia5) >= 0) {
5198#else
Evan Broderbe554312013-06-27 00:05:25 -07005199 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
Emeric Bruna33410c2013-09-17 15:47:48 +02005200#endif
Evan Broderbe554312013-06-27 00:05:25 -07005201 ok = ssl_sock_srv_hostcheck(str, servername);
5202 OPENSSL_free(str);
5203 }
5204 }
5205 }
Emeric Brun4ad50a42013-09-17 15:19:54 +02005206 sk_GENERAL_NAME_pop_free(alt_names, GENERAL_NAME_free);
Evan Broderbe554312013-06-27 00:05:25 -07005207 }
5208
5209 cert_subject = X509_get_subject_name(cert);
5210 i = -1;
5211 while (!ok && (i = X509_NAME_get_index_by_NID(cert_subject, NID_commonName, i)) != -1) {
5212 X509_NAME_ENTRY *entry = X509_NAME_get_entry(cert_subject, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005213 ASN1_STRING *value;
5214 value = X509_NAME_ENTRY_get_data(entry);
5215 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
Evan Broderbe554312013-06-27 00:05:25 -07005216 ok = ssl_sock_srv_hostcheck(str, servername);
5217 OPENSSL_free(str);
5218 }
5219 }
5220
Willy Tarreau71d058c2017-07-26 20:09:56 +02005221 /* report the mismatch and indicate if SNI was used or not */
5222 if (!ok && !conn->err_code)
5223 conn->err_code = sni ? CO_ER_SSL_MISMATCH_SNI : CO_ER_SSL_MISMATCH;
Evan Broderbe554312013-06-27 00:05:25 -07005224 return ok;
5225}
5226
Emeric Brun94324a42012-10-11 14:00:19 +02005227/* prepare ssl context from servers options. Returns an error count */
Willy Tarreau03209342016-12-22 17:08:28 +01005228int ssl_sock_prepare_srv_ctx(struct server *srv)
Emeric Brun94324a42012-10-11 14:00:19 +02005229{
Willy Tarreau03209342016-12-22 17:08:28 +01005230 struct proxy *curproxy = srv->proxy;
Emeric Brun94324a42012-10-11 14:00:19 +02005231 int cfgerr = 0;
Remi Gacogneaf5c3da2014-05-19 10:29:58 +02005232 long options =
Emeric Brun94324a42012-10-11 14:00:19 +02005233 SSL_OP_ALL | /* all known workarounds for bugs */
5234 SSL_OP_NO_SSLv2 |
5235 SSL_OP_NO_COMPRESSION;
Remi Gacogneaf5c3da2014-05-19 10:29:58 +02005236 long mode =
Emeric Brun94324a42012-10-11 14:00:19 +02005237 SSL_MODE_ENABLE_PARTIAL_WRITE |
5238 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
Willy Tarreau396a1862014-11-13 14:06:52 +01005239 SSL_MODE_RELEASE_BUFFERS |
5240 SSL_MODE_SMALL_BUFFERS;
Emeric Brun850efd52014-01-29 12:24:34 +01005241 int verify = SSL_VERIFY_NONE;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01005242 SSL_CTX *ctx = NULL;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005243 struct tls_version_filter *conf_ssl_methods = &srv->ssl_ctx.methods;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005244 int i, min, max, hole;
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005245 int flags = MC_SSL_O_ALL;
Emeric Brun94324a42012-10-11 14:00:19 +02005246
Thierry Fournier383085f2013-01-24 14:15:43 +01005247 /* Make sure openssl opens /dev/urandom before the chroot */
5248 if (!ssl_initialize_random()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005249 ha_alert("OpenSSL random data generator initialization failed.\n");
Thierry Fournier383085f2013-01-24 14:15:43 +01005250 cfgerr++;
5251 }
5252
Willy Tarreaufce03112015-01-15 21:32:40 +01005253 /* Automatic memory computations need to know we use SSL there */
5254 global.ssl_used_backend = 1;
5255
5256 /* Initiate SSL context for current server */
Emeric Brun821bb9b2017-06-15 16:37:39 +02005257 if (!srv->ssl_ctx.reused_sess) {
Olivier Houcharde6060c52017-11-16 17:42:52 +01005258 if ((srv->ssl_ctx.reused_sess = calloc(1, global.nbthread*sizeof(*srv->ssl_ctx.reused_sess))) == NULL) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005259 ha_alert("Proxy '%s', server '%s' [%s:%d] out of memory.\n",
5260 curproxy->id, srv->id,
5261 srv->conf.file, srv->conf.line);
Emeric Brun821bb9b2017-06-15 16:37:39 +02005262 cfgerr++;
5263 return cfgerr;
5264 }
5265 }
Emeric Brun94324a42012-10-11 14:00:19 +02005266 if (srv->use_ssl)
5267 srv->xprt = &ssl_sock;
5268 if (srv->check.use_ssl)
Cyril Bonté9ce13112014-11-15 22:41:27 +01005269 srv->check.xprt = &ssl_sock;
Emeric Brun94324a42012-10-11 14:00:19 +02005270
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005271 ctx = SSL_CTX_new(SSLv23_client_method());
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01005272 if (!ctx) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005273 ha_alert("config : %s '%s', server '%s': unable to allocate ssl context.\n",
5274 proxy_type_str(curproxy), curproxy->id,
5275 srv->id);
Emeric Brun94324a42012-10-11 14:00:19 +02005276 cfgerr++;
5277 return cfgerr;
5278 }
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005279
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005280 if (conf_ssl_methods->flags && (conf_ssl_methods->min || conf_ssl_methods->max))
Christopher Faulet767a84b2017-11-24 16:50:31 +01005281 ha_warning("config : %s '%s': no-sslv3/no-tlsv1x are ignored for server '%s'. "
5282 "Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
5283 proxy_type_str(curproxy), curproxy->id, srv->id);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005284 else
5285 flags = conf_ssl_methods->flags;
5286
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005287 /* Real min and max should be determinate with configuration and openssl's capabilities */
5288 if (conf_ssl_methods->min)
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005289 flags |= (methodVersions[conf_ssl_methods->min].flag - 1);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005290 if (conf_ssl_methods->max)
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005291 flags |= ~((methodVersions[conf_ssl_methods->max].flag << 1) - 1);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005292
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02005293 /* find min, max and holes */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005294 min = max = CONF_TLSV_NONE;
5295 hole = 0;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005296 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005297 /* version is in openssl && version not disable in configuration */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005298 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005299 if (min) {
5300 if (hole) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005301 ha_warning("config : %s '%s': SSL/TLS versions range not contiguous for server '%s'. "
5302 "Hole find for %s. Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
5303 proxy_type_str(curproxy), curproxy->id, srv->id,
5304 methodVersions[hole].name);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005305 hole = 0;
5306 }
5307 max = i;
5308 }
5309 else {
5310 min = max = i;
5311 }
5312 }
5313 else {
5314 if (min)
5315 hole = i;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005316 }
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005317 if (!min) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005318 ha_alert("config : %s '%s': all SSL/TLS versions are disabled for server '%s'.\n",
5319 proxy_type_str(curproxy), curproxy->id, srv->id);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005320 cfgerr += 1;
5321 }
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005322
Willy Tarreau9a1ab082019-05-09 13:26:41 +02005323#if (HA_OPENSSL_VERSION_NUMBER < 0x1010000fL)
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005324 /* Keep force-xxx implementation as it is in older haproxy. It's a
Joseph Herlant017b3da2018-11-15 09:07:59 -08005325 precautionary measure to avoid any surprise with older openssl version. */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005326 if (min == max)
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02005327 methodVersions[min].ctx_set_version(ctx, SET_CLIENT);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005328 else
5329 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
5330 if (flags & methodVersions[i].flag)
5331 options |= methodVersions[i].option;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005332#else /* openssl >= 1.1.0 */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005333 /* set the max_version is required to cap TLS version or activate new TLS (v1.3) */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02005334 methodVersions[min].ctx_set_version(ctx, SET_MIN);
5335 methodVersions[max].ctx_set_version(ctx, SET_MAX);
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005336#endif
5337
5338 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLS_TICKETS)
5339 options |= SSL_OP_NO_TICKET;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01005340 SSL_CTX_set_options(ctx, options);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005341
Willy Tarreau5db847a2019-05-09 14:13:35 +02005342#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005343 if (global_ssl.async)
5344 mode |= SSL_MODE_ASYNC;
5345#endif
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01005346 SSL_CTX_set_mode(ctx, mode);
5347 srv->ssl_ctx.ctx = ctx;
5348
Emeric Bruna7aa3092012-10-26 12:58:00 +02005349 if (srv->ssl_ctx.client_crt) {
5350 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 +01005351 ha_alert("config : %s '%s', server '%s': unable to load SSL private key from PEM file '%s'.\n",
5352 proxy_type_str(curproxy), curproxy->id,
5353 srv->id, srv->ssl_ctx.client_crt);
Emeric Bruna7aa3092012-10-26 12:58:00 +02005354 cfgerr++;
5355 }
5356 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 +01005357 ha_alert("config : %s '%s', server '%s': unable to load ssl certificate from PEM file '%s'.\n",
5358 proxy_type_str(curproxy), curproxy->id,
5359 srv->id, srv->ssl_ctx.client_crt);
Emeric Bruna7aa3092012-10-26 12:58:00 +02005360 cfgerr++;
5361 }
5362 else if (SSL_CTX_check_private_key(srv->ssl_ctx.ctx) <= 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005363 ha_alert("config : %s '%s', server '%s': inconsistencies between private key and certificate loaded from PEM file '%s'.\n",
5364 proxy_type_str(curproxy), curproxy->id,
5365 srv->id, srv->ssl_ctx.client_crt);
Emeric Bruna7aa3092012-10-26 12:58:00 +02005366 cfgerr++;
5367 }
5368 }
Emeric Brun94324a42012-10-11 14:00:19 +02005369
Emeric Brun850efd52014-01-29 12:24:34 +01005370 if (global.ssl_server_verify == SSL_SERVER_VERIFY_REQUIRED)
5371 verify = SSL_VERIFY_PEER;
Emeric Brun850efd52014-01-29 12:24:34 +01005372 switch (srv->ssl_ctx.verify) {
5373 case SSL_SOCK_VERIFY_NONE:
5374 verify = SSL_VERIFY_NONE;
5375 break;
5376 case SSL_SOCK_VERIFY_REQUIRED:
5377 verify = SSL_VERIFY_PEER;
5378 break;
5379 }
Evan Broderbe554312013-06-27 00:05:25 -07005380 SSL_CTX_set_verify(srv->ssl_ctx.ctx,
Emeric Brun850efd52014-01-29 12:24:34 +01005381 verify,
Willy Tarreau2ab88672017-07-05 18:23:03 +02005382 (srv->ssl_ctx.verify_host || (verify & SSL_VERIFY_PEER)) ? ssl_sock_srv_verifycbk : NULL);
Emeric Brun850efd52014-01-29 12:24:34 +01005383 if (verify & SSL_VERIFY_PEER) {
Emeric Brunef42d922012-10-11 16:11:36 +02005384 if (srv->ssl_ctx.ca_file) {
5385 /* load CAfile to verify */
5386 if (!SSL_CTX_load_verify_locations(srv->ssl_ctx.ctx, srv->ssl_ctx.ca_file, NULL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005387 ha_alert("Proxy '%s', server '%s' [%s:%d] unable to load CA file '%s'.\n",
5388 curproxy->id, srv->id,
5389 srv->conf.file, srv->conf.line, srv->ssl_ctx.ca_file);
Emeric Brunef42d922012-10-11 16:11:36 +02005390 cfgerr++;
5391 }
5392 }
Emeric Brun850efd52014-01-29 12:24:34 +01005393 else {
5394 if (global.ssl_server_verify == SSL_SERVER_VERIFY_REQUIRED)
Christopher Faulet767a84b2017-11-24 16:50:31 +01005395 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",
5396 curproxy->id, srv->id,
5397 srv->conf.file, srv->conf.line);
Emeric Brun850efd52014-01-29 12:24:34 +01005398 else
Christopher Faulet767a84b2017-11-24 16:50:31 +01005399 ha_alert("Proxy '%s', server '%s' [%s:%d] verify is enabled but no CA file specified.\n",
5400 curproxy->id, srv->id,
5401 srv->conf.file, srv->conf.line);
Emeric Brun850efd52014-01-29 12:24:34 +01005402 cfgerr++;
5403 }
Emeric Brunef42d922012-10-11 16:11:36 +02005404#ifdef X509_V_FLAG_CRL_CHECK
5405 if (srv->ssl_ctx.crl_file) {
5406 X509_STORE *store = SSL_CTX_get_cert_store(srv->ssl_ctx.ctx);
5407
5408 if (!store || !X509_STORE_load_locations(store, srv->ssl_ctx.crl_file, NULL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005409 ha_alert("Proxy '%s', server '%s' [%s:%d] unable to configure CRL file '%s'.\n",
5410 curproxy->id, srv->id,
5411 srv->conf.file, srv->conf.line, srv->ssl_ctx.crl_file);
Emeric Brunef42d922012-10-11 16:11:36 +02005412 cfgerr++;
5413 }
5414 else {
5415 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
5416 }
5417 }
5418#endif
5419 }
5420
Olivier Houchardbd84ac82017-11-03 13:43:35 +01005421 SSL_CTX_set_session_cache_mode(srv->ssl_ctx.ctx, SSL_SESS_CACHE_CLIENT |
5422 SSL_SESS_CACHE_NO_INTERNAL_STORE);
5423 SSL_CTX_sess_set_new_cb(srv->ssl_ctx.ctx, ssl_sess_new_srv_cb);
Emeric Brun94324a42012-10-11 14:00:19 +02005424 if (srv->ssl_ctx.ciphers &&
5425 !SSL_CTX_set_cipher_list(srv->ssl_ctx.ctx, srv->ssl_ctx.ciphers)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005426 ha_alert("Proxy '%s', server '%s' [%s:%d] : unable to set SSL cipher list to '%s'.\n",
5427 curproxy->id, srv->id,
5428 srv->conf.file, srv->conf.line, srv->ssl_ctx.ciphers);
Emeric Brun94324a42012-10-11 14:00:19 +02005429 cfgerr++;
5430 }
Dirkjan Bussink415150f2018-09-14 11:14:21 +02005431
Emmanuel Hocdet839af572019-05-14 16:27:35 +02005432#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02005433 if (srv->ssl_ctx.ciphersuites &&
Pierre Cheynierbc34cd12019-03-21 16:15:47 +00005434 !SSL_CTX_set_ciphersuites(srv->ssl_ctx.ctx, srv->ssl_ctx.ciphersuites)) {
Dirkjan Bussink415150f2018-09-14 11:14:21 +02005435 ha_alert("Proxy '%s', server '%s' [%s:%d] : unable to set TLS 1.3 cipher suites to '%s'.\n",
5436 curproxy->id, srv->id,
5437 srv->conf.file, srv->conf.line, srv->ssl_ctx.ciphersuites);
5438 cfgerr++;
5439 }
5440#endif
Olivier Houchardc7566002018-11-20 23:33:50 +01005441#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
5442 if (srv->ssl_ctx.npn_str)
5443 SSL_CTX_set_next_proto_select_cb(ctx, ssl_sock_srv_select_protos, srv);
5444#endif
5445#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
5446 if (srv->ssl_ctx.alpn_str)
5447 SSL_CTX_set_alpn_protos(ctx, (unsigned char *)srv->ssl_ctx.alpn_str, srv->ssl_ctx.alpn_len);
5448#endif
5449
Emeric Brun94324a42012-10-11 14:00:19 +02005450
5451 return cfgerr;
5452}
5453
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005454/* Walks down the two trees in bind_conf and prepares all certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +02005455 * be NULL, in which case nothing is done. Returns the number of errors
5456 * encountered.
5457 */
Willy Tarreau03209342016-12-22 17:08:28 +01005458int ssl_sock_prepare_all_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02005459{
5460 struct ebmb_node *node;
5461 struct sni_ctx *sni;
5462 int err = 0;
William Lallemand8b453912019-11-21 15:48:10 +01005463 int errcode = 0;
5464 char *errmsg = NULL;
Emeric Brunfc0421f2012-09-07 17:30:07 +02005465
Willy Tarreaufce03112015-01-15 21:32:40 +01005466 /* Automatic memory computations need to know we use SSL there */
5467 global.ssl_used_frontend = 1;
5468
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01005469 /* Make sure openssl opens /dev/urandom before the chroot */
5470 if (!ssl_initialize_random()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005471 ha_alert("OpenSSL random data generator initialization failed.\n");
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01005472 err++;
5473 }
5474 /* Create initial_ctx used to start the ssl connection before do switchctx */
5475 if (!bind_conf->initial_ctx) {
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005476 err += ssl_sock_initial_ctx(bind_conf);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01005477 /* It should not be necessary to call this function, but it's
5478 necessary first to check and move all initialisation related
5479 to initial_ctx in ssl_sock_initial_ctx. */
William Lallemand8b453912019-11-21 15:48:10 +01005480 errcode |= ssl_sock_prepare_ctx(bind_conf, NULL, bind_conf->initial_ctx, &errmsg);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01005481 }
Emeric Brun0bed9942014-10-30 19:25:24 +01005482 if (bind_conf->default_ctx)
William Lallemand8b453912019-11-21 15:48:10 +01005483 errcode |= ssl_sock_prepare_ctx(bind_conf, bind_conf->default_ssl_conf, bind_conf->default_ctx, &errmsg);
Emeric Brun0bed9942014-10-30 19:25:24 +01005484
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005485 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02005486 while (node) {
5487 sni = ebmb_entry(node, struct sni_ctx, name);
Emeric Brun0bed9942014-10-30 19:25:24 +01005488 if (!sni->order && sni->ctx != bind_conf->default_ctx)
5489 /* only initialize the CTX on its first occurrence and
5490 if it is not the default_ctx */
William Lallemand8b453912019-11-21 15:48:10 +01005491 errcode |= ssl_sock_prepare_ctx(bind_conf, sni->conf, sni->ctx, &errmsg);
Emeric Brunfc0421f2012-09-07 17:30:07 +02005492 node = ebmb_next(node);
5493 }
5494
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005495 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02005496 while (node) {
5497 sni = ebmb_entry(node, struct sni_ctx, name);
William Lallemand8b453912019-11-21 15:48:10 +01005498 if (!sni->order && sni->ctx != bind_conf->default_ctx) {
Emeric Brun0bed9942014-10-30 19:25:24 +01005499 /* only initialize the CTX on its first occurrence and
5500 if it is not the default_ctx */
William Lallemand8b453912019-11-21 15:48:10 +01005501 errcode |= ssl_sock_prepare_ctx(bind_conf, sni->conf, sni->ctx, &errmsg);
5502 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02005503 node = ebmb_next(node);
5504 }
William Lallemand8b453912019-11-21 15:48:10 +01005505
5506 if (errcode & ERR_WARN) {
Tim Duesterhusc0e820c2019-11-23 23:52:30 +01005507 ha_warning("%s", errmsg);
William Lallemand8b453912019-11-21 15:48:10 +01005508 } else if (errcode & ERR_CODE) {
Tim Duesterhusc0e820c2019-11-23 23:52:30 +01005509 ha_alert("%s", errmsg);
William Lallemand8b453912019-11-21 15:48:10 +01005510 err++;
5511 }
5512
5513 free(errmsg);
Emeric Brunfc0421f2012-09-07 17:30:07 +02005514 return err;
5515}
5516
Willy Tarreau55d37912016-12-21 23:38:39 +01005517/* Prepares all the contexts for a bind_conf and allocates the shared SSL
5518 * context if needed. Returns < 0 on error, 0 on success. The warnings and
5519 * alerts are directly emitted since the rest of the stack does it below.
5520 */
5521int ssl_sock_prepare_bind_conf(struct bind_conf *bind_conf)
5522{
5523 struct proxy *px = bind_conf->frontend;
5524 int alloc_ctx;
5525 int err;
5526
5527 if (!bind_conf->is_ssl) {
5528 if (bind_conf->default_ctx) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005529 ha_warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
5530 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreau55d37912016-12-21 23:38:39 +01005531 }
5532 return 0;
5533 }
5534 if (!bind_conf->default_ctx) {
Emmanuel Hocdetaa0d6372017-08-09 11:24:25 +02005535 if (bind_conf->strict_sni && !bind_conf->generate_certs) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005536 ha_warning("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d], ssl connections will fail (use 'crt').\n",
5537 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetaa0d6372017-08-09 11:24:25 +02005538 }
5539 else {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005540 ha_alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
5541 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetaa0d6372017-08-09 11:24:25 +02005542 return -1;
5543 }
Willy Tarreau55d37912016-12-21 23:38:39 +01005544 }
William Lallemandc61c0b32017-12-04 18:46:39 +01005545 if (!ssl_shctx && global.tune.sslcachesize) {
William Lallemandc3cd35f2017-11-28 11:04:43 +01005546 alloc_ctx = shctx_init(&ssl_shctx, global.tune.sslcachesize,
Frédéric Lécailleb7838af2018-10-22 16:21:39 +02005547 sizeof(struct sh_ssl_sess_hdr) + SHSESS_BLOCK_MIN_SIZE, -1,
William Lallemandc3cd35f2017-11-28 11:04:43 +01005548 sizeof(*sh_ssl_sess_tree),
5549 ((global.nbthread > 1) || (!global_ssl.private_cache && (global.nbproc > 1))) ? 1 : 0);
Frédéric Lécaille4c8aa112018-10-25 20:22:46 +02005550 if (alloc_ctx <= 0) {
William Lallemandc3cd35f2017-11-28 11:04:43 +01005551 if (alloc_ctx == SHCTX_E_INIT_LOCK)
5552 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");
5553 else
5554 ha_alert("Unable to allocate SSL session cache.\n");
5555 return -1;
5556 }
5557 /* free block callback */
5558 ssl_shctx->free_block = sh_ssl_sess_free_blocks;
5559 /* init the root tree within the extra space */
5560 sh_ssl_sess_tree = (void *)ssl_shctx + sizeof(struct shared_context);
5561 *sh_ssl_sess_tree = EB_ROOT_UNIQUE;
Willy Tarreau55d37912016-12-21 23:38:39 +01005562 }
Willy Tarreau55d37912016-12-21 23:38:39 +01005563 err = 0;
5564 /* initialize all certificate contexts */
5565 err += ssl_sock_prepare_all_ctx(bind_conf);
5566
5567 /* initialize CA variables if the certificates generation is enabled */
5568 err += ssl_sock_load_ca(bind_conf);
5569
5570 return -err;
5571}
Christopher Faulet77fe80c2015-07-29 13:02:40 +02005572
5573/* release ssl context allocated for servers. */
5574void ssl_sock_free_srv_ctx(struct server *srv)
5575{
Olivier Houchardc7566002018-11-20 23:33:50 +01005576#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
5577 if (srv->ssl_ctx.alpn_str)
5578 free(srv->ssl_ctx.alpn_str);
5579#endif
Lukas Tribusda95fd92018-11-25 13:21:27 +01005580#ifdef OPENSSL_NPN_NEGOTIATED
Olivier Houchardc7566002018-11-20 23:33:50 +01005581 if (srv->ssl_ctx.npn_str)
5582 free(srv->ssl_ctx.npn_str);
Lukas Tribus7706b852018-11-26 22:57:17 +01005583#endif
Christopher Faulet77fe80c2015-07-29 13:02:40 +02005584 if (srv->ssl_ctx.ctx)
5585 SSL_CTX_free(srv->ssl_ctx.ctx);
5586}
5587
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005588/* Walks down the two trees in bind_conf and frees all the certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +02005589 * be NULL, in which case nothing is done. The default_ctx is nullified too.
5590 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005591void ssl_sock_free_all_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02005592{
5593 struct ebmb_node *node, *back;
5594 struct sni_ctx *sni;
5595
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005596 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02005597 while (node) {
5598 sni = ebmb_entry(node, struct sni_ctx, name);
5599 back = ebmb_next(node);
5600 ebmb_delete(node);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005601 if (!sni->order) { /* only free the CTX on its first occurrence */
Emeric Brunfc0421f2012-09-07 17:30:07 +02005602 SSL_CTX_free(sni->ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005603 ssl_sock_free_ssl_conf(sni->conf);
5604 free(sni->conf);
5605 sni->conf = NULL;
5606 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02005607 free(sni);
5608 node = back;
5609 }
5610
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005611 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02005612 while (node) {
5613 sni = ebmb_entry(node, struct sni_ctx, name);
5614 back = ebmb_next(node);
5615 ebmb_delete(node);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005616 if (!sni->order) { /* only free the CTX on its first occurrence */
Emeric Brunfc0421f2012-09-07 17:30:07 +02005617 SSL_CTX_free(sni->ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005618 ssl_sock_free_ssl_conf(sni->conf);
5619 free(sni->conf);
5620 sni->conf = NULL;
5621 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02005622 free(sni);
5623 node = back;
5624 }
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01005625 SSL_CTX_free(bind_conf->initial_ctx);
5626 bind_conf->initial_ctx = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005627 bind_conf->default_ctx = NULL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005628 bind_conf->default_ssl_conf = NULL;
Emeric Brune1f38db2012-09-03 20:36:47 +02005629}
5630
Willy Tarreau795cdab2016-12-22 17:30:54 +01005631/* Destroys all the contexts for a bind_conf. This is used during deinit(). */
5632void ssl_sock_destroy_bind_conf(struct bind_conf *bind_conf)
5633{
5634 ssl_sock_free_ca(bind_conf);
5635 ssl_sock_free_all_ctx(bind_conf);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005636 ssl_sock_free_ssl_conf(&bind_conf->ssl_conf);
Willy Tarreau795cdab2016-12-22 17:30:54 +01005637 free(bind_conf->ca_sign_file);
5638 free(bind_conf->ca_sign_pass);
Willy Tarreau17b4aa12018-07-17 10:05:32 +02005639 if (bind_conf->keys_ref && !--bind_conf->keys_ref->refcount) {
Willy Tarreau795cdab2016-12-22 17:30:54 +01005640 free(bind_conf->keys_ref->filename);
5641 free(bind_conf->keys_ref->tlskeys);
5642 LIST_DEL(&bind_conf->keys_ref->list);
5643 free(bind_conf->keys_ref);
5644 }
5645 bind_conf->keys_ref = NULL;
Willy Tarreau795cdab2016-12-22 17:30:54 +01005646 bind_conf->ca_sign_pass = NULL;
5647 bind_conf->ca_sign_file = NULL;
Willy Tarreau795cdab2016-12-22 17:30:54 +01005648}
5649
Christopher Faulet31af49d2015-06-09 17:29:50 +02005650/* Load CA cert file and private key used to generate certificates */
5651int
Willy Tarreau03209342016-12-22 17:08:28 +01005652ssl_sock_load_ca(struct bind_conf *bind_conf)
Christopher Faulet31af49d2015-06-09 17:29:50 +02005653{
Willy Tarreau03209342016-12-22 17:08:28 +01005654 struct proxy *px = bind_conf->frontend;
Christopher Faulet31af49d2015-06-09 17:29:50 +02005655 FILE *fp;
5656 X509 *cacert = NULL;
5657 EVP_PKEY *capkey = NULL;
5658 int err = 0;
5659
Christopher Fauletf8bb0ce2017-09-15 09:52:49 +02005660 if (!bind_conf->generate_certs)
Christopher Faulet31af49d2015-06-09 17:29:50 +02005661 return err;
5662
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005663#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Emeric Brun821bb9b2017-06-15 16:37:39 +02005664 if (global_ssl.ctx_cache) {
Willy Tarreauef934602016-12-22 23:12:01 +01005665 ssl_ctx_lru_tree = lru64_new(global_ssl.ctx_cache);
Emeric Brun821bb9b2017-06-15 16:37:39 +02005666 }
Christopher Fauletd2cab922015-07-28 16:03:47 +02005667 ssl_ctx_lru_seed = (unsigned int)time(NULL);
Emeric Brun821bb9b2017-06-15 16:37:39 +02005668 ssl_ctx_serial = now_ms;
Willy Tarreaua84c2672015-10-09 12:10:13 +02005669#endif
Christopher Fauletd2cab922015-07-28 16:03:47 +02005670
Christopher Faulet31af49d2015-06-09 17:29:50 +02005671 if (!bind_conf->ca_sign_file) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005672 ha_alert("Proxy '%s': cannot enable certificate generation, "
5673 "no CA certificate File configured at [%s:%d].\n",
5674 px->id, bind_conf->file, bind_conf->line);
Christopher Faulet31af49d2015-06-09 17:29:50 +02005675 goto load_error;
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005676 }
Christopher Faulet31af49d2015-06-09 17:29:50 +02005677
5678 /* read in the CA certificate */
5679 if (!(fp = fopen(bind_conf->ca_sign_file, "r"))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005680 ha_alert("Proxy '%s': Failed to read CA certificate file '%s' at [%s:%d].\n",
5681 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Faulet31af49d2015-06-09 17:29:50 +02005682 goto load_error;
5683 }
5684 if (!(cacert = PEM_read_X509(fp, NULL, NULL, NULL))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005685 ha_alert("Proxy '%s': Failed to read CA certificate file '%s' at [%s:%d].\n",
5686 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005687 goto read_error;
Christopher Faulet31af49d2015-06-09 17:29:50 +02005688 }
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005689 rewind(fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02005690 if (!(capkey = PEM_read_PrivateKey(fp, NULL, NULL, bind_conf->ca_sign_pass))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005691 ha_alert("Proxy '%s': Failed to read CA private key file '%s' at [%s:%d].\n",
5692 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005693 goto read_error;
Christopher Faulet31af49d2015-06-09 17:29:50 +02005694 }
Christopher Faulet31af49d2015-06-09 17:29:50 +02005695
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005696 fclose (fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02005697 bind_conf->ca_sign_cert = cacert;
5698 bind_conf->ca_sign_pkey = capkey;
5699 return err;
5700
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005701 read_error:
5702 fclose (fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02005703 if (capkey) EVP_PKEY_free(capkey);
5704 if (cacert) X509_free(cacert);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005705 load_error:
5706 bind_conf->generate_certs = 0;
5707 err++;
Christopher Faulet31af49d2015-06-09 17:29:50 +02005708 return err;
5709}
5710
5711/* Release CA cert and private key used to generate certificated */
5712void
5713ssl_sock_free_ca(struct bind_conf *bind_conf)
5714{
Christopher Faulet31af49d2015-06-09 17:29:50 +02005715 if (bind_conf->ca_sign_pkey)
5716 EVP_PKEY_free(bind_conf->ca_sign_pkey);
5717 if (bind_conf->ca_sign_cert)
5718 X509_free(bind_conf->ca_sign_cert);
Willy Tarreau94ff03a2016-12-22 17:57:46 +01005719 bind_conf->ca_sign_pkey = NULL;
5720 bind_conf->ca_sign_cert = NULL;
Christopher Faulet31af49d2015-06-09 17:29:50 +02005721}
5722
Emeric Brun46591952012-05-18 15:47:34 +02005723/*
5724 * This function is called if SSL * context is not yet allocated. The function
5725 * is designed to be called before any other data-layer operation and sets the
5726 * handshake flag on the connection. It is safe to call it multiple times.
5727 * It returns 0 on success and -1 in error case.
5728 */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005729static int ssl_sock_init(struct connection *conn, void **xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02005730{
Olivier Houchard66ab4982019-02-26 18:37:15 +01005731 struct ssl_sock_ctx *ctx;
Emeric Brun46591952012-05-18 15:47:34 +02005732 /* already initialized */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005733 if (*xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02005734 return 0;
5735
Willy Tarreau3c728722014-01-23 13:50:42 +01005736 if (!conn_ctrl_ready(conn))
Willy Tarreauf79c8172013-10-21 16:30:56 +02005737 return 0;
5738
Olivier Houchard66ab4982019-02-26 18:37:15 +01005739 ctx = pool_alloc(ssl_sock_ctx_pool);
5740 if (!ctx) {
5741 conn->err_code = CO_ER_SSL_NO_MEM;
5742 return -1;
5743 }
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02005744 ctx->wait_event.tasklet = tasklet_new();
5745 if (!ctx->wait_event.tasklet) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02005746 conn->err_code = CO_ER_SSL_NO_MEM;
5747 pool_free(ssl_sock_ctx_pool, ctx);
5748 return -1;
5749 }
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02005750 ctx->wait_event.tasklet->process = ssl_sock_io_cb;
5751 ctx->wait_event.tasklet->context = ctx;
Olivier Houchardea8dd942019-05-20 14:02:16 +02005752 ctx->wait_event.events = 0;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01005753 ctx->sent_early_data = 0;
5754 ctx->tmp_early_data = -1;
Olivier Houcharda8955d52019-04-07 22:00:38 +02005755 ctx->conn = conn;
Olivier Houchard81284e62019-06-06 13:21:23 +02005756 ctx->send_wait = NULL;
5757 ctx->recv_wait = NULL;
Emeric Brun5762a0d2019-09-06 15:36:02 +02005758 ctx->xprt_st = 0;
5759 ctx->xprt_ctx = NULL;
Olivier Houcharda8955d52019-04-07 22:00:38 +02005760
5761 /* Only work with sockets for now, this should be adapted when we'll
5762 * add QUIC support.
5763 */
5764 ctx->xprt = xprt_get(XPRT_RAW);
Olivier Houchard19afb272019-05-23 18:24:07 +02005765 if (ctx->xprt->init) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02005766 if (ctx->xprt->init(conn, &ctx->xprt_ctx) != 0)
5767 goto err;
Olivier Houchard19afb272019-05-23 18:24:07 +02005768 }
Olivier Houchard66ab4982019-02-26 18:37:15 +01005769
Willy Tarreau20879a02012-12-03 16:32:10 +01005770 if (global.maxsslconn && sslconns >= global.maxsslconn) {
5771 conn->err_code = CO_ER_SSL_TOO_MANY;
Olivier Houchardea8dd942019-05-20 14:02:16 +02005772 goto err;
Willy Tarreau20879a02012-12-03 16:32:10 +01005773 }
Willy Tarreau403edff2012-09-06 11:58:37 +02005774
Emeric Brun46591952012-05-18 15:47:34 +02005775 /* If it is in client mode initiate SSL session
5776 in connect state otherwise accept state */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01005777 if (objt_server(conn->target)) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005778 int may_retry = 1;
5779
5780 retry_connect:
Emeric Brun46591952012-05-18 15:47:34 +02005781 /* Alloc a new SSL session ctx */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005782 ctx->ssl = SSL_new(__objt_server(conn->target)->ssl_ctx.ctx);
5783 if (!ctx->ssl) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005784 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005785 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005786 goto retry_connect;
5787 }
Willy Tarreau20879a02012-12-03 16:32:10 +01005788 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01005789 goto err;
Willy Tarreau20879a02012-12-03 16:32:10 +01005790 }
Olivier Houcharda8955d52019-04-07 22:00:38 +02005791 ctx->bio = BIO_new(ha_meth);
5792 if (!ctx->bio) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005793 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005794 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005795 goto retry_connect;
5796 }
Emeric Brun55476152014-11-12 17:35:37 +01005797 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01005798 goto err;
Emeric Brun55476152014-11-12 17:35:37 +01005799 }
Olivier Houcharda8955d52019-04-07 22:00:38 +02005800 BIO_set_data(ctx->bio, ctx);
Olivier Houcharda8955d52019-04-07 22:00:38 +02005801 SSL_set_bio(ctx->ssl, ctx->bio, ctx->bio);
Emeric Brun46591952012-05-18 15:47:34 +02005802
Evan Broderbe554312013-06-27 00:05:25 -07005803 /* set connection pointer */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005804 if (!SSL_set_ex_data(ctx->ssl, ssl_app_data_index, conn)) {
5805 SSL_free(ctx->ssl);
5806 ctx->ssl = NULL;
Emeric Brun55476152014-11-12 17:35:37 +01005807 conn->xprt_ctx = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005808 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005809 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005810 goto retry_connect;
5811 }
Emeric Brun55476152014-11-12 17:35:37 +01005812 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01005813 goto err;
Emeric Brun55476152014-11-12 17:35:37 +01005814 }
5815
Olivier Houchard66ab4982019-02-26 18:37:15 +01005816 SSL_set_connect_state(ctx->ssl);
Willy Tarreau07d94e42018-09-20 10:57:52 +02005817 if (__objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr) {
5818 const unsigned char *ptr = __objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr;
5819 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 +01005820 if (sess && !SSL_set_session(ctx->ssl, sess)) {
Olivier Houcharde6060c52017-11-16 17:42:52 +01005821 SSL_SESSION_free(sess);
Willy Tarreau07d94e42018-09-20 10:57:52 +02005822 free(__objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr);
5823 __objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr = NULL;
Olivier Houcharde6060c52017-11-16 17:42:52 +01005824 } else if (sess) {
5825 SSL_SESSION_free(sess);
Emeric Brun55476152014-11-12 17:35:37 +01005826 }
5827 }
Evan Broderbe554312013-06-27 00:05:25 -07005828
Emeric Brun46591952012-05-18 15:47:34 +02005829 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +02005830 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Willy Tarreau403edff2012-09-06 11:58:37 +02005831
Olivier Houchard2be5a4c2019-03-08 18:54:43 +01005832 _HA_ATOMIC_ADD(&sslconns, 1);
5833 _HA_ATOMIC_ADD(&totalsslconns, 1);
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005834 *xprt_ctx = ctx;
Olivier Houchardea8dd942019-05-20 14:02:16 +02005835 /* Start the handshake */
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02005836 tasklet_wakeup(ctx->wait_event.tasklet);
Olivier Houchardea8dd942019-05-20 14:02:16 +02005837 if (conn->flags & CO_FL_ERROR)
5838 goto err;
Emeric Brun46591952012-05-18 15:47:34 +02005839 return 0;
5840 }
Willy Tarreau3fdb3662012-11-12 00:42:33 +01005841 else if (objt_listener(conn->target)) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005842 int may_retry = 1;
5843
5844 retry_accept:
Emeric Brun46591952012-05-18 15:47:34 +02005845 /* Alloc a new SSL session ctx */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005846 ctx->ssl = SSL_new(__objt_listener(conn->target)->bind_conf->initial_ctx);
5847 if (!ctx->ssl) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005848 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005849 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005850 goto retry_accept;
5851 }
Willy Tarreau20879a02012-12-03 16:32:10 +01005852 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01005853 goto err;
Willy Tarreau20879a02012-12-03 16:32:10 +01005854 }
Emeric Brun46591952012-05-18 15:47:34 +02005855
Olivier Houcharda8955d52019-04-07 22:00:38 +02005856 ctx->bio = BIO_new(ha_meth);
5857 if (!ctx->bio) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005858 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005859 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005860 goto retry_accept;
5861 }
Emeric Brun55476152014-11-12 17:35:37 +01005862 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01005863 goto err;
Emeric Brun55476152014-11-12 17:35:37 +01005864 }
Olivier Houcharda8955d52019-04-07 22:00:38 +02005865 BIO_set_data(ctx->bio, ctx);
Olivier Houcharda8955d52019-04-07 22:00:38 +02005866 SSL_set_bio(ctx->ssl, ctx->bio, ctx->bio);
Emeric Brun46591952012-05-18 15:47:34 +02005867
Emeric Brune1f38db2012-09-03 20:36:47 +02005868 /* set connection pointer */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005869 if (!SSL_set_ex_data(ctx->ssl, ssl_app_data_index, conn)) {
5870 SSL_free(ctx->ssl);
5871 ctx->ssl = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005872 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005873 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005874 goto retry_accept;
5875 }
Emeric Brun55476152014-11-12 17:35:37 +01005876 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01005877 goto err;
Emeric Brun55476152014-11-12 17:35:37 +01005878 }
5879
Olivier Houchard66ab4982019-02-26 18:37:15 +01005880 SSL_set_accept_state(ctx->ssl);
Emeric Brune1f38db2012-09-03 20:36:47 +02005881
Emeric Brun46591952012-05-18 15:47:34 +02005882 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +02005883 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Emmanuel Hocdetf967c312019-08-05 18:04:16 +02005884#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Olivier Houchardc2aae742017-09-22 18:26:28 +02005885 conn->flags |= CO_FL_EARLY_SSL_HS;
5886#endif
Willy Tarreau403edff2012-09-06 11:58:37 +02005887
Olivier Houchard2be5a4c2019-03-08 18:54:43 +01005888 _HA_ATOMIC_ADD(&sslconns, 1);
5889 _HA_ATOMIC_ADD(&totalsslconns, 1);
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005890 *xprt_ctx = ctx;
Olivier Houchardea8dd942019-05-20 14:02:16 +02005891 /* Start the handshake */
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02005892 tasklet_wakeup(ctx->wait_event.tasklet);
Olivier Houchardea8dd942019-05-20 14:02:16 +02005893 if (conn->flags & CO_FL_ERROR)
5894 goto err;
Emeric Brun46591952012-05-18 15:47:34 +02005895 return 0;
5896 }
5897 /* don't know how to handle such a target */
Willy Tarreau20879a02012-12-03 16:32:10 +01005898 conn->err_code = CO_ER_SSL_NO_TARGET;
Olivier Houchard66ab4982019-02-26 18:37:15 +01005899err:
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02005900 if (ctx && ctx->wait_event.tasklet)
5901 tasklet_free(ctx->wait_event.tasklet);
Olivier Houchard66ab4982019-02-26 18:37:15 +01005902 pool_free(ssl_sock_ctx_pool, ctx);
Emeric Brun46591952012-05-18 15:47:34 +02005903 return -1;
5904}
5905
5906
5907/* This is the callback which is used when an SSL handshake is pending. It
5908 * updates the FD status if it wants some polling before being called again.
5909 * It returns 0 if it fails in a fatal way or needs to poll to go further,
5910 * otherwise it returns non-zero and removes itself from the connection's
5911 * flags (the bit is provided in <flag> by the caller).
5912 */
Olivier Houchard000694c2019-05-23 14:45:12 +02005913static int ssl_sock_handshake(struct connection *conn, unsigned int flag)
Emeric Brun46591952012-05-18 15:47:34 +02005914{
Olivier Houchard66ab4982019-02-26 18:37:15 +01005915 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
Emeric Brun46591952012-05-18 15:47:34 +02005916 int ret;
5917
Willy Tarreau3c728722014-01-23 13:50:42 +01005918 if (!conn_ctrl_ready(conn))
Willy Tarreauf79c8172013-10-21 16:30:56 +02005919 return 0;
5920
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005921 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02005922 goto out_error;
5923
Willy Tarreau5db847a2019-05-09 14:13:35 +02005924#if HA_OPENSSL_VERSION_NUMBER >= 0x10101000L
Olivier Houchardc2aae742017-09-22 18:26:28 +02005925 /*
5926 * Check if we have early data. If we do, we have to read them
5927 * before SSL_do_handshake() is called, And there's no way to
5928 * detect early data, except to try to read them
5929 */
5930 if (conn->flags & CO_FL_EARLY_SSL_HS) {
5931 size_t read_data;
5932
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01005933 ret = SSL_read_early_data(ctx->ssl, &ctx->tmp_early_data,
Olivier Houchardc2aae742017-09-22 18:26:28 +02005934 1, &read_data);
5935 if (ret == SSL_READ_EARLY_DATA_ERROR)
5936 goto check_error;
5937 if (ret == SSL_READ_EARLY_DATA_SUCCESS) {
5938 conn->flags &= ~(CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN);
5939 return 1;
5940 } else
5941 conn->flags &= ~CO_FL_EARLY_SSL_HS;
5942 }
5943#endif
Emeric Brun674b7432012-11-08 19:21:55 +01005944 /* If we use SSL_do_handshake to process a reneg initiated by
5945 * the remote peer, it sometimes returns SSL_ERROR_SSL.
5946 * Usually SSL_write and SSL_read are used and process implicitly
5947 * the reneg handshake.
5948 * Here we use SSL_peek as a workaround for reneg.
5949 */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005950 if ((conn->flags & CO_FL_CONNECTED) && SSL_renegotiate_pending(ctx->ssl)) {
Emeric Brun674b7432012-11-08 19:21:55 +01005951 char c;
5952
Olivier Houchard66ab4982019-02-26 18:37:15 +01005953 ret = SSL_peek(ctx->ssl, &c, 1);
Emeric Brun674b7432012-11-08 19:21:55 +01005954 if (ret <= 0) {
5955 /* handshake may have not been completed, let's find why */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005956 ret = SSL_get_error(ctx->ssl, ret);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005957
Emeric Brun674b7432012-11-08 19:21:55 +01005958 if (ret == SSL_ERROR_WANT_WRITE) {
5959 /* SSL handshake needs to write, L4 connection may not be ready */
Olivier Houchard03abf2d2019-05-28 10:12:02 +02005960 if (!(ctx->wait_event.events & SUB_RETRY_SEND))
Olivier Houchardea8dd942019-05-20 14:02:16 +02005961 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_SEND, &ctx->wait_event);
Emeric Brun674b7432012-11-08 19:21:55 +01005962 return 0;
5963 }
5964 else if (ret == SSL_ERROR_WANT_READ) {
5965 /* handshake may have been completed but we have
5966 * no more data to read.
5967 */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005968 if (!SSL_renegotiate_pending(ctx->ssl)) {
Emeric Brun674b7432012-11-08 19:21:55 +01005969 ret = 1;
5970 goto reneg_ok;
5971 }
5972 /* SSL handshake needs to read, L4 connection is ready */
Olivier Houchard03abf2d2019-05-28 10:12:02 +02005973 if (!(ctx->wait_event.events & SUB_RETRY_RECV))
Olivier Houchardea8dd942019-05-20 14:02:16 +02005974 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_RECV, &ctx->wait_event);
Emeric Brun674b7432012-11-08 19:21:55 +01005975 return 0;
5976 }
Willy Tarreau5db847a2019-05-09 14:13:35 +02005977#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005978 else if (ret == SSL_ERROR_WANT_ASYNC) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02005979 ssl_async_process_fds(ctx);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005980 return 0;
5981 }
5982#endif
Emeric Brun674b7432012-11-08 19:21:55 +01005983 else if (ret == SSL_ERROR_SYSCALL) {
5984 /* if errno is null, then connection was successfully established */
5985 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
5986 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Willy Tarreau20879a02012-12-03 16:32:10 +01005987 if (!conn->err_code) {
Lukas Tribus49799162019-07-08 14:29:15 +02005988#if defined(OPENSSL_IS_BORINGSSL) || defined(LIBRESSL_VERSION_NUMBER)
5989 /* do not handle empty handshakes in BoringSSL or LibreSSL */
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005990 conn->err_code = CO_ER_SSL_HANDSHAKE;
5991#else
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005992 int empty_handshake;
Willy Tarreau5db847a2019-05-09 14:13:35 +02005993#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL)
Lukas Tribus49799162019-07-08 14:29:15 +02005994 /* use SSL_get_state() in OpenSSL >= 1.1.0; SSL_state() is broken */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005995 OSSL_HANDSHAKE_STATE state = SSL_get_state((SSL *)ctx->ssl);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005996 empty_handshake = state == TLS_ST_BEFORE;
5997#else
Lukas Tribus49799162019-07-08 14:29:15 +02005998 /* access packet_length directly in OpenSSL <= 1.0.2; SSL_state() is broken */
5999 empty_handshake = !ctx->ssl->packet_length;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006000#endif
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006001 if (empty_handshake) {
Emeric Brun29f037d2014-04-25 19:05:36 +02006002 if (!errno) {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006003 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emeric Brun29f037d2014-04-25 19:05:36 +02006004 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
6005 else
6006 conn->err_code = CO_ER_SSL_EMPTY;
6007 }
6008 else {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006009 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emeric Brun29f037d2014-04-25 19:05:36 +02006010 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
6011 else
6012 conn->err_code = CO_ER_SSL_ABORT;
6013 }
6014 }
6015 else {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006016 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emeric Brun29f037d2014-04-25 19:05:36 +02006017 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
Willy Tarreau20879a02012-12-03 16:32:10 +01006018 else
Emeric Brun29f037d2014-04-25 19:05:36 +02006019 conn->err_code = CO_ER_SSL_HANDSHAKE;
6020 }
Lukas Tribus49799162019-07-08 14:29:15 +02006021#endif /* BoringSSL or LibreSSL */
Willy Tarreau20879a02012-12-03 16:32:10 +01006022 }
Emeric Brun674b7432012-11-08 19:21:55 +01006023 goto out_error;
6024 }
6025 else {
6026 /* Fail on all other handshake errors */
6027 /* Note: OpenSSL may leave unread bytes in the socket's
6028 * buffer, causing an RST to be emitted upon close() on
6029 * TCP sockets. We first try to drain possibly pending
6030 * data to avoid this as much as possible.
6031 */
Willy Tarreaud85c4852015-03-13 00:40:28 +01006032 conn_sock_drain(conn);
Willy Tarreau20879a02012-12-03 16:32:10 +01006033 if (!conn->err_code)
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006034 conn->err_code = (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT) ?
Willy Tarreauf51c6982014-04-25 20:02:39 +02006035 CO_ER_SSL_KILLED_HB : CO_ER_SSL_HANDSHAKE;
Emeric Brun674b7432012-11-08 19:21:55 +01006036 goto out_error;
6037 }
6038 }
6039 /* read some data: consider handshake completed */
6040 goto reneg_ok;
6041 }
Olivier Houchard66ab4982019-02-26 18:37:15 +01006042 ret = SSL_do_handshake(ctx->ssl);
Olivier Houchardc2aae742017-09-22 18:26:28 +02006043check_error:
Emeric Brun46591952012-05-18 15:47:34 +02006044 if (ret != 1) {
6045 /* handshake did not complete, let's find why */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006046 ret = SSL_get_error(ctx->ssl, ret);
Emeric Brun46591952012-05-18 15:47:34 +02006047
6048 if (ret == SSL_ERROR_WANT_WRITE) {
6049 /* SSL handshake needs to write, L4 connection may not be ready */
Olivier Houchard03abf2d2019-05-28 10:12:02 +02006050 if (!(ctx->wait_event.events & SUB_RETRY_SEND))
Olivier Houchardea8dd942019-05-20 14:02:16 +02006051 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_SEND, &ctx->wait_event);
Emeric Brun46591952012-05-18 15:47:34 +02006052 return 0;
6053 }
6054 else if (ret == SSL_ERROR_WANT_READ) {
6055 /* SSL handshake needs to read, L4 connection is ready */
Olivier Houchardea8dd942019-05-20 14:02:16 +02006056 if (!(ctx->wait_event.events & SUB_RETRY_RECV))
Olivier Houchardea8dd942019-05-20 14:02:16 +02006057 ctx->xprt->subscribe(conn, ctx->xprt_ctx,
6058 SUB_RETRY_RECV, &ctx->wait_event);
Emeric Brun46591952012-05-18 15:47:34 +02006059 return 0;
6060 }
Willy Tarreau5db847a2019-05-09 14:13:35 +02006061#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006062 else if (ret == SSL_ERROR_WANT_ASYNC) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02006063 ssl_async_process_fds(ctx);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006064 return 0;
6065 }
6066#endif
Willy Tarreau89230192012-09-28 20:22:13 +02006067 else if (ret == SSL_ERROR_SYSCALL) {
6068 /* if errno is null, then connection was successfully established */
6069 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
6070 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01006071 if (!conn->err_code) {
Lukas Tribus49799162019-07-08 14:29:15 +02006072#if defined(OPENSSL_IS_BORINGSSL) || defined(LIBRESSL_VERSION_NUMBER)
6073 /* do not handle empty handshakes in BoringSSL or LibreSSL */
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01006074 conn->err_code = CO_ER_SSL_HANDSHAKE;
6075#else
6076 int empty_handshake;
Willy Tarreau5db847a2019-05-09 14:13:35 +02006077#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL)
Lukas Tribus49799162019-07-08 14:29:15 +02006078 /* use SSL_get_state() in OpenSSL >= 1.1.0; SSL_state() is broken */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006079 OSSL_HANDSHAKE_STATE state = SSL_get_state(ctx->ssl);
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01006080 empty_handshake = state == TLS_ST_BEFORE;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006081#else
Lukas Tribus49799162019-07-08 14:29:15 +02006082 /* access packet_length directly in OpenSSL <= 1.0.2; SSL_state() is broken */
6083 empty_handshake = !ctx->ssl->packet_length;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006084#endif
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01006085 if (empty_handshake) {
6086 if (!errno) {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006087 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01006088 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
6089 else
6090 conn->err_code = CO_ER_SSL_EMPTY;
6091 }
6092 else {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006093 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01006094 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
6095 else
6096 conn->err_code = CO_ER_SSL_ABORT;
6097 }
Emeric Brun29f037d2014-04-25 19:05:36 +02006098 }
6099 else {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006100 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emeric Brun29f037d2014-04-25 19:05:36 +02006101 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
6102 else
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01006103 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun29f037d2014-04-25 19:05:36 +02006104 }
Lukas Tribus49799162019-07-08 14:29:15 +02006105#endif /* BoringSSL or LibreSSL */
Emeric Brun29f037d2014-04-25 19:05:36 +02006106 }
Willy Tarreau89230192012-09-28 20:22:13 +02006107 goto out_error;
6108 }
Emeric Brun46591952012-05-18 15:47:34 +02006109 else {
6110 /* Fail on all other handshake errors */
Willy Tarreau566dc552012-10-19 20:52:18 +02006111 /* Note: OpenSSL may leave unread bytes in the socket's
6112 * buffer, causing an RST to be emitted upon close() on
6113 * TCP sockets. We first try to drain possibly pending
6114 * data to avoid this as much as possible.
6115 */
Willy Tarreaud85c4852015-03-13 00:40:28 +01006116 conn_sock_drain(conn);
Willy Tarreau20879a02012-12-03 16:32:10 +01006117 if (!conn->err_code)
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006118 conn->err_code = (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT) ?
Willy Tarreauf51c6982014-04-25 20:02:39 +02006119 CO_ER_SSL_KILLED_HB : CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02006120 goto out_error;
6121 }
6122 }
Willy Tarreau5db847a2019-05-09 14:13:35 +02006123#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Olivier Houchard522eea72017-11-03 16:27:47 +01006124 else {
6125 /*
6126 * If the server refused the early data, we have to send a
6127 * 425 to the client, as we no longer have the data to sent
6128 * them again.
6129 */
6130 if ((conn->flags & CO_FL_EARLY_DATA) && (objt_server(conn->target))) {
Olivier Houchard66ab4982019-02-26 18:37:15 +01006131 if (SSL_get_early_data_status(ctx->ssl) == SSL_EARLY_DATA_REJECTED) {
Olivier Houchard522eea72017-11-03 16:27:47 +01006132 conn->err_code = CO_ER_SSL_EARLY_FAILED;
6133 goto out_error;
6134 }
6135 }
6136 }
6137#endif
6138
Emeric Brun46591952012-05-18 15:47:34 +02006139
Emeric Brun674b7432012-11-08 19:21:55 +01006140reneg_ok:
Emeric Brunb5e42a82017-06-06 12:35:14 +00006141
Willy Tarreau5db847a2019-05-09 14:13:35 +02006142#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00006143 /* ASYNC engine API doesn't support moving read/write
6144 * buffers. So we disable ASYNC mode right after
6145 * the handshake to avoid buffer oveflows.
6146 */
6147 if (global_ssl.async)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006148 SSL_clear_mode(ctx->ssl, SSL_MODE_ASYNC);
Emeric Brunb5e42a82017-06-06 12:35:14 +00006149#endif
Emeric Brun46591952012-05-18 15:47:34 +02006150 /* Handshake succeeded */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006151 if (!SSL_session_reused(ctx->ssl)) {
Willy Tarreau0c9c2722014-05-28 12:28:58 +02006152 if (objt_server(conn->target)) {
6153 update_freq_ctr(&global.ssl_be_keys_per_sec, 1);
6154 if (global.ssl_be_keys_per_sec.curr_ctr > global.ssl_be_keys_max)
6155 global.ssl_be_keys_max = global.ssl_be_keys_per_sec.curr_ctr;
Emeric Brun46591952012-05-18 15:47:34 +02006156 }
Willy Tarreau0c9c2722014-05-28 12:28:58 +02006157 else {
6158 update_freq_ctr(&global.ssl_fe_keys_per_sec, 1);
6159 if (global.ssl_fe_keys_per_sec.curr_ctr > global.ssl_fe_keys_max)
6160 global.ssl_fe_keys_max = global.ssl_fe_keys_per_sec.curr_ctr;
6161 }
Emeric Brun46591952012-05-18 15:47:34 +02006162 }
6163
6164 /* The connection is now established at both layers, it's time to leave */
6165 conn->flags &= ~(flag | CO_FL_WAIT_L4_CONN | CO_FL_WAIT_L6_CONN);
6166 return 1;
6167
6168 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01006169 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02006170 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01006171 ERR_clear_error();
6172
Emeric Brun9fa89732012-10-04 17:09:56 +02006173 /* free resumed session if exists */
Willy Tarreau07d94e42018-09-20 10:57:52 +02006174 if (objt_server(conn->target) && __objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr) {
6175 free(__objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr);
6176 __objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr = NULL;
Emeric Brun9fa89732012-10-04 17:09:56 +02006177 }
6178
Emeric Brun46591952012-05-18 15:47:34 +02006179 /* Fail on all other handshake errors */
6180 conn->flags |= CO_FL_ERROR;
Willy Tarreau20879a02012-12-03 16:32:10 +01006181 if (!conn->err_code)
6182 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02006183 return 0;
6184}
6185
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006186static int ssl_subscribe(struct connection *conn, void *xprt_ctx, int event_type, void *param)
Olivier Houcharddf357842019-03-21 16:30:07 +01006187{
Olivier Houchardea8dd942019-05-20 14:02:16 +02006188 struct wait_event *sw;
6189 struct ssl_sock_ctx *ctx = xprt_ctx;
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006190
Olivier Houchard0ff28652019-06-24 18:57:39 +02006191 if (!ctx)
6192 return -1;
6193
Olivier Houchardea8dd942019-05-20 14:02:16 +02006194 if (event_type & SUB_RETRY_RECV) {
6195 sw = param;
6196 BUG_ON(ctx->recv_wait != NULL || (sw->events & SUB_RETRY_RECV));
6197 sw->events |= SUB_RETRY_RECV;
6198 ctx->recv_wait = sw;
6199 if (!(conn->flags & CO_FL_SSL_WAIT_HS) &&
6200 !(ctx->wait_event.events & SUB_RETRY_RECV))
6201 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_RECV, &ctx->wait_event);
6202 event_type &= ~SUB_RETRY_RECV;
6203 }
6204 if (event_type & SUB_RETRY_SEND) {
6205sw = param;
6206 BUG_ON(ctx->send_wait != NULL || (sw->events & SUB_RETRY_SEND));
6207 sw->events |= SUB_RETRY_SEND;
6208 ctx->send_wait = sw;
6209 if (!(conn->flags & CO_FL_SSL_WAIT_HS) &&
6210 !(ctx->wait_event.events & SUB_RETRY_SEND))
6211 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_SEND, &ctx->wait_event);
6212 event_type &= ~SUB_RETRY_SEND;
6213
6214 }
6215 if (event_type != 0)
6216 return -1;
6217 return 0;
Olivier Houcharddf357842019-03-21 16:30:07 +01006218}
6219
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006220static int ssl_unsubscribe(struct connection *conn, void *xprt_ctx, int event_type, void *param)
Olivier Houcharddf357842019-03-21 16:30:07 +01006221{
Olivier Houchardea8dd942019-05-20 14:02:16 +02006222 struct wait_event *sw;
6223 struct ssl_sock_ctx *ctx = xprt_ctx;
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006224
Olivier Houchardea8dd942019-05-20 14:02:16 +02006225 if (event_type & SUB_RETRY_RECV) {
6226 sw = param;
6227 BUG_ON(ctx->recv_wait != sw);
6228 ctx->recv_wait = NULL;
6229 sw->events &= ~SUB_RETRY_RECV;
6230 /* If we subscribed, and we're not doing the handshake,
6231 * then we subscribed because the upper layer asked for it,
6232 * as the upper layer is no longer interested, we can
6233 * unsubscribe too.
6234 */
6235 if (!(ctx->conn->flags & CO_FL_SSL_WAIT_HS) &&
6236 (ctx->wait_event.events & SUB_RETRY_RECV))
6237 conn_unsubscribe(conn, ctx->xprt_ctx, SUB_RETRY_RECV,
6238 &ctx->wait_event);
6239 }
6240 if (event_type & SUB_RETRY_SEND) {
6241 sw = param;
6242 BUG_ON(ctx->send_wait != sw);
6243 ctx->send_wait = NULL;
6244 sw->events &= ~SUB_RETRY_SEND;
6245 if (!(ctx->conn->flags & CO_FL_SSL_WAIT_HS) &&
6246 (ctx->wait_event.events & SUB_RETRY_SEND))
6247 conn_unsubscribe(conn, ctx->xprt_ctx, SUB_RETRY_SEND,
6248 &ctx->wait_event);
6249
6250 }
6251
6252 return 0;
Olivier Houcharddf357842019-03-21 16:30:07 +01006253}
6254
Olivier Houchard2e055482019-05-27 19:50:12 +02006255/* Use the provided XPRT as an underlying XPRT, and provide the old one.
6256 * Returns 0 on success, and non-zero on failure.
6257 */
6258static 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)
6259{
6260 struct ssl_sock_ctx *ctx = xprt_ctx;
6261
6262 if (oldxprt_ops != NULL)
6263 *oldxprt_ops = ctx->xprt;
6264 if (oldxprt_ctx != NULL)
6265 *oldxprt_ctx = ctx->xprt_ctx;
6266 ctx->xprt = toadd_ops;
6267 ctx->xprt_ctx = toadd_ctx;
6268 return 0;
6269}
6270
Olivier Houchard5149b592019-05-23 17:47:36 +02006271/* Remove the specified xprt. If if it our underlying XPRT, remove it and
6272 * return 0, otherwise just call the remove_xprt method from the underlying
6273 * XPRT.
6274 */
6275static int ssl_remove_xprt(struct connection *conn, void *xprt_ctx, void *toremove_ctx, const struct xprt_ops *newops, void *newctx)
6276{
6277 struct ssl_sock_ctx *ctx = xprt_ctx;
6278
6279 if (ctx->xprt_ctx == toremove_ctx) {
6280 ctx->xprt_ctx = newctx;
6281 ctx->xprt = newops;
6282 return 0;
6283 }
6284 return (ctx->xprt->remove_xprt(conn, ctx->xprt_ctx, toremove_ctx, newops, newctx));
6285}
6286
Olivier Houchardea8dd942019-05-20 14:02:16 +02006287static struct task *ssl_sock_io_cb(struct task *t, void *context, unsigned short state)
6288{
6289 struct ssl_sock_ctx *ctx = context;
6290
6291 /* First if we're doing an handshake, try that */
6292 if (ctx->conn->flags & CO_FL_SSL_WAIT_HS)
6293 ssl_sock_handshake(ctx->conn, CO_FL_SSL_WAIT_HS);
6294 /* If we had an error, or the handshake is done and I/O is available,
6295 * let the upper layer know.
6296 * If no mux was set up yet, and nobody subscribed, then call
6297 * xprt_done_cb() ourself if it's set, or destroy the connection,
6298 * we can't be sure conn_fd_handler() will be called again.
6299 */
6300 if ((ctx->conn->flags & CO_FL_ERROR) ||
6301 !(ctx->conn->flags & CO_FL_SSL_WAIT_HS)) {
6302 int ret = 0;
6303 int woke = 0;
6304
6305 /* On error, wake any waiter */
6306 if (ctx->recv_wait) {
6307 ctx->recv_wait->events &= ~SUB_RETRY_RECV;
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02006308 tasklet_wakeup(ctx->recv_wait->tasklet);
Olivier Houchardea8dd942019-05-20 14:02:16 +02006309 ctx->recv_wait = NULL;
6310 woke = 1;
6311 }
6312 if (ctx->send_wait) {
6313 ctx->send_wait->events &= ~SUB_RETRY_SEND;
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02006314 tasklet_wakeup(ctx->send_wait->tasklet);
Olivier Houchardea8dd942019-05-20 14:02:16 +02006315 ctx->send_wait = NULL;
6316 woke = 1;
6317 }
6318 /* If we're the first xprt for the connection, let the
6319 * upper layers know. If xprt_done_cb() is set, call it,
6320 * otherwise, we should have a mux, so call its wake
6321 * method if we didn't woke a tasklet already.
6322 */
6323 if (ctx->conn->xprt_ctx == ctx) {
6324 if (ctx->conn->xprt_done_cb)
6325 ret = ctx->conn->xprt_done_cb(ctx->conn);
6326 if (ret >= 0 && !woke && ctx->conn->mux && ctx->conn->mux->wake)
6327 ctx->conn->mux->wake(ctx->conn);
6328 return NULL;
6329 }
6330 }
6331 return NULL;
6332}
6333
Emeric Brun46591952012-05-18 15:47:34 +02006334/* Receive up to <count> bytes from connection <conn>'s socket and store them
Willy Tarreauabf08d92014-01-14 11:31:27 +01006335 * into buffer <buf>. Only one call to recv() is performed, unless the
Emeric Brun46591952012-05-18 15:47:34 +02006336 * buffer wraps, in which case a second call may be performed. The connection's
6337 * flags are updated with whatever special event is detected (error, read0,
6338 * empty). The caller is responsible for taking care of those events and
6339 * avoiding the call if inappropriate. The function does not call the
6340 * connection's polling update function, so the caller is responsible for this.
6341 */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006342static 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 +02006343{
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006344 struct ssl_sock_ctx *ctx = xprt_ctx;
Willy Tarreaubfc4d772018-07-18 11:22:03 +02006345 ssize_t ret;
6346 size_t try, done = 0;
Emeric Brun46591952012-05-18 15:47:34 +02006347
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02006348 conn_refresh_polling_flags(conn);
6349
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006350 if (!ctx)
Emeric Brun46591952012-05-18 15:47:34 +02006351 goto out_error;
6352
6353 if (conn->flags & CO_FL_HANDSHAKE)
6354 /* a handshake was requested */
6355 return 0;
6356
Emeric Brun46591952012-05-18 15:47:34 +02006357 /* read the largest possible block. For this, we perform only one call
6358 * to recv() unless the buffer wraps and we exactly fill the first hunk,
6359 * in which case we accept to do it once again. A new attempt is made on
6360 * EINTR too.
6361 */
Willy Tarreau00b0fb92014-01-17 11:09:40 +01006362 while (count > 0) {
Olivier Houchardc2aae742017-09-22 18:26:28 +02006363 int need_out = 0;
6364
Willy Tarreau591d4452018-06-15 17:21:00 +02006365 try = b_contig_space(buf);
6366 if (!try)
6367 break;
6368
Willy Tarreauabf08d92014-01-14 11:31:27 +01006369 if (try > count)
6370 try = count;
Willy Tarreau591d4452018-06-15 17:21:00 +02006371
Olivier Houchardc2aae742017-09-22 18:26:28 +02006372 if (((conn->flags & (CO_FL_EARLY_SSL_HS | CO_FL_EARLY_DATA)) == CO_FL_EARLY_SSL_HS) &&
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006373 ctx->tmp_early_data != -1) {
6374 *b_tail(buf) = ctx->tmp_early_data;
Olivier Houchardc2aae742017-09-22 18:26:28 +02006375 done++;
6376 try--;
6377 count--;
Olivier Houchardacd14032018-06-28 18:17:23 +02006378 b_add(buf, 1);
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006379 ctx->tmp_early_data = -1;
Olivier Houchardc2aae742017-09-22 18:26:28 +02006380 continue;
6381 }
Willy Tarreauabf08d92014-01-14 11:31:27 +01006382
Willy Tarreau5db847a2019-05-09 14:13:35 +02006383#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Olivier Houchardc2aae742017-09-22 18:26:28 +02006384 if (conn->flags & CO_FL_EARLY_SSL_HS) {
6385 size_t read_length;
6386
Olivier Houchard66ab4982019-02-26 18:37:15 +01006387 ret = SSL_read_early_data(ctx->ssl,
Willy Tarreau8f9c72d2018-06-07 18:46:28 +02006388 b_tail(buf), try, &read_length);
Olivier Houchard522eea72017-11-03 16:27:47 +01006389 if (ret == SSL_READ_EARLY_DATA_SUCCESS &&
6390 read_length > 0)
Olivier Houchardc2aae742017-09-22 18:26:28 +02006391 conn->flags |= CO_FL_EARLY_DATA;
6392 if (ret == SSL_READ_EARLY_DATA_SUCCESS ||
6393 ret == SSL_READ_EARLY_DATA_FINISH) {
6394 if (ret == SSL_READ_EARLY_DATA_FINISH) {
6395 /*
6396 * We're done reading the early data,
6397 * let's make the handshake
6398 */
6399 conn->flags &= ~CO_FL_EARLY_SSL_HS;
6400 conn->flags |= CO_FL_SSL_WAIT_HS;
6401 need_out = 1;
Olivier Houchard965e84e2019-06-15 20:59:30 +02006402 /* Now initiate the handshake */
6403 tasklet_wakeup(ctx->wait_event.tasklet);
Olivier Houchardc2aae742017-09-22 18:26:28 +02006404 if (read_length == 0)
6405 break;
6406 }
6407 ret = read_length;
6408 }
6409 } else
6410#endif
Olivier Houchard66ab4982019-02-26 18:37:15 +01006411 ret = SSL_read(ctx->ssl, b_tail(buf), try);
Emmanuel Hocdetf967c312019-08-05 18:04:16 +02006412
Emeric Brune1f38db2012-09-03 20:36:47 +02006413 if (conn->flags & CO_FL_ERROR) {
6414 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01006415 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02006416 }
Emeric Brun46591952012-05-18 15:47:34 +02006417 if (ret > 0) {
Olivier Houchardacd14032018-06-28 18:17:23 +02006418 b_add(buf, ret);
Emeric Brun46591952012-05-18 15:47:34 +02006419 done += ret;
Emeric Brun46591952012-05-18 15:47:34 +02006420 count -= ret;
Emeric Brun46591952012-05-18 15:47:34 +02006421 }
Emeric Brun46591952012-05-18 15:47:34 +02006422 else {
Olivier Houchard66ab4982019-02-26 18:37:15 +01006423 ret = SSL_get_error(ctx->ssl, ret);
Emeric Brun46591952012-05-18 15:47:34 +02006424 if (ret == SSL_ERROR_WANT_WRITE) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01006425 /* handshake is running, and it needs to enable write */
Emeric Brun46591952012-05-18 15:47:34 +02006426 conn->flags |= CO_FL_SSL_WAIT_HS;
Olivier Houchardea8dd942019-05-20 14:02:16 +02006427 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_SEND, &ctx->wait_event);
Willy Tarreau5db847a2019-05-09 14:13:35 +02006428#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00006429 /* Async mode can be re-enabled, because we're leaving data state.*/
6430 if (global_ssl.async)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006431 SSL_set_mode(ctx->ssl, SSL_MODE_ASYNC);
Emeric Brunb5e42a82017-06-06 12:35:14 +00006432#endif
Emeric Brun46591952012-05-18 15:47:34 +02006433 break;
6434 }
6435 else if (ret == SSL_ERROR_WANT_READ) {
Olivier Houchard66ab4982019-02-26 18:37:15 +01006436 if (SSL_renegotiate_pending(ctx->ssl)) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02006437 ctx->xprt->subscribe(conn, ctx->xprt_ctx,
6438 SUB_RETRY_RECV,
6439 &ctx->wait_event);
Emeric Brun282a76a2012-11-08 18:02:56 +01006440 /* handshake is running, and it may need to re-enable read */
6441 conn->flags |= CO_FL_SSL_WAIT_HS;
Willy Tarreau5db847a2019-05-09 14:13:35 +02006442#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00006443 /* Async mode can be re-enabled, because we're leaving data state.*/
6444 if (global_ssl.async)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006445 SSL_set_mode(ctx->ssl, SSL_MODE_ASYNC);
Emeric Brunb5e42a82017-06-06 12:35:14 +00006446#endif
Emeric Brun282a76a2012-11-08 18:02:56 +01006447 break;
6448 }
Emeric Brun46591952012-05-18 15:47:34 +02006449 break;
Olivier Houchardc2aae742017-09-22 18:26:28 +02006450 } else if (ret == SSL_ERROR_ZERO_RETURN)
6451 goto read0;
Christopher Faulet4ac77a92018-02-19 14:25:15 +01006452 /* For SSL_ERROR_SYSCALL, make sure to clear the error
6453 * stack before shutting down the connection for
6454 * reading. */
Olivier Houchard7e2e5052018-02-13 15:17:23 +01006455 if (ret == SSL_ERROR_SYSCALL && (!errno || errno == EAGAIN))
6456 goto clear_ssl_error;
Emeric Brun46591952012-05-18 15:47:34 +02006457 /* otherwise it's a real error */
6458 goto out_error;
6459 }
Olivier Houchardc2aae742017-09-22 18:26:28 +02006460 if (need_out)
6461 break;
Emeric Brun46591952012-05-18 15:47:34 +02006462 }
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02006463 leave:
Emeric Brun46591952012-05-18 15:47:34 +02006464 return done;
6465
Christopher Faulet4ac77a92018-02-19 14:25:15 +01006466 clear_ssl_error:
6467 /* Clear openssl global errors stack */
6468 ssl_sock_dump_errors(conn);
6469 ERR_clear_error();
Emeric Brun46591952012-05-18 15:47:34 +02006470 read0:
6471 conn_sock_read0(conn);
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02006472 goto leave;
Christopher Faulet4ac77a92018-02-19 14:25:15 +01006473
Emeric Brun46591952012-05-18 15:47:34 +02006474 out_error:
Olivier Houchard7e2e5052018-02-13 15:17:23 +01006475 conn->flags |= CO_FL_ERROR;
Emeric Brun644cde02012-12-14 11:21:13 +01006476 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02006477 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01006478 ERR_clear_error();
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02006479 goto leave;
Emeric Brun46591952012-05-18 15:47:34 +02006480}
6481
6482
Willy Tarreau787db9a2018-06-14 18:31:46 +02006483/* Send up to <count> pending bytes from buffer <buf> to connection <conn>'s
6484 * socket. <flags> may contain some CO_SFL_* flags to hint the system about
6485 * other pending data for example, but this flag is ignored at the moment.
Emeric Brun46591952012-05-18 15:47:34 +02006486 * Only one call to send() is performed, unless the buffer wraps, in which case
6487 * a second call may be performed. The connection's flags are updated with
6488 * whatever special event is detected (error, empty). The caller is responsible
6489 * for taking care of those events and avoiding the call if inappropriate. The
6490 * function does not call the connection's polling update function, so the caller
Willy Tarreau787db9a2018-06-14 18:31:46 +02006491 * is responsible for this. The buffer's output is not adjusted, it's up to the
6492 * caller to take care of this. It's up to the caller to update the buffer's
6493 * contents based on the return value.
Emeric Brun46591952012-05-18 15:47:34 +02006494 */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006495static 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 +02006496{
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006497 struct ssl_sock_ctx *ctx = xprt_ctx;
Willy Tarreau787db9a2018-06-14 18:31:46 +02006498 ssize_t ret;
6499 size_t try, done;
Emeric Brun46591952012-05-18 15:47:34 +02006500
6501 done = 0;
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02006502 conn_refresh_polling_flags(conn);
Emeric Brun46591952012-05-18 15:47:34 +02006503
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006504 if (!ctx)
Emeric Brun46591952012-05-18 15:47:34 +02006505 goto out_error;
6506
Olivier Houchard010941f2019-05-03 20:56:19 +02006507 if (conn->flags & (CO_FL_HANDSHAKE | CO_FL_EARLY_SSL_HS))
Emeric Brun46591952012-05-18 15:47:34 +02006508 /* a handshake was requested */
6509 return 0;
6510
6511 /* send the largest possible block. For this we perform only one call
6512 * to send() unless the buffer wraps and we exactly fill the first hunk,
6513 * in which case we accept to do it once again.
6514 */
Willy Tarreau787db9a2018-06-14 18:31:46 +02006515 while (count) {
Willy Tarreau5db847a2019-05-09 14:13:35 +02006516#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Olivier Houchardc2aae742017-09-22 18:26:28 +02006517 size_t written_data;
6518#endif
6519
Willy Tarreau787db9a2018-06-14 18:31:46 +02006520 try = b_contig_data(buf, done);
6521 if (try > count)
6522 try = count;
Willy Tarreaubfd59462013-02-21 07:46:09 +01006523
Willy Tarreau7bed9452014-02-02 02:00:24 +01006524 if (!(flags & CO_SFL_STREAMER) &&
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006525 !(ctx->xprt_st & SSL_SOCK_SEND_UNLIMITED) &&
Willy Tarreauef934602016-12-22 23:12:01 +01006526 global_ssl.max_record && try > global_ssl.max_record) {
6527 try = global_ssl.max_record;
Willy Tarreau518cedd2014-02-17 15:43:01 +01006528 }
6529 else {
6530 /* we need to keep the information about the fact that
6531 * we're not limiting the upcoming send(), because if it
6532 * fails, we'll have to retry with at least as many data.
6533 */
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006534 ctx->xprt_st |= SSL_SOCK_SEND_UNLIMITED;
Willy Tarreau518cedd2014-02-17 15:43:01 +01006535 }
Willy Tarreaubfd59462013-02-21 07:46:09 +01006536
Willy Tarreau5db847a2019-05-09 14:13:35 +02006537#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Olivier Houchard010941f2019-05-03 20:56:19 +02006538 if (!SSL_is_init_finished(ctx->ssl) && conn_is_back(conn)) {
Olivier Houchardc2aae742017-09-22 18:26:28 +02006539 unsigned int max_early;
6540
Olivier Houchard522eea72017-11-03 16:27:47 +01006541 if (objt_listener(conn->target))
Olivier Houchard66ab4982019-02-26 18:37:15 +01006542 max_early = SSL_get_max_early_data(ctx->ssl);
Olivier Houchard522eea72017-11-03 16:27:47 +01006543 else {
Olivier Houchard66ab4982019-02-26 18:37:15 +01006544 if (SSL_get0_session(ctx->ssl))
6545 max_early = SSL_SESSION_get_max_early_data(SSL_get0_session(ctx->ssl));
Olivier Houchard522eea72017-11-03 16:27:47 +01006546 else
6547 max_early = 0;
6548 }
6549
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006550 if (try + ctx->sent_early_data > max_early) {
6551 try -= (try + ctx->sent_early_data) - max_early;
Olivier Houchard522eea72017-11-03 16:27:47 +01006552 if (try <= 0) {
Olivier Houchard010941f2019-05-03 20:56:19 +02006553 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Olivier Houchard965e84e2019-06-15 20:59:30 +02006554 tasklet_wakeup(ctx->wait_event.tasklet);
Olivier Houchardc2aae742017-09-22 18:26:28 +02006555 break;
Olivier Houchard522eea72017-11-03 16:27:47 +01006556 }
Olivier Houchardc2aae742017-09-22 18:26:28 +02006557 }
Olivier Houchard66ab4982019-02-26 18:37:15 +01006558 ret = SSL_write_early_data(ctx->ssl, b_peek(buf, done), try, &written_data);
Olivier Houchardc2aae742017-09-22 18:26:28 +02006559 if (ret == 1) {
6560 ret = written_data;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006561 ctx->sent_early_data += ret;
Olivier Houchard965e84e2019-06-15 20:59:30 +02006562 if (objt_server(conn->target)) {
Olivier Houchard522eea72017-11-03 16:27:47 +01006563 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN | CO_FL_EARLY_DATA;
Olivier Houchard965e84e2019-06-15 20:59:30 +02006564 /* Initiate the handshake, now */
6565 tasklet_wakeup(ctx->wait_event.tasklet);
6566 }
Olivier Houchard522eea72017-11-03 16:27:47 +01006567
Olivier Houchardc2aae742017-09-22 18:26:28 +02006568 }
6569
6570 } else
6571#endif
Olivier Houchard66ab4982019-02-26 18:37:15 +01006572 ret = SSL_write(ctx->ssl, b_peek(buf, done), try);
Willy Tarreau518cedd2014-02-17 15:43:01 +01006573
Emeric Brune1f38db2012-09-03 20:36:47 +02006574 if (conn->flags & CO_FL_ERROR) {
6575 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01006576 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02006577 }
Emeric Brun46591952012-05-18 15:47:34 +02006578 if (ret > 0) {
Olivier Houchardf24502b2019-01-17 19:09:11 +01006579 /* A send succeeded, so we can consier ourself connected */
6580 conn->flags |= CO_FL_CONNECTED;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006581 ctx->xprt_st &= ~SSL_SOCK_SEND_UNLIMITED;
Willy Tarreau787db9a2018-06-14 18:31:46 +02006582 count -= ret;
Emeric Brun46591952012-05-18 15:47:34 +02006583 done += ret;
Emeric Brun46591952012-05-18 15:47:34 +02006584 }
6585 else {
Olivier Houchard66ab4982019-02-26 18:37:15 +01006586 ret = SSL_get_error(ctx->ssl, ret);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006587
Emeric Brun46591952012-05-18 15:47:34 +02006588 if (ret == SSL_ERROR_WANT_WRITE) {
Olivier Houchard66ab4982019-02-26 18:37:15 +01006589 if (SSL_renegotiate_pending(ctx->ssl)) {
Emeric Brun282a76a2012-11-08 18:02:56 +01006590 /* handshake is running, and it may need to re-enable write */
6591 conn->flags |= CO_FL_SSL_WAIT_HS;
Olivier Houchardea8dd942019-05-20 14:02:16 +02006592 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_SEND, &ctx->wait_event);
Willy Tarreau5db847a2019-05-09 14:13:35 +02006593#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00006594 /* Async mode can be re-enabled, because we're leaving data state.*/
6595 if (global_ssl.async)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006596 SSL_set_mode(ctx->ssl, SSL_MODE_ASYNC);
Emeric Brunb5e42a82017-06-06 12:35:14 +00006597#endif
Emeric Brun282a76a2012-11-08 18:02:56 +01006598 break;
6599 }
Olivier Houchardea8dd942019-05-20 14:02:16 +02006600
Emeric Brun46591952012-05-18 15:47:34 +02006601 break;
6602 }
6603 else if (ret == SSL_ERROR_WANT_READ) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01006604 /* handshake is running, and it needs to enable read */
Emeric Brun46591952012-05-18 15:47:34 +02006605 conn->flags |= CO_FL_SSL_WAIT_HS;
Olivier Houchardea8dd942019-05-20 14:02:16 +02006606 ctx->xprt->subscribe(conn, ctx->xprt_ctx,
6607 SUB_RETRY_RECV,
6608 &ctx->wait_event);
Willy Tarreau5db847a2019-05-09 14:13:35 +02006609#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00006610 /* Async mode can be re-enabled, because we're leaving data state.*/
6611 if (global_ssl.async)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006612 SSL_set_mode(ctx->ssl, SSL_MODE_ASYNC);
Emeric Brunb5e42a82017-06-06 12:35:14 +00006613#endif
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006614 break;
6615 }
Emeric Brun46591952012-05-18 15:47:34 +02006616 goto out_error;
6617 }
6618 }
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02006619 leave:
Emeric Brun46591952012-05-18 15:47:34 +02006620 return done;
6621
6622 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01006623 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02006624 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01006625 ERR_clear_error();
6626
Emeric Brun46591952012-05-18 15:47:34 +02006627 conn->flags |= CO_FL_ERROR;
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02006628 goto leave;
Emeric Brun46591952012-05-18 15:47:34 +02006629}
6630
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006631static void ssl_sock_close(struct connection *conn, void *xprt_ctx) {
Emeric Brun46591952012-05-18 15:47:34 +02006632
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006633 struct ssl_sock_ctx *ctx = xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006634
Olivier Houchardea8dd942019-05-20 14:02:16 +02006635
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006636 if (ctx) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02006637 if (ctx->wait_event.events != 0)
6638 ctx->xprt->unsubscribe(ctx->conn, ctx->xprt_ctx,
6639 ctx->wait_event.events,
6640 &ctx->wait_event);
6641 if (ctx->send_wait) {
6642 ctx->send_wait->events &= ~SUB_RETRY_SEND;
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02006643 tasklet_wakeup(ctx->send_wait->tasklet);
Olivier Houchardea8dd942019-05-20 14:02:16 +02006644 }
6645 if (ctx->recv_wait) {
6646 ctx->recv_wait->events &= ~SUB_RETRY_RECV;
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02006647 tasklet_wakeup(ctx->recv_wait->tasklet);
Olivier Houchardea8dd942019-05-20 14:02:16 +02006648 }
Olivier Houchard692c1d02019-05-23 18:41:47 +02006649 if (ctx->xprt->close)
6650 ctx->xprt->close(conn, ctx->xprt_ctx);
Willy Tarreau5db847a2019-05-09 14:13:35 +02006651#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brun3854e012017-05-17 20:42:48 +02006652 if (global_ssl.async) {
6653 OSSL_ASYNC_FD all_fd[32], afd;
6654 size_t num_all_fds = 0;
6655 int i;
6656
Olivier Houchard66ab4982019-02-26 18:37:15 +01006657 SSL_get_all_async_fds(ctx->ssl, NULL, &num_all_fds);
Emeric Brun3854e012017-05-17 20:42:48 +02006658 if (num_all_fds > 32) {
6659 send_log(NULL, LOG_EMERG, "haproxy: openssl returns too many async fds. It seems a bug. Process may crash\n");
6660 return;
6661 }
6662
Olivier Houchard66ab4982019-02-26 18:37:15 +01006663 SSL_get_all_async_fds(ctx->ssl, all_fd, &num_all_fds);
Emeric Brun3854e012017-05-17 20:42:48 +02006664
6665 /* If an async job is pending, we must try to
6666 to catch the end using polling before calling
6667 SSL_free */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006668 if (num_all_fds && SSL_waiting_for_async(ctx->ssl)) {
Emeric Brun3854e012017-05-17 20:42:48 +02006669 for (i=0 ; i < num_all_fds ; i++) {
6670 /* switch on an handler designed to
6671 * handle the SSL_free
6672 */
6673 afd = all_fd[i];
6674 fdtab[afd].iocb = ssl_async_fd_free;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006675 fdtab[afd].owner = ctx->ssl;
Emeric Brun3854e012017-05-17 20:42:48 +02006676 fd_want_recv(afd);
Emeric Brunce9e01c2017-05-31 10:02:53 +00006677 /* To ensure that the fd cache won't be used
6678 * and we'll catch a real RD event.
6679 */
6680 fd_cant_recv(afd);
Emeric Brun3854e012017-05-17 20:42:48 +02006681 }
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02006682 tasklet_free(ctx->wait_event.tasklet);
Olivier Houchard66ab4982019-02-26 18:37:15 +01006683 pool_free(ssl_sock_ctx_pool, ctx);
Olivier Houchard2be5a4c2019-03-08 18:54:43 +01006684 _HA_ATOMIC_ADD(&jobs, 1);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006685 return;
6686 }
Emeric Brun3854e012017-05-17 20:42:48 +02006687 /* Else we can remove the fds from the fdtab
6688 * and call SSL_free.
6689 * note: we do a fd_remove and not a delete
6690 * because the fd is owned by the engine.
6691 * the engine is responsible to close
6692 */
6693 for (i=0 ; i < num_all_fds ; i++)
6694 fd_remove(all_fd[i]);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006695 }
6696#endif
Olivier Houchard66ab4982019-02-26 18:37:15 +01006697 SSL_free(ctx->ssl);
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02006698 tasklet_free(ctx->wait_event.tasklet);
Olivier Houchard66ab4982019-02-26 18:37:15 +01006699 pool_free(ssl_sock_ctx_pool, ctx);
Olivier Houchard2be5a4c2019-03-08 18:54:43 +01006700 _HA_ATOMIC_SUB(&sslconns, 1);
Emeric Brun46591952012-05-18 15:47:34 +02006701 }
Emeric Brun46591952012-05-18 15:47:34 +02006702}
6703
6704/* This function tries to perform a clean shutdown on an SSL connection, and in
6705 * any case, flags the connection as reusable if no handshake was in progress.
6706 */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006707static void ssl_sock_shutw(struct connection *conn, void *xprt_ctx, int clean)
Emeric Brun46591952012-05-18 15:47:34 +02006708{
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006709 struct ssl_sock_ctx *ctx = xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006710
Emeric Brun46591952012-05-18 15:47:34 +02006711 if (conn->flags & CO_FL_HANDSHAKE)
6712 return;
Emmanuel Hocdet405ff312017-01-08 14:07:39 +01006713 if (!clean)
6714 /* don't sent notify on SSL_shutdown */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006715 SSL_set_quiet_shutdown(ctx->ssl, 1);
Emeric Brun46591952012-05-18 15:47:34 +02006716 /* no handshake was in progress, try a clean ssl shutdown */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006717 if (SSL_shutdown(ctx->ssl) <= 0) {
Emeric Brun644cde02012-12-14 11:21:13 +01006718 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02006719 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01006720 ERR_clear_error();
6721 }
Emeric Brun46591952012-05-18 15:47:34 +02006722}
6723
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01006724/* used for ppv2 pkey alog (can be used for logging) */
Willy Tarreau83061a82018-07-13 11:56:34 +02006725int ssl_sock_get_pkey_algo(struct connection *conn, struct buffer *out)
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01006726{
Christopher Faulet82004142019-09-10 10:12:03 +02006727 struct ssl_sock_ctx *ctx;
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01006728 int bits = 0;
6729 int sig = TLSEXT_signature_anonymous;
6730 int len = -1;
Emmanuel Hocdetc3775d22019-11-04 18:19:32 +01006731 X509 *crt;
6732 EVP_PKEY *pkey;
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01006733
6734 if (!ssl_sock_is_ssl(conn))
6735 return 0;
Christopher Faulet82004142019-09-10 10:12:03 +02006736 ctx = conn->xprt_ctx;
Emmanuel Hocdetc3775d22019-11-04 18:19:32 +01006737
6738 crt = SSL_get_certificate(ctx->ssl);
6739 if (!crt)
6740 return 0;
6741 pkey = X509_get_pubkey(crt);
6742 if (pkey) {
6743 bits = EVP_PKEY_bits(pkey);
6744 switch(EVP_PKEY_base_id(pkey)) {
6745 case EVP_PKEY_RSA:
6746 sig = TLSEXT_signature_rsa;
6747 break;
6748 case EVP_PKEY_EC:
6749 sig = TLSEXT_signature_ecdsa;
6750 break;
6751 case EVP_PKEY_DSA:
6752 sig = TLSEXT_signature_dsa;
6753 break;
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01006754 }
Emmanuel Hocdetc3775d22019-11-04 18:19:32 +01006755 EVP_PKEY_free(pkey);
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01006756 }
6757
6758 switch(sig) {
6759 case TLSEXT_signature_rsa:
6760 len = chunk_printf(out, "RSA%d", bits);
6761 break;
6762 case TLSEXT_signature_ecdsa:
6763 len = chunk_printf(out, "EC%d", bits);
6764 break;
6765 case TLSEXT_signature_dsa:
6766 len = chunk_printf(out, "DSA%d", bits);
6767 break;
6768 default:
6769 return 0;
6770 }
6771 if (len < 0)
6772 return 0;
6773 return 1;
6774}
6775
Emmanuel Hocdet283e0042017-11-02 14:05:23 +01006776/* used for ppv2 cert signature (can be used for logging) */
6777const char *ssl_sock_get_cert_sig(struct connection *conn)
6778{
Christopher Faulet82004142019-09-10 10:12:03 +02006779 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006780
Emmanuel Hocdet283e0042017-11-02 14:05:23 +01006781 __OPENSSL_110_CONST__ ASN1_OBJECT *algorithm;
6782 X509 *crt;
6783
6784 if (!ssl_sock_is_ssl(conn))
6785 return NULL;
Christopher Faulet82004142019-09-10 10:12:03 +02006786 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006787 crt = SSL_get_certificate(ctx->ssl);
Emmanuel Hocdet283e0042017-11-02 14:05:23 +01006788 if (!crt)
6789 return NULL;
6790 X509_ALGOR_get0(&algorithm, NULL, NULL, X509_get0_tbs_sigalg(crt));
6791 return OBJ_nid2sn(OBJ_obj2nid(algorithm));
6792}
6793
Emmanuel Hocdet253c3b72018-02-01 18:29:59 +01006794/* used for ppv2 authority */
6795const char *ssl_sock_get_sni(struct connection *conn)
6796{
6797#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Christopher Faulet82004142019-09-10 10:12:03 +02006798 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006799
Emmanuel Hocdet253c3b72018-02-01 18:29:59 +01006800 if (!ssl_sock_is_ssl(conn))
6801 return NULL;
Christopher Faulet82004142019-09-10 10:12:03 +02006802 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006803 return SSL_get_servername(ctx->ssl, TLSEXT_NAMETYPE_host_name);
Emmanuel Hocdet253c3b72018-02-01 18:29:59 +01006804#else
Olivier Houchard66ab4982019-02-26 18:37:15 +01006805 return NULL;
Emmanuel Hocdet253c3b72018-02-01 18:29:59 +01006806#endif
6807}
6808
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02006809/* used for logging/ppv2, may be changed for a sample fetch later */
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02006810const char *ssl_sock_get_cipher_name(struct connection *conn)
6811{
Christopher Faulet82004142019-09-10 10:12:03 +02006812 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006813
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02006814 if (!ssl_sock_is_ssl(conn))
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02006815 return NULL;
Christopher Faulet82004142019-09-10 10:12:03 +02006816 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006817 return SSL_get_cipher_name(ctx->ssl);
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02006818}
6819
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02006820/* used for logging/ppv2, may be changed for a sample fetch later */
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02006821const char *ssl_sock_get_proto_version(struct connection *conn)
6822{
Christopher Faulet82004142019-09-10 10:12:03 +02006823 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006824
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02006825 if (!ssl_sock_is_ssl(conn))
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02006826 return NULL;
Christopher Faulet82004142019-09-10 10:12:03 +02006827 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006828 return SSL_get_version(ctx->ssl);
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02006829}
6830
Willy Tarreau8d598402012-10-22 17:58:39 +02006831/* Extract a serial from a cert, and copy it to a chunk.
6832 * Returns 1 if serial is found and copied, 0 if no serial found and
6833 * -1 if output is not large enough.
6834 */
6835static int
Willy Tarreau83061a82018-07-13 11:56:34 +02006836ssl_sock_get_serial(X509 *crt, struct buffer *out)
Willy Tarreau8d598402012-10-22 17:58:39 +02006837{
6838 ASN1_INTEGER *serial;
6839
6840 serial = X509_get_serialNumber(crt);
6841 if (!serial)
6842 return 0;
6843
6844 if (out->size < serial->length)
6845 return -1;
6846
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006847 memcpy(out->area, serial->data, serial->length);
6848 out->data = serial->length;
Willy Tarreau8d598402012-10-22 17:58:39 +02006849 return 1;
6850}
6851
Emeric Brun43e79582014-10-29 19:03:26 +01006852/* Extract a cert to der, and copy it to a chunk.
Joseph Herlant017b3da2018-11-15 09:07:59 -08006853 * Returns 1 if the cert is found and copied, 0 on der conversion failure
6854 * and -1 if the output is not large enough.
Emeric Brun43e79582014-10-29 19:03:26 +01006855 */
6856static int
Willy Tarreau83061a82018-07-13 11:56:34 +02006857ssl_sock_crt2der(X509 *crt, struct buffer *out)
Emeric Brun43e79582014-10-29 19:03:26 +01006858{
6859 int len;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006860 unsigned char *p = (unsigned char *) out->area;;
Emeric Brun43e79582014-10-29 19:03:26 +01006861
6862 len =i2d_X509(crt, NULL);
6863 if (len <= 0)
6864 return 1;
6865
6866 if (out->size < len)
6867 return -1;
6868
6869 i2d_X509(crt,&p);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006870 out->data = len;
Emeric Brun43e79582014-10-29 19:03:26 +01006871 return 1;
6872}
6873
Emeric Brunce5ad802012-10-22 14:11:22 +02006874
Willy Tarreau83061a82018-07-13 11:56:34 +02006875/* Copy Date in ASN1_UTCTIME format in struct buffer out.
Emeric Brunce5ad802012-10-22 14:11:22 +02006876 * Returns 1 if serial is found and copied, 0 if no valid time found
6877 * and -1 if output is not large enough.
6878 */
6879static int
Willy Tarreau83061a82018-07-13 11:56:34 +02006880ssl_sock_get_time(ASN1_TIME *tm, struct buffer *out)
Emeric Brunce5ad802012-10-22 14:11:22 +02006881{
6882 if (tm->type == V_ASN1_GENERALIZEDTIME) {
6883 ASN1_GENERALIZEDTIME *gentm = (ASN1_GENERALIZEDTIME *)tm;
6884
6885 if (gentm->length < 12)
6886 return 0;
6887 if (gentm->data[0] != 0x32 || gentm->data[1] != 0x30)
6888 return 0;
6889 if (out->size < gentm->length-2)
6890 return -1;
6891
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006892 memcpy(out->area, gentm->data+2, gentm->length-2);
6893 out->data = gentm->length-2;
Emeric Brunce5ad802012-10-22 14:11:22 +02006894 return 1;
6895 }
6896 else if (tm->type == V_ASN1_UTCTIME) {
6897 ASN1_UTCTIME *utctm = (ASN1_UTCTIME *)tm;
6898
6899 if (utctm->length < 10)
6900 return 0;
6901 if (utctm->data[0] >= 0x35)
6902 return 0;
6903 if (out->size < utctm->length)
6904 return -1;
6905
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006906 memcpy(out->area, utctm->data, utctm->length);
6907 out->data = utctm->length;
Emeric Brunce5ad802012-10-22 14:11:22 +02006908 return 1;
6909 }
6910
6911 return 0;
6912}
6913
Emeric Brun87855892012-10-17 17:39:35 +02006914/* Extract an entry from a X509_NAME and copy its value to an output chunk.
6915 * Returns 1 if entry found, 0 if entry not found, or -1 if output not large enough.
6916 */
6917static int
Willy Tarreau83061a82018-07-13 11:56:34 +02006918ssl_sock_get_dn_entry(X509_NAME *a, const struct buffer *entry, int pos,
6919 struct buffer *out)
Emeric Brun87855892012-10-17 17:39:35 +02006920{
6921 X509_NAME_ENTRY *ne;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006922 ASN1_OBJECT *obj;
6923 ASN1_STRING *data;
6924 const unsigned char *data_ptr;
6925 int data_len;
Emeric Brun87855892012-10-17 17:39:35 +02006926 int i, j, n;
6927 int cur = 0;
6928 const char *s;
6929 char tmp[128];
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006930 int name_count;
6931
6932 name_count = X509_NAME_entry_count(a);
Emeric Brun87855892012-10-17 17:39:35 +02006933
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006934 out->data = 0;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006935 for (i = 0; i < name_count; i++) {
Emeric Brun87855892012-10-17 17:39:35 +02006936 if (pos < 0)
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006937 j = (name_count-1) - i;
Emeric Brun87855892012-10-17 17:39:35 +02006938 else
6939 j = i;
6940
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006941 ne = X509_NAME_get_entry(a, j);
6942 obj = X509_NAME_ENTRY_get_object(ne);
6943 data = X509_NAME_ENTRY_get_data(ne);
6944 data_ptr = ASN1_STRING_get0_data(data);
6945 data_len = ASN1_STRING_length(data);
6946 n = OBJ_obj2nid(obj);
Emeric Brun87855892012-10-17 17:39:35 +02006947 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006948 i2t_ASN1_OBJECT(tmp, sizeof(tmp), obj);
Emeric Brun87855892012-10-17 17:39:35 +02006949 s = tmp;
6950 }
6951
6952 if (chunk_strcasecmp(entry, s) != 0)
6953 continue;
6954
6955 if (pos < 0)
6956 cur--;
6957 else
6958 cur++;
6959
6960 if (cur != pos)
6961 continue;
6962
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006963 if (data_len > out->size)
Emeric Brun87855892012-10-17 17:39:35 +02006964 return -1;
6965
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006966 memcpy(out->area, data_ptr, data_len);
6967 out->data = data_len;
Emeric Brun87855892012-10-17 17:39:35 +02006968 return 1;
6969 }
6970
6971 return 0;
6972
6973}
6974
6975/* Extract and format full DN from a X509_NAME and copy result into a chunk
6976 * Returns 1 if dn entries exits, 0 if no dn entry found or -1 if output is not large enough.
6977 */
6978static int
Willy Tarreau83061a82018-07-13 11:56:34 +02006979ssl_sock_get_dn_oneline(X509_NAME *a, struct buffer *out)
Emeric Brun87855892012-10-17 17:39:35 +02006980{
6981 X509_NAME_ENTRY *ne;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006982 ASN1_OBJECT *obj;
6983 ASN1_STRING *data;
6984 const unsigned char *data_ptr;
6985 int data_len;
Emeric Brun87855892012-10-17 17:39:35 +02006986 int i, n, ln;
6987 int l = 0;
6988 const char *s;
6989 char *p;
6990 char tmp[128];
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006991 int name_count;
6992
6993
6994 name_count = X509_NAME_entry_count(a);
Emeric Brun87855892012-10-17 17:39:35 +02006995
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006996 out->data = 0;
6997 p = out->area;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006998 for (i = 0; i < name_count; i++) {
6999 ne = X509_NAME_get_entry(a, i);
7000 obj = X509_NAME_ENTRY_get_object(ne);
7001 data = X509_NAME_ENTRY_get_data(ne);
7002 data_ptr = ASN1_STRING_get0_data(data);
7003 data_len = ASN1_STRING_length(data);
7004 n = OBJ_obj2nid(obj);
Emeric Brun87855892012-10-17 17:39:35 +02007005 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007006 i2t_ASN1_OBJECT(tmp, sizeof(tmp), obj);
Emeric Brun87855892012-10-17 17:39:35 +02007007 s = tmp;
7008 }
7009 ln = strlen(s);
7010
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007011 l += 1 + ln + 1 + data_len;
Emeric Brun87855892012-10-17 17:39:35 +02007012 if (l > out->size)
7013 return -1;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007014 out->data = l;
Emeric Brun87855892012-10-17 17:39:35 +02007015
7016 *(p++)='/';
7017 memcpy(p, s, ln);
7018 p += ln;
7019 *(p++)='=';
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007020 memcpy(p, data_ptr, data_len);
7021 p += data_len;
Emeric Brun87855892012-10-17 17:39:35 +02007022 }
7023
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007024 if (!out->data)
Emeric Brun87855892012-10-17 17:39:35 +02007025 return 0;
7026
7027 return 1;
7028}
7029
Olivier Houchardab28a322018-12-21 19:45:40 +01007030void ssl_sock_set_alpn(struct connection *conn, const unsigned char *alpn, int len)
7031{
7032#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Christopher Faulet82004142019-09-10 10:12:03 +02007033 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007034
Olivier Houcharde488ea82019-06-28 14:10:33 +02007035 if (!ssl_sock_is_ssl(conn))
7036 return;
Christopher Faulet82004142019-09-10 10:12:03 +02007037 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007038 SSL_set_alpn_protos(ctx->ssl, alpn, len);
Olivier Houchardab28a322018-12-21 19:45:40 +01007039#endif
7040}
7041
Willy Tarreau119a4082016-12-22 21:58:38 +01007042/* Sets advertised SNI for outgoing connections. Please set <hostname> to NULL
7043 * to disable SNI.
7044 */
Willy Tarreau63076412015-07-10 11:33:32 +02007045void ssl_sock_set_servername(struct connection *conn, const char *hostname)
7046{
7047#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Christopher Faulet82004142019-09-10 10:12:03 +02007048 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007049
Willy Tarreau119a4082016-12-22 21:58:38 +01007050 char *prev_name;
7051
Willy Tarreau63076412015-07-10 11:33:32 +02007052 if (!ssl_sock_is_ssl(conn))
7053 return;
Christopher Faulet82004142019-09-10 10:12:03 +02007054 ctx = conn->xprt_ctx;
Willy Tarreau63076412015-07-10 11:33:32 +02007055
Willy Tarreau119a4082016-12-22 21:58:38 +01007056 /* if the SNI changes, we must destroy the reusable context so that a
7057 * new connection will present a new SNI. As an optimization we could
7058 * later imagine having a small cache of ssl_ctx to hold a few SNI per
7059 * server.
7060 */
Olivier Houchard66ab4982019-02-26 18:37:15 +01007061 prev_name = (char *)SSL_get_servername(ctx->ssl, TLSEXT_NAMETYPE_host_name);
Willy Tarreau119a4082016-12-22 21:58:38 +01007062 if ((!prev_name && hostname) ||
7063 (prev_name && (!hostname || strcmp(hostname, prev_name) != 0)))
Olivier Houchard66ab4982019-02-26 18:37:15 +01007064 SSL_set_session(ctx->ssl, NULL);
Willy Tarreau119a4082016-12-22 21:58:38 +01007065
Olivier Houchard66ab4982019-02-26 18:37:15 +01007066 SSL_set_tlsext_host_name(ctx->ssl, hostname);
Willy Tarreau63076412015-07-10 11:33:32 +02007067#endif
7068}
7069
Emeric Brun0abf8362014-06-24 18:26:41 +02007070/* Extract peer certificate's common name into the chunk dest
7071 * Returns
7072 * the len of the extracted common name
7073 * or 0 if no CN found in DN
7074 * or -1 on error case (i.e. no peer certificate)
7075 */
Willy Tarreau83061a82018-07-13 11:56:34 +02007076int ssl_sock_get_remote_common_name(struct connection *conn,
7077 struct buffer *dest)
David Safb76832014-05-08 23:42:08 -04007078{
Christopher Faulet82004142019-09-10 10:12:03 +02007079 struct ssl_sock_ctx *ctx;
David Safb76832014-05-08 23:42:08 -04007080 X509 *crt = NULL;
7081 X509_NAME *name;
David Safb76832014-05-08 23:42:08 -04007082 const char find_cn[] = "CN";
Willy Tarreau83061a82018-07-13 11:56:34 +02007083 const struct buffer find_cn_chunk = {
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007084 .area = (char *)&find_cn,
7085 .data = sizeof(find_cn)-1
David Safb76832014-05-08 23:42:08 -04007086 };
Emeric Brun0abf8362014-06-24 18:26:41 +02007087 int result = -1;
David Safb76832014-05-08 23:42:08 -04007088
7089 if (!ssl_sock_is_ssl(conn))
Emeric Brun0abf8362014-06-24 18:26:41 +02007090 goto out;
Christopher Faulet82004142019-09-10 10:12:03 +02007091 ctx = conn->xprt_ctx;
David Safb76832014-05-08 23:42:08 -04007092
7093 /* SSL_get_peer_certificate, it increase X509 * ref count */
Olivier Houchard66ab4982019-02-26 18:37:15 +01007094 crt = SSL_get_peer_certificate(ctx->ssl);
David Safb76832014-05-08 23:42:08 -04007095 if (!crt)
7096 goto out;
7097
7098 name = X509_get_subject_name(crt);
7099 if (!name)
7100 goto out;
David Safb76832014-05-08 23:42:08 -04007101
Emeric Brun0abf8362014-06-24 18:26:41 +02007102 result = ssl_sock_get_dn_entry(name, &find_cn_chunk, 1, dest);
7103out:
David Safb76832014-05-08 23:42:08 -04007104 if (crt)
7105 X509_free(crt);
7106
7107 return result;
7108}
7109
Dave McCowan328fb582014-07-30 10:39:13 -04007110/* returns 1 if client passed a certificate for this session, 0 if not */
7111int ssl_sock_get_cert_used_sess(struct connection *conn)
7112{
Christopher Faulet82004142019-09-10 10:12:03 +02007113 struct ssl_sock_ctx *ctx;
Dave McCowan328fb582014-07-30 10:39:13 -04007114 X509 *crt = NULL;
7115
7116 if (!ssl_sock_is_ssl(conn))
7117 return 0;
Christopher Faulet82004142019-09-10 10:12:03 +02007118 ctx = conn->xprt_ctx;
Dave McCowan328fb582014-07-30 10:39:13 -04007119
7120 /* SSL_get_peer_certificate, it increase X509 * ref count */
Olivier Houchard66ab4982019-02-26 18:37:15 +01007121 crt = SSL_get_peer_certificate(ctx->ssl);
Dave McCowan328fb582014-07-30 10:39:13 -04007122 if (!crt)
7123 return 0;
7124
7125 X509_free(crt);
7126 return 1;
7127}
7128
7129/* returns 1 if client passed a certificate for this connection, 0 if not */
7130int ssl_sock_get_cert_used_conn(struct connection *conn)
David Safb76832014-05-08 23:42:08 -04007131{
Christopher Faulet82004142019-09-10 10:12:03 +02007132 struct ssl_sock_ctx *ctx;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007133
David Safb76832014-05-08 23:42:08 -04007134 if (!ssl_sock_is_ssl(conn))
7135 return 0;
Christopher Faulet82004142019-09-10 10:12:03 +02007136 ctx = conn->xprt_ctx;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007137 return SSL_SOCK_ST_FL_VERIFY_DONE & ctx->xprt_st ? 1 : 0;
David Safb76832014-05-08 23:42:08 -04007138}
7139
7140/* returns result from SSL verify */
7141unsigned int ssl_sock_get_verify_result(struct connection *conn)
7142{
Christopher Faulet82004142019-09-10 10:12:03 +02007143 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007144
David Safb76832014-05-08 23:42:08 -04007145 if (!ssl_sock_is_ssl(conn))
7146 return (unsigned int)X509_V_ERR_APPLICATION_VERIFICATION;
Christopher Faulet82004142019-09-10 10:12:03 +02007147 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007148 return (unsigned int)SSL_get_verify_result(ctx->ssl);
David Safb76832014-05-08 23:42:08 -04007149}
7150
Willy Tarreau8743f7e2016-12-04 18:44:29 +01007151/* Returns the application layer protocol name in <str> and <len> when known.
7152 * Zero is returned if the protocol name was not found, otherwise non-zero is
7153 * returned. The string is allocated in the SSL context and doesn't have to be
7154 * freed by the caller. NPN is also checked if available since older versions
7155 * of openssl (1.0.1) which are more common in field only support this one.
7156 */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01007157static int ssl_sock_get_alpn(const struct connection *conn, void *xprt_ctx, const char **str, int *len)
Willy Tarreau8743f7e2016-12-04 18:44:29 +01007158{
Olivier Houchard66ab4982019-02-26 18:37:15 +01007159#if defined(TLSEXT_TYPE_application_layer_protocol_negotiation) || \
7160 defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Olivier Houcharde179d0e2019-03-21 18:27:17 +01007161 struct ssl_sock_ctx *ctx = xprt_ctx;
7162 if (!ctx)
Willy Tarreau8743f7e2016-12-04 18:44:29 +01007163 return 0;
7164
7165 *str = NULL;
7166
7167#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Olivier Houchard66ab4982019-02-26 18:37:15 +01007168 SSL_get0_alpn_selected(ctx->ssl, (const unsigned char **)str, (unsigned *)len);
Willy Tarreau8743f7e2016-12-04 18:44:29 +01007169 if (*str)
7170 return 1;
7171#endif
Bernard Spil13c53f82018-02-15 13:34:58 +01007172#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007173 SSL_get0_next_proto_negotiated(ctx->ssl, (const unsigned char **)str, (unsigned *)len);
Willy Tarreau8743f7e2016-12-04 18:44:29 +01007174 if (*str)
7175 return 1;
7176#endif
Olivier Houcharde179d0e2019-03-21 18:27:17 +01007177#endif
Willy Tarreau8743f7e2016-12-04 18:44:29 +01007178 return 0;
7179}
7180
Willy Tarreau7875d092012-09-10 08:20:03 +02007181/***** Below are some sample fetching functions for ACL/patterns *****/
7182
Olivier Houchardccaa7de2017-10-02 11:51:03 +02007183static int
7184smp_fetch_ssl_fc_has_early(const struct arg *args, struct sample *smp, const char *kw, void *private)
7185{
7186 struct connection *conn;
7187
7188 conn = objt_conn(smp->sess->origin);
7189 if (!conn || conn->xprt != &ssl_sock)
7190 return 0;
7191
7192 smp->flags = 0;
7193 smp->data.type = SMP_T_BOOL;
Emmanuel Hocdetc9858012019-08-07 14:44:49 +02007194#ifdef OPENSSL_IS_BORINGSSL
7195 {
7196 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
7197 smp->data.u.sint = (SSL_in_early_data(ctx->ssl) &&
7198 SSL_early_data_accepted(ctx->ssl));
7199 }
7200#else
Olivier Houchard25ae45a2017-11-29 19:51:19 +01007201 smp->data.u.sint = ((conn->flags & CO_FL_EARLY_DATA) &&
7202 (conn->flags & (CO_FL_EARLY_SSL_HS | CO_FL_HANDSHAKE))) ? 1 : 0;
Emmanuel Hocdetc9858012019-08-07 14:44:49 +02007203#endif
Olivier Houchardccaa7de2017-10-02 11:51:03 +02007204 return 1;
7205}
7206
Emeric Brune64aef12012-09-21 13:15:06 +02007207/* boolean, returns true if client cert was present */
7208static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007209smp_fetch_ssl_fc_has_crt(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brune64aef12012-09-21 13:15:06 +02007210{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007211 struct connection *conn;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007212 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007213
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007214 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007215 if (!conn || conn->xprt != &ssl_sock)
Emeric Brune64aef12012-09-21 13:15:06 +02007216 return 0;
7217
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007218 ctx = conn->xprt_ctx;
7219
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007220 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brune64aef12012-09-21 13:15:06 +02007221 smp->flags |= SMP_F_MAY_CHANGE;
7222 return 0;
7223 }
7224
7225 smp->flags = 0;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007226 smp->data.type = SMP_T_BOOL;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007227 smp->data.u.sint = SSL_SOCK_ST_FL_VERIFY_DONE & ctx->xprt_st ? 1 : 0;
Emeric Brune64aef12012-09-21 13:15:06 +02007228
7229 return 1;
7230}
7231
Emeric Brun43e79582014-10-29 19:03:26 +01007232/* binary, returns a certificate in a binary chunk (der/raw).
7233 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7234 * should be use.
7235 */
7236static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007237smp_fetch_ssl_x_der(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun43e79582014-10-29 19:03:26 +01007238{
7239 int cert_peer = (kw[4] == 'c') ? 1 : 0;
7240 X509 *crt = NULL;
7241 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02007242 struct buffer *smp_trash;
Emeric Brun43e79582014-10-29 19:03:26 +01007243 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007244 struct ssl_sock_ctx *ctx;
Emeric Brun43e79582014-10-29 19:03:26 +01007245
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007246 conn = objt_conn(smp->sess->origin);
Emeric Brun43e79582014-10-29 19:03:26 +01007247 if (!conn || conn->xprt != &ssl_sock)
7248 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007249 ctx = conn->xprt_ctx;
Emeric Brun43e79582014-10-29 19:03:26 +01007250
7251 if (!(conn->flags & CO_FL_CONNECTED)) {
7252 smp->flags |= SMP_F_MAY_CHANGE;
7253 return 0;
7254 }
7255
7256 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007257 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brun43e79582014-10-29 19:03:26 +01007258 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007259 crt = SSL_get_certificate(ctx->ssl);
Emeric Brun43e79582014-10-29 19:03:26 +01007260
7261 if (!crt)
7262 goto out;
7263
7264 smp_trash = get_trash_chunk();
7265 if (ssl_sock_crt2der(crt, smp_trash) <= 0)
7266 goto out;
7267
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007268 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007269 smp->data.type = SMP_T_BIN;
Emeric Brun43e79582014-10-29 19:03:26 +01007270 ret = 1;
7271out:
7272 /* SSL_get_peer_certificate, it increase X509 * ref count */
7273 if (cert_peer && crt)
7274 X509_free(crt);
7275 return ret;
7276}
7277
Emeric Brunba841a12014-04-30 17:05:08 +02007278/* binary, returns serial of certificate in a binary chunk.
7279 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7280 * should be use.
7281 */
Willy Tarreau8d598402012-10-22 17:58:39 +02007282static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007283smp_fetch_ssl_x_serial(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau8d598402012-10-22 17:58:39 +02007284{
Emeric Brunba841a12014-04-30 17:05:08 +02007285 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Willy Tarreau8d598402012-10-22 17:58:39 +02007286 X509 *crt = NULL;
7287 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02007288 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007289 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007290 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007291
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007292 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007293 if (!conn || conn->xprt != &ssl_sock)
Willy Tarreau8d598402012-10-22 17:58:39 +02007294 return 0;
7295
Olivier Houchard66ab4982019-02-26 18:37:15 +01007296 ctx = conn->xprt_ctx;
7297
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007298 if (!(conn->flags & CO_FL_CONNECTED)) {
Willy Tarreau8d598402012-10-22 17:58:39 +02007299 smp->flags |= SMP_F_MAY_CHANGE;
7300 return 0;
7301 }
7302
Emeric Brunba841a12014-04-30 17:05:08 +02007303 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007304 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007305 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007306 crt = SSL_get_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007307
Willy Tarreau8d598402012-10-22 17:58:39 +02007308 if (!crt)
7309 goto out;
7310
Willy Tarreau47ca5452012-12-23 20:22:19 +01007311 smp_trash = get_trash_chunk();
Willy Tarreau8d598402012-10-22 17:58:39 +02007312 if (ssl_sock_get_serial(crt, smp_trash) <= 0)
7313 goto out;
7314
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007315 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007316 smp->data.type = SMP_T_BIN;
Willy Tarreau8d598402012-10-22 17:58:39 +02007317 ret = 1;
7318out:
Emeric Brunba841a12014-04-30 17:05:08 +02007319 /* SSL_get_peer_certificate, it increase X509 * ref count */
7320 if (cert_peer && crt)
Willy Tarreau8d598402012-10-22 17:58:39 +02007321 X509_free(crt);
7322 return ret;
7323}
Emeric Brune64aef12012-09-21 13:15:06 +02007324
Emeric Brunba841a12014-04-30 17:05:08 +02007325/* binary, returns the client certificate's SHA-1 fingerprint (SHA-1 hash of DER-encoded certificate) in a binary chunk.
7326 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7327 * should be use.
7328 */
James Votha051b4a2013-05-14 20:37:59 +02007329static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007330smp_fetch_ssl_x_sha1(const struct arg *args, struct sample *smp, const char *kw, void *private)
James Votha051b4a2013-05-14 20:37:59 +02007331{
Emeric Brunba841a12014-04-30 17:05:08 +02007332 int cert_peer = (kw[4] == 'c') ? 1 : 0;
James Votha051b4a2013-05-14 20:37:59 +02007333 X509 *crt = NULL;
7334 const EVP_MD *digest;
7335 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02007336 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007337 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007338 struct ssl_sock_ctx *ctx;
James Votha051b4a2013-05-14 20:37:59 +02007339
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007340 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007341 if (!conn || conn->xprt != &ssl_sock)
7342 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007343 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007344
7345 if (!(conn->flags & CO_FL_CONNECTED)) {
James Votha051b4a2013-05-14 20:37:59 +02007346 smp->flags |= SMP_F_MAY_CHANGE;
7347 return 0;
7348 }
7349
Emeric Brunba841a12014-04-30 17:05:08 +02007350 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007351 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007352 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007353 crt = SSL_get_certificate(ctx->ssl);
James Votha051b4a2013-05-14 20:37:59 +02007354 if (!crt)
7355 goto out;
7356
7357 smp_trash = get_trash_chunk();
7358 digest = EVP_sha1();
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007359 X509_digest(crt, digest, (unsigned char *) smp_trash->area,
7360 (unsigned int *)&smp_trash->data);
James Votha051b4a2013-05-14 20:37:59 +02007361
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007362 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007363 smp->data.type = SMP_T_BIN;
James Votha051b4a2013-05-14 20:37:59 +02007364 ret = 1;
7365out:
Emeric Brunba841a12014-04-30 17:05:08 +02007366 /* SSL_get_peer_certificate, it increase X509 * ref count */
7367 if (cert_peer && crt)
James Votha051b4a2013-05-14 20:37:59 +02007368 X509_free(crt);
7369 return ret;
7370}
7371
Emeric Brunba841a12014-04-30 17:05:08 +02007372/* string, returns certificate's notafter date in ASN1_UTCTIME format.
7373 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7374 * should be use.
7375 */
Emeric Brunce5ad802012-10-22 14:11:22 +02007376static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007377smp_fetch_ssl_x_notafter(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunce5ad802012-10-22 14:11:22 +02007378{
Emeric Brunba841a12014-04-30 17:05:08 +02007379 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brunce5ad802012-10-22 14:11:22 +02007380 X509 *crt = NULL;
7381 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02007382 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007383 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007384 struct ssl_sock_ctx *ctx;
Emeric Brunce5ad802012-10-22 14:11:22 +02007385
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007386 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007387 if (!conn || conn->xprt != &ssl_sock)
7388 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007389 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007390
7391 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02007392 smp->flags |= SMP_F_MAY_CHANGE;
7393 return 0;
7394 }
7395
Emeric Brunba841a12014-04-30 17:05:08 +02007396 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007397 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007398 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007399 crt = SSL_get_certificate(ctx->ssl);
Emeric Brunce5ad802012-10-22 14:11:22 +02007400 if (!crt)
7401 goto out;
7402
Willy Tarreau47ca5452012-12-23 20:22:19 +01007403 smp_trash = get_trash_chunk();
Rosen Penev68185952018-12-14 08:47:02 -08007404 if (ssl_sock_get_time(X509_getm_notAfter(crt), smp_trash) <= 0)
Emeric Brunce5ad802012-10-22 14:11:22 +02007405 goto out;
7406
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007407 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007408 smp->data.type = SMP_T_STR;
Emeric Brunce5ad802012-10-22 14:11:22 +02007409 ret = 1;
7410out:
Emeric Brunba841a12014-04-30 17:05:08 +02007411 /* SSL_get_peer_certificate, it increase X509 * ref count */
7412 if (cert_peer && crt)
Emeric Brunce5ad802012-10-22 14:11:22 +02007413 X509_free(crt);
7414 return ret;
7415}
7416
Emeric Brunba841a12014-04-30 17:05:08 +02007417/* string, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. of certificate's issuer
7418 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7419 * should be use.
7420 */
Emeric Brun87855892012-10-17 17:39:35 +02007421static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007422smp_fetch_ssl_x_i_dn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun87855892012-10-17 17:39:35 +02007423{
Emeric Brunba841a12014-04-30 17:05:08 +02007424 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun87855892012-10-17 17:39:35 +02007425 X509 *crt = NULL;
7426 X509_NAME *name;
7427 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02007428 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007429 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007430 struct ssl_sock_ctx *ctx;
Emeric Brun87855892012-10-17 17:39:35 +02007431
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007432 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007433 if (!conn || conn->xprt != &ssl_sock)
7434 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007435 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007436
7437 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02007438 smp->flags |= SMP_F_MAY_CHANGE;
7439 return 0;
7440 }
7441
Emeric Brunba841a12014-04-30 17:05:08 +02007442 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007443 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007444 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007445 crt = SSL_get_certificate(ctx->ssl);
Emeric Brun87855892012-10-17 17:39:35 +02007446 if (!crt)
7447 goto out;
7448
7449 name = X509_get_issuer_name(crt);
7450 if (!name)
7451 goto out;
7452
Willy Tarreau47ca5452012-12-23 20:22:19 +01007453 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02007454 if (args && args[0].type == ARGT_STR) {
7455 int pos = 1;
7456
7457 if (args[1].type == ARGT_SINT)
7458 pos = args[1].data.sint;
Emeric Brun87855892012-10-17 17:39:35 +02007459
7460 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
7461 goto out;
7462 }
7463 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
7464 goto out;
7465
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007466 smp->data.type = SMP_T_STR;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007467 smp->data.u.str = *smp_trash;
Emeric Brun87855892012-10-17 17:39:35 +02007468 ret = 1;
7469out:
Emeric Brunba841a12014-04-30 17:05:08 +02007470 /* SSL_get_peer_certificate, it increase X509 * ref count */
7471 if (cert_peer && crt)
Emeric Brun87855892012-10-17 17:39:35 +02007472 X509_free(crt);
7473 return ret;
7474}
7475
Emeric Brunba841a12014-04-30 17:05:08 +02007476/* string, returns notbefore date in ASN1_UTCTIME format.
7477 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7478 * should be use.
7479 */
Emeric Brunce5ad802012-10-22 14:11:22 +02007480static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007481smp_fetch_ssl_x_notbefore(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunce5ad802012-10-22 14:11:22 +02007482{
Emeric Brunba841a12014-04-30 17:05:08 +02007483 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brunce5ad802012-10-22 14:11:22 +02007484 X509 *crt = NULL;
7485 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02007486 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007487 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007488 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007489
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007490 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007491 if (!conn || conn->xprt != &ssl_sock)
Emeric Brunce5ad802012-10-22 14:11:22 +02007492 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007493 ctx = conn->xprt_ctx;
Emeric Brunce5ad802012-10-22 14:11:22 +02007494
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007495 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02007496 smp->flags |= SMP_F_MAY_CHANGE;
7497 return 0;
7498 }
7499
Emeric Brunba841a12014-04-30 17:05:08 +02007500 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007501 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007502 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007503 crt = SSL_get_certificate(ctx->ssl);
Emeric Brunce5ad802012-10-22 14:11:22 +02007504 if (!crt)
7505 goto out;
7506
Willy Tarreau47ca5452012-12-23 20:22:19 +01007507 smp_trash = get_trash_chunk();
Rosen Penev68185952018-12-14 08:47:02 -08007508 if (ssl_sock_get_time(X509_getm_notBefore(crt), smp_trash) <= 0)
Emeric Brunce5ad802012-10-22 14:11:22 +02007509 goto out;
7510
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007511 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007512 smp->data.type = SMP_T_STR;
Emeric Brunce5ad802012-10-22 14:11:22 +02007513 ret = 1;
7514out:
Emeric Brunba841a12014-04-30 17:05:08 +02007515 /* SSL_get_peer_certificate, it increase X509 * ref count */
7516 if (cert_peer && crt)
Emeric Brunce5ad802012-10-22 14:11:22 +02007517 X509_free(crt);
7518 return ret;
7519}
7520
Emeric Brunba841a12014-04-30 17:05:08 +02007521/* string, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. of certificate's subject
7522 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7523 * should be use.
7524 */
Emeric Brun87855892012-10-17 17:39:35 +02007525static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007526smp_fetch_ssl_x_s_dn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun87855892012-10-17 17:39:35 +02007527{
Emeric Brunba841a12014-04-30 17:05:08 +02007528 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun87855892012-10-17 17:39:35 +02007529 X509 *crt = NULL;
7530 X509_NAME *name;
7531 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02007532 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007533 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007534 struct ssl_sock_ctx *ctx;
Emeric Brun87855892012-10-17 17:39:35 +02007535
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007536 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007537 if (!conn || conn->xprt != &ssl_sock)
7538 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007539 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007540
7541 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02007542 smp->flags |= SMP_F_MAY_CHANGE;
7543 return 0;
7544 }
7545
Emeric Brunba841a12014-04-30 17:05:08 +02007546 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007547 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007548 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007549 crt = SSL_get_certificate(ctx->ssl);
Emeric Brun87855892012-10-17 17:39:35 +02007550 if (!crt)
7551 goto out;
7552
7553 name = X509_get_subject_name(crt);
7554 if (!name)
7555 goto out;
7556
Willy Tarreau47ca5452012-12-23 20:22:19 +01007557 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02007558 if (args && args[0].type == ARGT_STR) {
7559 int pos = 1;
7560
7561 if (args[1].type == ARGT_SINT)
7562 pos = args[1].data.sint;
Emeric Brun87855892012-10-17 17:39:35 +02007563
7564 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
7565 goto out;
7566 }
7567 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
7568 goto out;
7569
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007570 smp->data.type = SMP_T_STR;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007571 smp->data.u.str = *smp_trash;
Emeric Brun87855892012-10-17 17:39:35 +02007572 ret = 1;
7573out:
Emeric Brunba841a12014-04-30 17:05:08 +02007574 /* SSL_get_peer_certificate, it increase X509 * ref count */
7575 if (cert_peer && crt)
Emeric Brun87855892012-10-17 17:39:35 +02007576 X509_free(crt);
7577 return ret;
7578}
Emeric Brun9143d372012-12-20 15:44:16 +01007579
7580/* integer, returns true if current session use a client certificate */
7581static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007582smp_fetch_ssl_c_used(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun9143d372012-12-20 15:44:16 +01007583{
7584 X509 *crt;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007585 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007586 struct ssl_sock_ctx *ctx;
Emeric Brun9143d372012-12-20 15:44:16 +01007587
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007588 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007589 if (!conn || conn->xprt != &ssl_sock)
7590 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007591 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007592
7593 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun9143d372012-12-20 15:44:16 +01007594 smp->flags |= SMP_F_MAY_CHANGE;
7595 return 0;
7596 }
7597
7598 /* SSL_get_peer_certificate returns a ptr on allocated X509 struct */
Olivier Houchard66ab4982019-02-26 18:37:15 +01007599 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brun9143d372012-12-20 15:44:16 +01007600 if (crt) {
7601 X509_free(crt);
7602 }
7603
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007604 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007605 smp->data.u.sint = (crt != NULL);
Emeric Brun9143d372012-12-20 15:44:16 +01007606 return 1;
7607}
7608
Emeric Brunba841a12014-04-30 17:05:08 +02007609/* integer, returns the certificate version
7610 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7611 * should be use.
7612 */
Emeric Bruna7359fd2012-10-17 15:03:11 +02007613static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007614smp_fetch_ssl_x_version(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Bruna7359fd2012-10-17 15:03:11 +02007615{
Emeric Brunba841a12014-04-30 17:05:08 +02007616 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Bruna7359fd2012-10-17 15:03:11 +02007617 X509 *crt;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007618 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007619 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007620
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007621 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007622 if (!conn || conn->xprt != &ssl_sock)
Emeric Bruna7359fd2012-10-17 15:03:11 +02007623 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007624 ctx = conn->xprt_ctx;
Emeric Bruna7359fd2012-10-17 15:03:11 +02007625
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007626 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Bruna7359fd2012-10-17 15:03:11 +02007627 smp->flags |= SMP_F_MAY_CHANGE;
7628 return 0;
7629 }
7630
Emeric Brunba841a12014-04-30 17:05:08 +02007631 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007632 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007633 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007634 crt = SSL_get_certificate(ctx->ssl);
Emeric Bruna7359fd2012-10-17 15:03:11 +02007635 if (!crt)
7636 return 0;
7637
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007638 smp->data.u.sint = (unsigned int)(1 + X509_get_version(crt));
Emeric Brunba841a12014-04-30 17:05:08 +02007639 /* SSL_get_peer_certificate increase X509 * ref count */
7640 if (cert_peer)
7641 X509_free(crt);
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007642 smp->data.type = SMP_T_SINT;
Emeric Bruna7359fd2012-10-17 15:03:11 +02007643
7644 return 1;
7645}
7646
Emeric Brunba841a12014-04-30 17:05:08 +02007647/* string, returns the certificate's signature algorithm.
7648 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7649 * should be use.
7650 */
Emeric Brun7f56e742012-10-19 18:15:40 +02007651static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007652smp_fetch_ssl_x_sig_alg(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun7f56e742012-10-19 18:15:40 +02007653{
Emeric Brunba841a12014-04-30 17:05:08 +02007654 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun7f56e742012-10-19 18:15:40 +02007655 X509 *crt;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007656 __OPENSSL_110_CONST__ ASN1_OBJECT *algorithm;
Emeric Brun7f56e742012-10-19 18:15:40 +02007657 int nid;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007658 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007659 struct ssl_sock_ctx *ctx;
Emeric Brun7f56e742012-10-19 18:15:40 +02007660
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007661 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007662 if (!conn || conn->xprt != &ssl_sock)
7663 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007664 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007665
7666 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun7f56e742012-10-19 18:15:40 +02007667 smp->flags |= SMP_F_MAY_CHANGE;
7668 return 0;
7669 }
7670
Emeric Brunba841a12014-04-30 17:05:08 +02007671 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007672 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007673 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007674 crt = SSL_get_certificate(ctx->ssl);
Emeric Brun7f56e742012-10-19 18:15:40 +02007675 if (!crt)
7676 return 0;
7677
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007678 X509_ALGOR_get0(&algorithm, NULL, NULL, X509_get0_tbs_sigalg(crt));
7679 nid = OBJ_obj2nid(algorithm);
Emeric Brun7f56e742012-10-19 18:15:40 +02007680
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007681 smp->data.u.str.area = (char *)OBJ_nid2sn(nid);
7682 if (!smp->data.u.str.area) {
Emeric Brunba841a12014-04-30 17:05:08 +02007683 /* SSL_get_peer_certificate increase X509 * ref count */
7684 if (cert_peer)
7685 X509_free(crt);
Emeric Brun7f56e742012-10-19 18:15:40 +02007686 return 0;
Emeric Brun9bf3ba22013-10-07 14:31:44 +02007687 }
Emeric Brun7f56e742012-10-19 18:15:40 +02007688
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007689 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01007690 smp->flags |= SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007691 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brunba841a12014-04-30 17:05:08 +02007692 /* SSL_get_peer_certificate increase X509 * ref count */
7693 if (cert_peer)
7694 X509_free(crt);
Emeric Brun7f56e742012-10-19 18:15:40 +02007695
7696 return 1;
7697}
7698
Emeric Brunba841a12014-04-30 17:05:08 +02007699/* string, returns the certificate's key algorithm.
7700 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7701 * should be use.
7702 */
Emeric Brun521a0112012-10-22 12:22:55 +02007703static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007704smp_fetch_ssl_x_key_alg(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun521a0112012-10-22 12:22:55 +02007705{
Emeric Brunba841a12014-04-30 17:05:08 +02007706 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun521a0112012-10-22 12:22:55 +02007707 X509 *crt;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007708 ASN1_OBJECT *algorithm;
Emeric Brun521a0112012-10-22 12:22:55 +02007709 int nid;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007710 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007711 struct ssl_sock_ctx *ctx;
Emeric Brun521a0112012-10-22 12:22:55 +02007712
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007713 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007714 if (!conn || conn->xprt != &ssl_sock)
7715 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007716 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007717
7718 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun521a0112012-10-22 12:22:55 +02007719 smp->flags |= SMP_F_MAY_CHANGE;
7720 return 0;
7721 }
7722
Emeric Brunba841a12014-04-30 17:05:08 +02007723 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007724 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007725 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007726 crt = SSL_get_certificate(ctx->ssl);
Emeric Brun521a0112012-10-22 12:22:55 +02007727 if (!crt)
7728 return 0;
7729
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007730 X509_PUBKEY_get0_param(&algorithm, NULL, NULL, NULL, X509_get_X509_PUBKEY(crt));
7731 nid = OBJ_obj2nid(algorithm);
Emeric Brun521a0112012-10-22 12:22:55 +02007732
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007733 smp->data.u.str.area = (char *)OBJ_nid2sn(nid);
7734 if (!smp->data.u.str.area) {
Emeric Brunba841a12014-04-30 17:05:08 +02007735 /* SSL_get_peer_certificate increase X509 * ref count */
7736 if (cert_peer)
7737 X509_free(crt);
Emeric Brun521a0112012-10-22 12:22:55 +02007738 return 0;
Emeric Brun9bf3ba22013-10-07 14:31:44 +02007739 }
Emeric Brun521a0112012-10-22 12:22:55 +02007740
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007741 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01007742 smp->flags |= SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007743 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brunba841a12014-04-30 17:05:08 +02007744 if (cert_peer)
7745 X509_free(crt);
Emeric Brun521a0112012-10-22 12:22:55 +02007746
7747 return 1;
7748}
7749
Emeric Brun645ae792014-04-30 14:21:06 +02007750/* boolean, returns true if front conn. transport layer is SSL.
7751 * This function is also usable on backend conn if the fetch keyword 5th
7752 * char is 'b'.
7753 */
Willy Tarreau7875d092012-09-10 08:20:03 +02007754static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007755smp_fetch_ssl_fc(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02007756{
Emeric Bruneb8def92018-02-19 15:59:48 +01007757 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7758 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007759
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007760 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007761 smp->data.u.sint = (conn && conn->xprt == &ssl_sock);
Willy Tarreau7875d092012-09-10 08:20:03 +02007762 return 1;
7763}
7764
Emeric Brun2525b6b2012-10-18 15:59:43 +02007765/* boolean, returns true if client present a SNI */
Willy Tarreau7875d092012-09-10 08:20:03 +02007766static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007767smp_fetch_ssl_fc_has_sni(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02007768{
7769#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007770 struct connection *conn = objt_conn(smp->sess->origin);
Olivier Houchard66ab4982019-02-26 18:37:15 +01007771 struct ssl_sock_ctx *ctx = conn ? conn->xprt_ctx : NULL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007772
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007773 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007774 smp->data.u.sint = (conn && conn->xprt == &ssl_sock) &&
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007775 conn->xprt_ctx &&
Olivier Houchard66ab4982019-02-26 18:37:15 +01007776 SSL_get_servername(ctx->ssl, TLSEXT_NAMETYPE_host_name) != NULL;
Willy Tarreau7875d092012-09-10 08:20:03 +02007777 return 1;
7778#else
7779 return 0;
7780#endif
7781}
7782
Emeric Brun74f7ffa2018-02-19 16:14:12 +01007783/* boolean, returns true if client session has been resumed.
7784 * This function is also usable on backend conn if the fetch keyword 5th
7785 * char is 'b'.
7786 */
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02007787static int
7788smp_fetch_ssl_fc_is_resumed(const struct arg *args, struct sample *smp, const char *kw, void *private)
7789{
Emeric Brun74f7ffa2018-02-19 16:14:12 +01007790 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7791 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007792 struct ssl_sock_ctx *ctx = conn ? conn->xprt_ctx : NULL;
Emeric Brun74f7ffa2018-02-19 16:14:12 +01007793
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02007794
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007795 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007796 smp->data.u.sint = (conn && conn->xprt == &ssl_sock) &&
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02007797 conn->xprt_ctx &&
Olivier Houchard66ab4982019-02-26 18:37:15 +01007798 SSL_session_reused(ctx->ssl);
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02007799 return 1;
7800}
7801
Emeric Brun645ae792014-04-30 14:21:06 +02007802/* string, returns the used cipher if front conn. transport layer is SSL.
7803 * This function is also usable on backend conn if the fetch keyword 5th
7804 * char is 'b'.
7805 */
Emeric Brun589fcad2012-10-16 14:13:26 +02007806static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007807smp_fetch_ssl_fc_cipher(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02007808{
Emeric Bruneb8def92018-02-19 15:59:48 +01007809 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7810 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007811 struct ssl_sock_ctx *ctx;
Emeric Brun589fcad2012-10-16 14:13:26 +02007812
Willy Tarreaube508f12016-03-10 11:47:01 +01007813 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007814 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02007815 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007816 ctx = conn->xprt_ctx;
Emeric Brun589fcad2012-10-16 14:13:26 +02007817
Olivier Houchard66ab4982019-02-26 18:37:15 +01007818 smp->data.u.str.area = (char *)SSL_get_cipher_name(ctx->ssl);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007819 if (!smp->data.u.str.area)
Emeric Brun589fcad2012-10-16 14:13:26 +02007820 return 0;
7821
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007822 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01007823 smp->flags |= SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007824 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brun589fcad2012-10-16 14:13:26 +02007825
7826 return 1;
7827}
7828
Emeric Brun645ae792014-04-30 14:21:06 +02007829/* integer, returns the algoritm's keysize if front conn. transport layer
7830 * is SSL.
7831 * This function is also usable on backend conn if the fetch keyword 5th
7832 * char is 'b'.
7833 */
Emeric Brun589fcad2012-10-16 14:13:26 +02007834static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007835smp_fetch_ssl_fc_alg_keysize(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02007836{
Emeric Bruneb8def92018-02-19 15:59:48 +01007837 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7838 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007839 struct ssl_sock_ctx *ctx;
Willy Tarreaue237fe12016-03-10 17:05:28 +01007840 int sint;
Willy Tarreaube508f12016-03-10 11:47:01 +01007841
Emeric Brun589fcad2012-10-16 14:13:26 +02007842 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007843 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02007844 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007845 ctx = conn->xprt_ctx;
Emeric Brun589fcad2012-10-16 14:13:26 +02007846
Olivier Houchard66ab4982019-02-26 18:37:15 +01007847 if (!SSL_get_cipher_bits(ctx->ssl, &sint))
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007848 return 0;
7849
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007850 smp->data.u.sint = sint;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007851 smp->data.type = SMP_T_SINT;
Emeric Brun589fcad2012-10-16 14:13:26 +02007852
7853 return 1;
7854}
7855
Emeric Brun645ae792014-04-30 14:21:06 +02007856/* integer, returns the used keysize if front conn. transport layer is SSL.
7857 * This function is also usable on backend conn if the fetch keyword 5th
7858 * char is 'b'.
7859 */
Emeric Brun589fcad2012-10-16 14:13:26 +02007860static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007861smp_fetch_ssl_fc_use_keysize(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02007862{
Emeric Bruneb8def92018-02-19 15:59:48 +01007863 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7864 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007865 struct ssl_sock_ctx *ctx;
Willy Tarreaube508f12016-03-10 11:47:01 +01007866
Emeric Brun589fcad2012-10-16 14:13:26 +02007867 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007868 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7869 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007870 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007871
Olivier Houchard66ab4982019-02-26 18:37:15 +01007872 smp->data.u.sint = (unsigned int)SSL_get_cipher_bits(ctx->ssl, NULL);
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007873 if (!smp->data.u.sint)
Emeric Brun589fcad2012-10-16 14:13:26 +02007874 return 0;
7875
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007876 smp->data.type = SMP_T_SINT;
Emeric Brun589fcad2012-10-16 14:13:26 +02007877
7878 return 1;
7879}
7880
Bernard Spil13c53f82018-02-15 13:34:58 +01007881#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Willy Tarreau7875d092012-09-10 08:20:03 +02007882static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007883smp_fetch_ssl_fc_npn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreaua33c6542012-10-15 13:19:06 +02007884{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007885 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007886 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007887
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01007888 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007889 smp->data.type = SMP_T_STR;
Willy Tarreaua33c6542012-10-15 13:19:06 +02007890
Olivier Houchard6b77f492018-11-22 18:18:29 +01007891 conn = (kw[4] != 'b' ) ? objt_conn(smp->sess->origin) :
7892 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007893 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7894 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007895 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007896
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007897 smp->data.u.str.area = NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007898 SSL_get0_next_proto_negotiated(ctx->ssl,
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007899 (const unsigned char **)&smp->data.u.str.area,
7900 (unsigned *)&smp->data.u.str.data);
Willy Tarreaua33c6542012-10-15 13:19:06 +02007901
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007902 if (!smp->data.u.str.area)
Willy Tarreaua33c6542012-10-15 13:19:06 +02007903 return 0;
7904
7905 return 1;
Willy Tarreaua33c6542012-10-15 13:19:06 +02007906}
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02007907#endif
Willy Tarreaua33c6542012-10-15 13:19:06 +02007908
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01007909#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02007910static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007911smp_fetch_ssl_fc_alpn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreauab861d32013-04-02 02:30:41 +02007912{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007913 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007914 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007915
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01007916 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007917 smp->data.type = SMP_T_STR;
Willy Tarreauab861d32013-04-02 02:30:41 +02007918
Olivier Houchard6b77f492018-11-22 18:18:29 +01007919 conn = (kw[4] != 'b' ) ? objt_conn(smp->sess->origin) :
7920 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
7921
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007922 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Willy Tarreauab861d32013-04-02 02:30:41 +02007923 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007924 ctx = conn->xprt_ctx;
Willy Tarreauab861d32013-04-02 02:30:41 +02007925
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007926 smp->data.u.str.area = NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007927 SSL_get0_alpn_selected(ctx->ssl,
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007928 (const unsigned char **)&smp->data.u.str.area,
7929 (unsigned *)&smp->data.u.str.data);
Willy Tarreauab861d32013-04-02 02:30:41 +02007930
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007931 if (!smp->data.u.str.area)
Willy Tarreauab861d32013-04-02 02:30:41 +02007932 return 0;
7933
7934 return 1;
7935}
7936#endif
7937
Emeric Brun645ae792014-04-30 14:21:06 +02007938/* string, returns the used protocol if front conn. transport layer is SSL.
7939 * This function is also usable on backend conn if the fetch keyword 5th
7940 * char is 'b'.
7941 */
Willy Tarreaua33c6542012-10-15 13:19:06 +02007942static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007943smp_fetch_ssl_fc_protocol(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02007944{
Emeric Bruneb8def92018-02-19 15:59:48 +01007945 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7946 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007947 struct ssl_sock_ctx *ctx;
Willy Tarreaube508f12016-03-10 11:47:01 +01007948
Emeric Brun589fcad2012-10-16 14:13:26 +02007949 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007950 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7951 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007952 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007953
Olivier Houchard66ab4982019-02-26 18:37:15 +01007954 smp->data.u.str.area = (char *)SSL_get_version(ctx->ssl);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007955 if (!smp->data.u.str.area)
Emeric Brun589fcad2012-10-16 14:13:26 +02007956 return 0;
7957
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007958 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01007959 smp->flags = SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007960 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brun589fcad2012-10-16 14:13:26 +02007961
7962 return 1;
7963}
7964
Willy Tarreau87b09662015-04-03 00:22:06 +02007965/* binary, returns the SSL stream id if front conn. transport layer is SSL.
Emeric Brun645ae792014-04-30 14:21:06 +02007966 * This function is also usable on backend conn if the fetch keyword 5th
7967 * char is 'b'.
7968 */
Willy Tarreau9a1ab082019-05-09 13:26:41 +02007969#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
Emeric Brun589fcad2012-10-16 14:13:26 +02007970static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007971smp_fetch_ssl_fc_session_id(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunfe68f682012-10-16 14:59:28 +02007972{
Emeric Bruneb8def92018-02-19 15:59:48 +01007973 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7974 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaue237fe12016-03-10 17:05:28 +01007975 SSL_SESSION *ssl_sess;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007976 struct ssl_sock_ctx *ctx;
Willy Tarreaube508f12016-03-10 11:47:01 +01007977
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01007978 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007979 smp->data.type = SMP_T_BIN;
Emeric Brunfe68f682012-10-16 14:59:28 +02007980
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007981 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7982 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007983 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007984
Olivier Houchard66ab4982019-02-26 18:37:15 +01007985 ssl_sess = SSL_get_session(ctx->ssl);
Willy Tarreau192252e2015-04-04 01:47:55 +02007986 if (!ssl_sess)
Emeric Brunfe68f682012-10-16 14:59:28 +02007987 return 0;
7988
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007989 smp->data.u.str.area = (char *)SSL_SESSION_get_id(ssl_sess,
7990 (unsigned int *)&smp->data.u.str.data);
7991 if (!smp->data.u.str.area || !smp->data.u.str.data)
Emeric Brunfe68f682012-10-16 14:59:28 +02007992 return 0;
7993
7994 return 1;
Emeric Brunfe68f682012-10-16 14:59:28 +02007995}
Patrick Hemmer41966772018-04-28 19:15:48 -04007996#endif
7997
Emeric Brunfe68f682012-10-16 14:59:28 +02007998
Emmanuel Hocdet839af572019-05-14 16:27:35 +02007999#if HA_OPENSSL_VERSION_NUMBER >= 0x10100000L
Patrick Hemmere0275472018-04-28 19:15:51 -04008000static int
Patrick Hemmer65674662019-06-04 08:13:03 -04008001smp_fetch_ssl_fc_random(const struct arg *args, struct sample *smp, const char *kw, void *private)
8002{
8003 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
8004 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
8005 struct buffer *data;
8006 struct ssl_sock_ctx *ctx;
8007
8008 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8009 return 0;
8010 ctx = conn->xprt_ctx;
8011
8012 data = get_trash_chunk();
8013 if (kw[7] == 'c')
8014 data->data = SSL_get_client_random(ctx->ssl,
8015 (unsigned char *) data->area,
8016 data->size);
8017 else
8018 data->data = SSL_get_server_random(ctx->ssl,
8019 (unsigned char *) data->area,
8020 data->size);
8021 if (!data->data)
8022 return 0;
8023
8024 smp->flags = 0;
8025 smp->data.type = SMP_T_BIN;
8026 smp->data.u.str = *data;
8027
8028 return 1;
8029}
8030
8031static int
Patrick Hemmere0275472018-04-28 19:15:51 -04008032smp_fetch_ssl_fc_session_key(const struct arg *args, struct sample *smp, const char *kw, void *private)
8033{
8034 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
8035 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
8036 SSL_SESSION *ssl_sess;
Willy Tarreau83061a82018-07-13 11:56:34 +02008037 struct buffer *data;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008038 struct ssl_sock_ctx *ctx;
Patrick Hemmere0275472018-04-28 19:15:51 -04008039
8040 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8041 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008042 ctx = conn->xprt_ctx;
Patrick Hemmere0275472018-04-28 19:15:51 -04008043
Olivier Houchard66ab4982019-02-26 18:37:15 +01008044 ssl_sess = SSL_get_session(ctx->ssl);
Patrick Hemmere0275472018-04-28 19:15:51 -04008045 if (!ssl_sess)
8046 return 0;
8047
8048 data = get_trash_chunk();
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008049 data->data = SSL_SESSION_get_master_key(ssl_sess,
8050 (unsigned char *) data->area,
8051 data->size);
8052 if (!data->data)
Patrick Hemmere0275472018-04-28 19:15:51 -04008053 return 0;
8054
8055 smp->flags = 0;
8056 smp->data.type = SMP_T_BIN;
8057 smp->data.u.str = *data;
8058
8059 return 1;
8060}
8061#endif
8062
Patrick Hemmer41966772018-04-28 19:15:48 -04008063#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emeric Brunfe68f682012-10-16 14:59:28 +02008064static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008065smp_fetch_ssl_fc_sni(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02008066{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008067 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008068 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008069
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008070 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008071 smp->data.type = SMP_T_STR;
Willy Tarreau7875d092012-09-10 08:20:03 +02008072
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02008073 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008074 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8075 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008076 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008077
Olivier Houchard66ab4982019-02-26 18:37:15 +01008078 smp->data.u.str.area = (char *)SSL_get_servername(ctx->ssl, TLSEXT_NAMETYPE_host_name);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008079 if (!smp->data.u.str.area)
Willy Tarreau3e394c92012-09-14 23:56:58 +02008080 return 0;
8081
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008082 smp->data.u.str.data = strlen(smp->data.u.str.area);
Willy Tarreau7875d092012-09-10 08:20:03 +02008083 return 1;
Willy Tarreau7875d092012-09-10 08:20:03 +02008084}
Patrick Hemmer41966772018-04-28 19:15:48 -04008085#endif
Willy Tarreau7875d092012-09-10 08:20:03 +02008086
David Sc1ad52e2014-04-08 18:48:47 -04008087static int
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008088smp_fetch_ssl_fc_cl_bin(const struct arg *args, struct sample *smp, const char *kw, void *private)
8089{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008090 struct connection *conn;
8091 struct ssl_capture *capture;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008092 struct ssl_sock_ctx *ctx;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008093
8094 conn = objt_conn(smp->sess->origin);
8095 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8096 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008097 ctx = conn->xprt_ctx;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008098
Olivier Houchard66ab4982019-02-26 18:37:15 +01008099 capture = SSL_get_ex_data(ctx->ssl, ssl_capture_ptr_index);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008100 if (!capture)
8101 return 0;
8102
8103 smp->flags = SMP_F_CONST;
8104 smp->data.type = SMP_T_BIN;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008105 smp->data.u.str.area = capture->ciphersuite;
8106 smp->data.u.str.data = capture->ciphersuite_len;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008107 return 1;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008108}
8109
8110static int
8111smp_fetch_ssl_fc_cl_hex(const struct arg *args, struct sample *smp, const char *kw, void *private)
8112{
Willy Tarreau83061a82018-07-13 11:56:34 +02008113 struct buffer *data;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008114
8115 if (!smp_fetch_ssl_fc_cl_bin(args, smp, kw, private))
8116 return 0;
8117
8118 data = get_trash_chunk();
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008119 dump_binary(data, smp->data.u.str.area, smp->data.u.str.data);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008120 smp->data.type = SMP_T_BIN;
8121 smp->data.u.str = *data;
8122 return 1;
8123}
8124
8125static int
8126smp_fetch_ssl_fc_cl_xxh64(const struct arg *args, struct sample *smp, const char *kw, void *private)
8127{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008128 struct connection *conn;
8129 struct ssl_capture *capture;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008130 struct ssl_sock_ctx *ctx;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008131
8132 conn = objt_conn(smp->sess->origin);
8133 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8134 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008135 ctx = conn->xprt_ctx;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008136
Olivier Houchard66ab4982019-02-26 18:37:15 +01008137 capture = SSL_get_ex_data(ctx->ssl, ssl_capture_ptr_index);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008138 if (!capture)
8139 return 0;
8140
8141 smp->data.type = SMP_T_SINT;
8142 smp->data.u.sint = capture->xxh64;
8143 return 1;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008144}
8145
8146static int
8147smp_fetch_ssl_fc_cl_str(const struct arg *args, struct sample *smp, const char *kw, void *private)
8148{
Willy Tarreau5db847a2019-05-09 14:13:35 +02008149#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL)
Willy Tarreau83061a82018-07-13 11:56:34 +02008150 struct buffer *data;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008151 int i;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008152
8153 if (!smp_fetch_ssl_fc_cl_bin(args, smp, kw, private))
8154 return 0;
8155
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008156 data = get_trash_chunk();
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008157 for (i = 0; i + 1 < smp->data.u.str.data; i += 2) {
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02008158 const char *str;
8159 const SSL_CIPHER *cipher;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008160 const unsigned char *bin = (const unsigned char *) smp->data.u.str.area + i;
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02008161 uint16_t id = (bin[0] << 8) | bin[1];
8162#if defined(OPENSSL_IS_BORINGSSL)
8163 cipher = SSL_get_cipher_by_value(id);
8164#else
Willy Tarreaub7290772018-10-15 11:01:59 +02008165 struct connection *conn = __objt_conn(smp->sess->origin);
Olivier Houchard66ab4982019-02-26 18:37:15 +01008166 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
8167 cipher = SSL_CIPHER_find(ctx->ssl, bin);
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02008168#endif
8169 str = SSL_CIPHER_get_name(cipher);
8170 if (!str || strcmp(str, "(NONE)") == 0)
8171 chunk_appendf(data, "%sUNKNOWN(%04x)", i == 0 ? "" : ",", id);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008172 else
8173 chunk_appendf(data, "%s%s", i == 0 ? "" : ",", str);
8174 }
8175 smp->data.type = SMP_T_STR;
8176 smp->data.u.str = *data;
8177 return 1;
8178#else
8179 return smp_fetch_ssl_fc_cl_xxh64(args, smp, kw, private);
8180#endif
8181}
8182
Willy Tarreau9a1ab082019-05-09 13:26:41 +02008183#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008184static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008185smp_fetch_ssl_fc_unique_id(const struct arg *args, struct sample *smp, const char *kw, void *private)
David Sc1ad52e2014-04-08 18:48:47 -04008186{
Emeric Bruneb8def92018-02-19 15:59:48 +01008187 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
8188 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
David Sc1ad52e2014-04-08 18:48:47 -04008189 int finished_len;
Willy Tarreau83061a82018-07-13 11:56:34 +02008190 struct buffer *finished_trash;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008191 struct ssl_sock_ctx *ctx;
David Sc1ad52e2014-04-08 18:48:47 -04008192
8193 smp->flags = 0;
David Sc1ad52e2014-04-08 18:48:47 -04008194 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8195 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008196 ctx = conn->xprt_ctx;
David Sc1ad52e2014-04-08 18:48:47 -04008197
8198 if (!(conn->flags & CO_FL_CONNECTED)) {
8199 smp->flags |= SMP_F_MAY_CHANGE;
8200 return 0;
8201 }
8202
8203 finished_trash = get_trash_chunk();
Olivier Houchard66ab4982019-02-26 18:37:15 +01008204 if (!SSL_session_reused(ctx->ssl))
8205 finished_len = SSL_get_peer_finished(ctx->ssl,
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008206 finished_trash->area,
8207 finished_trash->size);
David Sc1ad52e2014-04-08 18:48:47 -04008208 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01008209 finished_len = SSL_get_finished(ctx->ssl,
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008210 finished_trash->area,
8211 finished_trash->size);
David Sc1ad52e2014-04-08 18:48:47 -04008212
8213 if (!finished_len)
8214 return 0;
8215
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008216 finished_trash->data = finished_len;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02008217 smp->data.u.str = *finished_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008218 smp->data.type = SMP_T_BIN;
David Sc1ad52e2014-04-08 18:48:47 -04008219
8220 return 1;
David Sc1ad52e2014-04-08 18:48:47 -04008221}
Patrick Hemmer41966772018-04-28 19:15:48 -04008222#endif
David Sc1ad52e2014-04-08 18:48:47 -04008223
Emeric Brun2525b6b2012-10-18 15:59:43 +02008224/* integer, returns the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02008225static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008226smp_fetch_ssl_c_ca_err(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunf282a812012-09-21 15:27:54 +02008227{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008228 struct connection *conn;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008229 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008230
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02008231 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008232 if (!conn || conn->xprt != &ssl_sock)
8233 return 0;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008234 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008235
8236 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02008237 smp->flags = SMP_F_MAY_CHANGE;
8238 return 0;
8239 }
8240
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008241 smp->data.type = SMP_T_SINT;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008242 smp->data.u.sint = (unsigned long long int)SSL_SOCK_ST_TO_CA_ERROR(ctx->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02008243 smp->flags = 0;
8244
8245 return 1;
8246}
8247
Emeric Brun2525b6b2012-10-18 15:59:43 +02008248/* integer, returns the depth of the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02008249static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008250smp_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 +02008251{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008252 struct connection *conn;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008253 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008254
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02008255 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008256 if (!conn || conn->xprt != &ssl_sock)
Emeric Brunf282a812012-09-21 15:27:54 +02008257 return 0;
8258
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008259 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02008260 smp->flags = SMP_F_MAY_CHANGE;
8261 return 0;
8262 }
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008263 ctx = conn->xprt_ctx;
Emeric Brunf282a812012-09-21 15:27:54 +02008264
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008265 smp->data.type = SMP_T_SINT;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008266 smp->data.u.sint = (long long int)SSL_SOCK_ST_TO_CAEDEPTH(ctx->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02008267 smp->flags = 0;
8268
8269 return 1;
8270}
8271
Emeric Brun2525b6b2012-10-18 15:59:43 +02008272/* integer, returns the first verify error on client certificate */
Emeric Brunf282a812012-09-21 15:27:54 +02008273static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008274smp_fetch_ssl_c_err(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunf282a812012-09-21 15:27:54 +02008275{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008276 struct connection *conn;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008277 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008278
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02008279 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008280 if (!conn || conn->xprt != &ssl_sock)
8281 return 0;
8282
8283 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02008284 smp->flags = SMP_F_MAY_CHANGE;
8285 return 0;
8286 }
8287
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008288 ctx = conn->xprt_ctx;
8289
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008290 smp->data.type = SMP_T_SINT;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008291 smp->data.u.sint = (long long int)SSL_SOCK_ST_TO_CRTERROR(ctx->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02008292 smp->flags = 0;
8293
8294 return 1;
8295}
8296
Emeric Brun2525b6b2012-10-18 15:59:43 +02008297/* integer, returns the verify result on client cert */
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02008298static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008299smp_fetch_ssl_c_verify(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02008300{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008301 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008302 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008303
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02008304 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008305 if (!conn || conn->xprt != &ssl_sock)
8306 return 0;
8307
8308 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02008309 smp->flags = SMP_F_MAY_CHANGE;
8310 return 0;
8311 }
8312
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008313 if (!conn->xprt_ctx)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02008314 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008315 ctx = conn->xprt_ctx;
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02008316
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008317 smp->data.type = SMP_T_SINT;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008318 smp->data.u.sint = (long long int)SSL_get_verify_result(ctx->ssl);
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02008319 smp->flags = 0;
8320
8321 return 1;
8322}
8323
Emeric Brunfb510ea2012-10-05 12:00:26 +02008324/* parse the "ca-file" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008325static 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 +02008326{
8327 if (!*args[cur_arg + 1]) {
8328 if (err)
8329 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
8330 return ERR_ALERT | ERR_FATAL;
8331 }
8332
Willy Tarreauef934602016-12-22 23:12:01 +01008333 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
8334 memprintf(&conf->ca_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02008335 else
8336 memprintf(&conf->ca_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02008337
Emeric Brund94b3fe2012-09-20 18:23:56 +02008338 return 0;
8339}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008340static int bind_parse_ca_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8341{
8342 return ssl_bind_parse_ca_file(args, cur_arg, px, &conf->ssl_conf, err);
8343}
Emeric Brund94b3fe2012-09-20 18:23:56 +02008344
Christopher Faulet31af49d2015-06-09 17:29:50 +02008345/* parse the "ca-sign-file" bind keyword */
8346static int bind_parse_ca_sign_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8347{
8348 if (!*args[cur_arg + 1]) {
8349 if (err)
8350 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
8351 return ERR_ALERT | ERR_FATAL;
8352 }
8353
Willy Tarreauef934602016-12-22 23:12:01 +01008354 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
8355 memprintf(&conf->ca_sign_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Christopher Faulet31af49d2015-06-09 17:29:50 +02008356 else
8357 memprintf(&conf->ca_sign_file, "%s", args[cur_arg + 1]);
8358
8359 return 0;
8360}
8361
Bertrand Jacquinff13c062016-11-13 16:37:11 +00008362/* parse the "ca-sign-pass" bind keyword */
Christopher Faulet31af49d2015-06-09 17:29:50 +02008363static int bind_parse_ca_sign_pass(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8364{
8365 if (!*args[cur_arg + 1]) {
8366 if (err)
8367 memprintf(err, "'%s' : missing CAkey password", args[cur_arg]);
8368 return ERR_ALERT | ERR_FATAL;
8369 }
8370 memprintf(&conf->ca_sign_pass, "%s", args[cur_arg + 1]);
8371 return 0;
8372}
8373
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008374/* parse the "ciphers" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008375static 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 +02008376{
8377 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02008378 memprintf(err, "'%s' : missing cipher suite", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008379 return ERR_ALERT | ERR_FATAL;
8380 }
8381
Emeric Brun76d88952012-10-05 15:47:31 +02008382 free(conf->ciphers);
Willy Tarreau4348fad2012-09-20 16:48:07 +02008383 conf->ciphers = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008384 return 0;
8385}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008386static int bind_parse_ciphers(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8387{
8388 return ssl_bind_parse_ciphers(args, cur_arg, px, &conf->ssl_conf, err);
8389}
Dirkjan Bussink415150f2018-09-14 11:14:21 +02008390
Emmanuel Hocdet839af572019-05-14 16:27:35 +02008391#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02008392/* parse the "ciphersuites" bind keyword */
8393static int ssl_bind_parse_ciphersuites(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
8394{
8395 if (!*args[cur_arg + 1]) {
8396 memprintf(err, "'%s' : missing cipher suite", args[cur_arg]);
8397 return ERR_ALERT | ERR_FATAL;
8398 }
8399
8400 free(conf->ciphersuites);
8401 conf->ciphersuites = strdup(args[cur_arg + 1]);
8402 return 0;
8403}
8404static int bind_parse_ciphersuites(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8405{
8406 return ssl_bind_parse_ciphersuites(args, cur_arg, px, &conf->ssl_conf, err);
8407}
8408#endif
8409
Willy Tarreaubbc91962019-10-16 16:42:19 +02008410/* parse the "crt" bind keyword. Returns a set of ERR_* flags possibly with an error in <err>. */
Willy Tarreau4348fad2012-09-20 16:48:07 +02008411static 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 +02008412{
Willy Tarreau38011032013-08-13 16:59:39 +02008413 char path[MAXPATHLEN];
Willy Tarreaub75d6922014-04-14 18:05:41 +02008414
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008415 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02008416 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008417 return ERR_ALERT | ERR_FATAL;
8418 }
8419
Willy Tarreauef934602016-12-22 23:12:01 +01008420 if ((*args[cur_arg + 1] != '/' ) && global_ssl.crt_base) {
8421 if ((strlen(global_ssl.crt_base) + 1 + strlen(args[cur_arg + 1]) + 1) > MAXPATHLEN) {
Emeric Brunc8e8d122012-10-02 18:42:10 +02008422 memprintf(err, "'%s' : path too long", args[cur_arg]);
8423 return ERR_ALERT | ERR_FATAL;
8424 }
Willy Tarreauef934602016-12-22 23:12:01 +01008425 snprintf(path, sizeof(path), "%s/%s", global_ssl.crt_base, args[cur_arg + 1]);
Willy Tarreaubbc91962019-10-16 16:42:19 +02008426 return ssl_sock_load_cert(path, conf, err);
Emeric Brunc8e8d122012-10-02 18:42:10 +02008427 }
8428
Willy Tarreaubbc91962019-10-16 16:42:19 +02008429 return ssl_sock_load_cert(args[cur_arg + 1], conf, err);
Emeric Brund94b3fe2012-09-20 18:23:56 +02008430}
8431
Willy Tarreaubbc91962019-10-16 16:42:19 +02008432/* 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 +01008433static int bind_parse_crt_list(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8434{
Willy Tarreaubbc91962019-10-16 16:42:19 +02008435 int err_code;
8436
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01008437 if (!*args[cur_arg + 1]) {
8438 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
8439 return ERR_ALERT | ERR_FATAL;
8440 }
8441
Willy Tarreaubbc91962019-10-16 16:42:19 +02008442 err_code = ssl_sock_load_cert_list_file(args[cur_arg + 1], conf, px, err);
8443 if (err_code)
Willy Tarreauad1731d2013-04-02 17:35:58 +02008444 memprintf(err, "'%s' : %s", args[cur_arg], *err);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01008445
Willy Tarreaubbc91962019-10-16 16:42:19 +02008446 return err_code;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01008447}
8448
Emeric Brunfb510ea2012-10-05 12:00:26 +02008449/* parse the "crl-file" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008450static 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 +02008451{
Emeric Brun051cdab2012-10-02 19:25:50 +02008452#ifndef X509_V_FLAG_CRL_CHECK
8453 if (err)
8454 memprintf(err, "'%s' : library does not support CRL verify", args[cur_arg]);
8455 return ERR_ALERT | ERR_FATAL;
8456#else
Emeric Brund94b3fe2012-09-20 18:23:56 +02008457 if (!*args[cur_arg + 1]) {
8458 if (err)
8459 memprintf(err, "'%s' : missing CRLfile path", args[cur_arg]);
8460 return ERR_ALERT | ERR_FATAL;
8461 }
Emeric Brun2b58d042012-09-20 17:10:03 +02008462
Willy Tarreauef934602016-12-22 23:12:01 +01008463 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
8464 memprintf(&conf->crl_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02008465 else
8466 memprintf(&conf->crl_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02008467
Emeric Brun2b58d042012-09-20 17:10:03 +02008468 return 0;
Emeric Brun051cdab2012-10-02 19:25:50 +02008469#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02008470}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008471static int bind_parse_crl_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8472{
8473 return ssl_bind_parse_crl_file(args, cur_arg, px, &conf->ssl_conf, err);
8474}
Emeric Brun2b58d042012-09-20 17:10:03 +02008475
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01008476/* parse the "curves" bind keyword keyword */
8477static int ssl_bind_parse_curves(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
8478{
Lukas Tribusd14b49c2019-11-24 18:20:40 +01008479#if ((HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL) || defined(LIBRESSL_VERSION_NUMBER))
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01008480 if (!*args[cur_arg + 1]) {
8481 if (err)
8482 memprintf(err, "'%s' : missing curve suite", args[cur_arg]);
8483 return ERR_ALERT | ERR_FATAL;
8484 }
8485 conf->curves = strdup(args[cur_arg + 1]);
8486 return 0;
8487#else
8488 if (err)
8489 memprintf(err, "'%s' : library does not support curve suite", args[cur_arg]);
8490 return ERR_ALERT | ERR_FATAL;
8491#endif
8492}
8493static int bind_parse_curves(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8494{
8495 return ssl_bind_parse_curves(args, cur_arg, px, &conf->ssl_conf, err);
8496}
8497
Bertrand Jacquinff13c062016-11-13 16:37:11 +00008498/* parse the "ecdhe" bind keyword keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008499static 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 +02008500{
Willy Tarreau9a1ab082019-05-09 13:26:41 +02008501#if HA_OPENSSL_VERSION_NUMBER < 0x0090800fL
Emeric Brun2b58d042012-09-20 17:10:03 +02008502 if (err)
8503 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (too old)", args[cur_arg]);
8504 return ERR_ALERT | ERR_FATAL;
8505#elif defined(OPENSSL_NO_ECDH)
8506 if (err)
8507 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (disabled via OPENSSL_NO_ECDH)", args[cur_arg]);
8508 return ERR_ALERT | ERR_FATAL;
8509#else
8510 if (!*args[cur_arg + 1]) {
8511 if (err)
8512 memprintf(err, "'%s' : missing named curve", args[cur_arg]);
8513 return ERR_ALERT | ERR_FATAL;
8514 }
8515
8516 conf->ecdhe = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008517
8518 return 0;
Emeric Brun2b58d042012-09-20 17:10:03 +02008519#endif
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008520}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008521static int bind_parse_ecdhe(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8522{
8523 return ssl_bind_parse_ecdhe(args, cur_arg, px, &conf->ssl_conf, err);
8524}
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008525
Bertrand Jacquinff13c062016-11-13 16:37:11 +00008526/* parse the "crt-ignore-err" and "ca-ignore-err" bind keywords */
Emeric Brun81c00f02012-09-21 14:31:21 +02008527static int bind_parse_ignore_err(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8528{
8529 int code;
8530 char *p = args[cur_arg + 1];
8531 unsigned long long *ignerr = &conf->crt_ignerr;
8532
8533 if (!*p) {
8534 if (err)
8535 memprintf(err, "'%s' : missing error IDs list", args[cur_arg]);
8536 return ERR_ALERT | ERR_FATAL;
8537 }
8538
8539 if (strcmp(args[cur_arg], "ca-ignore-err") == 0)
8540 ignerr = &conf->ca_ignerr;
8541
8542 if (strcmp(p, "all") == 0) {
8543 *ignerr = ~0ULL;
8544 return 0;
8545 }
8546
8547 while (p) {
8548 code = atoi(p);
8549 if ((code <= 0) || (code > 63)) {
8550 if (err)
8551 memprintf(err, "'%s' : ID '%d' out of range (1..63) in error IDs list '%s'",
8552 args[cur_arg], code, args[cur_arg + 1]);
8553 return ERR_ALERT | ERR_FATAL;
8554 }
8555 *ignerr |= 1ULL << code;
8556 p = strchr(p, ',');
8557 if (p)
8558 p++;
8559 }
8560
Emeric Brun2cb7ae52012-10-05 14:14:21 +02008561 return 0;
8562}
8563
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008564/* parse tls_method_options "no-xxx" and "force-xxx" */
8565static int parse_tls_method_options(char *arg, struct tls_version_filter *methods, char **err)
Emeric Brun2cb7ae52012-10-05 14:14:21 +02008566{
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008567 uint16_t v;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008568 char *p;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008569 p = strchr(arg, '-');
8570 if (!p)
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008571 goto fail;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008572 p++;
8573 if (!strcmp(p, "sslv3"))
8574 v = CONF_SSLV3;
8575 else if (!strcmp(p, "tlsv10"))
8576 v = CONF_TLSV10;
8577 else if (!strcmp(p, "tlsv11"))
8578 v = CONF_TLSV11;
8579 else if (!strcmp(p, "tlsv12"))
8580 v = CONF_TLSV12;
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +02008581 else if (!strcmp(p, "tlsv13"))
8582 v = CONF_TLSV13;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008583 else
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008584 goto fail;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008585 if (!strncmp(arg, "no-", 3))
8586 methods->flags |= methodVersions[v].flag;
8587 else if (!strncmp(arg, "force-", 6))
8588 methods->min = methods->max = v;
8589 else
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008590 goto fail;
Emeric Brun2d0c4822012-10-02 13:45:20 +02008591 return 0;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008592 fail:
8593 if (err)
8594 memprintf(err, "'%s' : option not implemented", arg);
8595 return ERR_ALERT | ERR_FATAL;
Emeric Brun2d0c4822012-10-02 13:45:20 +02008596}
8597
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008598static 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 +02008599{
Emmanuel Hocdet43664762017-08-09 18:26:20 +02008600 return parse_tls_method_options(args[cur_arg], &conf->ssl_conf.ssl_methods, err);
Emeric Brun2cb7ae52012-10-05 14:14:21 +02008601}
8602
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008603static 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 +02008604{
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008605 return parse_tls_method_options(args[*cur_arg], &newsrv->ssl_ctx.methods, err);
8606}
8607
8608/* parse tls_method min/max: "ssl-min-ver" and "ssl-max-ver" */
8609static int parse_tls_method_minmax(char **args, int cur_arg, struct tls_version_filter *methods, char **err)
8610{
8611 uint16_t i, v = 0;
8612 char *argv = args[cur_arg + 1];
8613 if (!*argv) {
8614 if (err)
8615 memprintf(err, "'%s' : missing the ssl/tls version", args[cur_arg]);
8616 return ERR_ALERT | ERR_FATAL;
8617 }
8618 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
8619 if (!strcmp(argv, methodVersions[i].name))
8620 v = i;
8621 if (!v) {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008622 if (err)
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008623 memprintf(err, "'%s' : unknown ssl/tls version", args[cur_arg + 1]);
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008624 return ERR_ALERT | ERR_FATAL;
8625 }
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008626 if (!strcmp("ssl-min-ver", args[cur_arg]))
8627 methods->min = v;
8628 else if (!strcmp("ssl-max-ver", args[cur_arg]))
8629 methods->max = v;
8630 else {
8631 if (err)
8632 memprintf(err, "'%s' : option not implemented", args[cur_arg]);
8633 return ERR_ALERT | ERR_FATAL;
8634 }
Emeric Brun2cb7ae52012-10-05 14:14:21 +02008635 return 0;
Emeric Brun2cb7ae52012-10-05 14:14:21 +02008636}
Emeric Brun2cb7ae52012-10-05 14:14:21 +02008637
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02008638static int ssl_bind_parse_tls_method_minmax(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
8639{
Willy Tarreau9a1ab082019-05-09 13:26:41 +02008640#if (HA_OPENSSL_VERSION_NUMBER < 0x10101000L) && !defined(OPENSSL_IS_BORINGSSL)
Christopher Faulet767a84b2017-11-24 16:50:31 +01008641 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 +02008642#endif
8643 return parse_tls_method_minmax(args, cur_arg, &conf->ssl_methods, err);
8644}
8645
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008646static int bind_parse_tls_method_minmax(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8647{
Emmanuel Hocdet43664762017-08-09 18:26:20 +02008648 return parse_tls_method_minmax(args, cur_arg, &conf->ssl_conf.ssl_methods, err);
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008649}
8650
8651static int srv_parse_tls_method_minmax(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8652{
8653 return parse_tls_method_minmax(args, *cur_arg, &newsrv->ssl_ctx.methods, err);
8654}
8655
Emeric Brun2d0c4822012-10-02 13:45:20 +02008656/* parse the "no-tls-tickets" bind keyword */
Emmanuel Hocdet4608ed92017-01-20 13:06:27 +01008657static 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 +02008658{
Emeric Brun89675492012-10-05 13:48:26 +02008659 conf->ssl_options |= BC_SSL_O_NO_TLS_TICKETS;
Emeric Brun81c00f02012-09-21 14:31:21 +02008660 return 0;
8661}
Emeric Brun2d0c4822012-10-02 13:45:20 +02008662
Olivier Houchardc2aae742017-09-22 18:26:28 +02008663/* parse the "allow-0rtt" bind keyword */
8664static int ssl_bind_parse_allow_0rtt(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
8665{
8666 conf->early_data = 1;
8667 return 0;
8668}
8669
8670static int bind_parse_allow_0rtt(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8671{
Olivier Houchard9679ac92017-10-27 14:58:08 +02008672 conf->ssl_conf.early_data = 1;
Olivier Houchardc2aae742017-09-22 18:26:28 +02008673 return 0;
8674}
8675
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02008676/* parse the "npn" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008677static 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 +02008678{
Bernard Spil13c53f82018-02-15 13:34:58 +01008679#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02008680 char *p1, *p2;
8681
8682 if (!*args[cur_arg + 1]) {
8683 memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[cur_arg]);
8684 return ERR_ALERT | ERR_FATAL;
8685 }
8686
8687 free(conf->npn_str);
8688
Willy Tarreau3724da12016-02-12 17:11:12 +01008689 /* the NPN string is built as a suite of (<len> <name>)*,
8690 * so we reuse each comma to store the next <len> and need
8691 * one more for the end of the string.
8692 */
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02008693 conf->npn_len = strlen(args[cur_arg + 1]) + 1;
Willy Tarreau3724da12016-02-12 17:11:12 +01008694 conf->npn_str = calloc(1, conf->npn_len + 1);
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02008695 memcpy(conf->npn_str + 1, args[cur_arg + 1], conf->npn_len);
8696
8697 /* replace commas with the name length */
8698 p1 = conf->npn_str;
8699 p2 = p1 + 1;
8700 while (1) {
8701 p2 = memchr(p1 + 1, ',', conf->npn_str + conf->npn_len - (p1 + 1));
8702 if (!p2)
8703 p2 = p1 + 1 + strlen(p1 + 1);
8704
8705 if (p2 - (p1 + 1) > 255) {
8706 *p2 = '\0';
8707 memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
8708 return ERR_ALERT | ERR_FATAL;
8709 }
8710
8711 *p1 = p2 - (p1 + 1);
8712 p1 = p2;
8713
8714 if (!*p2)
8715 break;
8716
8717 *(p2++) = '\0';
8718 }
8719 return 0;
8720#else
8721 if (err)
8722 memprintf(err, "'%s' : library does not support TLS NPN extension", args[cur_arg]);
8723 return ERR_ALERT | ERR_FATAL;
8724#endif
8725}
8726
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008727static int bind_parse_npn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8728{
8729 return ssl_bind_parse_npn(args, cur_arg, px, &conf->ssl_conf, err);
8730}
8731
Willy Tarreauab861d32013-04-02 02:30:41 +02008732/* parse the "alpn" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008733static 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 +02008734{
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01008735#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02008736 char *p1, *p2;
8737
8738 if (!*args[cur_arg + 1]) {
8739 memprintf(err, "'%s' : missing the comma-delimited ALPN protocol suite", args[cur_arg]);
8740 return ERR_ALERT | ERR_FATAL;
8741 }
8742
8743 free(conf->alpn_str);
8744
Marcoen Hirschbergbef60912016-02-12 17:05:24 +01008745 /* the ALPN string is built as a suite of (<len> <name>)*,
8746 * so we reuse each comma to store the next <len> and need
8747 * one more for the end of the string.
8748 */
Willy Tarreauab861d32013-04-02 02:30:41 +02008749 conf->alpn_len = strlen(args[cur_arg + 1]) + 1;
Marcoen Hirschbergbef60912016-02-12 17:05:24 +01008750 conf->alpn_str = calloc(1, conf->alpn_len + 1);
Willy Tarreauab861d32013-04-02 02:30:41 +02008751 memcpy(conf->alpn_str + 1, args[cur_arg + 1], conf->alpn_len);
8752
8753 /* replace commas with the name length */
8754 p1 = conf->alpn_str;
8755 p2 = p1 + 1;
8756 while (1) {
8757 p2 = memchr(p1 + 1, ',', conf->alpn_str + conf->alpn_len - (p1 + 1));
8758 if (!p2)
8759 p2 = p1 + 1 + strlen(p1 + 1);
8760
8761 if (p2 - (p1 + 1) > 255) {
8762 *p2 = '\0';
8763 memprintf(err, "'%s' : ALPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
8764 return ERR_ALERT | ERR_FATAL;
8765 }
8766
8767 *p1 = p2 - (p1 + 1);
8768 p1 = p2;
8769
8770 if (!*p2)
8771 break;
8772
8773 *(p2++) = '\0';
8774 }
8775 return 0;
8776#else
8777 if (err)
8778 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[cur_arg]);
8779 return ERR_ALERT | ERR_FATAL;
8780#endif
8781}
8782
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008783static int bind_parse_alpn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8784{
8785 return ssl_bind_parse_alpn(args, cur_arg, px, &conf->ssl_conf, err);
8786}
8787
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008788/* parse the "ssl" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02008789static 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 +02008790{
Willy Tarreau71a8c7c2016-12-21 22:04:54 +01008791 conf->xprt = &ssl_sock;
Willy Tarreau4348fad2012-09-20 16:48:07 +02008792 conf->is_ssl = 1;
Emeric Brun76d88952012-10-05 15:47:31 +02008793
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008794 if (global_ssl.listen_default_ciphers && !conf->ssl_conf.ciphers)
8795 conf->ssl_conf.ciphers = strdup(global_ssl.listen_default_ciphers);
Emmanuel Hocdet839af572019-05-14 16:27:35 +02008796#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02008797 if (global_ssl.listen_default_ciphersuites && !conf->ssl_conf.ciphersuites)
8798 conf->ssl_conf.ciphersuites = strdup(global_ssl.listen_default_ciphersuites);
8799#endif
Emmanuel Hocdet4608ed92017-01-20 13:06:27 +01008800 conf->ssl_options |= global_ssl.listen_default_ssloptions;
Emmanuel Hocdet43664762017-08-09 18:26:20 +02008801 conf->ssl_conf.ssl_methods.flags |= global_ssl.listen_default_sslmethods.flags;
8802 if (!conf->ssl_conf.ssl_methods.min)
8803 conf->ssl_conf.ssl_methods.min = global_ssl.listen_default_sslmethods.min;
8804 if (!conf->ssl_conf.ssl_methods.max)
8805 conf->ssl_conf.ssl_methods.max = global_ssl.listen_default_sslmethods.max;
Emeric Brun76d88952012-10-05 15:47:31 +02008806
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008807 return 0;
8808}
8809
Lukas Tribus53ae85c2017-05-04 15:45:40 +00008810/* parse the "prefer-client-ciphers" bind keyword */
8811static int bind_parse_pcc(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8812{
8813 conf->ssl_options |= BC_SSL_O_PREF_CLIE_CIPH;
8814 return 0;
8815}
8816
Christopher Faulet31af49d2015-06-09 17:29:50 +02008817/* parse the "generate-certificates" bind keyword */
8818static int bind_parse_generate_certs(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8819{
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01008820#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Christopher Faulet31af49d2015-06-09 17:29:50 +02008821 conf->generate_certs = 1;
8822#else
8823 memprintf(err, "%sthis version of openssl cannot generate SSL certificates.\n",
8824 err && *err ? *err : "");
8825#endif
8826 return 0;
8827}
8828
Emmanuel Hocdet65623372013-01-24 17:17:15 +01008829/* parse the "strict-sni" bind keyword */
8830static int bind_parse_strict_sni(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8831{
8832 conf->strict_sni = 1;
8833 return 0;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008834}
8835
8836/* parse the "tls-ticket-keys" bind keyword */
8837static int bind_parse_tls_ticket_keys(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8838{
8839#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
Christopher Faulete566f3d2019-10-21 09:55:49 +02008840 FILE *f = NULL;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008841 int i = 0;
8842 char thisline[LINESIZE];
Christopher Faulete566f3d2019-10-21 09:55:49 +02008843 struct tls_keys_ref *keys_ref = NULL;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008844
8845 if (!*args[cur_arg + 1]) {
8846 if (err)
8847 memprintf(err, "'%s' : missing TLS ticket keys file path", args[cur_arg]);
Christopher Faulete566f3d2019-10-21 09:55:49 +02008848 goto fail;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008849 }
8850
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02008851 keys_ref = tlskeys_ref_lookup(args[cur_arg + 1]);
Willy Tarreau17b4aa12018-07-17 10:05:32 +02008852 if (keys_ref) {
8853 keys_ref->refcount++;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02008854 conf->keys_ref = keys_ref;
8855 return 0;
8856 }
8857
Christopher Faulete566f3d2019-10-21 09:55:49 +02008858 keys_ref = calloc(1, sizeof(*keys_ref));
Emeric Brun09852f72019-01-10 10:51:13 +01008859 if (!keys_ref) {
8860 if (err)
8861 memprintf(err, "'%s' : allocation error", args[cur_arg+1]);
Christopher Faulete566f3d2019-10-21 09:55:49 +02008862 goto fail;
Emeric Brun09852f72019-01-10 10:51:13 +01008863 }
8864
Emeric Brun9e754772019-01-10 17:51:55 +01008865 keys_ref->tlskeys = malloc(TLS_TICKETS_NO * sizeof(union tls_sess_key));
Emeric Brun09852f72019-01-10 10:51:13 +01008866 if (!keys_ref->tlskeys) {
Emeric Brun09852f72019-01-10 10:51:13 +01008867 if (err)
8868 memprintf(err, "'%s' : allocation error", args[cur_arg+1]);
Christopher Faulete566f3d2019-10-21 09:55:49 +02008869 goto fail;
Emeric Brun09852f72019-01-10 10:51:13 +01008870 }
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008871
8872 if ((f = fopen(args[cur_arg + 1], "r")) == NULL) {
8873 if (err)
8874 memprintf(err, "'%s' : unable to load ssl tickets keys file", args[cur_arg+1]);
Christopher Faulete566f3d2019-10-21 09:55:49 +02008875 goto fail;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008876 }
8877
Nenad Merdanovic146defa2015-05-09 08:46:00 +02008878 keys_ref->filename = strdup(args[cur_arg + 1]);
Emeric Brun09852f72019-01-10 10:51:13 +01008879 if (!keys_ref->filename) {
Emeric Brun09852f72019-01-10 10:51:13 +01008880 if (err)
8881 memprintf(err, "'%s' : allocation error", args[cur_arg+1]);
Christopher Faulete566f3d2019-10-21 09:55:49 +02008882 goto fail;
Emeric Brun09852f72019-01-10 10:51:13 +01008883 }
Nenad Merdanovic146defa2015-05-09 08:46:00 +02008884
Emeric Brun9e754772019-01-10 17:51:55 +01008885 keys_ref->key_size_bits = 0;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008886 while (fgets(thisline, sizeof(thisline), f) != NULL) {
8887 int len = strlen(thisline);
Emeric Brun9e754772019-01-10 17:51:55 +01008888 int dec_size;
8889
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008890 /* Strip newline characters from the end */
8891 if(thisline[len - 1] == '\n')
8892 thisline[--len] = 0;
8893
8894 if(thisline[len - 1] == '\r')
8895 thisline[--len] = 0;
8896
Emeric Brun9e754772019-01-10 17:51:55 +01008897 dec_size = base64dec(thisline, len, (char *) (keys_ref->tlskeys + i % TLS_TICKETS_NO), sizeof(union tls_sess_key));
8898 if (dec_size < 0) {
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008899 if (err)
8900 memprintf(err, "'%s' : unable to decode base64 key on line %d", args[cur_arg+1], i + 1);
Christopher Faulete566f3d2019-10-21 09:55:49 +02008901 goto fail;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008902 }
Emeric Brun9e754772019-01-10 17:51:55 +01008903 else if (!keys_ref->key_size_bits && (dec_size == sizeof(struct tls_sess_key_128))) {
8904 keys_ref->key_size_bits = 128;
8905 }
8906 else if (!keys_ref->key_size_bits && (dec_size == sizeof(struct tls_sess_key_256))) {
8907 keys_ref->key_size_bits = 256;
8908 }
8909 else if (((dec_size != sizeof(struct tls_sess_key_128)) && (dec_size != sizeof(struct tls_sess_key_256)))
8910 || ((dec_size == sizeof(struct tls_sess_key_128) && (keys_ref->key_size_bits != 128)))
8911 || ((dec_size == sizeof(struct tls_sess_key_256) && (keys_ref->key_size_bits != 256)))) {
Emeric Brun9e754772019-01-10 17:51:55 +01008912 if (err)
8913 memprintf(err, "'%s' : wrong sized key on line %d", args[cur_arg+1], i + 1);
Christopher Faulete566f3d2019-10-21 09:55:49 +02008914 goto fail;
Emeric Brun9e754772019-01-10 17:51:55 +01008915 }
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008916 i++;
8917 }
8918
8919 if (i < TLS_TICKETS_NO) {
8920 if (err)
8921 memprintf(err, "'%s' : please supply at least %d keys in the tls-tickets-file", args[cur_arg+1], TLS_TICKETS_NO);
Christopher Faulete566f3d2019-10-21 09:55:49 +02008922 goto fail;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008923 }
8924
8925 fclose(f);
8926
8927 /* Use penultimate key for encryption, handle when TLS_TICKETS_NO = 1 */
Nenad Merdanovic17891152016-03-25 22:16:57 +01008928 i -= 2;
8929 keys_ref->tls_ticket_enc_index = i < 0 ? 0 : i % TLS_TICKETS_NO;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02008930 keys_ref->unique_id = -1;
Willy Tarreau17b4aa12018-07-17 10:05:32 +02008931 keys_ref->refcount = 1;
Christopher Faulet16f45c82018-02-16 11:23:49 +01008932 HA_RWLOCK_INIT(&keys_ref->lock);
Nenad Merdanovic146defa2015-05-09 08:46:00 +02008933 conf->keys_ref = keys_ref;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008934
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02008935 LIST_ADD(&tlskeys_reference, &keys_ref->list);
8936
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008937 return 0;
Christopher Faulete566f3d2019-10-21 09:55:49 +02008938
8939 fail:
8940 if (f)
8941 fclose(f);
8942 if (keys_ref) {
8943 free(keys_ref->filename);
8944 free(keys_ref->tlskeys);
8945 free(keys_ref);
8946 }
8947 return ERR_ALERT | ERR_FATAL;
8948
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008949#else
8950 if (err)
8951 memprintf(err, "'%s' : TLS ticket callback extension not supported", args[cur_arg]);
8952 return ERR_ALERT | ERR_FATAL;
8953#endif /* SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB */
Emmanuel Hocdet65623372013-01-24 17:17:15 +01008954}
8955
Emeric Brund94b3fe2012-09-20 18:23:56 +02008956/* parse the "verify" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008957static 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 +02008958{
8959 if (!*args[cur_arg + 1]) {
8960 if (err)
8961 memprintf(err, "'%s' : missing verify method", args[cur_arg]);
8962 return ERR_ALERT | ERR_FATAL;
8963 }
8964
8965 if (strcmp(args[cur_arg + 1], "none") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01008966 conf->verify = SSL_SOCK_VERIFY_NONE;
Emeric Brund94b3fe2012-09-20 18:23:56 +02008967 else if (strcmp(args[cur_arg + 1], "optional") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01008968 conf->verify = SSL_SOCK_VERIFY_OPTIONAL;
Emeric Brund94b3fe2012-09-20 18:23:56 +02008969 else if (strcmp(args[cur_arg + 1], "required") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01008970 conf->verify = SSL_SOCK_VERIFY_REQUIRED;
Emeric Brund94b3fe2012-09-20 18:23:56 +02008971 else {
8972 if (err)
8973 memprintf(err, "'%s' : unknown verify method '%s', only 'none', 'optional', and 'required' are supported\n",
8974 args[cur_arg], args[cur_arg + 1]);
8975 return ERR_ALERT | ERR_FATAL;
8976 }
8977
8978 return 0;
8979}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008980static int bind_parse_verify(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8981{
8982 return ssl_bind_parse_verify(args, cur_arg, px, &conf->ssl_conf, err);
8983}
Emeric Brund94b3fe2012-09-20 18:23:56 +02008984
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02008985/* parse the "no-ca-names" bind keyword */
8986static int ssl_bind_parse_no_ca_names(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
8987{
8988 conf->no_ca_names = 1;
8989 return 0;
8990}
8991static int bind_parse_no_ca_names(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8992{
8993 return ssl_bind_parse_no_ca_names(args, cur_arg, px, &conf->ssl_conf, err);
8994}
8995
Willy Tarreau92faadf2012-10-10 23:04:25 +02008996/************** "server" keywords ****************/
8997
Olivier Houchardc7566002018-11-20 23:33:50 +01008998/* parse the "npn" bind keyword */
8999static int srv_parse_npn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9000{
9001#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
9002 char *p1, *p2;
9003
9004 if (!*args[*cur_arg + 1]) {
9005 memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[*cur_arg]);
9006 return ERR_ALERT | ERR_FATAL;
9007 }
9008
9009 free(newsrv->ssl_ctx.npn_str);
9010
9011 /* the NPN string is built as a suite of (<len> <name>)*,
9012 * so we reuse each comma to store the next <len> and need
9013 * one more for the end of the string.
9014 */
9015 newsrv->ssl_ctx.npn_len = strlen(args[*cur_arg + 1]) + 1;
9016 newsrv->ssl_ctx.npn_str = calloc(1, newsrv->ssl_ctx.npn_len + 1);
9017 memcpy(newsrv->ssl_ctx.npn_str + 1, args[*cur_arg + 1],
9018 newsrv->ssl_ctx.npn_len);
9019
9020 /* replace commas with the name length */
9021 p1 = newsrv->ssl_ctx.npn_str;
9022 p2 = p1 + 1;
9023 while (1) {
9024 p2 = memchr(p1 + 1, ',', newsrv->ssl_ctx.npn_str +
9025 newsrv->ssl_ctx.npn_len - (p1 + 1));
9026 if (!p2)
9027 p2 = p1 + 1 + strlen(p1 + 1);
9028
9029 if (p2 - (p1 + 1) > 255) {
9030 *p2 = '\0';
9031 memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[*cur_arg], p1 + 1);
9032 return ERR_ALERT | ERR_FATAL;
9033 }
9034
9035 *p1 = p2 - (p1 + 1);
9036 p1 = p2;
9037
9038 if (!*p2)
9039 break;
9040
9041 *(p2++) = '\0';
9042 }
9043 return 0;
9044#else
9045 if (err)
9046 memprintf(err, "'%s' : library does not support TLS NPN extension", args[*cur_arg]);
9047 return ERR_ALERT | ERR_FATAL;
9048#endif
9049}
9050
Olivier Houchard92150142018-12-21 19:47:01 +01009051/* parse the "alpn" or the "check-alpn" server keyword */
Olivier Houchardc7566002018-11-20 23:33:50 +01009052static int srv_parse_alpn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9053{
9054#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
9055 char *p1, *p2;
Olivier Houchard92150142018-12-21 19:47:01 +01009056 char **alpn_str;
9057 int *alpn_len;
Olivier Houchardc7566002018-11-20 23:33:50 +01009058
Olivier Houchard92150142018-12-21 19:47:01 +01009059 if (*args[*cur_arg] == 'c') {
9060 alpn_str = &newsrv->check.alpn_str;
9061 alpn_len = &newsrv->check.alpn_len;
9062 } else {
9063 alpn_str = &newsrv->ssl_ctx.alpn_str;
9064 alpn_len = &newsrv->ssl_ctx.alpn_len;
9065
9066 }
Olivier Houchardc7566002018-11-20 23:33:50 +01009067 if (!*args[*cur_arg + 1]) {
9068 memprintf(err, "'%s' : missing the comma-delimited ALPN protocol suite", args[*cur_arg]);
9069 return ERR_ALERT | ERR_FATAL;
9070 }
9071
Olivier Houchard92150142018-12-21 19:47:01 +01009072 free(*alpn_str);
Olivier Houchardc7566002018-11-20 23:33:50 +01009073
9074 /* the ALPN string is built as a suite of (<len> <name>)*,
9075 * so we reuse each comma to store the next <len> and need
9076 * one more for the end of the string.
9077 */
Olivier Houchard92150142018-12-21 19:47:01 +01009078 *alpn_len = strlen(args[*cur_arg + 1]) + 1;
9079 *alpn_str = calloc(1, *alpn_len + 1);
9080 memcpy(*alpn_str + 1, args[*cur_arg + 1], *alpn_len);
Olivier Houchardc7566002018-11-20 23:33:50 +01009081
9082 /* replace commas with the name length */
Olivier Houchard92150142018-12-21 19:47:01 +01009083 p1 = *alpn_str;
Olivier Houchardc7566002018-11-20 23:33:50 +01009084 p2 = p1 + 1;
9085 while (1) {
Olivier Houchard92150142018-12-21 19:47:01 +01009086 p2 = memchr(p1 + 1, ',', *alpn_str + *alpn_len - (p1 + 1));
Olivier Houchardc7566002018-11-20 23:33:50 +01009087 if (!p2)
9088 p2 = p1 + 1 + strlen(p1 + 1);
9089
9090 if (p2 - (p1 + 1) > 255) {
9091 *p2 = '\0';
9092 memprintf(err, "'%s' : ALPN protocol name too long : '%s'", args[*cur_arg], p1 + 1);
9093 return ERR_ALERT | ERR_FATAL;
9094 }
9095
9096 *p1 = p2 - (p1 + 1);
9097 p1 = p2;
9098
9099 if (!*p2)
9100 break;
9101
9102 *(p2++) = '\0';
9103 }
9104 return 0;
9105#else
9106 if (err)
9107 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[*cur_arg]);
9108 return ERR_ALERT | ERR_FATAL;
9109#endif
9110}
9111
Emeric Brunef42d922012-10-11 16:11:36 +02009112/* parse the "ca-file" server keyword */
9113static int srv_parse_ca_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9114{
9115 if (!*args[*cur_arg + 1]) {
9116 if (err)
9117 memprintf(err, "'%s' : missing CAfile path", args[*cur_arg]);
9118 return ERR_ALERT | ERR_FATAL;
9119 }
9120
Willy Tarreauef934602016-12-22 23:12:01 +01009121 if ((*args[*cur_arg + 1] != '/') && global_ssl.ca_base)
9122 memprintf(&newsrv->ssl_ctx.ca_file, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02009123 else
9124 memprintf(&newsrv->ssl_ctx.ca_file, "%s", args[*cur_arg + 1]);
9125
9126 return 0;
9127}
9128
Olivier Houchard9130a962017-10-17 17:33:43 +02009129/* parse the "check-sni" server keyword */
9130static int srv_parse_check_sni(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9131{
9132 if (!*args[*cur_arg + 1]) {
9133 if (err)
9134 memprintf(err, "'%s' : missing SNI", args[*cur_arg]);
9135 return ERR_ALERT | ERR_FATAL;
9136 }
9137
9138 newsrv->check.sni = strdup(args[*cur_arg + 1]);
9139 if (!newsrv->check.sni) {
9140 memprintf(err, "'%s' : failed to allocate memory", args[*cur_arg]);
9141 return ERR_ALERT | ERR_FATAL;
9142 }
9143 return 0;
9144
9145}
9146
Willy Tarreau92faadf2012-10-10 23:04:25 +02009147/* parse the "check-ssl" server keyword */
9148static int srv_parse_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9149{
9150 newsrv->check.use_ssl = 1;
Willy Tarreauef934602016-12-22 23:12:01 +01009151 if (global_ssl.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
9152 newsrv->ssl_ctx.ciphers = strdup(global_ssl.connect_default_ciphers);
Emmanuel Hocdet839af572019-05-14 16:27:35 +02009153#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009154 if (global_ssl.connect_default_ciphersuites && !newsrv->ssl_ctx.ciphersuites)
9155 newsrv->ssl_ctx.ciphersuites = strdup(global_ssl.connect_default_ciphersuites);
9156#endif
Willy Tarreauef934602016-12-22 23:12:01 +01009157 newsrv->ssl_ctx.options |= global_ssl.connect_default_ssloptions;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02009158 newsrv->ssl_ctx.methods.flags |= global_ssl.connect_default_sslmethods.flags;
9159 if (!newsrv->ssl_ctx.methods.min)
9160 newsrv->ssl_ctx.methods.min = global_ssl.connect_default_sslmethods.min;
9161 if (!newsrv->ssl_ctx.methods.max)
9162 newsrv->ssl_ctx.methods.max = global_ssl.connect_default_sslmethods.max;
9163
Willy Tarreau92faadf2012-10-10 23:04:25 +02009164 return 0;
9165}
9166
9167/* parse the "ciphers" server keyword */
9168static int srv_parse_ciphers(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9169{
9170 if (!*args[*cur_arg + 1]) {
9171 memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
9172 return ERR_ALERT | ERR_FATAL;
9173 }
9174
9175 free(newsrv->ssl_ctx.ciphers);
9176 newsrv->ssl_ctx.ciphers = strdup(args[*cur_arg + 1]);
9177 return 0;
9178}
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009179
Emmanuel Hocdet839af572019-05-14 16:27:35 +02009180#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009181/* parse the "ciphersuites" server keyword */
9182static int srv_parse_ciphersuites(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9183{
9184 if (!*args[*cur_arg + 1]) {
9185 memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
9186 return ERR_ALERT | ERR_FATAL;
9187 }
9188
9189 free(newsrv->ssl_ctx.ciphersuites);
9190 newsrv->ssl_ctx.ciphersuites = strdup(args[*cur_arg + 1]);
9191 return 0;
9192}
9193#endif
Willy Tarreau92faadf2012-10-10 23:04:25 +02009194
Emeric Brunef42d922012-10-11 16:11:36 +02009195/* parse the "crl-file" server keyword */
9196static int srv_parse_crl_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9197{
9198#ifndef X509_V_FLAG_CRL_CHECK
9199 if (err)
9200 memprintf(err, "'%s' : library does not support CRL verify", args[*cur_arg]);
9201 return ERR_ALERT | ERR_FATAL;
9202#else
9203 if (!*args[*cur_arg + 1]) {
9204 if (err)
9205 memprintf(err, "'%s' : missing CRLfile path", args[*cur_arg]);
9206 return ERR_ALERT | ERR_FATAL;
9207 }
9208
Willy Tarreauef934602016-12-22 23:12:01 +01009209 if ((*args[*cur_arg + 1] != '/') && global_ssl.ca_base)
9210 memprintf(&newsrv->ssl_ctx.crl_file, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02009211 else
9212 memprintf(&newsrv->ssl_ctx.crl_file, "%s", args[*cur_arg + 1]);
9213
9214 return 0;
9215#endif
9216}
9217
Emeric Bruna7aa3092012-10-26 12:58:00 +02009218/* parse the "crt" server keyword */
9219static int srv_parse_crt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9220{
9221 if (!*args[*cur_arg + 1]) {
9222 if (err)
9223 memprintf(err, "'%s' : missing certificate file path", args[*cur_arg]);
9224 return ERR_ALERT | ERR_FATAL;
9225 }
9226
Willy Tarreauef934602016-12-22 23:12:01 +01009227 if ((*args[*cur_arg + 1] != '/') && global_ssl.crt_base)
Christopher Fauletff3a41e2017-11-23 09:13:32 +01009228 memprintf(&newsrv->ssl_ctx.client_crt, "%s/%s", global_ssl.crt_base, args[*cur_arg + 1]);
Emeric Bruna7aa3092012-10-26 12:58:00 +02009229 else
9230 memprintf(&newsrv->ssl_ctx.client_crt, "%s", args[*cur_arg + 1]);
9231
9232 return 0;
9233}
Emeric Brunef42d922012-10-11 16:11:36 +02009234
Frédéric Lécaille340ae602017-03-13 10:38:04 +01009235/* parse the "no-check-ssl" server keyword */
9236static int srv_parse_no_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9237{
9238 newsrv->check.use_ssl = 0;
9239 free(newsrv->ssl_ctx.ciphers);
9240 newsrv->ssl_ctx.ciphers = NULL;
9241 newsrv->ssl_ctx.options &= ~global_ssl.connect_default_ssloptions;
9242 return 0;
9243}
9244
Frédéric Lécaillee892c4c2017-03-13 12:08:01 +01009245/* parse the "no-send-proxy-v2-ssl" server keyword */
9246static int srv_parse_no_send_proxy_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9247{
9248 newsrv->pp_opts &= ~SRV_PP_V2;
9249 newsrv->pp_opts &= ~SRV_PP_V2_SSL;
9250 return 0;
9251}
9252
9253/* parse the "no-send-proxy-v2-ssl-cn" server keyword */
9254static int srv_parse_no_send_proxy_cn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9255{
9256 newsrv->pp_opts &= ~SRV_PP_V2;
9257 newsrv->pp_opts &= ~SRV_PP_V2_SSL;
9258 newsrv->pp_opts &= ~SRV_PP_V2_SSL_CN;
9259 return 0;
9260}
9261
Frédéric Lécaillee381d762017-03-13 11:54:17 +01009262/* parse the "no-ssl" server keyword */
9263static int srv_parse_no_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9264{
9265 newsrv->use_ssl = 0;
9266 free(newsrv->ssl_ctx.ciphers);
9267 newsrv->ssl_ctx.ciphers = NULL;
9268 return 0;
9269}
9270
Olivier Houchard522eea72017-11-03 16:27:47 +01009271/* parse the "allow-0rtt" server keyword */
9272static int srv_parse_allow_0rtt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9273{
9274 newsrv->ssl_ctx.options |= SRV_SSL_O_EARLY_DATA;
9275 return 0;
9276}
9277
Willy Tarreau2a3fb1c2015-02-05 16:47:07 +01009278/* parse the "no-ssl-reuse" server keyword */
9279static int srv_parse_no_ssl_reuse(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9280{
9281 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_REUSE;
9282 return 0;
9283}
9284
Emeric Brunf9c5c472012-10-11 15:28:34 +02009285/* parse the "no-tls-tickets" server keyword */
9286static int srv_parse_no_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9287{
9288 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLS_TICKETS;
9289 return 0;
9290}
David Safb76832014-05-08 23:42:08 -04009291/* parse the "send-proxy-v2-ssl" server keyword */
9292static int srv_parse_send_proxy_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9293{
9294 newsrv->pp_opts |= SRV_PP_V2;
9295 newsrv->pp_opts |= SRV_PP_V2_SSL;
9296 return 0;
9297}
9298
9299/* parse the "send-proxy-v2-ssl-cn" server keyword */
9300static int srv_parse_send_proxy_cn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9301{
9302 newsrv->pp_opts |= SRV_PP_V2;
9303 newsrv->pp_opts |= SRV_PP_V2_SSL;
9304 newsrv->pp_opts |= SRV_PP_V2_SSL_CN;
9305 return 0;
9306}
Emeric Brunf9c5c472012-10-11 15:28:34 +02009307
Willy Tarreau732eac42015-07-09 11:40:25 +02009308/* parse the "sni" server keyword */
9309static int srv_parse_sni(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9310{
9311#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
9312 memprintf(err, "'%s' : the current SSL library doesn't support the SNI TLS extension", args[*cur_arg]);
9313 return ERR_ALERT | ERR_FATAL;
9314#else
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01009315 char *arg;
Willy Tarreau732eac42015-07-09 11:40:25 +02009316
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01009317 arg = args[*cur_arg + 1];
9318 if (!*arg) {
Willy Tarreau732eac42015-07-09 11:40:25 +02009319 memprintf(err, "'%s' : missing sni expression", args[*cur_arg]);
9320 return ERR_ALERT | ERR_FATAL;
9321 }
9322
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01009323 free(newsrv->sni_expr);
9324 newsrv->sni_expr = strdup(arg);
Willy Tarreau732eac42015-07-09 11:40:25 +02009325
Willy Tarreau732eac42015-07-09 11:40:25 +02009326 return 0;
9327#endif
9328}
9329
Willy Tarreau92faadf2012-10-10 23:04:25 +02009330/* parse the "ssl" server keyword */
9331static int srv_parse_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9332{
9333 newsrv->use_ssl = 1;
Willy Tarreauef934602016-12-22 23:12:01 +01009334 if (global_ssl.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
9335 newsrv->ssl_ctx.ciphers = strdup(global_ssl.connect_default_ciphers);
Emmanuel Hocdet839af572019-05-14 16:27:35 +02009336#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009337 if (global_ssl.connect_default_ciphersuites && !newsrv->ssl_ctx.ciphersuites)
9338 newsrv->ssl_ctx.ciphersuites = strdup(global_ssl.connect_default_ciphersuites);
9339#endif
Willy Tarreau92faadf2012-10-10 23:04:25 +02009340 return 0;
9341}
9342
Frédéric Lécaille2cfcdbe2017-03-13 11:32:20 +01009343/* parse the "ssl-reuse" server keyword */
9344static int srv_parse_ssl_reuse(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9345{
9346 newsrv->ssl_ctx.options &= ~SRV_SSL_O_NO_REUSE;
9347 return 0;
9348}
9349
Frédéric Lécaille2cfcdbe2017-03-13 11:32:20 +01009350/* parse the "tls-tickets" server keyword */
9351static int srv_parse_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9352{
9353 newsrv->ssl_ctx.options &= ~SRV_SSL_O_NO_TLS_TICKETS;
9354 return 0;
9355}
9356
Emeric Brunef42d922012-10-11 16:11:36 +02009357/* parse the "verify" server keyword */
9358static int srv_parse_verify(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9359{
9360 if (!*args[*cur_arg + 1]) {
9361 if (err)
9362 memprintf(err, "'%s' : missing verify method", args[*cur_arg]);
9363 return ERR_ALERT | ERR_FATAL;
9364 }
9365
9366 if (strcmp(args[*cur_arg + 1], "none") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01009367 newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_NONE;
Emeric Brunef42d922012-10-11 16:11:36 +02009368 else if (strcmp(args[*cur_arg + 1], "required") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01009369 newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_REQUIRED;
Emeric Brunef42d922012-10-11 16:11:36 +02009370 else {
9371 if (err)
9372 memprintf(err, "'%s' : unknown verify method '%s', only 'none' and 'required' are supported\n",
9373 args[*cur_arg], args[*cur_arg + 1]);
9374 return ERR_ALERT | ERR_FATAL;
9375 }
9376
Evan Broderbe554312013-06-27 00:05:25 -07009377 return 0;
9378}
9379
9380/* parse the "verifyhost" server keyword */
9381static int srv_parse_verifyhost(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9382{
9383 if (!*args[*cur_arg + 1]) {
9384 if (err)
9385 memprintf(err, "'%s' : missing hostname to verify against", args[*cur_arg]);
9386 return ERR_ALERT | ERR_FATAL;
9387 }
9388
Frédéric Lécaille273f3212017-03-13 15:52:01 +01009389 free(newsrv->ssl_ctx.verify_host);
Evan Broderbe554312013-06-27 00:05:25 -07009390 newsrv->ssl_ctx.verify_host = strdup(args[*cur_arg + 1]);
9391
Emeric Brunef42d922012-10-11 16:11:36 +02009392 return 0;
9393}
9394
Emeric Brun2c86cbf2014-10-30 15:56:50 +01009395/* parse the "ssl-default-bind-options" keyword in global section */
9396static int ssl_parse_default_bind_options(char **args, int section_type, struct proxy *curpx,
9397 struct proxy *defpx, const char *file, int line,
9398 char **err) {
9399 int i = 1;
9400
9401 if (*(args[i]) == 0) {
9402 memprintf(err, "global statement '%s' expects an option as an argument.", args[0]);
9403 return -1;
9404 }
9405 while (*(args[i])) {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02009406 if (!strcmp(args[i], "no-tls-tickets"))
Willy Tarreauef934602016-12-22 23:12:01 +01009407 global_ssl.listen_default_ssloptions |= BC_SSL_O_NO_TLS_TICKETS;
Lukas Tribus53ae85c2017-05-04 15:45:40 +00009408 else if (!strcmp(args[i], "prefer-client-ciphers"))
9409 global_ssl.listen_default_ssloptions |= BC_SSL_O_PREF_CLIE_CIPH;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02009410 else if (!strcmp(args[i], "ssl-min-ver") || !strcmp(args[i], "ssl-max-ver")) {
9411 if (!parse_tls_method_minmax(args, i, &global_ssl.listen_default_sslmethods, err))
9412 i++;
9413 else {
9414 memprintf(err, "%s on global statement '%s'.", *err, args[0]);
9415 return -1;
9416 }
9417 }
9418 else if (parse_tls_method_options(args[i], &global_ssl.listen_default_sslmethods, err)) {
Emeric Brun2c86cbf2014-10-30 15:56:50 +01009419 memprintf(err, "unknown option '%s' on global statement '%s'.", args[i], args[0]);
9420 return -1;
9421 }
9422 i++;
9423 }
9424 return 0;
9425}
9426
9427/* parse the "ssl-default-server-options" keyword in global section */
9428static int ssl_parse_default_server_options(char **args, int section_type, struct proxy *curpx,
9429 struct proxy *defpx, const char *file, int line,
9430 char **err) {
9431 int i = 1;
9432
9433 if (*(args[i]) == 0) {
9434 memprintf(err, "global statement '%s' expects an option as an argument.", args[0]);
9435 return -1;
9436 }
9437 while (*(args[i])) {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02009438 if (!strcmp(args[i], "no-tls-tickets"))
Willy Tarreauef934602016-12-22 23:12:01 +01009439 global_ssl.connect_default_ssloptions |= SRV_SSL_O_NO_TLS_TICKETS;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02009440 else if (!strcmp(args[i], "ssl-min-ver") || !strcmp(args[i], "ssl-max-ver")) {
9441 if (!parse_tls_method_minmax(args, i, &global_ssl.connect_default_sslmethods, err))
9442 i++;
9443 else {
9444 memprintf(err, "%s on global statement '%s'.", *err, args[0]);
9445 return -1;
9446 }
9447 }
9448 else if (parse_tls_method_options(args[i], &global_ssl.connect_default_sslmethods, err)) {
Emeric Brun2c86cbf2014-10-30 15:56:50 +01009449 memprintf(err, "unknown option '%s' on global statement '%s'.", args[i], args[0]);
9450 return -1;
9451 }
9452 i++;
9453 }
9454 return 0;
9455}
9456
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01009457/* parse the "ca-base" / "crt-base" keywords in global section.
9458 * Returns <0 on alert, >0 on warning, 0 on success.
9459 */
9460static int ssl_parse_global_ca_crt_base(char **args, int section_type, struct proxy *curpx,
9461 struct proxy *defpx, const char *file, int line,
9462 char **err)
9463{
9464 char **target;
9465
Willy Tarreauef934602016-12-22 23:12:01 +01009466 target = (args[0][1] == 'a') ? &global_ssl.ca_base : &global_ssl.crt_base;
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01009467
9468 if (too_many_args(1, args, err, NULL))
9469 return -1;
9470
9471 if (*target) {
9472 memprintf(err, "'%s' already specified.", args[0]);
9473 return -1;
9474 }
9475
9476 if (*(args[1]) == 0) {
9477 memprintf(err, "global statement '%s' expects a directory path as an argument.", args[0]);
9478 return -1;
9479 }
9480 *target = strdup(args[1]);
9481 return 0;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00009482}
9483
9484/* parse the "ssl-mode-async" keyword in global section.
9485 * Returns <0 on alert, >0 on warning, 0 on success.
9486 */
9487static int ssl_parse_global_ssl_async(char **args, int section_type, struct proxy *curpx,
9488 struct proxy *defpx, const char *file, int line,
9489 char **err)
9490{
Willy Tarreau5db847a2019-05-09 14:13:35 +02009491#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00009492 global_ssl.async = 1;
Emeric Brunece0c332017-12-06 13:51:49 +01009493 global.ssl_used_async_engines = nb_engines;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00009494 return 0;
9495#else
9496 memprintf(err, "'%s': openssl library does not support async mode", args[0]);
9497 return -1;
9498#endif
9499}
9500
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02009501#ifndef OPENSSL_NO_ENGINE
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00009502static int ssl_check_async_engine_count(void) {
9503 int err_code = 0;
9504
Emeric Brun3854e012017-05-17 20:42:48 +02009505 if (global_ssl.async && (openssl_engines_initialized > 32)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01009506 ha_alert("ssl-mode-async only supports a maximum of 32 engines.\n");
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00009507 err_code = ERR_ABORT;
9508 }
9509 return err_code;
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01009510}
9511
Grant Zhang872f9c22017-01-21 01:10:18 +00009512/* parse the "ssl-engine" keyword in global section.
9513 * Returns <0 on alert, >0 on warning, 0 on success.
9514 */
9515static int ssl_parse_global_ssl_engine(char **args, int section_type, struct proxy *curpx,
9516 struct proxy *defpx, const char *file, int line,
9517 char **err)
9518{
9519 char *algo;
9520 int ret = -1;
9521
9522 if (*(args[1]) == 0) {
9523 memprintf(err, "global statement '%s' expects a valid engine name as an argument.", args[0]);
9524 return ret;
9525 }
9526
9527 if (*(args[2]) == 0) {
9528 /* if no list of algorithms is given, it defaults to ALL */
9529 algo = strdup("ALL");
9530 goto add_engine;
9531 }
9532
9533 /* otherwise the expected format is ssl-engine <engine_name> algo <list of algo> */
9534 if (strcmp(args[2], "algo") != 0) {
9535 memprintf(err, "global statement '%s' expects to have algo keyword.", args[0]);
9536 return ret;
9537 }
9538
9539 if (*(args[3]) == 0) {
9540 memprintf(err, "global statement '%s' expects algorithm names as an argument.", args[0]);
9541 return ret;
9542 }
9543 algo = strdup(args[3]);
9544
9545add_engine:
9546 if (ssl_init_single_engine(args[1], algo)==0) {
9547 openssl_engines_initialized++;
9548 ret = 0;
9549 }
9550 free(algo);
9551 return ret;
9552}
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02009553#endif
Grant Zhang872f9c22017-01-21 01:10:18 +00009554
Willy Tarreauf22e9682016-12-21 23:23:19 +01009555/* parse the "ssl-default-bind-ciphers" / "ssl-default-server-ciphers" keywords
9556 * in global section. Returns <0 on alert, >0 on warning, 0 on success.
9557 */
9558static int ssl_parse_global_ciphers(char **args, int section_type, struct proxy *curpx,
9559 struct proxy *defpx, const char *file, int line,
9560 char **err)
9561{
9562 char **target;
9563
Willy Tarreauef934602016-12-22 23:12:01 +01009564 target = (args[0][12] == 'b') ? &global_ssl.listen_default_ciphers : &global_ssl.connect_default_ciphers;
Willy Tarreauf22e9682016-12-21 23:23:19 +01009565
9566 if (too_many_args(1, args, err, NULL))
9567 return -1;
9568
9569 if (*(args[1]) == 0) {
9570 memprintf(err, "global statement '%s' expects a cipher suite as an argument.", args[0]);
9571 return -1;
9572 }
9573
9574 free(*target);
9575 *target = strdup(args[1]);
9576 return 0;
9577}
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009578
Emmanuel Hocdet839af572019-05-14 16:27:35 +02009579#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009580/* parse the "ssl-default-bind-ciphersuites" / "ssl-default-server-ciphersuites" keywords
9581 * in global section. Returns <0 on alert, >0 on warning, 0 on success.
9582 */
9583static int ssl_parse_global_ciphersuites(char **args, int section_type, struct proxy *curpx,
9584 struct proxy *defpx, const char *file, int line,
9585 char **err)
9586{
9587 char **target;
9588
9589 target = (args[0][12] == 'b') ? &global_ssl.listen_default_ciphersuites : &global_ssl.connect_default_ciphersuites;
9590
9591 if (too_many_args(1, args, err, NULL))
9592 return -1;
9593
9594 if (*(args[1]) == 0) {
9595 memprintf(err, "global statement '%s' expects a cipher suite as an argument.", args[0]);
9596 return -1;
9597 }
9598
9599 free(*target);
9600 *target = strdup(args[1]);
9601 return 0;
9602}
9603#endif
Willy Tarreauf22e9682016-12-21 23:23:19 +01009604
Willy Tarreau9ceda382016-12-21 23:13:03 +01009605/* parse various global tune.ssl settings consisting in positive integers.
9606 * Returns <0 on alert, >0 on warning, 0 on success.
9607 */
9608static int ssl_parse_global_int(char **args, int section_type, struct proxy *curpx,
9609 struct proxy *defpx, const char *file, int line,
9610 char **err)
9611{
9612 int *target;
9613
9614 if (strcmp(args[0], "tune.ssl.cachesize") == 0)
9615 target = &global.tune.sslcachesize;
9616 else if (strcmp(args[0], "tune.ssl.maxrecord") == 0)
Willy Tarreauef934602016-12-22 23:12:01 +01009617 target = (int *)&global_ssl.max_record;
Willy Tarreau9ceda382016-12-21 23:13:03 +01009618 else if (strcmp(args[0], "tune.ssl.ssl-ctx-cache-size") == 0)
Willy Tarreauef934602016-12-22 23:12:01 +01009619 target = &global_ssl.ctx_cache;
Willy Tarreau0bea58d2016-12-21 23:17:25 +01009620 else if (strcmp(args[0], "maxsslconn") == 0)
9621 target = &global.maxsslconn;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01009622 else if (strcmp(args[0], "tune.ssl.capture-cipherlist-size") == 0)
9623 target = &global_ssl.capture_cipherlist;
Willy Tarreau9ceda382016-12-21 23:13:03 +01009624 else {
9625 memprintf(err, "'%s' keyword not unhandled (please report this bug).", args[0]);
9626 return -1;
9627 }
9628
9629 if (too_many_args(1, args, err, NULL))
9630 return -1;
9631
9632 if (*(args[1]) == 0) {
9633 memprintf(err, "'%s' expects an integer argument.", args[0]);
9634 return -1;
9635 }
9636
9637 *target = atoi(args[1]);
9638 if (*target < 0) {
9639 memprintf(err, "'%s' expects a positive numeric value.", args[0]);
9640 return -1;
9641 }
9642 return 0;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01009643}
9644
9645static int ssl_parse_global_capture_cipherlist(char **args, int section_type, struct proxy *curpx,
9646 struct proxy *defpx, const char *file, int line,
9647 char **err)
9648{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01009649 int ret;
9650
9651 ret = ssl_parse_global_int(args, section_type, curpx, defpx, file, line, err);
9652 if (ret != 0)
9653 return ret;
9654
Willy Tarreaubafbe012017-11-24 17:34:44 +01009655 if (pool_head_ssl_capture) {
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01009656 memprintf(err, "'%s' is already configured.", args[0]);
9657 return -1;
9658 }
9659
Willy Tarreaubafbe012017-11-24 17:34:44 +01009660 pool_head_ssl_capture = create_pool("ssl-capture", sizeof(struct ssl_capture) + global_ssl.capture_cipherlist, MEM_F_SHARED);
9661 if (!pool_head_ssl_capture) {
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01009662 memprintf(err, "Out of memory error.");
9663 return -1;
9664 }
9665 return 0;
Willy Tarreau9ceda382016-12-21 23:13:03 +01009666}
9667
9668/* parse "ssl.force-private-cache".
9669 * Returns <0 on alert, >0 on warning, 0 on success.
9670 */
9671static int ssl_parse_global_private_cache(char **args, int section_type, struct proxy *curpx,
9672 struct proxy *defpx, const char *file, int line,
9673 char **err)
9674{
9675 if (too_many_args(0, args, err, NULL))
9676 return -1;
9677
Willy Tarreauef934602016-12-22 23:12:01 +01009678 global_ssl.private_cache = 1;
Willy Tarreau9ceda382016-12-21 23:13:03 +01009679 return 0;
9680}
9681
9682/* parse "ssl.lifetime".
9683 * Returns <0 on alert, >0 on warning, 0 on success.
9684 */
9685static int ssl_parse_global_lifetime(char **args, int section_type, struct proxy *curpx,
9686 struct proxy *defpx, const char *file, int line,
9687 char **err)
9688{
9689 const char *res;
9690
9691 if (too_many_args(1, args, err, NULL))
9692 return -1;
9693
9694 if (*(args[1]) == 0) {
9695 memprintf(err, "'%s' expects ssl sessions <lifetime> in seconds as argument.", args[0]);
9696 return -1;
9697 }
9698
Willy Tarreauef934602016-12-22 23:12:01 +01009699 res = parse_time_err(args[1], &global_ssl.life_time, TIME_UNIT_S);
Willy Tarreau9faebe32019-06-07 19:00:37 +02009700 if (res == PARSE_TIME_OVER) {
9701 memprintf(err, "timer overflow in argument '%s' to <%s> (maximum value is 2147483647 s or ~68 years).",
9702 args[1], args[0]);
9703 return -1;
9704 }
9705 else if (res == PARSE_TIME_UNDER) {
9706 memprintf(err, "timer underflow in argument '%s' to <%s> (minimum non-null value is 1 s).",
9707 args[1], args[0]);
9708 return -1;
9709 }
9710 else if (res) {
Willy Tarreau9ceda382016-12-21 23:13:03 +01009711 memprintf(err, "unexpected character '%c' in argument to <%s>.", *res, args[0]);
9712 return -1;
9713 }
9714 return 0;
9715}
9716
9717#ifndef OPENSSL_NO_DH
Willy Tarreau14e36a12016-12-21 23:28:13 +01009718/* parse "ssl-dh-param-file".
9719 * Returns <0 on alert, >0 on warning, 0 on success.
9720 */
9721static int ssl_parse_global_dh_param_file(char **args, int section_type, struct proxy *curpx,
9722 struct proxy *defpx, const char *file, int line,
9723 char **err)
9724{
9725 if (too_many_args(1, args, err, NULL))
9726 return -1;
9727
9728 if (*(args[1]) == 0) {
9729 memprintf(err, "'%s' expects a file path as an argument.", args[0]);
9730 return -1;
9731 }
9732
9733 if (ssl_sock_load_global_dh_param_from_file(args[1])) {
9734 memprintf(err, "'%s': unable to load DH parameters from file <%s>.", args[0], args[1]);
9735 return -1;
9736 }
9737 return 0;
9738}
9739
Willy Tarreau9ceda382016-12-21 23:13:03 +01009740/* parse "ssl.default-dh-param".
9741 * Returns <0 on alert, >0 on warning, 0 on success.
9742 */
9743static int ssl_parse_global_default_dh(char **args, int section_type, struct proxy *curpx,
9744 struct proxy *defpx, const char *file, int line,
9745 char **err)
9746{
9747 if (too_many_args(1, args, err, NULL))
9748 return -1;
9749
9750 if (*(args[1]) == 0) {
9751 memprintf(err, "'%s' expects an integer argument.", args[0]);
9752 return -1;
9753 }
9754
Willy Tarreauef934602016-12-22 23:12:01 +01009755 global_ssl.default_dh_param = atoi(args[1]);
9756 if (global_ssl.default_dh_param < 1024) {
Willy Tarreau9ceda382016-12-21 23:13:03 +01009757 memprintf(err, "'%s' expects a value >= 1024.", args[0]);
9758 return -1;
9759 }
9760 return 0;
9761}
9762#endif
9763
9764
William Lallemand32af2032016-10-29 18:09:35 +02009765/* This function is used with TLS ticket keys management. It permits to browse
9766 * each reference. The variable <getnext> must contain the current node,
9767 * <end> point to the root node.
9768 */
9769#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
9770static inline
9771struct tls_keys_ref *tlskeys_list_get_next(struct tls_keys_ref *getnext, struct list *end)
9772{
9773 struct tls_keys_ref *ref = getnext;
9774
9775 while (1) {
9776
9777 /* Get next list entry. */
9778 ref = LIST_NEXT(&ref->list, struct tls_keys_ref *, list);
9779
9780 /* If the entry is the last of the list, return NULL. */
9781 if (&ref->list == end)
9782 return NULL;
9783
9784 return ref;
9785 }
9786}
9787
9788static inline
9789struct tls_keys_ref *tlskeys_ref_lookup_ref(const char *reference)
9790{
9791 int id;
9792 char *error;
9793
9794 /* If the reference starts by a '#', this is numeric id. */
9795 if (reference[0] == '#') {
9796 /* Try to convert the numeric id. If the conversion fails, the lookup fails. */
9797 id = strtol(reference + 1, &error, 10);
9798 if (*error != '\0')
9799 return NULL;
9800
9801 /* Perform the unique id lookup. */
9802 return tlskeys_ref_lookupid(id);
9803 }
9804
9805 /* Perform the string lookup. */
9806 return tlskeys_ref_lookup(reference);
9807}
9808#endif
9809
9810
9811#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
9812
9813static int cli_io_handler_tlskeys_files(struct appctx *appctx);
9814
9815static inline int cli_io_handler_tlskeys_entries(struct appctx *appctx) {
9816 return cli_io_handler_tlskeys_files(appctx);
9817}
9818
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009819/* dumps all tls keys. Relies on cli.i0 (non-null = only list file names), cli.i1
9820 * (next index to be dumped), and cli.p0 (next key reference).
9821 */
William Lallemand32af2032016-10-29 18:09:35 +02009822static int cli_io_handler_tlskeys_files(struct appctx *appctx) {
9823
9824 struct stream_interface *si = appctx->owner;
9825
9826 switch (appctx->st2) {
9827 case STAT_ST_INIT:
9828 /* Display the column headers. If the message cannot be sent,
Joseph Herlant017b3da2018-11-15 09:07:59 -08009829 * quit the function with returning 0. The function is called
William Lallemand32af2032016-10-29 18:09:35 +02009830 * later and restart at the state "STAT_ST_INIT".
9831 */
9832 chunk_reset(&trash);
9833
9834 if (appctx->io_handler == cli_io_handler_tlskeys_entries)
9835 chunk_appendf(&trash, "# id secret\n");
9836 else
9837 chunk_appendf(&trash, "# id (file)\n");
9838
Willy Tarreau06d80a92017-10-19 14:32:15 +02009839 if (ci_putchk(si_ic(si), &trash) == -1) {
Willy Tarreaudb398432018-11-15 11:08:52 +01009840 si_rx_room_blk(si);
William Lallemand32af2032016-10-29 18:09:35 +02009841 return 0;
9842 }
9843
William Lallemand32af2032016-10-29 18:09:35 +02009844 /* Now, we start the browsing of the references lists.
9845 * Note that the following call to LIST_ELEM return bad pointer. The only
9846 * available field of this pointer is <list>. It is used with the function
9847 * tlskeys_list_get_next() for retruning the first available entry
9848 */
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009849 if (appctx->ctx.cli.p0 == NULL) {
9850 appctx->ctx.cli.p0 = LIST_ELEM(&tlskeys_reference, struct tls_keys_ref *, list);
9851 appctx->ctx.cli.p0 = tlskeys_list_get_next(appctx->ctx.cli.p0, &tlskeys_reference);
William Lallemand32af2032016-10-29 18:09:35 +02009852 }
9853
9854 appctx->st2 = STAT_ST_LIST;
9855 /* fall through */
9856
9857 case STAT_ST_LIST:
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009858 while (appctx->ctx.cli.p0) {
9859 struct tls_keys_ref *ref = appctx->ctx.cli.p0;
William Lallemand32af2032016-10-29 18:09:35 +02009860
9861 chunk_reset(&trash);
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009862 if (appctx->io_handler == cli_io_handler_tlskeys_entries && appctx->ctx.cli.i1 == 0)
William Lallemand32af2032016-10-29 18:09:35 +02009863 chunk_appendf(&trash, "# ");
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009864
9865 if (appctx->ctx.cli.i1 == 0)
9866 chunk_appendf(&trash, "%d (%s)\n", ref->unique_id, ref->filename);
9867
William Lallemand32af2032016-10-29 18:09:35 +02009868 if (appctx->io_handler == cli_io_handler_tlskeys_entries) {
Christopher Faulet16f45c82018-02-16 11:23:49 +01009869 int head;
9870
9871 HA_RWLOCK_RDLOCK(TLSKEYS_REF_LOCK, &ref->lock);
9872 head = ref->tls_ticket_enc_index;
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009873 while (appctx->ctx.cli.i1 < TLS_TICKETS_NO) {
Willy Tarreau83061a82018-07-13 11:56:34 +02009874 struct buffer *t2 = get_trash_chunk();
William Lallemand32af2032016-10-29 18:09:35 +02009875
9876 chunk_reset(t2);
9877 /* should never fail here because we dump only a key in the t2 buffer */
Emeric Brun9e754772019-01-10 17:51:55 +01009878 if (ref->key_size_bits == 128) {
9879 t2->data = a2base64((char *)(ref->tlskeys + (head + 2 + appctx->ctx.cli.i1) % TLS_TICKETS_NO),
9880 sizeof(struct tls_sess_key_128),
9881 t2->area, t2->size);
9882 chunk_appendf(&trash, "%d.%d %s\n", ref->unique_id, appctx->ctx.cli.i1,
9883 t2->area);
9884 }
9885 else if (ref->key_size_bits == 256) {
9886 t2->data = a2base64((char *)(ref->tlskeys + (head + 2 + appctx->ctx.cli.i1) % TLS_TICKETS_NO),
9887 sizeof(struct tls_sess_key_256),
9888 t2->area, t2->size);
9889 chunk_appendf(&trash, "%d.%d %s\n", ref->unique_id, appctx->ctx.cli.i1,
9890 t2->area);
9891 }
9892 else {
9893 /* This case should never happen */
9894 chunk_appendf(&trash, "%d.%d <unknown>\n", ref->unique_id, appctx->ctx.cli.i1);
9895 }
William Lallemand32af2032016-10-29 18:09:35 +02009896
Willy Tarreau06d80a92017-10-19 14:32:15 +02009897 if (ci_putchk(si_ic(si), &trash) == -1) {
William Lallemand32af2032016-10-29 18:09:35 +02009898 /* let's try again later from this stream. We add ourselves into
9899 * this stream's users so that it can remove us upon termination.
9900 */
Christopher Faulet16f45c82018-02-16 11:23:49 +01009901 HA_RWLOCK_RDUNLOCK(TLSKEYS_REF_LOCK, &ref->lock);
Willy Tarreaudb398432018-11-15 11:08:52 +01009902 si_rx_room_blk(si);
William Lallemand32af2032016-10-29 18:09:35 +02009903 return 0;
9904 }
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009905 appctx->ctx.cli.i1++;
William Lallemand32af2032016-10-29 18:09:35 +02009906 }
Christopher Faulet16f45c82018-02-16 11:23:49 +01009907 HA_RWLOCK_RDUNLOCK(TLSKEYS_REF_LOCK, &ref->lock);
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009908 appctx->ctx.cli.i1 = 0;
William Lallemand32af2032016-10-29 18:09:35 +02009909 }
Willy Tarreau06d80a92017-10-19 14:32:15 +02009910 if (ci_putchk(si_ic(si), &trash) == -1) {
William Lallemand32af2032016-10-29 18:09:35 +02009911 /* let's try again later from this stream. We add ourselves into
9912 * this stream's users so that it can remove us upon termination.
9913 */
Willy Tarreaudb398432018-11-15 11:08:52 +01009914 si_rx_room_blk(si);
William Lallemand32af2032016-10-29 18:09:35 +02009915 return 0;
9916 }
9917
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009918 if (appctx->ctx.cli.i0 == 0) /* don't display everything if not necessary */
William Lallemand32af2032016-10-29 18:09:35 +02009919 break;
9920
9921 /* get next list entry and check the end of the list */
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009922 appctx->ctx.cli.p0 = tlskeys_list_get_next(appctx->ctx.cli.p0, &tlskeys_reference);
William Lallemand32af2032016-10-29 18:09:35 +02009923 }
9924
9925 appctx->st2 = STAT_ST_FIN;
9926 /* fall through */
9927
9928 default:
9929 appctx->st2 = STAT_ST_FIN;
9930 return 1;
9931 }
9932 return 0;
9933}
9934
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009935/* sets cli.i0 to non-zero if only file lists should be dumped */
Aurélien Nephtaliabbf6072018-04-18 13:26:46 +02009936static int cli_parse_show_tlskeys(char **args, char *payload, struct appctx *appctx, void *private)
William Lallemand32af2032016-10-29 18:09:35 +02009937{
William Lallemand32af2032016-10-29 18:09:35 +02009938 /* no parameter, shows only file list */
9939 if (!*args[2]) {
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009940 appctx->ctx.cli.i0 = 1;
William Lallemand32af2032016-10-29 18:09:35 +02009941 appctx->io_handler = cli_io_handler_tlskeys_files;
Willy Tarreau3067bfa2016-12-05 14:50:15 +01009942 return 0;
William Lallemand32af2032016-10-29 18:09:35 +02009943 }
9944
9945 if (args[2][0] == '*') {
9946 /* list every TLS ticket keys */
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009947 appctx->ctx.cli.i0 = 1;
William Lallemand32af2032016-10-29 18:09:35 +02009948 } else {
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009949 appctx->ctx.cli.p0 = tlskeys_ref_lookup_ref(args[2]);
Willy Tarreau9d008692019-08-09 11:21:01 +02009950 if (!appctx->ctx.cli.p0)
9951 return cli_err(appctx, "'show tls-keys' unable to locate referenced filename\n");
William Lallemand32af2032016-10-29 18:09:35 +02009952 }
William Lallemand32af2032016-10-29 18:09:35 +02009953 appctx->io_handler = cli_io_handler_tlskeys_entries;
Willy Tarreau3067bfa2016-12-05 14:50:15 +01009954 return 0;
William Lallemand32af2032016-10-29 18:09:35 +02009955}
9956
Aurélien Nephtaliabbf6072018-04-18 13:26:46 +02009957static int cli_parse_set_tlskeys(char **args, char *payload, struct appctx *appctx, void *private)
William Lallemand32af2032016-10-29 18:09:35 +02009958{
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009959 struct tls_keys_ref *ref;
Willy Tarreau1c913e42018-08-22 05:26:57 +02009960 int ret;
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009961
William Lallemand32af2032016-10-29 18:09:35 +02009962 /* Expect two parameters: the filename and the new new TLS key in encoding */
Willy Tarreau9d008692019-08-09 11:21:01 +02009963 if (!*args[3] || !*args[4])
9964 return cli_err(appctx, "'set ssl tls-key' expects a filename and the new TLS key in base64 encoding.\n");
William Lallemand32af2032016-10-29 18:09:35 +02009965
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009966 ref = tlskeys_ref_lookup_ref(args[3]);
Willy Tarreau9d008692019-08-09 11:21:01 +02009967 if (!ref)
9968 return cli_err(appctx, "'set ssl tls-key' unable to locate referenced filename\n");
William Lallemand32af2032016-10-29 18:09:35 +02009969
Willy Tarreau1c913e42018-08-22 05:26:57 +02009970 ret = base64dec(args[4], strlen(args[4]), trash.area, trash.size);
Willy Tarreau9d008692019-08-09 11:21:01 +02009971 if (ret < 0)
9972 return cli_err(appctx, "'set ssl tls-key' received invalid base64 encoded TLS key.\n");
Emeric Brun9e754772019-01-10 17:51:55 +01009973
Willy Tarreau1c913e42018-08-22 05:26:57 +02009974 trash.data = ret;
Willy Tarreau9d008692019-08-09 11:21:01 +02009975 if (ssl_sock_update_tlskey_ref(ref, &trash) < 0)
9976 return cli_err(appctx, "'set ssl tls-key' received a key of wrong size.\n");
William Lallemand32af2032016-10-29 18:09:35 +02009977
Willy Tarreau9d008692019-08-09 11:21:01 +02009978 return cli_msg(appctx, LOG_INFO, "TLS ticket key updated!\n");
William Lallemand32af2032016-10-29 18:09:35 +02009979}
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01009980#endif
William Lallemand32af2032016-10-29 18:09:35 +02009981
William Lallemand44b35322019-10-17 16:28:40 +02009982
9983/* Type of SSL payloads that can be updated over the CLI */
9984
9985enum {
9986 CERT_TYPE_PEM = 0,
Emmanuel Hocdetf6ac4fa2019-10-30 17:41:27 +01009987#if ((defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP) || defined OPENSSL_IS_BORINGSSL)
William Lallemand44b35322019-10-17 16:28:40 +02009988 CERT_TYPE_OCSP,
Emmanuel Hocdetf6ac4fa2019-10-30 17:41:27 +01009989#endif
William Lallemand44b35322019-10-17 16:28:40 +02009990 CERT_TYPE_ISSUER,
Emmanuel Hocdetf6ac4fa2019-10-30 17:41:27 +01009991#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
William Lallemand44b35322019-10-17 16:28:40 +02009992 CERT_TYPE_SCTL,
Emmanuel Hocdetf6ac4fa2019-10-30 17:41:27 +01009993#endif
William Lallemand44b35322019-10-17 16:28:40 +02009994 CERT_TYPE_MAX,
9995};
9996
9997struct {
9998 const char *ext;
9999 int type;
10000 int (*load)(const char *path, char *payload, struct cert_key_and_chain *ckch, char **err);
10001 /* add a parsing callback */
William Lallemandf29cdef2019-10-23 15:00:52 +020010002} cert_exts[CERT_TYPE_MAX+1] = {
William Lallemand44b35322019-10-17 16:28:40 +020010003 [CERT_TYPE_PEM] = { "", CERT_TYPE_PEM, &ssl_sock_load_pem_into_ckch }, /* default mode, no extensions */
William Lallemand541a5342019-10-23 14:11:54 +020010004#if ((defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP) || defined OPENSSL_IS_BORINGSSL)
William Lallemand44b35322019-10-17 16:28:40 +020010005 [CERT_TYPE_OCSP] = { "ocsp", CERT_TYPE_OCSP, &ssl_sock_load_ocsp_response_from_file },
William Lallemand541a5342019-10-23 14:11:54 +020010006#endif
10007#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
William Lallemand44b35322019-10-17 16:28:40 +020010008 [CERT_TYPE_SCTL] = { "sctl", CERT_TYPE_SCTL, &ssl_sock_load_sctl_from_file },
William Lallemand541a5342019-10-23 14:11:54 +020010009#endif
William Lallemand44b35322019-10-17 16:28:40 +020010010 [CERT_TYPE_ISSUER] = { "issuer", CERT_TYPE_ISSUER, &ssl_sock_load_issuer_file_into_ckch },
William Lallemandf29cdef2019-10-23 15:00:52 +020010011 [CERT_TYPE_MAX] = { NULL, CERT_TYPE_MAX, NULL },
William Lallemand44b35322019-10-17 16:28:40 +020010012};
10013
William Lallemand430413e2019-10-28 14:30:47 +010010014/* states of the CLI IO handler for 'set ssl cert' */
10015enum {
10016 SETCERT_ST_INIT = 0,
10017 SETCERT_ST_GEN,
10018 SETCERT_ST_INSERT,
10019 SETCERT_ST_FIN,
10020};
William Lallemand8f840d72019-10-23 10:53:05 +020010021
William Lallemand430413e2019-10-28 14:30:47 +010010022/* release function of the `set ssl cert' command, free things and unlock the spinlock */
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010023static void cli_release_commit_cert(struct appctx *appctx)
William Lallemand8f840d72019-10-23 10:53:05 +020010024{
10025 struct ckch_store *new_ckchs;
10026 struct ckch_inst *ckchi, *ckchis;
William Lallemand8f840d72019-10-23 10:53:05 +020010027
William Lallemand430413e2019-10-28 14:30:47 +010010028 HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
William Lallemand8f840d72019-10-23 10:53:05 +020010029
William Lallemand430413e2019-10-28 14:30:47 +010010030 if (appctx->st2 != SETCERT_ST_FIN) {
William Lallemand8f840d72019-10-23 10:53:05 +020010031 /* free every new sni_ctx and the new store, which are not in the trees so no spinlock there */
William Lallemandbeea2a42019-10-30 17:45:33 +010010032 new_ckchs = appctx->ctx.ssl.new_ckchs;
William Lallemand8f840d72019-10-23 10:53:05 +020010033
William Lallemandbeea2a42019-10-30 17:45:33 +010010034 if (!new_ckchs)
10035 return;
William Lallemand8f840d72019-10-23 10:53:05 +020010036
William Lallemandbeea2a42019-10-30 17:45:33 +010010037 /* if the allocation failed, we need to free everything from the temporary list */
10038 list_for_each_entry_safe(ckchi, ckchis, &new_ckchs->ckch_inst, by_ckchs) {
10039 struct sni_ctx *sc0, *sc0s;
William Lallemand8f840d72019-10-23 10:53:05 +020010040
William Lallemandbeea2a42019-10-30 17:45:33 +010010041 list_for_each_entry_safe(sc0, sc0s, &ckchi->sni_ctx, by_ckch_inst) {
10042 if (sc0->order == 0) /* we only free if it's the first inserted */
10043 SSL_CTX_free(sc0->ctx);
10044 LIST_DEL(&sc0->by_ckch_inst);
10045 free(sc0);
William Lallemand8f840d72019-10-23 10:53:05 +020010046 }
William Lallemandbeea2a42019-10-30 17:45:33 +010010047 LIST_DEL(&ckchi->by_ckchs);
10048 free(ckchi);
William Lallemand8f840d72019-10-23 10:53:05 +020010049 }
William Lallemandbeea2a42019-10-30 17:45:33 +010010050 ckchs_free(new_ckchs);
William Lallemand8f840d72019-10-23 10:53:05 +020010051 }
10052}
10053
10054
10055/*
10056 * This function tries to create the new ckch_inst and their SNIs
10057 */
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010058static int cli_io_handler_commit_cert(struct appctx *appctx)
William Lallemand8f840d72019-10-23 10:53:05 +020010059{
10060 struct stream_interface *si = appctx->owner;
10061 int y = 0;
10062 char *err = NULL;
10063 int errcode = 0;
10064 struct ckch_store *old_ckchs, *new_ckchs = NULL;
10065 struct ckch_inst *ckchi, *ckchis;
William Lallemand8f840d72019-10-23 10:53:05 +020010066 struct buffer *trash = alloc_trash_chunk();
William Lallemand8ef0c2a2019-11-21 16:30:34 +010010067 struct sni_ctx *sc0, *sc0s;
William Lallemand8f840d72019-10-23 10:53:05 +020010068
William Lallemand33cc76f2019-10-31 11:43:45 +010010069 if (trash == NULL)
10070 goto error;
10071
William Lallemand8f840d72019-10-23 10:53:05 +020010072 if (unlikely(si_ic(si)->flags & (CF_WRITE_ERROR|CF_SHUTW)))
10073 goto error;
10074
William Lallemand430413e2019-10-28 14:30:47 +010010075 while (1) {
10076 switch (appctx->st2) {
10077 case SETCERT_ST_INIT:
10078 /* This state just print the update message */
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010079 chunk_printf(trash, "Committing %s", ckchs_transaction.path);
William Lallemand430413e2019-10-28 14:30:47 +010010080 if (ci_putchk(si_ic(si), trash) == -1) {
10081 si_rx_room_blk(si);
William Lallemand8f840d72019-10-23 10:53:05 +020010082 goto yield;
William Lallemand430413e2019-10-28 14:30:47 +010010083 }
10084 appctx->st2 = SETCERT_ST_GEN;
10085 /* fallthrough */
10086 case SETCERT_ST_GEN:
10087 /*
10088 * This state generates the ckch instances with their
10089 * sni_ctxs and SSL_CTX.
10090 *
William Lallemand430413e2019-10-28 14:30:47 +010010091 * Since the SSL_CTX generation can be CPU consumer, we
10092 * yield every 10 instances.
10093 */
William Lallemand8f840d72019-10-23 10:53:05 +020010094
William Lallemandbeea2a42019-10-30 17:45:33 +010010095 old_ckchs = appctx->ctx.ssl.old_ckchs;
10096 new_ckchs = appctx->ctx.ssl.new_ckchs;
William Lallemand8f840d72019-10-23 10:53:05 +020010097
William Lallemandbeea2a42019-10-30 17:45:33 +010010098 if (!new_ckchs)
10099 continue;
William Lallemand8f840d72019-10-23 10:53:05 +020010100
William Lallemandbeea2a42019-10-30 17:45:33 +010010101 /* get the next ckchi to regenerate */
10102 ckchi = appctx->ctx.ssl.next_ckchi;
10103 /* we didn't start yet, set it to the first elem */
10104 if (ckchi == NULL)
10105 ckchi = LIST_ELEM(old_ckchs->ckch_inst.n, typeof(ckchi), by_ckchs);
William Lallemand8f840d72019-10-23 10:53:05 +020010106
William Lallemandbeea2a42019-10-30 17:45:33 +010010107 /* walk through the old ckch_inst and creates new ckch_inst using the updated ckchs */
10108 list_for_each_entry_from(ckchi, &old_ckchs->ckch_inst, by_ckchs) {
10109 struct ckch_inst *new_inst;
William Lallemand8ef0c2a2019-11-21 16:30:34 +010010110 int verify = 0;
William Lallemand8f840d72019-10-23 10:53:05 +020010111
William Lallemandbeea2a42019-10-30 17:45:33 +010010112 /* it takes a lot of CPU to creates SSL_CTXs, so we yield every 10 CKCH instances */
10113 if (y >= 10) {
10114 /* save the next ckchi to compute */
10115 appctx->ctx.ssl.next_ckchi = ckchi;
10116 goto yield;
10117 }
William Lallemand8f840d72019-10-23 10:53:05 +020010118
William Lallemand8ef0c2a2019-11-21 16:30:34 +010010119 /* prevent ssl_sock_prepare_ctx() to do file access which is only for verify (crl/ca file) */
10120 verify = (ckchi->ssl_conf && ckchi->ssl_conf->verify) ? ckchi->ssl_conf->verify : ckchi->bind_conf->ssl_conf.verify;
10121 if (verify & SSL_VERIFY_PEER) {
10122 memprintf(&err, "%sCan't commit a certificate which use the 'verify' bind SSL option [%s:%d]\n", err ? err : "", ckchi->bind_conf->file, ckchi->bind_conf->line);
10123 errcode |= ERR_FATAL | ERR_ABORT;
10124 goto error;
10125 }
10126
10127
William Lallemandbeea2a42019-10-30 17:45:33 +010010128 if (new_ckchs->multi)
10129 errcode |= ckch_inst_new_load_multi_store(new_ckchs->path, new_ckchs, ckchi->bind_conf, ckchi->ssl_conf, NULL, 0, &new_inst, &err);
10130 else
10131 errcode |= ckch_inst_new_load_store(new_ckchs->path, new_ckchs, ckchi->bind_conf, ckchi->ssl_conf, NULL, 0, &new_inst, &err);
William Lallemand8f840d72019-10-23 10:53:05 +020010132
William Lallemandbeea2a42019-10-30 17:45:33 +010010133 if (errcode & ERR_CODE)
10134 goto error;
William Lallemand8f840d72019-10-23 10:53:05 +020010135
William Lallemand21724f02019-11-04 17:56:13 +010010136 /* if the previous ckchi was used as the default */
10137 if (ckchi->is_default)
10138 new_inst->is_default = 1;
10139
William Lallemand8ef0c2a2019-11-21 16:30:34 +010010140 /* we need to initialize the SSL_CTX generated */
10141 /* TODO: the prepare_ctx function need to be reworked to be safer there */
10142 list_for_each_entry_safe(sc0, sc0s, &ckchi->sni_ctx, by_ckch_inst) {
10143 if (!sc0->order) { /* we initiliazed only the first SSL_CTX because it's the same in the other sni_ctx's */
10144 errcode |= ssl_sock_prepare_ctx(ckchi->bind_conf, ckchi->ssl_conf, sc0->ctx, &err);
10145 if (errcode & ERR_CODE)
10146 goto error;
10147 }
10148 }
10149
10150
William Lallemandbeea2a42019-10-30 17:45:33 +010010151 /* display one dot per new instance */
10152 chunk_appendf(trash, ".");
10153 /* link the new ckch_inst to the duplicate */
10154 LIST_ADDQ(&new_ckchs->ckch_inst, &new_inst->by_ckchs);
10155 y++;
10156 }
William Lallemand430413e2019-10-28 14:30:47 +010010157 appctx->st2 = SETCERT_ST_INSERT;
10158 /* fallthrough */
10159 case SETCERT_ST_INSERT:
10160 /* The generation is finished, we can insert everything */
William Lallemand8f840d72019-10-23 10:53:05 +020010161
William Lallemandbeea2a42019-10-30 17:45:33 +010010162 old_ckchs = appctx->ctx.ssl.old_ckchs;
10163 new_ckchs = appctx->ctx.ssl.new_ckchs;
William Lallemand8f840d72019-10-23 10:53:05 +020010164
William Lallemandbeea2a42019-10-30 17:45:33 +010010165 if (!new_ckchs)
10166 continue;
William Lallemand430413e2019-10-28 14:30:47 +010010167
William Lallemand21724f02019-11-04 17:56:13 +010010168 /* First, we insert every new SNIs in the trees, also replace the default_ctx */
William Lallemandbeea2a42019-10-30 17:45:33 +010010169 list_for_each_entry_safe(ckchi, ckchis, &new_ckchs->ckch_inst, by_ckchs) {
10170 HA_RWLOCK_WRLOCK(SNI_LOCK, &ckchi->bind_conf->sni_lock);
10171 ssl_sock_load_cert_sni(ckchi, ckchi->bind_conf);
10172 HA_RWLOCK_WRUNLOCK(SNI_LOCK, &ckchi->bind_conf->sni_lock);
10173 }
William Lallemand8f840d72019-10-23 10:53:05 +020010174
William Lallemandbeea2a42019-10-30 17:45:33 +010010175 /* delete the old sni_ctx, the old ckch_insts and the ckch_store */
10176 list_for_each_entry_safe(ckchi, ckchis, &old_ckchs->ckch_inst, by_ckchs) {
William Lallemand430413e2019-10-28 14:30:47 +010010177
William Lallemandbeea2a42019-10-30 17:45:33 +010010178 HA_RWLOCK_WRLOCK(SNI_LOCK, &ckchi->bind_conf->sni_lock);
10179 list_for_each_entry_safe(sc0, sc0s, &ckchi->sni_ctx, by_ckch_inst) {
10180 ebmb_delete(&sc0->name);
10181 LIST_DEL(&sc0->by_ckch_inst);
10182 free(sc0);
William Lallemand430413e2019-10-28 14:30:47 +010010183 }
William Lallemandbeea2a42019-10-30 17:45:33 +010010184 HA_RWLOCK_WRUNLOCK(SNI_LOCK, &ckchi->bind_conf->sni_lock);
10185 LIST_DEL(&ckchi->by_ckchs);
10186 free(ckchi);
10187 }
William Lallemand8f840d72019-10-23 10:53:05 +020010188
William Lallemandbeea2a42019-10-30 17:45:33 +010010189 /* Replace the old ckchs by the new one */
10190 ebmb_delete(&old_ckchs->node);
10191 ckchs_free(old_ckchs);
10192 ebst_insert(&ckchs_tree, &new_ckchs->node);
William Lallemand430413e2019-10-28 14:30:47 +010010193 appctx->st2 = SETCERT_ST_FIN;
10194 /* fallthrough */
10195 case SETCERT_ST_FIN:
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010196 /* we achieved the transaction, we can set everything to NULL */
10197 free(ckchs_transaction.path);
10198 ckchs_transaction.path = NULL;
10199 ckchs_transaction.new_ckchs = NULL;
10200 ckchs_transaction.old_ckchs = NULL;
William Lallemand430413e2019-10-28 14:30:47 +010010201 goto end;
10202 }
William Lallemand8f840d72019-10-23 10:53:05 +020010203 }
William Lallemand430413e2019-10-28 14:30:47 +010010204end:
William Lallemand8f840d72019-10-23 10:53:05 +020010205
William Lallemanded442432019-11-21 16:41:07 +010010206 chunk_appendf(trash, "\n");
10207 if (errcode & ERR_WARN)
Tim Duesterhusc0e820c2019-11-23 23:52:30 +010010208 chunk_appendf(trash, "%s", err);
William Lallemanded442432019-11-21 16:41:07 +010010209 chunk_appendf(trash, "Success!\n");
William Lallemand430413e2019-10-28 14:30:47 +010010210 if (ci_putchk(si_ic(si), trash) == -1)
10211 si_rx_room_blk(si);
10212 free_trash_chunk(trash);
10213 /* success: call the release function and don't come back */
10214 return 1;
William Lallemand8f840d72019-10-23 10:53:05 +020010215yield:
10216 /* store the state */
10217 if (ci_putchk(si_ic(si), trash) == -1)
10218 si_rx_room_blk(si);
10219 free_trash_chunk(trash);
10220 si_rx_endp_more(si); /* let's come back later */
William Lallemand8f840d72019-10-23 10:53:05 +020010221 return 0; /* should come back */
10222
10223error:
10224 /* spin unlock and free are done in the release function */
William Lallemand33cc76f2019-10-31 11:43:45 +010010225 if (trash) {
10226 chunk_appendf(trash, "\n%sFailed!\n", err);
10227 if (ci_putchk(si_ic(si), trash) == -1)
10228 si_rx_room_blk(si);
10229 free_trash_chunk(trash);
10230 }
William Lallemand430413e2019-10-28 14:30:47 +010010231 /* error: call the release function and don't come back */
10232 return 1;
William Lallemand8f840d72019-10-23 10:53:05 +020010233}
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010234
10235/*
10236 * Parsing function of 'commit ssl cert'
10237 */
10238static int cli_parse_commit_cert(char **args, char *payload, struct appctx *appctx, void *private)
10239{
10240 char *err = NULL;
10241
10242 if (!*args[3])
10243 return cli_err(appctx, "'commit ssl cert expects a filename\n");
10244
10245 /* The operations on the CKCH architecture are locked so we can
10246 * manipulate ckch_store and ckch_inst */
10247 if (HA_SPIN_TRYLOCK(CKCH_LOCK, &ckch_lock))
10248 return cli_err(appctx, "Can't commit the certificate!\nOperations on certificates are currently locked!\n");
10249
10250 if (!ckchs_transaction.path) {
10251 memprintf(&err, "No ongoing transaction! !\n");
10252 goto error;
10253 }
10254
10255 if (strcmp(ckchs_transaction.path, args[3]) != 0) {
10256 memprintf(&err, "The ongoing transaction is about '%s' but you are trying to set '%s'\n", ckchs_transaction.path, args[3]);
10257 goto error;
10258 }
10259
10260 /* init the appctx structure */
10261 appctx->st2 = SETCERT_ST_INIT;
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010262 appctx->ctx.ssl.next_ckchi = NULL;
10263 appctx->ctx.ssl.new_ckchs = ckchs_transaction.new_ckchs;
10264 appctx->ctx.ssl.old_ckchs = ckchs_transaction.old_ckchs;
10265
10266 /* we don't unlock there, it will be unlock after the IO handler, in the release handler */
10267 return 0;
10268
10269error:
10270
10271 HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
10272 err = memprintf(&err, "%sCan't commit %s!\n", err ? err : "", args[3]);
10273
10274 return cli_dynerr(appctx, err);
10275}
10276
10277
William Lallemand8f840d72019-10-23 10:53:05 +020010278/*
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010279 * Parsing function of `set ssl cert`, it updates or creates a temporary ckch.
William Lallemand8f840d72019-10-23 10:53:05 +020010280 */
William Lallemand150bfa82019-09-19 17:12:49 +020010281static int cli_parse_set_cert(char **args, char *payload, struct appctx *appctx, void *private)
10282{
William Lallemand0c3b7d92019-10-18 11:27:07 +020010283 struct ckch_store *new_ckchs = NULL;
William Lallemand8f840d72019-10-23 10:53:05 +020010284 struct ckch_store *old_ckchs = NULL;
William Lallemand150bfa82019-09-19 17:12:49 +020010285 char *err = NULL;
William Lallemand963b2e72019-10-14 11:38:36 +020010286 int i;
William Lallemand849eed62019-10-17 16:23:50 +020010287 int bundle = -1; /* TRUE if >= 0 (ckch index) */
Emeric Brunf69ed1d2019-10-17 11:56:56 +020010288 int errcode = 0;
William Lallemand44b35322019-10-17 16:28:40 +020010289 char *end;
10290 int type = CERT_TYPE_PEM;
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010291 struct cert_key_and_chain *ckch;
10292 struct buffer *buf;
William Lallemand8f840d72019-10-23 10:53:05 +020010293
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010294 if ((buf = alloc_trash_chunk()) == NULL)
10295 return cli_err(appctx, "Can't allocate memory\n");
William Lallemand150bfa82019-09-19 17:12:49 +020010296
10297 if (!*args[3] || !payload)
10298 return cli_err(appctx, "'set ssl cert expects a filename and a certificat as a payload\n");
10299
10300 /* The operations on the CKCH architecture are locked so we can
10301 * manipulate ckch_store and ckch_inst */
10302 if (HA_SPIN_TRYLOCK(CKCH_LOCK, &ckch_lock))
10303 return cli_err(appctx, "Can't update the certificate!\nOperations on certificates are currently locked!\n");
10304
William Lallemand8f840d72019-10-23 10:53:05 +020010305 if (!chunk_strcpy(buf, args[3])) {
10306 memprintf(&err, "%sCan't allocate memory\n", err ? err : "");
10307 errcode |= ERR_ALERT | ERR_FATAL;
10308 goto end;
10309 }
10310
William Lallemand44b35322019-10-17 16:28:40 +020010311 /* check which type of file we want to update */
William Lallemandf29cdef2019-10-23 15:00:52 +020010312 for (i = 0; cert_exts[i].type < CERT_TYPE_MAX; i++) {
William Lallemand8f840d72019-10-23 10:53:05 +020010313 end = strrchr(buf->area, '.');
William Lallemand44b35322019-10-17 16:28:40 +020010314 if (end && *cert_exts[i].ext && (!strcmp(end + 1, cert_exts[i].ext))) {
10315 *end = '\0';
10316 type = cert_exts[i].type;
10317 break;
10318 }
10319 }
10320
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010321 appctx->ctx.ssl.old_ckchs = NULL;
10322 appctx->ctx.ssl.new_ckchs = NULL;
William Lallemand849eed62019-10-17 16:23:50 +020010323
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010324 /* if there is an ongoing transaction */
10325 if (ckchs_transaction.path) {
10326 /* if the ongoing transaction is a bundle, we need to find which part of the bundle need to be updated */
William Lallemand963b2e72019-10-14 11:38:36 +020010327#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010328 if (ckchs_transaction.new_ckchs->multi) {
Emmanuel Hocdet40f2f1e2019-10-30 17:31:28 +010010329 char *end;
William Lallemand963b2e72019-10-14 11:38:36 +020010330 int j;
William Lallemand150bfa82019-09-19 17:12:49 +020010331
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010332 /* check if it was used in a bundle by removing the
William Lallemand963b2e72019-10-14 11:38:36 +020010333 * .dsa/.rsa/.ecdsa at the end of the filename */
William Lallemand8f840d72019-10-23 10:53:05 +020010334 end = strrchr(buf->area, '.');
Emmanuel Hocdet40f2f1e2019-10-30 17:31:28 +010010335 for (j = 0; end && j < SSL_SOCK_NUM_KEYTYPES; j++) {
William Lallemand963b2e72019-10-14 11:38:36 +020010336 if (!strcmp(end + 1, SSL_SOCK_KEYTYPE_NAMES[j])) {
10337 bundle = j; /* keep the type of certificate so we insert it at the right place */
10338 *end = '\0'; /* it's a bundle let's end the string*/
10339 break;
10340 }
William Lallemand150bfa82019-09-19 17:12:49 +020010341 }
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010342 if (bundle < 0) {
10343 memprintf(&err, "The ongoing transaction is the '%s' bundle. You need to specify which part of the bundle you want to update ('%s.{rsa,ecdsa,dsa}')\n", ckchs_transaction.path, buf->area);
10344 errcode |= ERR_ALERT | ERR_FATAL;
10345 goto end;
10346 }
10347 }
10348#endif
10349
10350 /* if there is an ongoing transaction, check if this is the same file */
10351 if (strcmp(ckchs_transaction.path, buf->area) != 0) {
10352 memprintf(&err, "The ongoing transaction is about '%s' but you are trying to set '%s'\n", ckchs_transaction.path, buf->area);
10353 errcode |= ERR_ALERT | ERR_FATAL;
10354 goto end;
William Lallemand150bfa82019-09-19 17:12:49 +020010355 }
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010356
10357 appctx->ctx.ssl.old_ckchs = ckchs_transaction.new_ckchs;
10358
10359 } else {
10360 struct ckch_store *find_ckchs[2] = { NULL, NULL };
10361
10362 /* lookup for the certificate in the tree:
10363 * check if this is used as a bundle AND as a unique certificate */
10364 for (i = 0; i < 2; i++) {
10365
10366 if ((find_ckchs[i] = ckchs_lookup(buf->area)) != NULL) {
10367 /* only the bundle name is in the tree and you should
10368 * never update a bundle name, only a filename */
10369 if (bundle < 0 && find_ckchs[i]->multi) {
10370 /* we tried to look for a non-bundle and we found a bundle */
10371 memprintf(&err, "%s%s is a multi-cert bundle. Try updating %s.{dsa,rsa,ecdsa}\n",
10372 err ? err : "", args[3], args[3]);
10373 errcode |= ERR_ALERT | ERR_FATAL;
10374 goto end;
10375 }
William Lallemand3246d942019-11-04 14:02:11 +010010376 /* If we want a bundle but this is not a bundle
10377 * example: When you try to update <file>.rsa, but
10378 * <file> is a regular file */
10379 if (bundle >= 0 && find_ckchs[i]->multi == 0) {
10380 find_ckchs[i] = NULL;
10381 break;
10382 }
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010383 }
10384#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
10385 {
Emmanuel Hocdet40f2f1e2019-10-30 17:31:28 +010010386 char *end;
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010387 int j;
10388
10389 /* check if it was used in a bundle by removing the
10390 * .dsa/.rsa/.ecdsa at the end of the filename */
10391 end = strrchr(buf->area, '.');
Emmanuel Hocdet40f2f1e2019-10-30 17:31:28 +010010392 for (j = 0; end && j < SSL_SOCK_NUM_KEYTYPES; j++) {
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010393 if (!strcmp(end + 1, SSL_SOCK_KEYTYPE_NAMES[j])) {
10394 bundle = j; /* keep the type of certificate so we insert it at the right place */
10395 *end = '\0'; /* it's a bundle let's end the string*/
10396 break;
10397 }
10398 }
William Lallemand37031b82019-11-04 13:38:53 +010010399 if (bundle < 0) /* we didn't find a bundle extension */
10400 break;
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010401 }
William Lallemand963b2e72019-10-14 11:38:36 +020010402#else
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010403 /* bundles are not supported here, so we don't need to lookup again */
10404 break;
William Lallemand963b2e72019-10-14 11:38:36 +020010405#endif
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010406 }
10407
10408 if (find_ckchs[0] && find_ckchs[1]) {
10409 memprintf(&err, "%sUpdating a certificate which is used in the HAProxy configuration as a bundle and as a unique certificate is not supported. ('%s' and '%s')\n",
10410 err ? err : "", find_ckchs[0]->path, find_ckchs[1]->path);
10411 errcode |= ERR_ALERT | ERR_FATAL;
10412 goto end;
10413 }
10414
10415 appctx->ctx.ssl.old_ckchs = find_ckchs[0] ? find_ckchs[0] : find_ckchs[1];
William Lallemand150bfa82019-09-19 17:12:49 +020010416 }
10417
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010418 if (!appctx->ctx.ssl.old_ckchs) {
10419 memprintf(&err, "%sCan't replace a certificate which is not referenced by the configuration!\n",
William Lallemand150bfa82019-09-19 17:12:49 +020010420 err ? err : "");
Emeric Brunf69ed1d2019-10-17 11:56:56 +020010421 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemand8f840d72019-10-23 10:53:05 +020010422 goto end;
William Lallemand150bfa82019-09-19 17:12:49 +020010423 }
10424
William Lallemand8a7fdf02019-11-04 10:59:32 +010010425 if (!appctx->ctx.ssl.path) {
10426 /* this is a new transaction, set the path of the transaction */
10427 appctx->ctx.ssl.path = strdup(appctx->ctx.ssl.old_ckchs->path);
10428 if (!appctx->ctx.ssl.path) {
10429 memprintf(&err, "%sCan't allocate memory\n", err ? err : "");
10430 errcode |= ERR_ALERT | ERR_FATAL;
10431 goto end;
10432 }
10433 }
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010434
10435 old_ckchs = appctx->ctx.ssl.old_ckchs;
10436
10437 /* TODO: handle filters */
10438 if (old_ckchs->filters) {
10439 memprintf(&err, "%sCertificates used in crt-list with filters are not supported!\n",
10440 err ? err : "");
10441 errcode |= ERR_ALERT | ERR_FATAL;
10442 goto end;
10443 }
10444
10445 /* duplicate the ckch store */
10446 new_ckchs = ckchs_dup(old_ckchs);
10447 if (!new_ckchs) {
10448 memprintf(&err, "%sCannot allocate memory!\n",
10449 err ? err : "");
10450 errcode |= ERR_ALERT | ERR_FATAL;
10451 goto end;
10452 }
10453
10454 if (!new_ckchs->multi)
10455 ckch = new_ckchs->ckch;
10456 else
10457 ckch = &new_ckchs->ckch[bundle];
10458
10459 /* appply the change on the duplicate */
10460 if (cert_exts[type].load(buf->area, payload, ckch, &err) != 0) {
10461 memprintf(&err, "%sCan't load the payload\n", err ? err : "");
10462 errcode |= ERR_ALERT | ERR_FATAL;
10463 goto end;
10464 }
10465
10466 appctx->ctx.ssl.new_ckchs = new_ckchs;
10467
10468 /* we succeed, we can save the ckchs in the transaction */
10469
10470 /* if there wasn't a transaction, update the old ckchs */
William Dauchyc8bb1532019-11-24 15:04:20 +010010471 if (!ckchs_transaction.old_ckchs) {
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010472 ckchs_transaction.old_ckchs = appctx->ctx.ssl.old_ckchs;
10473 ckchs_transaction.path = appctx->ctx.ssl.path;
10474 err = memprintf(&err, "Transaction created for certificate %s!\n", ckchs_transaction.path);
10475 } else {
10476 err = memprintf(&err, "Transaction updated for certificate %s!\n", ckchs_transaction.path);
10477
10478 }
10479
10480 /* free the previous ckchs if there was a transaction */
10481 ckchs_free(ckchs_transaction.new_ckchs);
10482
10483 ckchs_transaction.new_ckchs = appctx->ctx.ssl.new_ckchs;
10484
10485
William Lallemand8f840d72019-10-23 10:53:05 +020010486 /* creates the SNI ctxs later in the IO handler */
William Lallemand150bfa82019-09-19 17:12:49 +020010487
William Lallemand8f840d72019-10-23 10:53:05 +020010488end:
10489 free_trash_chunk(buf);
William Lallemand150bfa82019-09-19 17:12:49 +020010490
Emeric Brunf69ed1d2019-10-17 11:56:56 +020010491 if (errcode & ERR_CODE) {
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010492
10493 ckchs_free(appctx->ctx.ssl.new_ckchs);
10494 appctx->ctx.ssl.new_ckchs = NULL;
10495
10496 appctx->ctx.ssl.old_ckchs = NULL;
10497
10498 free(appctx->ctx.ssl.path);
10499 appctx->ctx.ssl.path = NULL;
10500
10501 HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
William Lallemand44b35322019-10-17 16:28:40 +020010502 return cli_dynerr(appctx, memprintf(&err, "%sCan't update %s!\n", err ? err : "", args[3]));
William Lallemand430413e2019-10-28 14:30:47 +010010503 } else {
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010504
10505 HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
10506 return cli_dynmsg(appctx, LOG_NOTICE, err);
William Lallemand430413e2019-10-28 14:30:47 +010010507 }
William Lallemand8f840d72019-10-23 10:53:05 +020010508 /* TODO: handle the ERR_WARN which are not handled because of the io_handler */
William Lallemand150bfa82019-09-19 17:12:49 +020010509}
10510
William Lallemand0bc9c8a2019-11-19 15:51:51 +010010511/* parsing function of 'abort ssl cert' */
10512static int cli_parse_abort_cert(char **args, char *payload, struct appctx *appctx, void *private)
10513{
10514 char *err = NULL;
10515
10516 if (!*args[3])
10517 return cli_err(appctx, "'abort ssl cert' expects a filename\n");
10518
10519 /* The operations on the CKCH architecture are locked so we can
10520 * manipulate ckch_store and ckch_inst */
10521 if (HA_SPIN_TRYLOCK(CKCH_LOCK, &ckch_lock))
10522 return cli_err(appctx, "Can't abort!\nOperations on certificates are currently locked!\n");
10523
10524 if (!ckchs_transaction.path) {
10525 memprintf(&err, "No ongoing transaction!\n");
10526 goto error;
10527 }
10528
10529 if (strcmp(ckchs_transaction.path, args[3]) != 0) {
10530 memprintf(&err, "The ongoing transaction is about '%s' but you are trying to abort a transaction for '%s'\n", ckchs_transaction.path, args[3]);
10531 goto error;
10532 }
10533
10534 /* Only free the ckchs there, because the SNI and instances were not generated yet */
10535 ckchs_free(ckchs_transaction.new_ckchs);
10536 ckchs_transaction.new_ckchs = NULL;
10537 ckchs_free(ckchs_transaction.old_ckchs);
10538 ckchs_transaction.old_ckchs = NULL;
10539 free(ckchs_transaction.path);
10540 ckchs_transaction.path = NULL;
10541
10542 HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
10543
10544 err = memprintf(&err, "Transaction aborted for certificate '%s'!\n", args[3]);
10545 return cli_dynmsg(appctx, LOG_NOTICE, err);
10546
10547error:
10548 HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
10549
10550 return cli_dynerr(appctx, err);
10551}
10552
Aurélien Nephtaliabbf6072018-04-18 13:26:46 +020010553static int cli_parse_set_ocspresponse(char **args, char *payload, struct appctx *appctx, void *private)
William Lallemand32af2032016-10-29 18:09:35 +020010554{
10555#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
10556 char *err = NULL;
Willy Tarreau1c913e42018-08-22 05:26:57 +020010557 int i, j, ret;
Aurélien Nephtali1e0867c2018-04-18 14:04:58 +020010558
10559 if (!payload)
10560 payload = args[3];
William Lallemand32af2032016-10-29 18:09:35 +020010561
10562 /* Expect one parameter: the new response in base64 encoding */
Willy Tarreau9d008692019-08-09 11:21:01 +020010563 if (!*payload)
10564 return cli_err(appctx, "'set ssl ocsp-response' expects response in base64 encoding.\n");
Aurélien Nephtali1e0867c2018-04-18 14:04:58 +020010565
10566 /* remove \r and \n from the payload */
10567 for (i = 0, j = 0; payload[i]; i++) {
10568 if (payload[i] == '\r' || payload[i] == '\n')
10569 continue;
10570 payload[j++] = payload[i];
10571 }
10572 payload[j] = 0;
William Lallemand32af2032016-10-29 18:09:35 +020010573
Willy Tarreau1c913e42018-08-22 05:26:57 +020010574 ret = base64dec(payload, j, trash.area, trash.size);
Willy Tarreau9d008692019-08-09 11:21:01 +020010575 if (ret < 0)
10576 return cli_err(appctx, "'set ssl ocsp-response' received invalid base64 encoded response.\n");
William Lallemand32af2032016-10-29 18:09:35 +020010577
Willy Tarreau1c913e42018-08-22 05:26:57 +020010578 trash.data = ret;
William Lallemand32af2032016-10-29 18:09:35 +020010579 if (ssl_sock_update_ocsp_response(&trash, &err)) {
Willy Tarreau9d008692019-08-09 11:21:01 +020010580 if (err)
10581 return cli_dynerr(appctx, memprintf(&err, "%s.\n", err));
10582 else
10583 return cli_err(appctx, "Failed to update OCSP response.\n");
William Lallemand32af2032016-10-29 18:09:35 +020010584 }
Willy Tarreau9d008692019-08-09 11:21:01 +020010585
10586 return cli_msg(appctx, LOG_INFO, "OCSP Response updated!\n");
William Lallemand32af2032016-10-29 18:09:35 +020010587#else
Willy Tarreau9d008692019-08-09 11:21:01 +020010588 return cli_err(appctx, "HAProxy was compiled against a version of OpenSSL that doesn't support OCSP stapling.\n");
William Lallemand32af2032016-10-29 18:09:35 +020010589#endif
10590
Nenad Merdanovicc31499d2019-03-23 11:00:32 +010010591}
10592
Willy Tarreau86a394e2019-05-09 14:15:32 +020010593#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000100fL)
Nenad Merdanovicc31499d2019-03-23 11:00:32 +010010594static inline int sample_conv_var2smp_str(const struct arg *arg, struct sample *smp)
10595{
10596 switch (arg->type) {
10597 case ARGT_STR:
10598 smp->data.type = SMP_T_STR;
10599 smp->data.u.str = arg->data.str;
10600 return 1;
10601 case ARGT_VAR:
10602 if (!vars_get_by_desc(&arg->data.var, smp))
10603 return 0;
10604 if (!sample_casts[smp->data.type][SMP_T_STR])
10605 return 0;
10606 if (!sample_casts[smp->data.type][SMP_T_STR](smp))
10607 return 0;
10608 return 1;
10609 default:
10610 return 0;
10611 }
10612}
10613
10614static int check_aes_gcm(struct arg *args, struct sample_conv *conv,
10615 const char *file, int line, char **err)
10616{
10617 switch(args[0].data.sint) {
10618 case 128:
10619 case 192:
10620 case 256:
10621 break;
10622 default:
10623 memprintf(err, "key size must be 128, 192 or 256 (bits).");
10624 return 0;
10625 }
10626 /* Try to decode a variable. */
10627 vars_check_arg(&args[1], NULL);
10628 vars_check_arg(&args[2], NULL);
10629 vars_check_arg(&args[3], NULL);
10630 return 1;
10631}
10632
10633/* Arguements: AES size in bits, nonce, key, tag. The last three arguments are base64 encoded */
10634static int sample_conv_aes_gcm_dec(const struct arg *arg_p, struct sample *smp, void *private)
10635{
10636 struct sample nonce, key, aead_tag;
10637 struct buffer *smp_trash, *smp_trash_alloc;
10638 EVP_CIPHER_CTX *ctx;
10639 int dec_size, ret;
10640
10641 smp_set_owner(&nonce, smp->px, smp->sess, smp->strm, smp->opt);
10642 if (!sample_conv_var2smp_str(&arg_p[1], &nonce))
10643 return 0;
10644
10645 smp_set_owner(&key, smp->px, smp->sess, smp->strm, smp->opt);
10646 if (!sample_conv_var2smp_str(&arg_p[2], &key))
10647 return 0;
10648
10649 smp_set_owner(&aead_tag, smp->px, smp->sess, smp->strm, smp->opt);
10650 if (!sample_conv_var2smp_str(&arg_p[3], &aead_tag))
10651 return 0;
10652
10653 smp_trash = get_trash_chunk();
10654 smp_trash_alloc = alloc_trash_chunk();
10655 if (!smp_trash_alloc)
10656 return 0;
10657
10658 ctx = EVP_CIPHER_CTX_new();
10659
10660 if (!ctx)
10661 goto err;
10662
10663 dec_size = base64dec(nonce.data.u.str.area, nonce.data.u.str.data, smp_trash->area, smp_trash->size);
10664 if (dec_size < 0)
10665 goto err;
10666 smp_trash->data = dec_size;
10667
10668 /* Set cipher type and mode */
10669 switch(arg_p[0].data.sint) {
10670 case 128:
10671 EVP_DecryptInit_ex(ctx, EVP_aes_128_gcm(), NULL, NULL, NULL);
10672 break;
10673 case 192:
10674 EVP_DecryptInit_ex(ctx, EVP_aes_192_gcm(), NULL, NULL, NULL);
10675 break;
10676 case 256:
10677 EVP_DecryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL);
10678 break;
10679 }
10680
10681 EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, smp_trash->data, NULL);
10682
10683 /* Initialise IV */
10684 if(!EVP_DecryptInit_ex(ctx, NULL, NULL, NULL, (unsigned char *) smp_trash->area))
10685 goto err;
10686
10687 dec_size = base64dec(key.data.u.str.area, key.data.u.str.data, smp_trash->area, smp_trash->size);
10688 if (dec_size < 0)
10689 goto err;
10690 smp_trash->data = dec_size;
10691
10692 /* Initialise key */
10693 if (!EVP_DecryptInit_ex(ctx, NULL, NULL, (unsigned char *) smp_trash->area, NULL))
10694 goto err;
10695
10696 if (!EVP_DecryptUpdate(ctx, (unsigned char *) smp_trash->area, (int *) &smp_trash->data,
10697 (unsigned char *) smp->data.u.str.area, (int) smp->data.u.str.data))
10698 goto err;
10699
10700 dec_size = base64dec(aead_tag.data.u.str.area, aead_tag.data.u.str.data, smp_trash_alloc->area, smp_trash_alloc->size);
10701 if (dec_size < 0)
10702 goto err;
10703 smp_trash_alloc->data = dec_size;
10704 dec_size = smp_trash->data;
10705
10706 EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, smp_trash_alloc->data, (void *) smp_trash_alloc->area);
10707 ret = EVP_DecryptFinal_ex(ctx, (unsigned char *) smp_trash->area + smp_trash->data, (int *) &smp_trash->data);
10708
10709 if (ret <= 0)
10710 goto err;
10711
10712 smp->data.u.str.data = dec_size + smp_trash->data;
10713 smp->data.u.str.area = smp_trash->area;
10714 smp->data.type = SMP_T_BIN;
10715 smp->flags &= ~SMP_F_CONST;
10716 free_trash_chunk(smp_trash_alloc);
10717 return 1;
10718
10719err:
10720 free_trash_chunk(smp_trash_alloc);
10721 return 0;
William Lallemand32af2032016-10-29 18:09:35 +020010722}
Nenad Merdanovicc31499d2019-03-23 11:00:32 +010010723# endif
William Lallemand32af2032016-10-29 18:09:35 +020010724
10725/* register cli keywords */
10726static struct cli_kw_list cli_kws = {{ },{
10727#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
10728 { { "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 +020010729 { { "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 +020010730#endif
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +010010731 { { "set", "ssl", "ocsp-response", NULL }, NULL, cli_parse_set_ocspresponse, NULL },
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010732 { { "set", "ssl", "cert", NULL }, "set ssl cert <certfile> <payload> : replace a certificate file", cli_parse_set_cert, NULL, NULL },
10733 { { "commit", "ssl", "cert", NULL }, "commit ssl cert <certfile> : commit a certificate file", cli_parse_commit_cert, cli_io_handler_commit_cert, cli_release_commit_cert },
William Lallemand0bc9c8a2019-11-19 15:51:51 +010010734 { { "abort", "ssl", "cert", NULL }, "abort ssl cert <certfile> : abort a transaction for a certificate file", cli_parse_abort_cert, NULL, NULL },
William Lallemand32af2032016-10-29 18:09:35 +020010735 { { NULL }, NULL, NULL, NULL }
10736}};
10737
Willy Tarreau0108d902018-11-25 19:14:37 +010010738INITCALL1(STG_REGISTER, cli_register_kw, &cli_kws);
William Lallemand32af2032016-10-29 18:09:35 +020010739
Willy Tarreau7875d092012-09-10 08:20:03 +020010740/* Note: must not be declared <const> as its list will be overwritten.
10741 * Please take care of keeping this list alphabetically sorted.
10742 */
Willy Tarreaudc13c112013-06-21 23:16:39 +020010743static struct sample_fetch_kw_list sample_fetch_keywords = {ILH, {
Emeric Brun645ae792014-04-30 14:21:06 +020010744 { "ssl_bc", smp_fetch_ssl_fc, 0, NULL, SMP_T_BOOL, SMP_USE_L5SRV },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +020010745 { "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 +010010746#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Jérôme Magnine064a802018-12-03 22:21:04 +010010747 { "ssl_bc_alpn", smp_fetch_ssl_fc_alpn, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
Olivier Houchard6b77f492018-11-22 18:18:29 +010010748#endif
Emeric Brun645ae792014-04-30 14:21:06 +020010749 { "ssl_bc_cipher", smp_fetch_ssl_fc_cipher, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
Olivier Houchard6b77f492018-11-22 18:18:29 +010010750#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
10751 { "ssl_bc_npn", smp_fetch_ssl_fc_npn, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
10752#endif
Emeric Brun74f7ffa2018-02-19 16:14:12 +010010753 { "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 +020010754 { "ssl_bc_protocol", smp_fetch_ssl_fc_protocol, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
Emeric Brunb73a9b02014-04-30 18:49:19 +020010755 { "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 +020010756 { "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 +020010757#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
Emeric Brun645ae792014-04-30 14:21:06 +020010758 { "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 -040010759#endif
Emmanuel Hocdet839af572019-05-14 16:27:35 +020010760#if HA_OPENSSL_VERSION_NUMBER >= 0x10100000L
Patrick Hemmer65674662019-06-04 08:13:03 -040010761 { "ssl_bc_client_random", smp_fetch_ssl_fc_random, 0, NULL, SMP_T_BIN, SMP_USE_L5SRV },
10762 { "ssl_bc_server_random", smp_fetch_ssl_fc_random, 0, NULL, SMP_T_BIN, SMP_USE_L5SRV },
Patrick Hemmere0275472018-04-28 19:15:51 -040010763 { "ssl_bc_session_key", smp_fetch_ssl_fc_session_key, 0, NULL, SMP_T_BIN, SMP_USE_L5SRV },
10764#endif
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +020010765 { "ssl_c_ca_err", smp_fetch_ssl_c_ca_err, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
10766 { "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 +010010767 { "ssl_c_der", smp_fetch_ssl_x_der, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +020010768 { "ssl_c_err", smp_fetch_ssl_c_err, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Emeric Brunba841a12014-04-30 17:05:08 +020010769 { "ssl_c_i_dn", smp_fetch_ssl_x_i_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
10770 { "ssl_c_key_alg", smp_fetch_ssl_x_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
10771 { "ssl_c_notafter", smp_fetch_ssl_x_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
10772 { "ssl_c_notbefore", smp_fetch_ssl_x_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
10773 { "ssl_c_sig_alg", smp_fetch_ssl_x_sig_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
10774 { "ssl_c_s_dn", smp_fetch_ssl_x_s_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
10775 { "ssl_c_serial", smp_fetch_ssl_x_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
10776 { "ssl_c_sha1", smp_fetch_ssl_x_sha1, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +010010777 { "ssl_c_used", smp_fetch_ssl_c_used, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +020010778 { "ssl_c_verify", smp_fetch_ssl_c_verify, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
10779 { "ssl_c_version", smp_fetch_ssl_x_version, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Emeric Brun43e79582014-10-29 19:03:26 +010010780 { "ssl_f_der", smp_fetch_ssl_x_der, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Emeric Brunba841a12014-04-30 17:05:08 +020010781 { "ssl_f_i_dn", smp_fetch_ssl_x_i_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
10782 { "ssl_f_key_alg", smp_fetch_ssl_x_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
10783 { "ssl_f_notafter", smp_fetch_ssl_x_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
10784 { "ssl_f_notbefore", smp_fetch_ssl_x_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
10785 { "ssl_f_sig_alg", smp_fetch_ssl_x_sig_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
10786 { "ssl_f_s_dn", smp_fetch_ssl_x_s_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
10787 { "ssl_f_serial", smp_fetch_ssl_x_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Emeric Brun55f4fa82014-04-30 17:11:25 +020010788 { "ssl_f_sha1", smp_fetch_ssl_x_sha1, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +020010789 { "ssl_f_version", smp_fetch_ssl_x_version, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +010010790 { "ssl_fc", smp_fetch_ssl_fc, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +020010791 { "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 +010010792 { "ssl_fc_cipher", smp_fetch_ssl_fc_cipher, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +010010793 { "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 +020010794 { "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 +010010795 { "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 +020010796 { "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 +010010797#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +010010798 { "ssl_fc_npn", smp_fetch_ssl_fc_npn, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreaua33c6542012-10-15 13:19:06 +020010799#endif
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +010010800#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +010010801 { "ssl_fc_alpn", smp_fetch_ssl_fc_alpn, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreauab861d32013-04-02 02:30:41 +020010802#endif
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +010010803 { "ssl_fc_protocol", smp_fetch_ssl_fc_protocol, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreau9a1ab082019-05-09 13:26:41 +020010804#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
Emeric Brunb73a9b02014-04-30 18:49:19 +020010805 { "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 -040010806#endif
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +020010807 { "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 +020010808#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +010010809 { "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 -040010810#endif
Emmanuel Hocdet839af572019-05-14 16:27:35 +020010811#if HA_OPENSSL_VERSION_NUMBER >= 0x10100000L
Patrick Hemmer65674662019-06-04 08:13:03 -040010812 { "ssl_fc_client_random", smp_fetch_ssl_fc_random, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
10813 { "ssl_fc_server_random", smp_fetch_ssl_fc_random, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Patrick Hemmere0275472018-04-28 19:15:51 -040010814 { "ssl_fc_session_key", smp_fetch_ssl_fc_session_key, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
10815#endif
Patrick Hemmer41966772018-04-28 19:15:48 -040010816#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +010010817 { "ssl_fc_sni", smp_fetch_ssl_fc_sni, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Patrick Hemmer41966772018-04-28 19:15:48 -040010818#endif
Thierry FOURNIER5bf77322017-02-25 12:45:22 +010010819 { "ssl_fc_cipherlist_bin", smp_fetch_ssl_fc_cl_bin, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
10820 { "ssl_fc_cipherlist_hex", smp_fetch_ssl_fc_cl_hex, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
10821 { "ssl_fc_cipherlist_str", smp_fetch_ssl_fc_cl_str, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
10822 { "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 +020010823 { NULL, NULL, 0, 0, 0 },
10824}};
10825
Willy Tarreau0108d902018-11-25 19:14:37 +010010826INITCALL1(STG_REGISTER, sample_register_fetches, &sample_fetch_keywords);
10827
Willy Tarreau7875d092012-09-10 08:20:03 +020010828/* Note: must not be declared <const> as its list will be overwritten.
10829 * Please take care of keeping this list alphabetically sorted.
10830 */
Willy Tarreaudc13c112013-06-21 23:16:39 +020010831static struct acl_kw_list acl_kws = {ILH, {
Thierry FOURNIERc5a4e982014-03-05 16:07:08 +010010832 { "ssl_fc_sni_end", "ssl_fc_sni", PAT_MATCH_END },
10833 { "ssl_fc_sni_reg", "ssl_fc_sni", PAT_MATCH_REG },
Willy Tarreau8ed669b2013-01-11 15:49:37 +010010834 { /* END */ },
Willy Tarreau7875d092012-09-10 08:20:03 +020010835}};
10836
Willy Tarreau0108d902018-11-25 19:14:37 +010010837INITCALL1(STG_REGISTER, acl_register_keywords, &acl_kws);
10838
Willy Tarreau79eeafa2012-09-14 07:53:05 +020010839/* Note: must not be declared <const> as its list will be overwritten.
10840 * Please take care of keeping this list alphabetically sorted, doing so helps
10841 * all code contributors.
10842 * Optional keywords are also declared with a NULL ->parse() function so that
10843 * the config parser can report an appropriate error when a known keyword was
10844 * not enabled.
10845 */
Emmanuel Hocdet98263292016-12-29 18:26:15 +010010846static struct ssl_bind_kw ssl_bind_kws[] = {
Olivier Houchardc2aae742017-09-22 18:26:28 +020010847 { "allow-0rtt", ssl_bind_parse_allow_0rtt, 0 }, /* allow 0-RTT */
Emmanuel Hocdet98263292016-12-29 18:26:15 +010010848 { "alpn", ssl_bind_parse_alpn, 1 }, /* set ALPN supported protocols */
10849 { "ca-file", ssl_bind_parse_ca_file, 1 }, /* set CAfile to process verify on client cert */
10850 { "ciphers", ssl_bind_parse_ciphers, 1 }, /* set SSL cipher suite */
Emmanuel Hocdet839af572019-05-14 16:27:35 +020010851#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +020010852 { "ciphersuites", ssl_bind_parse_ciphersuites, 1 }, /* set TLS 1.3 cipher suite */
10853#endif
Emmanuel Hocdet98263292016-12-29 18:26:15 +010010854 { "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 +010010855 { "curves", ssl_bind_parse_curves, 1 }, /* set SSL curve suite */
Emmanuel Hocdet98263292016-12-29 18:26:15 +010010856 { "ecdhe", ssl_bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +020010857 { "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 +010010858 { "npn", ssl_bind_parse_npn, 1 }, /* set NPN supported protocols */
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +020010859 { "ssl-min-ver", ssl_bind_parse_tls_method_minmax,1 }, /* minimum version */
10860 { "ssl-max-ver", ssl_bind_parse_tls_method_minmax,1 }, /* maximum version */
Emmanuel Hocdet98263292016-12-29 18:26:15 +010010861 { "verify", ssl_bind_parse_verify, 1 }, /* set SSL verify method */
10862 { NULL, NULL, 0 },
10863};
10864
Willy Tarreau0108d902018-11-25 19:14:37 +010010865/* no initcall for ssl_bind_kws, these ones are parsed in the parser loop */
10866
Willy Tarreau51fb7652012-09-18 18:24:39 +020010867static struct bind_kw_list bind_kws = { "SSL", { }, {
Olivier Houchardc2aae742017-09-22 18:26:28 +020010868 { "allow-0rtt", bind_parse_allow_0rtt, 0 }, /* Allow 0RTT */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +020010869 { "alpn", bind_parse_alpn, 1 }, /* set ALPN supported protocols */
10870 { "ca-file", bind_parse_ca_file, 1 }, /* set CAfile to process verify on client cert */
10871 { "ca-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ignore on verify depth > 0 */
10872 { "ca-sign-file", bind_parse_ca_sign_file, 1 }, /* set CAFile used to generate and sign server certs */
10873 { "ca-sign-pass", bind_parse_ca_sign_pass, 1 }, /* set CAKey passphrase */
10874 { "ciphers", bind_parse_ciphers, 1 }, /* set SSL cipher suite */
Emmanuel Hocdet839af572019-05-14 16:27:35 +020010875#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +020010876 { "ciphersuites", bind_parse_ciphersuites, 1 }, /* set TLS 1.3 cipher suite */
10877#endif
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +020010878 { "crl-file", bind_parse_crl_file, 1 }, /* set certificat revocation list file use on client cert verify */
10879 { "crt", bind_parse_crt, 1 }, /* load SSL certificates from this location */
10880 { "crt-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ingore on verify depth == 0 */
10881 { "crt-list", bind_parse_crt_list, 1 }, /* load a list of crt from this location */
10882 { "curves", bind_parse_curves, 1 }, /* set SSL curve suite */
10883 { "ecdhe", bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
10884 { "force-sslv3", bind_parse_tls_method_options, 0 }, /* force SSLv3 */
10885 { "force-tlsv10", bind_parse_tls_method_options, 0 }, /* force TLSv10 */
10886 { "force-tlsv11", bind_parse_tls_method_options, 0 }, /* force TLSv11 */
10887 { "force-tlsv12", bind_parse_tls_method_options, 0 }, /* force TLSv12 */
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +020010888 { "force-tlsv13", bind_parse_tls_method_options, 0 }, /* force TLSv13 */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +020010889 { "generate-certificates", bind_parse_generate_certs, 0 }, /* enable the server certificates generation */
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +020010890 { "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 +020010891 { "no-sslv3", bind_parse_tls_method_options, 0 }, /* disable SSLv3 */
10892 { "no-tlsv10", bind_parse_tls_method_options, 0 }, /* disable TLSv10 */
10893 { "no-tlsv11", bind_parse_tls_method_options, 0 }, /* disable TLSv11 */
10894 { "no-tlsv12", bind_parse_tls_method_options, 0 }, /* disable TLSv12 */
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +020010895 { "no-tlsv13", bind_parse_tls_method_options, 0 }, /* disable TLSv13 */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +020010896 { "no-tls-tickets", bind_parse_no_tls_tickets, 0 }, /* disable session resumption tickets */
10897 { "ssl", bind_parse_ssl, 0 }, /* enable SSL processing */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +020010898 { "ssl-min-ver", bind_parse_tls_method_minmax, 1 }, /* minimum version */
10899 { "ssl-max-ver", bind_parse_tls_method_minmax, 1 }, /* maximum version */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +020010900 { "strict-sni", bind_parse_strict_sni, 0 }, /* refuse negotiation if sni doesn't match a certificate */
10901 { "tls-ticket-keys", bind_parse_tls_ticket_keys, 1 }, /* set file to load TLS ticket keys from */
10902 { "verify", bind_parse_verify, 1 }, /* set SSL verify method */
10903 { "npn", bind_parse_npn, 1 }, /* set NPN supported protocols */
10904 { "prefer-client-ciphers", bind_parse_pcc, 0 }, /* prefer client ciphers */
Willy Tarreau79eeafa2012-09-14 07:53:05 +020010905 { NULL, NULL, 0 },
10906}};
Emeric Brun46591952012-05-18 15:47:34 +020010907
Willy Tarreau0108d902018-11-25 19:14:37 +010010908INITCALL1(STG_REGISTER, bind_register_keywords, &bind_kws);
10909
Willy Tarreau92faadf2012-10-10 23:04:25 +020010910/* Note: must not be declared <const> as its list will be overwritten.
10911 * Please take care of keeping this list alphabetically sorted, doing so helps
10912 * all code contributors.
10913 * Optional keywords are also declared with a NULL ->parse() function so that
10914 * the config parser can report an appropriate error when a known keyword was
10915 * not enabled.
10916 */
10917static struct srv_kw_list srv_kws = { "SSL", { }, {
Olivier Houchard522eea72017-11-03 16:27:47 +010010918 { "allow-0rtt", srv_parse_allow_0rtt, 0, 1 }, /* Allow using early data on this server */
Olivier Houchardc7566002018-11-20 23:33:50 +010010919 { "alpn", srv_parse_alpn, 1, 1 }, /* Set ALPN supported protocols */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +020010920 { "ca-file", srv_parse_ca_file, 1, 1 }, /* set CAfile to process verify server cert */
Olivier Houchard92150142018-12-21 19:47:01 +010010921 { "check-alpn", srv_parse_alpn, 1, 1 }, /* Set ALPN used for checks */
Olivier Houchard9130a962017-10-17 17:33:43 +020010922 { "check-sni", srv_parse_check_sni, 1, 1 }, /* set SNI */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +020010923 { "check-ssl", srv_parse_check_ssl, 0, 1 }, /* enable SSL for health checks */
10924 { "ciphers", srv_parse_ciphers, 1, 1 }, /* select the cipher suite */
Emmanuel Hocdet839af572019-05-14 16:27:35 +020010925#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +020010926 { "ciphersuites", srv_parse_ciphersuites, 1, 1 }, /* select the cipher suite */
10927#endif
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +020010928 { "crl-file", srv_parse_crl_file, 1, 1 }, /* set certificate revocation list file use on server cert verify */
10929 { "crt", srv_parse_crt, 1, 1 }, /* set client certificate */
10930 { "force-sslv3", srv_parse_tls_method_options, 0, 1 }, /* force SSLv3 */
10931 { "force-tlsv10", srv_parse_tls_method_options, 0, 1 }, /* force TLSv10 */
10932 { "force-tlsv11", srv_parse_tls_method_options, 0, 1 }, /* force TLSv11 */
10933 { "force-tlsv12", srv_parse_tls_method_options, 0, 1 }, /* force TLSv12 */
10934 { "force-tlsv13", srv_parse_tls_method_options, 0, 1 }, /* force TLSv13 */
10935 { "no-check-ssl", srv_parse_no_check_ssl, 0, 1 }, /* disable SSL for health checks */
10936 { "no-send-proxy-v2-ssl", srv_parse_no_send_proxy_ssl, 0, 1 }, /* do not send PROXY protocol header v2 with SSL info */
10937 { "no-send-proxy-v2-ssl-cn", srv_parse_no_send_proxy_cn, 0, 1 }, /* do not send PROXY protocol header v2 with CN */
10938 { "no-ssl", srv_parse_no_ssl, 0, 1 }, /* disable SSL processing */
10939 { "no-ssl-reuse", srv_parse_no_ssl_reuse, 0, 1 }, /* disable session reuse */
10940 { "no-sslv3", srv_parse_tls_method_options, 0, 0 }, /* disable SSLv3 */
10941 { "no-tlsv10", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv10 */
10942 { "no-tlsv11", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv11 */
10943 { "no-tlsv12", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv12 */
10944 { "no-tlsv13", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv13 */
10945 { "no-tls-tickets", srv_parse_no_tls_tickets, 0, 1 }, /* disable session resumption tickets */
Olivier Houchardc7566002018-11-20 23:33:50 +010010946 { "npn", srv_parse_npn, 1, 1 }, /* Set NPN supported protocols */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +020010947 { "send-proxy-v2-ssl", srv_parse_send_proxy_ssl, 0, 1 }, /* send PROXY protocol header v2 with SSL info */
10948 { "send-proxy-v2-ssl-cn", srv_parse_send_proxy_cn, 0, 1 }, /* send PROXY protocol header v2 with CN */
10949 { "sni", srv_parse_sni, 1, 1 }, /* send SNI extension */
10950 { "ssl", srv_parse_ssl, 0, 1 }, /* enable SSL processing */
10951 { "ssl-min-ver", srv_parse_tls_method_minmax, 1, 1 }, /* minimum version */
10952 { "ssl-max-ver", srv_parse_tls_method_minmax, 1, 1 }, /* maximum version */
10953 { "ssl-reuse", srv_parse_ssl_reuse, 0, 1 }, /* enable session reuse */
10954 { "tls-tickets", srv_parse_tls_tickets, 0, 1 }, /* enable session resumption tickets */
10955 { "verify", srv_parse_verify, 1, 1 }, /* set SSL verify method */
10956 { "verifyhost", srv_parse_verifyhost, 1, 1 }, /* require that SSL cert verifies for hostname */
Willy Tarreau92faadf2012-10-10 23:04:25 +020010957 { NULL, NULL, 0, 0 },
10958}};
10959
Willy Tarreau0108d902018-11-25 19:14:37 +010010960INITCALL1(STG_REGISTER, srv_register_keywords, &srv_kws);
10961
Emeric Brun2c86cbf2014-10-30 15:56:50 +010010962static struct cfg_kw_list cfg_kws = {ILH, {
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +010010963 { CFG_GLOBAL, "ca-base", ssl_parse_global_ca_crt_base },
10964 { CFG_GLOBAL, "crt-base", ssl_parse_global_ca_crt_base },
Willy Tarreau0bea58d2016-12-21 23:17:25 +010010965 { CFG_GLOBAL, "maxsslconn", ssl_parse_global_int },
Emeric Brun2c86cbf2014-10-30 15:56:50 +010010966 { CFG_GLOBAL, "ssl-default-bind-options", ssl_parse_default_bind_options },
10967 { CFG_GLOBAL, "ssl-default-server-options", ssl_parse_default_server_options },
Willy Tarreau14e36a12016-12-21 23:28:13 +010010968#ifndef OPENSSL_NO_DH
10969 { CFG_GLOBAL, "ssl-dh-param-file", ssl_parse_global_dh_param_file },
10970#endif
Grant Zhangfa6c7ee2017-01-14 01:42:15 +000010971 { CFG_GLOBAL, "ssl-mode-async", ssl_parse_global_ssl_async },
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020010972#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +000010973 { CFG_GLOBAL, "ssl-engine", ssl_parse_global_ssl_engine },
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020010974#endif
Willy Tarreau9ceda382016-12-21 23:13:03 +010010975 { CFG_GLOBAL, "tune.ssl.cachesize", ssl_parse_global_int },
10976#ifndef OPENSSL_NO_DH
10977 { CFG_GLOBAL, "tune.ssl.default-dh-param", ssl_parse_global_default_dh },
10978#endif
10979 { CFG_GLOBAL, "tune.ssl.force-private-cache", ssl_parse_global_private_cache },
10980 { CFG_GLOBAL, "tune.ssl.lifetime", ssl_parse_global_lifetime },
10981 { CFG_GLOBAL, "tune.ssl.maxrecord", ssl_parse_global_int },
10982 { CFG_GLOBAL, "tune.ssl.ssl-ctx-cache-size", ssl_parse_global_int },
Thierry FOURNIER5bf77322017-02-25 12:45:22 +010010983 { CFG_GLOBAL, "tune.ssl.capture-cipherlist-size", ssl_parse_global_capture_cipherlist },
Willy Tarreauf22e9682016-12-21 23:23:19 +010010984 { CFG_GLOBAL, "ssl-default-bind-ciphers", ssl_parse_global_ciphers },
10985 { CFG_GLOBAL, "ssl-default-server-ciphers", ssl_parse_global_ciphers },
Emmanuel Hocdet839af572019-05-14 16:27:35 +020010986#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +020010987 { CFG_GLOBAL, "ssl-default-bind-ciphersuites", ssl_parse_global_ciphersuites },
10988 { CFG_GLOBAL, "ssl-default-server-ciphersuites", ssl_parse_global_ciphersuites },
10989#endif
Emeric Brun2c86cbf2014-10-30 15:56:50 +010010990 { 0, NULL, NULL },
10991}};
10992
Willy Tarreau0108d902018-11-25 19:14:37 +010010993INITCALL1(STG_REGISTER, cfg_register_keywords, &cfg_kws);
10994
Nenad Merdanovicc31499d2019-03-23 11:00:32 +010010995/* Note: must not be declared <const> as its list will be overwritten */
10996static struct sample_conv_kw_list conv_kws = {ILH, {
Willy Tarreau86a394e2019-05-09 14:15:32 +020010997#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000100fL)
Nenad Merdanovicc31499d2019-03-23 11:00:32 +010010998 { "aes_gcm_dec", sample_conv_aes_gcm_dec, ARG4(4,SINT,STR,STR,STR), check_aes_gcm, SMP_T_BIN, SMP_T_BIN },
10999#endif
11000 { NULL, NULL, 0, 0, 0 },
11001}};
11002
11003INITCALL1(STG_REGISTER, sample_register_convs, &conv_kws);
11004
Willy Tarreauf7bc57c2012-10-03 00:19:48 +020011005/* transport-layer operations for SSL sockets */
Willy Tarreaud9f5cca2016-12-22 21:08:52 +010011006static struct xprt_ops ssl_sock = {
Emeric Brun46591952012-05-18 15:47:34 +020011007 .snd_buf = ssl_sock_from_buf,
11008 .rcv_buf = ssl_sock_to_buf,
Olivier Houcharddf357842019-03-21 16:30:07 +010011009 .subscribe = ssl_subscribe,
11010 .unsubscribe = ssl_unsubscribe,
Olivier Houchard5149b592019-05-23 17:47:36 +020011011 .remove_xprt = ssl_remove_xprt,
Olivier Houchard2e055482019-05-27 19:50:12 +020011012 .add_xprt = ssl_add_xprt,
Emeric Brun46591952012-05-18 15:47:34 +020011013 .rcv_pipe = NULL,
11014 .snd_pipe = NULL,
11015 .shutr = NULL,
11016 .shutw = ssl_sock_shutw,
11017 .close = ssl_sock_close,
11018 .init = ssl_sock_init,
Willy Tarreau55d37912016-12-21 23:38:39 +010011019 .prepare_bind_conf = ssl_sock_prepare_bind_conf,
Willy Tarreau795cdab2016-12-22 17:30:54 +010011020 .destroy_bind_conf = ssl_sock_destroy_bind_conf,
Willy Tarreau17d45382016-12-22 21:16:08 +010011021 .prepare_srv = ssl_sock_prepare_srv_ctx,
11022 .destroy_srv = ssl_sock_free_srv_ctx,
Willy Tarreau8743f7e2016-12-04 18:44:29 +010011023 .get_alpn = ssl_sock_get_alpn,
Willy Tarreau8e0bb0a2016-11-24 16:58:12 +010011024 .name = "SSL",
Emeric Brun46591952012-05-18 15:47:34 +020011025};
11026
Olivier Houchardccaa7de2017-10-02 11:51:03 +020011027enum act_return ssl_action_wait_for_hs(struct act_rule *rule, struct proxy *px,
11028 struct session *sess, struct stream *s, int flags)
11029{
11030 struct connection *conn;
Olivier Houchard6fa63d92017-11-27 18:41:32 +010011031 struct conn_stream *cs;
Olivier Houchardccaa7de2017-10-02 11:51:03 +020011032
11033 conn = objt_conn(sess->origin);
Olivier Houchard6fa63d92017-11-27 18:41:32 +010011034 cs = objt_cs(s->si[0].end);
Olivier Houchardccaa7de2017-10-02 11:51:03 +020011035
Olivier Houchard6fa63d92017-11-27 18:41:32 +010011036 if (conn && cs) {
Olivier Houchardccaa7de2017-10-02 11:51:03 +020011037 if (conn->flags & (CO_FL_EARLY_SSL_HS | CO_FL_SSL_WAIT_HS)) {
Olivier Houchard6fa63d92017-11-27 18:41:32 +010011038 cs->flags |= CS_FL_WAIT_FOR_HS;
Olivier Houchardccaa7de2017-10-02 11:51:03 +020011039 s->req.flags |= CF_READ_NULL;
11040 return ACT_RET_YIELD;
11041 }
11042 }
11043 return (ACT_RET_CONT);
11044}
11045
11046static enum act_parse_ret ssl_parse_wait_for_hs(const char **args, int *orig_arg, struct proxy *px, struct act_rule *rule, char **err)
11047{
11048 rule->action_ptr = ssl_action_wait_for_hs;
11049
11050 return ACT_RET_PRS_OK;
11051}
11052
11053static struct action_kw_list http_req_actions = {ILH, {
11054 { "wait-for-handshake", ssl_parse_wait_for_hs },
11055 { /* END */ }
11056}};
11057
Willy Tarreau0108d902018-11-25 19:14:37 +010011058INITCALL1(STG_REGISTER, http_req_keywords_register, &http_req_actions);
11059
Willy Tarreau5db847a2019-05-09 14:13:35 +020011060#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +010011061
11062static void ssl_sock_sctl_free_func(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, long argl, void *argp)
11063{
11064 if (ptr) {
11065 chunk_destroy(ptr);
11066 free(ptr);
11067 }
11068}
11069
11070#endif
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +010011071static void ssl_sock_capture_free_func(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, long argl, void *argp)
11072{
Willy Tarreaubafbe012017-11-24 17:34:44 +010011073 pool_free(pool_head_ssl_capture, ptr);
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +010011074}
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +010011075
Emeric Brun46591952012-05-18 15:47:34 +020011076__attribute__((constructor))
Willy Tarreau92faadf2012-10-10 23:04:25 +020011077static void __ssl_sock_init(void)
11078{
Ilya Shipitsin0590f442019-05-25 19:30:50 +050011079#if (!defined(OPENSSL_NO_COMP) && !defined(SSL_OP_NO_COMPRESSION))
Emeric Brun46591952012-05-18 15:47:34 +020011080 STACK_OF(SSL_COMP)* cm;
Ilya Shipitsine242f3d2019-05-25 03:38:14 +050011081 int n;
Ilya Shipitsin0590f442019-05-25 19:30:50 +050011082#endif
Emeric Brun46591952012-05-18 15:47:34 +020011083
Willy Tarreauef934602016-12-22 23:12:01 +010011084 if (global_ssl.listen_default_ciphers)
11085 global_ssl.listen_default_ciphers = strdup(global_ssl.listen_default_ciphers);
11086 if (global_ssl.connect_default_ciphers)
11087 global_ssl.connect_default_ciphers = strdup(global_ssl.connect_default_ciphers);
Emmanuel Hocdet839af572019-05-14 16:27:35 +020011088#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +020011089 if (global_ssl.listen_default_ciphersuites)
11090 global_ssl.listen_default_ciphersuites = strdup(global_ssl.listen_default_ciphersuites);
11091 if (global_ssl.connect_default_ciphersuites)
11092 global_ssl.connect_default_ciphersuites = strdup(global_ssl.connect_default_ciphersuites);
11093#endif
Willy Tarreau610f04b2014-02-13 11:36:41 +010011094
Willy Tarreau13e14102016-12-22 20:25:26 +010011095 xprt_register(XPRT_SSL, &ssl_sock);
Willy Tarreau9a1ab082019-05-09 13:26:41 +020011096#if HA_OPENSSL_VERSION_NUMBER < 0x10100000L
Emeric Brun46591952012-05-18 15:47:34 +020011097 SSL_library_init();
Rosen Penev68185952018-12-14 08:47:02 -080011098#endif
Ilya Shipitsin0590f442019-05-25 19:30:50 +050011099#if (!defined(OPENSSL_NO_COMP) && !defined(SSL_OP_NO_COMPRESSION))
Emeric Brun46591952012-05-18 15:47:34 +020011100 cm = SSL_COMP_get_compression_methods();
Ilya Shipitsine242f3d2019-05-25 03:38:14 +050011101 n = sk_SSL_COMP_num(cm);
11102 while (n--) {
11103 (void) sk_SSL_COMP_pop(cm);
11104 }
Ilya Shipitsin0590f442019-05-25 19:30:50 +050011105#endif
Ilya Shipitsine242f3d2019-05-25 03:38:14 +050011106
Willy Tarreau5db847a2019-05-09 14:13:35 +020011107#if defined(USE_THREAD) && (HA_OPENSSL_VERSION_NUMBER < 0x10100000L)
Emeric Brun821bb9b2017-06-15 16:37:39 +020011108 ssl_locking_init();
11109#endif
Willy Tarreau5db847a2019-05-09 14:13:35 +020011110#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +010011111 sctl_ex_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, ssl_sock_sctl_free_func);
11112#endif
Thierry FOURNIER28962c92018-06-17 21:37:05 +020011113 ssl_app_data_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL);
Thierry FOURNIER16ff0502018-06-17 21:33:01 +020011114 ssl_capture_ptr_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, ssl_sock_capture_free_func);
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020011115#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +000011116 ENGINE_load_builtin_engines();
Grant Zhangfa6c7ee2017-01-14 01:42:15 +000011117 hap_register_post_check(ssl_check_async_engine_count);
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020011118#endif
Willy Tarreaud1c57502016-12-22 22:46:15 +010011119#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
11120 hap_register_post_check(tlskeys_finalize_config);
11121#endif
Willy Tarreau80713382018-11-26 10:19:54 +010011122
11123 global.ssl_session_max_cost = SSL_SESSION_MAX_COST;
11124 global.ssl_handshake_max_cost = SSL_HANDSHAKE_MAX_COST;
11125
11126#ifndef OPENSSL_NO_DH
11127 ssl_dh_ptr_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, NULL);
11128 hap_register_post_deinit(ssl_free_dh);
11129#endif
11130#ifndef OPENSSL_NO_ENGINE
11131 hap_register_post_deinit(ssl_free_engines);
11132#endif
11133 /* Load SSL string for the verbose & debug mode. */
11134 ERR_load_SSL_strings();
Olivier Houcharda8955d52019-04-07 22:00:38 +020011135 ha_meth = BIO_meth_new(0x666, "ha methods");
11136 BIO_meth_set_write(ha_meth, ha_ssl_write);
11137 BIO_meth_set_read(ha_meth, ha_ssl_read);
11138 BIO_meth_set_ctrl(ha_meth, ha_ssl_ctrl);
11139 BIO_meth_set_create(ha_meth, ha_ssl_new);
11140 BIO_meth_set_destroy(ha_meth, ha_ssl_free);
11141 BIO_meth_set_puts(ha_meth, ha_ssl_puts);
11142 BIO_meth_set_gets(ha_meth, ha_ssl_gets);
William Lallemand150bfa82019-09-19 17:12:49 +020011143
11144 HA_SPIN_INIT(&ckch_lock);
Willy Tarreau80713382018-11-26 10:19:54 +010011145}
Willy Tarreaud92aa5c2015-01-15 21:34:39 +010011146
Willy Tarreau80713382018-11-26 10:19:54 +010011147/* Compute and register the version string */
11148static void ssl_register_build_options()
11149{
11150 char *ptr = NULL;
11151 int i;
11152
Willy Tarreauc2c0b612016-12-21 19:23:20 +010011153 memprintf(&ptr, "Built with OpenSSL version : "
11154#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet50e25e12017-03-24 15:20:03 +010011155 "BoringSSL");
Willy Tarreauc2c0b612016-12-21 19:23:20 +010011156#else /* OPENSSL_IS_BORINGSSL */
11157 OPENSSL_VERSION_TEXT
11158 "\nRunning on OpenSSL version : %s%s",
Rosen Penev68185952018-12-14 08:47:02 -080011159 OpenSSL_version(OPENSSL_VERSION),
Willy Tarreau1d158ab2019-05-09 13:41:45 +020011160 ((OPENSSL_VERSION_NUMBER ^ OpenSSL_version_num()) >> 8) ? " (VERSIONS DIFFER!)" : "");
Willy Tarreauc2c0b612016-12-21 19:23:20 +010011161#endif
11162 memprintf(&ptr, "%s\nOpenSSL library supports TLS extensions : "
Willy Tarreau9a1ab082019-05-09 13:26:41 +020011163#if HA_OPENSSL_VERSION_NUMBER < 0x00907000L
Willy Tarreauc2c0b612016-12-21 19:23:20 +010011164 "no (library version too old)"
11165#elif defined(OPENSSL_NO_TLSEXT)
11166 "no (disabled via OPENSSL_NO_TLSEXT)"
11167#else
11168 "yes"
11169#endif
11170 "", ptr);
11171
11172 memprintf(&ptr, "%s\nOpenSSL library supports SNI : "
11173#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
11174 "yes"
11175#else
11176#ifdef OPENSSL_NO_TLSEXT
11177 "no (because of OPENSSL_NO_TLSEXT)"
11178#else
11179 "no (version might be too old, 0.9.8f min needed)"
11180#endif
11181#endif
11182 "", ptr);
11183
Emmanuel Hocdetf80bc242017-07-12 14:25:38 +020011184 memprintf(&ptr, "%s\nOpenSSL library supports :", ptr);
11185 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
11186 if (methodVersions[i].option)
11187 memprintf(&ptr, "%s %s", ptr, methodVersions[i].name);
Emmanuel Hocdet50e25e12017-03-24 15:20:03 +010011188
Willy Tarreauc2c0b612016-12-21 19:23:20 +010011189 hap_register_build_opts(ptr, 1);
Willy Tarreau80713382018-11-26 10:19:54 +010011190}
Willy Tarreauc2c0b612016-12-21 19:23:20 +010011191
Willy Tarreau80713382018-11-26 10:19:54 +010011192INITCALL0(STG_REGISTER, ssl_register_build_options);
Remi Gacogne4f902b82015-05-28 16:23:00 +020011193
Emeric Brun46591952012-05-18 15:47:34 +020011194
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020011195#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +000011196void ssl_free_engines(void) {
11197 struct ssl_engine_list *wl, *wlb;
11198 /* free up engine list */
11199 list_for_each_entry_safe(wl, wlb, &openssl_engines, list) {
11200 ENGINE_finish(wl->e);
11201 ENGINE_free(wl->e);
11202 LIST_DEL(&wl->list);
11203 free(wl);
11204 }
11205}
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020011206#endif
Christopher Faulet31af49d2015-06-09 17:29:50 +020011207
Remi Gacogned3a23c32015-05-28 16:39:47 +020011208#ifndef OPENSSL_NO_DH
Grant Zhang872f9c22017-01-21 01:10:18 +000011209void ssl_free_dh(void) {
11210 if (local_dh_1024) {
11211 DH_free(local_dh_1024);
11212 local_dh_1024 = NULL;
11213 }
11214 if (local_dh_2048) {
11215 DH_free(local_dh_2048);
11216 local_dh_2048 = NULL;
11217 }
11218 if (local_dh_4096) {
11219 DH_free(local_dh_4096);
11220 local_dh_4096 = NULL;
11221 }
Remi Gacogne47783ef2015-05-29 15:53:22 +020011222 if (global_dh) {
11223 DH_free(global_dh);
11224 global_dh = NULL;
11225 }
Grant Zhang872f9c22017-01-21 01:10:18 +000011226}
11227#endif
11228
11229__attribute__((destructor))
11230static void __ssl_sock_deinit(void)
11231{
11232#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Emeric Brun821bb9b2017-06-15 16:37:39 +020011233 if (ssl_ctx_lru_tree) {
11234 lru64_destroy(ssl_ctx_lru_tree);
Christopher Faulet2a944ee2017-11-07 10:42:54 +010011235 HA_RWLOCK_DESTROY(&ssl_ctx_lru_rwlock);
Emeric Brun821bb9b2017-06-15 16:37:39 +020011236 }
Remi Gacogned3a23c32015-05-28 16:39:47 +020011237#endif
11238
Willy Tarreau5db847a2019-05-09 14:13:35 +020011239#if (HA_OPENSSL_VERSION_NUMBER < 0x10100000L)
Remi Gacogned3a23c32015-05-28 16:39:47 +020011240 ERR_remove_state(0);
11241 ERR_free_strings();
11242
11243 EVP_cleanup();
Rosen Penev68185952018-12-14 08:47:02 -080011244#endif
Remi Gacogned3a23c32015-05-28 16:39:47 +020011245
Willy Tarreau5db847a2019-05-09 14:13:35 +020011246#if (HA_OPENSSL_VERSION_NUMBER >= 0x00907000L) && (HA_OPENSSL_VERSION_NUMBER < 0x10100000L)
Remi Gacogned3a23c32015-05-28 16:39:47 +020011247 CRYPTO_cleanup_all_ex_data();
11248#endif
Olivier Houcharda8955d52019-04-07 22:00:38 +020011249 BIO_meth_free(ha_meth);
Remi Gacogned3a23c32015-05-28 16:39:47 +020011250}
11251
11252
Emeric Brun46591952012-05-18 15:47:34 +020011253/*
11254 * Local variables:
11255 * c-indent-level: 8
11256 * c-basic-offset: 8
11257 * End:
11258 */