blob: fc7109f58accf69d54b81a546a004703e28e6577 [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",
Tim Duesterhus93128532019-11-23 23:45:10 +01003087 err && *err ? *err : "", path);
William Lallemandf9568fc2019-10-16 18:27:58 +02003088 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",
Tim Duesterhus93128532019-11-23 23:45:10 +01003278 err && *err ? *err : "", fp);
William Lallemanda17f4112019-10-10 15:16:44 +02003279 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",
Tim Duesterhus93128532019-11-23 23:45:10 +01003329 err && *err ? *err : "", fp);
William Lallemand246c0242019-10-11 08:59:13 +02003330 ret = 1;
3331 goto end;
3332 }
3333 } else {
3334 memprintf(err, "%sNo issuer found, cannot use the OCSP response'.\n",
Tim Duesterhus93128532019-11-23 23:45:10 +01003335 err && *err ? *err : "");
William Lallemand246c0242019-10-11 08:59:13 +02003336 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",
Tim Duesterhus93128532019-11-23 23:45:10 +01003423 err && *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) {
Tim Duesterhus93128532019-11-23 23:45:10 +01003434 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",
3435 err && *err ? *err : "", path);
Emeric Bruna96b5822019-10-17 13:25:14 +02003436 errcode |= ERR_ALERT | ERR_FATAL;
3437 goto end;
William Lallemand246c0242019-10-11 08:59:13 +02003438 }
3439 }
William Lallemand246c0242019-10-11 08:59:13 +02003440#endif
3441
Emeric Bruna96b5822019-10-17 13:25:14 +02003442 end:
3443 return errcode;
yanbzhu488a4d22015-12-01 15:16:07 -05003444}
3445
William Lallemandc4ecddf2019-07-31 16:50:08 +02003446#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
yanbzhu08ce6ab2015-12-02 13:01:29 -05003447
William Lallemand28a8fce2019-10-04 17:36:55 +02003448static int ssl_sock_populate_sni_keytypes_hplr(const char *str, struct eb_root *sni_keytypes, int key_index)
yanbzhu08ce6ab2015-12-02 13:01:29 -05003449{
3450 struct sni_keytype *s_kt = NULL;
3451 struct ebmb_node *node;
3452 int i;
3453
3454 for (i = 0; i < trash.size; i++) {
3455 if (!str[i])
3456 break;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02003457 trash.area[i] = tolower(str[i]);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003458 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +02003459 trash.area[i] = 0;
3460 node = ebst_lookup(sni_keytypes, trash.area);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003461 if (!node) {
3462 /* CN not found in tree */
3463 s_kt = malloc(sizeof(struct sni_keytype) + i + 1);
3464 /* Using memcpy here instead of strncpy.
3465 * strncpy will cause sig_abrt errors under certain versions of gcc with -O2
3466 * See: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=60792
3467 */
William Lallemand28a8fce2019-10-04 17:36:55 +02003468 if (!s_kt)
3469 return -1;
3470
Willy Tarreau843b7cb2018-07-13 10:54:26 +02003471 memcpy(s_kt->name.key, trash.area, i+1);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003472 s_kt->keytypes = 0;
3473 ebst_insert(sni_keytypes, &s_kt->name);
3474 } else {
3475 /* CN found in tree */
3476 s_kt = container_of(node, struct sni_keytype, name);
3477 }
3478
3479 /* Mark that this CN has the keytype of key_index via keytypes mask */
3480 s_kt->keytypes |= 1<<key_index;
3481
William Lallemand28a8fce2019-10-04 17:36:55 +02003482 return 0;
3483
yanbzhu08ce6ab2015-12-02 13:01:29 -05003484}
3485
William Lallemandc4ecddf2019-07-31 16:50:08 +02003486#endif
William Lallemand8c1cdde2019-10-18 10:58:14 +02003487/*
3488 * Free a ckch_store and its ckch(s)
3489 * The linked ckch_inst are not free'd
3490 */
3491void ckchs_free(struct ckch_store *ckchs)
3492{
3493 if (!ckchs)
3494 return;
3495
3496#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
3497 if (ckchs->multi) {
3498 int n;
3499
3500 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++)
3501 ssl_sock_free_cert_key_and_chain_contents(&ckchs->ckch[n]);
3502 } else
3503#endif
3504 {
3505 ssl_sock_free_cert_key_and_chain_contents(ckchs->ckch);
3506 ckchs->ckch = NULL;
3507 }
3508
3509 free(ckchs);
3510}
3511
3512/* allocate and duplicate a ckch_store
3513 * Return a new ckch_store or NULL */
3514static struct ckch_store *ckchs_dup(const struct ckch_store *src)
3515{
3516 struct ckch_store *dst;
3517 int pathlen;
3518
3519 pathlen = strlen(src->path);
3520 dst = calloc(1, sizeof(*dst) + pathlen + 1);
3521 if (!dst)
3522 return NULL;
3523 /* copy previous key */
3524 memcpy(dst->path, src->path, pathlen + 1);
3525 dst->multi = src->multi;
3526 LIST_INIT(&dst->ckch_inst);
3527
3528 dst->ckch = calloc((src->multi ? SSL_SOCK_NUM_KEYTYPES : 1), sizeof(*dst->ckch));
3529 if (!dst->ckch)
3530 goto error;
3531
3532#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
3533 if (src->multi) {
3534 int n;
3535
3536 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
3537 if (&src->ckch[n]) {
3538 if (!ssl_sock_copy_cert_key_and_chain(&src->ckch[n], &dst->ckch[n]))
3539 goto error;
3540 }
3541 }
3542 } else
3543#endif
3544 {
3545 if (!ssl_sock_copy_cert_key_and_chain(src->ckch, dst->ckch))
3546 goto error;
3547 }
3548
3549 return dst;
3550
3551error:
3552 ckchs_free(dst);
3553
3554 return NULL;
3555}
William Lallemandc4ecddf2019-07-31 16:50:08 +02003556
William Lallemand36b84632019-07-18 19:28:17 +02003557/*
William Lallemande3af8fb2019-10-08 11:36:53 +02003558 * lookup a path into the ckchs tree.
William Lallemand6af03992019-07-23 15:00:54 +02003559 */
William Lallemande3af8fb2019-10-08 11:36:53 +02003560static inline struct ckch_store *ckchs_lookup(char *path)
William Lallemand6af03992019-07-23 15:00:54 +02003561{
3562 struct ebmb_node *eb;
3563
William Lallemande3af8fb2019-10-08 11:36:53 +02003564 eb = ebst_lookup(&ckchs_tree, path);
William Lallemand6af03992019-07-23 15:00:54 +02003565 if (!eb)
3566 return NULL;
3567
William Lallemande3af8fb2019-10-08 11:36:53 +02003568 return ebmb_entry(eb, struct ckch_store, node);
William Lallemand6af03992019-07-23 15:00:54 +02003569}
3570
3571/*
William Lallemande3af8fb2019-10-08 11:36:53 +02003572 * This function allocate a ckch_store and populate it with certificates from files.
William Lallemand36b84632019-07-18 19:28:17 +02003573 */
William Lallemande3af8fb2019-10-08 11:36:53 +02003574static struct ckch_store *ckchs_load_cert_file(char *path, int multi, char **err)
William Lallemand36b84632019-07-18 19:28:17 +02003575{
William Lallemande3af8fb2019-10-08 11:36:53 +02003576 struct ckch_store *ckchs;
William Lallemand36b84632019-07-18 19:28:17 +02003577
William Lallemande3af8fb2019-10-08 11:36:53 +02003578 ckchs = calloc(1, sizeof(*ckchs) + strlen(path) + 1);
3579 if (!ckchs) {
William Lallemand36b84632019-07-18 19:28:17 +02003580 memprintf(err, "%sunable to allocate memory.\n", err && *err ? *err : "");
3581 goto end;
3582 }
William Lallemande3af8fb2019-10-08 11:36:53 +02003583 ckchs->ckch = calloc(1, sizeof(*ckchs->ckch) * (multi ? SSL_SOCK_NUM_KEYTYPES : 1));
William Lallemand36b84632019-07-18 19:28:17 +02003584
William Lallemande3af8fb2019-10-08 11:36:53 +02003585 if (!ckchs->ckch) {
William Lallemand36b84632019-07-18 19:28:17 +02003586 memprintf(err, "%sunable to allocate memory.\n", err && *err ? *err : "");
3587 goto end;
3588 }
3589
William Lallemand9117de92019-10-04 00:29:42 +02003590 LIST_INIT(&ckchs->ckch_inst);
3591
William Lallemand36b84632019-07-18 19:28:17 +02003592 if (!multi) {
3593
William Lallemand96a9c972019-10-17 11:56:17 +02003594 if (ssl_sock_load_files_into_ckch(path, ckchs->ckch, err) == 1)
William Lallemand36b84632019-07-18 19:28:17 +02003595 goto end;
3596
William Lallemande3af8fb2019-10-08 11:36:53 +02003597 /* insert into the ckchs tree */
3598 memcpy(ckchs->path, path, strlen(path) + 1);
3599 ebst_insert(&ckchs_tree, &ckchs->node);
William Lallemand36b84632019-07-18 19:28:17 +02003600 } else {
3601 int found = 0;
William Lallemandc4ecddf2019-07-31 16:50:08 +02003602#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
3603 char fp[MAXPATHLEN+1] = {0};
3604 int n = 0;
William Lallemand36b84632019-07-18 19:28:17 +02003605
3606 /* Load all possible certs and keys */
3607 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
3608 struct stat buf;
3609 snprintf(fp, sizeof(fp), "%s.%s", path, SSL_SOCK_KEYTYPE_NAMES[n]);
3610 if (stat(fp, &buf) == 0) {
William Lallemand96a9c972019-10-17 11:56:17 +02003611 if (ssl_sock_load_files_into_ckch(fp, &ckchs->ckch[n], err) == 1)
William Lallemand36b84632019-07-18 19:28:17 +02003612 goto end;
3613 found = 1;
William Lallemande3af8fb2019-10-08 11:36:53 +02003614 ckchs->multi = 1;
William Lallemand36b84632019-07-18 19:28:17 +02003615 }
3616 }
William Lallemandc4ecddf2019-07-31 16:50:08 +02003617#endif
William Lallemand36b84632019-07-18 19:28:17 +02003618
3619 if (!found) {
William Lallemand6e5f2ce2019-08-01 14:43:20 +02003620 memprintf(err, "%sDidn't find any certificate for bundle '%s'.\n", err && *err ? *err : "", path);
William Lallemand36b84632019-07-18 19:28:17 +02003621 goto end;
3622 }
William Lallemande3af8fb2019-10-08 11:36:53 +02003623 /* insert into the ckchs tree */
3624 memcpy(ckchs->path, path, strlen(path) + 1);
3625 ebst_insert(&ckchs_tree, &ckchs->node);
William Lallemand36b84632019-07-18 19:28:17 +02003626 }
William Lallemande3af8fb2019-10-08 11:36:53 +02003627 return ckchs;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003628
William Lallemand36b84632019-07-18 19:28:17 +02003629end:
William Lallemande3af8fb2019-10-08 11:36:53 +02003630 if (ckchs) {
3631 free(ckchs->ckch);
3632 ebmb_delete(&ckchs->node);
William Lallemand6af03992019-07-23 15:00:54 +02003633 }
3634
William Lallemande3af8fb2019-10-08 11:36:53 +02003635 free(ckchs);
William Lallemand36b84632019-07-18 19:28:17 +02003636
3637 return NULL;
3638}
3639
William Lallemandc4ecddf2019-07-31 16:50:08 +02003640#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
3641
William Lallemand36b84632019-07-18 19:28:17 +02003642/*
William Lallemande3af8fb2019-10-08 11:36:53 +02003643 * Take a ckch_store which contains a multi-certificate bundle.
William Lallemand36b84632019-07-18 19:28:17 +02003644 * Group these certificates into a set of SSL_CTX*
yanbzhu08ce6ab2015-12-02 13:01:29 -05003645 * based on shared and unique CN and SAN entries. Add these SSL_CTX* to the SNI tree.
3646 *
Joseph Herlant017b3da2018-11-15 09:07:59 -08003647 * This will allow the user to explicitly group multiple cert/keys for a single purpose
yanbzhu08ce6ab2015-12-02 13:01:29 -05003648 *
Emeric Brun054563d2019-10-17 13:16:58 +02003649 * Returns a bitfield containing the flags:
3650 * ERR_FATAL in any fatal error case
3651 * ERR_ALERT if the reason of the error is available in err
3652 * ERR_WARN if a warning is available into err
William Lallemand36b84632019-07-18 19:28:17 +02003653 *
yanbzhu08ce6ab2015-12-02 13:01:29 -05003654 */
Emeric Brun054563d2019-10-17 13:16:58 +02003655static int ckch_inst_new_load_multi_store(const char *path, struct ckch_store *ckchs,
3656 struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
3657 char **sni_filter, int fcount, struct ckch_inst **ckchi, char **err)
yanbzhu08ce6ab2015-12-02 13:01:29 -05003658{
William Lallemand36b84632019-07-18 19:28:17 +02003659 int i = 0, n = 0;
3660 struct cert_key_and_chain *certs_and_keys;
William Lallemand4b989f22019-10-04 18:36:55 +02003661 struct eb_root sni_keytypes_map = EB_ROOT;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003662 struct ebmb_node *node;
3663 struct ebmb_node *next;
3664 /* Array of SSL_CTX pointers corresponding to each possible combo
3665 * of keytypes
3666 */
3667 struct key_combo_ctx key_combos[SSL_SOCK_POSSIBLE_KT_COMBOS] = { {0} };
Emeric Brun054563d2019-10-17 13:16:58 +02003668 int errcode = 0;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003669 X509_NAME *xname = NULL;
3670 char *str = NULL;
3671#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
3672 STACK_OF(GENERAL_NAME) *names = NULL;
3673#endif
William Lallemand614ca0d2019-10-07 13:52:11 +02003674 struct ckch_inst *ckch_inst;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003675
Emeric Brun054563d2019-10-17 13:16:58 +02003676 *ckchi = NULL;
3677
William Lallemande3af8fb2019-10-08 11:36:53 +02003678 if (!ckchs || !ckchs->ckch || !ckchs->multi) {
William Lallemand36b84632019-07-18 19:28:17 +02003679 memprintf(err, "%sunable to load SSL certificate file '%s' file does not exist.\n",
3680 err && *err ? *err : "", path);
Emeric Brun054563d2019-10-17 13:16:58 +02003681 return ERR_ALERT | ERR_FATAL;
William Lallemand614ca0d2019-10-07 13:52:11 +02003682 }
3683
3684 ckch_inst = ckch_inst_new();
3685 if (!ckch_inst) {
3686 memprintf(err, "%sunable to allocate SSL context for cert '%s'.\n",
3687 err && *err ? *err : "", path);
Emeric Brun054563d2019-10-17 13:16:58 +02003688 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemand614ca0d2019-10-07 13:52:11 +02003689 goto end;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003690 }
3691
William Lallemande3af8fb2019-10-08 11:36:53 +02003692 certs_and_keys = ckchs->ckch;
William Lallemand36b84632019-07-18 19:28:17 +02003693
William Lallemand150bfa82019-09-19 17:12:49 +02003694 /* at least one of the instances is using filters during the config
3695 * parsing, that's ok to inherit this during loading on CLI */
3696 ckchs->filters = !!fcount;
3697
yanbzhu08ce6ab2015-12-02 13:01:29 -05003698 /* Process each ckch and update keytypes for each CN/SAN
3699 * for example, if CN/SAN www.a.com is associated with
3700 * certs with keytype 0 and 2, then at the end of the loop,
3701 * www.a.com will have:
3702 * keyindex = 0 | 1 | 4 = 5
3703 */
3704 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
William Lallemand28a8fce2019-10-04 17:36:55 +02003705 int ret;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003706
3707 if (!ssl_sock_is_ckch_valid(&certs_and_keys[n]))
3708 continue;
3709
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003710 if (fcount) {
William Lallemand28a8fce2019-10-04 17:36:55 +02003711 for (i = 0; i < fcount; i++) {
3712 ret = ssl_sock_populate_sni_keytypes_hplr(sni_filter[i], &sni_keytypes_map, n);
3713 if (ret < 0) {
3714 memprintf(err, "%sunable to allocate SSL context.\n",
3715 err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02003716 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemand28a8fce2019-10-04 17:36:55 +02003717 goto end;
3718 }
3719 }
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003720 } else {
3721 /* A lot of the following code is OpenSSL boilerplate for processing CN's and SAN's,
3722 * so the line that contains logic is marked via comments
3723 */
3724 xname = X509_get_subject_name(certs_and_keys[n].cert);
3725 i = -1;
3726 while ((i = X509_NAME_get_index_by_NID(xname, NID_commonName, i)) != -1) {
3727 X509_NAME_ENTRY *entry = X509_NAME_get_entry(xname, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003728 ASN1_STRING *value;
3729 value = X509_NAME_ENTRY_get_data(entry);
3730 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003731 /* Important line is here */
William Lallemand28a8fce2019-10-04 17:36:55 +02003732 ret = ssl_sock_populate_sni_keytypes_hplr(str, &sni_keytypes_map, n);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003733
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003734 OPENSSL_free(str);
3735 str = NULL;
William Lallemand28a8fce2019-10-04 17:36:55 +02003736 if (ret < 0) {
3737 memprintf(err, "%sunable to allocate SSL context.\n",
3738 err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02003739 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemand28a8fce2019-10-04 17:36:55 +02003740 goto end;
3741 }
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003742 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003743 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003744
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003745 /* Do the above logic for each SAN */
yanbzhu08ce6ab2015-12-02 13:01:29 -05003746#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003747 names = X509_get_ext_d2i(certs_and_keys[n].cert, NID_subject_alt_name, NULL, NULL);
3748 if (names) {
3749 for (i = 0; i < sk_GENERAL_NAME_num(names); i++) {
3750 GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003751
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003752 if (name->type == GEN_DNS) {
3753 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
3754 /* Important line is here */
William Lallemand28a8fce2019-10-04 17:36:55 +02003755 ret = ssl_sock_populate_sni_keytypes_hplr(str, &sni_keytypes_map, n);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003756
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003757 OPENSSL_free(str);
3758 str = NULL;
William Lallemand28a8fce2019-10-04 17:36:55 +02003759 if (ret < 0) {
3760 memprintf(err, "%sunable to allocate SSL context.\n",
3761 err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02003762 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemand28a8fce2019-10-04 17:36:55 +02003763 goto end;
3764 }
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003765 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003766 }
3767 }
3768 }
3769 }
3770#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
3771 }
3772
3773 /* If no files found, return error */
3774 if (eb_is_empty(&sni_keytypes_map)) {
3775 memprintf(err, "%sunable to load SSL certificate file '%s' file does not exist.\n",
3776 err && *err ? *err : "", path);
Emeric Brun054563d2019-10-17 13:16:58 +02003777 errcode |= ERR_ALERT | ERR_FATAL;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003778 goto end;
3779 }
3780
3781 /* We now have a map of CN/SAN to keytypes that are loaded in
3782 * Iterate through the map to create the SSL_CTX's (if needed)
3783 * and add each CTX to the SNI tree
3784 *
3785 * Some math here:
Joseph Herlant017b3da2018-11-15 09:07:59 -08003786 * There are 2^n - 1 possible combinations, each unique
yanbzhu08ce6ab2015-12-02 13:01:29 -05003787 * combination is denoted by the key in the map. Each key
3788 * has a value between 1 and 2^n - 1. Conveniently, the array
3789 * of SSL_CTX* is sized 2^n. So, we can simply use the i'th
3790 * entry in the array to correspond to the unique combo (key)
3791 * associated with i. This unique key combo (i) will be associated
3792 * with combos[i-1]
3793 */
3794
3795 node = ebmb_first(&sni_keytypes_map);
3796 while (node) {
3797 SSL_CTX *cur_ctx;
Bertrand Jacquin33423092016-11-13 16:37:13 +00003798 char cur_file[MAXPATHLEN+1];
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003799 const struct pkey_info kinfo = { .sig = TLSEXT_signature_anonymous, .bits = 0 };
yanbzhu08ce6ab2015-12-02 13:01:29 -05003800
3801 str = (char *)container_of(node, struct sni_keytype, name)->name.key;
3802 i = container_of(node, struct sni_keytype, name)->keytypes;
3803 cur_ctx = key_combos[i-1].ctx;
3804
3805 if (cur_ctx == NULL) {
3806 /* need to create SSL_CTX */
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003807 cur_ctx = SSL_CTX_new(SSLv23_server_method());
yanbzhu08ce6ab2015-12-02 13:01:29 -05003808 if (cur_ctx == NULL) {
3809 memprintf(err, "%sunable to allocate SSL context.\n",
3810 err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02003811 errcode |= ERR_ALERT | ERR_FATAL;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003812 goto end;
3813 }
3814
yanbzhube2774d2015-12-10 15:07:30 -05003815 /* Load all required certs/keys/chains/OCSPs info into SSL_CTX */
yanbzhu08ce6ab2015-12-02 13:01:29 -05003816 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
3817 if (i & (1<<n)) {
3818 /* Key combo contains ckch[n] */
Bertrand Jacquin33423092016-11-13 16:37:13 +00003819 snprintf(cur_file, MAXPATHLEN+1, "%s.%s", path, SSL_SOCK_KEYTYPE_NAMES[n]);
Emeric Bruna96b5822019-10-17 13:25:14 +02003820 errcode |= ssl_sock_put_ckch_into_ctx(cur_file, &certs_and_keys[n], cur_ctx, err);
3821 if (errcode & ERR_CODE)
yanbzhu08ce6ab2015-12-02 13:01:29 -05003822 goto end;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003823 }
3824 }
3825
yanbzhu08ce6ab2015-12-02 13:01:29 -05003826 /* Update key_combos */
3827 key_combos[i-1].ctx = cur_ctx;
3828 }
3829
3830 /* Update SNI Tree */
William Lallemand9117de92019-10-04 00:29:42 +02003831
William Lallemand1d29c742019-10-04 00:53:29 +02003832 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 +02003833 kinfo, str, key_combos[i-1].order);
3834 if (key_combos[i-1].order < 0) {
3835 memprintf(err, "%sunable to create a sni context.\n", err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02003836 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemandfe49bb32019-10-03 23:46:33 +02003837 goto end;
3838 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003839 node = ebmb_next(node);
3840 }
3841
3842
3843 /* Mark a default context if none exists, using the ctx that has the most shared keys */
3844 if (!bind_conf->default_ctx) {
3845 for (i = SSL_SOCK_POSSIBLE_KT_COMBOS - 1; i >= 0; i--) {
3846 if (key_combos[i].ctx) {
3847 bind_conf->default_ctx = key_combos[i].ctx;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003848 bind_conf->default_ssl_conf = ssl_conf;
William Lallemand21724f02019-11-04 17:56:13 +01003849 ckch_inst->is_default = 1;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003850 break;
3851 }
3852 }
3853 }
3854
William Lallemand614ca0d2019-10-07 13:52:11 +02003855 ckch_inst->bind_conf = bind_conf;
William Lallemand150bfa82019-09-19 17:12:49 +02003856 ckch_inst->ssl_conf = ssl_conf;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003857end:
3858
3859 if (names)
3860 sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
3861
yanbzhu08ce6ab2015-12-02 13:01:29 -05003862 node = ebmb_first(&sni_keytypes_map);
3863 while (node) {
3864 next = ebmb_next(node);
3865 ebmb_delete(node);
William Lallemand8ed5b962019-10-04 17:24:39 +02003866 free(ebmb_entry(node, struct sni_keytype, name));
yanbzhu08ce6ab2015-12-02 13:01:29 -05003867 node = next;
3868 }
3869
Emeric Brun054563d2019-10-17 13:16:58 +02003870 if (errcode & ERR_CODE && ckch_inst) {
William Lallemand0c6d12f2019-10-04 18:38:51 +02003871 struct sni_ctx *sc0, *sc0b;
3872
3873 /* free the SSL_CTX in case of error */
3874 for (i = 0; i < SSL_SOCK_POSSIBLE_KT_COMBOS; i++) {
3875 if (key_combos[i].ctx)
3876 SSL_CTX_free(key_combos[i].ctx);
3877 }
3878
3879 /* free the sni_ctx in case of error */
3880 list_for_each_entry_safe(sc0, sc0b, &ckch_inst->sni_ctx, by_ckch_inst) {
3881
3882 ebmb_delete(&sc0->name);
3883 LIST_DEL(&sc0->by_ckch_inst);
3884 free(sc0);
3885 }
William Lallemand614ca0d2019-10-07 13:52:11 +02003886 free(ckch_inst);
3887 ckch_inst = NULL;
William Lallemand0c6d12f2019-10-04 18:38:51 +02003888 }
3889
Emeric Brun054563d2019-10-17 13:16:58 +02003890 *ckchi = ckch_inst;
3891 return errcode;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003892}
3893#else
3894/* This is a dummy, that just logs an error and returns error */
Emeric Brun054563d2019-10-17 13:16:58 +02003895static int ckch_inst_new_load_multi_store(const char *path, struct ckch_store *ckchs,
3896 struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
3897 char **sni_filter, int fcount, struct ckch_inst **ckchi, char **err)
yanbzhu08ce6ab2015-12-02 13:01:29 -05003898{
3899 memprintf(err, "%sunable to stat SSL certificate from file '%s' : %s.\n",
3900 err && *err ? *err : "", path, strerror(errno));
Emeric Brun054563d2019-10-17 13:16:58 +02003901 return ERR_ALERT | ERR_FATAL;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003902}
3903
Willy Tarreau9a1ab082019-05-09 13:26:41 +02003904#endif /* #if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL: Support for loading multiple certs into a single SSL_CTX */
yanbzhu488a4d22015-12-01 15:16:07 -05003905
William Lallemand614ca0d2019-10-07 13:52:11 +02003906/*
3907 * This function allocate a ckch_inst and create its snis
Emeric Brun054563d2019-10-17 13:16:58 +02003908 *
3909 * Returns a bitfield containing the flags:
3910 * ERR_FATAL in any fatal error case
3911 * ERR_ALERT if the reason of the error is available in err
3912 * ERR_WARN if a warning is available into err
William Lallemand614ca0d2019-10-07 13:52:11 +02003913 */
Emeric Brun054563d2019-10-17 13:16:58 +02003914static int ckch_inst_new_load_store(const char *path, struct ckch_store *ckchs, struct bind_conf *bind_conf,
3915 struct ssl_bind_conf *ssl_conf, char **sni_filter, int fcount, struct ckch_inst **ckchi, char **err)
Emeric Brunfc0421f2012-09-07 17:30:07 +02003916{
William Lallemandc9402072019-05-15 15:33:54 +02003917 SSL_CTX *ctx;
William Lallemandc9402072019-05-15 15:33:54 +02003918 int i;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003919 int order = 0;
3920 X509_NAME *xname;
3921 char *str;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003922 EVP_PKEY *pkey;
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003923 struct pkey_info kinfo = { .sig = TLSEXT_signature_anonymous, .bits = 0 };
Emeric Brunfc0421f2012-09-07 17:30:07 +02003924#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
3925 STACK_OF(GENERAL_NAME) *names;
3926#endif
William Lallemand36b84632019-07-18 19:28:17 +02003927 struct cert_key_and_chain *ckch;
William Lallemand614ca0d2019-10-07 13:52:11 +02003928 struct ckch_inst *ckch_inst = NULL;
Emeric Brun054563d2019-10-17 13:16:58 +02003929 int errcode = 0;
3930
3931 *ckchi = NULL;
William Lallemanda59191b2019-05-15 16:08:56 +02003932
William Lallemande3af8fb2019-10-08 11:36:53 +02003933 if (!ckchs || !ckchs->ckch)
Emeric Brun054563d2019-10-17 13:16:58 +02003934 return ERR_FATAL;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003935
William Lallemande3af8fb2019-10-08 11:36:53 +02003936 ckch = ckchs->ckch;
William Lallemand36b84632019-07-18 19:28:17 +02003937
William Lallemand150bfa82019-09-19 17:12:49 +02003938 /* at least one of the instances is using filters during the config
3939 * parsing, that's ok to inherit this during loading on CLI */
3940 ckchs->filters = !!fcount;
3941
William Lallemandc9402072019-05-15 15:33:54 +02003942 ctx = SSL_CTX_new(SSLv23_server_method());
3943 if (!ctx) {
3944 memprintf(err, "%sunable to allocate SSL context for cert '%s'.\n",
3945 err && *err ? *err : "", path);
Emeric Brun054563d2019-10-17 13:16:58 +02003946 errcode |= ERR_ALERT | ERR_FATAL;
3947 goto error;
William Lallemandc9402072019-05-15 15:33:54 +02003948 }
3949
Emeric Bruna96b5822019-10-17 13:25:14 +02003950 errcode |= ssl_sock_put_ckch_into_ctx(path, ckch, ctx, err);
3951 if (errcode & ERR_CODE)
William Lallemand614ca0d2019-10-07 13:52:11 +02003952 goto error;
William Lallemand614ca0d2019-10-07 13:52:11 +02003953
3954 ckch_inst = ckch_inst_new();
3955 if (!ckch_inst) {
3956 memprintf(err, "%sunable to allocate SSL context for cert '%s'.\n",
3957 err && *err ? *err : "", path);
Emeric Brun054563d2019-10-17 13:16:58 +02003958 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemandd9199372019-10-04 15:37:05 +02003959 goto error;
William Lallemandc9402072019-05-15 15:33:54 +02003960 }
3961
William Lallemand36b84632019-07-18 19:28:17 +02003962 pkey = X509_get_pubkey(ckch->cert);
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003963 if (pkey) {
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003964 kinfo.bits = EVP_PKEY_bits(pkey);
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003965 switch(EVP_PKEY_base_id(pkey)) {
3966 case EVP_PKEY_RSA:
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003967 kinfo.sig = TLSEXT_signature_rsa;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003968 break;
3969 case EVP_PKEY_EC:
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003970 kinfo.sig = TLSEXT_signature_ecdsa;
3971 break;
3972 case EVP_PKEY_DSA:
3973 kinfo.sig = TLSEXT_signature_dsa;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003974 break;
3975 }
3976 EVP_PKEY_free(pkey);
3977 }
3978
Emeric Brun50bcecc2013-04-22 13:05:23 +02003979 if (fcount) {
William Lallemandfe49bb32019-10-03 23:46:33 +02003980 while (fcount--) {
William Lallemand1d29c742019-10-04 00:53:29 +02003981 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 +02003982 if (order < 0) {
3983 memprintf(err, "%sunable to create a sni context.\n", err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02003984 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemandd9199372019-10-04 15:37:05 +02003985 goto error;
William Lallemandfe49bb32019-10-03 23:46:33 +02003986 }
3987 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003988 }
3989 else {
Emeric Brunfc0421f2012-09-07 17:30:07 +02003990#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
William Lallemand36b84632019-07-18 19:28:17 +02003991 names = X509_get_ext_d2i(ckch->cert, NID_subject_alt_name, NULL, NULL);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003992 if (names) {
3993 for (i = 0; i < sk_GENERAL_NAME_num(names); i++) {
3994 GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i);
3995 if (name->type == GEN_DNS) {
3996 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
William Lallemand1d29c742019-10-04 00:53:29 +02003997 order = ckch_inst_add_cert_sni(ctx, ckch_inst, bind_conf, ssl_conf, kinfo, str, order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003998 OPENSSL_free(str);
William Lallemandfe49bb32019-10-03 23:46:33 +02003999 if (order < 0) {
4000 memprintf(err, "%sunable to create a sni context.\n", err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02004001 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemandd9199372019-10-04 15:37:05 +02004002 goto error;
William Lallemandfe49bb32019-10-03 23:46:33 +02004003 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004004 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004005 }
4006 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004007 sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004008 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004009#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
William Lallemand36b84632019-07-18 19:28:17 +02004010 xname = X509_get_subject_name(ckch->cert);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004011 i = -1;
4012 while ((i = X509_NAME_get_index_by_NID(xname, NID_commonName, i)) != -1) {
4013 X509_NAME_ENTRY *entry = X509_NAME_get_entry(xname, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02004014 ASN1_STRING *value;
4015
4016 value = X509_NAME_ENTRY_get_data(entry);
4017 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
William Lallemand1d29c742019-10-04 00:53:29 +02004018 order = ckch_inst_add_cert_sni(ctx, ckch_inst, bind_conf, ssl_conf, kinfo, str, order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004019 OPENSSL_free(str);
William Lallemandfe49bb32019-10-03 23:46:33 +02004020 if (order < 0) {
4021 memprintf(err, "%sunable to create a sni context.\n", err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02004022 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemandd9199372019-10-04 15:37:05 +02004023 goto error;
William Lallemandfe49bb32019-10-03 23:46:33 +02004024 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004025 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004026 }
4027 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004028 /* we must not free the SSL_CTX anymore below, since it's already in
4029 * the tree, so it will be discovered and cleaned in time.
4030 */
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02004031
Emeric Brunfc0421f2012-09-07 17:30:07 +02004032#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004033 if (bind_conf->default_ctx) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02004034 memprintf(err, "%sthis version of openssl cannot load multiple SSL certificates.\n",
4035 err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02004036 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemandd9199372019-10-04 15:37:05 +02004037 goto error;
Emeric Brunfc0421f2012-09-07 17:30:07 +02004038 }
4039#endif
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004040 if (!bind_conf->default_ctx) {
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004041 bind_conf->default_ctx = ctx;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004042 bind_conf->default_ssl_conf = ssl_conf;
William Lallemand21724f02019-11-04 17:56:13 +01004043 ckch_inst->is_default = 1;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004044 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004045
William Lallemand9117de92019-10-04 00:29:42 +02004046 /* everything succeed, the ckch instance can be used */
4047 ckch_inst->bind_conf = bind_conf;
William Lallemand150bfa82019-09-19 17:12:49 +02004048 ckch_inst->ssl_conf = ssl_conf;
William Lallemand9117de92019-10-04 00:29:42 +02004049
Emeric Brun054563d2019-10-17 13:16:58 +02004050 *ckchi = ckch_inst;
4051 return errcode;
William Lallemandd9199372019-10-04 15:37:05 +02004052
4053error:
4054 /* free the allocated sni_ctxs */
William Lallemand614ca0d2019-10-07 13:52:11 +02004055 if (ckch_inst) {
William Lallemandd9199372019-10-04 15:37:05 +02004056 struct sni_ctx *sc0, *sc0b;
4057
4058 list_for_each_entry_safe(sc0, sc0b, &ckch_inst->sni_ctx, by_ckch_inst) {
4059
4060 ebmb_delete(&sc0->name);
4061 LIST_DEL(&sc0->by_ckch_inst);
4062 free(sc0);
4063 }
William Lallemand614ca0d2019-10-07 13:52:11 +02004064 free(ckch_inst);
4065 ckch_inst = NULL;
William Lallemandd9199372019-10-04 15:37:05 +02004066 }
4067 /* We only created 1 SSL_CTX so we can free it there */
4068 SSL_CTX_free(ctx);
4069
Emeric Brun054563d2019-10-17 13:16:58 +02004070 return errcode;
Emeric Brunfc0421f2012-09-07 17:30:07 +02004071}
4072
Willy Tarreau8c5414a2019-10-16 17:06:25 +02004073/* Returns a set of ERR_* flags possibly with an error in <err>. */
William Lallemand614ca0d2019-10-07 13:52:11 +02004074static int ssl_sock_load_ckchs(const char *path, struct ckch_store *ckchs,
4075 struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
4076 char **sni_filter, int fcount, char **err)
4077{
4078 struct ckch_inst *ckch_inst = NULL;
Emeric Brun054563d2019-10-17 13:16:58 +02004079 int errcode = 0;
William Lallemand614ca0d2019-10-07 13:52:11 +02004080
4081 /* we found the ckchs in the tree, we can use it directly */
4082 if (ckchs->multi)
Emeric Brun054563d2019-10-17 13:16:58 +02004083 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 +02004084 else
Emeric Brun054563d2019-10-17 13:16:58 +02004085 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 +02004086
Emeric Brun054563d2019-10-17 13:16:58 +02004087 if (errcode & ERR_CODE)
4088 return errcode;
William Lallemand614ca0d2019-10-07 13:52:11 +02004089
4090 ssl_sock_load_cert_sni(ckch_inst, bind_conf);
4091
4092 /* succeed, add the instance to the ckch_store's list of instance */
4093 LIST_ADDQ(&ckchs->ckch_inst, &ckch_inst->by_ckchs);
Emeric Brun054563d2019-10-17 13:16:58 +02004094 return errcode;
William Lallemand614ca0d2019-10-07 13:52:11 +02004095}
4096
4097
Willy Tarreaubbc91962019-10-16 16:42:19 +02004098/* Returns a set of ERR_* flags possibly with an error in <err>. */
Willy Tarreau03209342016-12-22 17:08:28 +01004099int ssl_sock_load_cert(char *path, struct bind_conf *bind_conf, char **err)
Emeric Brunfc0421f2012-09-07 17:30:07 +02004100{
Cyril Bonté3180f7b2015-01-25 00:16:08 +01004101 struct dirent **de_list;
4102 int i, n;
Emeric Brunfc0421f2012-09-07 17:30:07 +02004103 DIR *dir;
4104 struct stat buf;
Willy Tarreauee2663b2012-12-06 11:36:59 +01004105 char *end;
4106 char fp[MAXPATHLEN+1];
Emeric Brunfc0421f2012-09-07 17:30:07 +02004107 int cfgerr = 0;
William Lallemande3af8fb2019-10-08 11:36:53 +02004108 struct ckch_store *ckchs;
Willy Tarreau9a1ab082019-05-09 13:26:41 +02004109#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
yanbzhu63ea8462015-12-09 13:35:14 -05004110 int is_bundle;
4111 int j;
4112#endif
William Lallemande3af8fb2019-10-08 11:36:53 +02004113 if ((ckchs = ckchs_lookup(path))) {
William Lallemande3af8fb2019-10-08 11:36:53 +02004114 /* we found the ckchs in the tree, we can use it directly */
Willy Tarreau8c5414a2019-10-16 17:06:25 +02004115 return ssl_sock_load_ckchs(path, ckchs, bind_conf, NULL, NULL, 0, err);
William Lallemand6af03992019-07-23 15:00:54 +02004116 }
4117
yanbzhu08ce6ab2015-12-02 13:01:29 -05004118 if (stat(path, &buf) == 0) {
4119 dir = opendir(path);
William Lallemand36b84632019-07-18 19:28:17 +02004120 if (!dir) {
William Lallemande3af8fb2019-10-08 11:36:53 +02004121 ckchs = ckchs_load_cert_file(path, 0, err);
4122 if (!ckchs)
Willy Tarreaubbc91962019-10-16 16:42:19 +02004123 return ERR_ALERT | ERR_FATAL;
4124
Willy Tarreau8c5414a2019-10-16 17:06:25 +02004125 return ssl_sock_load_ckchs(path, ckchs, bind_conf, NULL, NULL, 0, err);
William Lallemand36b84632019-07-18 19:28:17 +02004126 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004127
yanbzhu08ce6ab2015-12-02 13:01:29 -05004128 /* strip trailing slashes, including first one */
4129 for (end = path + strlen(path) - 1; end >= path && *end == '/'; end--)
4130 *end = 0;
Emeric Brunfc0421f2012-09-07 17:30:07 +02004131
yanbzhu08ce6ab2015-12-02 13:01:29 -05004132 n = scandir(path, &de_list, 0, alphasort);
4133 if (n < 0) {
4134 memprintf(err, "%sunable to scan directory '%s' : %s.\n",
4135 err && *err ? *err : "", path, strerror(errno));
Willy Tarreaubbc91962019-10-16 16:42:19 +02004136 cfgerr |= ERR_ALERT | ERR_FATAL;
yanbzhu08ce6ab2015-12-02 13:01:29 -05004137 }
4138 else {
4139 for (i = 0; i < n; i++) {
4140 struct dirent *de = de_list[i];
Emeric Brun2aab7222014-06-18 18:15:09 +02004141
yanbzhu08ce6ab2015-12-02 13:01:29 -05004142 end = strrchr(de->d_name, '.');
4143 if (end && (!strcmp(end, ".issuer") || !strcmp(end, ".ocsp") || !strcmp(end, ".sctl")))
4144 goto ignore_entry;
Cyril Bonté3180f7b2015-01-25 00:16:08 +01004145
yanbzhu08ce6ab2015-12-02 13:01:29 -05004146 snprintf(fp, sizeof(fp), "%s/%s", path, de->d_name);
4147 if (stat(fp, &buf) != 0) {
4148 memprintf(err, "%sunable to stat SSL certificate from file '%s' : %s.\n",
4149 err && *err ? *err : "", fp, strerror(errno));
Willy Tarreaubbc91962019-10-16 16:42:19 +02004150 cfgerr |= ERR_ALERT | ERR_FATAL;
yanbzhu08ce6ab2015-12-02 13:01:29 -05004151 goto ignore_entry;
4152 }
4153 if (!S_ISREG(buf.st_mode))
4154 goto ignore_entry;
yanbzhu63ea8462015-12-09 13:35:14 -05004155
Willy Tarreau9a1ab082019-05-09 13:26:41 +02004156#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
yanbzhu63ea8462015-12-09 13:35:14 -05004157 is_bundle = 0;
4158 /* Check if current entry in directory is part of a multi-cert bundle */
4159
4160 if (end) {
4161 for (j = 0; j < SSL_SOCK_NUM_KEYTYPES; j++) {
4162 if (!strcmp(end + 1, SSL_SOCK_KEYTYPE_NAMES[j])) {
4163 is_bundle = 1;
4164 break;
4165 }
4166 }
4167
4168 if (is_bundle) {
yanbzhu63ea8462015-12-09 13:35:14 -05004169 int dp_len;
4170
4171 dp_len = end - de->d_name;
yanbzhu63ea8462015-12-09 13:35:14 -05004172
4173 /* increment i and free de until we get to a non-bundle cert
4174 * Note here that we look at de_list[i + 1] before freeing de
Willy Tarreau05800522019-10-29 10:48:50 +01004175 * this is important since ignore_entry will free de. This also
4176 * guarantees that de->d_name continues to hold the same prefix.
yanbzhu63ea8462015-12-09 13:35:14 -05004177 */
Willy Tarreau05800522019-10-29 10:48:50 +01004178 while (i + 1 < n && !strncmp(de_list[i + 1]->d_name, de->d_name, dp_len)) {
yanbzhu63ea8462015-12-09 13:35:14 -05004179 free(de);
4180 i++;
4181 de = de_list[i];
4182 }
4183
Willy Tarreau05800522019-10-29 10:48:50 +01004184 snprintf(fp, sizeof(fp), "%s/%.*s", path, dp_len, de->d_name);
William Lallemande3af8fb2019-10-08 11:36:53 +02004185 if ((ckchs = ckchs_lookup(fp)) == NULL)
4186 ckchs = ckchs_load_cert_file(fp, 1, err);
4187 if (!ckchs)
Willy Tarreaubbc91962019-10-16 16:42:19 +02004188 cfgerr |= ERR_ALERT | ERR_FATAL;
Willy Tarreau8c5414a2019-10-16 17:06:25 +02004189 else
4190 cfgerr |= ssl_sock_load_ckchs(path, ckchs, bind_conf, NULL, NULL, 0, err);
yanbzhu63ea8462015-12-09 13:35:14 -05004191 /* Successfully processed the bundle */
4192 goto ignore_entry;
4193 }
4194 }
4195
4196#endif
William Lallemande3af8fb2019-10-08 11:36:53 +02004197 if ((ckchs = ckchs_lookup(fp)) == NULL)
4198 ckchs = ckchs_load_cert_file(fp, 0, err);
4199 if (!ckchs)
Willy Tarreaubbc91962019-10-16 16:42:19 +02004200 cfgerr |= ERR_ALERT | ERR_FATAL;
William Lallemand614ca0d2019-10-07 13:52:11 +02004201 else
Willy Tarreau8c5414a2019-10-16 17:06:25 +02004202 cfgerr |= ssl_sock_load_ckchs(path, ckchs, bind_conf, NULL, NULL, 0, err);
William Lallemand36b84632019-07-18 19:28:17 +02004203
yanbzhu08ce6ab2015-12-02 13:01:29 -05004204ignore_entry:
4205 free(de);
Cyril Bonté3180f7b2015-01-25 00:16:08 +01004206 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05004207 free(de_list);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004208 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05004209 closedir(dir);
4210 return cfgerr;
Emeric Brunfc0421f2012-09-07 17:30:07 +02004211 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05004212
William Lallemande3af8fb2019-10-08 11:36:53 +02004213 ckchs = ckchs_load_cert_file(path, 1, err);
4214 if (!ckchs)
Willy Tarreaubbc91962019-10-16 16:42:19 +02004215 return ERR_ALERT | ERR_FATAL;
4216
Willy Tarreau8c5414a2019-10-16 17:06:25 +02004217 cfgerr |= ssl_sock_load_ckchs(path, ckchs, bind_conf, NULL, NULL, 0, err);
yanbzhu08ce6ab2015-12-02 13:01:29 -05004218
Emeric Brunfc0421f2012-09-07 17:30:07 +02004219 return cfgerr;
4220}
4221
Thierry Fournier383085f2013-01-24 14:15:43 +01004222/* Make sure openssl opens /dev/urandom before the chroot. The work is only
4223 * done once. Zero is returned if the operation fails. No error is returned
4224 * if the random is said as not implemented, because we expect that openssl
4225 * will use another method once needed.
4226 */
4227static int ssl_initialize_random()
4228{
4229 unsigned char random;
4230 static int random_initialized = 0;
4231
4232 if (!random_initialized && RAND_bytes(&random, 1) != 0)
4233 random_initialized = 1;
4234
4235 return random_initialized;
4236}
4237
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004238/* release ssl bind conf */
4239void ssl_sock_free_ssl_conf(struct ssl_bind_conf *conf)
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004240{
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004241 if (conf) {
Bernard Spil13c53f82018-02-15 13:34:58 +01004242#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004243 free(conf->npn_str);
4244 conf->npn_str = NULL;
4245#endif
4246#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
4247 free(conf->alpn_str);
4248 conf->alpn_str = NULL;
4249#endif
4250 free(conf->ca_file);
4251 conf->ca_file = NULL;
4252 free(conf->crl_file);
4253 conf->crl_file = NULL;
4254 free(conf->ciphers);
4255 conf->ciphers = NULL;
Emmanuel Hocdet839af572019-05-14 16:27:35 +02004256#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02004257 free(conf->ciphersuites);
4258 conf->ciphersuites = NULL;
4259#endif
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004260 free(conf->curves);
4261 conf->curves = NULL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004262 free(conf->ecdhe);
4263 conf->ecdhe = NULL;
4264 }
4265}
4266
Willy Tarreaubbc91962019-10-16 16:42:19 +02004267/* Returns a set of ERR_* flags possibly with an error in <err>. */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004268int ssl_sock_load_cert_list_file(char *file, struct bind_conf *bind_conf, struct proxy *curproxy, char **err)
4269{
4270 char thisline[CRT_LINESIZE];
4271 char path[MAXPATHLEN+1];
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004272 FILE *f;
yanbzhu1b04e5b2015-12-02 13:54:14 -05004273 struct stat buf;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004274 int linenum = 0;
4275 int cfgerr = 0;
William Lallemande3af8fb2019-10-08 11:36:53 +02004276 struct ckch_store *ckchs;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004277
Willy Tarreauad1731d2013-04-02 17:35:58 +02004278 if ((f = fopen(file, "r")) == NULL) {
4279 memprintf(err, "cannot open file '%s' : %s", file, strerror(errno));
Willy Tarreaubbc91962019-10-16 16:42:19 +02004280 return ERR_ALERT | ERR_FATAL;
Willy Tarreauad1731d2013-04-02 17:35:58 +02004281 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004282
4283 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004284 int arg, newarg, cur_arg, i, ssl_b = 0, ssl_e = 0;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004285 char *end;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004286 char *args[MAX_CRT_ARGS + 1];
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004287 char *line = thisline;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004288 char *crt_path;
4289 struct ssl_bind_conf *ssl_conf = NULL;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004290
4291 linenum++;
4292 end = line + strlen(line);
4293 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
4294 /* Check if we reached the limit and the last char is not \n.
4295 * Watch out for the last line without the terminating '\n'!
4296 */
Willy Tarreauad1731d2013-04-02 17:35:58 +02004297 memprintf(err, "line %d too long in file '%s', limit is %d characters",
4298 linenum, file, (int)sizeof(thisline)-1);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004299 cfgerr |= ERR_ALERT | ERR_FATAL;
Willy Tarreauad1731d2013-04-02 17:35:58 +02004300 break;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004301 }
4302
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004303 arg = 0;
Emeric Brun50bcecc2013-04-22 13:05:23 +02004304 newarg = 1;
4305 while (*line) {
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004306 if (*line == '#' || *line == '\n' || *line == '\r') {
4307 /* end of string, end of loop */
4308 *line = 0;
4309 break;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004310 } else if (isspace(*line)) {
Emeric Brun50bcecc2013-04-22 13:05:23 +02004311 newarg = 1;
4312 *line = 0;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004313 } else if (*line == '[') {
4314 if (ssl_b) {
4315 memprintf(err, "too many '[' on line %d in file '%s'.", linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004316 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004317 break;
4318 }
4319 if (!arg) {
4320 memprintf(err, "file must start with a cert on line %d in file '%s'", linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004321 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004322 break;
4323 }
4324 ssl_b = arg;
4325 newarg = 1;
4326 *line = 0;
4327 } else if (*line == ']') {
4328 if (ssl_e) {
4329 memprintf(err, "too many ']' on line %d in file '%s'.", linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004330 cfgerr |= ERR_ALERT | ERR_FATAL;
Emeric Brun50bcecc2013-04-22 13:05:23 +02004331 break;
4332 }
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004333 if (!ssl_b) {
4334 memprintf(err, "missing '[' in line %d in file '%s'.", linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004335 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004336 break;
4337 }
4338 ssl_e = arg;
4339 newarg = 1;
4340 *line = 0;
4341 } else if (newarg) {
4342 if (arg == MAX_CRT_ARGS) {
4343 memprintf(err, "too many args on line %d in file '%s'.", linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004344 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004345 break;
4346 }
Emeric Brun50bcecc2013-04-22 13:05:23 +02004347 newarg = 0;
4348 args[arg++] = line;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004349 }
Emeric Brun50bcecc2013-04-22 13:05:23 +02004350 line++;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004351 }
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02004352 if (cfgerr)
4353 break;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004354 args[arg++] = line;
Willy Tarreauad1731d2013-04-02 17:35:58 +02004355
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004356 /* empty line */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004357 if (!*args[0])
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004358 continue;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004359
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004360 crt_path = args[0];
4361 if (*crt_path != '/' && global_ssl.crt_base) {
4362 if ((strlen(global_ssl.crt_base) + 1 + strlen(crt_path)) > MAXPATHLEN) {
4363 memprintf(err, "'%s' : path too long on line %d in file '%s'",
4364 crt_path, linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004365 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004366 break;
4367 }
4368 snprintf(path, sizeof(path), "%s/%s", global_ssl.crt_base, crt_path);
4369 crt_path = path;
4370 }
4371
4372 ssl_conf = calloc(1, sizeof *ssl_conf);
4373 cur_arg = ssl_b ? ssl_b : 1;
4374 while (cur_arg < ssl_e) {
4375 newarg = 0;
4376 for (i = 0; ssl_bind_kws[i].kw != NULL; i++) {
4377 if (strcmp(ssl_bind_kws[i].kw, args[cur_arg]) == 0) {
4378 newarg = 1;
Willy Tarreaubbc91962019-10-16 16:42:19 +02004379 cfgerr |= ssl_bind_kws[i].parse(args, cur_arg, curproxy, ssl_conf, err);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004380 if (cur_arg + 1 + ssl_bind_kws[i].skip > ssl_e) {
4381 memprintf(err, "ssl args out of '[]' for %s on line %d in file '%s'",
4382 args[cur_arg], linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004383 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004384 }
4385 cur_arg += 1 + ssl_bind_kws[i].skip;
4386 break;
4387 }
4388 }
4389 if (!cfgerr && !newarg) {
4390 memprintf(err, "unknown ssl keyword %s on line %d in file '%s'.",
4391 args[cur_arg], linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004392 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004393 break;
4394 }
4395 }
Willy Tarreaubbc91962019-10-16 16:42:19 +02004396
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004397 if (cfgerr) {
4398 ssl_sock_free_ssl_conf(ssl_conf);
4399 free(ssl_conf);
4400 ssl_conf = NULL;
4401 break;
4402 }
4403
William Lallemande3af8fb2019-10-08 11:36:53 +02004404 if ((ckchs = ckchs_lookup(crt_path)) == NULL) {
William Lallemandeed4bf22019-10-10 11:38:13 +02004405 if (stat(crt_path, &buf) == 0)
William Lallemande3af8fb2019-10-08 11:36:53 +02004406 ckchs = ckchs_load_cert_file(crt_path, 0, err);
Emmanuel Hocdet1503e052019-07-31 18:30:33 +02004407 else
William Lallemande3af8fb2019-10-08 11:36:53 +02004408 ckchs = ckchs_load_cert_file(crt_path, 1, err);
yanbzhu1b04e5b2015-12-02 13:54:14 -05004409 }
4410
Willy Tarreau8c5414a2019-10-16 17:06:25 +02004411 if (!ckchs)
Willy Tarreaubbc91962019-10-16 16:42:19 +02004412 cfgerr |= ERR_ALERT | ERR_FATAL;
Willy Tarreau8c5414a2019-10-16 17:06:25 +02004413 else
4414 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 +02004415
Willy Tarreauad1731d2013-04-02 17:35:58 +02004416 if (cfgerr) {
4417 memprintf(err, "error processing line %d in file '%s' : %s", linenum, file, *err);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004418 break;
Willy Tarreauad1731d2013-04-02 17:35:58 +02004419 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004420 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004421 fclose(f);
4422 return cfgerr;
4423}
4424
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004425/* Create an initial CTX used to start the SSL connection before switchctx */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004426static int
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004427ssl_sock_initial_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02004428{
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004429 SSL_CTX *ctx = NULL;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004430 long options =
Emeric Brunfc0421f2012-09-07 17:30:07 +02004431 SSL_OP_ALL | /* all known workarounds for bugs */
4432 SSL_OP_NO_SSLv2 |
4433 SSL_OP_NO_COMPRESSION |
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02004434 SSL_OP_SINGLE_DH_USE |
Emeric Brun2b58d042012-09-20 17:10:03 +02004435 SSL_OP_SINGLE_ECDH_USE |
Emeric Brun3c4bc6e2012-10-04 18:44:19 +02004436 SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION |
Lukas Tribus926594f2018-05-18 17:55:57 +02004437 SSL_OP_PRIORITIZE_CHACHA |
Emeric Brun3c4bc6e2012-10-04 18:44:19 +02004438 SSL_OP_CIPHER_SERVER_PREFERENCE;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004439 long mode =
Emeric Brunfc0421f2012-09-07 17:30:07 +02004440 SSL_MODE_ENABLE_PARTIAL_WRITE |
4441 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
Willy Tarreau396a1862014-11-13 14:06:52 +01004442 SSL_MODE_RELEASE_BUFFERS |
4443 SSL_MODE_SMALL_BUFFERS;
Emmanuel Hocdet43664762017-08-09 18:26:20 +02004444 struct tls_version_filter *conf_ssl_methods = &bind_conf->ssl_conf.ssl_methods;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004445 int i, min, max, hole;
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004446 int flags = MC_SSL_O_ALL;
4447 int cfgerr = 0;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004448
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004449 ctx = SSL_CTX_new(SSLv23_server_method());
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004450 bind_conf->initial_ctx = ctx;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004451
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004452 if (conf_ssl_methods->flags && (conf_ssl_methods->min || conf_ssl_methods->max))
Christopher Faulet767a84b2017-11-24 16:50:31 +01004453 ha_warning("Proxy '%s': no-sslv3/no-tlsv1x are ignored for bind '%s' at [%s:%d]. "
4454 "Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
4455 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004456 else
4457 flags = conf_ssl_methods->flags;
4458
Emmanuel Hocdetbd695fe2017-05-15 15:53:41 +02004459 min = conf_ssl_methods->min;
4460 max = conf_ssl_methods->max;
4461 /* start with TLSv10 to remove SSLv3 per default */
4462 if (!min && (!max || max >= CONF_TLSV10))
4463 min = CONF_TLSV10;
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004464 /* Real min and max should be determinate with configuration and openssl's capabilities */
Emmanuel Hocdetbd695fe2017-05-15 15:53:41 +02004465 if (min)
4466 flags |= (methodVersions[min].flag - 1);
4467 if (max)
4468 flags |= ~((methodVersions[max].flag << 1) - 1);
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004469 /* find min, max and holes */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004470 min = max = CONF_TLSV_NONE;
4471 hole = 0;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004472 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004473 /* version is in openssl && version not disable in configuration */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004474 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004475 if (min) {
4476 if (hole) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004477 ha_warning("Proxy '%s': SSL/TLS versions range not contiguous for bind '%s' at [%s:%d]. "
4478 "Hole find for %s. Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
4479 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line,
4480 methodVersions[hole].name);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004481 hole = 0;
4482 }
4483 max = i;
4484 }
4485 else {
4486 min = max = i;
4487 }
4488 }
4489 else {
4490 if (min)
4491 hole = i;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004492 }
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004493 if (!min) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004494 ha_alert("Proxy '%s': all SSL/TLS versions are disabled for bind '%s' at [%s:%d].\n",
4495 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004496 cfgerr += 1;
4497 }
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02004498 /* save real min/max in bind_conf */
4499 conf_ssl_methods->min = min;
4500 conf_ssl_methods->max = max;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004501
Willy Tarreau9a1ab082019-05-09 13:26:41 +02004502#if (HA_OPENSSL_VERSION_NUMBER < 0x1010000fL)
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004503 /* Keep force-xxx implementation as it is in older haproxy. It's a
Joseph Herlant017b3da2018-11-15 09:07:59 -08004504 precautionary measure to avoid any surprise with older openssl version. */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004505 if (min == max)
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004506 methodVersions[min].ctx_set_version(ctx, SET_SERVER);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004507 else
4508 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
4509 if (flags & methodVersions[i].flag)
4510 options |= methodVersions[i].option;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004511#else /* openssl >= 1.1.0 */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004512 /* set the max_version is required to cap TLS version or activate new TLS (v1.3) */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004513 methodVersions[min].ctx_set_version(ctx, SET_MIN);
4514 methodVersions[max].ctx_set_version(ctx, SET_MAX);
Emeric Brunfa5c5c82017-04-28 16:19:51 +02004515#endif
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004516
4517 if (bind_conf->ssl_options & BC_SSL_O_NO_TLS_TICKETS)
4518 options |= SSL_OP_NO_TICKET;
4519 if (bind_conf->ssl_options & BC_SSL_O_PREF_CLIE_CIPH)
4520 options &= ~SSL_OP_CIPHER_SERVER_PREFERENCE;
Dirkjan Bussink526894f2019-01-21 09:35:03 -08004521
4522#ifdef SSL_OP_NO_RENEGOTIATION
4523 options |= SSL_OP_NO_RENEGOTIATION;
4524#endif
4525
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004526 SSL_CTX_set_options(ctx, options);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004527
Willy Tarreau5db847a2019-05-09 14:13:35 +02004528#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004529 if (global_ssl.async)
4530 mode |= SSL_MODE_ASYNC;
4531#endif
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004532 SSL_CTX_set_mode(ctx, mode);
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004533 if (global_ssl.life_time)
4534 SSL_CTX_set_timeout(ctx, global_ssl.life_time);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004535
4536#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
4537#ifdef OPENSSL_IS_BORINGSSL
4538 SSL_CTX_set_select_certificate_cb(ctx, ssl_sock_switchctx_cbk);
4539 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_err_cbk);
Willy Tarreau5db847a2019-05-09 14:13:35 +02004540#elif (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Olivier Houchard51088ce2019-01-02 18:46:41 +01004541 if (bind_conf->ssl_conf.early_data) {
4542 SSL_CTX_set_options(ctx, SSL_OP_NO_ANTI_REPLAY);
4543 SSL_CTX_set_max_early_data(ctx, global.tune.bufsize - global.tune.maxrewrite);
4544 }
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02004545 SSL_CTX_set_client_hello_cb(ctx, ssl_sock_switchctx_cbk, NULL);
4546 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_err_cbk);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004547#else
4548 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_cbk);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004549#endif
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02004550 SSL_CTX_set_tlsext_servername_arg(ctx, bind_conf);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004551#endif
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004552 return cfgerr;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004553}
4554
William Lallemand4f45bb92017-10-30 20:08:51 +01004555
4556static inline void sh_ssl_sess_free_blocks(struct shared_block *first, struct shared_block *block)
4557{
4558 if (first == block) {
4559 struct sh_ssl_sess_hdr *sh_ssl_sess = (struct sh_ssl_sess_hdr *)first->data;
4560 if (first->len > 0)
4561 sh_ssl_sess_tree_delete(sh_ssl_sess);
4562 }
4563}
4564
4565/* return first block from sh_ssl_sess */
4566static inline struct shared_block *sh_ssl_sess_first_block(struct sh_ssl_sess_hdr *sh_ssl_sess)
4567{
4568 return (struct shared_block *)((unsigned char *)sh_ssl_sess - ((struct shared_block *)NULL)->data);
4569
4570}
4571
4572/* store a session into the cache
4573 * s_id : session id padded with zero to SSL_MAX_SSL_SESSION_ID_LENGTH
4574 * data: asn1 encoded session
4575 * data_len: asn1 encoded session length
4576 * Returns 1 id session was stored (else 0)
4577 */
4578static int sh_ssl_sess_store(unsigned char *s_id, unsigned char *data, int data_len)
4579{
4580 struct shared_block *first;
4581 struct sh_ssl_sess_hdr *sh_ssl_sess, *oldsh_ssl_sess;
4582
Frédéric Lécaille0bec8072018-10-22 17:55:57 +02004583 first = shctx_row_reserve_hot(ssl_shctx, NULL, data_len + sizeof(struct sh_ssl_sess_hdr));
William Lallemand4f45bb92017-10-30 20:08:51 +01004584 if (!first) {
4585 /* Could not retrieve enough free blocks to store that session */
4586 return 0;
4587 }
4588
4589 /* STORE the key in the first elem */
4590 sh_ssl_sess = (struct sh_ssl_sess_hdr *)first->data;
4591 memcpy(sh_ssl_sess->key_data, s_id, SSL_MAX_SSL_SESSION_ID_LENGTH);
4592 first->len = sizeof(struct sh_ssl_sess_hdr);
4593
4594 /* it returns the already existing node
4595 or current node if none, never returns null */
4596 oldsh_ssl_sess = sh_ssl_sess_tree_insert(sh_ssl_sess);
4597 if (oldsh_ssl_sess != sh_ssl_sess) {
4598 /* NOTE: Row couldn't be in use because we lock read & write function */
4599 /* release the reserved row */
4600 shctx_row_dec_hot(ssl_shctx, first);
4601 /* replace the previous session already in the tree */
4602 sh_ssl_sess = oldsh_ssl_sess;
4603 /* ignore the previous session data, only use the header */
4604 first = sh_ssl_sess_first_block(sh_ssl_sess);
4605 shctx_row_inc_hot(ssl_shctx, first);
4606 first->len = sizeof(struct sh_ssl_sess_hdr);
4607 }
4608
Frédéric Lécaille0bec8072018-10-22 17:55:57 +02004609 if (shctx_row_data_append(ssl_shctx, first, NULL, data, data_len) < 0) {
William Lallemand99b90af2018-01-03 19:15:51 +01004610 shctx_row_dec_hot(ssl_shctx, first);
William Lallemand4f45bb92017-10-30 20:08:51 +01004611 return 0;
William Lallemand99b90af2018-01-03 19:15:51 +01004612 }
4613
4614 shctx_row_dec_hot(ssl_shctx, first);
William Lallemand4f45bb92017-10-30 20:08:51 +01004615
4616 return 1;
4617}
William Lallemanded0b5ad2017-10-30 19:36:36 +01004618
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004619/* SSL callback used when a new session is created while connecting to a server */
4620static int ssl_sess_new_srv_cb(SSL *ssl, SSL_SESSION *sess)
4621{
Thierry FOURNIER28962c92018-06-17 21:37:05 +02004622 struct connection *conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Olivier Houcharde6060c52017-11-16 17:42:52 +01004623 struct server *s;
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004624
Willy Tarreau07d94e42018-09-20 10:57:52 +02004625 s = __objt_server(conn->target);
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004626
Olivier Houcharde6060c52017-11-16 17:42:52 +01004627 if (!(s->ssl_ctx.options & SRV_SSL_O_NO_REUSE)) {
4628 int len;
4629 unsigned char *ptr;
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004630
Olivier Houcharde6060c52017-11-16 17:42:52 +01004631 len = i2d_SSL_SESSION(sess, NULL);
4632 if (s->ssl_ctx.reused_sess[tid].ptr && s->ssl_ctx.reused_sess[tid].allocated_size >= len) {
4633 ptr = s->ssl_ctx.reused_sess[tid].ptr;
4634 } else {
4635 free(s->ssl_ctx.reused_sess[tid].ptr);
4636 ptr = s->ssl_ctx.reused_sess[tid].ptr = malloc(len);
4637 s->ssl_ctx.reused_sess[tid].allocated_size = len;
4638 }
4639 if (s->ssl_ctx.reused_sess[tid].ptr) {
4640 s->ssl_ctx.reused_sess[tid].size = i2d_SSL_SESSION(sess,
4641 &ptr);
4642 }
4643 } else {
4644 free(s->ssl_ctx.reused_sess[tid].ptr);
4645 s->ssl_ctx.reused_sess[tid].ptr = NULL;
4646 }
4647
4648 return 0;
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004649}
4650
Olivier Houcharde6060c52017-11-16 17:42:52 +01004651
William Lallemanded0b5ad2017-10-30 19:36:36 +01004652/* SSL callback used on new session creation */
William Lallemand4f45bb92017-10-30 20:08:51 +01004653int sh_ssl_sess_new_cb(SSL *ssl, SSL_SESSION *sess)
William Lallemanded0b5ad2017-10-30 19:36:36 +01004654{
4655 unsigned char encsess[SHSESS_MAX_DATA_LEN]; /* encoded session */
4656 unsigned char encid[SSL_MAX_SSL_SESSION_ID_LENGTH]; /* encoded id */
4657 unsigned char *p;
4658 int data_len;
Emeric Bruneb469652019-10-08 18:27:37 +02004659 unsigned int sid_length;
William Lallemanded0b5ad2017-10-30 19:36:36 +01004660 const unsigned char *sid_data;
William Lallemanded0b5ad2017-10-30 19:36:36 +01004661
4662 /* Session id is already stored in to key and session id is known
4663 * so we dont store it to keep size.
Emeric Bruneb469652019-10-08 18:27:37 +02004664 * note: SSL_SESSION_set1_id is using
4665 * a memcpy so we need to use a different pointer
4666 * than sid_data or sid_ctx_data to avoid valgrind
4667 * complaining.
William Lallemanded0b5ad2017-10-30 19:36:36 +01004668 */
4669
4670 sid_data = SSL_SESSION_get_id(sess, &sid_length);
Emeric Bruneb469652019-10-08 18:27:37 +02004671
4672 /* copy value in an other buffer */
4673 memcpy(encid, sid_data, sid_length);
4674
4675 /* pad with 0 */
4676 if (sid_length < SSL_MAX_SSL_SESSION_ID_LENGTH)
4677 memset(encid + sid_length, 0, SSL_MAX_SSL_SESSION_ID_LENGTH-sid_length);
4678
4679 /* force length to zero to avoid ASN1 encoding */
4680 SSL_SESSION_set1_id(sess, encid, 0);
4681
4682 /* force length to zero to avoid ASN1 encoding */
4683 SSL_SESSION_set1_id_context(sess, (const unsigned char *)SHCTX_APPNAME, 0);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004684
4685 /* check if buffer is large enough for the ASN1 encoded session */
4686 data_len = i2d_SSL_SESSION(sess, NULL);
4687 if (data_len > SHSESS_MAX_DATA_LEN)
4688 goto err;
4689
4690 p = encsess;
4691
4692 /* process ASN1 session encoding before the lock */
4693 i2d_SSL_SESSION(sess, &p);
4694
William Lallemanded0b5ad2017-10-30 19:36:36 +01004695
William Lallemanda3c77cf2017-10-30 23:44:40 +01004696 shctx_lock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004697 /* store to cache */
William Lallemand4f45bb92017-10-30 20:08:51 +01004698 sh_ssl_sess_store(encid, encsess, data_len);
William Lallemanda3c77cf2017-10-30 23:44:40 +01004699 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004700err:
4701 /* reset original length values */
Emeric Bruneb469652019-10-08 18:27:37 +02004702 SSL_SESSION_set1_id(sess, encid, sid_length);
4703 SSL_SESSION_set1_id_context(sess, (const unsigned char *)SHCTX_APPNAME, strlen(SHCTX_APPNAME));
William Lallemanded0b5ad2017-10-30 19:36:36 +01004704
4705 return 0; /* do not increment session reference count */
4706}
4707
4708/* SSL callback used on lookup an existing session cause none found in internal cache */
William Lallemand4f45bb92017-10-30 20:08:51 +01004709SSL_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 +01004710{
William Lallemand4f45bb92017-10-30 20:08:51 +01004711 struct sh_ssl_sess_hdr *sh_ssl_sess;
William Lallemanded0b5ad2017-10-30 19:36:36 +01004712 unsigned char data[SHSESS_MAX_DATA_LEN], *p;
4713 unsigned char tmpkey[SSL_MAX_SSL_SESSION_ID_LENGTH];
William Lallemanded0b5ad2017-10-30 19:36:36 +01004714 SSL_SESSION *sess;
William Lallemand4f45bb92017-10-30 20:08:51 +01004715 struct shared_block *first;
William Lallemanded0b5ad2017-10-30 19:36:36 +01004716
4717 global.shctx_lookups++;
4718
4719 /* allow the session to be freed automatically by openssl */
4720 *do_copy = 0;
4721
4722 /* tree key is zeros padded sessionid */
4723 if (key_len < SSL_MAX_SSL_SESSION_ID_LENGTH) {
4724 memcpy(tmpkey, key, key_len);
4725 memset(tmpkey + key_len, 0, SSL_MAX_SSL_SESSION_ID_LENGTH - key_len);
4726 key = tmpkey;
4727 }
4728
4729 /* lock cache */
William Lallemanda3c77cf2017-10-30 23:44:40 +01004730 shctx_lock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004731
4732 /* lookup for session */
William Lallemand4f45bb92017-10-30 20:08:51 +01004733 sh_ssl_sess = sh_ssl_sess_tree_lookup(key);
4734 if (!sh_ssl_sess) {
William Lallemanded0b5ad2017-10-30 19:36:36 +01004735 /* no session found: unlock cache and exit */
William Lallemanda3c77cf2017-10-30 23:44:40 +01004736 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004737 global.shctx_misses++;
4738 return NULL;
4739 }
4740
William Lallemand4f45bb92017-10-30 20:08:51 +01004741 /* sh_ssl_sess (shared_block->data) is at the end of shared_block */
4742 first = sh_ssl_sess_first_block(sh_ssl_sess);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004743
William Lallemand4f45bb92017-10-30 20:08:51 +01004744 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 +01004745
William Lallemanda3c77cf2017-10-30 23:44:40 +01004746 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004747
4748 /* decode ASN1 session */
4749 p = data;
William Lallemand4f45bb92017-10-30 20:08:51 +01004750 sess = d2i_SSL_SESSION(NULL, (const unsigned char **)&p, first->len-sizeof(struct sh_ssl_sess_hdr));
William Lallemanded0b5ad2017-10-30 19:36:36 +01004751 /* Reset session id and session id contenxt */
4752 if (sess) {
4753 SSL_SESSION_set1_id(sess, key, key_len);
4754 SSL_SESSION_set1_id_context(sess, (const unsigned char *)SHCTX_APPNAME, strlen(SHCTX_APPNAME));
4755 }
4756
4757 return sess;
4758}
4759
William Lallemand4f45bb92017-10-30 20:08:51 +01004760
William Lallemanded0b5ad2017-10-30 19:36:36 +01004761/* SSL callback used to signal session is no more used in internal cache */
William Lallemand4f45bb92017-10-30 20:08:51 +01004762void sh_ssl_sess_remove_cb(SSL_CTX *ctx, SSL_SESSION *sess)
William Lallemanded0b5ad2017-10-30 19:36:36 +01004763{
William Lallemand4f45bb92017-10-30 20:08:51 +01004764 struct sh_ssl_sess_hdr *sh_ssl_sess;
William Lallemanded0b5ad2017-10-30 19:36:36 +01004765 unsigned char tmpkey[SSL_MAX_SSL_SESSION_ID_LENGTH];
4766 unsigned int sid_length;
4767 const unsigned char *sid_data;
4768 (void)ctx;
4769
4770 sid_data = SSL_SESSION_get_id(sess, &sid_length);
4771 /* tree key is zeros padded sessionid */
4772 if (sid_length < SSL_MAX_SSL_SESSION_ID_LENGTH) {
4773 memcpy(tmpkey, sid_data, sid_length);
4774 memset(tmpkey+sid_length, 0, SSL_MAX_SSL_SESSION_ID_LENGTH - sid_length);
4775 sid_data = tmpkey;
4776 }
4777
William Lallemanda3c77cf2017-10-30 23:44:40 +01004778 shctx_lock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004779
4780 /* lookup for session */
William Lallemand4f45bb92017-10-30 20:08:51 +01004781 sh_ssl_sess = sh_ssl_sess_tree_lookup(sid_data);
4782 if (sh_ssl_sess) {
William Lallemanded0b5ad2017-10-30 19:36:36 +01004783 /* free session */
William Lallemand4f45bb92017-10-30 20:08:51 +01004784 sh_ssl_sess_tree_delete(sh_ssl_sess);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004785 }
4786
4787 /* unlock cache */
William Lallemanda3c77cf2017-10-30 23:44:40 +01004788 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004789}
4790
4791/* Set session cache mode to server and disable openssl internal cache.
4792 * Set shared cache callbacks on an ssl context.
4793 * Shared context MUST be firstly initialized */
William Lallemand4f45bb92017-10-30 20:08:51 +01004794void ssl_set_shctx(SSL_CTX *ctx)
William Lallemanded0b5ad2017-10-30 19:36:36 +01004795{
4796 SSL_CTX_set_session_id_context(ctx, (const unsigned char *)SHCTX_APPNAME, strlen(SHCTX_APPNAME));
4797
4798 if (!ssl_shctx) {
4799 SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF);
4800 return;
4801 }
4802
4803 SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_SERVER |
4804 SSL_SESS_CACHE_NO_INTERNAL |
4805 SSL_SESS_CACHE_NO_AUTO_CLEAR);
4806
4807 /* Set callbacks */
William Lallemand4f45bb92017-10-30 20:08:51 +01004808 SSL_CTX_sess_set_new_cb(ctx, sh_ssl_sess_new_cb);
4809 SSL_CTX_sess_set_get_cb(ctx, sh_ssl_sess_get_cb);
4810 SSL_CTX_sess_set_remove_cb(ctx, sh_ssl_sess_remove_cb);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004811}
4812
William Lallemand8b453912019-11-21 15:48:10 +01004813/*
4814 * This function applies the SSL configuration on a SSL_CTX
4815 * It returns an error code and fills the <err> buffer
4816 */
4817int 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 +01004818{
4819 struct proxy *curproxy = bind_conf->frontend;
4820 int cfgerr = 0;
4821 int verify = SSL_VERIFY_NONE;
Willy Tarreau5d4cafb2018-01-04 18:55:19 +01004822 struct ssl_bind_conf __maybe_unused *ssl_conf_cur;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004823 const char *conf_ciphers;
Emmanuel Hocdet839af572019-05-14 16:27:35 +02004824#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02004825 const char *conf_ciphersuites;
4826#endif
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004827 const char *conf_curves = NULL;
Emeric Brunfc0421f2012-09-07 17:30:07 +02004828
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02004829 if (ssl_conf) {
4830 struct tls_version_filter *conf_ssl_methods = &ssl_conf->ssl_methods;
4831 int i, min, max;
4832 int flags = MC_SSL_O_ALL;
4833
4834 /* Real min and max should be determinate with configuration and openssl's capabilities */
Emmanuel Hocdet43664762017-08-09 18:26:20 +02004835 min = conf_ssl_methods->min ? conf_ssl_methods->min : bind_conf->ssl_conf.ssl_methods.min;
4836 max = conf_ssl_methods->max ? conf_ssl_methods->max : bind_conf->ssl_conf.ssl_methods.max;
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02004837 if (min)
4838 flags |= (methodVersions[min].flag - 1);
4839 if (max)
4840 flags |= ~((methodVersions[max].flag << 1) - 1);
4841 min = max = CONF_TLSV_NONE;
4842 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
4843 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
4844 if (min)
4845 max = i;
4846 else
4847 min = max = i;
4848 }
4849 /* save real min/max */
4850 conf_ssl_methods->min = min;
4851 conf_ssl_methods->max = max;
4852 if (!min) {
Tim Duesterhus93128532019-11-23 23:45:10 +01004853 memprintf(err, "%sProxy '%s': all SSL/TLS versions are disabled for bind '%s' at [%s:%d].\n",
4854 err && *err ? *err : "", bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
William Lallemand8b453912019-11-21 15:48:10 +01004855 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02004856 }
4857 }
4858
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004859 switch ((ssl_conf && ssl_conf->verify) ? ssl_conf->verify : bind_conf->ssl_conf.verify) {
Emeric Brun850efd52014-01-29 12:24:34 +01004860 case SSL_SOCK_VERIFY_NONE:
4861 verify = SSL_VERIFY_NONE;
4862 break;
4863 case SSL_SOCK_VERIFY_OPTIONAL:
4864 verify = SSL_VERIFY_PEER;
4865 break;
4866 case SSL_SOCK_VERIFY_REQUIRED:
4867 verify = SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
4868 break;
4869 }
4870 SSL_CTX_set_verify(ctx, verify, ssl_sock_bind_verifycbk);
4871 if (verify & SSL_VERIFY_PEER) {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004872 char *ca_file = (ssl_conf && ssl_conf->ca_file) ? ssl_conf->ca_file : bind_conf->ssl_conf.ca_file;
4873 char *crl_file = (ssl_conf && ssl_conf->crl_file) ? ssl_conf->crl_file : bind_conf->ssl_conf.crl_file;
4874 if (ca_file) {
Emeric Brund94b3fe2012-09-20 18:23:56 +02004875 /* load CAfile to verify */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004876 if (!SSL_CTX_load_verify_locations(ctx, ca_file, NULL)) {
Tim Duesterhus93128532019-11-23 23:45:10 +01004877 memprintf(err, "%sProxy '%s': unable to load CA file '%s' for bind '%s' at [%s:%d].\n",
4878 err && *err ? *err : "", curproxy->id, ca_file, bind_conf->arg, bind_conf->file, bind_conf->line);
William Lallemand8b453912019-11-21 15:48:10 +01004879 cfgerr |= ERR_ALERT | ERR_FATAL;
Emeric Brund94b3fe2012-09-20 18:23:56 +02004880 }
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02004881 if (!((ssl_conf && ssl_conf->no_ca_names) || bind_conf->ssl_conf.no_ca_names)) {
4882 /* set CA names for client cert request, function returns void */
4883 SSL_CTX_set_client_CA_list(ctx, SSL_load_client_CA_file(ca_file));
4884 }
Emeric Brund94b3fe2012-09-20 18:23:56 +02004885 }
Emeric Brun850efd52014-01-29 12:24:34 +01004886 else {
Tim Duesterhus93128532019-11-23 23:45:10 +01004887 memprintf(err, "%sProxy '%s': verify is enabled but no CA file specified for bind '%s' at [%s:%d].\n",
4888 err && *err ? *err : "", curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
William Lallemand8b453912019-11-21 15:48:10 +01004889 cfgerr |= ERR_ALERT | ERR_FATAL;
Emeric Brun850efd52014-01-29 12:24:34 +01004890 }
Emeric Brun051cdab2012-10-02 19:25:50 +02004891#ifdef X509_V_FLAG_CRL_CHECK
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004892 if (crl_file) {
Emeric Brund94b3fe2012-09-20 18:23:56 +02004893 X509_STORE *store = SSL_CTX_get_cert_store(ctx);
4894
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004895 if (!store || !X509_STORE_load_locations(store, crl_file, NULL)) {
Tim Duesterhus93128532019-11-23 23:45:10 +01004896 memprintf(err, "%sProxy '%s': unable to configure CRL file '%s' for bind '%s' at [%s:%d].\n",
4897 err && *err ? *err : "", curproxy->id, crl_file, bind_conf->arg, bind_conf->file, bind_conf->line);
William Lallemand8b453912019-11-21 15:48:10 +01004898 cfgerr |= ERR_ALERT | ERR_FATAL;
Emeric Brund94b3fe2012-09-20 18:23:56 +02004899 }
Emeric Brun561e5742012-10-02 15:20:55 +02004900 else {
4901 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
4902 }
Emeric Brund94b3fe2012-09-20 18:23:56 +02004903 }
Emeric Brun051cdab2012-10-02 19:25:50 +02004904#endif
Emeric Brun644cde02012-12-14 11:21:13 +01004905 ERR_clear_error();
Emeric Brund94b3fe2012-09-20 18:23:56 +02004906 }
Nenad Merdanovic05552d42015-02-27 19:56:49 +01004907#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
Nenad Merdanovic146defa2015-05-09 08:46:00 +02004908 if(bind_conf->keys_ref) {
Nenad Merdanovic05552d42015-02-27 19:56:49 +01004909 if (!SSL_CTX_set_tlsext_ticket_key_cb(ctx, ssl_tlsext_ticket_key_cb)) {
Tim Duesterhus93128532019-11-23 23:45:10 +01004910 memprintf(err, "%sProxy '%s': unable to set callback for TLS ticket validation for bind '%s' at [%s:%d].\n",
4911 err && *err ? *err : "", curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
William Lallemand8b453912019-11-21 15:48:10 +01004912 cfgerr |= ERR_ALERT | ERR_FATAL;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01004913 }
4914 }
4915#endif
4916
William Lallemand4f45bb92017-10-30 20:08:51 +01004917 ssl_set_shctx(ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004918 conf_ciphers = (ssl_conf && ssl_conf->ciphers) ? ssl_conf->ciphers : bind_conf->ssl_conf.ciphers;
4919 if (conf_ciphers &&
4920 !SSL_CTX_set_cipher_list(ctx, conf_ciphers)) {
Tim Duesterhus93128532019-11-23 23:45:10 +01004921 memprintf(err, "%sProxy '%s': unable to set SSL cipher list to '%s' for bind '%s' at [%s:%d].\n",
4922 err && *err ? *err : "", curproxy->id, conf_ciphers, bind_conf->arg, bind_conf->file, bind_conf->line);
William Lallemand8b453912019-11-21 15:48:10 +01004923 cfgerr |= ERR_ALERT | ERR_FATAL;
Emeric Brunfc0421f2012-09-07 17:30:07 +02004924 }
4925
Emmanuel Hocdet839af572019-05-14 16:27:35 +02004926#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02004927 conf_ciphersuites = (ssl_conf && ssl_conf->ciphersuites) ? ssl_conf->ciphersuites : bind_conf->ssl_conf.ciphersuites;
4928 if (conf_ciphersuites &&
4929 !SSL_CTX_set_ciphersuites(ctx, conf_ciphersuites)) {
Tim Duesterhus93128532019-11-23 23:45:10 +01004930 memprintf(err, "%sProxy '%s': unable to set TLS 1.3 cipher suites to '%s' for bind '%s' at [%s:%d].\n",
4931 err && *err ? *err : "", curproxy->id, conf_ciphersuites, bind_conf->arg, bind_conf->file, bind_conf->line);
William Lallemand8b453912019-11-21 15:48:10 +01004932 cfgerr |= ERR_ALERT | ERR_FATAL;
Dirkjan Bussink415150f2018-09-14 11:14:21 +02004933 }
4934#endif
4935
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01004936#ifndef OPENSSL_NO_DH
Remi Gacogne47783ef2015-05-29 15:53:22 +02004937 /* If tune.ssl.default-dh-param has not been set,
4938 neither has ssl-default-dh-file and no static DH
4939 params were in the certificate file. */
Willy Tarreauef934602016-12-22 23:12:01 +01004940 if (global_ssl.default_dh_param == 0 &&
Remi Gacogne47783ef2015-05-29 15:53:22 +02004941 global_dh == NULL &&
Remi Gacogne4f902b82015-05-28 16:23:00 +02004942 (ssl_dh_ptr_index == -1 ||
4943 SSL_CTX_get_ex_data(ctx, ssl_dh_ptr_index) == NULL)) {
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01004944 STACK_OF(SSL_CIPHER) * ciphers = NULL;
4945 const SSL_CIPHER * cipher = NULL;
4946 char cipher_description[128];
4947 /* The description of ciphers using an Ephemeral Diffie Hellman key exchange
4948 contains " Kx=DH " or " Kx=DH(". Beware of " Kx=DH/",
4949 which is not ephemeral DH. */
4950 const char dhe_description[] = " Kx=DH ";
4951 const char dhe_export_description[] = " Kx=DH(";
4952 int idx = 0;
4953 int dhe_found = 0;
4954 SSL *ssl = NULL;
Lukas Tribus90132722014-08-18 00:56:33 +02004955
Remi Gacogne23d5d372014-10-10 17:04:26 +02004956 ssl = SSL_new(ctx);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004957
Remi Gacogne23d5d372014-10-10 17:04:26 +02004958 if (ssl) {
4959 ciphers = SSL_get_ciphers(ssl);
4960
4961 if (ciphers) {
4962 for (idx = 0; idx < sk_SSL_CIPHER_num(ciphers); idx++) {
4963 cipher = sk_SSL_CIPHER_value(ciphers, idx);
4964 if (SSL_CIPHER_description(cipher, cipher_description, sizeof (cipher_description)) == cipher_description) {
4965 if (strstr(cipher_description, dhe_description) != NULL ||
4966 strstr(cipher_description, dhe_export_description) != NULL) {
4967 dhe_found = 1;
4968 break;
4969 }
Remi Gacognec1eab8c2014-06-12 18:20:11 +02004970 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004971 }
4972 }
Remi Gacogne23d5d372014-10-10 17:04:26 +02004973 SSL_free(ssl);
4974 ssl = NULL;
Lukas Tribus90132722014-08-18 00:56:33 +02004975 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004976
Lukas Tribus90132722014-08-18 00:56:33 +02004977 if (dhe_found) {
Tim Duesterhus93128532019-11-23 23:45:10 +01004978 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",
4979 err && *err ? *err : "");
William Lallemand8b453912019-11-21 15:48:10 +01004980 cfgerr |= ERR_WARN;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004981 }
4982
Willy Tarreauef934602016-12-22 23:12:01 +01004983 global_ssl.default_dh_param = 1024;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004984 }
Remi Gacogne8de54152014-07-15 11:36:40 +02004985
Willy Tarreauef934602016-12-22 23:12:01 +01004986 if (global_ssl.default_dh_param >= 1024) {
Remi Gacogne8de54152014-07-15 11:36:40 +02004987 if (local_dh_1024 == NULL) {
4988 local_dh_1024 = ssl_get_dh_1024();
4989 }
Willy Tarreauef934602016-12-22 23:12:01 +01004990 if (global_ssl.default_dh_param >= 2048) {
Remi Gacogne8de54152014-07-15 11:36:40 +02004991 if (local_dh_2048 == NULL) {
4992 local_dh_2048 = ssl_get_dh_2048();
4993 }
Willy Tarreauef934602016-12-22 23:12:01 +01004994 if (global_ssl.default_dh_param >= 4096) {
Remi Gacogne8de54152014-07-15 11:36:40 +02004995 if (local_dh_4096 == NULL) {
4996 local_dh_4096 = ssl_get_dh_4096();
4997 }
Remi Gacogne8de54152014-07-15 11:36:40 +02004998 }
4999 }
5000 }
5001#endif /* OPENSSL_NO_DH */
Remi Gacognef46cd6e2014-06-12 14:58:40 +02005002
Emeric Brunfc0421f2012-09-07 17:30:07 +02005003 SSL_CTX_set_info_callback(ctx, ssl_sock_infocbk);
Willy Tarreau9a1ab082019-05-09 13:26:41 +02005004#if HA_OPENSSL_VERSION_NUMBER >= 0x00907000L
Emeric Brun29f037d2014-04-25 19:05:36 +02005005 SSL_CTX_set_msg_callback(ctx, ssl_sock_msgcbk);
Willy Tarreau5cbe4ef2014-05-08 22:45:11 +02005006#endif
Emeric Brun29f037d2014-04-25 19:05:36 +02005007
Bernard Spil13c53f82018-02-15 13:34:58 +01005008#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005009 ssl_conf_cur = NULL;
5010 if (ssl_conf && ssl_conf->npn_str)
5011 ssl_conf_cur = ssl_conf;
5012 else if (bind_conf->ssl_conf.npn_str)
5013 ssl_conf_cur = &bind_conf->ssl_conf;
5014 if (ssl_conf_cur)
5015 SSL_CTX_set_next_protos_advertised_cb(ctx, ssl_sock_advertise_npn_protos, ssl_conf_cur);
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02005016#endif
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01005017#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005018 ssl_conf_cur = NULL;
5019 if (ssl_conf && ssl_conf->alpn_str)
5020 ssl_conf_cur = ssl_conf;
5021 else if (bind_conf->ssl_conf.alpn_str)
5022 ssl_conf_cur = &bind_conf->ssl_conf;
5023 if (ssl_conf_cur)
5024 SSL_CTX_set_alpn_select_cb(ctx, ssl_sock_advertise_alpn_protos, ssl_conf_cur);
Willy Tarreauab861d32013-04-02 02:30:41 +02005025#endif
Lukas Tribusd14b49c2019-11-24 18:20:40 +01005026#if ((HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL) || defined(LIBRESSL_VERSION_NUMBER))
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01005027 conf_curves = (ssl_conf && ssl_conf->curves) ? ssl_conf->curves : bind_conf->ssl_conf.curves;
5028 if (conf_curves) {
5029 if (!SSL_CTX_set1_curves_list(ctx, conf_curves)) {
Tim Duesterhus93128532019-11-23 23:45:10 +01005030 memprintf(err, "%sProxy '%s': unable to set SSL curves list to '%s' for bind '%s' at [%s:%d].\n",
5031 err && *err ? *err : "", curproxy->id, conf_curves, bind_conf->arg, bind_conf->file, bind_conf->line);
William Lallemand8b453912019-11-21 15:48:10 +01005032 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01005033 }
Emmanuel Hocdeta52bb152017-03-20 11:11:49 +01005034#if defined(SSL_CTX_set_ecdh_auto)
5035 (void)SSL_CTX_set_ecdh_auto(ctx, 1);
5036#endif
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01005037 }
5038#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02005039#if defined(SSL_CTX_set_tmp_ecdh) && !defined(OPENSSL_NO_ECDH)
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01005040 if (!conf_curves) {
Emeric Brun2b58d042012-09-20 17:10:03 +02005041 int i;
5042 EC_KEY *ecdh;
Willy Tarreau9a1ab082019-05-09 13:26:41 +02005043#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005044 const char *ecdhe = (ssl_conf && ssl_conf->ecdhe) ? ssl_conf->ecdhe :
Olivier Houchardc2aae742017-09-22 18:26:28 +02005045 (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe :
5046 NULL);
5047
5048 if (ecdhe == NULL) {
Eric Salama3c8bde82019-11-20 11:33:40 +01005049 (void)SSL_CTX_set_ecdh_auto(ctx, 1);
Olivier Houchardc2aae742017-09-22 18:26:28 +02005050 return cfgerr;
5051 }
5052#else
5053 const char *ecdhe = (ssl_conf && ssl_conf->ecdhe) ? ssl_conf->ecdhe :
5054 (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe :
5055 ECDHE_DEFAULT_CURVE);
5056#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02005057
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005058 i = OBJ_sn2nid(ecdhe);
Emeric Brun2b58d042012-09-20 17:10:03 +02005059 if (!i || ((ecdh = EC_KEY_new_by_curve_name(i)) == NULL)) {
Tim Duesterhus93128532019-11-23 23:45:10 +01005060 memprintf(err, "%sProxy '%s': unable to set elliptic named curve to '%s' for bind '%s' at [%s:%d].\n",
5061 err && *err ? *err : "", curproxy->id, ecdhe, bind_conf->arg, bind_conf->file, bind_conf->line);
William Lallemand8b453912019-11-21 15:48:10 +01005062 cfgerr |= ERR_ALERT | ERR_FATAL;
Emeric Brun2b58d042012-09-20 17:10:03 +02005063 }
5064 else {
5065 SSL_CTX_set_tmp_ecdh(ctx, ecdh);
5066 EC_KEY_free(ecdh);
5067 }
5068 }
5069#endif
5070
Emeric Brunfc0421f2012-09-07 17:30:07 +02005071 return cfgerr;
5072}
5073
Evan Broderbe554312013-06-27 00:05:25 -07005074static int ssl_sock_srv_hostcheck(const char *pattern, const char *hostname)
5075{
5076 const char *pattern_wildcard, *pattern_left_label_end, *hostname_left_label_end;
5077 size_t prefixlen, suffixlen;
5078
5079 /* Trivial case */
5080 if (strcmp(pattern, hostname) == 0)
5081 return 1;
5082
Evan Broderbe554312013-06-27 00:05:25 -07005083 /* The rest of this logic is based on RFC 6125, section 6.4.3
5084 * (http://tools.ietf.org/html/rfc6125#section-6.4.3) */
5085
Emeric Bruna848dae2013-10-08 11:27:28 +02005086 pattern_wildcard = NULL;
5087 pattern_left_label_end = pattern;
5088 while (*pattern_left_label_end != '.') {
5089 switch (*pattern_left_label_end) {
5090 case 0:
5091 /* End of label not found */
5092 return 0;
5093 case '*':
5094 /* If there is more than one wildcards */
5095 if (pattern_wildcard)
5096 return 0;
5097 pattern_wildcard = pattern_left_label_end;
5098 break;
5099 }
5100 pattern_left_label_end++;
5101 }
5102
5103 /* If it's not trivial and there is no wildcard, it can't
5104 * match */
5105 if (!pattern_wildcard)
Evan Broderbe554312013-06-27 00:05:25 -07005106 return 0;
5107
5108 /* Make sure all labels match except the leftmost */
5109 hostname_left_label_end = strchr(hostname, '.');
5110 if (!hostname_left_label_end
5111 || strcmp(pattern_left_label_end, hostname_left_label_end) != 0)
5112 return 0;
5113
5114 /* Make sure the leftmost label of the hostname is long enough
5115 * that the wildcard can match */
Emeric Brun369da852013-10-08 11:39:35 +02005116 if (hostname_left_label_end - hostname < (pattern_left_label_end - pattern) - 1)
Evan Broderbe554312013-06-27 00:05:25 -07005117 return 0;
5118
5119 /* Finally compare the string on either side of the
5120 * wildcard */
5121 prefixlen = pattern_wildcard - pattern;
5122 suffixlen = pattern_left_label_end - (pattern_wildcard + 1);
Emeric Bruna848dae2013-10-08 11:27:28 +02005123 if ((prefixlen && (memcmp(pattern, hostname, prefixlen) != 0))
5124 || (suffixlen && (memcmp(pattern_wildcard + 1, hostname_left_label_end - suffixlen, suffixlen) != 0)))
Evan Broderbe554312013-06-27 00:05:25 -07005125 return 0;
5126
5127 return 1;
5128}
5129
5130static int ssl_sock_srv_verifycbk(int ok, X509_STORE_CTX *ctx)
5131{
5132 SSL *ssl;
5133 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01005134 struct ssl_sock_ctx *ssl_ctx;
Willy Tarreau2ab88672017-07-05 18:23:03 +02005135 const char *servername;
Willy Tarreau71d058c2017-07-26 20:09:56 +02005136 const char *sni;
Evan Broderbe554312013-06-27 00:05:25 -07005137
5138 int depth;
5139 X509 *cert;
5140 STACK_OF(GENERAL_NAME) *alt_names;
5141 int i;
5142 X509_NAME *cert_subject;
5143 char *str;
5144
5145 if (ok == 0)
5146 return ok;
5147
5148 ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
Thierry FOURNIER28962c92018-06-17 21:37:05 +02005149 conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Olivier Houchard66ab4982019-02-26 18:37:15 +01005150 ssl_ctx = conn->xprt_ctx;
Evan Broderbe554312013-06-27 00:05:25 -07005151
Willy Tarreauad92a9a2017-07-28 11:38:41 +02005152 /* We're checking if the provided hostnames match the desired one. The
5153 * desired hostname comes from the SNI we presented if any, or if not
5154 * provided then it may have been explicitly stated using a "verifyhost"
5155 * directive. If neither is set, we don't care about the name so the
5156 * verification is OK.
Willy Tarreau2ab88672017-07-05 18:23:03 +02005157 */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005158 servername = SSL_get_servername(ssl_ctx->ssl, TLSEXT_NAMETYPE_host_name);
Willy Tarreau71d058c2017-07-26 20:09:56 +02005159 sni = servername;
Willy Tarreau2ab88672017-07-05 18:23:03 +02005160 if (!servername) {
Willy Tarreau07d94e42018-09-20 10:57:52 +02005161 servername = __objt_server(conn->target)->ssl_ctx.verify_host;
Willy Tarreau2ab88672017-07-05 18:23:03 +02005162 if (!servername)
5163 return ok;
5164 }
Evan Broderbe554312013-06-27 00:05:25 -07005165
5166 /* We only need to verify the CN on the actual server cert,
5167 * not the indirect CAs */
5168 depth = X509_STORE_CTX_get_error_depth(ctx);
5169 if (depth != 0)
5170 return ok;
5171
5172 /* At this point, the cert is *not* OK unless we can find a
5173 * hostname match */
5174 ok = 0;
5175
5176 cert = X509_STORE_CTX_get_current_cert(ctx);
5177 /* It seems like this might happen if verify peer isn't set */
5178 if (!cert)
5179 return ok;
5180
5181 alt_names = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
5182 if (alt_names) {
5183 for (i = 0; !ok && i < sk_GENERAL_NAME_num(alt_names); i++) {
5184 GENERAL_NAME *name = sk_GENERAL_NAME_value(alt_names, i);
5185 if (name->type == GEN_DNS) {
Willy Tarreau9a1ab082019-05-09 13:26:41 +02005186#if HA_OPENSSL_VERSION_NUMBER < 0x00907000L
Emeric Bruna33410c2013-09-17 15:47:48 +02005187 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.ia5) >= 0) {
5188#else
Evan Broderbe554312013-06-27 00:05:25 -07005189 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
Emeric Bruna33410c2013-09-17 15:47:48 +02005190#endif
Evan Broderbe554312013-06-27 00:05:25 -07005191 ok = ssl_sock_srv_hostcheck(str, servername);
5192 OPENSSL_free(str);
5193 }
5194 }
5195 }
Emeric Brun4ad50a42013-09-17 15:19:54 +02005196 sk_GENERAL_NAME_pop_free(alt_names, GENERAL_NAME_free);
Evan Broderbe554312013-06-27 00:05:25 -07005197 }
5198
5199 cert_subject = X509_get_subject_name(cert);
5200 i = -1;
5201 while (!ok && (i = X509_NAME_get_index_by_NID(cert_subject, NID_commonName, i)) != -1) {
5202 X509_NAME_ENTRY *entry = X509_NAME_get_entry(cert_subject, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005203 ASN1_STRING *value;
5204 value = X509_NAME_ENTRY_get_data(entry);
5205 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
Evan Broderbe554312013-06-27 00:05:25 -07005206 ok = ssl_sock_srv_hostcheck(str, servername);
5207 OPENSSL_free(str);
5208 }
5209 }
5210
Willy Tarreau71d058c2017-07-26 20:09:56 +02005211 /* report the mismatch and indicate if SNI was used or not */
5212 if (!ok && !conn->err_code)
5213 conn->err_code = sni ? CO_ER_SSL_MISMATCH_SNI : CO_ER_SSL_MISMATCH;
Evan Broderbe554312013-06-27 00:05:25 -07005214 return ok;
5215}
5216
Emeric Brun94324a42012-10-11 14:00:19 +02005217/* prepare ssl context from servers options. Returns an error count */
Willy Tarreau03209342016-12-22 17:08:28 +01005218int ssl_sock_prepare_srv_ctx(struct server *srv)
Emeric Brun94324a42012-10-11 14:00:19 +02005219{
Willy Tarreau03209342016-12-22 17:08:28 +01005220 struct proxy *curproxy = srv->proxy;
Emeric Brun94324a42012-10-11 14:00:19 +02005221 int cfgerr = 0;
Remi Gacogneaf5c3da2014-05-19 10:29:58 +02005222 long options =
Emeric Brun94324a42012-10-11 14:00:19 +02005223 SSL_OP_ALL | /* all known workarounds for bugs */
5224 SSL_OP_NO_SSLv2 |
5225 SSL_OP_NO_COMPRESSION;
Remi Gacogneaf5c3da2014-05-19 10:29:58 +02005226 long mode =
Emeric Brun94324a42012-10-11 14:00:19 +02005227 SSL_MODE_ENABLE_PARTIAL_WRITE |
5228 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
Willy Tarreau396a1862014-11-13 14:06:52 +01005229 SSL_MODE_RELEASE_BUFFERS |
5230 SSL_MODE_SMALL_BUFFERS;
Emeric Brun850efd52014-01-29 12:24:34 +01005231 int verify = SSL_VERIFY_NONE;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01005232 SSL_CTX *ctx = NULL;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005233 struct tls_version_filter *conf_ssl_methods = &srv->ssl_ctx.methods;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005234 int i, min, max, hole;
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005235 int flags = MC_SSL_O_ALL;
Emeric Brun94324a42012-10-11 14:00:19 +02005236
Thierry Fournier383085f2013-01-24 14:15:43 +01005237 /* Make sure openssl opens /dev/urandom before the chroot */
5238 if (!ssl_initialize_random()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005239 ha_alert("OpenSSL random data generator initialization failed.\n");
Thierry Fournier383085f2013-01-24 14:15:43 +01005240 cfgerr++;
5241 }
5242
Willy Tarreaufce03112015-01-15 21:32:40 +01005243 /* Automatic memory computations need to know we use SSL there */
5244 global.ssl_used_backend = 1;
5245
5246 /* Initiate SSL context for current server */
Emeric Brun821bb9b2017-06-15 16:37:39 +02005247 if (!srv->ssl_ctx.reused_sess) {
Olivier Houcharde6060c52017-11-16 17:42:52 +01005248 if ((srv->ssl_ctx.reused_sess = calloc(1, global.nbthread*sizeof(*srv->ssl_ctx.reused_sess))) == NULL) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005249 ha_alert("Proxy '%s', server '%s' [%s:%d] out of memory.\n",
5250 curproxy->id, srv->id,
5251 srv->conf.file, srv->conf.line);
Emeric Brun821bb9b2017-06-15 16:37:39 +02005252 cfgerr++;
5253 return cfgerr;
5254 }
5255 }
Emeric Brun94324a42012-10-11 14:00:19 +02005256 if (srv->use_ssl)
5257 srv->xprt = &ssl_sock;
5258 if (srv->check.use_ssl)
Cyril Bonté9ce13112014-11-15 22:41:27 +01005259 srv->check.xprt = &ssl_sock;
Emeric Brun94324a42012-10-11 14:00:19 +02005260
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005261 ctx = SSL_CTX_new(SSLv23_client_method());
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01005262 if (!ctx) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005263 ha_alert("config : %s '%s', server '%s': unable to allocate ssl context.\n",
5264 proxy_type_str(curproxy), curproxy->id,
5265 srv->id);
Emeric Brun94324a42012-10-11 14:00:19 +02005266 cfgerr++;
5267 return cfgerr;
5268 }
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005269
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005270 if (conf_ssl_methods->flags && (conf_ssl_methods->min || conf_ssl_methods->max))
Christopher Faulet767a84b2017-11-24 16:50:31 +01005271 ha_warning("config : %s '%s': no-sslv3/no-tlsv1x are ignored for server '%s'. "
5272 "Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
5273 proxy_type_str(curproxy), curproxy->id, srv->id);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005274 else
5275 flags = conf_ssl_methods->flags;
5276
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005277 /* Real min and max should be determinate with configuration and openssl's capabilities */
5278 if (conf_ssl_methods->min)
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005279 flags |= (methodVersions[conf_ssl_methods->min].flag - 1);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005280 if (conf_ssl_methods->max)
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005281 flags |= ~((methodVersions[conf_ssl_methods->max].flag << 1) - 1);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005282
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02005283 /* find min, max and holes */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005284 min = max = CONF_TLSV_NONE;
5285 hole = 0;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005286 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005287 /* version is in openssl && version not disable in configuration */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005288 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005289 if (min) {
5290 if (hole) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005291 ha_warning("config : %s '%s': SSL/TLS versions range not contiguous for server '%s'. "
5292 "Hole find for %s. Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
5293 proxy_type_str(curproxy), curproxy->id, srv->id,
5294 methodVersions[hole].name);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005295 hole = 0;
5296 }
5297 max = i;
5298 }
5299 else {
5300 min = max = i;
5301 }
5302 }
5303 else {
5304 if (min)
5305 hole = i;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005306 }
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005307 if (!min) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005308 ha_alert("config : %s '%s': all SSL/TLS versions are disabled for server '%s'.\n",
5309 proxy_type_str(curproxy), curproxy->id, srv->id);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005310 cfgerr += 1;
5311 }
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005312
Willy Tarreau9a1ab082019-05-09 13:26:41 +02005313#if (HA_OPENSSL_VERSION_NUMBER < 0x1010000fL)
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005314 /* Keep force-xxx implementation as it is in older haproxy. It's a
Joseph Herlant017b3da2018-11-15 09:07:59 -08005315 precautionary measure to avoid any surprise with older openssl version. */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005316 if (min == max)
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02005317 methodVersions[min].ctx_set_version(ctx, SET_CLIENT);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005318 else
5319 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
5320 if (flags & methodVersions[i].flag)
5321 options |= methodVersions[i].option;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005322#else /* openssl >= 1.1.0 */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005323 /* set the max_version is required to cap TLS version or activate new TLS (v1.3) */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02005324 methodVersions[min].ctx_set_version(ctx, SET_MIN);
5325 methodVersions[max].ctx_set_version(ctx, SET_MAX);
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005326#endif
5327
5328 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLS_TICKETS)
5329 options |= SSL_OP_NO_TICKET;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01005330 SSL_CTX_set_options(ctx, options);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005331
Willy Tarreau5db847a2019-05-09 14:13:35 +02005332#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005333 if (global_ssl.async)
5334 mode |= SSL_MODE_ASYNC;
5335#endif
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01005336 SSL_CTX_set_mode(ctx, mode);
5337 srv->ssl_ctx.ctx = ctx;
5338
Emeric Bruna7aa3092012-10-26 12:58:00 +02005339 if (srv->ssl_ctx.client_crt) {
5340 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 +01005341 ha_alert("config : %s '%s', server '%s': unable to load SSL private key from PEM file '%s'.\n",
5342 proxy_type_str(curproxy), curproxy->id,
5343 srv->id, srv->ssl_ctx.client_crt);
Emeric Bruna7aa3092012-10-26 12:58:00 +02005344 cfgerr++;
5345 }
5346 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 +01005347 ha_alert("config : %s '%s', server '%s': unable to load ssl certificate from PEM file '%s'.\n",
5348 proxy_type_str(curproxy), curproxy->id,
5349 srv->id, srv->ssl_ctx.client_crt);
Emeric Bruna7aa3092012-10-26 12:58:00 +02005350 cfgerr++;
5351 }
5352 else if (SSL_CTX_check_private_key(srv->ssl_ctx.ctx) <= 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005353 ha_alert("config : %s '%s', server '%s': inconsistencies between private key and certificate loaded from PEM file '%s'.\n",
5354 proxy_type_str(curproxy), curproxy->id,
5355 srv->id, srv->ssl_ctx.client_crt);
Emeric Bruna7aa3092012-10-26 12:58:00 +02005356 cfgerr++;
5357 }
5358 }
Emeric Brun94324a42012-10-11 14:00:19 +02005359
Emeric Brun850efd52014-01-29 12:24:34 +01005360 if (global.ssl_server_verify == SSL_SERVER_VERIFY_REQUIRED)
5361 verify = SSL_VERIFY_PEER;
Emeric Brun850efd52014-01-29 12:24:34 +01005362 switch (srv->ssl_ctx.verify) {
5363 case SSL_SOCK_VERIFY_NONE:
5364 verify = SSL_VERIFY_NONE;
5365 break;
5366 case SSL_SOCK_VERIFY_REQUIRED:
5367 verify = SSL_VERIFY_PEER;
5368 break;
5369 }
Evan Broderbe554312013-06-27 00:05:25 -07005370 SSL_CTX_set_verify(srv->ssl_ctx.ctx,
Emeric Brun850efd52014-01-29 12:24:34 +01005371 verify,
Willy Tarreau2ab88672017-07-05 18:23:03 +02005372 (srv->ssl_ctx.verify_host || (verify & SSL_VERIFY_PEER)) ? ssl_sock_srv_verifycbk : NULL);
Emeric Brun850efd52014-01-29 12:24:34 +01005373 if (verify & SSL_VERIFY_PEER) {
Emeric Brunef42d922012-10-11 16:11:36 +02005374 if (srv->ssl_ctx.ca_file) {
5375 /* load CAfile to verify */
5376 if (!SSL_CTX_load_verify_locations(srv->ssl_ctx.ctx, srv->ssl_ctx.ca_file, NULL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005377 ha_alert("Proxy '%s', server '%s' [%s:%d] unable to load CA file '%s'.\n",
5378 curproxy->id, srv->id,
5379 srv->conf.file, srv->conf.line, srv->ssl_ctx.ca_file);
Emeric Brunef42d922012-10-11 16:11:36 +02005380 cfgerr++;
5381 }
5382 }
Emeric Brun850efd52014-01-29 12:24:34 +01005383 else {
5384 if (global.ssl_server_verify == SSL_SERVER_VERIFY_REQUIRED)
Christopher Faulet767a84b2017-11-24 16:50:31 +01005385 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",
5386 curproxy->id, srv->id,
5387 srv->conf.file, srv->conf.line);
Emeric Brun850efd52014-01-29 12:24:34 +01005388 else
Christopher Faulet767a84b2017-11-24 16:50:31 +01005389 ha_alert("Proxy '%s', server '%s' [%s:%d] verify is enabled but no CA file specified.\n",
5390 curproxy->id, srv->id,
5391 srv->conf.file, srv->conf.line);
Emeric Brun850efd52014-01-29 12:24:34 +01005392 cfgerr++;
5393 }
Emeric Brunef42d922012-10-11 16:11:36 +02005394#ifdef X509_V_FLAG_CRL_CHECK
5395 if (srv->ssl_ctx.crl_file) {
5396 X509_STORE *store = SSL_CTX_get_cert_store(srv->ssl_ctx.ctx);
5397
5398 if (!store || !X509_STORE_load_locations(store, srv->ssl_ctx.crl_file, NULL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005399 ha_alert("Proxy '%s', server '%s' [%s:%d] unable to configure CRL file '%s'.\n",
5400 curproxy->id, srv->id,
5401 srv->conf.file, srv->conf.line, srv->ssl_ctx.crl_file);
Emeric Brunef42d922012-10-11 16:11:36 +02005402 cfgerr++;
5403 }
5404 else {
5405 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
5406 }
5407 }
5408#endif
5409 }
5410
Olivier Houchardbd84ac82017-11-03 13:43:35 +01005411 SSL_CTX_set_session_cache_mode(srv->ssl_ctx.ctx, SSL_SESS_CACHE_CLIENT |
5412 SSL_SESS_CACHE_NO_INTERNAL_STORE);
5413 SSL_CTX_sess_set_new_cb(srv->ssl_ctx.ctx, ssl_sess_new_srv_cb);
Emeric Brun94324a42012-10-11 14:00:19 +02005414 if (srv->ssl_ctx.ciphers &&
5415 !SSL_CTX_set_cipher_list(srv->ssl_ctx.ctx, srv->ssl_ctx.ciphers)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005416 ha_alert("Proxy '%s', server '%s' [%s:%d] : unable to set SSL cipher list to '%s'.\n",
5417 curproxy->id, srv->id,
5418 srv->conf.file, srv->conf.line, srv->ssl_ctx.ciphers);
Emeric Brun94324a42012-10-11 14:00:19 +02005419 cfgerr++;
5420 }
Dirkjan Bussink415150f2018-09-14 11:14:21 +02005421
Emmanuel Hocdet839af572019-05-14 16:27:35 +02005422#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02005423 if (srv->ssl_ctx.ciphersuites &&
Pierre Cheynierbc34cd12019-03-21 16:15:47 +00005424 !SSL_CTX_set_ciphersuites(srv->ssl_ctx.ctx, srv->ssl_ctx.ciphersuites)) {
Dirkjan Bussink415150f2018-09-14 11:14:21 +02005425 ha_alert("Proxy '%s', server '%s' [%s:%d] : unable to set TLS 1.3 cipher suites to '%s'.\n",
5426 curproxy->id, srv->id,
5427 srv->conf.file, srv->conf.line, srv->ssl_ctx.ciphersuites);
5428 cfgerr++;
5429 }
5430#endif
Olivier Houchardc7566002018-11-20 23:33:50 +01005431#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
5432 if (srv->ssl_ctx.npn_str)
5433 SSL_CTX_set_next_proto_select_cb(ctx, ssl_sock_srv_select_protos, srv);
5434#endif
5435#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
5436 if (srv->ssl_ctx.alpn_str)
5437 SSL_CTX_set_alpn_protos(ctx, (unsigned char *)srv->ssl_ctx.alpn_str, srv->ssl_ctx.alpn_len);
5438#endif
5439
Emeric Brun94324a42012-10-11 14:00:19 +02005440
5441 return cfgerr;
5442}
5443
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005444/* Walks down the two trees in bind_conf and prepares all certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +02005445 * be NULL, in which case nothing is done. Returns the number of errors
5446 * encountered.
5447 */
Willy Tarreau03209342016-12-22 17:08:28 +01005448int ssl_sock_prepare_all_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02005449{
5450 struct ebmb_node *node;
5451 struct sni_ctx *sni;
5452 int err = 0;
William Lallemand8b453912019-11-21 15:48:10 +01005453 int errcode = 0;
5454 char *errmsg = NULL;
Emeric Brunfc0421f2012-09-07 17:30:07 +02005455
Willy Tarreaufce03112015-01-15 21:32:40 +01005456 /* Automatic memory computations need to know we use SSL there */
5457 global.ssl_used_frontend = 1;
5458
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01005459 /* Make sure openssl opens /dev/urandom before the chroot */
5460 if (!ssl_initialize_random()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005461 ha_alert("OpenSSL random data generator initialization failed.\n");
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01005462 err++;
5463 }
5464 /* Create initial_ctx used to start the ssl connection before do switchctx */
5465 if (!bind_conf->initial_ctx) {
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005466 err += ssl_sock_initial_ctx(bind_conf);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01005467 /* It should not be necessary to call this function, but it's
5468 necessary first to check and move all initialisation related
5469 to initial_ctx in ssl_sock_initial_ctx. */
William Lallemand8b453912019-11-21 15:48:10 +01005470 errcode |= ssl_sock_prepare_ctx(bind_conf, NULL, bind_conf->initial_ctx, &errmsg);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01005471 }
Emeric Brun0bed9942014-10-30 19:25:24 +01005472 if (bind_conf->default_ctx)
William Lallemand8b453912019-11-21 15:48:10 +01005473 errcode |= ssl_sock_prepare_ctx(bind_conf, bind_conf->default_ssl_conf, bind_conf->default_ctx, &errmsg);
Emeric Brun0bed9942014-10-30 19:25:24 +01005474
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005475 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02005476 while (node) {
5477 sni = ebmb_entry(node, struct sni_ctx, name);
Emeric Brun0bed9942014-10-30 19:25:24 +01005478 if (!sni->order && sni->ctx != bind_conf->default_ctx)
5479 /* only initialize the CTX on its first occurrence and
5480 if it is not the default_ctx */
William Lallemand8b453912019-11-21 15:48:10 +01005481 errcode |= ssl_sock_prepare_ctx(bind_conf, sni->conf, sni->ctx, &errmsg);
Emeric Brunfc0421f2012-09-07 17:30:07 +02005482 node = ebmb_next(node);
5483 }
5484
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005485 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02005486 while (node) {
5487 sni = ebmb_entry(node, struct sni_ctx, name);
William Lallemand8b453912019-11-21 15:48:10 +01005488 if (!sni->order && sni->ctx != bind_conf->default_ctx) {
Emeric Brun0bed9942014-10-30 19:25:24 +01005489 /* 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);
5492 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02005493 node = ebmb_next(node);
5494 }
William Lallemand8b453912019-11-21 15:48:10 +01005495
5496 if (errcode & ERR_WARN) {
Tim Duesterhusc0e820c2019-11-23 23:52:30 +01005497 ha_warning("%s", errmsg);
William Lallemand8b453912019-11-21 15:48:10 +01005498 } else if (errcode & ERR_CODE) {
Tim Duesterhusc0e820c2019-11-23 23:52:30 +01005499 ha_alert("%s", errmsg);
William Lallemand8b453912019-11-21 15:48:10 +01005500 err++;
5501 }
5502
5503 free(errmsg);
Emeric Brunfc0421f2012-09-07 17:30:07 +02005504 return err;
5505}
5506
Willy Tarreau55d37912016-12-21 23:38:39 +01005507/* Prepares all the contexts for a bind_conf and allocates the shared SSL
5508 * context if needed. Returns < 0 on error, 0 on success. The warnings and
5509 * alerts are directly emitted since the rest of the stack does it below.
5510 */
5511int ssl_sock_prepare_bind_conf(struct bind_conf *bind_conf)
5512{
5513 struct proxy *px = bind_conf->frontend;
5514 int alloc_ctx;
5515 int err;
5516
5517 if (!bind_conf->is_ssl) {
5518 if (bind_conf->default_ctx) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005519 ha_warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
5520 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreau55d37912016-12-21 23:38:39 +01005521 }
5522 return 0;
5523 }
5524 if (!bind_conf->default_ctx) {
Emmanuel Hocdetaa0d6372017-08-09 11:24:25 +02005525 if (bind_conf->strict_sni && !bind_conf->generate_certs) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005526 ha_warning("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d], ssl connections will fail (use 'crt').\n",
5527 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetaa0d6372017-08-09 11:24:25 +02005528 }
5529 else {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005530 ha_alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
5531 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetaa0d6372017-08-09 11:24:25 +02005532 return -1;
5533 }
Willy Tarreau55d37912016-12-21 23:38:39 +01005534 }
William Lallemandc61c0b32017-12-04 18:46:39 +01005535 if (!ssl_shctx && global.tune.sslcachesize) {
William Lallemandc3cd35f2017-11-28 11:04:43 +01005536 alloc_ctx = shctx_init(&ssl_shctx, global.tune.sslcachesize,
Frédéric Lécailleb7838af2018-10-22 16:21:39 +02005537 sizeof(struct sh_ssl_sess_hdr) + SHSESS_BLOCK_MIN_SIZE, -1,
William Lallemandc3cd35f2017-11-28 11:04:43 +01005538 sizeof(*sh_ssl_sess_tree),
5539 ((global.nbthread > 1) || (!global_ssl.private_cache && (global.nbproc > 1))) ? 1 : 0);
Frédéric Lécaille4c8aa112018-10-25 20:22:46 +02005540 if (alloc_ctx <= 0) {
William Lallemandc3cd35f2017-11-28 11:04:43 +01005541 if (alloc_ctx == SHCTX_E_INIT_LOCK)
5542 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");
5543 else
5544 ha_alert("Unable to allocate SSL session cache.\n");
5545 return -1;
5546 }
5547 /* free block callback */
5548 ssl_shctx->free_block = sh_ssl_sess_free_blocks;
5549 /* init the root tree within the extra space */
5550 sh_ssl_sess_tree = (void *)ssl_shctx + sizeof(struct shared_context);
5551 *sh_ssl_sess_tree = EB_ROOT_UNIQUE;
Willy Tarreau55d37912016-12-21 23:38:39 +01005552 }
Willy Tarreau55d37912016-12-21 23:38:39 +01005553 err = 0;
5554 /* initialize all certificate contexts */
5555 err += ssl_sock_prepare_all_ctx(bind_conf);
5556
5557 /* initialize CA variables if the certificates generation is enabled */
5558 err += ssl_sock_load_ca(bind_conf);
5559
5560 return -err;
5561}
Christopher Faulet77fe80c2015-07-29 13:02:40 +02005562
5563/* release ssl context allocated for servers. */
5564void ssl_sock_free_srv_ctx(struct server *srv)
5565{
Olivier Houchardc7566002018-11-20 23:33:50 +01005566#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
5567 if (srv->ssl_ctx.alpn_str)
5568 free(srv->ssl_ctx.alpn_str);
5569#endif
Lukas Tribusda95fd92018-11-25 13:21:27 +01005570#ifdef OPENSSL_NPN_NEGOTIATED
Olivier Houchardc7566002018-11-20 23:33:50 +01005571 if (srv->ssl_ctx.npn_str)
5572 free(srv->ssl_ctx.npn_str);
Lukas Tribus7706b852018-11-26 22:57:17 +01005573#endif
Christopher Faulet77fe80c2015-07-29 13:02:40 +02005574 if (srv->ssl_ctx.ctx)
5575 SSL_CTX_free(srv->ssl_ctx.ctx);
5576}
5577
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005578/* Walks down the two trees in bind_conf and frees all the certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +02005579 * be NULL, in which case nothing is done. The default_ctx is nullified too.
5580 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005581void ssl_sock_free_all_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02005582{
5583 struct ebmb_node *node, *back;
5584 struct sni_ctx *sni;
5585
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005586 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02005587 while (node) {
5588 sni = ebmb_entry(node, struct sni_ctx, name);
5589 back = ebmb_next(node);
5590 ebmb_delete(node);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005591 if (!sni->order) { /* only free the CTX on its first occurrence */
Emeric Brunfc0421f2012-09-07 17:30:07 +02005592 SSL_CTX_free(sni->ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005593 ssl_sock_free_ssl_conf(sni->conf);
5594 free(sni->conf);
5595 sni->conf = NULL;
5596 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02005597 free(sni);
5598 node = back;
5599 }
5600
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005601 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02005602 while (node) {
5603 sni = ebmb_entry(node, struct sni_ctx, name);
5604 back = ebmb_next(node);
5605 ebmb_delete(node);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005606 if (!sni->order) { /* only free the CTX on its first occurrence */
Emeric Brunfc0421f2012-09-07 17:30:07 +02005607 SSL_CTX_free(sni->ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005608 ssl_sock_free_ssl_conf(sni->conf);
5609 free(sni->conf);
5610 sni->conf = NULL;
5611 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02005612 free(sni);
5613 node = back;
5614 }
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01005615 SSL_CTX_free(bind_conf->initial_ctx);
5616 bind_conf->initial_ctx = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005617 bind_conf->default_ctx = NULL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005618 bind_conf->default_ssl_conf = NULL;
Emeric Brune1f38db2012-09-03 20:36:47 +02005619}
5620
Willy Tarreau795cdab2016-12-22 17:30:54 +01005621/* Destroys all the contexts for a bind_conf. This is used during deinit(). */
5622void ssl_sock_destroy_bind_conf(struct bind_conf *bind_conf)
5623{
5624 ssl_sock_free_ca(bind_conf);
5625 ssl_sock_free_all_ctx(bind_conf);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005626 ssl_sock_free_ssl_conf(&bind_conf->ssl_conf);
Willy Tarreau795cdab2016-12-22 17:30:54 +01005627 free(bind_conf->ca_sign_file);
5628 free(bind_conf->ca_sign_pass);
Willy Tarreau17b4aa12018-07-17 10:05:32 +02005629 if (bind_conf->keys_ref && !--bind_conf->keys_ref->refcount) {
Willy Tarreau795cdab2016-12-22 17:30:54 +01005630 free(bind_conf->keys_ref->filename);
5631 free(bind_conf->keys_ref->tlskeys);
5632 LIST_DEL(&bind_conf->keys_ref->list);
5633 free(bind_conf->keys_ref);
5634 }
5635 bind_conf->keys_ref = NULL;
Willy Tarreau795cdab2016-12-22 17:30:54 +01005636 bind_conf->ca_sign_pass = NULL;
5637 bind_conf->ca_sign_file = NULL;
Willy Tarreau795cdab2016-12-22 17:30:54 +01005638}
5639
Christopher Faulet31af49d2015-06-09 17:29:50 +02005640/* Load CA cert file and private key used to generate certificates */
5641int
Willy Tarreau03209342016-12-22 17:08:28 +01005642ssl_sock_load_ca(struct bind_conf *bind_conf)
Christopher Faulet31af49d2015-06-09 17:29:50 +02005643{
Willy Tarreau03209342016-12-22 17:08:28 +01005644 struct proxy *px = bind_conf->frontend;
Christopher Faulet31af49d2015-06-09 17:29:50 +02005645 FILE *fp;
5646 X509 *cacert = NULL;
5647 EVP_PKEY *capkey = NULL;
5648 int err = 0;
5649
Christopher Fauletf8bb0ce2017-09-15 09:52:49 +02005650 if (!bind_conf->generate_certs)
Christopher Faulet31af49d2015-06-09 17:29:50 +02005651 return err;
5652
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005653#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Emeric Brun821bb9b2017-06-15 16:37:39 +02005654 if (global_ssl.ctx_cache) {
Willy Tarreauef934602016-12-22 23:12:01 +01005655 ssl_ctx_lru_tree = lru64_new(global_ssl.ctx_cache);
Emeric Brun821bb9b2017-06-15 16:37:39 +02005656 }
Christopher Fauletd2cab922015-07-28 16:03:47 +02005657 ssl_ctx_lru_seed = (unsigned int)time(NULL);
Emeric Brun821bb9b2017-06-15 16:37:39 +02005658 ssl_ctx_serial = now_ms;
Willy Tarreaua84c2672015-10-09 12:10:13 +02005659#endif
Christopher Fauletd2cab922015-07-28 16:03:47 +02005660
Christopher Faulet31af49d2015-06-09 17:29:50 +02005661 if (!bind_conf->ca_sign_file) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005662 ha_alert("Proxy '%s': cannot enable certificate generation, "
5663 "no CA certificate File configured at [%s:%d].\n",
5664 px->id, bind_conf->file, bind_conf->line);
Christopher Faulet31af49d2015-06-09 17:29:50 +02005665 goto load_error;
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005666 }
Christopher Faulet31af49d2015-06-09 17:29:50 +02005667
5668 /* read in the CA certificate */
5669 if (!(fp = fopen(bind_conf->ca_sign_file, "r"))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005670 ha_alert("Proxy '%s': Failed to read CA certificate file '%s' at [%s:%d].\n",
5671 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Faulet31af49d2015-06-09 17:29:50 +02005672 goto load_error;
5673 }
5674 if (!(cacert = PEM_read_X509(fp, NULL, NULL, NULL))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005675 ha_alert("Proxy '%s': Failed to read CA certificate file '%s' at [%s:%d].\n",
5676 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005677 goto read_error;
Christopher Faulet31af49d2015-06-09 17:29:50 +02005678 }
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005679 rewind(fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02005680 if (!(capkey = PEM_read_PrivateKey(fp, NULL, NULL, bind_conf->ca_sign_pass))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005681 ha_alert("Proxy '%s': Failed to read CA private key file '%s' at [%s:%d].\n",
5682 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005683 goto read_error;
Christopher Faulet31af49d2015-06-09 17:29:50 +02005684 }
Christopher Faulet31af49d2015-06-09 17:29:50 +02005685
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005686 fclose (fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02005687 bind_conf->ca_sign_cert = cacert;
5688 bind_conf->ca_sign_pkey = capkey;
5689 return err;
5690
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005691 read_error:
5692 fclose (fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02005693 if (capkey) EVP_PKEY_free(capkey);
5694 if (cacert) X509_free(cacert);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005695 load_error:
5696 bind_conf->generate_certs = 0;
5697 err++;
Christopher Faulet31af49d2015-06-09 17:29:50 +02005698 return err;
5699}
5700
5701/* Release CA cert and private key used to generate certificated */
5702void
5703ssl_sock_free_ca(struct bind_conf *bind_conf)
5704{
Christopher Faulet31af49d2015-06-09 17:29:50 +02005705 if (bind_conf->ca_sign_pkey)
5706 EVP_PKEY_free(bind_conf->ca_sign_pkey);
5707 if (bind_conf->ca_sign_cert)
5708 X509_free(bind_conf->ca_sign_cert);
Willy Tarreau94ff03a2016-12-22 17:57:46 +01005709 bind_conf->ca_sign_pkey = NULL;
5710 bind_conf->ca_sign_cert = NULL;
Christopher Faulet31af49d2015-06-09 17:29:50 +02005711}
5712
Emeric Brun46591952012-05-18 15:47:34 +02005713/*
5714 * This function is called if SSL * context is not yet allocated. The function
5715 * is designed to be called before any other data-layer operation and sets the
5716 * handshake flag on the connection. It is safe to call it multiple times.
5717 * It returns 0 on success and -1 in error case.
5718 */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005719static int ssl_sock_init(struct connection *conn, void **xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02005720{
Olivier Houchard66ab4982019-02-26 18:37:15 +01005721 struct ssl_sock_ctx *ctx;
Emeric Brun46591952012-05-18 15:47:34 +02005722 /* already initialized */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005723 if (*xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02005724 return 0;
5725
Willy Tarreau3c728722014-01-23 13:50:42 +01005726 if (!conn_ctrl_ready(conn))
Willy Tarreauf79c8172013-10-21 16:30:56 +02005727 return 0;
5728
Olivier Houchard66ab4982019-02-26 18:37:15 +01005729 ctx = pool_alloc(ssl_sock_ctx_pool);
5730 if (!ctx) {
5731 conn->err_code = CO_ER_SSL_NO_MEM;
5732 return -1;
5733 }
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02005734 ctx->wait_event.tasklet = tasklet_new();
5735 if (!ctx->wait_event.tasklet) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02005736 conn->err_code = CO_ER_SSL_NO_MEM;
5737 pool_free(ssl_sock_ctx_pool, ctx);
5738 return -1;
5739 }
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02005740 ctx->wait_event.tasklet->process = ssl_sock_io_cb;
5741 ctx->wait_event.tasklet->context = ctx;
Olivier Houchardea8dd942019-05-20 14:02:16 +02005742 ctx->wait_event.events = 0;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01005743 ctx->sent_early_data = 0;
5744 ctx->tmp_early_data = -1;
Olivier Houcharda8955d52019-04-07 22:00:38 +02005745 ctx->conn = conn;
Olivier Houchard81284e62019-06-06 13:21:23 +02005746 ctx->send_wait = NULL;
5747 ctx->recv_wait = NULL;
Emeric Brun5762a0d2019-09-06 15:36:02 +02005748 ctx->xprt_st = 0;
5749 ctx->xprt_ctx = NULL;
Olivier Houcharda8955d52019-04-07 22:00:38 +02005750
5751 /* Only work with sockets for now, this should be adapted when we'll
5752 * add QUIC support.
5753 */
5754 ctx->xprt = xprt_get(XPRT_RAW);
Olivier Houchard19afb272019-05-23 18:24:07 +02005755 if (ctx->xprt->init) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02005756 if (ctx->xprt->init(conn, &ctx->xprt_ctx) != 0)
5757 goto err;
Olivier Houchard19afb272019-05-23 18:24:07 +02005758 }
Olivier Houchard66ab4982019-02-26 18:37:15 +01005759
Willy Tarreau20879a02012-12-03 16:32:10 +01005760 if (global.maxsslconn && sslconns >= global.maxsslconn) {
5761 conn->err_code = CO_ER_SSL_TOO_MANY;
Olivier Houchardea8dd942019-05-20 14:02:16 +02005762 goto err;
Willy Tarreau20879a02012-12-03 16:32:10 +01005763 }
Willy Tarreau403edff2012-09-06 11:58:37 +02005764
Emeric Brun46591952012-05-18 15:47:34 +02005765 /* If it is in client mode initiate SSL session
5766 in connect state otherwise accept state */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01005767 if (objt_server(conn->target)) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005768 int may_retry = 1;
5769
5770 retry_connect:
Emeric Brun46591952012-05-18 15:47:34 +02005771 /* Alloc a new SSL session ctx */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005772 ctx->ssl = SSL_new(__objt_server(conn->target)->ssl_ctx.ctx);
5773 if (!ctx->ssl) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005774 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005775 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005776 goto retry_connect;
5777 }
Willy Tarreau20879a02012-12-03 16:32:10 +01005778 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01005779 goto err;
Willy Tarreau20879a02012-12-03 16:32:10 +01005780 }
Olivier Houcharda8955d52019-04-07 22:00:38 +02005781 ctx->bio = BIO_new(ha_meth);
5782 if (!ctx->bio) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005783 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005784 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005785 goto retry_connect;
5786 }
Emeric Brun55476152014-11-12 17:35:37 +01005787 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01005788 goto err;
Emeric Brun55476152014-11-12 17:35:37 +01005789 }
Olivier Houcharda8955d52019-04-07 22:00:38 +02005790 BIO_set_data(ctx->bio, ctx);
Olivier Houcharda8955d52019-04-07 22:00:38 +02005791 SSL_set_bio(ctx->ssl, ctx->bio, ctx->bio);
Emeric Brun46591952012-05-18 15:47:34 +02005792
Evan Broderbe554312013-06-27 00:05:25 -07005793 /* set connection pointer */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005794 if (!SSL_set_ex_data(ctx->ssl, ssl_app_data_index, conn)) {
5795 SSL_free(ctx->ssl);
5796 ctx->ssl = NULL;
Emeric Brun55476152014-11-12 17:35:37 +01005797 conn->xprt_ctx = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005798 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005799 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005800 goto retry_connect;
5801 }
Emeric Brun55476152014-11-12 17:35:37 +01005802 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01005803 goto err;
Emeric Brun55476152014-11-12 17:35:37 +01005804 }
5805
Olivier Houchard66ab4982019-02-26 18:37:15 +01005806 SSL_set_connect_state(ctx->ssl);
Willy Tarreau07d94e42018-09-20 10:57:52 +02005807 if (__objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr) {
5808 const unsigned char *ptr = __objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr;
5809 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 +01005810 if (sess && !SSL_set_session(ctx->ssl, sess)) {
Olivier Houcharde6060c52017-11-16 17:42:52 +01005811 SSL_SESSION_free(sess);
Willy Tarreau07d94e42018-09-20 10:57:52 +02005812 free(__objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr);
5813 __objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr = NULL;
Olivier Houcharde6060c52017-11-16 17:42:52 +01005814 } else if (sess) {
5815 SSL_SESSION_free(sess);
Emeric Brun55476152014-11-12 17:35:37 +01005816 }
5817 }
Evan Broderbe554312013-06-27 00:05:25 -07005818
Emeric Brun46591952012-05-18 15:47:34 +02005819 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +02005820 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Willy Tarreau403edff2012-09-06 11:58:37 +02005821
Olivier Houchard2be5a4c2019-03-08 18:54:43 +01005822 _HA_ATOMIC_ADD(&sslconns, 1);
5823 _HA_ATOMIC_ADD(&totalsslconns, 1);
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005824 *xprt_ctx = ctx;
Olivier Houchardea8dd942019-05-20 14:02:16 +02005825 /* Start the handshake */
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02005826 tasklet_wakeup(ctx->wait_event.tasklet);
Olivier Houchardea8dd942019-05-20 14:02:16 +02005827 if (conn->flags & CO_FL_ERROR)
5828 goto err;
Emeric Brun46591952012-05-18 15:47:34 +02005829 return 0;
5830 }
Willy Tarreau3fdb3662012-11-12 00:42:33 +01005831 else if (objt_listener(conn->target)) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005832 int may_retry = 1;
5833
5834 retry_accept:
Emeric Brun46591952012-05-18 15:47:34 +02005835 /* Alloc a new SSL session ctx */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005836 ctx->ssl = SSL_new(__objt_listener(conn->target)->bind_conf->initial_ctx);
5837 if (!ctx->ssl) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005838 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005839 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005840 goto retry_accept;
5841 }
Willy Tarreau20879a02012-12-03 16:32:10 +01005842 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01005843 goto err;
Willy Tarreau20879a02012-12-03 16:32:10 +01005844 }
Emeric Brun46591952012-05-18 15:47:34 +02005845
Olivier Houcharda8955d52019-04-07 22:00:38 +02005846 ctx->bio = BIO_new(ha_meth);
5847 if (!ctx->bio) {
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 }
Emeric Brun55476152014-11-12 17:35:37 +01005852 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01005853 goto err;
Emeric Brun55476152014-11-12 17:35:37 +01005854 }
Olivier Houcharda8955d52019-04-07 22:00:38 +02005855 BIO_set_data(ctx->bio, ctx);
Olivier Houcharda8955d52019-04-07 22:00:38 +02005856 SSL_set_bio(ctx->ssl, ctx->bio, ctx->bio);
Emeric Brun46591952012-05-18 15:47:34 +02005857
Emeric Brune1f38db2012-09-03 20:36:47 +02005858 /* set connection pointer */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005859 if (!SSL_set_ex_data(ctx->ssl, ssl_app_data_index, conn)) {
5860 SSL_free(ctx->ssl);
5861 ctx->ssl = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005862 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005863 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005864 goto retry_accept;
5865 }
Emeric Brun55476152014-11-12 17:35:37 +01005866 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01005867 goto err;
Emeric Brun55476152014-11-12 17:35:37 +01005868 }
5869
Olivier Houchard66ab4982019-02-26 18:37:15 +01005870 SSL_set_accept_state(ctx->ssl);
Emeric Brune1f38db2012-09-03 20:36:47 +02005871
Emeric Brun46591952012-05-18 15:47:34 +02005872 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +02005873 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Emmanuel Hocdetf967c312019-08-05 18:04:16 +02005874#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Olivier Houchardc2aae742017-09-22 18:26:28 +02005875 conn->flags |= CO_FL_EARLY_SSL_HS;
5876#endif
Willy Tarreau403edff2012-09-06 11:58:37 +02005877
Olivier Houchard2be5a4c2019-03-08 18:54:43 +01005878 _HA_ATOMIC_ADD(&sslconns, 1);
5879 _HA_ATOMIC_ADD(&totalsslconns, 1);
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005880 *xprt_ctx = ctx;
Olivier Houchardea8dd942019-05-20 14:02:16 +02005881 /* Start the handshake */
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02005882 tasklet_wakeup(ctx->wait_event.tasklet);
Olivier Houchardea8dd942019-05-20 14:02:16 +02005883 if (conn->flags & CO_FL_ERROR)
5884 goto err;
Emeric Brun46591952012-05-18 15:47:34 +02005885 return 0;
5886 }
5887 /* don't know how to handle such a target */
Willy Tarreau20879a02012-12-03 16:32:10 +01005888 conn->err_code = CO_ER_SSL_NO_TARGET;
Olivier Houchard66ab4982019-02-26 18:37:15 +01005889err:
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02005890 if (ctx && ctx->wait_event.tasklet)
5891 tasklet_free(ctx->wait_event.tasklet);
Olivier Houchard66ab4982019-02-26 18:37:15 +01005892 pool_free(ssl_sock_ctx_pool, ctx);
Emeric Brun46591952012-05-18 15:47:34 +02005893 return -1;
5894}
5895
5896
5897/* This is the callback which is used when an SSL handshake is pending. It
5898 * updates the FD status if it wants some polling before being called again.
5899 * It returns 0 if it fails in a fatal way or needs to poll to go further,
5900 * otherwise it returns non-zero and removes itself from the connection's
5901 * flags (the bit is provided in <flag> by the caller).
5902 */
Olivier Houchard000694c2019-05-23 14:45:12 +02005903static int ssl_sock_handshake(struct connection *conn, unsigned int flag)
Emeric Brun46591952012-05-18 15:47:34 +02005904{
Olivier Houchard66ab4982019-02-26 18:37:15 +01005905 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
Emeric Brun46591952012-05-18 15:47:34 +02005906 int ret;
5907
Willy Tarreau3c728722014-01-23 13:50:42 +01005908 if (!conn_ctrl_ready(conn))
Willy Tarreauf79c8172013-10-21 16:30:56 +02005909 return 0;
5910
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005911 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02005912 goto out_error;
5913
Willy Tarreau5db847a2019-05-09 14:13:35 +02005914#if HA_OPENSSL_VERSION_NUMBER >= 0x10101000L
Olivier Houchardc2aae742017-09-22 18:26:28 +02005915 /*
5916 * Check if we have early data. If we do, we have to read them
5917 * before SSL_do_handshake() is called, And there's no way to
5918 * detect early data, except to try to read them
5919 */
5920 if (conn->flags & CO_FL_EARLY_SSL_HS) {
5921 size_t read_data;
5922
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01005923 ret = SSL_read_early_data(ctx->ssl, &ctx->tmp_early_data,
Olivier Houchardc2aae742017-09-22 18:26:28 +02005924 1, &read_data);
5925 if (ret == SSL_READ_EARLY_DATA_ERROR)
5926 goto check_error;
5927 if (ret == SSL_READ_EARLY_DATA_SUCCESS) {
5928 conn->flags &= ~(CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN);
5929 return 1;
5930 } else
5931 conn->flags &= ~CO_FL_EARLY_SSL_HS;
5932 }
5933#endif
Emeric Brun674b7432012-11-08 19:21:55 +01005934 /* If we use SSL_do_handshake to process a reneg initiated by
5935 * the remote peer, it sometimes returns SSL_ERROR_SSL.
5936 * Usually SSL_write and SSL_read are used and process implicitly
5937 * the reneg handshake.
5938 * Here we use SSL_peek as a workaround for reneg.
5939 */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005940 if ((conn->flags & CO_FL_CONNECTED) && SSL_renegotiate_pending(ctx->ssl)) {
Emeric Brun674b7432012-11-08 19:21:55 +01005941 char c;
5942
Olivier Houchard66ab4982019-02-26 18:37:15 +01005943 ret = SSL_peek(ctx->ssl, &c, 1);
Emeric Brun674b7432012-11-08 19:21:55 +01005944 if (ret <= 0) {
5945 /* handshake may have not been completed, let's find why */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005946 ret = SSL_get_error(ctx->ssl, ret);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005947
Emeric Brun674b7432012-11-08 19:21:55 +01005948 if (ret == SSL_ERROR_WANT_WRITE) {
5949 /* SSL handshake needs to write, L4 connection may not be ready */
Olivier Houchard03abf2d2019-05-28 10:12:02 +02005950 if (!(ctx->wait_event.events & SUB_RETRY_SEND))
Olivier Houchardea8dd942019-05-20 14:02:16 +02005951 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_SEND, &ctx->wait_event);
Emeric Brun674b7432012-11-08 19:21:55 +01005952 return 0;
5953 }
5954 else if (ret == SSL_ERROR_WANT_READ) {
5955 /* handshake may have been completed but we have
5956 * no more data to read.
5957 */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005958 if (!SSL_renegotiate_pending(ctx->ssl)) {
Emeric Brun674b7432012-11-08 19:21:55 +01005959 ret = 1;
5960 goto reneg_ok;
5961 }
5962 /* SSL handshake needs to read, L4 connection is ready */
Olivier Houchard03abf2d2019-05-28 10:12:02 +02005963 if (!(ctx->wait_event.events & SUB_RETRY_RECV))
Olivier Houchardea8dd942019-05-20 14:02:16 +02005964 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_RECV, &ctx->wait_event);
Emeric Brun674b7432012-11-08 19:21:55 +01005965 return 0;
5966 }
Willy Tarreau5db847a2019-05-09 14:13:35 +02005967#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005968 else if (ret == SSL_ERROR_WANT_ASYNC) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02005969 ssl_async_process_fds(ctx);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005970 return 0;
5971 }
5972#endif
Emeric Brun674b7432012-11-08 19:21:55 +01005973 else if (ret == SSL_ERROR_SYSCALL) {
5974 /* if errno is null, then connection was successfully established */
5975 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
5976 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Willy Tarreau20879a02012-12-03 16:32:10 +01005977 if (!conn->err_code) {
Lukas Tribus49799162019-07-08 14:29:15 +02005978#if defined(OPENSSL_IS_BORINGSSL) || defined(LIBRESSL_VERSION_NUMBER)
5979 /* do not handle empty handshakes in BoringSSL or LibreSSL */
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005980 conn->err_code = CO_ER_SSL_HANDSHAKE;
5981#else
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005982 int empty_handshake;
Willy Tarreau5db847a2019-05-09 14:13:35 +02005983#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL)
Lukas Tribus49799162019-07-08 14:29:15 +02005984 /* use SSL_get_state() in OpenSSL >= 1.1.0; SSL_state() is broken */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005985 OSSL_HANDSHAKE_STATE state = SSL_get_state((SSL *)ctx->ssl);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005986 empty_handshake = state == TLS_ST_BEFORE;
5987#else
Lukas Tribus49799162019-07-08 14:29:15 +02005988 /* access packet_length directly in OpenSSL <= 1.0.2; SSL_state() is broken */
5989 empty_handshake = !ctx->ssl->packet_length;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005990#endif
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005991 if (empty_handshake) {
Emeric Brun29f037d2014-04-25 19:05:36 +02005992 if (!errno) {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01005993 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emeric Brun29f037d2014-04-25 19:05:36 +02005994 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5995 else
5996 conn->err_code = CO_ER_SSL_EMPTY;
5997 }
5998 else {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01005999 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emeric Brun29f037d2014-04-25 19:05:36 +02006000 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
6001 else
6002 conn->err_code = CO_ER_SSL_ABORT;
6003 }
6004 }
6005 else {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006006 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emeric Brun29f037d2014-04-25 19:05:36 +02006007 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
Willy Tarreau20879a02012-12-03 16:32:10 +01006008 else
Emeric Brun29f037d2014-04-25 19:05:36 +02006009 conn->err_code = CO_ER_SSL_HANDSHAKE;
6010 }
Lukas Tribus49799162019-07-08 14:29:15 +02006011#endif /* BoringSSL or LibreSSL */
Willy Tarreau20879a02012-12-03 16:32:10 +01006012 }
Emeric Brun674b7432012-11-08 19:21:55 +01006013 goto out_error;
6014 }
6015 else {
6016 /* Fail on all other handshake errors */
6017 /* Note: OpenSSL may leave unread bytes in the socket's
6018 * buffer, causing an RST to be emitted upon close() on
6019 * TCP sockets. We first try to drain possibly pending
6020 * data to avoid this as much as possible.
6021 */
Willy Tarreaud85c4852015-03-13 00:40:28 +01006022 conn_sock_drain(conn);
Willy Tarreau20879a02012-12-03 16:32:10 +01006023 if (!conn->err_code)
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006024 conn->err_code = (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT) ?
Willy Tarreauf51c6982014-04-25 20:02:39 +02006025 CO_ER_SSL_KILLED_HB : CO_ER_SSL_HANDSHAKE;
Emeric Brun674b7432012-11-08 19:21:55 +01006026 goto out_error;
6027 }
6028 }
6029 /* read some data: consider handshake completed */
6030 goto reneg_ok;
6031 }
Olivier Houchard66ab4982019-02-26 18:37:15 +01006032 ret = SSL_do_handshake(ctx->ssl);
Olivier Houchardc2aae742017-09-22 18:26:28 +02006033check_error:
Emeric Brun46591952012-05-18 15:47:34 +02006034 if (ret != 1) {
6035 /* handshake did not complete, let's find why */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006036 ret = SSL_get_error(ctx->ssl, ret);
Emeric Brun46591952012-05-18 15:47:34 +02006037
6038 if (ret == SSL_ERROR_WANT_WRITE) {
6039 /* SSL handshake needs to write, L4 connection may not be ready */
Olivier Houchard03abf2d2019-05-28 10:12:02 +02006040 if (!(ctx->wait_event.events & SUB_RETRY_SEND))
Olivier Houchardea8dd942019-05-20 14:02:16 +02006041 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_SEND, &ctx->wait_event);
Emeric Brun46591952012-05-18 15:47:34 +02006042 return 0;
6043 }
6044 else if (ret == SSL_ERROR_WANT_READ) {
6045 /* SSL handshake needs to read, L4 connection is ready */
Olivier Houchardea8dd942019-05-20 14:02:16 +02006046 if (!(ctx->wait_event.events & SUB_RETRY_RECV))
Olivier Houchardea8dd942019-05-20 14:02:16 +02006047 ctx->xprt->subscribe(conn, ctx->xprt_ctx,
6048 SUB_RETRY_RECV, &ctx->wait_event);
Emeric Brun46591952012-05-18 15:47:34 +02006049 return 0;
6050 }
Willy Tarreau5db847a2019-05-09 14:13:35 +02006051#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006052 else if (ret == SSL_ERROR_WANT_ASYNC) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02006053 ssl_async_process_fds(ctx);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006054 return 0;
6055 }
6056#endif
Willy Tarreau89230192012-09-28 20:22:13 +02006057 else if (ret == SSL_ERROR_SYSCALL) {
6058 /* if errno is null, then connection was successfully established */
6059 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
6060 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01006061 if (!conn->err_code) {
Lukas Tribus49799162019-07-08 14:29:15 +02006062#if defined(OPENSSL_IS_BORINGSSL) || defined(LIBRESSL_VERSION_NUMBER)
6063 /* do not handle empty handshakes in BoringSSL or LibreSSL */
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01006064 conn->err_code = CO_ER_SSL_HANDSHAKE;
6065#else
6066 int empty_handshake;
Willy Tarreau5db847a2019-05-09 14:13:35 +02006067#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL)
Lukas Tribus49799162019-07-08 14:29:15 +02006068 /* use SSL_get_state() in OpenSSL >= 1.1.0; SSL_state() is broken */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006069 OSSL_HANDSHAKE_STATE state = SSL_get_state(ctx->ssl);
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01006070 empty_handshake = state == TLS_ST_BEFORE;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006071#else
Lukas Tribus49799162019-07-08 14:29:15 +02006072 /* access packet_length directly in OpenSSL <= 1.0.2; SSL_state() is broken */
6073 empty_handshake = !ctx->ssl->packet_length;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006074#endif
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01006075 if (empty_handshake) {
6076 if (!errno) {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006077 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01006078 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
6079 else
6080 conn->err_code = CO_ER_SSL_EMPTY;
6081 }
6082 else {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006083 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01006084 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
6085 else
6086 conn->err_code = CO_ER_SSL_ABORT;
6087 }
Emeric Brun29f037d2014-04-25 19:05:36 +02006088 }
6089 else {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006090 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emeric Brun29f037d2014-04-25 19:05:36 +02006091 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
6092 else
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01006093 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun29f037d2014-04-25 19:05:36 +02006094 }
Lukas Tribus49799162019-07-08 14:29:15 +02006095#endif /* BoringSSL or LibreSSL */
Emeric Brun29f037d2014-04-25 19:05:36 +02006096 }
Willy Tarreau89230192012-09-28 20:22:13 +02006097 goto out_error;
6098 }
Emeric Brun46591952012-05-18 15:47:34 +02006099 else {
6100 /* Fail on all other handshake errors */
Willy Tarreau566dc552012-10-19 20:52:18 +02006101 /* Note: OpenSSL may leave unread bytes in the socket's
6102 * buffer, causing an RST to be emitted upon close() on
6103 * TCP sockets. We first try to drain possibly pending
6104 * data to avoid this as much as possible.
6105 */
Willy Tarreaud85c4852015-03-13 00:40:28 +01006106 conn_sock_drain(conn);
Willy Tarreau20879a02012-12-03 16:32:10 +01006107 if (!conn->err_code)
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006108 conn->err_code = (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT) ?
Willy Tarreauf51c6982014-04-25 20:02:39 +02006109 CO_ER_SSL_KILLED_HB : CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02006110 goto out_error;
6111 }
6112 }
Willy Tarreau5db847a2019-05-09 14:13:35 +02006113#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Olivier Houchard522eea72017-11-03 16:27:47 +01006114 else {
6115 /*
6116 * If the server refused the early data, we have to send a
6117 * 425 to the client, as we no longer have the data to sent
6118 * them again.
6119 */
6120 if ((conn->flags & CO_FL_EARLY_DATA) && (objt_server(conn->target))) {
Olivier Houchard66ab4982019-02-26 18:37:15 +01006121 if (SSL_get_early_data_status(ctx->ssl) == SSL_EARLY_DATA_REJECTED) {
Olivier Houchard522eea72017-11-03 16:27:47 +01006122 conn->err_code = CO_ER_SSL_EARLY_FAILED;
6123 goto out_error;
6124 }
6125 }
6126 }
6127#endif
6128
Emeric Brun46591952012-05-18 15:47:34 +02006129
Emeric Brun674b7432012-11-08 19:21:55 +01006130reneg_ok:
Emeric Brunb5e42a82017-06-06 12:35:14 +00006131
Willy Tarreau5db847a2019-05-09 14:13:35 +02006132#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00006133 /* ASYNC engine API doesn't support moving read/write
6134 * buffers. So we disable ASYNC mode right after
6135 * the handshake to avoid buffer oveflows.
6136 */
6137 if (global_ssl.async)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006138 SSL_clear_mode(ctx->ssl, SSL_MODE_ASYNC);
Emeric Brunb5e42a82017-06-06 12:35:14 +00006139#endif
Emeric Brun46591952012-05-18 15:47:34 +02006140 /* Handshake succeeded */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006141 if (!SSL_session_reused(ctx->ssl)) {
Willy Tarreau0c9c2722014-05-28 12:28:58 +02006142 if (objt_server(conn->target)) {
6143 update_freq_ctr(&global.ssl_be_keys_per_sec, 1);
6144 if (global.ssl_be_keys_per_sec.curr_ctr > global.ssl_be_keys_max)
6145 global.ssl_be_keys_max = global.ssl_be_keys_per_sec.curr_ctr;
Emeric Brun46591952012-05-18 15:47:34 +02006146 }
Willy Tarreau0c9c2722014-05-28 12:28:58 +02006147 else {
6148 update_freq_ctr(&global.ssl_fe_keys_per_sec, 1);
6149 if (global.ssl_fe_keys_per_sec.curr_ctr > global.ssl_fe_keys_max)
6150 global.ssl_fe_keys_max = global.ssl_fe_keys_per_sec.curr_ctr;
6151 }
Emeric Brun46591952012-05-18 15:47:34 +02006152 }
6153
6154 /* The connection is now established at both layers, it's time to leave */
6155 conn->flags &= ~(flag | CO_FL_WAIT_L4_CONN | CO_FL_WAIT_L6_CONN);
6156 return 1;
6157
6158 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01006159 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02006160 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01006161 ERR_clear_error();
6162
Emeric Brun9fa89732012-10-04 17:09:56 +02006163 /* free resumed session if exists */
Willy Tarreau07d94e42018-09-20 10:57:52 +02006164 if (objt_server(conn->target) && __objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr) {
6165 free(__objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr);
6166 __objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr = NULL;
Emeric Brun9fa89732012-10-04 17:09:56 +02006167 }
6168
Emeric Brun46591952012-05-18 15:47:34 +02006169 /* Fail on all other handshake errors */
6170 conn->flags |= CO_FL_ERROR;
Willy Tarreau20879a02012-12-03 16:32:10 +01006171 if (!conn->err_code)
6172 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02006173 return 0;
6174}
6175
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006176static int ssl_subscribe(struct connection *conn, void *xprt_ctx, int event_type, void *param)
Olivier Houcharddf357842019-03-21 16:30:07 +01006177{
Olivier Houchardea8dd942019-05-20 14:02:16 +02006178 struct wait_event *sw;
6179 struct ssl_sock_ctx *ctx = xprt_ctx;
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006180
Olivier Houchard0ff28652019-06-24 18:57:39 +02006181 if (!ctx)
6182 return -1;
6183
Olivier Houchardea8dd942019-05-20 14:02:16 +02006184 if (event_type & SUB_RETRY_RECV) {
6185 sw = param;
6186 BUG_ON(ctx->recv_wait != NULL || (sw->events & SUB_RETRY_RECV));
6187 sw->events |= SUB_RETRY_RECV;
6188 ctx->recv_wait = sw;
6189 if (!(conn->flags & CO_FL_SSL_WAIT_HS) &&
6190 !(ctx->wait_event.events & SUB_RETRY_RECV))
6191 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_RECV, &ctx->wait_event);
6192 event_type &= ~SUB_RETRY_RECV;
6193 }
6194 if (event_type & SUB_RETRY_SEND) {
6195sw = param;
6196 BUG_ON(ctx->send_wait != NULL || (sw->events & SUB_RETRY_SEND));
6197 sw->events |= SUB_RETRY_SEND;
6198 ctx->send_wait = sw;
6199 if (!(conn->flags & CO_FL_SSL_WAIT_HS) &&
6200 !(ctx->wait_event.events & SUB_RETRY_SEND))
6201 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_SEND, &ctx->wait_event);
6202 event_type &= ~SUB_RETRY_SEND;
6203
6204 }
6205 if (event_type != 0)
6206 return -1;
6207 return 0;
Olivier Houcharddf357842019-03-21 16:30:07 +01006208}
6209
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006210static int ssl_unsubscribe(struct connection *conn, void *xprt_ctx, int event_type, void *param)
Olivier Houcharddf357842019-03-21 16:30:07 +01006211{
Olivier Houchardea8dd942019-05-20 14:02:16 +02006212 struct wait_event *sw;
6213 struct ssl_sock_ctx *ctx = xprt_ctx;
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006214
Olivier Houchardea8dd942019-05-20 14:02:16 +02006215 if (event_type & SUB_RETRY_RECV) {
6216 sw = param;
6217 BUG_ON(ctx->recv_wait != sw);
6218 ctx->recv_wait = NULL;
6219 sw->events &= ~SUB_RETRY_RECV;
6220 /* If we subscribed, and we're not doing the handshake,
6221 * then we subscribed because the upper layer asked for it,
6222 * as the upper layer is no longer interested, we can
6223 * unsubscribe too.
6224 */
6225 if (!(ctx->conn->flags & CO_FL_SSL_WAIT_HS) &&
6226 (ctx->wait_event.events & SUB_RETRY_RECV))
6227 conn_unsubscribe(conn, ctx->xprt_ctx, SUB_RETRY_RECV,
6228 &ctx->wait_event);
6229 }
6230 if (event_type & SUB_RETRY_SEND) {
6231 sw = param;
6232 BUG_ON(ctx->send_wait != sw);
6233 ctx->send_wait = NULL;
6234 sw->events &= ~SUB_RETRY_SEND;
6235 if (!(ctx->conn->flags & CO_FL_SSL_WAIT_HS) &&
6236 (ctx->wait_event.events & SUB_RETRY_SEND))
6237 conn_unsubscribe(conn, ctx->xprt_ctx, SUB_RETRY_SEND,
6238 &ctx->wait_event);
6239
6240 }
6241
6242 return 0;
Olivier Houcharddf357842019-03-21 16:30:07 +01006243}
6244
Olivier Houchard2e055482019-05-27 19:50:12 +02006245/* Use the provided XPRT as an underlying XPRT, and provide the old one.
6246 * Returns 0 on success, and non-zero on failure.
6247 */
6248static 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)
6249{
6250 struct ssl_sock_ctx *ctx = xprt_ctx;
6251
6252 if (oldxprt_ops != NULL)
6253 *oldxprt_ops = ctx->xprt;
6254 if (oldxprt_ctx != NULL)
6255 *oldxprt_ctx = ctx->xprt_ctx;
6256 ctx->xprt = toadd_ops;
6257 ctx->xprt_ctx = toadd_ctx;
6258 return 0;
6259}
6260
Olivier Houchard5149b592019-05-23 17:47:36 +02006261/* Remove the specified xprt. If if it our underlying XPRT, remove it and
6262 * return 0, otherwise just call the remove_xprt method from the underlying
6263 * XPRT.
6264 */
6265static int ssl_remove_xprt(struct connection *conn, void *xprt_ctx, void *toremove_ctx, const struct xprt_ops *newops, void *newctx)
6266{
6267 struct ssl_sock_ctx *ctx = xprt_ctx;
6268
6269 if (ctx->xprt_ctx == toremove_ctx) {
6270 ctx->xprt_ctx = newctx;
6271 ctx->xprt = newops;
6272 return 0;
6273 }
6274 return (ctx->xprt->remove_xprt(conn, ctx->xprt_ctx, toremove_ctx, newops, newctx));
6275}
6276
Olivier Houchardea8dd942019-05-20 14:02:16 +02006277static struct task *ssl_sock_io_cb(struct task *t, void *context, unsigned short state)
6278{
6279 struct ssl_sock_ctx *ctx = context;
6280
6281 /* First if we're doing an handshake, try that */
6282 if (ctx->conn->flags & CO_FL_SSL_WAIT_HS)
6283 ssl_sock_handshake(ctx->conn, CO_FL_SSL_WAIT_HS);
6284 /* If we had an error, or the handshake is done and I/O is available,
6285 * let the upper layer know.
6286 * If no mux was set up yet, and nobody subscribed, then call
6287 * xprt_done_cb() ourself if it's set, or destroy the connection,
6288 * we can't be sure conn_fd_handler() will be called again.
6289 */
6290 if ((ctx->conn->flags & CO_FL_ERROR) ||
6291 !(ctx->conn->flags & CO_FL_SSL_WAIT_HS)) {
6292 int ret = 0;
6293 int woke = 0;
6294
6295 /* On error, wake any waiter */
6296 if (ctx->recv_wait) {
6297 ctx->recv_wait->events &= ~SUB_RETRY_RECV;
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02006298 tasklet_wakeup(ctx->recv_wait->tasklet);
Olivier Houchardea8dd942019-05-20 14:02:16 +02006299 ctx->recv_wait = NULL;
6300 woke = 1;
6301 }
6302 if (ctx->send_wait) {
6303 ctx->send_wait->events &= ~SUB_RETRY_SEND;
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02006304 tasklet_wakeup(ctx->send_wait->tasklet);
Olivier Houchardea8dd942019-05-20 14:02:16 +02006305 ctx->send_wait = NULL;
6306 woke = 1;
6307 }
6308 /* If we're the first xprt for the connection, let the
6309 * upper layers know. If xprt_done_cb() is set, call it,
6310 * otherwise, we should have a mux, so call its wake
6311 * method if we didn't woke a tasklet already.
6312 */
6313 if (ctx->conn->xprt_ctx == ctx) {
6314 if (ctx->conn->xprt_done_cb)
6315 ret = ctx->conn->xprt_done_cb(ctx->conn);
6316 if (ret >= 0 && !woke && ctx->conn->mux && ctx->conn->mux->wake)
6317 ctx->conn->mux->wake(ctx->conn);
6318 return NULL;
6319 }
6320 }
6321 return NULL;
6322}
6323
Emeric Brun46591952012-05-18 15:47:34 +02006324/* Receive up to <count> bytes from connection <conn>'s socket and store them
Willy Tarreauabf08d92014-01-14 11:31:27 +01006325 * into buffer <buf>. Only one call to recv() is performed, unless the
Emeric Brun46591952012-05-18 15:47:34 +02006326 * buffer wraps, in which case a second call may be performed. The connection's
6327 * flags are updated with whatever special event is detected (error, read0,
6328 * empty). The caller is responsible for taking care of those events and
6329 * avoiding the call if inappropriate. The function does not call the
6330 * connection's polling update function, so the caller is responsible for this.
6331 */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006332static 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 +02006333{
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006334 struct ssl_sock_ctx *ctx = xprt_ctx;
Willy Tarreaubfc4d772018-07-18 11:22:03 +02006335 ssize_t ret;
6336 size_t try, done = 0;
Emeric Brun46591952012-05-18 15:47:34 +02006337
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02006338 conn_refresh_polling_flags(conn);
6339
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006340 if (!ctx)
Emeric Brun46591952012-05-18 15:47:34 +02006341 goto out_error;
6342
6343 if (conn->flags & CO_FL_HANDSHAKE)
6344 /* a handshake was requested */
6345 return 0;
6346
Emeric Brun46591952012-05-18 15:47:34 +02006347 /* read the largest possible block. For this, we perform only one call
6348 * to recv() unless the buffer wraps and we exactly fill the first hunk,
6349 * in which case we accept to do it once again. A new attempt is made on
6350 * EINTR too.
6351 */
Willy Tarreau00b0fb92014-01-17 11:09:40 +01006352 while (count > 0) {
Olivier Houchardc2aae742017-09-22 18:26:28 +02006353 int need_out = 0;
6354
Willy Tarreau591d4452018-06-15 17:21:00 +02006355 try = b_contig_space(buf);
6356 if (!try)
6357 break;
6358
Willy Tarreauabf08d92014-01-14 11:31:27 +01006359 if (try > count)
6360 try = count;
Willy Tarreau591d4452018-06-15 17:21:00 +02006361
Olivier Houchardc2aae742017-09-22 18:26:28 +02006362 if (((conn->flags & (CO_FL_EARLY_SSL_HS | CO_FL_EARLY_DATA)) == CO_FL_EARLY_SSL_HS) &&
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006363 ctx->tmp_early_data != -1) {
6364 *b_tail(buf) = ctx->tmp_early_data;
Olivier Houchardc2aae742017-09-22 18:26:28 +02006365 done++;
6366 try--;
6367 count--;
Olivier Houchardacd14032018-06-28 18:17:23 +02006368 b_add(buf, 1);
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006369 ctx->tmp_early_data = -1;
Olivier Houchardc2aae742017-09-22 18:26:28 +02006370 continue;
6371 }
Willy Tarreauabf08d92014-01-14 11:31:27 +01006372
Willy Tarreau5db847a2019-05-09 14:13:35 +02006373#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Olivier Houchardc2aae742017-09-22 18:26:28 +02006374 if (conn->flags & CO_FL_EARLY_SSL_HS) {
6375 size_t read_length;
6376
Olivier Houchard66ab4982019-02-26 18:37:15 +01006377 ret = SSL_read_early_data(ctx->ssl,
Willy Tarreau8f9c72d2018-06-07 18:46:28 +02006378 b_tail(buf), try, &read_length);
Olivier Houchard522eea72017-11-03 16:27:47 +01006379 if (ret == SSL_READ_EARLY_DATA_SUCCESS &&
6380 read_length > 0)
Olivier Houchardc2aae742017-09-22 18:26:28 +02006381 conn->flags |= CO_FL_EARLY_DATA;
6382 if (ret == SSL_READ_EARLY_DATA_SUCCESS ||
6383 ret == SSL_READ_EARLY_DATA_FINISH) {
6384 if (ret == SSL_READ_EARLY_DATA_FINISH) {
6385 /*
6386 * We're done reading the early data,
6387 * let's make the handshake
6388 */
6389 conn->flags &= ~CO_FL_EARLY_SSL_HS;
6390 conn->flags |= CO_FL_SSL_WAIT_HS;
6391 need_out = 1;
Olivier Houchard965e84e2019-06-15 20:59:30 +02006392 /* Now initiate the handshake */
6393 tasklet_wakeup(ctx->wait_event.tasklet);
Olivier Houchardc2aae742017-09-22 18:26:28 +02006394 if (read_length == 0)
6395 break;
6396 }
6397 ret = read_length;
6398 }
6399 } else
6400#endif
Olivier Houchard66ab4982019-02-26 18:37:15 +01006401 ret = SSL_read(ctx->ssl, b_tail(buf), try);
Emmanuel Hocdetf967c312019-08-05 18:04:16 +02006402
Emeric Brune1f38db2012-09-03 20:36:47 +02006403 if (conn->flags & CO_FL_ERROR) {
6404 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01006405 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02006406 }
Emeric Brun46591952012-05-18 15:47:34 +02006407 if (ret > 0) {
Olivier Houchardacd14032018-06-28 18:17:23 +02006408 b_add(buf, ret);
Emeric Brun46591952012-05-18 15:47:34 +02006409 done += ret;
Emeric Brun46591952012-05-18 15:47:34 +02006410 count -= ret;
Emeric Brun46591952012-05-18 15:47:34 +02006411 }
Emeric Brun46591952012-05-18 15:47:34 +02006412 else {
Olivier Houchard66ab4982019-02-26 18:37:15 +01006413 ret = SSL_get_error(ctx->ssl, ret);
Emeric Brun46591952012-05-18 15:47:34 +02006414 if (ret == SSL_ERROR_WANT_WRITE) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01006415 /* handshake is running, and it needs to enable write */
Emeric Brun46591952012-05-18 15:47:34 +02006416 conn->flags |= CO_FL_SSL_WAIT_HS;
Olivier Houchardea8dd942019-05-20 14:02:16 +02006417 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_SEND, &ctx->wait_event);
Willy Tarreau5db847a2019-05-09 14:13:35 +02006418#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00006419 /* Async mode can be re-enabled, because we're leaving data state.*/
6420 if (global_ssl.async)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006421 SSL_set_mode(ctx->ssl, SSL_MODE_ASYNC);
Emeric Brunb5e42a82017-06-06 12:35:14 +00006422#endif
Emeric Brun46591952012-05-18 15:47:34 +02006423 break;
6424 }
6425 else if (ret == SSL_ERROR_WANT_READ) {
Olivier Houchard66ab4982019-02-26 18:37:15 +01006426 if (SSL_renegotiate_pending(ctx->ssl)) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02006427 ctx->xprt->subscribe(conn, ctx->xprt_ctx,
6428 SUB_RETRY_RECV,
6429 &ctx->wait_event);
Emeric Brun282a76a2012-11-08 18:02:56 +01006430 /* handshake is running, and it may need to re-enable read */
6431 conn->flags |= CO_FL_SSL_WAIT_HS;
Willy Tarreau5db847a2019-05-09 14:13:35 +02006432#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00006433 /* Async mode can be re-enabled, because we're leaving data state.*/
6434 if (global_ssl.async)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006435 SSL_set_mode(ctx->ssl, SSL_MODE_ASYNC);
Emeric Brunb5e42a82017-06-06 12:35:14 +00006436#endif
Emeric Brun282a76a2012-11-08 18:02:56 +01006437 break;
6438 }
Emeric Brun46591952012-05-18 15:47:34 +02006439 break;
Olivier Houchardc2aae742017-09-22 18:26:28 +02006440 } else if (ret == SSL_ERROR_ZERO_RETURN)
6441 goto read0;
Christopher Faulet4ac77a92018-02-19 14:25:15 +01006442 /* For SSL_ERROR_SYSCALL, make sure to clear the error
6443 * stack before shutting down the connection for
6444 * reading. */
Olivier Houchard7e2e5052018-02-13 15:17:23 +01006445 if (ret == SSL_ERROR_SYSCALL && (!errno || errno == EAGAIN))
6446 goto clear_ssl_error;
Emeric Brun46591952012-05-18 15:47:34 +02006447 /* otherwise it's a real error */
6448 goto out_error;
6449 }
Olivier Houchardc2aae742017-09-22 18:26:28 +02006450 if (need_out)
6451 break;
Emeric Brun46591952012-05-18 15:47:34 +02006452 }
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02006453 leave:
Emeric Brun46591952012-05-18 15:47:34 +02006454 return done;
6455
Christopher Faulet4ac77a92018-02-19 14:25:15 +01006456 clear_ssl_error:
6457 /* Clear openssl global errors stack */
6458 ssl_sock_dump_errors(conn);
6459 ERR_clear_error();
Emeric Brun46591952012-05-18 15:47:34 +02006460 read0:
6461 conn_sock_read0(conn);
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02006462 goto leave;
Christopher Faulet4ac77a92018-02-19 14:25:15 +01006463
Emeric Brun46591952012-05-18 15:47:34 +02006464 out_error:
Olivier Houchard7e2e5052018-02-13 15:17:23 +01006465 conn->flags |= CO_FL_ERROR;
Emeric Brun644cde02012-12-14 11:21:13 +01006466 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02006467 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01006468 ERR_clear_error();
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02006469 goto leave;
Emeric Brun46591952012-05-18 15:47:34 +02006470}
6471
6472
Willy Tarreau787db9a2018-06-14 18:31:46 +02006473/* Send up to <count> pending bytes from buffer <buf> to connection <conn>'s
6474 * socket. <flags> may contain some CO_SFL_* flags to hint the system about
6475 * other pending data for example, but this flag is ignored at the moment.
Emeric Brun46591952012-05-18 15:47:34 +02006476 * Only one call to send() is performed, unless the buffer wraps, in which case
6477 * a second call may be performed. The connection's flags are updated with
6478 * whatever special event is detected (error, empty). The caller is responsible
6479 * for taking care of those events and avoiding the call if inappropriate. The
6480 * function does not call the connection's polling update function, so the caller
Willy Tarreau787db9a2018-06-14 18:31:46 +02006481 * is responsible for this. The buffer's output is not adjusted, it's up to the
6482 * caller to take care of this. It's up to the caller to update the buffer's
6483 * contents based on the return value.
Emeric Brun46591952012-05-18 15:47:34 +02006484 */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006485static 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 +02006486{
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006487 struct ssl_sock_ctx *ctx = xprt_ctx;
Willy Tarreau787db9a2018-06-14 18:31:46 +02006488 ssize_t ret;
6489 size_t try, done;
Emeric Brun46591952012-05-18 15:47:34 +02006490
6491 done = 0;
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02006492 conn_refresh_polling_flags(conn);
Emeric Brun46591952012-05-18 15:47:34 +02006493
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006494 if (!ctx)
Emeric Brun46591952012-05-18 15:47:34 +02006495 goto out_error;
6496
Olivier Houchard010941f2019-05-03 20:56:19 +02006497 if (conn->flags & (CO_FL_HANDSHAKE | CO_FL_EARLY_SSL_HS))
Emeric Brun46591952012-05-18 15:47:34 +02006498 /* a handshake was requested */
6499 return 0;
6500
6501 /* send the largest possible block. For this we perform only one call
6502 * to send() unless the buffer wraps and we exactly fill the first hunk,
6503 * in which case we accept to do it once again.
6504 */
Willy Tarreau787db9a2018-06-14 18:31:46 +02006505 while (count) {
Willy Tarreau5db847a2019-05-09 14:13:35 +02006506#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Olivier Houchardc2aae742017-09-22 18:26:28 +02006507 size_t written_data;
6508#endif
6509
Willy Tarreau787db9a2018-06-14 18:31:46 +02006510 try = b_contig_data(buf, done);
6511 if (try > count)
6512 try = count;
Willy Tarreaubfd59462013-02-21 07:46:09 +01006513
Willy Tarreau7bed9452014-02-02 02:00:24 +01006514 if (!(flags & CO_SFL_STREAMER) &&
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006515 !(ctx->xprt_st & SSL_SOCK_SEND_UNLIMITED) &&
Willy Tarreauef934602016-12-22 23:12:01 +01006516 global_ssl.max_record && try > global_ssl.max_record) {
6517 try = global_ssl.max_record;
Willy Tarreau518cedd2014-02-17 15:43:01 +01006518 }
6519 else {
6520 /* we need to keep the information about the fact that
6521 * we're not limiting the upcoming send(), because if it
6522 * fails, we'll have to retry with at least as many data.
6523 */
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006524 ctx->xprt_st |= SSL_SOCK_SEND_UNLIMITED;
Willy Tarreau518cedd2014-02-17 15:43:01 +01006525 }
Willy Tarreaubfd59462013-02-21 07:46:09 +01006526
Willy Tarreau5db847a2019-05-09 14:13:35 +02006527#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Olivier Houchard010941f2019-05-03 20:56:19 +02006528 if (!SSL_is_init_finished(ctx->ssl) && conn_is_back(conn)) {
Olivier Houchardc2aae742017-09-22 18:26:28 +02006529 unsigned int max_early;
6530
Olivier Houchard522eea72017-11-03 16:27:47 +01006531 if (objt_listener(conn->target))
Olivier Houchard66ab4982019-02-26 18:37:15 +01006532 max_early = SSL_get_max_early_data(ctx->ssl);
Olivier Houchard522eea72017-11-03 16:27:47 +01006533 else {
Olivier Houchard66ab4982019-02-26 18:37:15 +01006534 if (SSL_get0_session(ctx->ssl))
6535 max_early = SSL_SESSION_get_max_early_data(SSL_get0_session(ctx->ssl));
Olivier Houchard522eea72017-11-03 16:27:47 +01006536 else
6537 max_early = 0;
6538 }
6539
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006540 if (try + ctx->sent_early_data > max_early) {
6541 try -= (try + ctx->sent_early_data) - max_early;
Olivier Houchard522eea72017-11-03 16:27:47 +01006542 if (try <= 0) {
Olivier Houchard010941f2019-05-03 20:56:19 +02006543 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Olivier Houchard965e84e2019-06-15 20:59:30 +02006544 tasklet_wakeup(ctx->wait_event.tasklet);
Olivier Houchardc2aae742017-09-22 18:26:28 +02006545 break;
Olivier Houchard522eea72017-11-03 16:27:47 +01006546 }
Olivier Houchardc2aae742017-09-22 18:26:28 +02006547 }
Olivier Houchard66ab4982019-02-26 18:37:15 +01006548 ret = SSL_write_early_data(ctx->ssl, b_peek(buf, done), try, &written_data);
Olivier Houchardc2aae742017-09-22 18:26:28 +02006549 if (ret == 1) {
6550 ret = written_data;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006551 ctx->sent_early_data += ret;
Olivier Houchard965e84e2019-06-15 20:59:30 +02006552 if (objt_server(conn->target)) {
Olivier Houchard522eea72017-11-03 16:27:47 +01006553 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN | CO_FL_EARLY_DATA;
Olivier Houchard965e84e2019-06-15 20:59:30 +02006554 /* Initiate the handshake, now */
6555 tasklet_wakeup(ctx->wait_event.tasklet);
6556 }
Olivier Houchard522eea72017-11-03 16:27:47 +01006557
Olivier Houchardc2aae742017-09-22 18:26:28 +02006558 }
6559
6560 } else
6561#endif
Olivier Houchard66ab4982019-02-26 18:37:15 +01006562 ret = SSL_write(ctx->ssl, b_peek(buf, done), try);
Willy Tarreau518cedd2014-02-17 15:43:01 +01006563
Emeric Brune1f38db2012-09-03 20:36:47 +02006564 if (conn->flags & CO_FL_ERROR) {
6565 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01006566 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02006567 }
Emeric Brun46591952012-05-18 15:47:34 +02006568 if (ret > 0) {
Olivier Houchardf24502b2019-01-17 19:09:11 +01006569 /* A send succeeded, so we can consier ourself connected */
6570 conn->flags |= CO_FL_CONNECTED;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006571 ctx->xprt_st &= ~SSL_SOCK_SEND_UNLIMITED;
Willy Tarreau787db9a2018-06-14 18:31:46 +02006572 count -= ret;
Emeric Brun46591952012-05-18 15:47:34 +02006573 done += ret;
Emeric Brun46591952012-05-18 15:47:34 +02006574 }
6575 else {
Olivier Houchard66ab4982019-02-26 18:37:15 +01006576 ret = SSL_get_error(ctx->ssl, ret);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006577
Emeric Brun46591952012-05-18 15:47:34 +02006578 if (ret == SSL_ERROR_WANT_WRITE) {
Olivier Houchard66ab4982019-02-26 18:37:15 +01006579 if (SSL_renegotiate_pending(ctx->ssl)) {
Emeric Brun282a76a2012-11-08 18:02:56 +01006580 /* handshake is running, and it may need to re-enable write */
6581 conn->flags |= CO_FL_SSL_WAIT_HS;
Olivier Houchardea8dd942019-05-20 14:02:16 +02006582 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_SEND, &ctx->wait_event);
Willy Tarreau5db847a2019-05-09 14:13:35 +02006583#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00006584 /* Async mode can be re-enabled, because we're leaving data state.*/
6585 if (global_ssl.async)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006586 SSL_set_mode(ctx->ssl, SSL_MODE_ASYNC);
Emeric Brunb5e42a82017-06-06 12:35:14 +00006587#endif
Emeric Brun282a76a2012-11-08 18:02:56 +01006588 break;
6589 }
Olivier Houchardea8dd942019-05-20 14:02:16 +02006590
Emeric Brun46591952012-05-18 15:47:34 +02006591 break;
6592 }
6593 else if (ret == SSL_ERROR_WANT_READ) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01006594 /* handshake is running, and it needs to enable read */
Emeric Brun46591952012-05-18 15:47:34 +02006595 conn->flags |= CO_FL_SSL_WAIT_HS;
Olivier Houchardea8dd942019-05-20 14:02:16 +02006596 ctx->xprt->subscribe(conn, ctx->xprt_ctx,
6597 SUB_RETRY_RECV,
6598 &ctx->wait_event);
Willy Tarreau5db847a2019-05-09 14:13:35 +02006599#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00006600 /* Async mode can be re-enabled, because we're leaving data state.*/
6601 if (global_ssl.async)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006602 SSL_set_mode(ctx->ssl, SSL_MODE_ASYNC);
Emeric Brunb5e42a82017-06-06 12:35:14 +00006603#endif
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006604 break;
6605 }
Emeric Brun46591952012-05-18 15:47:34 +02006606 goto out_error;
6607 }
6608 }
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02006609 leave:
Emeric Brun46591952012-05-18 15:47:34 +02006610 return done;
6611
6612 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01006613 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02006614 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01006615 ERR_clear_error();
6616
Emeric Brun46591952012-05-18 15:47:34 +02006617 conn->flags |= CO_FL_ERROR;
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02006618 goto leave;
Emeric Brun46591952012-05-18 15:47:34 +02006619}
6620
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006621static void ssl_sock_close(struct connection *conn, void *xprt_ctx) {
Emeric Brun46591952012-05-18 15:47:34 +02006622
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006623 struct ssl_sock_ctx *ctx = xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006624
Olivier Houchardea8dd942019-05-20 14:02:16 +02006625
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006626 if (ctx) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02006627 if (ctx->wait_event.events != 0)
6628 ctx->xprt->unsubscribe(ctx->conn, ctx->xprt_ctx,
6629 ctx->wait_event.events,
6630 &ctx->wait_event);
6631 if (ctx->send_wait) {
6632 ctx->send_wait->events &= ~SUB_RETRY_SEND;
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02006633 tasklet_wakeup(ctx->send_wait->tasklet);
Olivier Houchardea8dd942019-05-20 14:02:16 +02006634 }
6635 if (ctx->recv_wait) {
6636 ctx->recv_wait->events &= ~SUB_RETRY_RECV;
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02006637 tasklet_wakeup(ctx->recv_wait->tasklet);
Olivier Houchardea8dd942019-05-20 14:02:16 +02006638 }
Olivier Houchard692c1d02019-05-23 18:41:47 +02006639 if (ctx->xprt->close)
6640 ctx->xprt->close(conn, ctx->xprt_ctx);
Willy Tarreau5db847a2019-05-09 14:13:35 +02006641#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brun3854e012017-05-17 20:42:48 +02006642 if (global_ssl.async) {
6643 OSSL_ASYNC_FD all_fd[32], afd;
6644 size_t num_all_fds = 0;
6645 int i;
6646
Olivier Houchard66ab4982019-02-26 18:37:15 +01006647 SSL_get_all_async_fds(ctx->ssl, NULL, &num_all_fds);
Emeric Brun3854e012017-05-17 20:42:48 +02006648 if (num_all_fds > 32) {
6649 send_log(NULL, LOG_EMERG, "haproxy: openssl returns too many async fds. It seems a bug. Process may crash\n");
6650 return;
6651 }
6652
Olivier Houchard66ab4982019-02-26 18:37:15 +01006653 SSL_get_all_async_fds(ctx->ssl, all_fd, &num_all_fds);
Emeric Brun3854e012017-05-17 20:42:48 +02006654
6655 /* If an async job is pending, we must try to
6656 to catch the end using polling before calling
6657 SSL_free */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006658 if (num_all_fds && SSL_waiting_for_async(ctx->ssl)) {
Emeric Brun3854e012017-05-17 20:42:48 +02006659 for (i=0 ; i < num_all_fds ; i++) {
6660 /* switch on an handler designed to
6661 * handle the SSL_free
6662 */
6663 afd = all_fd[i];
6664 fdtab[afd].iocb = ssl_async_fd_free;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006665 fdtab[afd].owner = ctx->ssl;
Emeric Brun3854e012017-05-17 20:42:48 +02006666 fd_want_recv(afd);
Emeric Brunce9e01c2017-05-31 10:02:53 +00006667 /* To ensure that the fd cache won't be used
6668 * and we'll catch a real RD event.
6669 */
6670 fd_cant_recv(afd);
Emeric Brun3854e012017-05-17 20:42:48 +02006671 }
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02006672 tasklet_free(ctx->wait_event.tasklet);
Olivier Houchard66ab4982019-02-26 18:37:15 +01006673 pool_free(ssl_sock_ctx_pool, ctx);
Olivier Houchard2be5a4c2019-03-08 18:54:43 +01006674 _HA_ATOMIC_ADD(&jobs, 1);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006675 return;
6676 }
Emeric Brun3854e012017-05-17 20:42:48 +02006677 /* Else we can remove the fds from the fdtab
6678 * and call SSL_free.
6679 * note: we do a fd_remove and not a delete
6680 * because the fd is owned by the engine.
6681 * the engine is responsible to close
6682 */
6683 for (i=0 ; i < num_all_fds ; i++)
6684 fd_remove(all_fd[i]);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006685 }
6686#endif
Olivier Houchard66ab4982019-02-26 18:37:15 +01006687 SSL_free(ctx->ssl);
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02006688 tasklet_free(ctx->wait_event.tasklet);
Olivier Houchard66ab4982019-02-26 18:37:15 +01006689 pool_free(ssl_sock_ctx_pool, ctx);
Olivier Houchard2be5a4c2019-03-08 18:54:43 +01006690 _HA_ATOMIC_SUB(&sslconns, 1);
Emeric Brun46591952012-05-18 15:47:34 +02006691 }
Emeric Brun46591952012-05-18 15:47:34 +02006692}
6693
6694/* This function tries to perform a clean shutdown on an SSL connection, and in
6695 * any case, flags the connection as reusable if no handshake was in progress.
6696 */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006697static void ssl_sock_shutw(struct connection *conn, void *xprt_ctx, int clean)
Emeric Brun46591952012-05-18 15:47:34 +02006698{
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006699 struct ssl_sock_ctx *ctx = xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006700
Emeric Brun46591952012-05-18 15:47:34 +02006701 if (conn->flags & CO_FL_HANDSHAKE)
6702 return;
Emmanuel Hocdet405ff312017-01-08 14:07:39 +01006703 if (!clean)
6704 /* don't sent notify on SSL_shutdown */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006705 SSL_set_quiet_shutdown(ctx->ssl, 1);
Emeric Brun46591952012-05-18 15:47:34 +02006706 /* no handshake was in progress, try a clean ssl shutdown */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006707 if (SSL_shutdown(ctx->ssl) <= 0) {
Emeric Brun644cde02012-12-14 11:21:13 +01006708 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02006709 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01006710 ERR_clear_error();
6711 }
Emeric Brun46591952012-05-18 15:47:34 +02006712}
6713
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01006714/* used for ppv2 pkey alog (can be used for logging) */
Willy Tarreau83061a82018-07-13 11:56:34 +02006715int ssl_sock_get_pkey_algo(struct connection *conn, struct buffer *out)
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01006716{
Christopher Faulet82004142019-09-10 10:12:03 +02006717 struct ssl_sock_ctx *ctx;
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01006718 int bits = 0;
6719 int sig = TLSEXT_signature_anonymous;
6720 int len = -1;
Emmanuel Hocdetc3775d22019-11-04 18:19:32 +01006721 X509 *crt;
6722 EVP_PKEY *pkey;
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01006723
6724 if (!ssl_sock_is_ssl(conn))
6725 return 0;
Christopher Faulet82004142019-09-10 10:12:03 +02006726 ctx = conn->xprt_ctx;
Emmanuel Hocdetc3775d22019-11-04 18:19:32 +01006727
6728 crt = SSL_get_certificate(ctx->ssl);
6729 if (!crt)
6730 return 0;
6731 pkey = X509_get_pubkey(crt);
6732 if (pkey) {
6733 bits = EVP_PKEY_bits(pkey);
6734 switch(EVP_PKEY_base_id(pkey)) {
6735 case EVP_PKEY_RSA:
6736 sig = TLSEXT_signature_rsa;
6737 break;
6738 case EVP_PKEY_EC:
6739 sig = TLSEXT_signature_ecdsa;
6740 break;
6741 case EVP_PKEY_DSA:
6742 sig = TLSEXT_signature_dsa;
6743 break;
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01006744 }
Emmanuel Hocdetc3775d22019-11-04 18:19:32 +01006745 EVP_PKEY_free(pkey);
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01006746 }
6747
6748 switch(sig) {
6749 case TLSEXT_signature_rsa:
6750 len = chunk_printf(out, "RSA%d", bits);
6751 break;
6752 case TLSEXT_signature_ecdsa:
6753 len = chunk_printf(out, "EC%d", bits);
6754 break;
6755 case TLSEXT_signature_dsa:
6756 len = chunk_printf(out, "DSA%d", bits);
6757 break;
6758 default:
6759 return 0;
6760 }
6761 if (len < 0)
6762 return 0;
6763 return 1;
6764}
6765
Emmanuel Hocdet283e0042017-11-02 14:05:23 +01006766/* used for ppv2 cert signature (can be used for logging) */
6767const char *ssl_sock_get_cert_sig(struct connection *conn)
6768{
Christopher Faulet82004142019-09-10 10:12:03 +02006769 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006770
Emmanuel Hocdet283e0042017-11-02 14:05:23 +01006771 __OPENSSL_110_CONST__ ASN1_OBJECT *algorithm;
6772 X509 *crt;
6773
6774 if (!ssl_sock_is_ssl(conn))
6775 return NULL;
Christopher Faulet82004142019-09-10 10:12:03 +02006776 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006777 crt = SSL_get_certificate(ctx->ssl);
Emmanuel Hocdet283e0042017-11-02 14:05:23 +01006778 if (!crt)
6779 return NULL;
6780 X509_ALGOR_get0(&algorithm, NULL, NULL, X509_get0_tbs_sigalg(crt));
6781 return OBJ_nid2sn(OBJ_obj2nid(algorithm));
6782}
6783
Emmanuel Hocdet253c3b72018-02-01 18:29:59 +01006784/* used for ppv2 authority */
6785const char *ssl_sock_get_sni(struct connection *conn)
6786{
6787#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Christopher Faulet82004142019-09-10 10:12:03 +02006788 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006789
Emmanuel Hocdet253c3b72018-02-01 18:29:59 +01006790 if (!ssl_sock_is_ssl(conn))
6791 return NULL;
Christopher Faulet82004142019-09-10 10:12:03 +02006792 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006793 return SSL_get_servername(ctx->ssl, TLSEXT_NAMETYPE_host_name);
Emmanuel Hocdet253c3b72018-02-01 18:29:59 +01006794#else
Olivier Houchard66ab4982019-02-26 18:37:15 +01006795 return NULL;
Emmanuel Hocdet253c3b72018-02-01 18:29:59 +01006796#endif
6797}
6798
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02006799/* used for logging/ppv2, may be changed for a sample fetch later */
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02006800const char *ssl_sock_get_cipher_name(struct connection *conn)
6801{
Christopher Faulet82004142019-09-10 10:12:03 +02006802 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006803
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02006804 if (!ssl_sock_is_ssl(conn))
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02006805 return NULL;
Christopher Faulet82004142019-09-10 10:12:03 +02006806 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006807 return SSL_get_cipher_name(ctx->ssl);
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02006808}
6809
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02006810/* used for logging/ppv2, may be changed for a sample fetch later */
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02006811const char *ssl_sock_get_proto_version(struct connection *conn)
6812{
Christopher Faulet82004142019-09-10 10:12:03 +02006813 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006814
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02006815 if (!ssl_sock_is_ssl(conn))
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02006816 return NULL;
Christopher Faulet82004142019-09-10 10:12:03 +02006817 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006818 return SSL_get_version(ctx->ssl);
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02006819}
6820
Willy Tarreau8d598402012-10-22 17:58:39 +02006821/* Extract a serial from a cert, and copy it to a chunk.
6822 * Returns 1 if serial is found and copied, 0 if no serial found and
6823 * -1 if output is not large enough.
6824 */
6825static int
Willy Tarreau83061a82018-07-13 11:56:34 +02006826ssl_sock_get_serial(X509 *crt, struct buffer *out)
Willy Tarreau8d598402012-10-22 17:58:39 +02006827{
6828 ASN1_INTEGER *serial;
6829
6830 serial = X509_get_serialNumber(crt);
6831 if (!serial)
6832 return 0;
6833
6834 if (out->size < serial->length)
6835 return -1;
6836
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006837 memcpy(out->area, serial->data, serial->length);
6838 out->data = serial->length;
Willy Tarreau8d598402012-10-22 17:58:39 +02006839 return 1;
6840}
6841
Emeric Brun43e79582014-10-29 19:03:26 +01006842/* Extract a cert to der, and copy it to a chunk.
Joseph Herlant017b3da2018-11-15 09:07:59 -08006843 * Returns 1 if the cert is found and copied, 0 on der conversion failure
6844 * and -1 if the output is not large enough.
Emeric Brun43e79582014-10-29 19:03:26 +01006845 */
6846static int
Willy Tarreau83061a82018-07-13 11:56:34 +02006847ssl_sock_crt2der(X509 *crt, struct buffer *out)
Emeric Brun43e79582014-10-29 19:03:26 +01006848{
6849 int len;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006850 unsigned char *p = (unsigned char *) out->area;;
Emeric Brun43e79582014-10-29 19:03:26 +01006851
6852 len =i2d_X509(crt, NULL);
6853 if (len <= 0)
6854 return 1;
6855
6856 if (out->size < len)
6857 return -1;
6858
6859 i2d_X509(crt,&p);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006860 out->data = len;
Emeric Brun43e79582014-10-29 19:03:26 +01006861 return 1;
6862}
6863
Emeric Brunce5ad802012-10-22 14:11:22 +02006864
Willy Tarreau83061a82018-07-13 11:56:34 +02006865/* Copy Date in ASN1_UTCTIME format in struct buffer out.
Emeric Brunce5ad802012-10-22 14:11:22 +02006866 * Returns 1 if serial is found and copied, 0 if no valid time found
6867 * and -1 if output is not large enough.
6868 */
6869static int
Willy Tarreau83061a82018-07-13 11:56:34 +02006870ssl_sock_get_time(ASN1_TIME *tm, struct buffer *out)
Emeric Brunce5ad802012-10-22 14:11:22 +02006871{
6872 if (tm->type == V_ASN1_GENERALIZEDTIME) {
6873 ASN1_GENERALIZEDTIME *gentm = (ASN1_GENERALIZEDTIME *)tm;
6874
6875 if (gentm->length < 12)
6876 return 0;
6877 if (gentm->data[0] != 0x32 || gentm->data[1] != 0x30)
6878 return 0;
6879 if (out->size < gentm->length-2)
6880 return -1;
6881
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006882 memcpy(out->area, gentm->data+2, gentm->length-2);
6883 out->data = gentm->length-2;
Emeric Brunce5ad802012-10-22 14:11:22 +02006884 return 1;
6885 }
6886 else if (tm->type == V_ASN1_UTCTIME) {
6887 ASN1_UTCTIME *utctm = (ASN1_UTCTIME *)tm;
6888
6889 if (utctm->length < 10)
6890 return 0;
6891 if (utctm->data[0] >= 0x35)
6892 return 0;
6893 if (out->size < utctm->length)
6894 return -1;
6895
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006896 memcpy(out->area, utctm->data, utctm->length);
6897 out->data = utctm->length;
Emeric Brunce5ad802012-10-22 14:11:22 +02006898 return 1;
6899 }
6900
6901 return 0;
6902}
6903
Emeric Brun87855892012-10-17 17:39:35 +02006904/* Extract an entry from a X509_NAME and copy its value to an output chunk.
6905 * Returns 1 if entry found, 0 if entry not found, or -1 if output not large enough.
6906 */
6907static int
Willy Tarreau83061a82018-07-13 11:56:34 +02006908ssl_sock_get_dn_entry(X509_NAME *a, const struct buffer *entry, int pos,
6909 struct buffer *out)
Emeric Brun87855892012-10-17 17:39:35 +02006910{
6911 X509_NAME_ENTRY *ne;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006912 ASN1_OBJECT *obj;
6913 ASN1_STRING *data;
6914 const unsigned char *data_ptr;
6915 int data_len;
Emeric Brun87855892012-10-17 17:39:35 +02006916 int i, j, n;
6917 int cur = 0;
6918 const char *s;
6919 char tmp[128];
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006920 int name_count;
6921
6922 name_count = X509_NAME_entry_count(a);
Emeric Brun87855892012-10-17 17:39:35 +02006923
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006924 out->data = 0;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006925 for (i = 0; i < name_count; i++) {
Emeric Brun87855892012-10-17 17:39:35 +02006926 if (pos < 0)
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006927 j = (name_count-1) - i;
Emeric Brun87855892012-10-17 17:39:35 +02006928 else
6929 j = i;
6930
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006931 ne = X509_NAME_get_entry(a, j);
6932 obj = X509_NAME_ENTRY_get_object(ne);
6933 data = X509_NAME_ENTRY_get_data(ne);
6934 data_ptr = ASN1_STRING_get0_data(data);
6935 data_len = ASN1_STRING_length(data);
6936 n = OBJ_obj2nid(obj);
Emeric Brun87855892012-10-17 17:39:35 +02006937 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006938 i2t_ASN1_OBJECT(tmp, sizeof(tmp), obj);
Emeric Brun87855892012-10-17 17:39:35 +02006939 s = tmp;
6940 }
6941
6942 if (chunk_strcasecmp(entry, s) != 0)
6943 continue;
6944
6945 if (pos < 0)
6946 cur--;
6947 else
6948 cur++;
6949
6950 if (cur != pos)
6951 continue;
6952
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006953 if (data_len > out->size)
Emeric Brun87855892012-10-17 17:39:35 +02006954 return -1;
6955
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006956 memcpy(out->area, data_ptr, data_len);
6957 out->data = data_len;
Emeric Brun87855892012-10-17 17:39:35 +02006958 return 1;
6959 }
6960
6961 return 0;
6962
6963}
6964
6965/* Extract and format full DN from a X509_NAME and copy result into a chunk
6966 * Returns 1 if dn entries exits, 0 if no dn entry found or -1 if output is not large enough.
6967 */
6968static int
Willy Tarreau83061a82018-07-13 11:56:34 +02006969ssl_sock_get_dn_oneline(X509_NAME *a, struct buffer *out)
Emeric Brun87855892012-10-17 17:39:35 +02006970{
6971 X509_NAME_ENTRY *ne;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006972 ASN1_OBJECT *obj;
6973 ASN1_STRING *data;
6974 const unsigned char *data_ptr;
6975 int data_len;
Emeric Brun87855892012-10-17 17:39:35 +02006976 int i, n, ln;
6977 int l = 0;
6978 const char *s;
6979 char *p;
6980 char tmp[128];
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006981 int name_count;
6982
6983
6984 name_count = X509_NAME_entry_count(a);
Emeric Brun87855892012-10-17 17:39:35 +02006985
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006986 out->data = 0;
6987 p = out->area;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006988 for (i = 0; i < name_count; i++) {
6989 ne = X509_NAME_get_entry(a, i);
6990 obj = X509_NAME_ENTRY_get_object(ne);
6991 data = X509_NAME_ENTRY_get_data(ne);
6992 data_ptr = ASN1_STRING_get0_data(data);
6993 data_len = ASN1_STRING_length(data);
6994 n = OBJ_obj2nid(obj);
Emeric Brun87855892012-10-17 17:39:35 +02006995 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006996 i2t_ASN1_OBJECT(tmp, sizeof(tmp), obj);
Emeric Brun87855892012-10-17 17:39:35 +02006997 s = tmp;
6998 }
6999 ln = strlen(s);
7000
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007001 l += 1 + ln + 1 + data_len;
Emeric Brun87855892012-10-17 17:39:35 +02007002 if (l > out->size)
7003 return -1;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007004 out->data = l;
Emeric Brun87855892012-10-17 17:39:35 +02007005
7006 *(p++)='/';
7007 memcpy(p, s, ln);
7008 p += ln;
7009 *(p++)='=';
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007010 memcpy(p, data_ptr, data_len);
7011 p += data_len;
Emeric Brun87855892012-10-17 17:39:35 +02007012 }
7013
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007014 if (!out->data)
Emeric Brun87855892012-10-17 17:39:35 +02007015 return 0;
7016
7017 return 1;
7018}
7019
Olivier Houchardab28a322018-12-21 19:45:40 +01007020void ssl_sock_set_alpn(struct connection *conn, const unsigned char *alpn, int len)
7021{
7022#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Christopher Faulet82004142019-09-10 10:12:03 +02007023 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007024
Olivier Houcharde488ea82019-06-28 14:10:33 +02007025 if (!ssl_sock_is_ssl(conn))
7026 return;
Christopher Faulet82004142019-09-10 10:12:03 +02007027 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007028 SSL_set_alpn_protos(ctx->ssl, alpn, len);
Olivier Houchardab28a322018-12-21 19:45:40 +01007029#endif
7030}
7031
Willy Tarreau119a4082016-12-22 21:58:38 +01007032/* Sets advertised SNI for outgoing connections. Please set <hostname> to NULL
7033 * to disable SNI.
7034 */
Willy Tarreau63076412015-07-10 11:33:32 +02007035void ssl_sock_set_servername(struct connection *conn, const char *hostname)
7036{
7037#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Christopher Faulet82004142019-09-10 10:12:03 +02007038 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007039
Willy Tarreau119a4082016-12-22 21:58:38 +01007040 char *prev_name;
7041
Willy Tarreau63076412015-07-10 11:33:32 +02007042 if (!ssl_sock_is_ssl(conn))
7043 return;
Christopher Faulet82004142019-09-10 10:12:03 +02007044 ctx = conn->xprt_ctx;
Willy Tarreau63076412015-07-10 11:33:32 +02007045
Willy Tarreau119a4082016-12-22 21:58:38 +01007046 /* if the SNI changes, we must destroy the reusable context so that a
7047 * new connection will present a new SNI. As an optimization we could
7048 * later imagine having a small cache of ssl_ctx to hold a few SNI per
7049 * server.
7050 */
Olivier Houchard66ab4982019-02-26 18:37:15 +01007051 prev_name = (char *)SSL_get_servername(ctx->ssl, TLSEXT_NAMETYPE_host_name);
Willy Tarreau119a4082016-12-22 21:58:38 +01007052 if ((!prev_name && hostname) ||
7053 (prev_name && (!hostname || strcmp(hostname, prev_name) != 0)))
Olivier Houchard66ab4982019-02-26 18:37:15 +01007054 SSL_set_session(ctx->ssl, NULL);
Willy Tarreau119a4082016-12-22 21:58:38 +01007055
Olivier Houchard66ab4982019-02-26 18:37:15 +01007056 SSL_set_tlsext_host_name(ctx->ssl, hostname);
Willy Tarreau63076412015-07-10 11:33:32 +02007057#endif
7058}
7059
Emeric Brun0abf8362014-06-24 18:26:41 +02007060/* Extract peer certificate's common name into the chunk dest
7061 * Returns
7062 * the len of the extracted common name
7063 * or 0 if no CN found in DN
7064 * or -1 on error case (i.e. no peer certificate)
7065 */
Willy Tarreau83061a82018-07-13 11:56:34 +02007066int ssl_sock_get_remote_common_name(struct connection *conn,
7067 struct buffer *dest)
David Safb76832014-05-08 23:42:08 -04007068{
Christopher Faulet82004142019-09-10 10:12:03 +02007069 struct ssl_sock_ctx *ctx;
David Safb76832014-05-08 23:42:08 -04007070 X509 *crt = NULL;
7071 X509_NAME *name;
David Safb76832014-05-08 23:42:08 -04007072 const char find_cn[] = "CN";
Willy Tarreau83061a82018-07-13 11:56:34 +02007073 const struct buffer find_cn_chunk = {
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007074 .area = (char *)&find_cn,
7075 .data = sizeof(find_cn)-1
David Safb76832014-05-08 23:42:08 -04007076 };
Emeric Brun0abf8362014-06-24 18:26:41 +02007077 int result = -1;
David Safb76832014-05-08 23:42:08 -04007078
7079 if (!ssl_sock_is_ssl(conn))
Emeric Brun0abf8362014-06-24 18:26:41 +02007080 goto out;
Christopher Faulet82004142019-09-10 10:12:03 +02007081 ctx = conn->xprt_ctx;
David Safb76832014-05-08 23:42:08 -04007082
7083 /* SSL_get_peer_certificate, it increase X509 * ref count */
Olivier Houchard66ab4982019-02-26 18:37:15 +01007084 crt = SSL_get_peer_certificate(ctx->ssl);
David Safb76832014-05-08 23:42:08 -04007085 if (!crt)
7086 goto out;
7087
7088 name = X509_get_subject_name(crt);
7089 if (!name)
7090 goto out;
David Safb76832014-05-08 23:42:08 -04007091
Emeric Brun0abf8362014-06-24 18:26:41 +02007092 result = ssl_sock_get_dn_entry(name, &find_cn_chunk, 1, dest);
7093out:
David Safb76832014-05-08 23:42:08 -04007094 if (crt)
7095 X509_free(crt);
7096
7097 return result;
7098}
7099
Dave McCowan328fb582014-07-30 10:39:13 -04007100/* returns 1 if client passed a certificate for this session, 0 if not */
7101int ssl_sock_get_cert_used_sess(struct connection *conn)
7102{
Christopher Faulet82004142019-09-10 10:12:03 +02007103 struct ssl_sock_ctx *ctx;
Dave McCowan328fb582014-07-30 10:39:13 -04007104 X509 *crt = NULL;
7105
7106 if (!ssl_sock_is_ssl(conn))
7107 return 0;
Christopher Faulet82004142019-09-10 10:12:03 +02007108 ctx = conn->xprt_ctx;
Dave McCowan328fb582014-07-30 10:39:13 -04007109
7110 /* SSL_get_peer_certificate, it increase X509 * ref count */
Olivier Houchard66ab4982019-02-26 18:37:15 +01007111 crt = SSL_get_peer_certificate(ctx->ssl);
Dave McCowan328fb582014-07-30 10:39:13 -04007112 if (!crt)
7113 return 0;
7114
7115 X509_free(crt);
7116 return 1;
7117}
7118
7119/* returns 1 if client passed a certificate for this connection, 0 if not */
7120int ssl_sock_get_cert_used_conn(struct connection *conn)
David Safb76832014-05-08 23:42:08 -04007121{
Christopher Faulet82004142019-09-10 10:12:03 +02007122 struct ssl_sock_ctx *ctx;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007123
David Safb76832014-05-08 23:42:08 -04007124 if (!ssl_sock_is_ssl(conn))
7125 return 0;
Christopher Faulet82004142019-09-10 10:12:03 +02007126 ctx = conn->xprt_ctx;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007127 return SSL_SOCK_ST_FL_VERIFY_DONE & ctx->xprt_st ? 1 : 0;
David Safb76832014-05-08 23:42:08 -04007128}
7129
7130/* returns result from SSL verify */
7131unsigned int ssl_sock_get_verify_result(struct connection *conn)
7132{
Christopher Faulet82004142019-09-10 10:12:03 +02007133 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007134
David Safb76832014-05-08 23:42:08 -04007135 if (!ssl_sock_is_ssl(conn))
7136 return (unsigned int)X509_V_ERR_APPLICATION_VERIFICATION;
Christopher Faulet82004142019-09-10 10:12:03 +02007137 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007138 return (unsigned int)SSL_get_verify_result(ctx->ssl);
David Safb76832014-05-08 23:42:08 -04007139}
7140
Willy Tarreau8743f7e2016-12-04 18:44:29 +01007141/* Returns the application layer protocol name in <str> and <len> when known.
7142 * Zero is returned if the protocol name was not found, otherwise non-zero is
7143 * returned. The string is allocated in the SSL context and doesn't have to be
7144 * freed by the caller. NPN is also checked if available since older versions
7145 * of openssl (1.0.1) which are more common in field only support this one.
7146 */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01007147static int ssl_sock_get_alpn(const struct connection *conn, void *xprt_ctx, const char **str, int *len)
Willy Tarreau8743f7e2016-12-04 18:44:29 +01007148{
Olivier Houchard66ab4982019-02-26 18:37:15 +01007149#if defined(TLSEXT_TYPE_application_layer_protocol_negotiation) || \
7150 defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Olivier Houcharde179d0e2019-03-21 18:27:17 +01007151 struct ssl_sock_ctx *ctx = xprt_ctx;
7152 if (!ctx)
Willy Tarreau8743f7e2016-12-04 18:44:29 +01007153 return 0;
7154
7155 *str = NULL;
7156
7157#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Olivier Houchard66ab4982019-02-26 18:37:15 +01007158 SSL_get0_alpn_selected(ctx->ssl, (const unsigned char **)str, (unsigned *)len);
Willy Tarreau8743f7e2016-12-04 18:44:29 +01007159 if (*str)
7160 return 1;
7161#endif
Bernard Spil13c53f82018-02-15 13:34:58 +01007162#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007163 SSL_get0_next_proto_negotiated(ctx->ssl, (const unsigned char **)str, (unsigned *)len);
Willy Tarreau8743f7e2016-12-04 18:44:29 +01007164 if (*str)
7165 return 1;
7166#endif
Olivier Houcharde179d0e2019-03-21 18:27:17 +01007167#endif
Willy Tarreau8743f7e2016-12-04 18:44:29 +01007168 return 0;
7169}
7170
Willy Tarreau7875d092012-09-10 08:20:03 +02007171/***** Below are some sample fetching functions for ACL/patterns *****/
7172
Olivier Houchardccaa7de2017-10-02 11:51:03 +02007173static int
7174smp_fetch_ssl_fc_has_early(const struct arg *args, struct sample *smp, const char *kw, void *private)
7175{
7176 struct connection *conn;
7177
7178 conn = objt_conn(smp->sess->origin);
7179 if (!conn || conn->xprt != &ssl_sock)
7180 return 0;
7181
7182 smp->flags = 0;
7183 smp->data.type = SMP_T_BOOL;
Emmanuel Hocdetc9858012019-08-07 14:44:49 +02007184#ifdef OPENSSL_IS_BORINGSSL
7185 {
7186 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
7187 smp->data.u.sint = (SSL_in_early_data(ctx->ssl) &&
7188 SSL_early_data_accepted(ctx->ssl));
7189 }
7190#else
Olivier Houchard25ae45a2017-11-29 19:51:19 +01007191 smp->data.u.sint = ((conn->flags & CO_FL_EARLY_DATA) &&
7192 (conn->flags & (CO_FL_EARLY_SSL_HS | CO_FL_HANDSHAKE))) ? 1 : 0;
Emmanuel Hocdetc9858012019-08-07 14:44:49 +02007193#endif
Olivier Houchardccaa7de2017-10-02 11:51:03 +02007194 return 1;
7195}
7196
Emeric Brune64aef12012-09-21 13:15:06 +02007197/* boolean, returns true if client cert was present */
7198static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007199smp_fetch_ssl_fc_has_crt(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brune64aef12012-09-21 13:15:06 +02007200{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007201 struct connection *conn;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007202 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007203
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007204 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007205 if (!conn || conn->xprt != &ssl_sock)
Emeric Brune64aef12012-09-21 13:15:06 +02007206 return 0;
7207
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007208 ctx = conn->xprt_ctx;
7209
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007210 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brune64aef12012-09-21 13:15:06 +02007211 smp->flags |= SMP_F_MAY_CHANGE;
7212 return 0;
7213 }
7214
7215 smp->flags = 0;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007216 smp->data.type = SMP_T_BOOL;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007217 smp->data.u.sint = SSL_SOCK_ST_FL_VERIFY_DONE & ctx->xprt_st ? 1 : 0;
Emeric Brune64aef12012-09-21 13:15:06 +02007218
7219 return 1;
7220}
7221
Emeric Brun43e79582014-10-29 19:03:26 +01007222/* binary, returns a certificate in a binary chunk (der/raw).
7223 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7224 * should be use.
7225 */
7226static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007227smp_fetch_ssl_x_der(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun43e79582014-10-29 19:03:26 +01007228{
7229 int cert_peer = (kw[4] == 'c') ? 1 : 0;
7230 X509 *crt = NULL;
7231 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02007232 struct buffer *smp_trash;
Emeric Brun43e79582014-10-29 19:03:26 +01007233 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007234 struct ssl_sock_ctx *ctx;
Emeric Brun43e79582014-10-29 19:03:26 +01007235
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007236 conn = objt_conn(smp->sess->origin);
Emeric Brun43e79582014-10-29 19:03:26 +01007237 if (!conn || conn->xprt != &ssl_sock)
7238 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007239 ctx = conn->xprt_ctx;
Emeric Brun43e79582014-10-29 19:03:26 +01007240
7241 if (!(conn->flags & CO_FL_CONNECTED)) {
7242 smp->flags |= SMP_F_MAY_CHANGE;
7243 return 0;
7244 }
7245
7246 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007247 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brun43e79582014-10-29 19:03:26 +01007248 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007249 crt = SSL_get_certificate(ctx->ssl);
Emeric Brun43e79582014-10-29 19:03:26 +01007250
7251 if (!crt)
7252 goto out;
7253
7254 smp_trash = get_trash_chunk();
7255 if (ssl_sock_crt2der(crt, smp_trash) <= 0)
7256 goto out;
7257
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007258 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007259 smp->data.type = SMP_T_BIN;
Emeric Brun43e79582014-10-29 19:03:26 +01007260 ret = 1;
7261out:
7262 /* SSL_get_peer_certificate, it increase X509 * ref count */
7263 if (cert_peer && crt)
7264 X509_free(crt);
7265 return ret;
7266}
7267
Emeric Brunba841a12014-04-30 17:05:08 +02007268/* binary, returns serial of certificate in a binary chunk.
7269 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7270 * should be use.
7271 */
Willy Tarreau8d598402012-10-22 17:58:39 +02007272static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007273smp_fetch_ssl_x_serial(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau8d598402012-10-22 17:58:39 +02007274{
Emeric Brunba841a12014-04-30 17:05:08 +02007275 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Willy Tarreau8d598402012-10-22 17:58:39 +02007276 X509 *crt = NULL;
7277 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02007278 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007279 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007280 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007281
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007282 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007283 if (!conn || conn->xprt != &ssl_sock)
Willy Tarreau8d598402012-10-22 17:58:39 +02007284 return 0;
7285
Olivier Houchard66ab4982019-02-26 18:37:15 +01007286 ctx = conn->xprt_ctx;
7287
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007288 if (!(conn->flags & CO_FL_CONNECTED)) {
Willy Tarreau8d598402012-10-22 17:58:39 +02007289 smp->flags |= SMP_F_MAY_CHANGE;
7290 return 0;
7291 }
7292
Emeric Brunba841a12014-04-30 17:05:08 +02007293 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007294 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007295 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007296 crt = SSL_get_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007297
Willy Tarreau8d598402012-10-22 17:58:39 +02007298 if (!crt)
7299 goto out;
7300
Willy Tarreau47ca5452012-12-23 20:22:19 +01007301 smp_trash = get_trash_chunk();
Willy Tarreau8d598402012-10-22 17:58:39 +02007302 if (ssl_sock_get_serial(crt, smp_trash) <= 0)
7303 goto out;
7304
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007305 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007306 smp->data.type = SMP_T_BIN;
Willy Tarreau8d598402012-10-22 17:58:39 +02007307 ret = 1;
7308out:
Emeric Brunba841a12014-04-30 17:05:08 +02007309 /* SSL_get_peer_certificate, it increase X509 * ref count */
7310 if (cert_peer && crt)
Willy Tarreau8d598402012-10-22 17:58:39 +02007311 X509_free(crt);
7312 return ret;
7313}
Emeric Brune64aef12012-09-21 13:15:06 +02007314
Emeric Brunba841a12014-04-30 17:05:08 +02007315/* binary, returns the client certificate's SHA-1 fingerprint (SHA-1 hash of DER-encoded certificate) in a binary chunk.
7316 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7317 * should be use.
7318 */
James Votha051b4a2013-05-14 20:37:59 +02007319static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007320smp_fetch_ssl_x_sha1(const struct arg *args, struct sample *smp, const char *kw, void *private)
James Votha051b4a2013-05-14 20:37:59 +02007321{
Emeric Brunba841a12014-04-30 17:05:08 +02007322 int cert_peer = (kw[4] == 'c') ? 1 : 0;
James Votha051b4a2013-05-14 20:37:59 +02007323 X509 *crt = NULL;
7324 const EVP_MD *digest;
7325 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02007326 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007327 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007328 struct ssl_sock_ctx *ctx;
James Votha051b4a2013-05-14 20:37:59 +02007329
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007330 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007331 if (!conn || conn->xprt != &ssl_sock)
7332 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007333 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007334
7335 if (!(conn->flags & CO_FL_CONNECTED)) {
James Votha051b4a2013-05-14 20:37:59 +02007336 smp->flags |= SMP_F_MAY_CHANGE;
7337 return 0;
7338 }
7339
Emeric Brunba841a12014-04-30 17:05:08 +02007340 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007341 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007342 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007343 crt = SSL_get_certificate(ctx->ssl);
James Votha051b4a2013-05-14 20:37:59 +02007344 if (!crt)
7345 goto out;
7346
7347 smp_trash = get_trash_chunk();
7348 digest = EVP_sha1();
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007349 X509_digest(crt, digest, (unsigned char *) smp_trash->area,
7350 (unsigned int *)&smp_trash->data);
James Votha051b4a2013-05-14 20:37:59 +02007351
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007352 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007353 smp->data.type = SMP_T_BIN;
James Votha051b4a2013-05-14 20:37:59 +02007354 ret = 1;
7355out:
Emeric Brunba841a12014-04-30 17:05:08 +02007356 /* SSL_get_peer_certificate, it increase X509 * ref count */
7357 if (cert_peer && crt)
James Votha051b4a2013-05-14 20:37:59 +02007358 X509_free(crt);
7359 return ret;
7360}
7361
Emeric Brunba841a12014-04-30 17:05:08 +02007362/* string, returns certificate's notafter date in ASN1_UTCTIME format.
7363 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7364 * should be use.
7365 */
Emeric Brunce5ad802012-10-22 14:11:22 +02007366static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007367smp_fetch_ssl_x_notafter(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunce5ad802012-10-22 14:11:22 +02007368{
Emeric Brunba841a12014-04-30 17:05:08 +02007369 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brunce5ad802012-10-22 14:11:22 +02007370 X509 *crt = NULL;
7371 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02007372 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007373 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007374 struct ssl_sock_ctx *ctx;
Emeric Brunce5ad802012-10-22 14:11:22 +02007375
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007376 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007377 if (!conn || conn->xprt != &ssl_sock)
7378 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007379 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007380
7381 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02007382 smp->flags |= SMP_F_MAY_CHANGE;
7383 return 0;
7384 }
7385
Emeric Brunba841a12014-04-30 17:05:08 +02007386 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007387 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007388 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007389 crt = SSL_get_certificate(ctx->ssl);
Emeric Brunce5ad802012-10-22 14:11:22 +02007390 if (!crt)
7391 goto out;
7392
Willy Tarreau47ca5452012-12-23 20:22:19 +01007393 smp_trash = get_trash_chunk();
Rosen Penev68185952018-12-14 08:47:02 -08007394 if (ssl_sock_get_time(X509_getm_notAfter(crt), smp_trash) <= 0)
Emeric Brunce5ad802012-10-22 14:11:22 +02007395 goto out;
7396
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007397 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007398 smp->data.type = SMP_T_STR;
Emeric Brunce5ad802012-10-22 14:11:22 +02007399 ret = 1;
7400out:
Emeric Brunba841a12014-04-30 17:05:08 +02007401 /* SSL_get_peer_certificate, it increase X509 * ref count */
7402 if (cert_peer && crt)
Emeric Brunce5ad802012-10-22 14:11:22 +02007403 X509_free(crt);
7404 return ret;
7405}
7406
Emeric Brunba841a12014-04-30 17:05:08 +02007407/* string, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. of certificate's issuer
7408 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7409 * should be use.
7410 */
Emeric Brun87855892012-10-17 17:39:35 +02007411static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007412smp_fetch_ssl_x_i_dn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun87855892012-10-17 17:39:35 +02007413{
Emeric Brunba841a12014-04-30 17:05:08 +02007414 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun87855892012-10-17 17:39:35 +02007415 X509 *crt = NULL;
7416 X509_NAME *name;
7417 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02007418 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007419 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007420 struct ssl_sock_ctx *ctx;
Emeric Brun87855892012-10-17 17:39:35 +02007421
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007422 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007423 if (!conn || conn->xprt != &ssl_sock)
7424 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007425 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007426
7427 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02007428 smp->flags |= SMP_F_MAY_CHANGE;
7429 return 0;
7430 }
7431
Emeric Brunba841a12014-04-30 17:05:08 +02007432 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007433 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007434 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007435 crt = SSL_get_certificate(ctx->ssl);
Emeric Brun87855892012-10-17 17:39:35 +02007436 if (!crt)
7437 goto out;
7438
7439 name = X509_get_issuer_name(crt);
7440 if (!name)
7441 goto out;
7442
Willy Tarreau47ca5452012-12-23 20:22:19 +01007443 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02007444 if (args && args[0].type == ARGT_STR) {
7445 int pos = 1;
7446
7447 if (args[1].type == ARGT_SINT)
7448 pos = args[1].data.sint;
Emeric Brun87855892012-10-17 17:39:35 +02007449
7450 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
7451 goto out;
7452 }
7453 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
7454 goto out;
7455
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007456 smp->data.type = SMP_T_STR;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007457 smp->data.u.str = *smp_trash;
Emeric Brun87855892012-10-17 17:39:35 +02007458 ret = 1;
7459out:
Emeric Brunba841a12014-04-30 17:05:08 +02007460 /* SSL_get_peer_certificate, it increase X509 * ref count */
7461 if (cert_peer && crt)
Emeric Brun87855892012-10-17 17:39:35 +02007462 X509_free(crt);
7463 return ret;
7464}
7465
Emeric Brunba841a12014-04-30 17:05:08 +02007466/* string, returns notbefore date in ASN1_UTCTIME format.
7467 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7468 * should be use.
7469 */
Emeric Brunce5ad802012-10-22 14:11:22 +02007470static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007471smp_fetch_ssl_x_notbefore(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunce5ad802012-10-22 14:11:22 +02007472{
Emeric Brunba841a12014-04-30 17:05:08 +02007473 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brunce5ad802012-10-22 14:11:22 +02007474 X509 *crt = NULL;
7475 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02007476 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007477 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007478 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007479
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007480 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007481 if (!conn || conn->xprt != &ssl_sock)
Emeric Brunce5ad802012-10-22 14:11:22 +02007482 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007483 ctx = conn->xprt_ctx;
Emeric Brunce5ad802012-10-22 14:11:22 +02007484
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007485 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02007486 smp->flags |= SMP_F_MAY_CHANGE;
7487 return 0;
7488 }
7489
Emeric Brunba841a12014-04-30 17:05:08 +02007490 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007491 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007492 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007493 crt = SSL_get_certificate(ctx->ssl);
Emeric Brunce5ad802012-10-22 14:11:22 +02007494 if (!crt)
7495 goto out;
7496
Willy Tarreau47ca5452012-12-23 20:22:19 +01007497 smp_trash = get_trash_chunk();
Rosen Penev68185952018-12-14 08:47:02 -08007498 if (ssl_sock_get_time(X509_getm_notBefore(crt), smp_trash) <= 0)
Emeric Brunce5ad802012-10-22 14:11:22 +02007499 goto out;
7500
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007501 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007502 smp->data.type = SMP_T_STR;
Emeric Brunce5ad802012-10-22 14:11:22 +02007503 ret = 1;
7504out:
Emeric Brunba841a12014-04-30 17:05:08 +02007505 /* SSL_get_peer_certificate, it increase X509 * ref count */
7506 if (cert_peer && crt)
Emeric Brunce5ad802012-10-22 14:11:22 +02007507 X509_free(crt);
7508 return ret;
7509}
7510
Emeric Brunba841a12014-04-30 17:05:08 +02007511/* string, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. of certificate's subject
7512 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7513 * should be use.
7514 */
Emeric Brun87855892012-10-17 17:39:35 +02007515static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007516smp_fetch_ssl_x_s_dn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun87855892012-10-17 17:39:35 +02007517{
Emeric Brunba841a12014-04-30 17:05:08 +02007518 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun87855892012-10-17 17:39:35 +02007519 X509 *crt = NULL;
7520 X509_NAME *name;
7521 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02007522 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007523 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007524 struct ssl_sock_ctx *ctx;
Emeric Brun87855892012-10-17 17:39:35 +02007525
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007526 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007527 if (!conn || conn->xprt != &ssl_sock)
7528 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007529 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007530
7531 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02007532 smp->flags |= SMP_F_MAY_CHANGE;
7533 return 0;
7534 }
7535
Emeric Brunba841a12014-04-30 17:05:08 +02007536 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007537 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007538 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007539 crt = SSL_get_certificate(ctx->ssl);
Emeric Brun87855892012-10-17 17:39:35 +02007540 if (!crt)
7541 goto out;
7542
7543 name = X509_get_subject_name(crt);
7544 if (!name)
7545 goto out;
7546
Willy Tarreau47ca5452012-12-23 20:22:19 +01007547 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02007548 if (args && args[0].type == ARGT_STR) {
7549 int pos = 1;
7550
7551 if (args[1].type == ARGT_SINT)
7552 pos = args[1].data.sint;
Emeric Brun87855892012-10-17 17:39:35 +02007553
7554 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
7555 goto out;
7556 }
7557 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
7558 goto out;
7559
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007560 smp->data.type = SMP_T_STR;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007561 smp->data.u.str = *smp_trash;
Emeric Brun87855892012-10-17 17:39:35 +02007562 ret = 1;
7563out:
Emeric Brunba841a12014-04-30 17:05:08 +02007564 /* SSL_get_peer_certificate, it increase X509 * ref count */
7565 if (cert_peer && crt)
Emeric Brun87855892012-10-17 17:39:35 +02007566 X509_free(crt);
7567 return ret;
7568}
Emeric Brun9143d372012-12-20 15:44:16 +01007569
7570/* integer, returns true if current session use a client certificate */
7571static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007572smp_fetch_ssl_c_used(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun9143d372012-12-20 15:44:16 +01007573{
7574 X509 *crt;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007575 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007576 struct ssl_sock_ctx *ctx;
Emeric Brun9143d372012-12-20 15:44:16 +01007577
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007578 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007579 if (!conn || conn->xprt != &ssl_sock)
7580 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007581 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007582
7583 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun9143d372012-12-20 15:44:16 +01007584 smp->flags |= SMP_F_MAY_CHANGE;
7585 return 0;
7586 }
7587
7588 /* SSL_get_peer_certificate returns a ptr on allocated X509 struct */
Olivier Houchard66ab4982019-02-26 18:37:15 +01007589 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brun9143d372012-12-20 15:44:16 +01007590 if (crt) {
7591 X509_free(crt);
7592 }
7593
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007594 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007595 smp->data.u.sint = (crt != NULL);
Emeric Brun9143d372012-12-20 15:44:16 +01007596 return 1;
7597}
7598
Emeric Brunba841a12014-04-30 17:05:08 +02007599/* integer, returns the certificate version
7600 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7601 * should be use.
7602 */
Emeric Bruna7359fd2012-10-17 15:03:11 +02007603static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007604smp_fetch_ssl_x_version(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Bruna7359fd2012-10-17 15:03:11 +02007605{
Emeric Brunba841a12014-04-30 17:05:08 +02007606 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Bruna7359fd2012-10-17 15:03:11 +02007607 X509 *crt;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007608 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007609 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007610
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007611 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007612 if (!conn || conn->xprt != &ssl_sock)
Emeric Bruna7359fd2012-10-17 15:03:11 +02007613 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007614 ctx = conn->xprt_ctx;
Emeric Bruna7359fd2012-10-17 15:03:11 +02007615
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007616 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Bruna7359fd2012-10-17 15:03:11 +02007617 smp->flags |= SMP_F_MAY_CHANGE;
7618 return 0;
7619 }
7620
Emeric Brunba841a12014-04-30 17:05:08 +02007621 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007622 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007623 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007624 crt = SSL_get_certificate(ctx->ssl);
Emeric Bruna7359fd2012-10-17 15:03:11 +02007625 if (!crt)
7626 return 0;
7627
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007628 smp->data.u.sint = (unsigned int)(1 + X509_get_version(crt));
Emeric Brunba841a12014-04-30 17:05:08 +02007629 /* SSL_get_peer_certificate increase X509 * ref count */
7630 if (cert_peer)
7631 X509_free(crt);
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007632 smp->data.type = SMP_T_SINT;
Emeric Bruna7359fd2012-10-17 15:03:11 +02007633
7634 return 1;
7635}
7636
Emeric Brunba841a12014-04-30 17:05:08 +02007637/* string, returns the certificate's signature algorithm.
7638 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7639 * should be use.
7640 */
Emeric Brun7f56e742012-10-19 18:15:40 +02007641static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007642smp_fetch_ssl_x_sig_alg(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun7f56e742012-10-19 18:15:40 +02007643{
Emeric Brunba841a12014-04-30 17:05:08 +02007644 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun7f56e742012-10-19 18:15:40 +02007645 X509 *crt;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007646 __OPENSSL_110_CONST__ ASN1_OBJECT *algorithm;
Emeric Brun7f56e742012-10-19 18:15:40 +02007647 int nid;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007648 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007649 struct ssl_sock_ctx *ctx;
Emeric Brun7f56e742012-10-19 18:15:40 +02007650
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007651 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007652 if (!conn || conn->xprt != &ssl_sock)
7653 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007654 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007655
7656 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun7f56e742012-10-19 18:15:40 +02007657 smp->flags |= SMP_F_MAY_CHANGE;
7658 return 0;
7659 }
7660
Emeric Brunba841a12014-04-30 17:05:08 +02007661 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007662 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007663 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007664 crt = SSL_get_certificate(ctx->ssl);
Emeric Brun7f56e742012-10-19 18:15:40 +02007665 if (!crt)
7666 return 0;
7667
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007668 X509_ALGOR_get0(&algorithm, NULL, NULL, X509_get0_tbs_sigalg(crt));
7669 nid = OBJ_obj2nid(algorithm);
Emeric Brun7f56e742012-10-19 18:15:40 +02007670
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007671 smp->data.u.str.area = (char *)OBJ_nid2sn(nid);
7672 if (!smp->data.u.str.area) {
Emeric Brunba841a12014-04-30 17:05:08 +02007673 /* SSL_get_peer_certificate increase X509 * ref count */
7674 if (cert_peer)
7675 X509_free(crt);
Emeric Brun7f56e742012-10-19 18:15:40 +02007676 return 0;
Emeric Brun9bf3ba22013-10-07 14:31:44 +02007677 }
Emeric Brun7f56e742012-10-19 18:15:40 +02007678
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007679 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01007680 smp->flags |= SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007681 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brunba841a12014-04-30 17:05:08 +02007682 /* SSL_get_peer_certificate increase X509 * ref count */
7683 if (cert_peer)
7684 X509_free(crt);
Emeric Brun7f56e742012-10-19 18:15:40 +02007685
7686 return 1;
7687}
7688
Emeric Brunba841a12014-04-30 17:05:08 +02007689/* string, returns the certificate's key algorithm.
7690 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7691 * should be use.
7692 */
Emeric Brun521a0112012-10-22 12:22:55 +02007693static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007694smp_fetch_ssl_x_key_alg(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun521a0112012-10-22 12:22:55 +02007695{
Emeric Brunba841a12014-04-30 17:05:08 +02007696 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun521a0112012-10-22 12:22:55 +02007697 X509 *crt;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007698 ASN1_OBJECT *algorithm;
Emeric Brun521a0112012-10-22 12:22:55 +02007699 int nid;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007700 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007701 struct ssl_sock_ctx *ctx;
Emeric Brun521a0112012-10-22 12:22:55 +02007702
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007703 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007704 if (!conn || conn->xprt != &ssl_sock)
7705 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007706 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007707
7708 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun521a0112012-10-22 12:22:55 +02007709 smp->flags |= SMP_F_MAY_CHANGE;
7710 return 0;
7711 }
7712
Emeric Brunba841a12014-04-30 17:05:08 +02007713 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007714 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007715 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007716 crt = SSL_get_certificate(ctx->ssl);
Emeric Brun521a0112012-10-22 12:22:55 +02007717 if (!crt)
7718 return 0;
7719
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007720 X509_PUBKEY_get0_param(&algorithm, NULL, NULL, NULL, X509_get_X509_PUBKEY(crt));
7721 nid = OBJ_obj2nid(algorithm);
Emeric Brun521a0112012-10-22 12:22:55 +02007722
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007723 smp->data.u.str.area = (char *)OBJ_nid2sn(nid);
7724 if (!smp->data.u.str.area) {
Emeric Brunba841a12014-04-30 17:05:08 +02007725 /* SSL_get_peer_certificate increase X509 * ref count */
7726 if (cert_peer)
7727 X509_free(crt);
Emeric Brun521a0112012-10-22 12:22:55 +02007728 return 0;
Emeric Brun9bf3ba22013-10-07 14:31:44 +02007729 }
Emeric Brun521a0112012-10-22 12:22:55 +02007730
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007731 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01007732 smp->flags |= SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007733 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brunba841a12014-04-30 17:05:08 +02007734 if (cert_peer)
7735 X509_free(crt);
Emeric Brun521a0112012-10-22 12:22:55 +02007736
7737 return 1;
7738}
7739
Emeric Brun645ae792014-04-30 14:21:06 +02007740/* boolean, returns true if front conn. transport layer is SSL.
7741 * This function is also usable on backend conn if the fetch keyword 5th
7742 * char is 'b'.
7743 */
Willy Tarreau7875d092012-09-10 08:20:03 +02007744static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007745smp_fetch_ssl_fc(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02007746{
Emeric Bruneb8def92018-02-19 15:59:48 +01007747 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7748 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007749
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007750 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007751 smp->data.u.sint = (conn && conn->xprt == &ssl_sock);
Willy Tarreau7875d092012-09-10 08:20:03 +02007752 return 1;
7753}
7754
Emeric Brun2525b6b2012-10-18 15:59:43 +02007755/* boolean, returns true if client present a SNI */
Willy Tarreau7875d092012-09-10 08:20:03 +02007756static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007757smp_fetch_ssl_fc_has_sni(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02007758{
7759#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007760 struct connection *conn = objt_conn(smp->sess->origin);
Olivier Houchard66ab4982019-02-26 18:37:15 +01007761 struct ssl_sock_ctx *ctx = conn ? conn->xprt_ctx : NULL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007762
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007763 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007764 smp->data.u.sint = (conn && conn->xprt == &ssl_sock) &&
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007765 conn->xprt_ctx &&
Olivier Houchard66ab4982019-02-26 18:37:15 +01007766 SSL_get_servername(ctx->ssl, TLSEXT_NAMETYPE_host_name) != NULL;
Willy Tarreau7875d092012-09-10 08:20:03 +02007767 return 1;
7768#else
7769 return 0;
7770#endif
7771}
7772
Emeric Brun74f7ffa2018-02-19 16:14:12 +01007773/* boolean, returns true if client session has been resumed.
7774 * This function is also usable on backend conn if the fetch keyword 5th
7775 * char is 'b'.
7776 */
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02007777static int
7778smp_fetch_ssl_fc_is_resumed(const struct arg *args, struct sample *smp, const char *kw, void *private)
7779{
Emeric Brun74f7ffa2018-02-19 16:14:12 +01007780 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7781 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007782 struct ssl_sock_ctx *ctx = conn ? conn->xprt_ctx : NULL;
Emeric Brun74f7ffa2018-02-19 16:14:12 +01007783
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02007784
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007785 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007786 smp->data.u.sint = (conn && conn->xprt == &ssl_sock) &&
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02007787 conn->xprt_ctx &&
Olivier Houchard66ab4982019-02-26 18:37:15 +01007788 SSL_session_reused(ctx->ssl);
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02007789 return 1;
7790}
7791
Emeric Brun645ae792014-04-30 14:21:06 +02007792/* string, returns the used cipher if front conn. transport layer is SSL.
7793 * This function is also usable on backend conn if the fetch keyword 5th
7794 * char is 'b'.
7795 */
Emeric Brun589fcad2012-10-16 14:13:26 +02007796static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007797smp_fetch_ssl_fc_cipher(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02007798{
Emeric Bruneb8def92018-02-19 15:59:48 +01007799 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7800 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007801 struct ssl_sock_ctx *ctx;
Emeric Brun589fcad2012-10-16 14:13:26 +02007802
Willy Tarreaube508f12016-03-10 11:47:01 +01007803 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007804 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02007805 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007806 ctx = conn->xprt_ctx;
Emeric Brun589fcad2012-10-16 14:13:26 +02007807
Olivier Houchard66ab4982019-02-26 18:37:15 +01007808 smp->data.u.str.area = (char *)SSL_get_cipher_name(ctx->ssl);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007809 if (!smp->data.u.str.area)
Emeric Brun589fcad2012-10-16 14:13:26 +02007810 return 0;
7811
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007812 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01007813 smp->flags |= SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007814 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brun589fcad2012-10-16 14:13:26 +02007815
7816 return 1;
7817}
7818
Emeric Brun645ae792014-04-30 14:21:06 +02007819/* integer, returns the algoritm's keysize if front conn. transport layer
7820 * is SSL.
7821 * This function is also usable on backend conn if the fetch keyword 5th
7822 * char is 'b'.
7823 */
Emeric Brun589fcad2012-10-16 14:13:26 +02007824static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007825smp_fetch_ssl_fc_alg_keysize(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02007826{
Emeric Bruneb8def92018-02-19 15:59:48 +01007827 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7828 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007829 struct ssl_sock_ctx *ctx;
Willy Tarreaue237fe12016-03-10 17:05:28 +01007830 int sint;
Willy Tarreaube508f12016-03-10 11:47:01 +01007831
Emeric Brun589fcad2012-10-16 14:13:26 +02007832 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007833 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02007834 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007835 ctx = conn->xprt_ctx;
Emeric Brun589fcad2012-10-16 14:13:26 +02007836
Olivier Houchard66ab4982019-02-26 18:37:15 +01007837 if (!SSL_get_cipher_bits(ctx->ssl, &sint))
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007838 return 0;
7839
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007840 smp->data.u.sint = sint;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007841 smp->data.type = SMP_T_SINT;
Emeric Brun589fcad2012-10-16 14:13:26 +02007842
7843 return 1;
7844}
7845
Emeric Brun645ae792014-04-30 14:21:06 +02007846/* integer, returns the used keysize if front conn. transport layer is SSL.
7847 * This function is also usable on backend conn if the fetch keyword 5th
7848 * char is 'b'.
7849 */
Emeric Brun589fcad2012-10-16 14:13:26 +02007850static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007851smp_fetch_ssl_fc_use_keysize(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02007852{
Emeric Bruneb8def92018-02-19 15:59:48 +01007853 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7854 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007855 struct ssl_sock_ctx *ctx;
Willy Tarreaube508f12016-03-10 11:47:01 +01007856
Emeric Brun589fcad2012-10-16 14:13:26 +02007857 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007858 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7859 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007860 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007861
Olivier Houchard66ab4982019-02-26 18:37:15 +01007862 smp->data.u.sint = (unsigned int)SSL_get_cipher_bits(ctx->ssl, NULL);
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007863 if (!smp->data.u.sint)
Emeric Brun589fcad2012-10-16 14:13:26 +02007864 return 0;
7865
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007866 smp->data.type = SMP_T_SINT;
Emeric Brun589fcad2012-10-16 14:13:26 +02007867
7868 return 1;
7869}
7870
Bernard Spil13c53f82018-02-15 13:34:58 +01007871#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Willy Tarreau7875d092012-09-10 08:20:03 +02007872static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007873smp_fetch_ssl_fc_npn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreaua33c6542012-10-15 13:19:06 +02007874{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007875 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007876 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007877
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01007878 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007879 smp->data.type = SMP_T_STR;
Willy Tarreaua33c6542012-10-15 13:19:06 +02007880
Olivier Houchard6b77f492018-11-22 18:18:29 +01007881 conn = (kw[4] != 'b' ) ? objt_conn(smp->sess->origin) :
7882 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007883 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7884 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007885 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007886
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007887 smp->data.u.str.area = NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007888 SSL_get0_next_proto_negotiated(ctx->ssl,
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007889 (const unsigned char **)&smp->data.u.str.area,
7890 (unsigned *)&smp->data.u.str.data);
Willy Tarreaua33c6542012-10-15 13:19:06 +02007891
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007892 if (!smp->data.u.str.area)
Willy Tarreaua33c6542012-10-15 13:19:06 +02007893 return 0;
7894
7895 return 1;
Willy Tarreaua33c6542012-10-15 13:19:06 +02007896}
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02007897#endif
Willy Tarreaua33c6542012-10-15 13:19:06 +02007898
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01007899#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02007900static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007901smp_fetch_ssl_fc_alpn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreauab861d32013-04-02 02:30:41 +02007902{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007903 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007904 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007905
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01007906 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007907 smp->data.type = SMP_T_STR;
Willy Tarreauab861d32013-04-02 02:30:41 +02007908
Olivier Houchard6b77f492018-11-22 18:18:29 +01007909 conn = (kw[4] != 'b' ) ? objt_conn(smp->sess->origin) :
7910 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
7911
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007912 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Willy Tarreauab861d32013-04-02 02:30:41 +02007913 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007914 ctx = conn->xprt_ctx;
Willy Tarreauab861d32013-04-02 02:30:41 +02007915
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007916 smp->data.u.str.area = NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007917 SSL_get0_alpn_selected(ctx->ssl,
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007918 (const unsigned char **)&smp->data.u.str.area,
7919 (unsigned *)&smp->data.u.str.data);
Willy Tarreauab861d32013-04-02 02:30:41 +02007920
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007921 if (!smp->data.u.str.area)
Willy Tarreauab861d32013-04-02 02:30:41 +02007922 return 0;
7923
7924 return 1;
7925}
7926#endif
7927
Emeric Brun645ae792014-04-30 14:21:06 +02007928/* string, returns the used protocol if front conn. transport layer is SSL.
7929 * This function is also usable on backend conn if the fetch keyword 5th
7930 * char is 'b'.
7931 */
Willy Tarreaua33c6542012-10-15 13:19:06 +02007932static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007933smp_fetch_ssl_fc_protocol(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02007934{
Emeric Bruneb8def92018-02-19 15:59:48 +01007935 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7936 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007937 struct ssl_sock_ctx *ctx;
Willy Tarreaube508f12016-03-10 11:47:01 +01007938
Emeric Brun589fcad2012-10-16 14:13:26 +02007939 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007940 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7941 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007942 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007943
Olivier Houchard66ab4982019-02-26 18:37:15 +01007944 smp->data.u.str.area = (char *)SSL_get_version(ctx->ssl);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007945 if (!smp->data.u.str.area)
Emeric Brun589fcad2012-10-16 14:13:26 +02007946 return 0;
7947
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007948 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01007949 smp->flags = SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007950 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brun589fcad2012-10-16 14:13:26 +02007951
7952 return 1;
7953}
7954
Willy Tarreau87b09662015-04-03 00:22:06 +02007955/* binary, returns the SSL stream id if front conn. transport layer is SSL.
Emeric Brun645ae792014-04-30 14:21:06 +02007956 * This function is also usable on backend conn if the fetch keyword 5th
7957 * char is 'b'.
7958 */
Willy Tarreau9a1ab082019-05-09 13:26:41 +02007959#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
Emeric Brun589fcad2012-10-16 14:13:26 +02007960static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007961smp_fetch_ssl_fc_session_id(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunfe68f682012-10-16 14:59:28 +02007962{
Emeric Bruneb8def92018-02-19 15:59:48 +01007963 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7964 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaue237fe12016-03-10 17:05:28 +01007965 SSL_SESSION *ssl_sess;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007966 struct ssl_sock_ctx *ctx;
Willy Tarreaube508f12016-03-10 11:47:01 +01007967
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01007968 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007969 smp->data.type = SMP_T_BIN;
Emeric Brunfe68f682012-10-16 14:59:28 +02007970
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007971 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7972 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007973 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007974
Olivier Houchard66ab4982019-02-26 18:37:15 +01007975 ssl_sess = SSL_get_session(ctx->ssl);
Willy Tarreau192252e2015-04-04 01:47:55 +02007976 if (!ssl_sess)
Emeric Brunfe68f682012-10-16 14:59:28 +02007977 return 0;
7978
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007979 smp->data.u.str.area = (char *)SSL_SESSION_get_id(ssl_sess,
7980 (unsigned int *)&smp->data.u.str.data);
7981 if (!smp->data.u.str.area || !smp->data.u.str.data)
Emeric Brunfe68f682012-10-16 14:59:28 +02007982 return 0;
7983
7984 return 1;
Emeric Brunfe68f682012-10-16 14:59:28 +02007985}
Patrick Hemmer41966772018-04-28 19:15:48 -04007986#endif
7987
Emeric Brunfe68f682012-10-16 14:59:28 +02007988
Emmanuel Hocdet839af572019-05-14 16:27:35 +02007989#if HA_OPENSSL_VERSION_NUMBER >= 0x10100000L
Patrick Hemmere0275472018-04-28 19:15:51 -04007990static int
Patrick Hemmer65674662019-06-04 08:13:03 -04007991smp_fetch_ssl_fc_random(const struct arg *args, struct sample *smp, const char *kw, void *private)
7992{
7993 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7994 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
7995 struct buffer *data;
7996 struct ssl_sock_ctx *ctx;
7997
7998 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7999 return 0;
8000 ctx = conn->xprt_ctx;
8001
8002 data = get_trash_chunk();
8003 if (kw[7] == 'c')
8004 data->data = SSL_get_client_random(ctx->ssl,
8005 (unsigned char *) data->area,
8006 data->size);
8007 else
8008 data->data = SSL_get_server_random(ctx->ssl,
8009 (unsigned char *) data->area,
8010 data->size);
8011 if (!data->data)
8012 return 0;
8013
8014 smp->flags = 0;
8015 smp->data.type = SMP_T_BIN;
8016 smp->data.u.str = *data;
8017
8018 return 1;
8019}
8020
8021static int
Patrick Hemmere0275472018-04-28 19:15:51 -04008022smp_fetch_ssl_fc_session_key(const struct arg *args, struct sample *smp, const char *kw, void *private)
8023{
8024 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
8025 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
8026 SSL_SESSION *ssl_sess;
Willy Tarreau83061a82018-07-13 11:56:34 +02008027 struct buffer *data;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008028 struct ssl_sock_ctx *ctx;
Patrick Hemmere0275472018-04-28 19:15:51 -04008029
8030 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8031 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008032 ctx = conn->xprt_ctx;
Patrick Hemmere0275472018-04-28 19:15:51 -04008033
Olivier Houchard66ab4982019-02-26 18:37:15 +01008034 ssl_sess = SSL_get_session(ctx->ssl);
Patrick Hemmere0275472018-04-28 19:15:51 -04008035 if (!ssl_sess)
8036 return 0;
8037
8038 data = get_trash_chunk();
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008039 data->data = SSL_SESSION_get_master_key(ssl_sess,
8040 (unsigned char *) data->area,
8041 data->size);
8042 if (!data->data)
Patrick Hemmere0275472018-04-28 19:15:51 -04008043 return 0;
8044
8045 smp->flags = 0;
8046 smp->data.type = SMP_T_BIN;
8047 smp->data.u.str = *data;
8048
8049 return 1;
8050}
8051#endif
8052
Patrick Hemmer41966772018-04-28 19:15:48 -04008053#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emeric Brunfe68f682012-10-16 14:59:28 +02008054static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008055smp_fetch_ssl_fc_sni(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02008056{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008057 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008058 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008059
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008060 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008061 smp->data.type = SMP_T_STR;
Willy Tarreau7875d092012-09-10 08:20:03 +02008062
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02008063 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008064 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8065 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008066 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008067
Olivier Houchard66ab4982019-02-26 18:37:15 +01008068 smp->data.u.str.area = (char *)SSL_get_servername(ctx->ssl, TLSEXT_NAMETYPE_host_name);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008069 if (!smp->data.u.str.area)
Willy Tarreau3e394c92012-09-14 23:56:58 +02008070 return 0;
8071
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008072 smp->data.u.str.data = strlen(smp->data.u.str.area);
Willy Tarreau7875d092012-09-10 08:20:03 +02008073 return 1;
Willy Tarreau7875d092012-09-10 08:20:03 +02008074}
Patrick Hemmer41966772018-04-28 19:15:48 -04008075#endif
Willy Tarreau7875d092012-09-10 08:20:03 +02008076
David Sc1ad52e2014-04-08 18:48:47 -04008077static int
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008078smp_fetch_ssl_fc_cl_bin(const struct arg *args, struct sample *smp, const char *kw, void *private)
8079{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008080 struct connection *conn;
8081 struct ssl_capture *capture;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008082 struct ssl_sock_ctx *ctx;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008083
8084 conn = objt_conn(smp->sess->origin);
8085 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8086 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008087 ctx = conn->xprt_ctx;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008088
Olivier Houchard66ab4982019-02-26 18:37:15 +01008089 capture = SSL_get_ex_data(ctx->ssl, ssl_capture_ptr_index);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008090 if (!capture)
8091 return 0;
8092
8093 smp->flags = SMP_F_CONST;
8094 smp->data.type = SMP_T_BIN;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008095 smp->data.u.str.area = capture->ciphersuite;
8096 smp->data.u.str.data = capture->ciphersuite_len;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008097 return 1;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008098}
8099
8100static int
8101smp_fetch_ssl_fc_cl_hex(const struct arg *args, struct sample *smp, const char *kw, void *private)
8102{
Willy Tarreau83061a82018-07-13 11:56:34 +02008103 struct buffer *data;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008104
8105 if (!smp_fetch_ssl_fc_cl_bin(args, smp, kw, private))
8106 return 0;
8107
8108 data = get_trash_chunk();
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008109 dump_binary(data, smp->data.u.str.area, smp->data.u.str.data);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008110 smp->data.type = SMP_T_BIN;
8111 smp->data.u.str = *data;
8112 return 1;
8113}
8114
8115static int
8116smp_fetch_ssl_fc_cl_xxh64(const struct arg *args, struct sample *smp, const char *kw, void *private)
8117{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008118 struct connection *conn;
8119 struct ssl_capture *capture;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008120 struct ssl_sock_ctx *ctx;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008121
8122 conn = objt_conn(smp->sess->origin);
8123 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8124 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008125 ctx = conn->xprt_ctx;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008126
Olivier Houchard66ab4982019-02-26 18:37:15 +01008127 capture = SSL_get_ex_data(ctx->ssl, ssl_capture_ptr_index);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008128 if (!capture)
8129 return 0;
8130
8131 smp->data.type = SMP_T_SINT;
8132 smp->data.u.sint = capture->xxh64;
8133 return 1;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008134}
8135
8136static int
8137smp_fetch_ssl_fc_cl_str(const struct arg *args, struct sample *smp, const char *kw, void *private)
8138{
Willy Tarreau5db847a2019-05-09 14:13:35 +02008139#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL)
Willy Tarreau83061a82018-07-13 11:56:34 +02008140 struct buffer *data;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008141 int i;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008142
8143 if (!smp_fetch_ssl_fc_cl_bin(args, smp, kw, private))
8144 return 0;
8145
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008146 data = get_trash_chunk();
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008147 for (i = 0; i + 1 < smp->data.u.str.data; i += 2) {
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02008148 const char *str;
8149 const SSL_CIPHER *cipher;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008150 const unsigned char *bin = (const unsigned char *) smp->data.u.str.area + i;
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02008151 uint16_t id = (bin[0] << 8) | bin[1];
8152#if defined(OPENSSL_IS_BORINGSSL)
8153 cipher = SSL_get_cipher_by_value(id);
8154#else
Willy Tarreaub7290772018-10-15 11:01:59 +02008155 struct connection *conn = __objt_conn(smp->sess->origin);
Olivier Houchard66ab4982019-02-26 18:37:15 +01008156 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
8157 cipher = SSL_CIPHER_find(ctx->ssl, bin);
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02008158#endif
8159 str = SSL_CIPHER_get_name(cipher);
8160 if (!str || strcmp(str, "(NONE)") == 0)
8161 chunk_appendf(data, "%sUNKNOWN(%04x)", i == 0 ? "" : ",", id);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008162 else
8163 chunk_appendf(data, "%s%s", i == 0 ? "" : ",", str);
8164 }
8165 smp->data.type = SMP_T_STR;
8166 smp->data.u.str = *data;
8167 return 1;
8168#else
8169 return smp_fetch_ssl_fc_cl_xxh64(args, smp, kw, private);
8170#endif
8171}
8172
Willy Tarreau9a1ab082019-05-09 13:26:41 +02008173#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008174static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008175smp_fetch_ssl_fc_unique_id(const struct arg *args, struct sample *smp, const char *kw, void *private)
David Sc1ad52e2014-04-08 18:48:47 -04008176{
Emeric Bruneb8def92018-02-19 15:59:48 +01008177 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
8178 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
David Sc1ad52e2014-04-08 18:48:47 -04008179 int finished_len;
Willy Tarreau83061a82018-07-13 11:56:34 +02008180 struct buffer *finished_trash;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008181 struct ssl_sock_ctx *ctx;
David Sc1ad52e2014-04-08 18:48:47 -04008182
8183 smp->flags = 0;
David Sc1ad52e2014-04-08 18:48:47 -04008184 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8185 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008186 ctx = conn->xprt_ctx;
David Sc1ad52e2014-04-08 18:48:47 -04008187
8188 if (!(conn->flags & CO_FL_CONNECTED)) {
8189 smp->flags |= SMP_F_MAY_CHANGE;
8190 return 0;
8191 }
8192
8193 finished_trash = get_trash_chunk();
Olivier Houchard66ab4982019-02-26 18:37:15 +01008194 if (!SSL_session_reused(ctx->ssl))
8195 finished_len = SSL_get_peer_finished(ctx->ssl,
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008196 finished_trash->area,
8197 finished_trash->size);
David Sc1ad52e2014-04-08 18:48:47 -04008198 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01008199 finished_len = SSL_get_finished(ctx->ssl,
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008200 finished_trash->area,
8201 finished_trash->size);
David Sc1ad52e2014-04-08 18:48:47 -04008202
8203 if (!finished_len)
8204 return 0;
8205
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008206 finished_trash->data = finished_len;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02008207 smp->data.u.str = *finished_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008208 smp->data.type = SMP_T_BIN;
David Sc1ad52e2014-04-08 18:48:47 -04008209
8210 return 1;
David Sc1ad52e2014-04-08 18:48:47 -04008211}
Patrick Hemmer41966772018-04-28 19:15:48 -04008212#endif
David Sc1ad52e2014-04-08 18:48:47 -04008213
Emeric Brun2525b6b2012-10-18 15:59:43 +02008214/* integer, returns the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02008215static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008216smp_fetch_ssl_c_ca_err(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunf282a812012-09-21 15:27:54 +02008217{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008218 struct connection *conn;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008219 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008220
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02008221 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008222 if (!conn || conn->xprt != &ssl_sock)
8223 return 0;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008224 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008225
8226 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02008227 smp->flags = SMP_F_MAY_CHANGE;
8228 return 0;
8229 }
8230
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008231 smp->data.type = SMP_T_SINT;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008232 smp->data.u.sint = (unsigned long long int)SSL_SOCK_ST_TO_CA_ERROR(ctx->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02008233 smp->flags = 0;
8234
8235 return 1;
8236}
8237
Emeric Brun2525b6b2012-10-18 15:59:43 +02008238/* integer, returns the depth of the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02008239static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008240smp_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 +02008241{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008242 struct connection *conn;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008243 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008244
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02008245 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008246 if (!conn || conn->xprt != &ssl_sock)
Emeric Brunf282a812012-09-21 15:27:54 +02008247 return 0;
8248
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008249 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02008250 smp->flags = SMP_F_MAY_CHANGE;
8251 return 0;
8252 }
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008253 ctx = conn->xprt_ctx;
Emeric Brunf282a812012-09-21 15:27:54 +02008254
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008255 smp->data.type = SMP_T_SINT;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008256 smp->data.u.sint = (long long int)SSL_SOCK_ST_TO_CAEDEPTH(ctx->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02008257 smp->flags = 0;
8258
8259 return 1;
8260}
8261
Emeric Brun2525b6b2012-10-18 15:59:43 +02008262/* integer, returns the first verify error on client certificate */
Emeric Brunf282a812012-09-21 15:27:54 +02008263static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008264smp_fetch_ssl_c_err(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunf282a812012-09-21 15:27:54 +02008265{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008266 struct connection *conn;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008267 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008268
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02008269 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008270 if (!conn || conn->xprt != &ssl_sock)
8271 return 0;
8272
8273 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02008274 smp->flags = SMP_F_MAY_CHANGE;
8275 return 0;
8276 }
8277
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008278 ctx = conn->xprt_ctx;
8279
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008280 smp->data.type = SMP_T_SINT;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008281 smp->data.u.sint = (long long int)SSL_SOCK_ST_TO_CRTERROR(ctx->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02008282 smp->flags = 0;
8283
8284 return 1;
8285}
8286
Emeric Brun2525b6b2012-10-18 15:59:43 +02008287/* integer, returns the verify result on client cert */
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02008288static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008289smp_fetch_ssl_c_verify(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02008290{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008291 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008292 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008293
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02008294 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008295 if (!conn || conn->xprt != &ssl_sock)
8296 return 0;
8297
8298 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02008299 smp->flags = SMP_F_MAY_CHANGE;
8300 return 0;
8301 }
8302
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008303 if (!conn->xprt_ctx)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02008304 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008305 ctx = conn->xprt_ctx;
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02008306
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008307 smp->data.type = SMP_T_SINT;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008308 smp->data.u.sint = (long long int)SSL_get_verify_result(ctx->ssl);
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02008309 smp->flags = 0;
8310
8311 return 1;
8312}
8313
Emeric Brunfb510ea2012-10-05 12:00:26 +02008314/* parse the "ca-file" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008315static 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 +02008316{
8317 if (!*args[cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01008318 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
Emeric Brund94b3fe2012-09-20 18:23:56 +02008319 return ERR_ALERT | ERR_FATAL;
8320 }
8321
Willy Tarreauef934602016-12-22 23:12:01 +01008322 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
8323 memprintf(&conf->ca_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02008324 else
8325 memprintf(&conf->ca_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02008326
Emeric Brund94b3fe2012-09-20 18:23:56 +02008327 return 0;
8328}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008329static int bind_parse_ca_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8330{
8331 return ssl_bind_parse_ca_file(args, cur_arg, px, &conf->ssl_conf, err);
8332}
Emeric Brund94b3fe2012-09-20 18:23:56 +02008333
Christopher Faulet31af49d2015-06-09 17:29:50 +02008334/* parse the "ca-sign-file" bind keyword */
8335static int bind_parse_ca_sign_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8336{
8337 if (!*args[cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01008338 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
Christopher Faulet31af49d2015-06-09 17:29:50 +02008339 return ERR_ALERT | ERR_FATAL;
8340 }
8341
Willy Tarreauef934602016-12-22 23:12:01 +01008342 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
8343 memprintf(&conf->ca_sign_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Christopher Faulet31af49d2015-06-09 17:29:50 +02008344 else
8345 memprintf(&conf->ca_sign_file, "%s", args[cur_arg + 1]);
8346
8347 return 0;
8348}
8349
Bertrand Jacquinff13c062016-11-13 16:37:11 +00008350/* parse the "ca-sign-pass" bind keyword */
Christopher Faulet31af49d2015-06-09 17:29:50 +02008351static int bind_parse_ca_sign_pass(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8352{
8353 if (!*args[cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01008354 memprintf(err, "'%s' : missing CAkey password", args[cur_arg]);
Christopher Faulet31af49d2015-06-09 17:29:50 +02008355 return ERR_ALERT | ERR_FATAL;
8356 }
8357 memprintf(&conf->ca_sign_pass, "%s", args[cur_arg + 1]);
8358 return 0;
8359}
8360
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008361/* parse the "ciphers" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008362static 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 +02008363{
8364 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02008365 memprintf(err, "'%s' : missing cipher suite", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008366 return ERR_ALERT | ERR_FATAL;
8367 }
8368
Emeric Brun76d88952012-10-05 15:47:31 +02008369 free(conf->ciphers);
Willy Tarreau4348fad2012-09-20 16:48:07 +02008370 conf->ciphers = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008371 return 0;
8372}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008373static int bind_parse_ciphers(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8374{
8375 return ssl_bind_parse_ciphers(args, cur_arg, px, &conf->ssl_conf, err);
8376}
Dirkjan Bussink415150f2018-09-14 11:14:21 +02008377
Emmanuel Hocdet839af572019-05-14 16:27:35 +02008378#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02008379/* parse the "ciphersuites" bind keyword */
8380static int ssl_bind_parse_ciphersuites(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
8381{
8382 if (!*args[cur_arg + 1]) {
8383 memprintf(err, "'%s' : missing cipher suite", args[cur_arg]);
8384 return ERR_ALERT | ERR_FATAL;
8385 }
8386
8387 free(conf->ciphersuites);
8388 conf->ciphersuites = strdup(args[cur_arg + 1]);
8389 return 0;
8390}
8391static int bind_parse_ciphersuites(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8392{
8393 return ssl_bind_parse_ciphersuites(args, cur_arg, px, &conf->ssl_conf, err);
8394}
8395#endif
8396
Willy Tarreaubbc91962019-10-16 16:42:19 +02008397/* parse the "crt" bind keyword. Returns a set of ERR_* flags possibly with an error in <err>. */
Willy Tarreau4348fad2012-09-20 16:48:07 +02008398static 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 +02008399{
Willy Tarreau38011032013-08-13 16:59:39 +02008400 char path[MAXPATHLEN];
Willy Tarreaub75d6922014-04-14 18:05:41 +02008401
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008402 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02008403 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008404 return ERR_ALERT | ERR_FATAL;
8405 }
8406
Willy Tarreauef934602016-12-22 23:12:01 +01008407 if ((*args[cur_arg + 1] != '/' ) && global_ssl.crt_base) {
8408 if ((strlen(global_ssl.crt_base) + 1 + strlen(args[cur_arg + 1]) + 1) > MAXPATHLEN) {
Emeric Brunc8e8d122012-10-02 18:42:10 +02008409 memprintf(err, "'%s' : path too long", args[cur_arg]);
8410 return ERR_ALERT | ERR_FATAL;
8411 }
Willy Tarreauef934602016-12-22 23:12:01 +01008412 snprintf(path, sizeof(path), "%s/%s", global_ssl.crt_base, args[cur_arg + 1]);
Willy Tarreaubbc91962019-10-16 16:42:19 +02008413 return ssl_sock_load_cert(path, conf, err);
Emeric Brunc8e8d122012-10-02 18:42:10 +02008414 }
8415
Willy Tarreaubbc91962019-10-16 16:42:19 +02008416 return ssl_sock_load_cert(args[cur_arg + 1], conf, err);
Emeric Brund94b3fe2012-09-20 18:23:56 +02008417}
8418
Willy Tarreaubbc91962019-10-16 16:42:19 +02008419/* 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 +01008420static int bind_parse_crt_list(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8421{
Willy Tarreaubbc91962019-10-16 16:42:19 +02008422 int err_code;
8423
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01008424 if (!*args[cur_arg + 1]) {
8425 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
8426 return ERR_ALERT | ERR_FATAL;
8427 }
8428
Willy Tarreaubbc91962019-10-16 16:42:19 +02008429 err_code = ssl_sock_load_cert_list_file(args[cur_arg + 1], conf, px, err);
8430 if (err_code)
Willy Tarreauad1731d2013-04-02 17:35:58 +02008431 memprintf(err, "'%s' : %s", args[cur_arg], *err);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01008432
Willy Tarreaubbc91962019-10-16 16:42:19 +02008433 return err_code;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01008434}
8435
Emeric Brunfb510ea2012-10-05 12:00:26 +02008436/* parse the "crl-file" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008437static 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 +02008438{
Emeric Brun051cdab2012-10-02 19:25:50 +02008439#ifndef X509_V_FLAG_CRL_CHECK
Tim Duesterhus93128532019-11-23 23:45:10 +01008440 memprintf(err, "'%s' : library does not support CRL verify", args[cur_arg]);
Emeric Brun051cdab2012-10-02 19:25:50 +02008441 return ERR_ALERT | ERR_FATAL;
8442#else
Emeric Brund94b3fe2012-09-20 18:23:56 +02008443 if (!*args[cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01008444 memprintf(err, "'%s' : missing CRLfile path", args[cur_arg]);
Emeric Brund94b3fe2012-09-20 18:23:56 +02008445 return ERR_ALERT | ERR_FATAL;
8446 }
Emeric Brun2b58d042012-09-20 17:10:03 +02008447
Willy Tarreauef934602016-12-22 23:12:01 +01008448 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
8449 memprintf(&conf->crl_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02008450 else
8451 memprintf(&conf->crl_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02008452
Emeric Brun2b58d042012-09-20 17:10:03 +02008453 return 0;
Emeric Brun051cdab2012-10-02 19:25:50 +02008454#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02008455}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008456static int bind_parse_crl_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8457{
8458 return ssl_bind_parse_crl_file(args, cur_arg, px, &conf->ssl_conf, err);
8459}
Emeric Brun2b58d042012-09-20 17:10:03 +02008460
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01008461/* parse the "curves" bind keyword keyword */
8462static int ssl_bind_parse_curves(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
8463{
Lukas Tribusd14b49c2019-11-24 18:20:40 +01008464#if ((HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL) || defined(LIBRESSL_VERSION_NUMBER))
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01008465 if (!*args[cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01008466 memprintf(err, "'%s' : missing curve suite", args[cur_arg]);
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01008467 return ERR_ALERT | ERR_FATAL;
8468 }
8469 conf->curves = strdup(args[cur_arg + 1]);
8470 return 0;
8471#else
Tim Duesterhus93128532019-11-23 23:45:10 +01008472 memprintf(err, "'%s' : library does not support curve suite", args[cur_arg]);
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01008473 return ERR_ALERT | ERR_FATAL;
8474#endif
8475}
8476static int bind_parse_curves(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8477{
8478 return ssl_bind_parse_curves(args, cur_arg, px, &conf->ssl_conf, err);
8479}
8480
Bertrand Jacquinff13c062016-11-13 16:37:11 +00008481/* parse the "ecdhe" bind keyword keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008482static 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 +02008483{
Willy Tarreau9a1ab082019-05-09 13:26:41 +02008484#if HA_OPENSSL_VERSION_NUMBER < 0x0090800fL
Tim Duesterhus93128532019-11-23 23:45:10 +01008485 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (too old)", args[cur_arg]);
Emeric Brun2b58d042012-09-20 17:10:03 +02008486 return ERR_ALERT | ERR_FATAL;
8487#elif defined(OPENSSL_NO_ECDH)
Tim Duesterhus93128532019-11-23 23:45:10 +01008488 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (disabled via OPENSSL_NO_ECDH)", args[cur_arg]);
Emeric Brun2b58d042012-09-20 17:10:03 +02008489 return ERR_ALERT | ERR_FATAL;
8490#else
8491 if (!*args[cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01008492 memprintf(err, "'%s' : missing named curve", args[cur_arg]);
Emeric Brun2b58d042012-09-20 17:10:03 +02008493 return ERR_ALERT | ERR_FATAL;
8494 }
8495
8496 conf->ecdhe = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008497
8498 return 0;
Emeric Brun2b58d042012-09-20 17:10:03 +02008499#endif
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008500}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008501static int bind_parse_ecdhe(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8502{
8503 return ssl_bind_parse_ecdhe(args, cur_arg, px, &conf->ssl_conf, err);
8504}
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008505
Bertrand Jacquinff13c062016-11-13 16:37:11 +00008506/* parse the "crt-ignore-err" and "ca-ignore-err" bind keywords */
Emeric Brun81c00f02012-09-21 14:31:21 +02008507static int bind_parse_ignore_err(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8508{
8509 int code;
8510 char *p = args[cur_arg + 1];
8511 unsigned long long *ignerr = &conf->crt_ignerr;
8512
8513 if (!*p) {
Tim Duesterhus93128532019-11-23 23:45:10 +01008514 memprintf(err, "'%s' : missing error IDs list", args[cur_arg]);
Emeric Brun81c00f02012-09-21 14:31:21 +02008515 return ERR_ALERT | ERR_FATAL;
8516 }
8517
8518 if (strcmp(args[cur_arg], "ca-ignore-err") == 0)
8519 ignerr = &conf->ca_ignerr;
8520
8521 if (strcmp(p, "all") == 0) {
8522 *ignerr = ~0ULL;
8523 return 0;
8524 }
8525
8526 while (p) {
8527 code = atoi(p);
8528 if ((code <= 0) || (code > 63)) {
Tim Duesterhus93128532019-11-23 23:45:10 +01008529 memprintf(err, "'%s' : ID '%d' out of range (1..63) in error IDs list '%s'",
8530 args[cur_arg], code, args[cur_arg + 1]);
Emeric Brun81c00f02012-09-21 14:31:21 +02008531 return ERR_ALERT | ERR_FATAL;
8532 }
8533 *ignerr |= 1ULL << code;
8534 p = strchr(p, ',');
8535 if (p)
8536 p++;
8537 }
8538
Emeric Brun2cb7ae52012-10-05 14:14:21 +02008539 return 0;
8540}
8541
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008542/* parse tls_method_options "no-xxx" and "force-xxx" */
8543static int parse_tls_method_options(char *arg, struct tls_version_filter *methods, char **err)
Emeric Brun2cb7ae52012-10-05 14:14:21 +02008544{
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008545 uint16_t v;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008546 char *p;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008547 p = strchr(arg, '-');
8548 if (!p)
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008549 goto fail;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008550 p++;
8551 if (!strcmp(p, "sslv3"))
8552 v = CONF_SSLV3;
8553 else if (!strcmp(p, "tlsv10"))
8554 v = CONF_TLSV10;
8555 else if (!strcmp(p, "tlsv11"))
8556 v = CONF_TLSV11;
8557 else if (!strcmp(p, "tlsv12"))
8558 v = CONF_TLSV12;
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +02008559 else if (!strcmp(p, "tlsv13"))
8560 v = CONF_TLSV13;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008561 else
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008562 goto fail;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008563 if (!strncmp(arg, "no-", 3))
8564 methods->flags |= methodVersions[v].flag;
8565 else if (!strncmp(arg, "force-", 6))
8566 methods->min = methods->max = v;
8567 else
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008568 goto fail;
Emeric Brun2d0c4822012-10-02 13:45:20 +02008569 return 0;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008570 fail:
Tim Duesterhus93128532019-11-23 23:45:10 +01008571 memprintf(err, "'%s' : option not implemented", arg);
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008572 return ERR_ALERT | ERR_FATAL;
Emeric Brun2d0c4822012-10-02 13:45:20 +02008573}
8574
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008575static 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 +02008576{
Emmanuel Hocdet43664762017-08-09 18:26:20 +02008577 return parse_tls_method_options(args[cur_arg], &conf->ssl_conf.ssl_methods, err);
Emeric Brun2cb7ae52012-10-05 14:14:21 +02008578}
8579
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008580static 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 +02008581{
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008582 return parse_tls_method_options(args[*cur_arg], &newsrv->ssl_ctx.methods, err);
8583}
8584
8585/* parse tls_method min/max: "ssl-min-ver" and "ssl-max-ver" */
8586static int parse_tls_method_minmax(char **args, int cur_arg, struct tls_version_filter *methods, char **err)
8587{
8588 uint16_t i, v = 0;
8589 char *argv = args[cur_arg + 1];
8590 if (!*argv) {
Tim Duesterhus93128532019-11-23 23:45:10 +01008591 memprintf(err, "'%s' : missing the ssl/tls version", args[cur_arg]);
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008592 return ERR_ALERT | ERR_FATAL;
8593 }
8594 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
8595 if (!strcmp(argv, methodVersions[i].name))
8596 v = i;
8597 if (!v) {
Tim Duesterhus93128532019-11-23 23:45:10 +01008598 memprintf(err, "'%s' : unknown ssl/tls version", args[cur_arg + 1]);
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008599 return ERR_ALERT | ERR_FATAL;
8600 }
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008601 if (!strcmp("ssl-min-ver", args[cur_arg]))
8602 methods->min = v;
8603 else if (!strcmp("ssl-max-ver", args[cur_arg]))
8604 methods->max = v;
8605 else {
Tim Duesterhus93128532019-11-23 23:45:10 +01008606 memprintf(err, "'%s' : option not implemented", args[cur_arg]);
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008607 return ERR_ALERT | ERR_FATAL;
8608 }
Emeric Brun2cb7ae52012-10-05 14:14:21 +02008609 return 0;
Emeric Brun2cb7ae52012-10-05 14:14:21 +02008610}
Emeric Brun2cb7ae52012-10-05 14:14:21 +02008611
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02008612static int ssl_bind_parse_tls_method_minmax(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
8613{
Willy Tarreau9a1ab082019-05-09 13:26:41 +02008614#if (HA_OPENSSL_VERSION_NUMBER < 0x10101000L) && !defined(OPENSSL_IS_BORINGSSL)
Christopher Faulet767a84b2017-11-24 16:50:31 +01008615 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 +02008616#endif
8617 return parse_tls_method_minmax(args, cur_arg, &conf->ssl_methods, err);
8618}
8619
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008620static int bind_parse_tls_method_minmax(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8621{
Emmanuel Hocdet43664762017-08-09 18:26:20 +02008622 return parse_tls_method_minmax(args, cur_arg, &conf->ssl_conf.ssl_methods, err);
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008623}
8624
8625static int srv_parse_tls_method_minmax(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8626{
8627 return parse_tls_method_minmax(args, *cur_arg, &newsrv->ssl_ctx.methods, err);
8628}
8629
Emeric Brun2d0c4822012-10-02 13:45:20 +02008630/* parse the "no-tls-tickets" bind keyword */
Emmanuel Hocdet4608ed92017-01-20 13:06:27 +01008631static 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 +02008632{
Emeric Brun89675492012-10-05 13:48:26 +02008633 conf->ssl_options |= BC_SSL_O_NO_TLS_TICKETS;
Emeric Brun81c00f02012-09-21 14:31:21 +02008634 return 0;
8635}
Emeric Brun2d0c4822012-10-02 13:45:20 +02008636
Olivier Houchardc2aae742017-09-22 18:26:28 +02008637/* parse the "allow-0rtt" bind keyword */
8638static int ssl_bind_parse_allow_0rtt(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
8639{
8640 conf->early_data = 1;
8641 return 0;
8642}
8643
8644static int bind_parse_allow_0rtt(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8645{
Olivier Houchard9679ac92017-10-27 14:58:08 +02008646 conf->ssl_conf.early_data = 1;
Olivier Houchardc2aae742017-09-22 18:26:28 +02008647 return 0;
8648}
8649
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02008650/* parse the "npn" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008651static 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 +02008652{
Bernard Spil13c53f82018-02-15 13:34:58 +01008653#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02008654 char *p1, *p2;
8655
8656 if (!*args[cur_arg + 1]) {
8657 memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[cur_arg]);
8658 return ERR_ALERT | ERR_FATAL;
8659 }
8660
8661 free(conf->npn_str);
8662
Willy Tarreau3724da12016-02-12 17:11:12 +01008663 /* the NPN string is built as a suite of (<len> <name>)*,
8664 * so we reuse each comma to store the next <len> and need
8665 * one more for the end of the string.
8666 */
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02008667 conf->npn_len = strlen(args[cur_arg + 1]) + 1;
Willy Tarreau3724da12016-02-12 17:11:12 +01008668 conf->npn_str = calloc(1, conf->npn_len + 1);
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02008669 memcpy(conf->npn_str + 1, args[cur_arg + 1], conf->npn_len);
8670
8671 /* replace commas with the name length */
8672 p1 = conf->npn_str;
8673 p2 = p1 + 1;
8674 while (1) {
8675 p2 = memchr(p1 + 1, ',', conf->npn_str + conf->npn_len - (p1 + 1));
8676 if (!p2)
8677 p2 = p1 + 1 + strlen(p1 + 1);
8678
8679 if (p2 - (p1 + 1) > 255) {
8680 *p2 = '\0';
8681 memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
8682 return ERR_ALERT | ERR_FATAL;
8683 }
8684
8685 *p1 = p2 - (p1 + 1);
8686 p1 = p2;
8687
8688 if (!*p2)
8689 break;
8690
8691 *(p2++) = '\0';
8692 }
8693 return 0;
8694#else
Tim Duesterhus93128532019-11-23 23:45:10 +01008695 memprintf(err, "'%s' : library does not support TLS NPN extension", args[cur_arg]);
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02008696 return ERR_ALERT | ERR_FATAL;
8697#endif
8698}
8699
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008700static int bind_parse_npn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8701{
8702 return ssl_bind_parse_npn(args, cur_arg, px, &conf->ssl_conf, err);
8703}
8704
Willy Tarreauab861d32013-04-02 02:30:41 +02008705/* parse the "alpn" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008706static 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 +02008707{
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01008708#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02008709 char *p1, *p2;
8710
8711 if (!*args[cur_arg + 1]) {
8712 memprintf(err, "'%s' : missing the comma-delimited ALPN protocol suite", args[cur_arg]);
8713 return ERR_ALERT | ERR_FATAL;
8714 }
8715
8716 free(conf->alpn_str);
8717
Marcoen Hirschbergbef60912016-02-12 17:05:24 +01008718 /* the ALPN string is built as a suite of (<len> <name>)*,
8719 * so we reuse each comma to store the next <len> and need
8720 * one more for the end of the string.
8721 */
Willy Tarreauab861d32013-04-02 02:30:41 +02008722 conf->alpn_len = strlen(args[cur_arg + 1]) + 1;
Marcoen Hirschbergbef60912016-02-12 17:05:24 +01008723 conf->alpn_str = calloc(1, conf->alpn_len + 1);
Willy Tarreauab861d32013-04-02 02:30:41 +02008724 memcpy(conf->alpn_str + 1, args[cur_arg + 1], conf->alpn_len);
8725
8726 /* replace commas with the name length */
8727 p1 = conf->alpn_str;
8728 p2 = p1 + 1;
8729 while (1) {
8730 p2 = memchr(p1 + 1, ',', conf->alpn_str + conf->alpn_len - (p1 + 1));
8731 if (!p2)
8732 p2 = p1 + 1 + strlen(p1 + 1);
8733
8734 if (p2 - (p1 + 1) > 255) {
8735 *p2 = '\0';
8736 memprintf(err, "'%s' : ALPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
8737 return ERR_ALERT | ERR_FATAL;
8738 }
8739
8740 *p1 = p2 - (p1 + 1);
8741 p1 = p2;
8742
8743 if (!*p2)
8744 break;
8745
8746 *(p2++) = '\0';
8747 }
8748 return 0;
8749#else
Tim Duesterhus93128532019-11-23 23:45:10 +01008750 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[cur_arg]);
Willy Tarreauab861d32013-04-02 02:30:41 +02008751 return ERR_ALERT | ERR_FATAL;
8752#endif
8753}
8754
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008755static int bind_parse_alpn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8756{
8757 return ssl_bind_parse_alpn(args, cur_arg, px, &conf->ssl_conf, err);
8758}
8759
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008760/* parse the "ssl" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02008761static 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 +02008762{
Willy Tarreau71a8c7c2016-12-21 22:04:54 +01008763 conf->xprt = &ssl_sock;
Willy Tarreau4348fad2012-09-20 16:48:07 +02008764 conf->is_ssl = 1;
Emeric Brun76d88952012-10-05 15:47:31 +02008765
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008766 if (global_ssl.listen_default_ciphers && !conf->ssl_conf.ciphers)
8767 conf->ssl_conf.ciphers = strdup(global_ssl.listen_default_ciphers);
Emmanuel Hocdet839af572019-05-14 16:27:35 +02008768#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02008769 if (global_ssl.listen_default_ciphersuites && !conf->ssl_conf.ciphersuites)
8770 conf->ssl_conf.ciphersuites = strdup(global_ssl.listen_default_ciphersuites);
8771#endif
Emmanuel Hocdet4608ed92017-01-20 13:06:27 +01008772 conf->ssl_options |= global_ssl.listen_default_ssloptions;
Emmanuel Hocdet43664762017-08-09 18:26:20 +02008773 conf->ssl_conf.ssl_methods.flags |= global_ssl.listen_default_sslmethods.flags;
8774 if (!conf->ssl_conf.ssl_methods.min)
8775 conf->ssl_conf.ssl_methods.min = global_ssl.listen_default_sslmethods.min;
8776 if (!conf->ssl_conf.ssl_methods.max)
8777 conf->ssl_conf.ssl_methods.max = global_ssl.listen_default_sslmethods.max;
Emeric Brun76d88952012-10-05 15:47:31 +02008778
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008779 return 0;
8780}
8781
Lukas Tribus53ae85c2017-05-04 15:45:40 +00008782/* parse the "prefer-client-ciphers" bind keyword */
8783static int bind_parse_pcc(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8784{
8785 conf->ssl_options |= BC_SSL_O_PREF_CLIE_CIPH;
8786 return 0;
8787}
8788
Christopher Faulet31af49d2015-06-09 17:29:50 +02008789/* parse the "generate-certificates" bind keyword */
8790static int bind_parse_generate_certs(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8791{
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01008792#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Christopher Faulet31af49d2015-06-09 17:29:50 +02008793 conf->generate_certs = 1;
8794#else
8795 memprintf(err, "%sthis version of openssl cannot generate SSL certificates.\n",
8796 err && *err ? *err : "");
8797#endif
8798 return 0;
8799}
8800
Emmanuel Hocdet65623372013-01-24 17:17:15 +01008801/* parse the "strict-sni" bind keyword */
8802static int bind_parse_strict_sni(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8803{
8804 conf->strict_sni = 1;
8805 return 0;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008806}
8807
8808/* parse the "tls-ticket-keys" bind keyword */
8809static int bind_parse_tls_ticket_keys(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8810{
8811#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
Christopher Faulete566f3d2019-10-21 09:55:49 +02008812 FILE *f = NULL;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008813 int i = 0;
8814 char thisline[LINESIZE];
Christopher Faulete566f3d2019-10-21 09:55:49 +02008815 struct tls_keys_ref *keys_ref = NULL;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008816
8817 if (!*args[cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01008818 memprintf(err, "'%s' : missing TLS ticket keys file path", args[cur_arg]);
Christopher Faulete566f3d2019-10-21 09:55:49 +02008819 goto fail;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008820 }
8821
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02008822 keys_ref = tlskeys_ref_lookup(args[cur_arg + 1]);
Willy Tarreau17b4aa12018-07-17 10:05:32 +02008823 if (keys_ref) {
8824 keys_ref->refcount++;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02008825 conf->keys_ref = keys_ref;
8826 return 0;
8827 }
8828
Christopher Faulete566f3d2019-10-21 09:55:49 +02008829 keys_ref = calloc(1, sizeof(*keys_ref));
Emeric Brun09852f72019-01-10 10:51:13 +01008830 if (!keys_ref) {
Tim Duesterhus93128532019-11-23 23:45:10 +01008831 memprintf(err, "'%s' : allocation error", args[cur_arg+1]);
Christopher Faulete566f3d2019-10-21 09:55:49 +02008832 goto fail;
Emeric Brun09852f72019-01-10 10:51:13 +01008833 }
8834
Emeric Brun9e754772019-01-10 17:51:55 +01008835 keys_ref->tlskeys = malloc(TLS_TICKETS_NO * sizeof(union tls_sess_key));
Emeric Brun09852f72019-01-10 10:51:13 +01008836 if (!keys_ref->tlskeys) {
Tim Duesterhus93128532019-11-23 23:45:10 +01008837 memprintf(err, "'%s' : allocation error", args[cur_arg+1]);
Christopher Faulete566f3d2019-10-21 09:55:49 +02008838 goto fail;
Emeric Brun09852f72019-01-10 10:51:13 +01008839 }
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008840
8841 if ((f = fopen(args[cur_arg + 1], "r")) == NULL) {
Tim Duesterhus93128532019-11-23 23:45:10 +01008842 memprintf(err, "'%s' : unable to load ssl tickets keys file", args[cur_arg+1]);
Christopher Faulete566f3d2019-10-21 09:55:49 +02008843 goto fail;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008844 }
8845
Nenad Merdanovic146defa2015-05-09 08:46:00 +02008846 keys_ref->filename = strdup(args[cur_arg + 1]);
Emeric Brun09852f72019-01-10 10:51:13 +01008847 if (!keys_ref->filename) {
Tim Duesterhus93128532019-11-23 23:45:10 +01008848 memprintf(err, "'%s' : allocation error", args[cur_arg+1]);
Christopher Faulete566f3d2019-10-21 09:55:49 +02008849 goto fail;
Emeric Brun09852f72019-01-10 10:51:13 +01008850 }
Nenad Merdanovic146defa2015-05-09 08:46:00 +02008851
Emeric Brun9e754772019-01-10 17:51:55 +01008852 keys_ref->key_size_bits = 0;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008853 while (fgets(thisline, sizeof(thisline), f) != NULL) {
8854 int len = strlen(thisline);
Emeric Brun9e754772019-01-10 17:51:55 +01008855 int dec_size;
8856
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008857 /* Strip newline characters from the end */
8858 if(thisline[len - 1] == '\n')
8859 thisline[--len] = 0;
8860
8861 if(thisline[len - 1] == '\r')
8862 thisline[--len] = 0;
8863
Emeric Brun9e754772019-01-10 17:51:55 +01008864 dec_size = base64dec(thisline, len, (char *) (keys_ref->tlskeys + i % TLS_TICKETS_NO), sizeof(union tls_sess_key));
8865 if (dec_size < 0) {
Tim Duesterhus93128532019-11-23 23:45:10 +01008866 memprintf(err, "'%s' : unable to decode base64 key on line %d", args[cur_arg+1], i + 1);
Christopher Faulete566f3d2019-10-21 09:55:49 +02008867 goto fail;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008868 }
Emeric Brun9e754772019-01-10 17:51:55 +01008869 else if (!keys_ref->key_size_bits && (dec_size == sizeof(struct tls_sess_key_128))) {
8870 keys_ref->key_size_bits = 128;
8871 }
8872 else if (!keys_ref->key_size_bits && (dec_size == sizeof(struct tls_sess_key_256))) {
8873 keys_ref->key_size_bits = 256;
8874 }
8875 else if (((dec_size != sizeof(struct tls_sess_key_128)) && (dec_size != sizeof(struct tls_sess_key_256)))
8876 || ((dec_size == sizeof(struct tls_sess_key_128) && (keys_ref->key_size_bits != 128)))
8877 || ((dec_size == sizeof(struct tls_sess_key_256) && (keys_ref->key_size_bits != 256)))) {
Tim Duesterhus93128532019-11-23 23:45:10 +01008878 memprintf(err, "'%s' : wrong sized key on line %d", args[cur_arg+1], i + 1);
Christopher Faulete566f3d2019-10-21 09:55:49 +02008879 goto fail;
Emeric Brun9e754772019-01-10 17:51:55 +01008880 }
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008881 i++;
8882 }
8883
8884 if (i < TLS_TICKETS_NO) {
Tim Duesterhus93128532019-11-23 23:45:10 +01008885 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 +02008886 goto fail;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008887 }
8888
8889 fclose(f);
8890
8891 /* Use penultimate key for encryption, handle when TLS_TICKETS_NO = 1 */
Nenad Merdanovic17891152016-03-25 22:16:57 +01008892 i -= 2;
8893 keys_ref->tls_ticket_enc_index = i < 0 ? 0 : i % TLS_TICKETS_NO;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02008894 keys_ref->unique_id = -1;
Willy Tarreau17b4aa12018-07-17 10:05:32 +02008895 keys_ref->refcount = 1;
Christopher Faulet16f45c82018-02-16 11:23:49 +01008896 HA_RWLOCK_INIT(&keys_ref->lock);
Nenad Merdanovic146defa2015-05-09 08:46:00 +02008897 conf->keys_ref = keys_ref;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008898
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02008899 LIST_ADD(&tlskeys_reference, &keys_ref->list);
8900
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008901 return 0;
Christopher Faulete566f3d2019-10-21 09:55:49 +02008902
8903 fail:
8904 if (f)
8905 fclose(f);
8906 if (keys_ref) {
8907 free(keys_ref->filename);
8908 free(keys_ref->tlskeys);
8909 free(keys_ref);
8910 }
8911 return ERR_ALERT | ERR_FATAL;
8912
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008913#else
Tim Duesterhus93128532019-11-23 23:45:10 +01008914 memprintf(err, "'%s' : TLS ticket callback extension not supported", args[cur_arg]);
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008915 return ERR_ALERT | ERR_FATAL;
8916#endif /* SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB */
Emmanuel Hocdet65623372013-01-24 17:17:15 +01008917}
8918
Emeric Brund94b3fe2012-09-20 18:23:56 +02008919/* parse the "verify" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008920static 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 +02008921{
8922 if (!*args[cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01008923 memprintf(err, "'%s' : missing verify method", args[cur_arg]);
Emeric Brund94b3fe2012-09-20 18:23:56 +02008924 return ERR_ALERT | ERR_FATAL;
8925 }
8926
8927 if (strcmp(args[cur_arg + 1], "none") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01008928 conf->verify = SSL_SOCK_VERIFY_NONE;
Emeric Brund94b3fe2012-09-20 18:23:56 +02008929 else if (strcmp(args[cur_arg + 1], "optional") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01008930 conf->verify = SSL_SOCK_VERIFY_OPTIONAL;
Emeric Brund94b3fe2012-09-20 18:23:56 +02008931 else if (strcmp(args[cur_arg + 1], "required") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01008932 conf->verify = SSL_SOCK_VERIFY_REQUIRED;
Emeric Brund94b3fe2012-09-20 18:23:56 +02008933 else {
Tim Duesterhus93128532019-11-23 23:45:10 +01008934 memprintf(err, "'%s' : unknown verify method '%s', only 'none', 'optional', and 'required' are supported\n",
8935 args[cur_arg], args[cur_arg + 1]);
Emeric Brund94b3fe2012-09-20 18:23:56 +02008936 return ERR_ALERT | ERR_FATAL;
8937 }
8938
8939 return 0;
8940}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008941static int bind_parse_verify(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8942{
8943 return ssl_bind_parse_verify(args, cur_arg, px, &conf->ssl_conf, err);
8944}
Emeric Brund94b3fe2012-09-20 18:23:56 +02008945
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02008946/* parse the "no-ca-names" bind keyword */
8947static int ssl_bind_parse_no_ca_names(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
8948{
8949 conf->no_ca_names = 1;
8950 return 0;
8951}
8952static int bind_parse_no_ca_names(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8953{
8954 return ssl_bind_parse_no_ca_names(args, cur_arg, px, &conf->ssl_conf, err);
8955}
8956
Willy Tarreau92faadf2012-10-10 23:04:25 +02008957/************** "server" keywords ****************/
8958
Olivier Houchardc7566002018-11-20 23:33:50 +01008959/* parse the "npn" bind keyword */
8960static int srv_parse_npn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8961{
8962#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
8963 char *p1, *p2;
8964
8965 if (!*args[*cur_arg + 1]) {
8966 memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[*cur_arg]);
8967 return ERR_ALERT | ERR_FATAL;
8968 }
8969
8970 free(newsrv->ssl_ctx.npn_str);
8971
8972 /* the NPN string is built as a suite of (<len> <name>)*,
8973 * so we reuse each comma to store the next <len> and need
8974 * one more for the end of the string.
8975 */
8976 newsrv->ssl_ctx.npn_len = strlen(args[*cur_arg + 1]) + 1;
8977 newsrv->ssl_ctx.npn_str = calloc(1, newsrv->ssl_ctx.npn_len + 1);
8978 memcpy(newsrv->ssl_ctx.npn_str + 1, args[*cur_arg + 1],
8979 newsrv->ssl_ctx.npn_len);
8980
8981 /* replace commas with the name length */
8982 p1 = newsrv->ssl_ctx.npn_str;
8983 p2 = p1 + 1;
8984 while (1) {
8985 p2 = memchr(p1 + 1, ',', newsrv->ssl_ctx.npn_str +
8986 newsrv->ssl_ctx.npn_len - (p1 + 1));
8987 if (!p2)
8988 p2 = p1 + 1 + strlen(p1 + 1);
8989
8990 if (p2 - (p1 + 1) > 255) {
8991 *p2 = '\0';
8992 memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[*cur_arg], p1 + 1);
8993 return ERR_ALERT | ERR_FATAL;
8994 }
8995
8996 *p1 = p2 - (p1 + 1);
8997 p1 = p2;
8998
8999 if (!*p2)
9000 break;
9001
9002 *(p2++) = '\0';
9003 }
9004 return 0;
9005#else
Tim Duesterhus93128532019-11-23 23:45:10 +01009006 memprintf(err, "'%s' : library does not support TLS NPN extension", args[*cur_arg]);
Olivier Houchardc7566002018-11-20 23:33:50 +01009007 return ERR_ALERT | ERR_FATAL;
9008#endif
9009}
9010
Olivier Houchard92150142018-12-21 19:47:01 +01009011/* parse the "alpn" or the "check-alpn" server keyword */
Olivier Houchardc7566002018-11-20 23:33:50 +01009012static int srv_parse_alpn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9013{
9014#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
9015 char *p1, *p2;
Olivier Houchard92150142018-12-21 19:47:01 +01009016 char **alpn_str;
9017 int *alpn_len;
Olivier Houchardc7566002018-11-20 23:33:50 +01009018
Olivier Houchard92150142018-12-21 19:47:01 +01009019 if (*args[*cur_arg] == 'c') {
9020 alpn_str = &newsrv->check.alpn_str;
9021 alpn_len = &newsrv->check.alpn_len;
9022 } else {
9023 alpn_str = &newsrv->ssl_ctx.alpn_str;
9024 alpn_len = &newsrv->ssl_ctx.alpn_len;
9025
9026 }
Olivier Houchardc7566002018-11-20 23:33:50 +01009027 if (!*args[*cur_arg + 1]) {
9028 memprintf(err, "'%s' : missing the comma-delimited ALPN protocol suite", args[*cur_arg]);
9029 return ERR_ALERT | ERR_FATAL;
9030 }
9031
Olivier Houchard92150142018-12-21 19:47:01 +01009032 free(*alpn_str);
Olivier Houchardc7566002018-11-20 23:33:50 +01009033
9034 /* the ALPN string is built as a suite of (<len> <name>)*,
9035 * so we reuse each comma to store the next <len> and need
9036 * one more for the end of the string.
9037 */
Olivier Houchard92150142018-12-21 19:47:01 +01009038 *alpn_len = strlen(args[*cur_arg + 1]) + 1;
9039 *alpn_str = calloc(1, *alpn_len + 1);
9040 memcpy(*alpn_str + 1, args[*cur_arg + 1], *alpn_len);
Olivier Houchardc7566002018-11-20 23:33:50 +01009041
9042 /* replace commas with the name length */
Olivier Houchard92150142018-12-21 19:47:01 +01009043 p1 = *alpn_str;
Olivier Houchardc7566002018-11-20 23:33:50 +01009044 p2 = p1 + 1;
9045 while (1) {
Olivier Houchard92150142018-12-21 19:47:01 +01009046 p2 = memchr(p1 + 1, ',', *alpn_str + *alpn_len - (p1 + 1));
Olivier Houchardc7566002018-11-20 23:33:50 +01009047 if (!p2)
9048 p2 = p1 + 1 + strlen(p1 + 1);
9049
9050 if (p2 - (p1 + 1) > 255) {
9051 *p2 = '\0';
9052 memprintf(err, "'%s' : ALPN protocol name too long : '%s'", args[*cur_arg], p1 + 1);
9053 return ERR_ALERT | ERR_FATAL;
9054 }
9055
9056 *p1 = p2 - (p1 + 1);
9057 p1 = p2;
9058
9059 if (!*p2)
9060 break;
9061
9062 *(p2++) = '\0';
9063 }
9064 return 0;
9065#else
Tim Duesterhus93128532019-11-23 23:45:10 +01009066 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[*cur_arg]);
Olivier Houchardc7566002018-11-20 23:33:50 +01009067 return ERR_ALERT | ERR_FATAL;
9068#endif
9069}
9070
Emeric Brunef42d922012-10-11 16:11:36 +02009071/* parse the "ca-file" server keyword */
9072static int srv_parse_ca_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9073{
9074 if (!*args[*cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009075 memprintf(err, "'%s' : missing CAfile path", args[*cur_arg]);
Emeric Brunef42d922012-10-11 16:11:36 +02009076 return ERR_ALERT | ERR_FATAL;
9077 }
9078
Willy Tarreauef934602016-12-22 23:12:01 +01009079 if ((*args[*cur_arg + 1] != '/') && global_ssl.ca_base)
9080 memprintf(&newsrv->ssl_ctx.ca_file, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02009081 else
9082 memprintf(&newsrv->ssl_ctx.ca_file, "%s", args[*cur_arg + 1]);
9083
9084 return 0;
9085}
9086
Olivier Houchard9130a962017-10-17 17:33:43 +02009087/* parse the "check-sni" server keyword */
9088static int srv_parse_check_sni(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9089{
9090 if (!*args[*cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009091 memprintf(err, "'%s' : missing SNI", args[*cur_arg]);
Olivier Houchard9130a962017-10-17 17:33:43 +02009092 return ERR_ALERT | ERR_FATAL;
9093 }
9094
9095 newsrv->check.sni = strdup(args[*cur_arg + 1]);
9096 if (!newsrv->check.sni) {
9097 memprintf(err, "'%s' : failed to allocate memory", args[*cur_arg]);
9098 return ERR_ALERT | ERR_FATAL;
9099 }
9100 return 0;
9101
9102}
9103
Willy Tarreau92faadf2012-10-10 23:04:25 +02009104/* parse the "check-ssl" server keyword */
9105static int srv_parse_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9106{
9107 newsrv->check.use_ssl = 1;
Willy Tarreauef934602016-12-22 23:12:01 +01009108 if (global_ssl.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
9109 newsrv->ssl_ctx.ciphers = strdup(global_ssl.connect_default_ciphers);
Emmanuel Hocdet839af572019-05-14 16:27:35 +02009110#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009111 if (global_ssl.connect_default_ciphersuites && !newsrv->ssl_ctx.ciphersuites)
9112 newsrv->ssl_ctx.ciphersuites = strdup(global_ssl.connect_default_ciphersuites);
9113#endif
Willy Tarreauef934602016-12-22 23:12:01 +01009114 newsrv->ssl_ctx.options |= global_ssl.connect_default_ssloptions;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02009115 newsrv->ssl_ctx.methods.flags |= global_ssl.connect_default_sslmethods.flags;
9116 if (!newsrv->ssl_ctx.methods.min)
9117 newsrv->ssl_ctx.methods.min = global_ssl.connect_default_sslmethods.min;
9118 if (!newsrv->ssl_ctx.methods.max)
9119 newsrv->ssl_ctx.methods.max = global_ssl.connect_default_sslmethods.max;
9120
Willy Tarreau92faadf2012-10-10 23:04:25 +02009121 return 0;
9122}
9123
9124/* parse the "ciphers" server keyword */
9125static int srv_parse_ciphers(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9126{
9127 if (!*args[*cur_arg + 1]) {
9128 memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
9129 return ERR_ALERT | ERR_FATAL;
9130 }
9131
9132 free(newsrv->ssl_ctx.ciphers);
9133 newsrv->ssl_ctx.ciphers = strdup(args[*cur_arg + 1]);
9134 return 0;
9135}
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009136
Emmanuel Hocdet839af572019-05-14 16:27:35 +02009137#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009138/* parse the "ciphersuites" server keyword */
9139static int srv_parse_ciphersuites(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9140{
9141 if (!*args[*cur_arg + 1]) {
9142 memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
9143 return ERR_ALERT | ERR_FATAL;
9144 }
9145
9146 free(newsrv->ssl_ctx.ciphersuites);
9147 newsrv->ssl_ctx.ciphersuites = strdup(args[*cur_arg + 1]);
9148 return 0;
9149}
9150#endif
Willy Tarreau92faadf2012-10-10 23:04:25 +02009151
Emeric Brunef42d922012-10-11 16:11:36 +02009152/* parse the "crl-file" server keyword */
9153static int srv_parse_crl_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9154{
9155#ifndef X509_V_FLAG_CRL_CHECK
Tim Duesterhus93128532019-11-23 23:45:10 +01009156 memprintf(err, "'%s' : library does not support CRL verify", args[*cur_arg]);
Emeric Brunef42d922012-10-11 16:11:36 +02009157 return ERR_ALERT | ERR_FATAL;
9158#else
9159 if (!*args[*cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009160 memprintf(err, "'%s' : missing CRLfile path", args[*cur_arg]);
Emeric Brunef42d922012-10-11 16:11:36 +02009161 return ERR_ALERT | ERR_FATAL;
9162 }
9163
Willy Tarreauef934602016-12-22 23:12:01 +01009164 if ((*args[*cur_arg + 1] != '/') && global_ssl.ca_base)
9165 memprintf(&newsrv->ssl_ctx.crl_file, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02009166 else
9167 memprintf(&newsrv->ssl_ctx.crl_file, "%s", args[*cur_arg + 1]);
9168
9169 return 0;
9170#endif
9171}
9172
Emeric Bruna7aa3092012-10-26 12:58:00 +02009173/* parse the "crt" server keyword */
9174static int srv_parse_crt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9175{
9176 if (!*args[*cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009177 memprintf(err, "'%s' : missing certificate file path", args[*cur_arg]);
Emeric Bruna7aa3092012-10-26 12:58:00 +02009178 return ERR_ALERT | ERR_FATAL;
9179 }
9180
Willy Tarreauef934602016-12-22 23:12:01 +01009181 if ((*args[*cur_arg + 1] != '/') && global_ssl.crt_base)
Christopher Fauletff3a41e2017-11-23 09:13:32 +01009182 memprintf(&newsrv->ssl_ctx.client_crt, "%s/%s", global_ssl.crt_base, args[*cur_arg + 1]);
Emeric Bruna7aa3092012-10-26 12:58:00 +02009183 else
9184 memprintf(&newsrv->ssl_ctx.client_crt, "%s", args[*cur_arg + 1]);
9185
9186 return 0;
9187}
Emeric Brunef42d922012-10-11 16:11:36 +02009188
Frédéric Lécaille340ae602017-03-13 10:38:04 +01009189/* parse the "no-check-ssl" server keyword */
9190static int srv_parse_no_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9191{
9192 newsrv->check.use_ssl = 0;
9193 free(newsrv->ssl_ctx.ciphers);
9194 newsrv->ssl_ctx.ciphers = NULL;
9195 newsrv->ssl_ctx.options &= ~global_ssl.connect_default_ssloptions;
9196 return 0;
9197}
9198
Frédéric Lécaillee892c4c2017-03-13 12:08:01 +01009199/* parse the "no-send-proxy-v2-ssl" server keyword */
9200static int srv_parse_no_send_proxy_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9201{
9202 newsrv->pp_opts &= ~SRV_PP_V2;
9203 newsrv->pp_opts &= ~SRV_PP_V2_SSL;
9204 return 0;
9205}
9206
9207/* parse the "no-send-proxy-v2-ssl-cn" server keyword */
9208static int srv_parse_no_send_proxy_cn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9209{
9210 newsrv->pp_opts &= ~SRV_PP_V2;
9211 newsrv->pp_opts &= ~SRV_PP_V2_SSL;
9212 newsrv->pp_opts &= ~SRV_PP_V2_SSL_CN;
9213 return 0;
9214}
9215
Frédéric Lécaillee381d762017-03-13 11:54:17 +01009216/* parse the "no-ssl" server keyword */
9217static int srv_parse_no_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9218{
9219 newsrv->use_ssl = 0;
9220 free(newsrv->ssl_ctx.ciphers);
9221 newsrv->ssl_ctx.ciphers = NULL;
9222 return 0;
9223}
9224
Olivier Houchard522eea72017-11-03 16:27:47 +01009225/* parse the "allow-0rtt" server keyword */
9226static int srv_parse_allow_0rtt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9227{
9228 newsrv->ssl_ctx.options |= SRV_SSL_O_EARLY_DATA;
9229 return 0;
9230}
9231
Willy Tarreau2a3fb1c2015-02-05 16:47:07 +01009232/* parse the "no-ssl-reuse" server keyword */
9233static int srv_parse_no_ssl_reuse(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9234{
9235 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_REUSE;
9236 return 0;
9237}
9238
Emeric Brunf9c5c472012-10-11 15:28:34 +02009239/* parse the "no-tls-tickets" server keyword */
9240static int srv_parse_no_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9241{
9242 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLS_TICKETS;
9243 return 0;
9244}
David Safb76832014-05-08 23:42:08 -04009245/* parse the "send-proxy-v2-ssl" server keyword */
9246static int srv_parse_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 "send-proxy-v2-ssl-cn" server keyword */
9254static int srv_parse_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}
Emeric Brunf9c5c472012-10-11 15:28:34 +02009261
Willy Tarreau732eac42015-07-09 11:40:25 +02009262/* parse the "sni" server keyword */
9263static int srv_parse_sni(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9264{
9265#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
9266 memprintf(err, "'%s' : the current SSL library doesn't support the SNI TLS extension", args[*cur_arg]);
9267 return ERR_ALERT | ERR_FATAL;
9268#else
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01009269 char *arg;
Willy Tarreau732eac42015-07-09 11:40:25 +02009270
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01009271 arg = args[*cur_arg + 1];
9272 if (!*arg) {
Willy Tarreau732eac42015-07-09 11:40:25 +02009273 memprintf(err, "'%s' : missing sni expression", args[*cur_arg]);
9274 return ERR_ALERT | ERR_FATAL;
9275 }
9276
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01009277 free(newsrv->sni_expr);
9278 newsrv->sni_expr = strdup(arg);
Willy Tarreau732eac42015-07-09 11:40:25 +02009279
Willy Tarreau732eac42015-07-09 11:40:25 +02009280 return 0;
9281#endif
9282}
9283
Willy Tarreau92faadf2012-10-10 23:04:25 +02009284/* parse the "ssl" server keyword */
9285static int srv_parse_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9286{
9287 newsrv->use_ssl = 1;
Willy Tarreauef934602016-12-22 23:12:01 +01009288 if (global_ssl.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
9289 newsrv->ssl_ctx.ciphers = strdup(global_ssl.connect_default_ciphers);
Emmanuel Hocdet839af572019-05-14 16:27:35 +02009290#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009291 if (global_ssl.connect_default_ciphersuites && !newsrv->ssl_ctx.ciphersuites)
9292 newsrv->ssl_ctx.ciphersuites = strdup(global_ssl.connect_default_ciphersuites);
9293#endif
Willy Tarreau92faadf2012-10-10 23:04:25 +02009294 return 0;
9295}
9296
Frédéric Lécaille2cfcdbe2017-03-13 11:32:20 +01009297/* parse the "ssl-reuse" server keyword */
9298static int srv_parse_ssl_reuse(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9299{
9300 newsrv->ssl_ctx.options &= ~SRV_SSL_O_NO_REUSE;
9301 return 0;
9302}
9303
Frédéric Lécaille2cfcdbe2017-03-13 11:32:20 +01009304/* parse the "tls-tickets" server keyword */
9305static int srv_parse_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9306{
9307 newsrv->ssl_ctx.options &= ~SRV_SSL_O_NO_TLS_TICKETS;
9308 return 0;
9309}
9310
Emeric Brunef42d922012-10-11 16:11:36 +02009311/* parse the "verify" server keyword */
9312static int srv_parse_verify(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9313{
9314 if (!*args[*cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009315 memprintf(err, "'%s' : missing verify method", args[*cur_arg]);
Emeric Brunef42d922012-10-11 16:11:36 +02009316 return ERR_ALERT | ERR_FATAL;
9317 }
9318
9319 if (strcmp(args[*cur_arg + 1], "none") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01009320 newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_NONE;
Emeric Brunef42d922012-10-11 16:11:36 +02009321 else if (strcmp(args[*cur_arg + 1], "required") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01009322 newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_REQUIRED;
Emeric Brunef42d922012-10-11 16:11:36 +02009323 else {
Tim Duesterhus93128532019-11-23 23:45:10 +01009324 memprintf(err, "'%s' : unknown verify method '%s', only 'none' and 'required' are supported\n",
9325 args[*cur_arg], args[*cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02009326 return ERR_ALERT | ERR_FATAL;
9327 }
9328
Evan Broderbe554312013-06-27 00:05:25 -07009329 return 0;
9330}
9331
9332/* parse the "verifyhost" server keyword */
9333static int srv_parse_verifyhost(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9334{
9335 if (!*args[*cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009336 memprintf(err, "'%s' : missing hostname to verify against", args[*cur_arg]);
Evan Broderbe554312013-06-27 00:05:25 -07009337 return ERR_ALERT | ERR_FATAL;
9338 }
9339
Frédéric Lécaille273f3212017-03-13 15:52:01 +01009340 free(newsrv->ssl_ctx.verify_host);
Evan Broderbe554312013-06-27 00:05:25 -07009341 newsrv->ssl_ctx.verify_host = strdup(args[*cur_arg + 1]);
9342
Emeric Brunef42d922012-10-11 16:11:36 +02009343 return 0;
9344}
9345
Emeric Brun2c86cbf2014-10-30 15:56:50 +01009346/* parse the "ssl-default-bind-options" keyword in global section */
9347static int ssl_parse_default_bind_options(char **args, int section_type, struct proxy *curpx,
9348 struct proxy *defpx, const char *file, int line,
9349 char **err) {
9350 int i = 1;
9351
9352 if (*(args[i]) == 0) {
9353 memprintf(err, "global statement '%s' expects an option as an argument.", args[0]);
9354 return -1;
9355 }
9356 while (*(args[i])) {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02009357 if (!strcmp(args[i], "no-tls-tickets"))
Willy Tarreauef934602016-12-22 23:12:01 +01009358 global_ssl.listen_default_ssloptions |= BC_SSL_O_NO_TLS_TICKETS;
Lukas Tribus53ae85c2017-05-04 15:45:40 +00009359 else if (!strcmp(args[i], "prefer-client-ciphers"))
9360 global_ssl.listen_default_ssloptions |= BC_SSL_O_PREF_CLIE_CIPH;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02009361 else if (!strcmp(args[i], "ssl-min-ver") || !strcmp(args[i], "ssl-max-ver")) {
9362 if (!parse_tls_method_minmax(args, i, &global_ssl.listen_default_sslmethods, err))
9363 i++;
9364 else {
9365 memprintf(err, "%s on global statement '%s'.", *err, args[0]);
9366 return -1;
9367 }
9368 }
9369 else if (parse_tls_method_options(args[i], &global_ssl.listen_default_sslmethods, err)) {
Emeric Brun2c86cbf2014-10-30 15:56:50 +01009370 memprintf(err, "unknown option '%s' on global statement '%s'.", args[i], args[0]);
9371 return -1;
9372 }
9373 i++;
9374 }
9375 return 0;
9376}
9377
9378/* parse the "ssl-default-server-options" keyword in global section */
9379static int ssl_parse_default_server_options(char **args, int section_type, struct proxy *curpx,
9380 struct proxy *defpx, const char *file, int line,
9381 char **err) {
9382 int i = 1;
9383
9384 if (*(args[i]) == 0) {
9385 memprintf(err, "global statement '%s' expects an option as an argument.", args[0]);
9386 return -1;
9387 }
9388 while (*(args[i])) {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02009389 if (!strcmp(args[i], "no-tls-tickets"))
Willy Tarreauef934602016-12-22 23:12:01 +01009390 global_ssl.connect_default_ssloptions |= SRV_SSL_O_NO_TLS_TICKETS;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02009391 else if (!strcmp(args[i], "ssl-min-ver") || !strcmp(args[i], "ssl-max-ver")) {
9392 if (!parse_tls_method_minmax(args, i, &global_ssl.connect_default_sslmethods, err))
9393 i++;
9394 else {
9395 memprintf(err, "%s on global statement '%s'.", *err, args[0]);
9396 return -1;
9397 }
9398 }
9399 else if (parse_tls_method_options(args[i], &global_ssl.connect_default_sslmethods, err)) {
Emeric Brun2c86cbf2014-10-30 15:56:50 +01009400 memprintf(err, "unknown option '%s' on global statement '%s'.", args[i], args[0]);
9401 return -1;
9402 }
9403 i++;
9404 }
9405 return 0;
9406}
9407
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01009408/* parse the "ca-base" / "crt-base" keywords in global section.
9409 * Returns <0 on alert, >0 on warning, 0 on success.
9410 */
9411static int ssl_parse_global_ca_crt_base(char **args, int section_type, struct proxy *curpx,
9412 struct proxy *defpx, const char *file, int line,
9413 char **err)
9414{
9415 char **target;
9416
Willy Tarreauef934602016-12-22 23:12:01 +01009417 target = (args[0][1] == 'a') ? &global_ssl.ca_base : &global_ssl.crt_base;
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01009418
9419 if (too_many_args(1, args, err, NULL))
9420 return -1;
9421
9422 if (*target) {
9423 memprintf(err, "'%s' already specified.", args[0]);
9424 return -1;
9425 }
9426
9427 if (*(args[1]) == 0) {
9428 memprintf(err, "global statement '%s' expects a directory path as an argument.", args[0]);
9429 return -1;
9430 }
9431 *target = strdup(args[1]);
9432 return 0;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00009433}
9434
9435/* parse the "ssl-mode-async" keyword in global section.
9436 * Returns <0 on alert, >0 on warning, 0 on success.
9437 */
9438static int ssl_parse_global_ssl_async(char **args, int section_type, struct proxy *curpx,
9439 struct proxy *defpx, const char *file, int line,
9440 char **err)
9441{
Willy Tarreau5db847a2019-05-09 14:13:35 +02009442#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00009443 global_ssl.async = 1;
Emeric Brunece0c332017-12-06 13:51:49 +01009444 global.ssl_used_async_engines = nb_engines;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00009445 return 0;
9446#else
9447 memprintf(err, "'%s': openssl library does not support async mode", args[0]);
9448 return -1;
9449#endif
9450}
9451
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02009452#ifndef OPENSSL_NO_ENGINE
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00009453static int ssl_check_async_engine_count(void) {
9454 int err_code = 0;
9455
Emeric Brun3854e012017-05-17 20:42:48 +02009456 if (global_ssl.async && (openssl_engines_initialized > 32)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01009457 ha_alert("ssl-mode-async only supports a maximum of 32 engines.\n");
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00009458 err_code = ERR_ABORT;
9459 }
9460 return err_code;
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01009461}
9462
Grant Zhang872f9c22017-01-21 01:10:18 +00009463/* parse the "ssl-engine" keyword in global section.
9464 * Returns <0 on alert, >0 on warning, 0 on success.
9465 */
9466static int ssl_parse_global_ssl_engine(char **args, int section_type, struct proxy *curpx,
9467 struct proxy *defpx, const char *file, int line,
9468 char **err)
9469{
9470 char *algo;
9471 int ret = -1;
9472
9473 if (*(args[1]) == 0) {
9474 memprintf(err, "global statement '%s' expects a valid engine name as an argument.", args[0]);
9475 return ret;
9476 }
9477
9478 if (*(args[2]) == 0) {
9479 /* if no list of algorithms is given, it defaults to ALL */
9480 algo = strdup("ALL");
9481 goto add_engine;
9482 }
9483
9484 /* otherwise the expected format is ssl-engine <engine_name> algo <list of algo> */
9485 if (strcmp(args[2], "algo") != 0) {
9486 memprintf(err, "global statement '%s' expects to have algo keyword.", args[0]);
9487 return ret;
9488 }
9489
9490 if (*(args[3]) == 0) {
9491 memprintf(err, "global statement '%s' expects algorithm names as an argument.", args[0]);
9492 return ret;
9493 }
9494 algo = strdup(args[3]);
9495
9496add_engine:
9497 if (ssl_init_single_engine(args[1], algo)==0) {
9498 openssl_engines_initialized++;
9499 ret = 0;
9500 }
9501 free(algo);
9502 return ret;
9503}
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02009504#endif
Grant Zhang872f9c22017-01-21 01:10:18 +00009505
Willy Tarreauf22e9682016-12-21 23:23:19 +01009506/* parse the "ssl-default-bind-ciphers" / "ssl-default-server-ciphers" keywords
9507 * in global section. Returns <0 on alert, >0 on warning, 0 on success.
9508 */
9509static int ssl_parse_global_ciphers(char **args, int section_type, struct proxy *curpx,
9510 struct proxy *defpx, const char *file, int line,
9511 char **err)
9512{
9513 char **target;
9514
Willy Tarreauef934602016-12-22 23:12:01 +01009515 target = (args[0][12] == 'b') ? &global_ssl.listen_default_ciphers : &global_ssl.connect_default_ciphers;
Willy Tarreauf22e9682016-12-21 23:23:19 +01009516
9517 if (too_many_args(1, args, err, NULL))
9518 return -1;
9519
9520 if (*(args[1]) == 0) {
9521 memprintf(err, "global statement '%s' expects a cipher suite as an argument.", args[0]);
9522 return -1;
9523 }
9524
9525 free(*target);
9526 *target = strdup(args[1]);
9527 return 0;
9528}
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009529
Emmanuel Hocdet839af572019-05-14 16:27:35 +02009530#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009531/* parse the "ssl-default-bind-ciphersuites" / "ssl-default-server-ciphersuites" keywords
9532 * in global section. Returns <0 on alert, >0 on warning, 0 on success.
9533 */
9534static int ssl_parse_global_ciphersuites(char **args, int section_type, struct proxy *curpx,
9535 struct proxy *defpx, const char *file, int line,
9536 char **err)
9537{
9538 char **target;
9539
9540 target = (args[0][12] == 'b') ? &global_ssl.listen_default_ciphersuites : &global_ssl.connect_default_ciphersuites;
9541
9542 if (too_many_args(1, args, err, NULL))
9543 return -1;
9544
9545 if (*(args[1]) == 0) {
9546 memprintf(err, "global statement '%s' expects a cipher suite as an argument.", args[0]);
9547 return -1;
9548 }
9549
9550 free(*target);
9551 *target = strdup(args[1]);
9552 return 0;
9553}
9554#endif
Willy Tarreauf22e9682016-12-21 23:23:19 +01009555
Willy Tarreau9ceda382016-12-21 23:13:03 +01009556/* parse various global tune.ssl settings consisting in positive integers.
9557 * Returns <0 on alert, >0 on warning, 0 on success.
9558 */
9559static int ssl_parse_global_int(char **args, int section_type, struct proxy *curpx,
9560 struct proxy *defpx, const char *file, int line,
9561 char **err)
9562{
9563 int *target;
9564
9565 if (strcmp(args[0], "tune.ssl.cachesize") == 0)
9566 target = &global.tune.sslcachesize;
9567 else if (strcmp(args[0], "tune.ssl.maxrecord") == 0)
Willy Tarreauef934602016-12-22 23:12:01 +01009568 target = (int *)&global_ssl.max_record;
Willy Tarreau9ceda382016-12-21 23:13:03 +01009569 else if (strcmp(args[0], "tune.ssl.ssl-ctx-cache-size") == 0)
Willy Tarreauef934602016-12-22 23:12:01 +01009570 target = &global_ssl.ctx_cache;
Willy Tarreau0bea58d2016-12-21 23:17:25 +01009571 else if (strcmp(args[0], "maxsslconn") == 0)
9572 target = &global.maxsslconn;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01009573 else if (strcmp(args[0], "tune.ssl.capture-cipherlist-size") == 0)
9574 target = &global_ssl.capture_cipherlist;
Willy Tarreau9ceda382016-12-21 23:13:03 +01009575 else {
9576 memprintf(err, "'%s' keyword not unhandled (please report this bug).", args[0]);
9577 return -1;
9578 }
9579
9580 if (too_many_args(1, args, err, NULL))
9581 return -1;
9582
9583 if (*(args[1]) == 0) {
9584 memprintf(err, "'%s' expects an integer argument.", args[0]);
9585 return -1;
9586 }
9587
9588 *target = atoi(args[1]);
9589 if (*target < 0) {
9590 memprintf(err, "'%s' expects a positive numeric value.", args[0]);
9591 return -1;
9592 }
9593 return 0;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01009594}
9595
9596static int ssl_parse_global_capture_cipherlist(char **args, int section_type, struct proxy *curpx,
9597 struct proxy *defpx, const char *file, int line,
9598 char **err)
9599{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01009600 int ret;
9601
9602 ret = ssl_parse_global_int(args, section_type, curpx, defpx, file, line, err);
9603 if (ret != 0)
9604 return ret;
9605
Willy Tarreaubafbe012017-11-24 17:34:44 +01009606 if (pool_head_ssl_capture) {
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01009607 memprintf(err, "'%s' is already configured.", args[0]);
9608 return -1;
9609 }
9610
Willy Tarreaubafbe012017-11-24 17:34:44 +01009611 pool_head_ssl_capture = create_pool("ssl-capture", sizeof(struct ssl_capture) + global_ssl.capture_cipherlist, MEM_F_SHARED);
9612 if (!pool_head_ssl_capture) {
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01009613 memprintf(err, "Out of memory error.");
9614 return -1;
9615 }
9616 return 0;
Willy Tarreau9ceda382016-12-21 23:13:03 +01009617}
9618
9619/* parse "ssl.force-private-cache".
9620 * Returns <0 on alert, >0 on warning, 0 on success.
9621 */
9622static int ssl_parse_global_private_cache(char **args, int section_type, struct proxy *curpx,
9623 struct proxy *defpx, const char *file, int line,
9624 char **err)
9625{
9626 if (too_many_args(0, args, err, NULL))
9627 return -1;
9628
Willy Tarreauef934602016-12-22 23:12:01 +01009629 global_ssl.private_cache = 1;
Willy Tarreau9ceda382016-12-21 23:13:03 +01009630 return 0;
9631}
9632
9633/* parse "ssl.lifetime".
9634 * Returns <0 on alert, >0 on warning, 0 on success.
9635 */
9636static int ssl_parse_global_lifetime(char **args, int section_type, struct proxy *curpx,
9637 struct proxy *defpx, const char *file, int line,
9638 char **err)
9639{
9640 const char *res;
9641
9642 if (too_many_args(1, args, err, NULL))
9643 return -1;
9644
9645 if (*(args[1]) == 0) {
9646 memprintf(err, "'%s' expects ssl sessions <lifetime> in seconds as argument.", args[0]);
9647 return -1;
9648 }
9649
Willy Tarreauef934602016-12-22 23:12:01 +01009650 res = parse_time_err(args[1], &global_ssl.life_time, TIME_UNIT_S);
Willy Tarreau9faebe32019-06-07 19:00:37 +02009651 if (res == PARSE_TIME_OVER) {
9652 memprintf(err, "timer overflow in argument '%s' to <%s> (maximum value is 2147483647 s or ~68 years).",
9653 args[1], args[0]);
9654 return -1;
9655 }
9656 else if (res == PARSE_TIME_UNDER) {
9657 memprintf(err, "timer underflow in argument '%s' to <%s> (minimum non-null value is 1 s).",
9658 args[1], args[0]);
9659 return -1;
9660 }
9661 else if (res) {
Willy Tarreau9ceda382016-12-21 23:13:03 +01009662 memprintf(err, "unexpected character '%c' in argument to <%s>.", *res, args[0]);
9663 return -1;
9664 }
9665 return 0;
9666}
9667
9668#ifndef OPENSSL_NO_DH
Willy Tarreau14e36a12016-12-21 23:28:13 +01009669/* parse "ssl-dh-param-file".
9670 * Returns <0 on alert, >0 on warning, 0 on success.
9671 */
9672static int ssl_parse_global_dh_param_file(char **args, int section_type, struct proxy *curpx,
9673 struct proxy *defpx, const char *file, int line,
9674 char **err)
9675{
9676 if (too_many_args(1, args, err, NULL))
9677 return -1;
9678
9679 if (*(args[1]) == 0) {
9680 memprintf(err, "'%s' expects a file path as an argument.", args[0]);
9681 return -1;
9682 }
9683
9684 if (ssl_sock_load_global_dh_param_from_file(args[1])) {
9685 memprintf(err, "'%s': unable to load DH parameters from file <%s>.", args[0], args[1]);
9686 return -1;
9687 }
9688 return 0;
9689}
9690
Willy Tarreau9ceda382016-12-21 23:13:03 +01009691/* parse "ssl.default-dh-param".
9692 * Returns <0 on alert, >0 on warning, 0 on success.
9693 */
9694static int ssl_parse_global_default_dh(char **args, int section_type, struct proxy *curpx,
9695 struct proxy *defpx, const char *file, int line,
9696 char **err)
9697{
9698 if (too_many_args(1, args, err, NULL))
9699 return -1;
9700
9701 if (*(args[1]) == 0) {
9702 memprintf(err, "'%s' expects an integer argument.", args[0]);
9703 return -1;
9704 }
9705
Willy Tarreauef934602016-12-22 23:12:01 +01009706 global_ssl.default_dh_param = atoi(args[1]);
9707 if (global_ssl.default_dh_param < 1024) {
Willy Tarreau9ceda382016-12-21 23:13:03 +01009708 memprintf(err, "'%s' expects a value >= 1024.", args[0]);
9709 return -1;
9710 }
9711 return 0;
9712}
9713#endif
9714
9715
William Lallemand32af2032016-10-29 18:09:35 +02009716/* This function is used with TLS ticket keys management. It permits to browse
9717 * each reference. The variable <getnext> must contain the current node,
9718 * <end> point to the root node.
9719 */
9720#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
9721static inline
9722struct tls_keys_ref *tlskeys_list_get_next(struct tls_keys_ref *getnext, struct list *end)
9723{
9724 struct tls_keys_ref *ref = getnext;
9725
9726 while (1) {
9727
9728 /* Get next list entry. */
9729 ref = LIST_NEXT(&ref->list, struct tls_keys_ref *, list);
9730
9731 /* If the entry is the last of the list, return NULL. */
9732 if (&ref->list == end)
9733 return NULL;
9734
9735 return ref;
9736 }
9737}
9738
9739static inline
9740struct tls_keys_ref *tlskeys_ref_lookup_ref(const char *reference)
9741{
9742 int id;
9743 char *error;
9744
9745 /* If the reference starts by a '#', this is numeric id. */
9746 if (reference[0] == '#') {
9747 /* Try to convert the numeric id. If the conversion fails, the lookup fails. */
9748 id = strtol(reference + 1, &error, 10);
9749 if (*error != '\0')
9750 return NULL;
9751
9752 /* Perform the unique id lookup. */
9753 return tlskeys_ref_lookupid(id);
9754 }
9755
9756 /* Perform the string lookup. */
9757 return tlskeys_ref_lookup(reference);
9758}
9759#endif
9760
9761
9762#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
9763
9764static int cli_io_handler_tlskeys_files(struct appctx *appctx);
9765
9766static inline int cli_io_handler_tlskeys_entries(struct appctx *appctx) {
9767 return cli_io_handler_tlskeys_files(appctx);
9768}
9769
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009770/* dumps all tls keys. Relies on cli.i0 (non-null = only list file names), cli.i1
9771 * (next index to be dumped), and cli.p0 (next key reference).
9772 */
William Lallemand32af2032016-10-29 18:09:35 +02009773static int cli_io_handler_tlskeys_files(struct appctx *appctx) {
9774
9775 struct stream_interface *si = appctx->owner;
9776
9777 switch (appctx->st2) {
9778 case STAT_ST_INIT:
9779 /* Display the column headers. If the message cannot be sent,
Joseph Herlant017b3da2018-11-15 09:07:59 -08009780 * quit the function with returning 0. The function is called
William Lallemand32af2032016-10-29 18:09:35 +02009781 * later and restart at the state "STAT_ST_INIT".
9782 */
9783 chunk_reset(&trash);
9784
9785 if (appctx->io_handler == cli_io_handler_tlskeys_entries)
9786 chunk_appendf(&trash, "# id secret\n");
9787 else
9788 chunk_appendf(&trash, "# id (file)\n");
9789
Willy Tarreau06d80a92017-10-19 14:32:15 +02009790 if (ci_putchk(si_ic(si), &trash) == -1) {
Willy Tarreaudb398432018-11-15 11:08:52 +01009791 si_rx_room_blk(si);
William Lallemand32af2032016-10-29 18:09:35 +02009792 return 0;
9793 }
9794
William Lallemand32af2032016-10-29 18:09:35 +02009795 /* Now, we start the browsing of the references lists.
9796 * Note that the following call to LIST_ELEM return bad pointer. The only
9797 * available field of this pointer is <list>. It is used with the function
9798 * tlskeys_list_get_next() for retruning the first available entry
9799 */
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009800 if (appctx->ctx.cli.p0 == NULL) {
9801 appctx->ctx.cli.p0 = LIST_ELEM(&tlskeys_reference, struct tls_keys_ref *, list);
9802 appctx->ctx.cli.p0 = tlskeys_list_get_next(appctx->ctx.cli.p0, &tlskeys_reference);
William Lallemand32af2032016-10-29 18:09:35 +02009803 }
9804
9805 appctx->st2 = STAT_ST_LIST;
9806 /* fall through */
9807
9808 case STAT_ST_LIST:
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009809 while (appctx->ctx.cli.p0) {
9810 struct tls_keys_ref *ref = appctx->ctx.cli.p0;
William Lallemand32af2032016-10-29 18:09:35 +02009811
9812 chunk_reset(&trash);
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009813 if (appctx->io_handler == cli_io_handler_tlskeys_entries && appctx->ctx.cli.i1 == 0)
William Lallemand32af2032016-10-29 18:09:35 +02009814 chunk_appendf(&trash, "# ");
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009815
9816 if (appctx->ctx.cli.i1 == 0)
9817 chunk_appendf(&trash, "%d (%s)\n", ref->unique_id, ref->filename);
9818
William Lallemand32af2032016-10-29 18:09:35 +02009819 if (appctx->io_handler == cli_io_handler_tlskeys_entries) {
Christopher Faulet16f45c82018-02-16 11:23:49 +01009820 int head;
9821
9822 HA_RWLOCK_RDLOCK(TLSKEYS_REF_LOCK, &ref->lock);
9823 head = ref->tls_ticket_enc_index;
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009824 while (appctx->ctx.cli.i1 < TLS_TICKETS_NO) {
Willy Tarreau83061a82018-07-13 11:56:34 +02009825 struct buffer *t2 = get_trash_chunk();
William Lallemand32af2032016-10-29 18:09:35 +02009826
9827 chunk_reset(t2);
9828 /* should never fail here because we dump only a key in the t2 buffer */
Emeric Brun9e754772019-01-10 17:51:55 +01009829 if (ref->key_size_bits == 128) {
9830 t2->data = a2base64((char *)(ref->tlskeys + (head + 2 + appctx->ctx.cli.i1) % TLS_TICKETS_NO),
9831 sizeof(struct tls_sess_key_128),
9832 t2->area, t2->size);
9833 chunk_appendf(&trash, "%d.%d %s\n", ref->unique_id, appctx->ctx.cli.i1,
9834 t2->area);
9835 }
9836 else if (ref->key_size_bits == 256) {
9837 t2->data = a2base64((char *)(ref->tlskeys + (head + 2 + appctx->ctx.cli.i1) % TLS_TICKETS_NO),
9838 sizeof(struct tls_sess_key_256),
9839 t2->area, t2->size);
9840 chunk_appendf(&trash, "%d.%d %s\n", ref->unique_id, appctx->ctx.cli.i1,
9841 t2->area);
9842 }
9843 else {
9844 /* This case should never happen */
9845 chunk_appendf(&trash, "%d.%d <unknown>\n", ref->unique_id, appctx->ctx.cli.i1);
9846 }
William Lallemand32af2032016-10-29 18:09:35 +02009847
Willy Tarreau06d80a92017-10-19 14:32:15 +02009848 if (ci_putchk(si_ic(si), &trash) == -1) {
William Lallemand32af2032016-10-29 18:09:35 +02009849 /* let's try again later from this stream. We add ourselves into
9850 * this stream's users so that it can remove us upon termination.
9851 */
Christopher Faulet16f45c82018-02-16 11:23:49 +01009852 HA_RWLOCK_RDUNLOCK(TLSKEYS_REF_LOCK, &ref->lock);
Willy Tarreaudb398432018-11-15 11:08:52 +01009853 si_rx_room_blk(si);
William Lallemand32af2032016-10-29 18:09:35 +02009854 return 0;
9855 }
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009856 appctx->ctx.cli.i1++;
William Lallemand32af2032016-10-29 18:09:35 +02009857 }
Christopher Faulet16f45c82018-02-16 11:23:49 +01009858 HA_RWLOCK_RDUNLOCK(TLSKEYS_REF_LOCK, &ref->lock);
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009859 appctx->ctx.cli.i1 = 0;
William Lallemand32af2032016-10-29 18:09:35 +02009860 }
Willy Tarreau06d80a92017-10-19 14:32:15 +02009861 if (ci_putchk(si_ic(si), &trash) == -1) {
William Lallemand32af2032016-10-29 18:09:35 +02009862 /* let's try again later from this stream. We add ourselves into
9863 * this stream's users so that it can remove us upon termination.
9864 */
Willy Tarreaudb398432018-11-15 11:08:52 +01009865 si_rx_room_blk(si);
William Lallemand32af2032016-10-29 18:09:35 +02009866 return 0;
9867 }
9868
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009869 if (appctx->ctx.cli.i0 == 0) /* don't display everything if not necessary */
William Lallemand32af2032016-10-29 18:09:35 +02009870 break;
9871
9872 /* get next list entry and check the end of the list */
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009873 appctx->ctx.cli.p0 = tlskeys_list_get_next(appctx->ctx.cli.p0, &tlskeys_reference);
William Lallemand32af2032016-10-29 18:09:35 +02009874 }
9875
9876 appctx->st2 = STAT_ST_FIN;
9877 /* fall through */
9878
9879 default:
9880 appctx->st2 = STAT_ST_FIN;
9881 return 1;
9882 }
9883 return 0;
9884}
9885
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009886/* sets cli.i0 to non-zero if only file lists should be dumped */
Aurélien Nephtaliabbf6072018-04-18 13:26:46 +02009887static int cli_parse_show_tlskeys(char **args, char *payload, struct appctx *appctx, void *private)
William Lallemand32af2032016-10-29 18:09:35 +02009888{
William Lallemand32af2032016-10-29 18:09:35 +02009889 /* no parameter, shows only file list */
9890 if (!*args[2]) {
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009891 appctx->ctx.cli.i0 = 1;
William Lallemand32af2032016-10-29 18:09:35 +02009892 appctx->io_handler = cli_io_handler_tlskeys_files;
Willy Tarreau3067bfa2016-12-05 14:50:15 +01009893 return 0;
William Lallemand32af2032016-10-29 18:09:35 +02009894 }
9895
9896 if (args[2][0] == '*') {
9897 /* list every TLS ticket keys */
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009898 appctx->ctx.cli.i0 = 1;
William Lallemand32af2032016-10-29 18:09:35 +02009899 } else {
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009900 appctx->ctx.cli.p0 = tlskeys_ref_lookup_ref(args[2]);
Willy Tarreau9d008692019-08-09 11:21:01 +02009901 if (!appctx->ctx.cli.p0)
9902 return cli_err(appctx, "'show tls-keys' unable to locate referenced filename\n");
William Lallemand32af2032016-10-29 18:09:35 +02009903 }
William Lallemand32af2032016-10-29 18:09:35 +02009904 appctx->io_handler = cli_io_handler_tlskeys_entries;
Willy Tarreau3067bfa2016-12-05 14:50:15 +01009905 return 0;
William Lallemand32af2032016-10-29 18:09:35 +02009906}
9907
Aurélien Nephtaliabbf6072018-04-18 13:26:46 +02009908static int cli_parse_set_tlskeys(char **args, char *payload, struct appctx *appctx, void *private)
William Lallemand32af2032016-10-29 18:09:35 +02009909{
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009910 struct tls_keys_ref *ref;
Willy Tarreau1c913e42018-08-22 05:26:57 +02009911 int ret;
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009912
William Lallemand32af2032016-10-29 18:09:35 +02009913 /* Expect two parameters: the filename and the new new TLS key in encoding */
Willy Tarreau9d008692019-08-09 11:21:01 +02009914 if (!*args[3] || !*args[4])
9915 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 +02009916
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009917 ref = tlskeys_ref_lookup_ref(args[3]);
Willy Tarreau9d008692019-08-09 11:21:01 +02009918 if (!ref)
9919 return cli_err(appctx, "'set ssl tls-key' unable to locate referenced filename\n");
William Lallemand32af2032016-10-29 18:09:35 +02009920
Willy Tarreau1c913e42018-08-22 05:26:57 +02009921 ret = base64dec(args[4], strlen(args[4]), trash.area, trash.size);
Willy Tarreau9d008692019-08-09 11:21:01 +02009922 if (ret < 0)
9923 return cli_err(appctx, "'set ssl tls-key' received invalid base64 encoded TLS key.\n");
Emeric Brun9e754772019-01-10 17:51:55 +01009924
Willy Tarreau1c913e42018-08-22 05:26:57 +02009925 trash.data = ret;
Willy Tarreau9d008692019-08-09 11:21:01 +02009926 if (ssl_sock_update_tlskey_ref(ref, &trash) < 0)
9927 return cli_err(appctx, "'set ssl tls-key' received a key of wrong size.\n");
William Lallemand32af2032016-10-29 18:09:35 +02009928
Willy Tarreau9d008692019-08-09 11:21:01 +02009929 return cli_msg(appctx, LOG_INFO, "TLS ticket key updated!\n");
William Lallemand32af2032016-10-29 18:09:35 +02009930}
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01009931#endif
William Lallemand32af2032016-10-29 18:09:35 +02009932
William Lallemand44b35322019-10-17 16:28:40 +02009933
9934/* Type of SSL payloads that can be updated over the CLI */
9935
9936enum {
9937 CERT_TYPE_PEM = 0,
Emmanuel Hocdetf6ac4fa2019-10-30 17:41:27 +01009938#if ((defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP) || defined OPENSSL_IS_BORINGSSL)
William Lallemand44b35322019-10-17 16:28:40 +02009939 CERT_TYPE_OCSP,
Emmanuel Hocdetf6ac4fa2019-10-30 17:41:27 +01009940#endif
William Lallemand44b35322019-10-17 16:28:40 +02009941 CERT_TYPE_ISSUER,
Emmanuel Hocdetf6ac4fa2019-10-30 17:41:27 +01009942#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
William Lallemand44b35322019-10-17 16:28:40 +02009943 CERT_TYPE_SCTL,
Emmanuel Hocdetf6ac4fa2019-10-30 17:41:27 +01009944#endif
William Lallemand44b35322019-10-17 16:28:40 +02009945 CERT_TYPE_MAX,
9946};
9947
9948struct {
9949 const char *ext;
9950 int type;
9951 int (*load)(const char *path, char *payload, struct cert_key_and_chain *ckch, char **err);
9952 /* add a parsing callback */
William Lallemandf29cdef2019-10-23 15:00:52 +02009953} cert_exts[CERT_TYPE_MAX+1] = {
William Lallemand44b35322019-10-17 16:28:40 +02009954 [CERT_TYPE_PEM] = { "", CERT_TYPE_PEM, &ssl_sock_load_pem_into_ckch }, /* default mode, no extensions */
William Lallemand541a5342019-10-23 14:11:54 +02009955#if ((defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP) || defined OPENSSL_IS_BORINGSSL)
William Lallemand44b35322019-10-17 16:28:40 +02009956 [CERT_TYPE_OCSP] = { "ocsp", CERT_TYPE_OCSP, &ssl_sock_load_ocsp_response_from_file },
William Lallemand541a5342019-10-23 14:11:54 +02009957#endif
9958#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
William Lallemand44b35322019-10-17 16:28:40 +02009959 [CERT_TYPE_SCTL] = { "sctl", CERT_TYPE_SCTL, &ssl_sock_load_sctl_from_file },
William Lallemand541a5342019-10-23 14:11:54 +02009960#endif
William Lallemand44b35322019-10-17 16:28:40 +02009961 [CERT_TYPE_ISSUER] = { "issuer", CERT_TYPE_ISSUER, &ssl_sock_load_issuer_file_into_ckch },
William Lallemandf29cdef2019-10-23 15:00:52 +02009962 [CERT_TYPE_MAX] = { NULL, CERT_TYPE_MAX, NULL },
William Lallemand44b35322019-10-17 16:28:40 +02009963};
9964
William Lallemand430413e2019-10-28 14:30:47 +01009965/* states of the CLI IO handler for 'set ssl cert' */
9966enum {
9967 SETCERT_ST_INIT = 0,
9968 SETCERT_ST_GEN,
9969 SETCERT_ST_INSERT,
9970 SETCERT_ST_FIN,
9971};
William Lallemand8f840d72019-10-23 10:53:05 +02009972
William Lallemand430413e2019-10-28 14:30:47 +01009973/* release function of the `set ssl cert' command, free things and unlock the spinlock */
William Lallemandbc6ca7c2019-10-29 23:48:19 +01009974static void cli_release_commit_cert(struct appctx *appctx)
William Lallemand8f840d72019-10-23 10:53:05 +02009975{
9976 struct ckch_store *new_ckchs;
9977 struct ckch_inst *ckchi, *ckchis;
William Lallemand8f840d72019-10-23 10:53:05 +02009978
William Lallemand430413e2019-10-28 14:30:47 +01009979 HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
William Lallemand8f840d72019-10-23 10:53:05 +02009980
William Lallemand430413e2019-10-28 14:30:47 +01009981 if (appctx->st2 != SETCERT_ST_FIN) {
William Lallemand8f840d72019-10-23 10:53:05 +02009982 /* 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 +01009983 new_ckchs = appctx->ctx.ssl.new_ckchs;
William Lallemand8f840d72019-10-23 10:53:05 +02009984
William Lallemandbeea2a42019-10-30 17:45:33 +01009985 if (!new_ckchs)
9986 return;
William Lallemand8f840d72019-10-23 10:53:05 +02009987
William Lallemandbeea2a42019-10-30 17:45:33 +01009988 /* if the allocation failed, we need to free everything from the temporary list */
9989 list_for_each_entry_safe(ckchi, ckchis, &new_ckchs->ckch_inst, by_ckchs) {
9990 struct sni_ctx *sc0, *sc0s;
William Lallemand8f840d72019-10-23 10:53:05 +02009991
William Lallemandbeea2a42019-10-30 17:45:33 +01009992 list_for_each_entry_safe(sc0, sc0s, &ckchi->sni_ctx, by_ckch_inst) {
9993 if (sc0->order == 0) /* we only free if it's the first inserted */
9994 SSL_CTX_free(sc0->ctx);
9995 LIST_DEL(&sc0->by_ckch_inst);
9996 free(sc0);
William Lallemand8f840d72019-10-23 10:53:05 +02009997 }
William Lallemandbeea2a42019-10-30 17:45:33 +01009998 LIST_DEL(&ckchi->by_ckchs);
9999 free(ckchi);
William Lallemand8f840d72019-10-23 10:53:05 +020010000 }
William Lallemandbeea2a42019-10-30 17:45:33 +010010001 ckchs_free(new_ckchs);
William Lallemand8f840d72019-10-23 10:53:05 +020010002 }
10003}
10004
10005
10006/*
10007 * This function tries to create the new ckch_inst and their SNIs
10008 */
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010009static int cli_io_handler_commit_cert(struct appctx *appctx)
William Lallemand8f840d72019-10-23 10:53:05 +020010010{
10011 struct stream_interface *si = appctx->owner;
10012 int y = 0;
10013 char *err = NULL;
10014 int errcode = 0;
10015 struct ckch_store *old_ckchs, *new_ckchs = NULL;
10016 struct ckch_inst *ckchi, *ckchis;
William Lallemand8f840d72019-10-23 10:53:05 +020010017 struct buffer *trash = alloc_trash_chunk();
William Lallemand8ef0c2a2019-11-21 16:30:34 +010010018 struct sni_ctx *sc0, *sc0s;
William Lallemand8f840d72019-10-23 10:53:05 +020010019
William Lallemand33cc76f2019-10-31 11:43:45 +010010020 if (trash == NULL)
10021 goto error;
10022
William Lallemand8f840d72019-10-23 10:53:05 +020010023 if (unlikely(si_ic(si)->flags & (CF_WRITE_ERROR|CF_SHUTW)))
10024 goto error;
10025
William Lallemand430413e2019-10-28 14:30:47 +010010026 while (1) {
10027 switch (appctx->st2) {
10028 case SETCERT_ST_INIT:
10029 /* This state just print the update message */
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010030 chunk_printf(trash, "Committing %s", ckchs_transaction.path);
William Lallemand430413e2019-10-28 14:30:47 +010010031 if (ci_putchk(si_ic(si), trash) == -1) {
10032 si_rx_room_blk(si);
William Lallemand8f840d72019-10-23 10:53:05 +020010033 goto yield;
William Lallemand430413e2019-10-28 14:30:47 +010010034 }
10035 appctx->st2 = SETCERT_ST_GEN;
10036 /* fallthrough */
10037 case SETCERT_ST_GEN:
10038 /*
10039 * This state generates the ckch instances with their
10040 * sni_ctxs and SSL_CTX.
10041 *
William Lallemand430413e2019-10-28 14:30:47 +010010042 * Since the SSL_CTX generation can be CPU consumer, we
10043 * yield every 10 instances.
10044 */
William Lallemand8f840d72019-10-23 10:53:05 +020010045
William Lallemandbeea2a42019-10-30 17:45:33 +010010046 old_ckchs = appctx->ctx.ssl.old_ckchs;
10047 new_ckchs = appctx->ctx.ssl.new_ckchs;
William Lallemand8f840d72019-10-23 10:53:05 +020010048
William Lallemandbeea2a42019-10-30 17:45:33 +010010049 if (!new_ckchs)
10050 continue;
William Lallemand8f840d72019-10-23 10:53:05 +020010051
William Lallemandbeea2a42019-10-30 17:45:33 +010010052 /* get the next ckchi to regenerate */
10053 ckchi = appctx->ctx.ssl.next_ckchi;
10054 /* we didn't start yet, set it to the first elem */
10055 if (ckchi == NULL)
10056 ckchi = LIST_ELEM(old_ckchs->ckch_inst.n, typeof(ckchi), by_ckchs);
William Lallemand8f840d72019-10-23 10:53:05 +020010057
William Lallemandbeea2a42019-10-30 17:45:33 +010010058 /* walk through the old ckch_inst and creates new ckch_inst using the updated ckchs */
10059 list_for_each_entry_from(ckchi, &old_ckchs->ckch_inst, by_ckchs) {
10060 struct ckch_inst *new_inst;
William Lallemand8ef0c2a2019-11-21 16:30:34 +010010061 int verify = 0;
William Lallemand8f840d72019-10-23 10:53:05 +020010062
William Lallemandbeea2a42019-10-30 17:45:33 +010010063 /* it takes a lot of CPU to creates SSL_CTXs, so we yield every 10 CKCH instances */
10064 if (y >= 10) {
10065 /* save the next ckchi to compute */
10066 appctx->ctx.ssl.next_ckchi = ckchi;
10067 goto yield;
10068 }
William Lallemand8f840d72019-10-23 10:53:05 +020010069
William Lallemand8ef0c2a2019-11-21 16:30:34 +010010070 /* prevent ssl_sock_prepare_ctx() to do file access which is only for verify (crl/ca file) */
10071 verify = (ckchi->ssl_conf && ckchi->ssl_conf->verify) ? ckchi->ssl_conf->verify : ckchi->bind_conf->ssl_conf.verify;
10072 if (verify & SSL_VERIFY_PEER) {
10073 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);
10074 errcode |= ERR_FATAL | ERR_ABORT;
10075 goto error;
10076 }
10077
10078
William Lallemandbeea2a42019-10-30 17:45:33 +010010079 if (new_ckchs->multi)
10080 errcode |= ckch_inst_new_load_multi_store(new_ckchs->path, new_ckchs, ckchi->bind_conf, ckchi->ssl_conf, NULL, 0, &new_inst, &err);
10081 else
10082 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 +020010083
William Lallemandbeea2a42019-10-30 17:45:33 +010010084 if (errcode & ERR_CODE)
10085 goto error;
William Lallemand8f840d72019-10-23 10:53:05 +020010086
William Lallemand21724f02019-11-04 17:56:13 +010010087 /* if the previous ckchi was used as the default */
10088 if (ckchi->is_default)
10089 new_inst->is_default = 1;
10090
William Lallemand8ef0c2a2019-11-21 16:30:34 +010010091 /* we need to initialize the SSL_CTX generated */
10092 /* TODO: the prepare_ctx function need to be reworked to be safer there */
10093 list_for_each_entry_safe(sc0, sc0s, &ckchi->sni_ctx, by_ckch_inst) {
10094 if (!sc0->order) { /* we initiliazed only the first SSL_CTX because it's the same in the other sni_ctx's */
10095 errcode |= ssl_sock_prepare_ctx(ckchi->bind_conf, ckchi->ssl_conf, sc0->ctx, &err);
10096 if (errcode & ERR_CODE)
10097 goto error;
10098 }
10099 }
10100
10101
William Lallemandbeea2a42019-10-30 17:45:33 +010010102 /* display one dot per new instance */
10103 chunk_appendf(trash, ".");
10104 /* link the new ckch_inst to the duplicate */
10105 LIST_ADDQ(&new_ckchs->ckch_inst, &new_inst->by_ckchs);
10106 y++;
10107 }
William Lallemand430413e2019-10-28 14:30:47 +010010108 appctx->st2 = SETCERT_ST_INSERT;
10109 /* fallthrough */
10110 case SETCERT_ST_INSERT:
10111 /* The generation is finished, we can insert everything */
William Lallemand8f840d72019-10-23 10:53:05 +020010112
William Lallemandbeea2a42019-10-30 17:45:33 +010010113 old_ckchs = appctx->ctx.ssl.old_ckchs;
10114 new_ckchs = appctx->ctx.ssl.new_ckchs;
William Lallemand8f840d72019-10-23 10:53:05 +020010115
William Lallemandbeea2a42019-10-30 17:45:33 +010010116 if (!new_ckchs)
10117 continue;
William Lallemand430413e2019-10-28 14:30:47 +010010118
William Lallemand21724f02019-11-04 17:56:13 +010010119 /* First, we insert every new SNIs in the trees, also replace the default_ctx */
William Lallemandbeea2a42019-10-30 17:45:33 +010010120 list_for_each_entry_safe(ckchi, ckchis, &new_ckchs->ckch_inst, by_ckchs) {
10121 HA_RWLOCK_WRLOCK(SNI_LOCK, &ckchi->bind_conf->sni_lock);
10122 ssl_sock_load_cert_sni(ckchi, ckchi->bind_conf);
10123 HA_RWLOCK_WRUNLOCK(SNI_LOCK, &ckchi->bind_conf->sni_lock);
10124 }
William Lallemand8f840d72019-10-23 10:53:05 +020010125
William Lallemandbeea2a42019-10-30 17:45:33 +010010126 /* delete the old sni_ctx, the old ckch_insts and the ckch_store */
10127 list_for_each_entry_safe(ckchi, ckchis, &old_ckchs->ckch_inst, by_ckchs) {
William Lallemand430413e2019-10-28 14:30:47 +010010128
William Lallemandbeea2a42019-10-30 17:45:33 +010010129 HA_RWLOCK_WRLOCK(SNI_LOCK, &ckchi->bind_conf->sni_lock);
10130 list_for_each_entry_safe(sc0, sc0s, &ckchi->sni_ctx, by_ckch_inst) {
10131 ebmb_delete(&sc0->name);
10132 LIST_DEL(&sc0->by_ckch_inst);
10133 free(sc0);
William Lallemand430413e2019-10-28 14:30:47 +010010134 }
William Lallemandbeea2a42019-10-30 17:45:33 +010010135 HA_RWLOCK_WRUNLOCK(SNI_LOCK, &ckchi->bind_conf->sni_lock);
10136 LIST_DEL(&ckchi->by_ckchs);
10137 free(ckchi);
10138 }
William Lallemand8f840d72019-10-23 10:53:05 +020010139
William Lallemandbeea2a42019-10-30 17:45:33 +010010140 /* Replace the old ckchs by the new one */
10141 ebmb_delete(&old_ckchs->node);
10142 ckchs_free(old_ckchs);
10143 ebst_insert(&ckchs_tree, &new_ckchs->node);
William Lallemand430413e2019-10-28 14:30:47 +010010144 appctx->st2 = SETCERT_ST_FIN;
10145 /* fallthrough */
10146 case SETCERT_ST_FIN:
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010147 /* we achieved the transaction, we can set everything to NULL */
10148 free(ckchs_transaction.path);
10149 ckchs_transaction.path = NULL;
10150 ckchs_transaction.new_ckchs = NULL;
10151 ckchs_transaction.old_ckchs = NULL;
William Lallemand430413e2019-10-28 14:30:47 +010010152 goto end;
10153 }
William Lallemand8f840d72019-10-23 10:53:05 +020010154 }
William Lallemand430413e2019-10-28 14:30:47 +010010155end:
William Lallemand8f840d72019-10-23 10:53:05 +020010156
William Lallemanded442432019-11-21 16:41:07 +010010157 chunk_appendf(trash, "\n");
10158 if (errcode & ERR_WARN)
Tim Duesterhusc0e820c2019-11-23 23:52:30 +010010159 chunk_appendf(trash, "%s", err);
William Lallemanded442432019-11-21 16:41:07 +010010160 chunk_appendf(trash, "Success!\n");
William Lallemand430413e2019-10-28 14:30:47 +010010161 if (ci_putchk(si_ic(si), trash) == -1)
10162 si_rx_room_blk(si);
10163 free_trash_chunk(trash);
10164 /* success: call the release function and don't come back */
10165 return 1;
William Lallemand8f840d72019-10-23 10:53:05 +020010166yield:
10167 /* store the state */
10168 if (ci_putchk(si_ic(si), trash) == -1)
10169 si_rx_room_blk(si);
10170 free_trash_chunk(trash);
10171 si_rx_endp_more(si); /* let's come back later */
William Lallemand8f840d72019-10-23 10:53:05 +020010172 return 0; /* should come back */
10173
10174error:
10175 /* spin unlock and free are done in the release function */
William Lallemand33cc76f2019-10-31 11:43:45 +010010176 if (trash) {
10177 chunk_appendf(trash, "\n%sFailed!\n", err);
10178 if (ci_putchk(si_ic(si), trash) == -1)
10179 si_rx_room_blk(si);
10180 free_trash_chunk(trash);
10181 }
William Lallemand430413e2019-10-28 14:30:47 +010010182 /* error: call the release function and don't come back */
10183 return 1;
William Lallemand8f840d72019-10-23 10:53:05 +020010184}
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010185
10186/*
10187 * Parsing function of 'commit ssl cert'
10188 */
10189static int cli_parse_commit_cert(char **args, char *payload, struct appctx *appctx, void *private)
10190{
10191 char *err = NULL;
10192
10193 if (!*args[3])
10194 return cli_err(appctx, "'commit ssl cert expects a filename\n");
10195
10196 /* The operations on the CKCH architecture are locked so we can
10197 * manipulate ckch_store and ckch_inst */
10198 if (HA_SPIN_TRYLOCK(CKCH_LOCK, &ckch_lock))
10199 return cli_err(appctx, "Can't commit the certificate!\nOperations on certificates are currently locked!\n");
10200
10201 if (!ckchs_transaction.path) {
10202 memprintf(&err, "No ongoing transaction! !\n");
10203 goto error;
10204 }
10205
10206 if (strcmp(ckchs_transaction.path, args[3]) != 0) {
10207 memprintf(&err, "The ongoing transaction is about '%s' but you are trying to set '%s'\n", ckchs_transaction.path, args[3]);
10208 goto error;
10209 }
10210
10211 /* init the appctx structure */
10212 appctx->st2 = SETCERT_ST_INIT;
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010213 appctx->ctx.ssl.next_ckchi = NULL;
10214 appctx->ctx.ssl.new_ckchs = ckchs_transaction.new_ckchs;
10215 appctx->ctx.ssl.old_ckchs = ckchs_transaction.old_ckchs;
10216
10217 /* we don't unlock there, it will be unlock after the IO handler, in the release handler */
10218 return 0;
10219
10220error:
10221
10222 HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
10223 err = memprintf(&err, "%sCan't commit %s!\n", err ? err : "", args[3]);
10224
10225 return cli_dynerr(appctx, err);
10226}
10227
10228
William Lallemand8f840d72019-10-23 10:53:05 +020010229/*
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010230 * Parsing function of `set ssl cert`, it updates or creates a temporary ckch.
William Lallemand8f840d72019-10-23 10:53:05 +020010231 */
William Lallemand150bfa82019-09-19 17:12:49 +020010232static int cli_parse_set_cert(char **args, char *payload, struct appctx *appctx, void *private)
10233{
William Lallemand0c3b7d92019-10-18 11:27:07 +020010234 struct ckch_store *new_ckchs = NULL;
William Lallemand8f840d72019-10-23 10:53:05 +020010235 struct ckch_store *old_ckchs = NULL;
William Lallemand150bfa82019-09-19 17:12:49 +020010236 char *err = NULL;
William Lallemand963b2e72019-10-14 11:38:36 +020010237 int i;
William Lallemand849eed62019-10-17 16:23:50 +020010238 int bundle = -1; /* TRUE if >= 0 (ckch index) */
Emeric Brunf69ed1d2019-10-17 11:56:56 +020010239 int errcode = 0;
William Lallemand44b35322019-10-17 16:28:40 +020010240 char *end;
10241 int type = CERT_TYPE_PEM;
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010242 struct cert_key_and_chain *ckch;
10243 struct buffer *buf;
William Lallemand8f840d72019-10-23 10:53:05 +020010244
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010245 if ((buf = alloc_trash_chunk()) == NULL)
10246 return cli_err(appctx, "Can't allocate memory\n");
William Lallemand150bfa82019-09-19 17:12:49 +020010247
10248 if (!*args[3] || !payload)
10249 return cli_err(appctx, "'set ssl cert expects a filename and a certificat as a payload\n");
10250
10251 /* The operations on the CKCH architecture are locked so we can
10252 * manipulate ckch_store and ckch_inst */
10253 if (HA_SPIN_TRYLOCK(CKCH_LOCK, &ckch_lock))
10254 return cli_err(appctx, "Can't update the certificate!\nOperations on certificates are currently locked!\n");
10255
William Lallemand8f840d72019-10-23 10:53:05 +020010256 if (!chunk_strcpy(buf, args[3])) {
10257 memprintf(&err, "%sCan't allocate memory\n", err ? err : "");
10258 errcode |= ERR_ALERT | ERR_FATAL;
10259 goto end;
10260 }
10261
William Lallemand44b35322019-10-17 16:28:40 +020010262 /* check which type of file we want to update */
William Lallemandf29cdef2019-10-23 15:00:52 +020010263 for (i = 0; cert_exts[i].type < CERT_TYPE_MAX; i++) {
William Lallemand8f840d72019-10-23 10:53:05 +020010264 end = strrchr(buf->area, '.');
William Lallemand44b35322019-10-17 16:28:40 +020010265 if (end && *cert_exts[i].ext && (!strcmp(end + 1, cert_exts[i].ext))) {
10266 *end = '\0';
10267 type = cert_exts[i].type;
10268 break;
10269 }
10270 }
10271
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010272 appctx->ctx.ssl.old_ckchs = NULL;
10273 appctx->ctx.ssl.new_ckchs = NULL;
William Lallemand849eed62019-10-17 16:23:50 +020010274
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010275 /* if there is an ongoing transaction */
10276 if (ckchs_transaction.path) {
10277 /* 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 +020010278#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010279 if (ckchs_transaction.new_ckchs->multi) {
Emmanuel Hocdet40f2f1e2019-10-30 17:31:28 +010010280 char *end;
William Lallemand963b2e72019-10-14 11:38:36 +020010281 int j;
William Lallemand150bfa82019-09-19 17:12:49 +020010282
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010283 /* check if it was used in a bundle by removing the
William Lallemand963b2e72019-10-14 11:38:36 +020010284 * .dsa/.rsa/.ecdsa at the end of the filename */
William Lallemand8f840d72019-10-23 10:53:05 +020010285 end = strrchr(buf->area, '.');
Emmanuel Hocdet40f2f1e2019-10-30 17:31:28 +010010286 for (j = 0; end && j < SSL_SOCK_NUM_KEYTYPES; j++) {
William Lallemand963b2e72019-10-14 11:38:36 +020010287 if (!strcmp(end + 1, SSL_SOCK_KEYTYPE_NAMES[j])) {
10288 bundle = j; /* keep the type of certificate so we insert it at the right place */
10289 *end = '\0'; /* it's a bundle let's end the string*/
10290 break;
10291 }
William Lallemand150bfa82019-09-19 17:12:49 +020010292 }
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010293 if (bundle < 0) {
10294 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);
10295 errcode |= ERR_ALERT | ERR_FATAL;
10296 goto end;
10297 }
10298 }
10299#endif
10300
10301 /* if there is an ongoing transaction, check if this is the same file */
10302 if (strcmp(ckchs_transaction.path, buf->area) != 0) {
10303 memprintf(&err, "The ongoing transaction is about '%s' but you are trying to set '%s'\n", ckchs_transaction.path, buf->area);
10304 errcode |= ERR_ALERT | ERR_FATAL;
10305 goto end;
William Lallemand150bfa82019-09-19 17:12:49 +020010306 }
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010307
10308 appctx->ctx.ssl.old_ckchs = ckchs_transaction.new_ckchs;
10309
10310 } else {
10311 struct ckch_store *find_ckchs[2] = { NULL, NULL };
10312
10313 /* lookup for the certificate in the tree:
10314 * check if this is used as a bundle AND as a unique certificate */
10315 for (i = 0; i < 2; i++) {
10316
10317 if ((find_ckchs[i] = ckchs_lookup(buf->area)) != NULL) {
10318 /* only the bundle name is in the tree and you should
10319 * never update a bundle name, only a filename */
10320 if (bundle < 0 && find_ckchs[i]->multi) {
10321 /* we tried to look for a non-bundle and we found a bundle */
10322 memprintf(&err, "%s%s is a multi-cert bundle. Try updating %s.{dsa,rsa,ecdsa}\n",
10323 err ? err : "", args[3], args[3]);
10324 errcode |= ERR_ALERT | ERR_FATAL;
10325 goto end;
10326 }
William Lallemand3246d942019-11-04 14:02:11 +010010327 /* If we want a bundle but this is not a bundle
10328 * example: When you try to update <file>.rsa, but
10329 * <file> is a regular file */
10330 if (bundle >= 0 && find_ckchs[i]->multi == 0) {
10331 find_ckchs[i] = NULL;
10332 break;
10333 }
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010334 }
10335#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
10336 {
Emmanuel Hocdet40f2f1e2019-10-30 17:31:28 +010010337 char *end;
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010338 int j;
10339
10340 /* check if it was used in a bundle by removing the
10341 * .dsa/.rsa/.ecdsa at the end of the filename */
10342 end = strrchr(buf->area, '.');
Emmanuel Hocdet40f2f1e2019-10-30 17:31:28 +010010343 for (j = 0; end && j < SSL_SOCK_NUM_KEYTYPES; j++) {
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010344 if (!strcmp(end + 1, SSL_SOCK_KEYTYPE_NAMES[j])) {
10345 bundle = j; /* keep the type of certificate so we insert it at the right place */
10346 *end = '\0'; /* it's a bundle let's end the string*/
10347 break;
10348 }
10349 }
William Lallemand37031b82019-11-04 13:38:53 +010010350 if (bundle < 0) /* we didn't find a bundle extension */
10351 break;
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010352 }
William Lallemand963b2e72019-10-14 11:38:36 +020010353#else
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010354 /* bundles are not supported here, so we don't need to lookup again */
10355 break;
William Lallemand963b2e72019-10-14 11:38:36 +020010356#endif
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010357 }
10358
10359 if (find_ckchs[0] && find_ckchs[1]) {
10360 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",
10361 err ? err : "", find_ckchs[0]->path, find_ckchs[1]->path);
10362 errcode |= ERR_ALERT | ERR_FATAL;
10363 goto end;
10364 }
10365
10366 appctx->ctx.ssl.old_ckchs = find_ckchs[0] ? find_ckchs[0] : find_ckchs[1];
William Lallemand150bfa82019-09-19 17:12:49 +020010367 }
10368
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010369 if (!appctx->ctx.ssl.old_ckchs) {
10370 memprintf(&err, "%sCan't replace a certificate which is not referenced by the configuration!\n",
William Lallemand150bfa82019-09-19 17:12:49 +020010371 err ? err : "");
Emeric Brunf69ed1d2019-10-17 11:56:56 +020010372 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemand8f840d72019-10-23 10:53:05 +020010373 goto end;
William Lallemand150bfa82019-09-19 17:12:49 +020010374 }
10375
William Lallemand8a7fdf02019-11-04 10:59:32 +010010376 if (!appctx->ctx.ssl.path) {
10377 /* this is a new transaction, set the path of the transaction */
10378 appctx->ctx.ssl.path = strdup(appctx->ctx.ssl.old_ckchs->path);
10379 if (!appctx->ctx.ssl.path) {
10380 memprintf(&err, "%sCan't allocate memory\n", err ? err : "");
10381 errcode |= ERR_ALERT | ERR_FATAL;
10382 goto end;
10383 }
10384 }
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010385
10386 old_ckchs = appctx->ctx.ssl.old_ckchs;
10387
10388 /* TODO: handle filters */
10389 if (old_ckchs->filters) {
10390 memprintf(&err, "%sCertificates used in crt-list with filters are not supported!\n",
10391 err ? err : "");
10392 errcode |= ERR_ALERT | ERR_FATAL;
10393 goto end;
10394 }
10395
10396 /* duplicate the ckch store */
10397 new_ckchs = ckchs_dup(old_ckchs);
10398 if (!new_ckchs) {
10399 memprintf(&err, "%sCannot allocate memory!\n",
10400 err ? err : "");
10401 errcode |= ERR_ALERT | ERR_FATAL;
10402 goto end;
10403 }
10404
10405 if (!new_ckchs->multi)
10406 ckch = new_ckchs->ckch;
10407 else
10408 ckch = &new_ckchs->ckch[bundle];
10409
10410 /* appply the change on the duplicate */
10411 if (cert_exts[type].load(buf->area, payload, ckch, &err) != 0) {
10412 memprintf(&err, "%sCan't load the payload\n", err ? err : "");
10413 errcode |= ERR_ALERT | ERR_FATAL;
10414 goto end;
10415 }
10416
10417 appctx->ctx.ssl.new_ckchs = new_ckchs;
10418
10419 /* we succeed, we can save the ckchs in the transaction */
10420
10421 /* if there wasn't a transaction, update the old ckchs */
William Dauchyc8bb1532019-11-24 15:04:20 +010010422 if (!ckchs_transaction.old_ckchs) {
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010423 ckchs_transaction.old_ckchs = appctx->ctx.ssl.old_ckchs;
10424 ckchs_transaction.path = appctx->ctx.ssl.path;
10425 err = memprintf(&err, "Transaction created for certificate %s!\n", ckchs_transaction.path);
10426 } else {
10427 err = memprintf(&err, "Transaction updated for certificate %s!\n", ckchs_transaction.path);
10428
10429 }
10430
10431 /* free the previous ckchs if there was a transaction */
10432 ckchs_free(ckchs_transaction.new_ckchs);
10433
10434 ckchs_transaction.new_ckchs = appctx->ctx.ssl.new_ckchs;
10435
10436
William Lallemand8f840d72019-10-23 10:53:05 +020010437 /* creates the SNI ctxs later in the IO handler */
William Lallemand150bfa82019-09-19 17:12:49 +020010438
William Lallemand8f840d72019-10-23 10:53:05 +020010439end:
10440 free_trash_chunk(buf);
William Lallemand150bfa82019-09-19 17:12:49 +020010441
Emeric Brunf69ed1d2019-10-17 11:56:56 +020010442 if (errcode & ERR_CODE) {
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010443
10444 ckchs_free(appctx->ctx.ssl.new_ckchs);
10445 appctx->ctx.ssl.new_ckchs = NULL;
10446
10447 appctx->ctx.ssl.old_ckchs = NULL;
10448
10449 free(appctx->ctx.ssl.path);
10450 appctx->ctx.ssl.path = NULL;
10451
10452 HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
William Lallemand44b35322019-10-17 16:28:40 +020010453 return cli_dynerr(appctx, memprintf(&err, "%sCan't update %s!\n", err ? err : "", args[3]));
William Lallemand430413e2019-10-28 14:30:47 +010010454 } else {
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010455
10456 HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
10457 return cli_dynmsg(appctx, LOG_NOTICE, err);
William Lallemand430413e2019-10-28 14:30:47 +010010458 }
William Lallemand8f840d72019-10-23 10:53:05 +020010459 /* TODO: handle the ERR_WARN which are not handled because of the io_handler */
William Lallemand150bfa82019-09-19 17:12:49 +020010460}
10461
William Lallemand0bc9c8a2019-11-19 15:51:51 +010010462/* parsing function of 'abort ssl cert' */
10463static int cli_parse_abort_cert(char **args, char *payload, struct appctx *appctx, void *private)
10464{
10465 char *err = NULL;
10466
10467 if (!*args[3])
10468 return cli_err(appctx, "'abort ssl cert' expects a filename\n");
10469
10470 /* The operations on the CKCH architecture are locked so we can
10471 * manipulate ckch_store and ckch_inst */
10472 if (HA_SPIN_TRYLOCK(CKCH_LOCK, &ckch_lock))
10473 return cli_err(appctx, "Can't abort!\nOperations on certificates are currently locked!\n");
10474
10475 if (!ckchs_transaction.path) {
10476 memprintf(&err, "No ongoing transaction!\n");
10477 goto error;
10478 }
10479
10480 if (strcmp(ckchs_transaction.path, args[3]) != 0) {
10481 memprintf(&err, "The ongoing transaction is about '%s' but you are trying to abort a transaction for '%s'\n", ckchs_transaction.path, args[3]);
10482 goto error;
10483 }
10484
10485 /* Only free the ckchs there, because the SNI and instances were not generated yet */
10486 ckchs_free(ckchs_transaction.new_ckchs);
10487 ckchs_transaction.new_ckchs = NULL;
10488 ckchs_free(ckchs_transaction.old_ckchs);
10489 ckchs_transaction.old_ckchs = NULL;
10490 free(ckchs_transaction.path);
10491 ckchs_transaction.path = NULL;
10492
10493 HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
10494
10495 err = memprintf(&err, "Transaction aborted for certificate '%s'!\n", args[3]);
10496 return cli_dynmsg(appctx, LOG_NOTICE, err);
10497
10498error:
10499 HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
10500
10501 return cli_dynerr(appctx, err);
10502}
10503
Aurélien Nephtaliabbf6072018-04-18 13:26:46 +020010504static int cli_parse_set_ocspresponse(char **args, char *payload, struct appctx *appctx, void *private)
William Lallemand32af2032016-10-29 18:09:35 +020010505{
10506#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
10507 char *err = NULL;
Willy Tarreau1c913e42018-08-22 05:26:57 +020010508 int i, j, ret;
Aurélien Nephtali1e0867c2018-04-18 14:04:58 +020010509
10510 if (!payload)
10511 payload = args[3];
William Lallemand32af2032016-10-29 18:09:35 +020010512
10513 /* Expect one parameter: the new response in base64 encoding */
Willy Tarreau9d008692019-08-09 11:21:01 +020010514 if (!*payload)
10515 return cli_err(appctx, "'set ssl ocsp-response' expects response in base64 encoding.\n");
Aurélien Nephtali1e0867c2018-04-18 14:04:58 +020010516
10517 /* remove \r and \n from the payload */
10518 for (i = 0, j = 0; payload[i]; i++) {
10519 if (payload[i] == '\r' || payload[i] == '\n')
10520 continue;
10521 payload[j++] = payload[i];
10522 }
10523 payload[j] = 0;
William Lallemand32af2032016-10-29 18:09:35 +020010524
Willy Tarreau1c913e42018-08-22 05:26:57 +020010525 ret = base64dec(payload, j, trash.area, trash.size);
Willy Tarreau9d008692019-08-09 11:21:01 +020010526 if (ret < 0)
10527 return cli_err(appctx, "'set ssl ocsp-response' received invalid base64 encoded response.\n");
William Lallemand32af2032016-10-29 18:09:35 +020010528
Willy Tarreau1c913e42018-08-22 05:26:57 +020010529 trash.data = ret;
William Lallemand32af2032016-10-29 18:09:35 +020010530 if (ssl_sock_update_ocsp_response(&trash, &err)) {
Willy Tarreau9d008692019-08-09 11:21:01 +020010531 if (err)
10532 return cli_dynerr(appctx, memprintf(&err, "%s.\n", err));
10533 else
10534 return cli_err(appctx, "Failed to update OCSP response.\n");
William Lallemand32af2032016-10-29 18:09:35 +020010535 }
Willy Tarreau9d008692019-08-09 11:21:01 +020010536
10537 return cli_msg(appctx, LOG_INFO, "OCSP Response updated!\n");
William Lallemand32af2032016-10-29 18:09:35 +020010538#else
Willy Tarreau9d008692019-08-09 11:21:01 +020010539 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 +020010540#endif
10541
Nenad Merdanovicc31499d2019-03-23 11:00:32 +010010542}
10543
Willy Tarreau86a394e2019-05-09 14:15:32 +020010544#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000100fL)
Nenad Merdanovicc31499d2019-03-23 11:00:32 +010010545static inline int sample_conv_var2smp_str(const struct arg *arg, struct sample *smp)
10546{
10547 switch (arg->type) {
10548 case ARGT_STR:
10549 smp->data.type = SMP_T_STR;
10550 smp->data.u.str = arg->data.str;
10551 return 1;
10552 case ARGT_VAR:
10553 if (!vars_get_by_desc(&arg->data.var, smp))
10554 return 0;
10555 if (!sample_casts[smp->data.type][SMP_T_STR])
10556 return 0;
10557 if (!sample_casts[smp->data.type][SMP_T_STR](smp))
10558 return 0;
10559 return 1;
10560 default:
10561 return 0;
10562 }
10563}
10564
10565static int check_aes_gcm(struct arg *args, struct sample_conv *conv,
10566 const char *file, int line, char **err)
10567{
10568 switch(args[0].data.sint) {
10569 case 128:
10570 case 192:
10571 case 256:
10572 break;
10573 default:
10574 memprintf(err, "key size must be 128, 192 or 256 (bits).");
10575 return 0;
10576 }
10577 /* Try to decode a variable. */
10578 vars_check_arg(&args[1], NULL);
10579 vars_check_arg(&args[2], NULL);
10580 vars_check_arg(&args[3], NULL);
10581 return 1;
10582}
10583
10584/* Arguements: AES size in bits, nonce, key, tag. The last three arguments are base64 encoded */
10585static int sample_conv_aes_gcm_dec(const struct arg *arg_p, struct sample *smp, void *private)
10586{
10587 struct sample nonce, key, aead_tag;
10588 struct buffer *smp_trash, *smp_trash_alloc;
10589 EVP_CIPHER_CTX *ctx;
10590 int dec_size, ret;
10591
10592 smp_set_owner(&nonce, smp->px, smp->sess, smp->strm, smp->opt);
10593 if (!sample_conv_var2smp_str(&arg_p[1], &nonce))
10594 return 0;
10595
10596 smp_set_owner(&key, smp->px, smp->sess, smp->strm, smp->opt);
10597 if (!sample_conv_var2smp_str(&arg_p[2], &key))
10598 return 0;
10599
10600 smp_set_owner(&aead_tag, smp->px, smp->sess, smp->strm, smp->opt);
10601 if (!sample_conv_var2smp_str(&arg_p[3], &aead_tag))
10602 return 0;
10603
10604 smp_trash = get_trash_chunk();
10605 smp_trash_alloc = alloc_trash_chunk();
10606 if (!smp_trash_alloc)
10607 return 0;
10608
10609 ctx = EVP_CIPHER_CTX_new();
10610
10611 if (!ctx)
10612 goto err;
10613
10614 dec_size = base64dec(nonce.data.u.str.area, nonce.data.u.str.data, smp_trash->area, smp_trash->size);
10615 if (dec_size < 0)
10616 goto err;
10617 smp_trash->data = dec_size;
10618
10619 /* Set cipher type and mode */
10620 switch(arg_p[0].data.sint) {
10621 case 128:
10622 EVP_DecryptInit_ex(ctx, EVP_aes_128_gcm(), NULL, NULL, NULL);
10623 break;
10624 case 192:
10625 EVP_DecryptInit_ex(ctx, EVP_aes_192_gcm(), NULL, NULL, NULL);
10626 break;
10627 case 256:
10628 EVP_DecryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL);
10629 break;
10630 }
10631
10632 EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, smp_trash->data, NULL);
10633
10634 /* Initialise IV */
10635 if(!EVP_DecryptInit_ex(ctx, NULL, NULL, NULL, (unsigned char *) smp_trash->area))
10636 goto err;
10637
10638 dec_size = base64dec(key.data.u.str.area, key.data.u.str.data, smp_trash->area, smp_trash->size);
10639 if (dec_size < 0)
10640 goto err;
10641 smp_trash->data = dec_size;
10642
10643 /* Initialise key */
10644 if (!EVP_DecryptInit_ex(ctx, NULL, NULL, (unsigned char *) smp_trash->area, NULL))
10645 goto err;
10646
10647 if (!EVP_DecryptUpdate(ctx, (unsigned char *) smp_trash->area, (int *) &smp_trash->data,
10648 (unsigned char *) smp->data.u.str.area, (int) smp->data.u.str.data))
10649 goto err;
10650
10651 dec_size = base64dec(aead_tag.data.u.str.area, aead_tag.data.u.str.data, smp_trash_alloc->area, smp_trash_alloc->size);
10652 if (dec_size < 0)
10653 goto err;
10654 smp_trash_alloc->data = dec_size;
10655 dec_size = smp_trash->data;
10656
10657 EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, smp_trash_alloc->data, (void *) smp_trash_alloc->area);
10658 ret = EVP_DecryptFinal_ex(ctx, (unsigned char *) smp_trash->area + smp_trash->data, (int *) &smp_trash->data);
10659
10660 if (ret <= 0)
10661 goto err;
10662
10663 smp->data.u.str.data = dec_size + smp_trash->data;
10664 smp->data.u.str.area = smp_trash->area;
10665 smp->data.type = SMP_T_BIN;
10666 smp->flags &= ~SMP_F_CONST;
10667 free_trash_chunk(smp_trash_alloc);
10668 return 1;
10669
10670err:
10671 free_trash_chunk(smp_trash_alloc);
10672 return 0;
William Lallemand32af2032016-10-29 18:09:35 +020010673}
Nenad Merdanovicc31499d2019-03-23 11:00:32 +010010674# endif
William Lallemand32af2032016-10-29 18:09:35 +020010675
10676/* register cli keywords */
10677static struct cli_kw_list cli_kws = {{ },{
10678#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
10679 { { "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 +020010680 { { "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 +020010681#endif
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +010010682 { { "set", "ssl", "ocsp-response", NULL }, NULL, cli_parse_set_ocspresponse, NULL },
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010683 { { "set", "ssl", "cert", NULL }, "set ssl cert <certfile> <payload> : replace a certificate file", cli_parse_set_cert, NULL, NULL },
10684 { { "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 +010010685 { { "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 +020010686 { { NULL }, NULL, NULL, NULL }
10687}};
10688
Willy Tarreau0108d902018-11-25 19:14:37 +010010689INITCALL1(STG_REGISTER, cli_register_kw, &cli_kws);
William Lallemand32af2032016-10-29 18:09:35 +020010690
Willy Tarreau7875d092012-09-10 08:20:03 +020010691/* Note: must not be declared <const> as its list will be overwritten.
10692 * Please take care of keeping this list alphabetically sorted.
10693 */
Willy Tarreaudc13c112013-06-21 23:16:39 +020010694static struct sample_fetch_kw_list sample_fetch_keywords = {ILH, {
Emeric Brun645ae792014-04-30 14:21:06 +020010695 { "ssl_bc", smp_fetch_ssl_fc, 0, NULL, SMP_T_BOOL, SMP_USE_L5SRV },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +020010696 { "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 +010010697#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Jérôme Magnine064a802018-12-03 22:21:04 +010010698 { "ssl_bc_alpn", smp_fetch_ssl_fc_alpn, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
Olivier Houchard6b77f492018-11-22 18:18:29 +010010699#endif
Emeric Brun645ae792014-04-30 14:21:06 +020010700 { "ssl_bc_cipher", smp_fetch_ssl_fc_cipher, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
Olivier Houchard6b77f492018-11-22 18:18:29 +010010701#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
10702 { "ssl_bc_npn", smp_fetch_ssl_fc_npn, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
10703#endif
Emeric Brun74f7ffa2018-02-19 16:14:12 +010010704 { "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 +020010705 { "ssl_bc_protocol", smp_fetch_ssl_fc_protocol, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
Emeric Brunb73a9b02014-04-30 18:49:19 +020010706 { "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 +020010707 { "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 +020010708#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
Emeric Brun645ae792014-04-30 14:21:06 +020010709 { "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 -040010710#endif
Emmanuel Hocdet839af572019-05-14 16:27:35 +020010711#if HA_OPENSSL_VERSION_NUMBER >= 0x10100000L
Patrick Hemmer65674662019-06-04 08:13:03 -040010712 { "ssl_bc_client_random", smp_fetch_ssl_fc_random, 0, NULL, SMP_T_BIN, SMP_USE_L5SRV },
10713 { "ssl_bc_server_random", smp_fetch_ssl_fc_random, 0, NULL, SMP_T_BIN, SMP_USE_L5SRV },
Patrick Hemmere0275472018-04-28 19:15:51 -040010714 { "ssl_bc_session_key", smp_fetch_ssl_fc_session_key, 0, NULL, SMP_T_BIN, SMP_USE_L5SRV },
10715#endif
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +020010716 { "ssl_c_ca_err", smp_fetch_ssl_c_ca_err, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
10717 { "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 +010010718 { "ssl_c_der", smp_fetch_ssl_x_der, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +020010719 { "ssl_c_err", smp_fetch_ssl_c_err, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Emeric Brunba841a12014-04-30 17:05:08 +020010720 { "ssl_c_i_dn", smp_fetch_ssl_x_i_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
10721 { "ssl_c_key_alg", smp_fetch_ssl_x_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
10722 { "ssl_c_notafter", smp_fetch_ssl_x_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
10723 { "ssl_c_notbefore", smp_fetch_ssl_x_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
10724 { "ssl_c_sig_alg", smp_fetch_ssl_x_sig_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
10725 { "ssl_c_s_dn", smp_fetch_ssl_x_s_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
10726 { "ssl_c_serial", smp_fetch_ssl_x_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
10727 { "ssl_c_sha1", smp_fetch_ssl_x_sha1, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +010010728 { "ssl_c_used", smp_fetch_ssl_c_used, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +020010729 { "ssl_c_verify", smp_fetch_ssl_c_verify, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
10730 { "ssl_c_version", smp_fetch_ssl_x_version, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Emeric Brun43e79582014-10-29 19:03:26 +010010731 { "ssl_f_der", smp_fetch_ssl_x_der, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Emeric Brunba841a12014-04-30 17:05:08 +020010732 { "ssl_f_i_dn", smp_fetch_ssl_x_i_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
10733 { "ssl_f_key_alg", smp_fetch_ssl_x_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
10734 { "ssl_f_notafter", smp_fetch_ssl_x_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
10735 { "ssl_f_notbefore", smp_fetch_ssl_x_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
10736 { "ssl_f_sig_alg", smp_fetch_ssl_x_sig_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
10737 { "ssl_f_s_dn", smp_fetch_ssl_x_s_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
10738 { "ssl_f_serial", smp_fetch_ssl_x_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Emeric Brun55f4fa82014-04-30 17:11:25 +020010739 { "ssl_f_sha1", smp_fetch_ssl_x_sha1, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +020010740 { "ssl_f_version", smp_fetch_ssl_x_version, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +010010741 { "ssl_fc", smp_fetch_ssl_fc, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +020010742 { "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 +010010743 { "ssl_fc_cipher", smp_fetch_ssl_fc_cipher, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +010010744 { "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 +020010745 { "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 +010010746 { "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 +020010747 { "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 +010010748#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +010010749 { "ssl_fc_npn", smp_fetch_ssl_fc_npn, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreaua33c6542012-10-15 13:19:06 +020010750#endif
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +010010751#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +010010752 { "ssl_fc_alpn", smp_fetch_ssl_fc_alpn, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreauab861d32013-04-02 02:30:41 +020010753#endif
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +010010754 { "ssl_fc_protocol", smp_fetch_ssl_fc_protocol, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreau9a1ab082019-05-09 13:26:41 +020010755#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
Emeric Brunb73a9b02014-04-30 18:49:19 +020010756 { "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 -040010757#endif
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +020010758 { "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 +020010759#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +010010760 { "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 -040010761#endif
Emmanuel Hocdet839af572019-05-14 16:27:35 +020010762#if HA_OPENSSL_VERSION_NUMBER >= 0x10100000L
Patrick Hemmer65674662019-06-04 08:13:03 -040010763 { "ssl_fc_client_random", smp_fetch_ssl_fc_random, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
10764 { "ssl_fc_server_random", smp_fetch_ssl_fc_random, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Patrick Hemmere0275472018-04-28 19:15:51 -040010765 { "ssl_fc_session_key", smp_fetch_ssl_fc_session_key, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
10766#endif
Patrick Hemmer41966772018-04-28 19:15:48 -040010767#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +010010768 { "ssl_fc_sni", smp_fetch_ssl_fc_sni, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Patrick Hemmer41966772018-04-28 19:15:48 -040010769#endif
Thierry FOURNIER5bf77322017-02-25 12:45:22 +010010770 { "ssl_fc_cipherlist_bin", smp_fetch_ssl_fc_cl_bin, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
10771 { "ssl_fc_cipherlist_hex", smp_fetch_ssl_fc_cl_hex, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
10772 { "ssl_fc_cipherlist_str", smp_fetch_ssl_fc_cl_str, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
10773 { "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 +020010774 { NULL, NULL, 0, 0, 0 },
10775}};
10776
Willy Tarreau0108d902018-11-25 19:14:37 +010010777INITCALL1(STG_REGISTER, sample_register_fetches, &sample_fetch_keywords);
10778
Willy Tarreau7875d092012-09-10 08:20:03 +020010779/* Note: must not be declared <const> as its list will be overwritten.
10780 * Please take care of keeping this list alphabetically sorted.
10781 */
Willy Tarreaudc13c112013-06-21 23:16:39 +020010782static struct acl_kw_list acl_kws = {ILH, {
Thierry FOURNIERc5a4e982014-03-05 16:07:08 +010010783 { "ssl_fc_sni_end", "ssl_fc_sni", PAT_MATCH_END },
10784 { "ssl_fc_sni_reg", "ssl_fc_sni", PAT_MATCH_REG },
Willy Tarreau8ed669b2013-01-11 15:49:37 +010010785 { /* END */ },
Willy Tarreau7875d092012-09-10 08:20:03 +020010786}};
10787
Willy Tarreau0108d902018-11-25 19:14:37 +010010788INITCALL1(STG_REGISTER, acl_register_keywords, &acl_kws);
10789
Willy Tarreau79eeafa2012-09-14 07:53:05 +020010790/* Note: must not be declared <const> as its list will be overwritten.
10791 * Please take care of keeping this list alphabetically sorted, doing so helps
10792 * all code contributors.
10793 * Optional keywords are also declared with a NULL ->parse() function so that
10794 * the config parser can report an appropriate error when a known keyword was
10795 * not enabled.
10796 */
Emmanuel Hocdet98263292016-12-29 18:26:15 +010010797static struct ssl_bind_kw ssl_bind_kws[] = {
Olivier Houchardc2aae742017-09-22 18:26:28 +020010798 { "allow-0rtt", ssl_bind_parse_allow_0rtt, 0 }, /* allow 0-RTT */
Emmanuel Hocdet98263292016-12-29 18:26:15 +010010799 { "alpn", ssl_bind_parse_alpn, 1 }, /* set ALPN supported protocols */
10800 { "ca-file", ssl_bind_parse_ca_file, 1 }, /* set CAfile to process verify on client cert */
10801 { "ciphers", ssl_bind_parse_ciphers, 1 }, /* set SSL cipher suite */
Emmanuel Hocdet839af572019-05-14 16:27:35 +020010802#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +020010803 { "ciphersuites", ssl_bind_parse_ciphersuites, 1 }, /* set TLS 1.3 cipher suite */
10804#endif
Emmanuel Hocdet98263292016-12-29 18:26:15 +010010805 { "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 +010010806 { "curves", ssl_bind_parse_curves, 1 }, /* set SSL curve suite */
Emmanuel Hocdet98263292016-12-29 18:26:15 +010010807 { "ecdhe", ssl_bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +020010808 { "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 +010010809 { "npn", ssl_bind_parse_npn, 1 }, /* set NPN supported protocols */
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +020010810 { "ssl-min-ver", ssl_bind_parse_tls_method_minmax,1 }, /* minimum version */
10811 { "ssl-max-ver", ssl_bind_parse_tls_method_minmax,1 }, /* maximum version */
Emmanuel Hocdet98263292016-12-29 18:26:15 +010010812 { "verify", ssl_bind_parse_verify, 1 }, /* set SSL verify method */
10813 { NULL, NULL, 0 },
10814};
10815
Willy Tarreau0108d902018-11-25 19:14:37 +010010816/* no initcall for ssl_bind_kws, these ones are parsed in the parser loop */
10817
Willy Tarreau51fb7652012-09-18 18:24:39 +020010818static struct bind_kw_list bind_kws = { "SSL", { }, {
Olivier Houchardc2aae742017-09-22 18:26:28 +020010819 { "allow-0rtt", bind_parse_allow_0rtt, 0 }, /* Allow 0RTT */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +020010820 { "alpn", bind_parse_alpn, 1 }, /* set ALPN supported protocols */
10821 { "ca-file", bind_parse_ca_file, 1 }, /* set CAfile to process verify on client cert */
10822 { "ca-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ignore on verify depth > 0 */
10823 { "ca-sign-file", bind_parse_ca_sign_file, 1 }, /* set CAFile used to generate and sign server certs */
10824 { "ca-sign-pass", bind_parse_ca_sign_pass, 1 }, /* set CAKey passphrase */
10825 { "ciphers", bind_parse_ciphers, 1 }, /* set SSL cipher suite */
Emmanuel Hocdet839af572019-05-14 16:27:35 +020010826#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +020010827 { "ciphersuites", bind_parse_ciphersuites, 1 }, /* set TLS 1.3 cipher suite */
10828#endif
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +020010829 { "crl-file", bind_parse_crl_file, 1 }, /* set certificat revocation list file use on client cert verify */
10830 { "crt", bind_parse_crt, 1 }, /* load SSL certificates from this location */
10831 { "crt-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ingore on verify depth == 0 */
10832 { "crt-list", bind_parse_crt_list, 1 }, /* load a list of crt from this location */
10833 { "curves", bind_parse_curves, 1 }, /* set SSL curve suite */
10834 { "ecdhe", bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
10835 { "force-sslv3", bind_parse_tls_method_options, 0 }, /* force SSLv3 */
10836 { "force-tlsv10", bind_parse_tls_method_options, 0 }, /* force TLSv10 */
10837 { "force-tlsv11", bind_parse_tls_method_options, 0 }, /* force TLSv11 */
10838 { "force-tlsv12", bind_parse_tls_method_options, 0 }, /* force TLSv12 */
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +020010839 { "force-tlsv13", bind_parse_tls_method_options, 0 }, /* force TLSv13 */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +020010840 { "generate-certificates", bind_parse_generate_certs, 0 }, /* enable the server certificates generation */
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +020010841 { "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 +020010842 { "no-sslv3", bind_parse_tls_method_options, 0 }, /* disable SSLv3 */
10843 { "no-tlsv10", bind_parse_tls_method_options, 0 }, /* disable TLSv10 */
10844 { "no-tlsv11", bind_parse_tls_method_options, 0 }, /* disable TLSv11 */
10845 { "no-tlsv12", bind_parse_tls_method_options, 0 }, /* disable TLSv12 */
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +020010846 { "no-tlsv13", bind_parse_tls_method_options, 0 }, /* disable TLSv13 */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +020010847 { "no-tls-tickets", bind_parse_no_tls_tickets, 0 }, /* disable session resumption tickets */
10848 { "ssl", bind_parse_ssl, 0 }, /* enable SSL processing */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +020010849 { "ssl-min-ver", bind_parse_tls_method_minmax, 1 }, /* minimum version */
10850 { "ssl-max-ver", bind_parse_tls_method_minmax, 1 }, /* maximum version */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +020010851 { "strict-sni", bind_parse_strict_sni, 0 }, /* refuse negotiation if sni doesn't match a certificate */
10852 { "tls-ticket-keys", bind_parse_tls_ticket_keys, 1 }, /* set file to load TLS ticket keys from */
10853 { "verify", bind_parse_verify, 1 }, /* set SSL verify method */
10854 { "npn", bind_parse_npn, 1 }, /* set NPN supported protocols */
10855 { "prefer-client-ciphers", bind_parse_pcc, 0 }, /* prefer client ciphers */
Willy Tarreau79eeafa2012-09-14 07:53:05 +020010856 { NULL, NULL, 0 },
10857}};
Emeric Brun46591952012-05-18 15:47:34 +020010858
Willy Tarreau0108d902018-11-25 19:14:37 +010010859INITCALL1(STG_REGISTER, bind_register_keywords, &bind_kws);
10860
Willy Tarreau92faadf2012-10-10 23:04:25 +020010861/* Note: must not be declared <const> as its list will be overwritten.
10862 * Please take care of keeping this list alphabetically sorted, doing so helps
10863 * all code contributors.
10864 * Optional keywords are also declared with a NULL ->parse() function so that
10865 * the config parser can report an appropriate error when a known keyword was
10866 * not enabled.
10867 */
10868static struct srv_kw_list srv_kws = { "SSL", { }, {
Olivier Houchard522eea72017-11-03 16:27:47 +010010869 { "allow-0rtt", srv_parse_allow_0rtt, 0, 1 }, /* Allow using early data on this server */
Olivier Houchardc7566002018-11-20 23:33:50 +010010870 { "alpn", srv_parse_alpn, 1, 1 }, /* Set ALPN supported protocols */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +020010871 { "ca-file", srv_parse_ca_file, 1, 1 }, /* set CAfile to process verify server cert */
Olivier Houchard92150142018-12-21 19:47:01 +010010872 { "check-alpn", srv_parse_alpn, 1, 1 }, /* Set ALPN used for checks */
Olivier Houchard9130a962017-10-17 17:33:43 +020010873 { "check-sni", srv_parse_check_sni, 1, 1 }, /* set SNI */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +020010874 { "check-ssl", srv_parse_check_ssl, 0, 1 }, /* enable SSL for health checks */
10875 { "ciphers", srv_parse_ciphers, 1, 1 }, /* select the cipher suite */
Emmanuel Hocdet839af572019-05-14 16:27:35 +020010876#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +020010877 { "ciphersuites", srv_parse_ciphersuites, 1, 1 }, /* select the cipher suite */
10878#endif
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +020010879 { "crl-file", srv_parse_crl_file, 1, 1 }, /* set certificate revocation list file use on server cert verify */
10880 { "crt", srv_parse_crt, 1, 1 }, /* set client certificate */
10881 { "force-sslv3", srv_parse_tls_method_options, 0, 1 }, /* force SSLv3 */
10882 { "force-tlsv10", srv_parse_tls_method_options, 0, 1 }, /* force TLSv10 */
10883 { "force-tlsv11", srv_parse_tls_method_options, 0, 1 }, /* force TLSv11 */
10884 { "force-tlsv12", srv_parse_tls_method_options, 0, 1 }, /* force TLSv12 */
10885 { "force-tlsv13", srv_parse_tls_method_options, 0, 1 }, /* force TLSv13 */
10886 { "no-check-ssl", srv_parse_no_check_ssl, 0, 1 }, /* disable SSL for health checks */
10887 { "no-send-proxy-v2-ssl", srv_parse_no_send_proxy_ssl, 0, 1 }, /* do not send PROXY protocol header v2 with SSL info */
10888 { "no-send-proxy-v2-ssl-cn", srv_parse_no_send_proxy_cn, 0, 1 }, /* do not send PROXY protocol header v2 with CN */
10889 { "no-ssl", srv_parse_no_ssl, 0, 1 }, /* disable SSL processing */
10890 { "no-ssl-reuse", srv_parse_no_ssl_reuse, 0, 1 }, /* disable session reuse */
10891 { "no-sslv3", srv_parse_tls_method_options, 0, 0 }, /* disable SSLv3 */
10892 { "no-tlsv10", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv10 */
10893 { "no-tlsv11", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv11 */
10894 { "no-tlsv12", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv12 */
10895 { "no-tlsv13", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv13 */
10896 { "no-tls-tickets", srv_parse_no_tls_tickets, 0, 1 }, /* disable session resumption tickets */
Olivier Houchardc7566002018-11-20 23:33:50 +010010897 { "npn", srv_parse_npn, 1, 1 }, /* Set NPN supported protocols */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +020010898 { "send-proxy-v2-ssl", srv_parse_send_proxy_ssl, 0, 1 }, /* send PROXY protocol header v2 with SSL info */
10899 { "send-proxy-v2-ssl-cn", srv_parse_send_proxy_cn, 0, 1 }, /* send PROXY protocol header v2 with CN */
10900 { "sni", srv_parse_sni, 1, 1 }, /* send SNI extension */
10901 { "ssl", srv_parse_ssl, 0, 1 }, /* enable SSL processing */
10902 { "ssl-min-ver", srv_parse_tls_method_minmax, 1, 1 }, /* minimum version */
10903 { "ssl-max-ver", srv_parse_tls_method_minmax, 1, 1 }, /* maximum version */
10904 { "ssl-reuse", srv_parse_ssl_reuse, 0, 1 }, /* enable session reuse */
10905 { "tls-tickets", srv_parse_tls_tickets, 0, 1 }, /* enable session resumption tickets */
10906 { "verify", srv_parse_verify, 1, 1 }, /* set SSL verify method */
10907 { "verifyhost", srv_parse_verifyhost, 1, 1 }, /* require that SSL cert verifies for hostname */
Willy Tarreau92faadf2012-10-10 23:04:25 +020010908 { NULL, NULL, 0, 0 },
10909}};
10910
Willy Tarreau0108d902018-11-25 19:14:37 +010010911INITCALL1(STG_REGISTER, srv_register_keywords, &srv_kws);
10912
Emeric Brun2c86cbf2014-10-30 15:56:50 +010010913static struct cfg_kw_list cfg_kws = {ILH, {
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +010010914 { CFG_GLOBAL, "ca-base", ssl_parse_global_ca_crt_base },
10915 { CFG_GLOBAL, "crt-base", ssl_parse_global_ca_crt_base },
Willy Tarreau0bea58d2016-12-21 23:17:25 +010010916 { CFG_GLOBAL, "maxsslconn", ssl_parse_global_int },
Emeric Brun2c86cbf2014-10-30 15:56:50 +010010917 { CFG_GLOBAL, "ssl-default-bind-options", ssl_parse_default_bind_options },
10918 { CFG_GLOBAL, "ssl-default-server-options", ssl_parse_default_server_options },
Willy Tarreau14e36a12016-12-21 23:28:13 +010010919#ifndef OPENSSL_NO_DH
10920 { CFG_GLOBAL, "ssl-dh-param-file", ssl_parse_global_dh_param_file },
10921#endif
Grant Zhangfa6c7ee2017-01-14 01:42:15 +000010922 { CFG_GLOBAL, "ssl-mode-async", ssl_parse_global_ssl_async },
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020010923#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +000010924 { CFG_GLOBAL, "ssl-engine", ssl_parse_global_ssl_engine },
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020010925#endif
Willy Tarreau9ceda382016-12-21 23:13:03 +010010926 { CFG_GLOBAL, "tune.ssl.cachesize", ssl_parse_global_int },
10927#ifndef OPENSSL_NO_DH
10928 { CFG_GLOBAL, "tune.ssl.default-dh-param", ssl_parse_global_default_dh },
10929#endif
10930 { CFG_GLOBAL, "tune.ssl.force-private-cache", ssl_parse_global_private_cache },
10931 { CFG_GLOBAL, "tune.ssl.lifetime", ssl_parse_global_lifetime },
10932 { CFG_GLOBAL, "tune.ssl.maxrecord", ssl_parse_global_int },
10933 { CFG_GLOBAL, "tune.ssl.ssl-ctx-cache-size", ssl_parse_global_int },
Thierry FOURNIER5bf77322017-02-25 12:45:22 +010010934 { CFG_GLOBAL, "tune.ssl.capture-cipherlist-size", ssl_parse_global_capture_cipherlist },
Willy Tarreauf22e9682016-12-21 23:23:19 +010010935 { CFG_GLOBAL, "ssl-default-bind-ciphers", ssl_parse_global_ciphers },
10936 { CFG_GLOBAL, "ssl-default-server-ciphers", ssl_parse_global_ciphers },
Emmanuel Hocdet839af572019-05-14 16:27:35 +020010937#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +020010938 { CFG_GLOBAL, "ssl-default-bind-ciphersuites", ssl_parse_global_ciphersuites },
10939 { CFG_GLOBAL, "ssl-default-server-ciphersuites", ssl_parse_global_ciphersuites },
10940#endif
Emeric Brun2c86cbf2014-10-30 15:56:50 +010010941 { 0, NULL, NULL },
10942}};
10943
Willy Tarreau0108d902018-11-25 19:14:37 +010010944INITCALL1(STG_REGISTER, cfg_register_keywords, &cfg_kws);
10945
Nenad Merdanovicc31499d2019-03-23 11:00:32 +010010946/* Note: must not be declared <const> as its list will be overwritten */
10947static struct sample_conv_kw_list conv_kws = {ILH, {
Willy Tarreau86a394e2019-05-09 14:15:32 +020010948#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000100fL)
Nenad Merdanovicc31499d2019-03-23 11:00:32 +010010949 { "aes_gcm_dec", sample_conv_aes_gcm_dec, ARG4(4,SINT,STR,STR,STR), check_aes_gcm, SMP_T_BIN, SMP_T_BIN },
10950#endif
10951 { NULL, NULL, 0, 0, 0 },
10952}};
10953
10954INITCALL1(STG_REGISTER, sample_register_convs, &conv_kws);
10955
Willy Tarreauf7bc57c2012-10-03 00:19:48 +020010956/* transport-layer operations for SSL sockets */
Willy Tarreaud9f5cca2016-12-22 21:08:52 +010010957static struct xprt_ops ssl_sock = {
Emeric Brun46591952012-05-18 15:47:34 +020010958 .snd_buf = ssl_sock_from_buf,
10959 .rcv_buf = ssl_sock_to_buf,
Olivier Houcharddf357842019-03-21 16:30:07 +010010960 .subscribe = ssl_subscribe,
10961 .unsubscribe = ssl_unsubscribe,
Olivier Houchard5149b592019-05-23 17:47:36 +020010962 .remove_xprt = ssl_remove_xprt,
Olivier Houchard2e055482019-05-27 19:50:12 +020010963 .add_xprt = ssl_add_xprt,
Emeric Brun46591952012-05-18 15:47:34 +020010964 .rcv_pipe = NULL,
10965 .snd_pipe = NULL,
10966 .shutr = NULL,
10967 .shutw = ssl_sock_shutw,
10968 .close = ssl_sock_close,
10969 .init = ssl_sock_init,
Willy Tarreau55d37912016-12-21 23:38:39 +010010970 .prepare_bind_conf = ssl_sock_prepare_bind_conf,
Willy Tarreau795cdab2016-12-22 17:30:54 +010010971 .destroy_bind_conf = ssl_sock_destroy_bind_conf,
Willy Tarreau17d45382016-12-22 21:16:08 +010010972 .prepare_srv = ssl_sock_prepare_srv_ctx,
10973 .destroy_srv = ssl_sock_free_srv_ctx,
Willy Tarreau8743f7e2016-12-04 18:44:29 +010010974 .get_alpn = ssl_sock_get_alpn,
Willy Tarreau8e0bb0a2016-11-24 16:58:12 +010010975 .name = "SSL",
Emeric Brun46591952012-05-18 15:47:34 +020010976};
10977
Olivier Houchardccaa7de2017-10-02 11:51:03 +020010978enum act_return ssl_action_wait_for_hs(struct act_rule *rule, struct proxy *px,
10979 struct session *sess, struct stream *s, int flags)
10980{
10981 struct connection *conn;
Olivier Houchard6fa63d92017-11-27 18:41:32 +010010982 struct conn_stream *cs;
Olivier Houchardccaa7de2017-10-02 11:51:03 +020010983
10984 conn = objt_conn(sess->origin);
Olivier Houchard6fa63d92017-11-27 18:41:32 +010010985 cs = objt_cs(s->si[0].end);
Olivier Houchardccaa7de2017-10-02 11:51:03 +020010986
Olivier Houchard6fa63d92017-11-27 18:41:32 +010010987 if (conn && cs) {
Olivier Houchardccaa7de2017-10-02 11:51:03 +020010988 if (conn->flags & (CO_FL_EARLY_SSL_HS | CO_FL_SSL_WAIT_HS)) {
Olivier Houchard6fa63d92017-11-27 18:41:32 +010010989 cs->flags |= CS_FL_WAIT_FOR_HS;
Olivier Houchardccaa7de2017-10-02 11:51:03 +020010990 s->req.flags |= CF_READ_NULL;
10991 return ACT_RET_YIELD;
10992 }
10993 }
10994 return (ACT_RET_CONT);
10995}
10996
10997static enum act_parse_ret ssl_parse_wait_for_hs(const char **args, int *orig_arg, struct proxy *px, struct act_rule *rule, char **err)
10998{
10999 rule->action_ptr = ssl_action_wait_for_hs;
11000
11001 return ACT_RET_PRS_OK;
11002}
11003
11004static struct action_kw_list http_req_actions = {ILH, {
11005 { "wait-for-handshake", ssl_parse_wait_for_hs },
11006 { /* END */ }
11007}};
11008
Willy Tarreau0108d902018-11-25 19:14:37 +010011009INITCALL1(STG_REGISTER, http_req_keywords_register, &http_req_actions);
11010
Willy Tarreau5db847a2019-05-09 14:13:35 +020011011#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +010011012
11013static void ssl_sock_sctl_free_func(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, long argl, void *argp)
11014{
11015 if (ptr) {
11016 chunk_destroy(ptr);
11017 free(ptr);
11018 }
11019}
11020
11021#endif
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +010011022static void ssl_sock_capture_free_func(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, long argl, void *argp)
11023{
Willy Tarreaubafbe012017-11-24 17:34:44 +010011024 pool_free(pool_head_ssl_capture, ptr);
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +010011025}
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +010011026
Emeric Brun46591952012-05-18 15:47:34 +020011027__attribute__((constructor))
Willy Tarreau92faadf2012-10-10 23:04:25 +020011028static void __ssl_sock_init(void)
11029{
Ilya Shipitsin0590f442019-05-25 19:30:50 +050011030#if (!defined(OPENSSL_NO_COMP) && !defined(SSL_OP_NO_COMPRESSION))
Emeric Brun46591952012-05-18 15:47:34 +020011031 STACK_OF(SSL_COMP)* cm;
Ilya Shipitsine242f3d2019-05-25 03:38:14 +050011032 int n;
Ilya Shipitsin0590f442019-05-25 19:30:50 +050011033#endif
Emeric Brun46591952012-05-18 15:47:34 +020011034
Willy Tarreauef934602016-12-22 23:12:01 +010011035 if (global_ssl.listen_default_ciphers)
11036 global_ssl.listen_default_ciphers = strdup(global_ssl.listen_default_ciphers);
11037 if (global_ssl.connect_default_ciphers)
11038 global_ssl.connect_default_ciphers = strdup(global_ssl.connect_default_ciphers);
Emmanuel Hocdet839af572019-05-14 16:27:35 +020011039#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +020011040 if (global_ssl.listen_default_ciphersuites)
11041 global_ssl.listen_default_ciphersuites = strdup(global_ssl.listen_default_ciphersuites);
11042 if (global_ssl.connect_default_ciphersuites)
11043 global_ssl.connect_default_ciphersuites = strdup(global_ssl.connect_default_ciphersuites);
11044#endif
Willy Tarreau610f04b2014-02-13 11:36:41 +010011045
Willy Tarreau13e14102016-12-22 20:25:26 +010011046 xprt_register(XPRT_SSL, &ssl_sock);
Willy Tarreau9a1ab082019-05-09 13:26:41 +020011047#if HA_OPENSSL_VERSION_NUMBER < 0x10100000L
Emeric Brun46591952012-05-18 15:47:34 +020011048 SSL_library_init();
Rosen Penev68185952018-12-14 08:47:02 -080011049#endif
Ilya Shipitsin0590f442019-05-25 19:30:50 +050011050#if (!defined(OPENSSL_NO_COMP) && !defined(SSL_OP_NO_COMPRESSION))
Emeric Brun46591952012-05-18 15:47:34 +020011051 cm = SSL_COMP_get_compression_methods();
Ilya Shipitsine242f3d2019-05-25 03:38:14 +050011052 n = sk_SSL_COMP_num(cm);
11053 while (n--) {
11054 (void) sk_SSL_COMP_pop(cm);
11055 }
Ilya Shipitsin0590f442019-05-25 19:30:50 +050011056#endif
Ilya Shipitsine242f3d2019-05-25 03:38:14 +050011057
Willy Tarreau5db847a2019-05-09 14:13:35 +020011058#if defined(USE_THREAD) && (HA_OPENSSL_VERSION_NUMBER < 0x10100000L)
Emeric Brun821bb9b2017-06-15 16:37:39 +020011059 ssl_locking_init();
11060#endif
Willy Tarreau5db847a2019-05-09 14:13:35 +020011061#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +010011062 sctl_ex_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, ssl_sock_sctl_free_func);
11063#endif
Thierry FOURNIER28962c92018-06-17 21:37:05 +020011064 ssl_app_data_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL);
Thierry FOURNIER16ff0502018-06-17 21:33:01 +020011065 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 +020011066#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +000011067 ENGINE_load_builtin_engines();
Grant Zhangfa6c7ee2017-01-14 01:42:15 +000011068 hap_register_post_check(ssl_check_async_engine_count);
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020011069#endif
Willy Tarreaud1c57502016-12-22 22:46:15 +010011070#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
11071 hap_register_post_check(tlskeys_finalize_config);
11072#endif
Willy Tarreau80713382018-11-26 10:19:54 +010011073
11074 global.ssl_session_max_cost = SSL_SESSION_MAX_COST;
11075 global.ssl_handshake_max_cost = SSL_HANDSHAKE_MAX_COST;
11076
11077#ifndef OPENSSL_NO_DH
11078 ssl_dh_ptr_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, NULL);
11079 hap_register_post_deinit(ssl_free_dh);
11080#endif
11081#ifndef OPENSSL_NO_ENGINE
11082 hap_register_post_deinit(ssl_free_engines);
11083#endif
11084 /* Load SSL string for the verbose & debug mode. */
11085 ERR_load_SSL_strings();
Olivier Houcharda8955d52019-04-07 22:00:38 +020011086 ha_meth = BIO_meth_new(0x666, "ha methods");
11087 BIO_meth_set_write(ha_meth, ha_ssl_write);
11088 BIO_meth_set_read(ha_meth, ha_ssl_read);
11089 BIO_meth_set_ctrl(ha_meth, ha_ssl_ctrl);
11090 BIO_meth_set_create(ha_meth, ha_ssl_new);
11091 BIO_meth_set_destroy(ha_meth, ha_ssl_free);
11092 BIO_meth_set_puts(ha_meth, ha_ssl_puts);
11093 BIO_meth_set_gets(ha_meth, ha_ssl_gets);
William Lallemand150bfa82019-09-19 17:12:49 +020011094
11095 HA_SPIN_INIT(&ckch_lock);
Willy Tarreau80713382018-11-26 10:19:54 +010011096}
Willy Tarreaud92aa5c2015-01-15 21:34:39 +010011097
Willy Tarreau80713382018-11-26 10:19:54 +010011098/* Compute and register the version string */
11099static void ssl_register_build_options()
11100{
11101 char *ptr = NULL;
11102 int i;
11103
Willy Tarreauc2c0b612016-12-21 19:23:20 +010011104 memprintf(&ptr, "Built with OpenSSL version : "
11105#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet50e25e12017-03-24 15:20:03 +010011106 "BoringSSL");
Willy Tarreauc2c0b612016-12-21 19:23:20 +010011107#else /* OPENSSL_IS_BORINGSSL */
11108 OPENSSL_VERSION_TEXT
11109 "\nRunning on OpenSSL version : %s%s",
Rosen Penev68185952018-12-14 08:47:02 -080011110 OpenSSL_version(OPENSSL_VERSION),
Willy Tarreau1d158ab2019-05-09 13:41:45 +020011111 ((OPENSSL_VERSION_NUMBER ^ OpenSSL_version_num()) >> 8) ? " (VERSIONS DIFFER!)" : "");
Willy Tarreauc2c0b612016-12-21 19:23:20 +010011112#endif
11113 memprintf(&ptr, "%s\nOpenSSL library supports TLS extensions : "
Willy Tarreau9a1ab082019-05-09 13:26:41 +020011114#if HA_OPENSSL_VERSION_NUMBER < 0x00907000L
Willy Tarreauc2c0b612016-12-21 19:23:20 +010011115 "no (library version too old)"
11116#elif defined(OPENSSL_NO_TLSEXT)
11117 "no (disabled via OPENSSL_NO_TLSEXT)"
11118#else
11119 "yes"
11120#endif
11121 "", ptr);
11122
11123 memprintf(&ptr, "%s\nOpenSSL library supports SNI : "
11124#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
11125 "yes"
11126#else
11127#ifdef OPENSSL_NO_TLSEXT
11128 "no (because of OPENSSL_NO_TLSEXT)"
11129#else
11130 "no (version might be too old, 0.9.8f min needed)"
11131#endif
11132#endif
11133 "", ptr);
11134
Emmanuel Hocdetf80bc242017-07-12 14:25:38 +020011135 memprintf(&ptr, "%s\nOpenSSL library supports :", ptr);
11136 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
11137 if (methodVersions[i].option)
11138 memprintf(&ptr, "%s %s", ptr, methodVersions[i].name);
Emmanuel Hocdet50e25e12017-03-24 15:20:03 +010011139
Willy Tarreauc2c0b612016-12-21 19:23:20 +010011140 hap_register_build_opts(ptr, 1);
Willy Tarreau80713382018-11-26 10:19:54 +010011141}
Willy Tarreauc2c0b612016-12-21 19:23:20 +010011142
Willy Tarreau80713382018-11-26 10:19:54 +010011143INITCALL0(STG_REGISTER, ssl_register_build_options);
Remi Gacogne4f902b82015-05-28 16:23:00 +020011144
Emeric Brun46591952012-05-18 15:47:34 +020011145
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020011146#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +000011147void ssl_free_engines(void) {
11148 struct ssl_engine_list *wl, *wlb;
11149 /* free up engine list */
11150 list_for_each_entry_safe(wl, wlb, &openssl_engines, list) {
11151 ENGINE_finish(wl->e);
11152 ENGINE_free(wl->e);
11153 LIST_DEL(&wl->list);
11154 free(wl);
11155 }
11156}
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020011157#endif
Christopher Faulet31af49d2015-06-09 17:29:50 +020011158
Remi Gacogned3a23c32015-05-28 16:39:47 +020011159#ifndef OPENSSL_NO_DH
Grant Zhang872f9c22017-01-21 01:10:18 +000011160void ssl_free_dh(void) {
11161 if (local_dh_1024) {
11162 DH_free(local_dh_1024);
11163 local_dh_1024 = NULL;
11164 }
11165 if (local_dh_2048) {
11166 DH_free(local_dh_2048);
11167 local_dh_2048 = NULL;
11168 }
11169 if (local_dh_4096) {
11170 DH_free(local_dh_4096);
11171 local_dh_4096 = NULL;
11172 }
Remi Gacogne47783ef2015-05-29 15:53:22 +020011173 if (global_dh) {
11174 DH_free(global_dh);
11175 global_dh = NULL;
11176 }
Grant Zhang872f9c22017-01-21 01:10:18 +000011177}
11178#endif
11179
11180__attribute__((destructor))
11181static void __ssl_sock_deinit(void)
11182{
11183#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Emeric Brun821bb9b2017-06-15 16:37:39 +020011184 if (ssl_ctx_lru_tree) {
11185 lru64_destroy(ssl_ctx_lru_tree);
Christopher Faulet2a944ee2017-11-07 10:42:54 +010011186 HA_RWLOCK_DESTROY(&ssl_ctx_lru_rwlock);
Emeric Brun821bb9b2017-06-15 16:37:39 +020011187 }
Remi Gacogned3a23c32015-05-28 16:39:47 +020011188#endif
11189
Willy Tarreau5db847a2019-05-09 14:13:35 +020011190#if (HA_OPENSSL_VERSION_NUMBER < 0x10100000L)
Remi Gacogned3a23c32015-05-28 16:39:47 +020011191 ERR_remove_state(0);
11192 ERR_free_strings();
11193
11194 EVP_cleanup();
Rosen Penev68185952018-12-14 08:47:02 -080011195#endif
Remi Gacogned3a23c32015-05-28 16:39:47 +020011196
Willy Tarreau5db847a2019-05-09 14:13:35 +020011197#if (HA_OPENSSL_VERSION_NUMBER >= 0x00907000L) && (HA_OPENSSL_VERSION_NUMBER < 0x10100000L)
Remi Gacogned3a23c32015-05-28 16:39:47 +020011198 CRYPTO_cleanup_all_ex_data();
11199#endif
Olivier Houcharda8955d52019-04-07 22:00:38 +020011200 BIO_meth_free(ha_meth);
Remi Gacogned3a23c32015-05-28 16:39:47 +020011201}
11202
11203
Emeric Brun46591952012-05-18 15:47:34 +020011204/*
11205 * Local variables:
11206 * c-indent-level: 8
11207 * c-basic-offset: 8
11208 * End:
11209 */