blob: 7698eec7fbb2b1b8a5545abc322881a15e29cc23 [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
William Lallemand3af48e72020-02-03 17:15:52 +0100127/* file to guess during file loading */
128#define SSL_GF_NONE 0x00000000 /* Don't guess any file, only open the files specified in the configuration files */
129#define SSL_GF_BUNDLE 0x00000001 /* try to open the bundles */
130#define SSL_GF_SCTL 0x00000002 /* try to open the .sctl file */
131#define SSL_GF_OCSP 0x00000004 /* try to open the .ocsp file */
132#define SSL_GF_OCSP_ISSUER 0x00000008 /* try to open the .issuer file if an OCSP file was loaded */
133
134#define SSL_GF_ALL (SSL_GF_BUNDLE|SSL_GF_SCTL|SSL_GF_OCSP|SSL_GF_OCSP_ISSUER)
135
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200136/* ssl_methods versions */
137enum {
138 CONF_TLSV_NONE = 0,
139 CONF_TLSV_MIN = 1,
140 CONF_SSLV3 = 1,
141 CONF_TLSV10 = 2,
142 CONF_TLSV11 = 3,
143 CONF_TLSV12 = 4,
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +0200144 CONF_TLSV13 = 5,
145 CONF_TLSV_MAX = 5,
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200146};
147
Emeric Brun850efd52014-01-29 12:24:34 +0100148/* server and bind verify method, it uses a global value as default */
149enum {
150 SSL_SOCK_VERIFY_DEFAULT = 0,
151 SSL_SOCK_VERIFY_REQUIRED = 1,
152 SSL_SOCK_VERIFY_OPTIONAL = 2,
153 SSL_SOCK_VERIFY_NONE = 3,
154};
155
William Lallemand3f85c9a2017-10-09 16:30:50 +0200156
Willy Tarreau71b734c2014-01-28 15:19:44 +0100157int sslconns = 0;
158int totalsslconns = 0;
Willy Tarreaud9f5cca2016-12-22 21:08:52 +0100159static struct xprt_ops ssl_sock;
Emeric Brunece0c332017-12-06 13:51:49 +0100160int nb_engines = 0;
Emeric Brune1f38db2012-09-03 20:36:47 +0200161
Willy Tarreauef934602016-12-22 23:12:01 +0100162static struct {
163 char *crt_base; /* base directory path for certificates */
164 char *ca_base; /* base directory path for CAs and CRLs */
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000165 int async; /* whether we use ssl async mode */
Willy Tarreauef934602016-12-22 23:12:01 +0100166
167 char *listen_default_ciphers;
168 char *connect_default_ciphers;
Emmanuel Hocdet839af572019-05-14 16:27:35 +0200169#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +0200170 char *listen_default_ciphersuites;
171 char *connect_default_ciphersuites;
172#endif
Willy Tarreauef934602016-12-22 23:12:01 +0100173 int listen_default_ssloptions;
174 int connect_default_ssloptions;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200175 struct tls_version_filter listen_default_sslmethods;
176 struct tls_version_filter connect_default_sslmethods;
Willy Tarreauef934602016-12-22 23:12:01 +0100177
178 int private_cache; /* Force to use a private session cache even if nbproc > 1 */
179 unsigned int life_time; /* SSL session lifetime in seconds */
180 unsigned int max_record; /* SSL max record size */
181 unsigned int default_dh_param; /* SSL maximum DH parameter size */
182 int ctx_cache; /* max number of entries in the ssl_ctx cache. */
Thierry FOURNIER5bf77322017-02-25 12:45:22 +0100183 int capture_cipherlist; /* Size of the cipherlist buffer. */
William Lallemand3af48e72020-02-03 17:15:52 +0100184 int extra_files; /* which files not defined in the configuration file are we looking for */
Willy Tarreauef934602016-12-22 23:12:01 +0100185} global_ssl = {
186#ifdef LISTEN_DEFAULT_CIPHERS
187 .listen_default_ciphers = LISTEN_DEFAULT_CIPHERS,
188#endif
189#ifdef CONNECT_DEFAULT_CIPHERS
190 .connect_default_ciphers = CONNECT_DEFAULT_CIPHERS,
191#endif
Emmanuel Hocdet839af572019-05-14 16:27:35 +0200192#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +0200193#ifdef LISTEN_DEFAULT_CIPHERSUITES
194 .listen_default_ciphersuites = LISTEN_DEFAULT_CIPHERSUITES,
195#endif
196#ifdef CONNECT_DEFAULT_CIPHERSUITES
197 .connect_default_ciphersuites = CONNECT_DEFAULT_CIPHERSUITES,
198#endif
199#endif
Willy Tarreauef934602016-12-22 23:12:01 +0100200 .listen_default_ssloptions = BC_SSL_O_NONE,
201 .connect_default_ssloptions = SRV_SSL_O_NONE,
202
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200203 .listen_default_sslmethods.flags = MC_SSL_O_ALL,
204 .listen_default_sslmethods.min = CONF_TLSV_NONE,
205 .listen_default_sslmethods.max = CONF_TLSV_NONE,
206 .connect_default_sslmethods.flags = MC_SSL_O_ALL,
207 .connect_default_sslmethods.min = CONF_TLSV_NONE,
208 .connect_default_sslmethods.max = CONF_TLSV_NONE,
209
Willy Tarreauef934602016-12-22 23:12:01 +0100210#ifdef DEFAULT_SSL_MAX_RECORD
211 .max_record = DEFAULT_SSL_MAX_RECORD,
212#endif
213 .default_dh_param = SSL_DEFAULT_DH_PARAM,
214 .ctx_cache = DEFAULT_SSL_CTX_CACHE,
Thierry FOURNIER5bf77322017-02-25 12:45:22 +0100215 .capture_cipherlist = 0,
William Lallemand3af48e72020-02-03 17:15:52 +0100216 .extra_files = SSL_GF_ALL,
Willy Tarreauef934602016-12-22 23:12:01 +0100217};
218
Olivier Houcharda8955d52019-04-07 22:00:38 +0200219static BIO_METHOD *ha_meth;
220
Olivier Houchard66ab4982019-02-26 18:37:15 +0100221struct ssl_sock_ctx {
Olivier Houcharda8955d52019-04-07 22:00:38 +0200222 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +0100223 SSL *ssl;
Olivier Houcharda8955d52019-04-07 22:00:38 +0200224 BIO *bio;
Olivier Houchard5149b592019-05-23 17:47:36 +0200225 const struct xprt_ops *xprt;
Olivier Houchard66ab4982019-02-26 18:37:15 +0100226 void *xprt_ctx;
Olivier Houchardea8dd942019-05-20 14:02:16 +0200227 struct wait_event wait_event;
Willy Tarreau113d52b2020-01-10 09:20:26 +0100228 struct wait_event *subs;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +0100229 int xprt_st; /* transport layer state, initialized to zero */
Olivier Houchard54907bb2019-12-19 15:02:39 +0100230 struct buffer early_buf; /* buffer to store the early data received */
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +0100231 int sent_early_data; /* Amount of early data we sent so far */
232
Olivier Houchard66ab4982019-02-26 18:37:15 +0100233};
234
235DECLARE_STATIC_POOL(ssl_sock_ctx_pool, "ssl_sock_ctx_pool", sizeof(struct ssl_sock_ctx));
236
Olivier Houchardea8dd942019-05-20 14:02:16 +0200237static struct task *ssl_sock_io_cb(struct task *, void *, unsigned short);
Olivier Houchard000694c2019-05-23 14:45:12 +0200238static int ssl_sock_handshake(struct connection *conn, unsigned int flag);
Olivier Houchardea8dd942019-05-20 14:02:16 +0200239
Olivier Houcharda8955d52019-04-07 22:00:38 +0200240/* Methods to implement OpenSSL BIO */
241static int ha_ssl_write(BIO *h, const char *buf, int num)
242{
243 struct buffer tmpbuf;
244 struct ssl_sock_ctx *ctx;
245 int ret;
246
247 ctx = BIO_get_data(h);
248 tmpbuf.size = num;
249 tmpbuf.area = (void *)(uintptr_t)buf;
250 tmpbuf.data = num;
251 tmpbuf.head = 0;
252 ret = ctx->xprt->snd_buf(ctx->conn, ctx->xprt_ctx, &tmpbuf, num, 0);
Olivier Houchardb51937e2019-05-01 17:24:36 +0200253 if (ret == 0 && !(ctx->conn->flags & (CO_FL_ERROR | CO_FL_SOCK_WR_SH))) {
Olivier Houcharda8955d52019-04-07 22:00:38 +0200254 BIO_set_retry_write(h);
Olivier Houcharda28454e2019-04-24 12:04:36 +0200255 ret = -1;
Olivier Houchardb51937e2019-05-01 17:24:36 +0200256 } else if (ret == 0)
257 BIO_clear_retry_flags(h);
Olivier Houcharda8955d52019-04-07 22:00:38 +0200258 return ret;
259}
260
261static int ha_ssl_gets(BIO *h, char *buf, int size)
262{
263
264 return 0;
265}
266
267static int ha_ssl_puts(BIO *h, const char *str)
268{
269
270 return ha_ssl_write(h, str, strlen(str));
271}
272
273static int ha_ssl_read(BIO *h, char *buf, int size)
274{
275 struct buffer tmpbuf;
276 struct ssl_sock_ctx *ctx;
277 int ret;
278
279 ctx = BIO_get_data(h);
280 tmpbuf.size = size;
281 tmpbuf.area = buf;
282 tmpbuf.data = 0;
283 tmpbuf.head = 0;
284 ret = ctx->xprt->rcv_buf(ctx->conn, ctx->xprt_ctx, &tmpbuf, size, 0);
Olivier Houchardb51937e2019-05-01 17:24:36 +0200285 if (ret == 0 && !(ctx->conn->flags & (CO_FL_ERROR | CO_FL_SOCK_RD_SH))) {
Olivier Houcharda8955d52019-04-07 22:00:38 +0200286 BIO_set_retry_read(h);
Olivier Houcharda28454e2019-04-24 12:04:36 +0200287 ret = -1;
Olivier Houchardb51937e2019-05-01 17:24:36 +0200288 } else if (ret == 0)
289 BIO_clear_retry_flags(h);
Olivier Houcharda8955d52019-04-07 22:00:38 +0200290
291 return ret;
292}
293
294static long ha_ssl_ctrl(BIO *h, int cmd, long arg1, void *arg2)
295{
296 int ret = 0;
297 switch (cmd) {
298 case BIO_CTRL_DUP:
299 case BIO_CTRL_FLUSH:
300 ret = 1;
301 break;
302 }
303 return ret;
304}
305
306static int ha_ssl_new(BIO *h)
307{
308 BIO_set_init(h, 1);
309 BIO_set_data(h, NULL);
310 BIO_clear_flags(h, ~0);
311 return 1;
312}
313
314static int ha_ssl_free(BIO *data)
315{
316
317 return 1;
318}
319
320
Willy Tarreau5db847a2019-05-09 14:13:35 +0200321#if defined(USE_THREAD) && (HA_OPENSSL_VERSION_NUMBER < 0x10100000L)
Christopher Faulet9dcf9b62017-11-13 10:34:01 +0100322
Emeric Brun821bb9b2017-06-15 16:37:39 +0200323static HA_RWLOCK_T *ssl_rwlocks;
324
325
326unsigned long ssl_id_function(void)
327{
328 return (unsigned long)tid;
329}
330
331void ssl_locking_function(int mode, int n, const char * file, int line)
332{
333 if (mode & CRYPTO_LOCK) {
334 if (mode & CRYPTO_READ)
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100335 HA_RWLOCK_RDLOCK(SSL_LOCK, &ssl_rwlocks[n]);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200336 else
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100337 HA_RWLOCK_WRLOCK(SSL_LOCK, &ssl_rwlocks[n]);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200338 }
339 else {
340 if (mode & CRYPTO_READ)
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100341 HA_RWLOCK_RDUNLOCK(SSL_LOCK, &ssl_rwlocks[n]);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200342 else
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100343 HA_RWLOCK_WRUNLOCK(SSL_LOCK, &ssl_rwlocks[n]);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200344 }
345}
346
347static int ssl_locking_init(void)
348{
349 int i;
350
351 ssl_rwlocks = malloc(sizeof(HA_RWLOCK_T)*CRYPTO_num_locks());
352 if (!ssl_rwlocks)
353 return -1;
354
355 for (i = 0 ; i < CRYPTO_num_locks() ; i++)
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100356 HA_RWLOCK_INIT(&ssl_rwlocks[i]);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200357
358 CRYPTO_set_id_callback(ssl_id_function);
359 CRYPTO_set_locking_callback(ssl_locking_function);
360
361 return 0;
362}
Christopher Faulet9dcf9b62017-11-13 10:34:01 +0100363
Emeric Brun821bb9b2017-06-15 16:37:39 +0200364#endif
365
William Lallemand150bfa82019-09-19 17:12:49 +0200366__decl_hathreads(HA_SPINLOCK_T ckch_lock);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200367
William Lallemandbc6ca7c2019-10-29 23:48:19 +0100368/* Uncommitted CKCH transaction */
369
370static struct {
371 struct ckch_store *new_ckchs;
372 struct ckch_store *old_ckchs;
373 char *path;
374} ckchs_transaction;
375
Emmanuel Hocdetd4f9a602019-10-24 11:32:47 +0200376/*
Emmanuel Hocdetb270e812019-11-21 19:09:31 +0100377 * deduplicate cafile (and crlfile)
Emmanuel Hocdetd4f9a602019-10-24 11:32:47 +0200378 */
379struct cafile_entry {
380 X509_STORE *ca_store;
Emmanuel Hocdet129d3282019-10-24 18:08:51 +0200381 STACK_OF(X509_NAME) *ca_list;
Emmanuel Hocdetd4f9a602019-10-24 11:32:47 +0200382 struct ebmb_node node;
383 char path[0];
384};
385
386static struct eb_root cafile_tree = EB_ROOT_UNIQUE;
387
388static X509_STORE* ssl_store_get0_locations_file(char *path)
389{
390 struct ebmb_node *eb;
391
392 eb = ebst_lookup(&cafile_tree, path);
393 if (eb) {
394 struct cafile_entry *ca_e;
395 ca_e = ebmb_entry(eb, struct cafile_entry, node);
396 return ca_e->ca_store;
397 }
398 return NULL;
399}
400
401static int ssl_store_load_locations_file(char *path)
402{
403 if (ssl_store_get0_locations_file(path) == NULL) {
404 struct cafile_entry *ca_e;
405 X509_STORE *store = X509_STORE_new();
406 if (X509_STORE_load_locations(store, path, NULL)) {
407 int pathlen;
408 pathlen = strlen(path);
409 ca_e = calloc(1, sizeof(*ca_e) + pathlen + 1);
410 if (ca_e) {
411 memcpy(ca_e->path, path, pathlen + 1);
412 ca_e->ca_store = store;
413 ebst_insert(&cafile_tree, &ca_e->node);
414 return 1;
415 }
416 }
417 X509_STORE_free(store);
418 return 0;
419 }
420 return 1;
421}
422
423/* mimic what X509_STORE_load_locations do with store_ctx */
424static int ssl_set_cert_crl_file(X509_STORE *store_ctx, char *path)
425{
426 X509_STORE *store;
427 store = ssl_store_get0_locations_file(path);
428 if (store_ctx && store) {
429 int i;
430 X509_OBJECT *obj;
431 STACK_OF(X509_OBJECT) *objs = X509_STORE_get0_objects(store);
432 for (i = 0; i < sk_X509_OBJECT_num(objs); i++) {
433 obj = sk_X509_OBJECT_value(objs, i);
434 switch (X509_OBJECT_get_type(obj)) {
435 case X509_LU_X509:
436 X509_STORE_add_cert(store_ctx, X509_OBJECT_get0_X509(obj));
437 break;
438 case X509_LU_CRL:
439 X509_STORE_add_crl(store_ctx, X509_OBJECT_get0_X509_CRL(obj));
440 break;
441 default:
442 break;
443 }
444 }
445 return 1;
446 }
447 return 0;
448}
449
450/* SSL_CTX_load_verify_locations substitute, internaly call X509_STORE_load_locations */
451static int ssl_set_verify_locations_file(SSL_CTX *ctx, char *path)
452{
453 X509_STORE *store_ctx = SSL_CTX_get_cert_store(ctx);
454 return ssl_set_cert_crl_file(store_ctx, path);
455}
456
Emmanuel Hocdet129d3282019-10-24 18:08:51 +0200457/*
458 Extract CA_list from CA_file already in tree.
459 Duplicate ca_name is tracking with ebtree. It's simplify openssl compatibility.
460 Return a shared ca_list: SSL_dup_CA_list must be used before set it on SSL_CTX.
461*/
462static STACK_OF(X509_NAME)* ssl_get_client_ca_file(char *path)
463{
464 struct ebmb_node *eb;
465 struct cafile_entry *ca_e;
466
467 eb = ebst_lookup(&cafile_tree, path);
468 if (!eb)
469 return NULL;
470 ca_e = ebmb_entry(eb, struct cafile_entry, node);
471
472 if (ca_e->ca_list == NULL) {
473 int i;
474 unsigned long key;
475 struct eb_root ca_name_tree = EB_ROOT;
476 struct eb64_node *node, *back;
477 struct {
478 struct eb64_node node;
479 X509_NAME *xname;
480 } *ca_name;
481 STACK_OF(X509_OBJECT) *objs;
482 STACK_OF(X509_NAME) *skn;
483 X509 *x;
484 X509_NAME *xn;
485
486 skn = sk_X509_NAME_new_null();
487 /* take x509 from cafile_tree */
488 objs = X509_STORE_get0_objects(ca_e->ca_store);
489 for (i = 0; i < sk_X509_OBJECT_num(objs); i++) {
490 x = X509_OBJECT_get0_X509(sk_X509_OBJECT_value(objs, i));
491 if (!x)
492 continue;
493 xn = X509_get_subject_name(x);
494 if (!xn)
495 continue;
496 /* Check for duplicates. */
497 key = X509_NAME_hash(xn);
498 for (node = eb64_lookup(&ca_name_tree, key), ca_name = NULL;
499 node && ca_name == NULL;
500 node = eb64_next(node)) {
501 ca_name = container_of(node, typeof(*ca_name), node);
502 if (X509_NAME_cmp(xn, ca_name->xname) != 0)
503 ca_name = NULL;
504 }
505 /* find a duplicate */
506 if (ca_name)
507 continue;
508 ca_name = calloc(1, sizeof *ca_name);
509 xn = X509_NAME_dup(xn);
510 if (!ca_name ||
511 !xn ||
512 !sk_X509_NAME_push(skn, xn)) {
513 free(ca_name);
514 X509_NAME_free(xn);
515 sk_X509_NAME_pop_free(skn, X509_NAME_free);
516 sk_X509_NAME_free(skn);
517 skn = NULL;
518 break;
519 }
520 ca_name->node.key = key;
521 ca_name->xname = xn;
522 eb64_insert(&ca_name_tree, &ca_name->node);
523 }
524 ca_e->ca_list = skn;
525 /* remove temporary ca_name tree */
526 node = eb64_first(&ca_name_tree);
527 while (node) {
528 ca_name = container_of(node, typeof(*ca_name), node);
529 back = eb64_next(node);
530 eb64_delete(node);
531 free(ca_name);
532 node = back;
533 }
534 }
535 return ca_e->ca_list;
536}
537
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +0100538/* This memory pool is used for capturing clienthello parameters. */
Thierry FOURNIER5bf77322017-02-25 12:45:22 +0100539struct ssl_capture {
Thierry FOURNIER5bf77322017-02-25 12:45:22 +0100540 unsigned long long int xxh64;
541 unsigned char ciphersuite_len;
542 char ciphersuite[0];
543};
Willy Tarreaubafbe012017-11-24 17:34:44 +0100544struct pool_head *pool_head_ssl_capture = NULL;
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +0100545static int ssl_capture_ptr_index = -1;
Thierry FOURNIER28962c92018-06-17 21:37:05 +0200546static int ssl_app_data_index = -1;
Willy Tarreauef934602016-12-22 23:12:01 +0100547
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200548#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
549struct list tlskeys_reference = LIST_HEAD_INIT(tlskeys_reference);
550#endif
551
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +0200552#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +0000553static unsigned int openssl_engines_initialized;
554struct list openssl_engines = LIST_HEAD_INIT(openssl_engines);
555struct ssl_engine_list {
556 struct list list;
557 ENGINE *e;
558};
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +0200559#endif
Grant Zhang872f9c22017-01-21 01:10:18 +0000560
Remi Gacogne8de54152014-07-15 11:36:40 +0200561#ifndef OPENSSL_NO_DH
Remi Gacogne4f902b82015-05-28 16:23:00 +0200562static int ssl_dh_ptr_index = -1;
Remi Gacogne47783ef2015-05-29 15:53:22 +0200563static DH *global_dh = NULL;
Remi Gacogne8de54152014-07-15 11:36:40 +0200564static DH *local_dh_1024 = NULL;
565static DH *local_dh_2048 = NULL;
566static DH *local_dh_4096 = NULL;
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +0100567static DH *ssl_get_tmp_dh(SSL *ssl, int export, int keylen);
Remi Gacogne8de54152014-07-15 11:36:40 +0200568#endif /* OPENSSL_NO_DH */
569
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100570#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Christopher Faulet31af49d2015-06-09 17:29:50 +0200571/* X509V3 Extensions that will be added on generated certificates */
572#define X509V3_EXT_SIZE 5
573static char *x509v3_ext_names[X509V3_EXT_SIZE] = {
574 "basicConstraints",
575 "nsComment",
576 "subjectKeyIdentifier",
577 "authorityKeyIdentifier",
578 "keyUsage",
579};
580static char *x509v3_ext_values[X509V3_EXT_SIZE] = {
581 "CA:FALSE",
582 "\"OpenSSL Generated Certificate\"",
583 "hash",
584 "keyid,issuer:always",
585 "nonRepudiation,digitalSignature,keyEncipherment"
586};
Christopher Faulet31af49d2015-06-09 17:29:50 +0200587/* LRU cache to store generated certificate */
588static struct lru64_head *ssl_ctx_lru_tree = NULL;
589static unsigned int ssl_ctx_lru_seed = 0;
Emeric Brun821bb9b2017-06-15 16:37:39 +0200590static unsigned int ssl_ctx_serial;
Willy Tarreau86abe442018-11-25 20:12:18 +0100591__decl_rwlock(ssl_ctx_lru_rwlock);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200592
Willy Tarreauc8ad3be2015-06-17 15:48:26 +0200593#endif // SSL_CTRL_SET_TLSEXT_HOSTNAME
594
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100595static struct ssl_bind_kw ssl_bind_kws[];
596
Willy Tarreau9a1ab082019-05-09 13:26:41 +0200597#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
yanbzhube2774d2015-12-10 15:07:30 -0500598/* The order here matters for picking a default context,
599 * keep the most common keytype at the bottom of the list
600 */
601const char *SSL_SOCK_KEYTYPE_NAMES[] = {
602 "dsa",
603 "ecdsa",
604 "rsa"
605};
606#define SSL_SOCK_NUM_KEYTYPES 3
Willy Tarreau30da7ad2015-12-14 11:28:33 +0100607#else
608#define SSL_SOCK_NUM_KEYTYPES 1
yanbzhube2774d2015-12-10 15:07:30 -0500609#endif
610
William Lallemandc3cd35f2017-11-28 11:04:43 +0100611static struct shared_context *ssl_shctx = NULL; /* ssl shared session cache */
William Lallemand4f45bb92017-10-30 20:08:51 +0100612static struct eb_root *sh_ssl_sess_tree; /* ssl shared session tree */
613
614#define sh_ssl_sess_tree_delete(s) ebmb_delete(&(s)->key);
615
616#define sh_ssl_sess_tree_insert(s) (struct sh_ssl_sess_hdr *)ebmb_insert(sh_ssl_sess_tree, \
617 &(s)->key, SSL_MAX_SSL_SESSION_ID_LENGTH);
618
619#define sh_ssl_sess_tree_lookup(k) (struct sh_ssl_sess_hdr *)ebmb_lookup(sh_ssl_sess_tree, \
620 (k), SSL_MAX_SSL_SESSION_ID_LENGTH);
William Lallemand3f85c9a2017-10-09 16:30:50 +0200621
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100622/*
623 * This function gives the detail of the SSL error. It is used only
624 * if the debug mode and the verbose mode are activated. It dump all
625 * the SSL error until the stack was empty.
626 */
627static forceinline void ssl_sock_dump_errors(struct connection *conn)
628{
629 unsigned long ret;
630
631 if (unlikely(global.mode & MODE_DEBUG)) {
632 while(1) {
633 ret = ERR_get_error();
634 if (ret == 0)
635 return;
636 fprintf(stderr, "fd[%04x] OpenSSL error[0x%lx] %s: %s\n",
Willy Tarreau585744b2017-08-24 14:31:19 +0200637 (unsigned short)conn->handle.fd, ret,
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100638 ERR_func_error_string(ret), ERR_reason_error_string(ret));
639 }
640 }
641}
642
yanbzhube2774d2015-12-10 15:07:30 -0500643
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +0200644#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +0000645static int ssl_init_single_engine(const char *engine_id, const char *def_algorithms)
646{
647 int err_code = ERR_ABORT;
648 ENGINE *engine;
649 struct ssl_engine_list *el;
650
651 /* grab the structural reference to the engine */
652 engine = ENGINE_by_id(engine_id);
653 if (engine == NULL) {
Christopher Faulet767a84b2017-11-24 16:50:31 +0100654 ha_alert("ssl-engine %s: failed to get structural reference\n", engine_id);
Grant Zhang872f9c22017-01-21 01:10:18 +0000655 goto fail_get;
656 }
657
658 if (!ENGINE_init(engine)) {
659 /* the engine couldn't initialise, release it */
Christopher Faulet767a84b2017-11-24 16:50:31 +0100660 ha_alert("ssl-engine %s: failed to initialize\n", engine_id);
Grant Zhang872f9c22017-01-21 01:10:18 +0000661 goto fail_init;
662 }
663
664 if (ENGINE_set_default_string(engine, def_algorithms) == 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +0100665 ha_alert("ssl-engine %s: failed on ENGINE_set_default_string\n", engine_id);
Grant Zhang872f9c22017-01-21 01:10:18 +0000666 goto fail_set_method;
667 }
668
669 el = calloc(1, sizeof(*el));
670 el->e = engine;
671 LIST_ADD(&openssl_engines, &el->list);
Emeric Brunece0c332017-12-06 13:51:49 +0100672 nb_engines++;
673 if (global_ssl.async)
674 global.ssl_used_async_engines = nb_engines;
Grant Zhang872f9c22017-01-21 01:10:18 +0000675 return 0;
676
677fail_set_method:
678 /* release the functional reference from ENGINE_init() */
679 ENGINE_finish(engine);
680
681fail_init:
682 /* release the structural reference from ENGINE_by_id() */
683 ENGINE_free(engine);
684
685fail_get:
686 return err_code;
687}
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +0200688#endif
Grant Zhang872f9c22017-01-21 01:10:18 +0000689
Willy Tarreau5db847a2019-05-09 14:13:35 +0200690#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brun3854e012017-05-17 20:42:48 +0200691/*
692 * openssl async fd handler
693 */
Emeric Brund0e095c2019-04-19 17:15:28 +0200694void ssl_async_fd_handler(int fd)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000695{
Olivier Houchardea8dd942019-05-20 14:02:16 +0200696 struct ssl_sock_ctx *ctx = fdtab[fd].owner;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000697
Emeric Brun3854e012017-05-17 20:42:48 +0200698 /* fd is an async enfine fd, we must stop
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000699 * to poll this fd until it is requested
700 */
Emeric Brunbbc16542017-06-02 15:54:06 +0000701 fd_stop_recv(fd);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000702 fd_cant_recv(fd);
703
704 /* crypto engine is available, let's notify the associated
705 * connection that it can pursue its processing.
706 */
Olivier Houchard03abf2d2019-05-28 10:12:02 +0200707 ssl_sock_io_cb(NULL, ctx, 0);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000708}
709
Emeric Brun3854e012017-05-17 20:42:48 +0200710/*
711 * openssl async delayed SSL_free handler
712 */
Emeric Brund0e095c2019-04-19 17:15:28 +0200713void ssl_async_fd_free(int fd)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000714{
715 SSL *ssl = fdtab[fd].owner;
Emeric Brun3854e012017-05-17 20:42:48 +0200716 OSSL_ASYNC_FD all_fd[32];
717 size_t num_all_fds = 0;
718 int i;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000719
Emeric Brun3854e012017-05-17 20:42:48 +0200720 /* We suppose that the async job for a same SSL *
721 * are serialized. So if we are awake it is
722 * because the running job has just finished
723 * and we can remove all async fds safely
724 */
725 SSL_get_all_async_fds(ssl, NULL, &num_all_fds);
726 if (num_all_fds > 32) {
727 send_log(NULL, LOG_EMERG, "haproxy: openssl returns too many async fds. It seems a bug. Process may crash\n");
728 return;
729 }
730
731 SSL_get_all_async_fds(ssl, all_fd, &num_all_fds);
732 for (i=0 ; i < num_all_fds ; i++)
733 fd_remove(all_fd[i]);
734
735 /* Now we can safely call SSL_free, no more pending job in engines */
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000736 SSL_free(ssl);
Olivier Houchard2be5a4c2019-03-08 18:54:43 +0100737 _HA_ATOMIC_SUB(&sslconns, 1);
738 _HA_ATOMIC_SUB(&jobs, 1);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000739}
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000740/*
Emeric Brun3854e012017-05-17 20:42:48 +0200741 * function used to manage a returned SSL_ERROR_WANT_ASYNC
742 * and enable/disable polling for async fds
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000743 */
Olivier Houchardea8dd942019-05-20 14:02:16 +0200744static inline void ssl_async_process_fds(struct ssl_sock_ctx *ctx)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000745{
Willy Tarreaua9786b62018-01-25 07:22:13 +0100746 OSSL_ASYNC_FD add_fd[32];
Emeric Brun3854e012017-05-17 20:42:48 +0200747 OSSL_ASYNC_FD del_fd[32];
Olivier Houchardea8dd942019-05-20 14:02:16 +0200748 SSL *ssl = ctx->ssl;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000749 size_t num_add_fds = 0;
750 size_t num_del_fds = 0;
Emeric Brun3854e012017-05-17 20:42:48 +0200751 int i;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000752
753 SSL_get_changed_async_fds(ssl, NULL, &num_add_fds, NULL,
754 &num_del_fds);
Emeric Brun3854e012017-05-17 20:42:48 +0200755 if (num_add_fds > 32 || num_del_fds > 32) {
756 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 +0000757 return;
758 }
759
Emeric Brun3854e012017-05-17 20:42:48 +0200760 SSL_get_changed_async_fds(ssl, add_fd, &num_add_fds, del_fd, &num_del_fds);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000761
Emeric Brun3854e012017-05-17 20:42:48 +0200762 /* We remove unused fds from the fdtab */
763 for (i=0 ; i < num_del_fds ; i++)
764 fd_remove(del_fd[i]);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000765
Emeric Brun3854e012017-05-17 20:42:48 +0200766 /* We add new fds to the fdtab */
767 for (i=0 ; i < num_add_fds ; i++) {
Olivier Houchardea8dd942019-05-20 14:02:16 +0200768 fd_insert(add_fd[i], ctx, ssl_async_fd_handler, tid_bit);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000769 }
770
Emeric Brun3854e012017-05-17 20:42:48 +0200771 num_add_fds = 0;
772 SSL_get_all_async_fds(ssl, NULL, &num_add_fds);
773 if (num_add_fds > 32) {
774 send_log(NULL, LOG_EMERG, "haproxy: openssl returns too many async fds. It seems a bug. Process may crash\n");
775 return;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000776 }
Emeric Brun3854e012017-05-17 20:42:48 +0200777
778 /* We activate the polling for all known async fds */
779 SSL_get_all_async_fds(ssl, add_fd, &num_add_fds);
Emeric Brunce9e01c2017-05-31 10:02:53 +0000780 for (i=0 ; i < num_add_fds ; i++) {
Emeric Brun3854e012017-05-17 20:42:48 +0200781 fd_want_recv(add_fd[i]);
Emeric Brunce9e01c2017-05-31 10:02:53 +0000782 /* To ensure that the fd cache won't be used
783 * We'll prefer to catch a real RD event
784 * because handling an EAGAIN on this fd will
785 * result in a context switch and also
786 * some engines uses a fd in blocking mode.
787 */
788 fd_cant_recv(add_fd[i]);
789 }
Emeric Brun3854e012017-05-17 20:42:48 +0200790
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000791}
792#endif
793
William Lallemand104a7a62019-10-14 14:14:59 +0200794#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
Emeric Brun4f3c87a2014-06-20 15:46:13 +0200795/*
796 * This function returns the number of seconds elapsed
797 * since the Epoch, 1970-01-01 00:00:00 +0000 (UTC) and the
798 * date presented un ASN1_GENERALIZEDTIME.
799 *
800 * In parsing error case, it returns -1.
801 */
802static long asn1_generalizedtime_to_epoch(ASN1_GENERALIZEDTIME *d)
803{
804 long epoch;
805 char *p, *end;
806 const unsigned short month_offset[12] = {
807 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
808 };
809 int year, month;
810
811 if (!d || (d->type != V_ASN1_GENERALIZEDTIME)) return -1;
812
813 p = (char *)d->data;
814 end = p + d->length;
815
816 if (end - p < 4) return -1;
817 year = 1000 * (p[0] - '0') + 100 * (p[1] - '0') + 10 * (p[2] - '0') + p[3] - '0';
818 p += 4;
819 if (end - p < 2) return -1;
820 month = 10 * (p[0] - '0') + p[1] - '0';
821 if (month < 1 || month > 12) return -1;
822 /* Compute the number of seconds since 1 jan 1970 and the beginning of current month
823 We consider leap years and the current month (<marsh or not) */
824 epoch = ( ((year - 1970) * 365)
825 + ((year - (month < 3)) / 4 - (year - (month < 3)) / 100 + (year - (month < 3)) / 400)
826 - ((1970 - 1) / 4 - (1970 - 1) / 100 + (1970 - 1) / 400)
827 + month_offset[month-1]
828 ) * 24 * 60 * 60;
829 p += 2;
830 if (end - p < 2) return -1;
831 /* Add the number of seconds of completed days of current month */
832 epoch += (10 * (p[0] - '0') + p[1] - '0' - 1) * 24 * 60 * 60;
833 p += 2;
834 if (end - p < 2) return -1;
835 /* Add the completed hours of the current day */
836 epoch += (10 * (p[0] - '0') + p[1] - '0') * 60 * 60;
837 p += 2;
838 if (end - p < 2) return -1;
839 /* Add the completed minutes of the current hour */
840 epoch += (10 * (p[0] - '0') + p[1] - '0') * 60;
841 p += 2;
842 if (p == end) return -1;
843 /* Test if there is available seconds */
844 if (p[0] < '0' || p[0] > '9')
845 goto nosec;
846 if (end - p < 2) return -1;
847 /* Add the seconds of the current minute */
848 epoch += 10 * (p[0] - '0') + p[1] - '0';
849 p += 2;
850 if (p == end) return -1;
851 /* Ignore seconds float part if present */
852 if (p[0] == '.') {
853 do {
854 if (++p == end) return -1;
855 } while (p[0] >= '0' && p[0] <= '9');
856 }
857
858nosec:
859 if (p[0] == 'Z') {
860 if (end - p != 1) return -1;
861 return epoch;
862 }
863 else if (p[0] == '+') {
864 if (end - p != 5) return -1;
865 /* Apply timezone offset */
Frederik Deweerdt953917a2017-10-16 07:37:31 -0700866 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 +0200867 }
868 else if (p[0] == '-') {
869 if (end - p != 5) return -1;
870 /* Apply timezone offset */
Frederik Deweerdt953917a2017-10-16 07:37:31 -0700871 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 +0200872 }
873
874 return -1;
875}
876
William Lallemand104a7a62019-10-14 14:14:59 +0200877/*
878 * struct alignment works here such that the key.key is the same as key_data
879 * Do not change the placement of key_data
880 */
881struct certificate_ocsp {
882 struct ebmb_node key;
883 unsigned char key_data[OCSP_MAX_CERTID_ASN1_LENGTH];
884 struct buffer response;
885 long expire;
886};
887
888struct ocsp_cbk_arg {
889 int is_single;
890 int single_kt;
891 union {
892 struct certificate_ocsp *s_ocsp;
893 /*
894 * m_ocsp will have multiple entries dependent on key type
895 * Entry 0 - DSA
896 * Entry 1 - ECDSA
897 * Entry 2 - RSA
898 */
899 struct certificate_ocsp *m_ocsp[SSL_SOCK_NUM_KEYTYPES];
900 };
901};
902
Emeric Brun1d3865b2014-06-20 15:37:32 +0200903static struct eb_root cert_ocsp_tree = EB_ROOT_UNIQUE;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200904
905/* This function starts to check if the OCSP response (in DER format) contained
906 * in chunk 'ocsp_response' is valid (else exits on error).
907 * If 'cid' is not NULL, it will be compared to the OCSP certificate ID
908 * contained in the OCSP Response and exits on error if no match.
909 * If it's a valid OCSP Response:
910 * If 'ocsp' is not NULL, the chunk is copied in the OCSP response's container
911 * pointed by 'ocsp'.
912 * If 'ocsp' is NULL, the function looks up into the OCSP response's
913 * containers tree (using as index the ASN1 form of the OCSP Certificate ID extracted
914 * from the response) and exits on error if not found. Finally, If an OCSP response is
915 * already present in the container, it will be overwritten.
916 *
917 * Note: OCSP response containing more than one OCSP Single response is not
918 * considered valid.
919 *
920 * Returns 0 on success, 1 in error case.
921 */
Willy Tarreau83061a82018-07-13 11:56:34 +0200922static int ssl_sock_load_ocsp_response(struct buffer *ocsp_response,
923 struct certificate_ocsp *ocsp,
924 OCSP_CERTID *cid, char **err)
Emeric Brun4147b2e2014-06-16 18:36:30 +0200925{
926 OCSP_RESPONSE *resp;
927 OCSP_BASICRESP *bs = NULL;
928 OCSP_SINGLERESP *sr;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200929 OCSP_CERTID *id;
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200930 unsigned char *p = (unsigned char *) ocsp_response->area;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200931 int rc , count_sr;
Emeric Brun13a6b482014-06-20 15:44:34 +0200932 ASN1_GENERALIZEDTIME *revtime, *thisupd, *nextupd = NULL;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200933 int reason;
934 int ret = 1;
935
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200936 resp = d2i_OCSP_RESPONSE(NULL, (const unsigned char **)&p,
937 ocsp_response->data);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200938 if (!resp) {
939 memprintf(err, "Unable to parse OCSP response");
940 goto out;
941 }
942
943 rc = OCSP_response_status(resp);
944 if (rc != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
945 memprintf(err, "OCSP response status not successful");
946 goto out;
947 }
948
949 bs = OCSP_response_get1_basic(resp);
950 if (!bs) {
951 memprintf(err, "Failed to get basic response from OCSP Response");
952 goto out;
953 }
954
955 count_sr = OCSP_resp_count(bs);
956 if (count_sr > 1) {
957 memprintf(err, "OCSP response ignored because contains multiple single responses (%d)", count_sr);
958 goto out;
959 }
960
961 sr = OCSP_resp_get0(bs, 0);
962 if (!sr) {
963 memprintf(err, "Failed to get OCSP single response");
964 goto out;
965 }
966
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200967 id = (OCSP_CERTID*)OCSP_SINGLERESP_get0_id(sr);
968
Emeric Brun4147b2e2014-06-16 18:36:30 +0200969 rc = OCSP_single_get0_status(sr, &reason, &revtime, &thisupd, &nextupd);
Emmanuel Hocdetef607052017-10-24 14:57:16 +0200970 if (rc != V_OCSP_CERTSTATUS_GOOD && rc != V_OCSP_CERTSTATUS_REVOKED) {
Emmanuel Hocdet872085c2017-10-10 15:18:52 +0200971 memprintf(err, "OCSP single response: certificate status is unknown");
Emeric Brun4147b2e2014-06-16 18:36:30 +0200972 goto out;
973 }
974
Emeric Brun13a6b482014-06-20 15:44:34 +0200975 if (!nextupd) {
976 memprintf(err, "OCSP single response: missing nextupdate");
977 goto out;
978 }
979
Emeric Brunc8b27b62014-06-19 14:16:17 +0200980 rc = OCSP_check_validity(thisupd, nextupd, OCSP_MAX_RESPONSE_TIME_SKEW, -1);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200981 if (!rc) {
982 memprintf(err, "OCSP single response: no longer valid.");
983 goto out;
984 }
985
986 if (cid) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200987 if (OCSP_id_cmp(id, cid)) {
Emeric Brun4147b2e2014-06-16 18:36:30 +0200988 memprintf(err, "OCSP single response: Certificate ID does not match certificate and issuer");
989 goto out;
990 }
991 }
992
993 if (!ocsp) {
994 unsigned char key[OCSP_MAX_CERTID_ASN1_LENGTH];
995 unsigned char *p;
996
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200997 rc = i2d_OCSP_CERTID(id, NULL);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200998 if (!rc) {
999 memprintf(err, "OCSP single response: Unable to encode Certificate ID");
1000 goto out;
1001 }
1002
1003 if (rc > OCSP_MAX_CERTID_ASN1_LENGTH) {
1004 memprintf(err, "OCSP single response: Certificate ID too long");
1005 goto out;
1006 }
1007
1008 p = key;
1009 memset(key, 0, OCSP_MAX_CERTID_ASN1_LENGTH);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001010 i2d_OCSP_CERTID(id, &p);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001011 ocsp = (struct certificate_ocsp *)ebmb_lookup(&cert_ocsp_tree, key, OCSP_MAX_CERTID_ASN1_LENGTH);
1012 if (!ocsp) {
1013 memprintf(err, "OCSP single response: Certificate ID does not match any certificate or issuer");
1014 goto out;
1015 }
1016 }
1017
1018 /* According to comments on "chunk_dup", the
1019 previous chunk buffer will be freed */
1020 if (!chunk_dup(&ocsp->response, ocsp_response)) {
1021 memprintf(err, "OCSP response: Memory allocation error");
1022 goto out;
1023 }
1024
Emeric Brun4f3c87a2014-06-20 15:46:13 +02001025 ocsp->expire = asn1_generalizedtime_to_epoch(nextupd) - OCSP_MAX_RESPONSE_TIME_SKEW;
1026
Emeric Brun4147b2e2014-06-16 18:36:30 +02001027 ret = 0;
1028out:
Janusz Dziemidowicz8d710492017-03-08 16:59:41 +01001029 ERR_clear_error();
1030
Emeric Brun4147b2e2014-06-16 18:36:30 +02001031 if (bs)
1032 OCSP_BASICRESP_free(bs);
1033
1034 if (resp)
1035 OCSP_RESPONSE_free(resp);
1036
1037 return ret;
1038}
1039/*
1040 * External function use to update the OCSP response in the OCSP response's
1041 * containers tree. The chunk 'ocsp_response' must contain the OCSP response
1042 * to update in DER format.
1043 *
1044 * Returns 0 on success, 1 in error case.
1045 */
Willy Tarreau83061a82018-07-13 11:56:34 +02001046int ssl_sock_update_ocsp_response(struct buffer *ocsp_response, char **err)
Emeric Brun4147b2e2014-06-16 18:36:30 +02001047{
1048 return ssl_sock_load_ocsp_response(ocsp_response, NULL, NULL, err);
1049}
1050
William Lallemand4a660132019-10-14 14:51:41 +02001051#endif
1052
1053#if ((defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP) || defined OPENSSL_IS_BORINGSSL)
Emeric Brun4147b2e2014-06-16 18:36:30 +02001054/*
1055 * This function load the OCSP Resonse in DER format contained in file at
William Lallemand3b5f3602019-10-16 18:05:05 +02001056 * path 'ocsp_path' or base64 in a buffer <buf>
Emeric Brun4147b2e2014-06-16 18:36:30 +02001057 *
1058 * Returns 0 on success, 1 in error case.
1059 */
William Lallemand3b5f3602019-10-16 18:05:05 +02001060static 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 +02001061{
1062 int fd = -1;
1063 int r = 0;
1064 int ret = 1;
William Lallemand3b5f3602019-10-16 18:05:05 +02001065 struct buffer *ocsp_response;
1066 struct buffer *src = NULL;
Emeric Brun4147b2e2014-06-16 18:36:30 +02001067
William Lallemand3b5f3602019-10-16 18:05:05 +02001068 if (buf) {
1069 int i, j;
1070 /* if it's from a buffer it will be base64 */
Emeric Brun4147b2e2014-06-16 18:36:30 +02001071
William Lallemand3b5f3602019-10-16 18:05:05 +02001072 /* remove \r and \n from the payload */
1073 for (i = 0, j = 0; buf[i]; i++) {
1074 if (buf[i] == '\r' || buf[i] == '\n')
Emeric Brun4147b2e2014-06-16 18:36:30 +02001075 continue;
William Lallemand3b5f3602019-10-16 18:05:05 +02001076 buf[j++] = buf[i];
1077 }
1078 buf[j] = 0;
Emeric Brun4147b2e2014-06-16 18:36:30 +02001079
William Lallemand3b5f3602019-10-16 18:05:05 +02001080 ret = base64dec(buf, j, trash.area, trash.size);
1081 if (ret < 0) {
1082 memprintf(err, "Error reading OCSP response in base64 format");
Emeric Brun4147b2e2014-06-16 18:36:30 +02001083 goto end;
1084 }
William Lallemand3b5f3602019-10-16 18:05:05 +02001085 trash.data = ret;
1086 src = &trash;
1087 } else {
1088 fd = open(ocsp_path, O_RDONLY);
1089 if (fd == -1) {
1090 memprintf(err, "Error opening OCSP response file");
1091 goto end;
Emeric Brun4147b2e2014-06-16 18:36:30 +02001092 }
William Lallemand3b5f3602019-10-16 18:05:05 +02001093
1094 trash.data = 0;
1095 while (trash.data < trash.size) {
1096 r = read(fd, trash.area + trash.data, trash.size - trash.data);
1097 if (r < 0) {
1098 if (errno == EINTR)
1099 continue;
1100
1101 memprintf(err, "Error reading OCSP response from file");
1102 goto end;
1103 }
1104 else if (r == 0) {
1105 break;
1106 }
1107 trash.data += r;
1108 }
1109 close(fd);
1110 fd = -1;
1111 src = &trash;
Emeric Brun4147b2e2014-06-16 18:36:30 +02001112 }
1113
William Lallemand3b5f3602019-10-16 18:05:05 +02001114 ocsp_response = calloc(1, sizeof(*ocsp_response));
1115 if (!chunk_dup(ocsp_response, src)) {
1116 free(ocsp_response);
1117 ocsp_response = NULL;
William Lallemand246c0242019-10-11 08:59:13 +02001118 goto end;
1119 }
Emmanuel Hocdet0667fae2020-01-16 14:41:36 +01001120 /* no error, fill ckch with new context, old context must be free */
1121 if (ckch->ocsp_response) {
1122 free(ckch->ocsp_response->area);
1123 ckch->ocsp_response->area = NULL;
1124 free(ckch->ocsp_response);
1125 }
William Lallemand3b5f3602019-10-16 18:05:05 +02001126 ckch->ocsp_response = ocsp_response;
William Lallemande0f48ae2019-10-15 13:44:57 +02001127 ret = 0;
Emeric Brun4147b2e2014-06-16 18:36:30 +02001128end:
1129 if (fd != -1)
1130 close(fd);
1131
1132 return ret;
1133}
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01001134#endif
Emeric Brun4147b2e2014-06-16 18:36:30 +02001135
Nenad Merdanovic05552d42015-02-27 19:56:49 +01001136#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
1137static 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)
1138{
Christopher Faulet16f45c82018-02-16 11:23:49 +01001139 struct tls_keys_ref *ref;
Emeric Brun9e754772019-01-10 17:51:55 +01001140 union tls_sess_key *keys;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01001141 struct connection *conn;
1142 int head;
1143 int i;
Christopher Faulet16f45c82018-02-16 11:23:49 +01001144 int ret = -1; /* error by default */
Nenad Merdanovic05552d42015-02-27 19:56:49 +01001145
Thierry FOURNIER28962c92018-06-17 21:37:05 +02001146 conn = SSL_get_ex_data(s, ssl_app_data_index);
Willy Tarreau07d94e42018-09-20 10:57:52 +02001147 ref = __objt_listener(conn->target)->bind_conf->keys_ref;
Christopher Faulet16f45c82018-02-16 11:23:49 +01001148 HA_RWLOCK_RDLOCK(TLSKEYS_REF_LOCK, &ref->lock);
1149
1150 keys = ref->tlskeys;
1151 head = ref->tls_ticket_enc_index;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01001152
1153 if (enc) {
1154 memcpy(key_name, keys[head].name, 16);
1155
1156 if(!RAND_pseudo_bytes(iv, EVP_MAX_IV_LENGTH))
Christopher Faulet16f45c82018-02-16 11:23:49 +01001157 goto end;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01001158
Emeric Brun9e754772019-01-10 17:51:55 +01001159 if (ref->key_size_bits == 128) {
Nenad Merdanovic05552d42015-02-27 19:56:49 +01001160
Emeric Brun9e754772019-01-10 17:51:55 +01001161 if(!EVP_EncryptInit_ex(ectx, EVP_aes_128_cbc(), NULL, keys[head].key_128.aes_key, iv))
1162 goto end;
1163
Willy Tarreau9356dac2019-05-10 09:22:53 +02001164 HMAC_Init_ex(hctx, keys[head].key_128.hmac_key, 16, TLS_TICKET_HASH_FUNCT(), NULL);
Emeric Brun9e754772019-01-10 17:51:55 +01001165 ret = 1;
1166 }
1167 else if (ref->key_size_bits == 256 ) {
1168
1169 if(!EVP_EncryptInit_ex(ectx, EVP_aes_256_cbc(), NULL, keys[head].key_256.aes_key, iv))
1170 goto end;
1171
Willy Tarreau9356dac2019-05-10 09:22:53 +02001172 HMAC_Init_ex(hctx, keys[head].key_256.hmac_key, 32, TLS_TICKET_HASH_FUNCT(), NULL);
Emeric Brun9e754772019-01-10 17:51:55 +01001173 ret = 1;
1174 }
Nenad Merdanovic05552d42015-02-27 19:56:49 +01001175 } else {
1176 for (i = 0; i < TLS_TICKETS_NO; i++) {
1177 if (!memcmp(key_name, keys[(head + i) % TLS_TICKETS_NO].name, 16))
1178 goto found;
1179 }
Christopher Faulet16f45c82018-02-16 11:23:49 +01001180 ret = 0;
1181 goto end;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01001182
Christopher Faulet16f45c82018-02-16 11:23:49 +01001183 found:
Emeric Brun9e754772019-01-10 17:51:55 +01001184 if (ref->key_size_bits == 128) {
Willy Tarreau9356dac2019-05-10 09:22:53 +02001185 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 +01001186 if(!EVP_DecryptInit_ex(ectx, EVP_aes_128_cbc(), NULL, keys[(head + i) % TLS_TICKETS_NO].key_128.aes_key, iv))
1187 goto end;
1188 /* 2 for key renewal, 1 if current key is still valid */
1189 ret = i ? 2 : 1;
1190 }
1191 else if (ref->key_size_bits == 256) {
Willy Tarreau9356dac2019-05-10 09:22:53 +02001192 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 +01001193 if(!EVP_DecryptInit_ex(ectx, EVP_aes_256_cbc(), NULL, keys[(head + i) % TLS_TICKETS_NO].key_256.aes_key, iv))
1194 goto end;
1195 /* 2 for key renewal, 1 if current key is still valid */
1196 ret = i ? 2 : 1;
1197 }
Nenad Merdanovic05552d42015-02-27 19:56:49 +01001198 }
Emeric Brun9e754772019-01-10 17:51:55 +01001199
Christopher Faulet16f45c82018-02-16 11:23:49 +01001200 end:
1201 HA_RWLOCK_RDUNLOCK(TLSKEYS_REF_LOCK, &ref->lock);
1202 return ret;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02001203}
1204
1205struct tls_keys_ref *tlskeys_ref_lookup(const char *filename)
1206{
1207 struct tls_keys_ref *ref;
1208
1209 list_for_each_entry(ref, &tlskeys_reference, list)
1210 if (ref->filename && strcmp(filename, ref->filename) == 0)
1211 return ref;
1212 return NULL;
1213}
1214
1215struct tls_keys_ref *tlskeys_ref_lookupid(int unique_id)
1216{
1217 struct tls_keys_ref *ref;
1218
1219 list_for_each_entry(ref, &tlskeys_reference, list)
1220 if (ref->unique_id == unique_id)
1221 return ref;
1222 return NULL;
1223}
1224
Emeric Brun9e754772019-01-10 17:51:55 +01001225/* Update the key into ref: if keysize doesnt
1226 * match existing ones, this function returns -1
1227 * else it returns 0 on success.
1228 */
1229int ssl_sock_update_tlskey_ref(struct tls_keys_ref *ref,
Willy Tarreau83061a82018-07-13 11:56:34 +02001230 struct buffer *tlskey)
Christopher Faulet16f45c82018-02-16 11:23:49 +01001231{
Emeric Brun9e754772019-01-10 17:51:55 +01001232 if (ref->key_size_bits == 128) {
1233 if (tlskey->data != sizeof(struct tls_sess_key_128))
1234 return -1;
1235 }
1236 else if (ref->key_size_bits == 256) {
1237 if (tlskey->data != sizeof(struct tls_sess_key_256))
1238 return -1;
1239 }
1240 else
1241 return -1;
1242
Christopher Faulet16f45c82018-02-16 11:23:49 +01001243 HA_RWLOCK_WRLOCK(TLSKEYS_REF_LOCK, &ref->lock);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001244 memcpy((char *) (ref->tlskeys + ((ref->tls_ticket_enc_index + 2) % TLS_TICKETS_NO)),
1245 tlskey->area, tlskey->data);
Christopher Faulet16f45c82018-02-16 11:23:49 +01001246 ref->tls_ticket_enc_index = (ref->tls_ticket_enc_index + 1) % TLS_TICKETS_NO;
1247 HA_RWLOCK_WRUNLOCK(TLSKEYS_REF_LOCK, &ref->lock);
Emeric Brun9e754772019-01-10 17:51:55 +01001248
1249 return 0;
Christopher Faulet16f45c82018-02-16 11:23:49 +01001250}
1251
Willy Tarreau83061a82018-07-13 11:56:34 +02001252int ssl_sock_update_tlskey(char *filename, struct buffer *tlskey, char **err)
Christopher Faulet16f45c82018-02-16 11:23:49 +01001253{
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02001254 struct tls_keys_ref *ref = tlskeys_ref_lookup(filename);
1255
1256 if(!ref) {
1257 memprintf(err, "Unable to locate the referenced filename: %s", filename);
1258 return 1;
1259 }
Emeric Brun9e754772019-01-10 17:51:55 +01001260 if (ssl_sock_update_tlskey_ref(ref, tlskey) < 0) {
1261 memprintf(err, "Invalid key size");
1262 return 1;
1263 }
1264
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02001265 return 0;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01001266}
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02001267
1268/* This function finalize the configuration parsing. Its set all the
Willy Tarreaud1c57502016-12-22 22:46:15 +01001269 * automatic ids. It's called just after the basic checks. It returns
1270 * 0 on success otherwise ERR_*.
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02001271 */
Willy Tarreaud1c57502016-12-22 22:46:15 +01001272static int tlskeys_finalize_config(void)
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02001273{
1274 int i = 0;
1275 struct tls_keys_ref *ref, *ref2, *ref3;
1276 struct list tkr = LIST_HEAD_INIT(tkr);
1277
1278 list_for_each_entry(ref, &tlskeys_reference, list) {
1279 if (ref->unique_id == -1) {
1280 /* Look for the first free id. */
1281 while (1) {
1282 list_for_each_entry(ref2, &tlskeys_reference, list) {
1283 if (ref2->unique_id == i) {
1284 i++;
1285 break;
1286 }
1287 }
1288 if (&ref2->list == &tlskeys_reference)
1289 break;
1290 }
1291
1292 /* Uses the unique id and increment it for the next entry. */
1293 ref->unique_id = i;
1294 i++;
1295 }
1296 }
1297
1298 /* This sort the reference list by id. */
1299 list_for_each_entry_safe(ref, ref2, &tlskeys_reference, list) {
1300 LIST_DEL(&ref->list);
1301 list_for_each_entry(ref3, &tkr, list) {
1302 if (ref->unique_id < ref3->unique_id) {
1303 LIST_ADDQ(&ref3->list, &ref->list);
1304 break;
1305 }
1306 }
1307 if (&ref3->list == &tkr)
1308 LIST_ADDQ(&tkr, &ref->list);
1309 }
1310
1311 /* swap root */
1312 LIST_ADD(&tkr, &tlskeys_reference);
1313 LIST_DEL(&tkr);
Willy Tarreaud1c57502016-12-22 22:46:15 +01001314 return 0;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02001315}
Nenad Merdanovic05552d42015-02-27 19:56:49 +01001316#endif /* SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB */
1317
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01001318#ifndef OPENSSL_NO_OCSP
yanbzhube2774d2015-12-10 15:07:30 -05001319int ssl_sock_get_ocsp_arg_kt_index(int evp_keytype)
1320{
1321 switch (evp_keytype) {
1322 case EVP_PKEY_RSA:
1323 return 2;
1324 case EVP_PKEY_DSA:
1325 return 0;
1326 case EVP_PKEY_EC:
1327 return 1;
1328 }
1329
1330 return -1;
1331}
1332
Emeric Brun4147b2e2014-06-16 18:36:30 +02001333/*
1334 * Callback used to set OCSP status extension content in server hello.
1335 */
1336int ssl_sock_ocsp_stapling_cbk(SSL *ssl, void *arg)
1337{
yanbzhube2774d2015-12-10 15:07:30 -05001338 struct certificate_ocsp *ocsp;
1339 struct ocsp_cbk_arg *ocsp_arg;
1340 char *ssl_buf;
1341 EVP_PKEY *ssl_pkey;
1342 int key_type;
1343 int index;
1344
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02001345 ocsp_arg = arg;
yanbzhube2774d2015-12-10 15:07:30 -05001346
1347 ssl_pkey = SSL_get_privatekey(ssl);
1348 if (!ssl_pkey)
1349 return SSL_TLSEXT_ERR_NOACK;
1350
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001351 key_type = EVP_PKEY_base_id(ssl_pkey);
yanbzhube2774d2015-12-10 15:07:30 -05001352
1353 if (ocsp_arg->is_single && ocsp_arg->single_kt == key_type)
1354 ocsp = ocsp_arg->s_ocsp;
1355 else {
1356 /* For multiple certs per context, we have to find the correct OCSP response based on
1357 * the certificate type
1358 */
1359 index = ssl_sock_get_ocsp_arg_kt_index(key_type);
1360
1361 if (index < 0)
1362 return SSL_TLSEXT_ERR_NOACK;
1363
1364 ocsp = ocsp_arg->m_ocsp[index];
1365
1366 }
Emeric Brun4147b2e2014-06-16 18:36:30 +02001367
1368 if (!ocsp ||
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001369 !ocsp->response.area ||
1370 !ocsp->response.data ||
Emeric Brun4f3c87a2014-06-20 15:46:13 +02001371 (ocsp->expire < now.tv_sec))
Emeric Brun4147b2e2014-06-16 18:36:30 +02001372 return SSL_TLSEXT_ERR_NOACK;
1373
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001374 ssl_buf = OPENSSL_malloc(ocsp->response.data);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001375 if (!ssl_buf)
1376 return SSL_TLSEXT_ERR_NOACK;
1377
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001378 memcpy(ssl_buf, ocsp->response.area, ocsp->response.data);
1379 SSL_set_tlsext_status_ocsp_resp(ssl, ssl_buf, ocsp->response.data);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001380
1381 return SSL_TLSEXT_ERR_OK;
1382}
1383
William Lallemand4a660132019-10-14 14:51:41 +02001384#endif
1385
1386#if ((defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP) || defined OPENSSL_IS_BORINGSSL)
Emeric Brun4147b2e2014-06-16 18:36:30 +02001387/*
1388 * This function enables the handling of OCSP status extension on 'ctx' if a
William Lallemand246c0242019-10-11 08:59:13 +02001389 * ocsp_response buffer was found in the cert_key_and_chain. To enable OCSP
1390 * status extension, the issuer's certificate is mandatory. It should be
1391 * present in ckch->ocsp_issuer.
Emeric Brun4147b2e2014-06-16 18:36:30 +02001392 *
William Lallemand246c0242019-10-11 08:59:13 +02001393 * In addition, the ckch->ocsp_reponse buffer is loaded as a DER format of an
1394 * OCSP response. If file is empty or content is not a valid OCSP response,
1395 * OCSP status extension is enabled but OCSP response is ignored (a warning is
1396 * displayed).
Emeric Brun4147b2e2014-06-16 18:36:30 +02001397 *
1398 * Returns 1 if no ".ocsp" file found, 0 if OCSP status extension is
Joseph Herlant017b3da2018-11-15 09:07:59 -08001399 * successfully enabled, or -1 in other error case.
Emeric Brun4147b2e2014-06-16 18:36:30 +02001400 */
William Lallemand4a660132019-10-14 14:51:41 +02001401#ifndef OPENSSL_IS_BORINGSSL
William Lallemand246c0242019-10-11 08:59:13 +02001402static int ssl_sock_load_ocsp(SSL_CTX *ctx, const struct cert_key_and_chain *ckch)
Emeric Brun4147b2e2014-06-16 18:36:30 +02001403{
William Lallemand246c0242019-10-11 08:59:13 +02001404 X509 *x = NULL, *issuer = NULL;
Emeric Brun4147b2e2014-06-16 18:36:30 +02001405 OCSP_CERTID *cid = NULL;
Emeric Brun4147b2e2014-06-16 18:36:30 +02001406 int i, ret = -1;
Emeric Brun4147b2e2014-06-16 18:36:30 +02001407 struct certificate_ocsp *ocsp = NULL, *iocsp;
1408 char *warn = NULL;
1409 unsigned char *p;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001410 void (*callback) (void);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001411
Emeric Brun4147b2e2014-06-16 18:36:30 +02001412
William Lallemand246c0242019-10-11 08:59:13 +02001413 x = ckch->cert;
Emeric Brun4147b2e2014-06-16 18:36:30 +02001414 if (!x)
1415 goto out;
1416
William Lallemand246c0242019-10-11 08:59:13 +02001417 issuer = ckch->ocsp_issuer;
1418 if (!issuer)
1419 goto out;
Emeric Brun4147b2e2014-06-16 18:36:30 +02001420
1421 cid = OCSP_cert_to_id(0, x, issuer);
1422 if (!cid)
1423 goto out;
1424
1425 i = i2d_OCSP_CERTID(cid, NULL);
1426 if (!i || (i > OCSP_MAX_CERTID_ASN1_LENGTH))
1427 goto out;
1428
Vincent Bernat02779b62016-04-03 13:48:43 +02001429 ocsp = calloc(1, sizeof(*ocsp));
Emeric Brun4147b2e2014-06-16 18:36:30 +02001430 if (!ocsp)
1431 goto out;
1432
1433 p = ocsp->key_data;
1434 i2d_OCSP_CERTID(cid, &p);
1435
1436 iocsp = (struct certificate_ocsp *)ebmb_insert(&cert_ocsp_tree, &ocsp->key, OCSP_MAX_CERTID_ASN1_LENGTH);
1437 if (iocsp == ocsp)
1438 ocsp = NULL;
1439
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001440#ifndef SSL_CTX_get_tlsext_status_cb
1441# define SSL_CTX_get_tlsext_status_cb(ctx, cb) \
1442 *cb = (void (*) (void))ctx->tlsext_status_cb;
1443#endif
1444 SSL_CTX_get_tlsext_status_cb(ctx, &callback);
1445
1446 if (!callback) {
Vincent Bernat02779b62016-04-03 13:48:43 +02001447 struct ocsp_cbk_arg *cb_arg = calloc(1, sizeof(*cb_arg));
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001448 EVP_PKEY *pkey;
yanbzhube2774d2015-12-10 15:07:30 -05001449
1450 cb_arg->is_single = 1;
1451 cb_arg->s_ocsp = iocsp;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001452
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001453 pkey = X509_get_pubkey(x);
1454 cb_arg->single_kt = EVP_PKEY_base_id(pkey);
1455 EVP_PKEY_free(pkey);
yanbzhube2774d2015-12-10 15:07:30 -05001456
1457 SSL_CTX_set_tlsext_status_cb(ctx, ssl_sock_ocsp_stapling_cbk);
1458 SSL_CTX_set_tlsext_status_arg(ctx, cb_arg);
1459 } else {
1460 /*
1461 * If the ctx has a status CB, then we have previously set an OCSP staple for this ctx
1462 * Update that cb_arg with the new cert's staple
1463 */
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001464 struct ocsp_cbk_arg *cb_arg;
yanbzhube2774d2015-12-10 15:07:30 -05001465 struct certificate_ocsp *tmp_ocsp;
1466 int index;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001467 int key_type;
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001468 EVP_PKEY *pkey;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001469
1470#ifdef SSL_CTX_get_tlsext_status_arg
1471 SSL_CTX_ctrl(ctx, SSL_CTRL_GET_TLSEXT_STATUS_REQ_CB_ARG, 0, &cb_arg);
1472#else
1473 cb_arg = ctx->tlsext_status_arg;
1474#endif
yanbzhube2774d2015-12-10 15:07:30 -05001475
1476 /*
1477 * The following few lines will convert cb_arg from a single ocsp to multi ocsp
1478 * the order of operations below matter, take care when changing it
1479 */
1480 tmp_ocsp = cb_arg->s_ocsp;
1481 index = ssl_sock_get_ocsp_arg_kt_index(cb_arg->single_kt);
1482 cb_arg->s_ocsp = NULL;
1483 cb_arg->m_ocsp[index] = tmp_ocsp;
1484 cb_arg->is_single = 0;
1485 cb_arg->single_kt = 0;
1486
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001487 pkey = X509_get_pubkey(x);
1488 key_type = EVP_PKEY_base_id(pkey);
1489 EVP_PKEY_free(pkey);
1490
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001491 index = ssl_sock_get_ocsp_arg_kt_index(key_type);
yanbzhube2774d2015-12-10 15:07:30 -05001492 if (index >= 0 && !cb_arg->m_ocsp[index])
1493 cb_arg->m_ocsp[index] = iocsp;
1494
1495 }
Emeric Brun4147b2e2014-06-16 18:36:30 +02001496
1497 ret = 0;
1498
1499 warn = NULL;
William Lallemand246c0242019-10-11 08:59:13 +02001500 if (ssl_sock_load_ocsp_response(ckch->ocsp_response, ocsp, cid, &warn)) {
William Lallemand3b5f3602019-10-16 18:05:05 +02001501 memprintf(&warn, "Loading: %s. Content will be ignored", warn ? warn : "failure");
Christopher Faulet767a84b2017-11-24 16:50:31 +01001502 ha_warning("%s.\n", warn);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001503 }
1504
1505out:
Emeric Brun4147b2e2014-06-16 18:36:30 +02001506 if (cid)
1507 OCSP_CERTID_free(cid);
1508
1509 if (ocsp)
1510 free(ocsp);
1511
1512 if (warn)
1513 free(warn);
1514
Emeric Brun4147b2e2014-06-16 18:36:30 +02001515 return ret;
1516}
William Lallemand4a660132019-10-14 14:51:41 +02001517#else /* OPENSSL_IS_BORINGSSL */
1518static int ssl_sock_load_ocsp(SSL_CTX *ctx, const struct cert_key_and_chain *ckch)
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02001519{
William Lallemand4a660132019-10-14 14:51:41 +02001520 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 +02001521}
1522#endif
1523
William Lallemand4a660132019-10-14 14:51:41 +02001524#endif
1525
1526
Willy Tarreau5db847a2019-05-09 14:13:35 +02001527#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001528
1529#define CT_EXTENSION_TYPE 18
1530
1531static int sctl_ex_index = -1;
1532
1533/*
1534 * Try to parse Signed Certificate Timestamp List structure. This function
1535 * makes only basic test if the data seems like SCTL. No signature validation
1536 * is performed.
1537 */
Willy Tarreau83061a82018-07-13 11:56:34 +02001538static int ssl_sock_parse_sctl(struct buffer *sctl)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001539{
1540 int ret = 1;
1541 int len, pos, sct_len;
1542 unsigned char *data;
1543
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001544 if (sctl->data < 2)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001545 goto out;
1546
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001547 data = (unsigned char *) sctl->area;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001548 len = (data[0] << 8) | data[1];
1549
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001550 if (len + 2 != sctl->data)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001551 goto out;
1552
1553 data = data + 2;
1554 pos = 0;
1555 while (pos < len) {
1556 if (len - pos < 2)
1557 goto out;
1558
1559 sct_len = (data[pos] << 8) | data[pos + 1];
1560 if (pos + sct_len + 2 > len)
1561 goto out;
1562
1563 pos += sct_len + 2;
1564 }
1565
1566 ret = 0;
1567
1568out:
1569 return ret;
1570}
1571
William Lallemand0dfae6c2019-10-16 18:06:58 +02001572/* Try to load a sctl from a buffer <buf> if not NULL, or read the file <sctl_path>
1573 * It fills the ckch->sctl buffer
1574 * return 0 on success or != 0 on failure */
1575static 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 +01001576{
1577 int fd = -1;
1578 int r = 0;
1579 int ret = 1;
William Lallemand0dfae6c2019-10-16 18:06:58 +02001580 struct buffer tmp;
1581 struct buffer *src;
1582 struct buffer *sctl;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001583
William Lallemand0dfae6c2019-10-16 18:06:58 +02001584 if (buf) {
1585 tmp.area = buf;
1586 tmp.data = strlen(buf);
1587 tmp.size = tmp.data + 1;
1588 src = &tmp;
1589 } else {
1590 fd = open(sctl_path, O_RDONLY);
1591 if (fd == -1)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001592 goto end;
William Lallemand0dfae6c2019-10-16 18:06:58 +02001593
1594 trash.data = 0;
1595 while (trash.data < trash.size) {
1596 r = read(fd, trash.area + trash.data, trash.size - trash.data);
1597 if (r < 0) {
1598 if (errno == EINTR)
1599 continue;
1600 goto end;
1601 }
1602 else if (r == 0) {
1603 break;
1604 }
1605 trash.data += r;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001606 }
William Lallemand0dfae6c2019-10-16 18:06:58 +02001607 src = &trash;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001608 }
1609
William Lallemand0dfae6c2019-10-16 18:06:58 +02001610 ret = ssl_sock_parse_sctl(src);
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001611 if (ret)
1612 goto end;
1613
William Lallemand0dfae6c2019-10-16 18:06:58 +02001614 sctl = calloc(1, sizeof(*sctl));
1615 if (!chunk_dup(sctl, src)) {
1616 free(sctl);
1617 sctl = NULL;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001618 goto end;
1619 }
Emmanuel Hocdet224a0872020-01-16 15:15:49 +01001620 /* no error, fill ckch with new context, old context must be free */
1621 if (ckch->sctl) {
1622 free(ckch->sctl->area);
1623 ckch->sctl->area = NULL;
1624 free(ckch->sctl);
1625 }
William Lallemand0dfae6c2019-10-16 18:06:58 +02001626 ckch->sctl = sctl;
Emmanuel Hocdet224a0872020-01-16 15:15:49 +01001627 ret = 0;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001628end:
1629 if (fd != -1)
1630 close(fd);
1631
1632 return ret;
1633}
1634
1635int ssl_sock_sctl_add_cbk(SSL *ssl, unsigned ext_type, const unsigned char **out, size_t *outlen, int *al, void *add_arg)
1636{
Willy Tarreau83061a82018-07-13 11:56:34 +02001637 struct buffer *sctl = add_arg;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001638
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001639 *out = (unsigned char *) sctl->area;
1640 *outlen = sctl->data;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001641
1642 return 1;
1643}
1644
1645int ssl_sock_sctl_parse_cbk(SSL *s, unsigned int ext_type, const unsigned char *in, size_t inlen, int *al, void *parse_arg)
1646{
1647 return 1;
1648}
1649
William Lallemanda17f4112019-10-10 15:16:44 +02001650static int ssl_sock_load_sctl(SSL_CTX *ctx, struct buffer *sctl)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001651{
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001652 int ret = -1;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001653
William Lallemanda17f4112019-10-10 15:16:44 +02001654 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 +01001655 goto out;
1656
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001657 SSL_CTX_set_ex_data(ctx, sctl_ex_index, sctl);
1658
1659 ret = 0;
1660
1661out:
1662 return ret;
1663}
1664
1665#endif
1666
Emeric Brune1f38db2012-09-03 20:36:47 +02001667void ssl_sock_infocbk(const SSL *ssl, int where, int ret)
1668{
Thierry FOURNIER28962c92018-06-17 21:37:05 +02001669 struct connection *conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001670 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
Emeric Brund8b2bb52014-01-28 15:43:53 +01001671 BIO *write_bio;
Willy Tarreau622317d2015-02-27 16:36:16 +01001672 (void)ret; /* shut gcc stupid warning */
Emeric Brune1f38db2012-09-03 20:36:47 +02001673
Dirkjan Bussink526894f2019-01-21 09:35:03 -08001674#ifndef SSL_OP_NO_RENEGOTIATION
1675 /* Please note that BoringSSL defines this macro to zero so don't
1676 * change this to #if and do not assign a default value to this macro!
1677 */
Emeric Brune1f38db2012-09-03 20:36:47 +02001678 if (where & SSL_CB_HANDSHAKE_START) {
1679 /* Disable renegotiation (CVE-2009-3555) */
Willy Tarreauc192b0a2020-01-23 09:11:58 +01001680 if ((conn->flags & (CO_FL_WAIT_L6_CONN | CO_FL_EARLY_SSL_HS | CO_FL_EARLY_DATA)) == 0) {
Emeric Brune1f38db2012-09-03 20:36:47 +02001681 conn->flags |= CO_FL_ERROR;
Willy Tarreau20879a02012-12-03 16:32:10 +01001682 conn->err_code = CO_ER_SSL_RENEG;
1683 }
Emeric Brune1f38db2012-09-03 20:36:47 +02001684 }
Dirkjan Bussink526894f2019-01-21 09:35:03 -08001685#endif
Emeric Brund8b2bb52014-01-28 15:43:53 +01001686
1687 if ((where & SSL_CB_ACCEPT_LOOP) == SSL_CB_ACCEPT_LOOP) {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001688 if (!(ctx->xprt_st & SSL_SOCK_ST_FL_16K_WBFSIZE)) {
Emeric Brund8b2bb52014-01-28 15:43:53 +01001689 /* Long certificate chains optimz
1690 If write and read bios are differents, we
1691 consider that the buffering was activated,
1692 so we rise the output buffer size from 4k
1693 to 16k */
1694 write_bio = SSL_get_wbio(ssl);
1695 if (write_bio != SSL_get_rbio(ssl)) {
1696 BIO_set_write_buffer_size(write_bio, 16384);
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001697 ctx->xprt_st |= SSL_SOCK_ST_FL_16K_WBFSIZE;
Emeric Brund8b2bb52014-01-28 15:43:53 +01001698 }
1699 }
1700 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02001701}
1702
Emeric Brune64aef12012-09-21 13:15:06 +02001703/* Callback is called for each certificate of the chain during a verify
1704 ok is set to 1 if preverify detect no error on current certificate.
1705 Returns 0 to break the handshake, 1 otherwise. */
Evan Broderbe554312013-06-27 00:05:25 -07001706int ssl_sock_bind_verifycbk(int ok, X509_STORE_CTX *x_store)
Emeric Brune64aef12012-09-21 13:15:06 +02001707{
1708 SSL *ssl;
1709 struct connection *conn;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001710 struct ssl_sock_ctx *ctx;
Emeric Brun81c00f02012-09-21 14:31:21 +02001711 int err, depth;
Emeric Brune64aef12012-09-21 13:15:06 +02001712
1713 ssl = X509_STORE_CTX_get_ex_data(x_store, SSL_get_ex_data_X509_STORE_CTX_idx());
Thierry FOURNIER28962c92018-06-17 21:37:05 +02001714 conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Emeric Brune64aef12012-09-21 13:15:06 +02001715
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001716 ctx = conn->xprt_ctx;
1717
1718 ctx->xprt_st |= SSL_SOCK_ST_FL_VERIFY_DONE;
Emeric Brune64aef12012-09-21 13:15:06 +02001719
Emeric Brun81c00f02012-09-21 14:31:21 +02001720 if (ok) /* no errors */
1721 return ok;
1722
1723 depth = X509_STORE_CTX_get_error_depth(x_store);
1724 err = X509_STORE_CTX_get_error(x_store);
1725
1726 /* check if CA error needs to be ignored */
1727 if (depth > 0) {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001728 if (!SSL_SOCK_ST_TO_CA_ERROR(ctx->xprt_st)) {
1729 ctx->xprt_st |= SSL_SOCK_CA_ERROR_TO_ST(err);
1730 ctx->xprt_st |= SSL_SOCK_CAEDEPTH_TO_ST(depth);
Emeric Brunf282a812012-09-21 15:27:54 +02001731 }
1732
Willy Tarreau731248f2020-02-04 14:02:02 +01001733 if (err < 64 && __objt_listener(conn->target)->bind_conf->ca_ignerr & (1ULL << err)) {
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02001734 ssl_sock_dump_errors(conn);
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001735 ERR_clear_error();
Emeric Brun81c00f02012-09-21 14:31:21 +02001736 return 1;
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001737 }
Emeric Brun81c00f02012-09-21 14:31:21 +02001738
Willy Tarreau20879a02012-12-03 16:32:10 +01001739 conn->err_code = CO_ER_SSL_CA_FAIL;
Emeric Brun81c00f02012-09-21 14:31:21 +02001740 return 0;
1741 }
1742
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001743 if (!SSL_SOCK_ST_TO_CRTERROR(ctx->xprt_st))
1744 ctx->xprt_st |= SSL_SOCK_CRTERROR_TO_ST(err);
Emeric Brunf282a812012-09-21 15:27:54 +02001745
Emeric Brun81c00f02012-09-21 14:31:21 +02001746 /* check if certificate error needs to be ignored */
Willy Tarreau731248f2020-02-04 14:02:02 +01001747 if (err < 64 && __objt_listener(conn->target)->bind_conf->crt_ignerr & (1ULL << err)) {
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02001748 ssl_sock_dump_errors(conn);
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001749 ERR_clear_error();
Emeric Brun81c00f02012-09-21 14:31:21 +02001750 return 1;
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001751 }
Emeric Brun81c00f02012-09-21 14:31:21 +02001752
Willy Tarreau20879a02012-12-03 16:32:10 +01001753 conn->err_code = CO_ER_SSL_CRT_FAIL;
Emeric Brun81c00f02012-09-21 14:31:21 +02001754 return 0;
Emeric Brune64aef12012-09-21 13:15:06 +02001755}
1756
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001757static inline
1758void ssl_sock_parse_clienthello(int write_p, int version, int content_type,
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001759 const void *buf, size_t len, SSL *ssl)
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001760{
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001761 struct ssl_capture *capture;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001762 unsigned char *msg;
1763 unsigned char *end;
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001764 size_t rec_len;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001765
1766 /* This function is called for "from client" and "to server"
1767 * connections. The combination of write_p == 0 and content_type == 22
Joseph Herlant017b3da2018-11-15 09:07:59 -08001768 * is only available during "from client" connection.
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001769 */
1770
1771 /* "write_p" is set to 0 is the bytes are received messages,
1772 * otherwise it is set to 1.
1773 */
1774 if (write_p != 0)
1775 return;
1776
1777 /* content_type contains the type of message received or sent
1778 * according with the SSL/TLS protocol spec. This message is
1779 * encoded with one byte. The value 256 (two bytes) is used
1780 * for designing the SSL/TLS record layer. According with the
1781 * rfc6101, the expected message (other than 256) are:
1782 * - change_cipher_spec(20)
1783 * - alert(21)
1784 * - handshake(22)
1785 * - application_data(23)
1786 * - (255)
1787 * We are interessed by the handshake and specially the client
1788 * hello.
1789 */
1790 if (content_type != 22)
1791 return;
1792
1793 /* The message length is at least 4 bytes, containing the
1794 * message type and the message length.
1795 */
1796 if (len < 4)
1797 return;
1798
1799 /* First byte of the handshake message id the type of
1800 * message. The konwn types are:
1801 * - hello_request(0)
1802 * - client_hello(1)
1803 * - server_hello(2)
1804 * - certificate(11)
1805 * - server_key_exchange (12)
1806 * - certificate_request(13)
1807 * - server_hello_done(14)
1808 * We are interested by the client hello.
1809 */
1810 msg = (unsigned char *)buf;
1811 if (msg[0] != 1)
1812 return;
1813
1814 /* Next three bytes are the length of the message. The total length
1815 * must be this decoded length + 4. If the length given as argument
1816 * is not the same, we abort the protocol dissector.
1817 */
1818 rec_len = (msg[1] << 16) + (msg[2] << 8) + msg[3];
1819 if (len < rec_len + 4)
1820 return;
1821 msg += 4;
1822 end = msg + rec_len;
1823 if (end < msg)
1824 return;
1825
1826 /* Expect 2 bytes for protocol version (1 byte for major and 1 byte
1827 * for minor, the random, composed by 4 bytes for the unix time and
Baptiste Assmann6be139f2018-11-28 15:20:25 +01001828 * 28 bytes for unix payload. So we jump 1 + 1 + 4 + 28.
1829 */
1830 msg += 1 + 1 + 4 + 28;
1831 if (msg > end)
1832 return;
1833
1834 /* Next, is session id:
1835 * if present, we have to jump by length + 1 for the size information
1836 * if not present, we have to jump by 1 only
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001837 */
Baptiste Assmann6be139f2018-11-28 15:20:25 +01001838 if (msg[0] > 0)
1839 msg += msg[0];
1840 msg += 1;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001841 if (msg > end)
1842 return;
1843
1844 /* Next two bytes are the ciphersuite length. */
1845 if (msg + 2 > end)
1846 return;
1847 rec_len = (msg[0] << 8) + msg[1];
1848 msg += 2;
1849 if (msg + rec_len > end || msg + rec_len < msg)
1850 return;
1851
Willy Tarreaubafbe012017-11-24 17:34:44 +01001852 capture = pool_alloc_dirty(pool_head_ssl_capture);
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001853 if (!capture)
1854 return;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001855 /* Compute the xxh64 of the ciphersuite. */
1856 capture->xxh64 = XXH64(msg, rec_len, 0);
1857
1858 /* Capture the ciphersuite. */
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001859 capture->ciphersuite_len = (global_ssl.capture_cipherlist < rec_len) ?
1860 global_ssl.capture_cipherlist : rec_len;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001861 memcpy(capture->ciphersuite, msg, capture->ciphersuite_len);
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001862
1863 SSL_set_ex_data(ssl, ssl_capture_ptr_index, capture);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001864}
1865
Emeric Brun29f037d2014-04-25 19:05:36 +02001866/* Callback is called for ssl protocol analyse */
1867void ssl_sock_msgcbk(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg)
1868{
Emeric Brun29f037d2014-04-25 19:05:36 +02001869#ifdef TLS1_RT_HEARTBEAT
1870 /* test heartbeat received (write_p is set to 0
1871 for a received record) */
Willy Tarreauf51c6982014-04-25 20:02:39 +02001872 if ((content_type == TLS1_RT_HEARTBEAT) && (write_p == 0)) {
Thierry FOURNIER28962c92018-06-17 21:37:05 +02001873 struct connection *conn = SSL_get_ex_data(ssl, ssl_app_data_index);
William Lallemand7e1770b2019-05-13 14:31:34 +02001874 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
Willy Tarreauf51c6982014-04-25 20:02:39 +02001875 const unsigned char *p = buf;
1876 unsigned int payload;
1877
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001878 ctx->xprt_st |= SSL_SOCK_RECV_HEARTBEAT;
Willy Tarreauf51c6982014-04-25 20:02:39 +02001879
1880 /* Check if this is a CVE-2014-0160 exploitation attempt. */
1881 if (*p != TLS1_HB_REQUEST)
1882 return;
1883
Willy Tarreauaeed6722014-04-25 23:59:58 +02001884 if (len < 1 + 2 + 16) /* 1 type + 2 size + 0 payload + 16 padding */
Willy Tarreauf51c6982014-04-25 20:02:39 +02001885 goto kill_it;
1886
1887 payload = (p[1] * 256) + p[2];
Willy Tarreau3b2fdb62014-04-25 23:44:22 +02001888 if (3 + payload + 16 <= len)
Willy Tarreauf51c6982014-04-25 20:02:39 +02001889 return; /* OK no problem */
Willy Tarreauaeed6722014-04-25 23:59:58 +02001890 kill_it:
Willy Tarreau3b2fdb62014-04-25 23:44:22 +02001891 /* We have a clear heartbleed attack (CVE-2014-0160), the
1892 * advertised payload is larger than the advertised packet
1893 * length, so we have garbage in the buffer between the
1894 * payload and the end of the buffer (p+len). We can't know
1895 * if the SSL stack is patched, and we don't know if we can
1896 * safely wipe out the area between p+3+len and payload.
1897 * So instead, we prevent the response from being sent by
1898 * setting the max_send_fragment to 0 and we report an SSL
1899 * error, which will kill this connection. It will be reported
1900 * above as SSL_ERROR_SSL while an other handshake failure with
Willy Tarreauf51c6982014-04-25 20:02:39 +02001901 * a heartbeat message will be reported as SSL_ERROR_SYSCALL.
1902 */
Willy Tarreau3b2fdb62014-04-25 23:44:22 +02001903 ssl->max_send_fragment = 0;
Willy Tarreauf51c6982014-04-25 20:02:39 +02001904 SSLerr(SSL_F_TLS1_HEARTBEAT, SSL_R_SSL_HANDSHAKE_FAILURE);
1905 return;
1906 }
Emeric Brun29f037d2014-04-25 19:05:36 +02001907#endif
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001908 if (global_ssl.capture_cipherlist > 0)
1909 ssl_sock_parse_clienthello(write_p, version, content_type, buf, len, ssl);
Emeric Brun29f037d2014-04-25 19:05:36 +02001910}
1911
Bernard Spil13c53f82018-02-15 13:34:58 +01001912#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Olivier Houchardc7566002018-11-20 23:33:50 +01001913static int ssl_sock_srv_select_protos(SSL *s, unsigned char **out, unsigned char *outlen,
1914 const unsigned char *in, unsigned int inlen,
1915 void *arg)
1916{
1917 struct server *srv = arg;
1918
1919 if (SSL_select_next_proto(out, outlen, in, inlen, (unsigned char *)srv->ssl_ctx.npn_str,
1920 srv->ssl_ctx.npn_len) == OPENSSL_NPN_NEGOTIATED)
1921 return SSL_TLSEXT_ERR_OK;
1922 return SSL_TLSEXT_ERR_NOACK;
1923}
1924#endif
1925
1926#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02001927/* This callback is used so that the server advertises the list of
1928 * negociable protocols for NPN.
1929 */
1930static int ssl_sock_advertise_npn_protos(SSL *s, const unsigned char **data,
1931 unsigned int *len, void *arg)
1932{
Emmanuel Hocdet98263292016-12-29 18:26:15 +01001933 struct ssl_bind_conf *conf = arg;
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02001934
1935 *data = (const unsigned char *)conf->npn_str;
1936 *len = conf->npn_len;
1937 return SSL_TLSEXT_ERR_OK;
1938}
1939#endif
1940
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01001941#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02001942/* This callback is used so that the server advertises the list of
1943 * negociable protocols for ALPN.
1944 */
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01001945static int ssl_sock_advertise_alpn_protos(SSL *s, const unsigned char **out,
1946 unsigned char *outlen,
1947 const unsigned char *server,
1948 unsigned int server_len, void *arg)
Willy Tarreauab861d32013-04-02 02:30:41 +02001949{
Emmanuel Hocdet98263292016-12-29 18:26:15 +01001950 struct ssl_bind_conf *conf = arg;
Willy Tarreauab861d32013-04-02 02:30:41 +02001951
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01001952 if (SSL_select_next_proto((unsigned char**) out, outlen, (const unsigned char *)conf->alpn_str,
1953 conf->alpn_len, server, server_len) != OPENSSL_NPN_NEGOTIATED) {
1954 return SSL_TLSEXT_ERR_NOACK;
1955 }
Willy Tarreauab861d32013-04-02 02:30:41 +02001956 return SSL_TLSEXT_ERR_OK;
1957}
1958#endif
1959
Willy Tarreauc8ad3be2015-06-17 15:48:26 +02001960#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01001961#ifndef SSL_NO_GENERATE_CERTIFICATES
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001962
Christopher Faulet30548802015-06-11 13:39:32 +02001963/* Create a X509 certificate with the specified servername and serial. This
1964 * function returns a SSL_CTX object or NULL if an error occurs. */
Christopher Faulet7969a332015-10-09 11:15:03 +02001965static SSL_CTX *
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001966ssl_sock_do_create_cert(const char *servername, struct bind_conf *bind_conf, SSL *ssl)
Christopher Faulet31af49d2015-06-09 17:29:50 +02001967{
Christopher Faulet7969a332015-10-09 11:15:03 +02001968 X509 *cacert = bind_conf->ca_sign_cert;
1969 EVP_PKEY *capkey = bind_conf->ca_sign_pkey;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001970 SSL_CTX *ssl_ctx = NULL;
1971 X509 *newcrt = NULL;
1972 EVP_PKEY *pkey = NULL;
Emmanuel Hocdet15969292017-08-11 10:56:00 +02001973 SSL *tmp_ssl = NULL;
Emmanuel Hocdeta9b84022018-10-01 18:41:36 +02001974 CONF *ctmp = NULL;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001975 X509_NAME *name;
1976 const EVP_MD *digest;
1977 X509V3_CTX ctx;
1978 unsigned int i;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001979 int key_type;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001980
Christopher Faulet48a83322017-07-28 16:56:09 +02001981 /* Get the private key of the default certificate and use it */
Willy Tarreau5db847a2019-05-09 14:13:35 +02001982#if (HA_OPENSSL_VERSION_NUMBER >= 0x10002000L)
Emmanuel Hocdet15969292017-08-11 10:56:00 +02001983 pkey = SSL_CTX_get0_privatekey(bind_conf->default_ctx);
1984#else
1985 tmp_ssl = SSL_new(bind_conf->default_ctx);
1986 if (tmp_ssl)
1987 pkey = SSL_get_privatekey(tmp_ssl);
1988#endif
1989 if (!pkey)
Christopher Faulet31af49d2015-06-09 17:29:50 +02001990 goto mkcert_error;
1991
1992 /* Create the certificate */
1993 if (!(newcrt = X509_new()))
1994 goto mkcert_error;
1995
1996 /* Set version number for the certificate (X509v3) and the serial
1997 * number */
1998 if (X509_set_version(newcrt, 2L) != 1)
1999 goto mkcert_error;
Olivier Houchard2be5a4c2019-03-08 18:54:43 +01002000 ASN1_INTEGER_set(X509_get_serialNumber(newcrt), _HA_ATOMIC_ADD(&ssl_ctx_serial, 1));
Christopher Faulet31af49d2015-06-09 17:29:50 +02002001
2002 /* Set duration for the certificate */
Rosen Penev68185952018-12-14 08:47:02 -08002003 if (!X509_gmtime_adj(X509_getm_notBefore(newcrt), (long)-60*60*24) ||
2004 !X509_gmtime_adj(X509_getm_notAfter(newcrt),(long)60*60*24*365))
Christopher Faulet31af49d2015-06-09 17:29:50 +02002005 goto mkcert_error;
2006
2007 /* set public key in the certificate */
2008 if (X509_set_pubkey(newcrt, pkey) != 1)
2009 goto mkcert_error;
2010
2011 /* Set issuer name from the CA */
2012 if (!(name = X509_get_subject_name(cacert)))
2013 goto mkcert_error;
2014 if (X509_set_issuer_name(newcrt, name) != 1)
2015 goto mkcert_error;
2016
2017 /* Set the subject name using the same, but the CN */
2018 name = X509_NAME_dup(name);
2019 if (X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC,
2020 (const unsigned char *)servername,
2021 -1, -1, 0) != 1) {
2022 X509_NAME_free(name);
2023 goto mkcert_error;
2024 }
2025 if (X509_set_subject_name(newcrt, name) != 1) {
2026 X509_NAME_free(name);
2027 goto mkcert_error;
2028 }
2029 X509_NAME_free(name);
2030
2031 /* Add x509v3 extensions as specified */
Emmanuel Hocdeta9b84022018-10-01 18:41:36 +02002032 ctmp = NCONF_new(NULL);
Christopher Faulet31af49d2015-06-09 17:29:50 +02002033 X509V3_set_ctx(&ctx, cacert, newcrt, NULL, NULL, 0);
2034 for (i = 0; i < X509V3_EXT_SIZE; i++) {
2035 X509_EXTENSION *ext;
2036
Emmanuel Hocdeta9b84022018-10-01 18:41:36 +02002037 if (!(ext = X509V3_EXT_nconf(ctmp, &ctx, x509v3_ext_names[i], x509v3_ext_values[i])))
Christopher Faulet31af49d2015-06-09 17:29:50 +02002038 goto mkcert_error;
2039 if (!X509_add_ext(newcrt, ext, -1)) {
2040 X509_EXTENSION_free(ext);
2041 goto mkcert_error;
2042 }
2043 X509_EXTENSION_free(ext);
2044 }
2045
2046 /* Sign the certificate with the CA private key */
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002047
2048 key_type = EVP_PKEY_base_id(capkey);
2049
2050 if (key_type == EVP_PKEY_DSA)
2051 digest = EVP_sha1();
2052 else if (key_type == EVP_PKEY_RSA)
Christopher Faulet31af49d2015-06-09 17:29:50 +02002053 digest = EVP_sha256();
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002054 else if (key_type == EVP_PKEY_EC)
Christopher Faulet7969a332015-10-09 11:15:03 +02002055 digest = EVP_sha256();
2056 else {
Willy Tarreau9a1ab082019-05-09 13:26:41 +02002057#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000000fL) && !defined(OPENSSL_IS_BORINGSSL)
Christopher Faulet7969a332015-10-09 11:15:03 +02002058 int nid;
2059
2060 if (EVP_PKEY_get_default_digest_nid(capkey, &nid) <= 0)
2061 goto mkcert_error;
2062 if (!(digest = EVP_get_digestbynid(nid)))
2063 goto mkcert_error;
Christopher Faulete7db2162015-10-19 13:59:24 +02002064#else
2065 goto mkcert_error;
2066#endif
Christopher Faulet7969a332015-10-09 11:15:03 +02002067 }
2068
Christopher Faulet31af49d2015-06-09 17:29:50 +02002069 if (!(X509_sign(newcrt, capkey, digest)))
2070 goto mkcert_error;
2071
2072 /* Create and set the new SSL_CTX */
2073 if (!(ssl_ctx = SSL_CTX_new(SSLv23_server_method())))
2074 goto mkcert_error;
2075 if (!SSL_CTX_use_PrivateKey(ssl_ctx, pkey))
2076 goto mkcert_error;
2077 if (!SSL_CTX_use_certificate(ssl_ctx, newcrt))
2078 goto mkcert_error;
2079 if (!SSL_CTX_check_private_key(ssl_ctx))
2080 goto mkcert_error;
2081
2082 if (newcrt) X509_free(newcrt);
Christopher Faulet7969a332015-10-09 11:15:03 +02002083
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01002084#ifndef OPENSSL_NO_DH
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02002085 SSL_CTX_set_tmp_dh_callback(ssl_ctx, ssl_get_tmp_dh);
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01002086#endif
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02002087#if defined(SSL_CTX_set_tmp_ecdh) && !defined(OPENSSL_NO_ECDH)
2088 {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01002089 const char *ecdhe = (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe : ECDHE_DEFAULT_CURVE);
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02002090 EC_KEY *ecc;
2091 int nid;
2092
2093 if ((nid = OBJ_sn2nid(ecdhe)) == NID_undef)
2094 goto end;
2095 if (!(ecc = EC_KEY_new_by_curve_name(nid)))
2096 goto end;
2097 SSL_CTX_set_tmp_ecdh(ssl_ctx, ecc);
2098 EC_KEY_free(ecc);
2099 }
2100#endif
2101 end:
Christopher Faulet31af49d2015-06-09 17:29:50 +02002102 return ssl_ctx;
2103
2104 mkcert_error:
Emmanuel Hocdeta9b84022018-10-01 18:41:36 +02002105 if (ctmp) NCONF_free(ctmp);
Emmanuel Hocdet15969292017-08-11 10:56:00 +02002106 if (tmp_ssl) SSL_free(tmp_ssl);
Christopher Faulet31af49d2015-06-09 17:29:50 +02002107 if (ssl_ctx) SSL_CTX_free(ssl_ctx);
2108 if (newcrt) X509_free(newcrt);
Christopher Faulet31af49d2015-06-09 17:29:50 +02002109 return NULL;
2110}
2111
Christopher Faulet7969a332015-10-09 11:15:03 +02002112SSL_CTX *
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002113ssl_sock_create_cert(struct connection *conn, const char *servername, unsigned int key)
Christopher Faulet7969a332015-10-09 11:15:03 +02002114{
Willy Tarreau07d94e42018-09-20 10:57:52 +02002115 struct bind_conf *bind_conf = __objt_listener(conn->target)->bind_conf;
Olivier Houchard66ab4982019-02-26 18:37:15 +01002116 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002117
Olivier Houchard66ab4982019-02-26 18:37:15 +01002118 return ssl_sock_do_create_cert(servername, bind_conf, ctx->ssl);
Christopher Faulet7969a332015-10-09 11:15:03 +02002119}
2120
Christopher Faulet30548802015-06-11 13:39:32 +02002121/* Do a lookup for a certificate in the LRU cache used to store generated
Emeric Brun821bb9b2017-06-15 16:37:39 +02002122 * certificates and immediately assign it to the SSL session if not null. */
Christopher Faulet30548802015-06-11 13:39:32 +02002123SSL_CTX *
Emeric Brun821bb9b2017-06-15 16:37:39 +02002124ssl_sock_assign_generated_cert(unsigned int key, struct bind_conf *bind_conf, SSL *ssl)
Christopher Faulet30548802015-06-11 13:39:32 +02002125{
2126 struct lru64 *lru = NULL;
2127
2128 if (ssl_ctx_lru_tree) {
Willy Tarreau03f4ec42018-05-17 10:56:47 +02002129 HA_RWLOCK_WRLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002130 lru = lru64_lookup(key, ssl_ctx_lru_tree, bind_conf->ca_sign_cert, 0);
Emeric Brun821bb9b2017-06-15 16:37:39 +02002131 if (lru && lru->domain) {
2132 if (ssl)
2133 SSL_set_SSL_CTX(ssl, (SSL_CTX *)lru->data);
Willy Tarreau03f4ec42018-05-17 10:56:47 +02002134 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet30548802015-06-11 13:39:32 +02002135 return (SSL_CTX *)lru->data;
Emeric Brun821bb9b2017-06-15 16:37:39 +02002136 }
Willy Tarreau03f4ec42018-05-17 10:56:47 +02002137 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet30548802015-06-11 13:39:32 +02002138 }
2139 return NULL;
2140}
2141
Emeric Brun821bb9b2017-06-15 16:37:39 +02002142/* Same as <ssl_sock_assign_generated_cert> but without SSL session. This
2143 * function is not thread-safe, it should only be used to check if a certificate
2144 * exists in the lru cache (with no warranty it will not be removed by another
2145 * thread). It is kept for backward compatibility. */
2146SSL_CTX *
2147ssl_sock_get_generated_cert(unsigned int key, struct bind_conf *bind_conf)
2148{
2149 return ssl_sock_assign_generated_cert(key, bind_conf, NULL);
2150}
2151
Christopher Fauletd2cab922015-07-28 16:03:47 +02002152/* Set a certificate int the LRU cache used to store generated
2153 * certificate. Return 0 on success, otherwise -1 */
2154int
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002155ssl_sock_set_generated_cert(SSL_CTX *ssl_ctx, unsigned int key, struct bind_conf *bind_conf)
Christopher Faulet30548802015-06-11 13:39:32 +02002156{
2157 struct lru64 *lru = NULL;
2158
2159 if (ssl_ctx_lru_tree) {
Christopher Faulet2a944ee2017-11-07 10:42:54 +01002160 HA_RWLOCK_WRLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002161 lru = lru64_get(key, ssl_ctx_lru_tree, bind_conf->ca_sign_cert, 0);
Emeric Brun821bb9b2017-06-15 16:37:39 +02002162 if (!lru) {
Christopher Faulet2a944ee2017-11-07 10:42:54 +01002163 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Fauletd2cab922015-07-28 16:03:47 +02002164 return -1;
Emeric Brun821bb9b2017-06-15 16:37:39 +02002165 }
Christopher Faulet30548802015-06-11 13:39:32 +02002166 if (lru->domain && lru->data)
2167 lru->free((SSL_CTX *)lru->data);
Christopher Faulet7969a332015-10-09 11:15:03 +02002168 lru64_commit(lru, ssl_ctx, bind_conf->ca_sign_cert, 0, (void (*)(void *))SSL_CTX_free);
Christopher Faulet2a944ee2017-11-07 10:42:54 +01002169 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Fauletd2cab922015-07-28 16:03:47 +02002170 return 0;
Christopher Faulet30548802015-06-11 13:39:32 +02002171 }
Christopher Fauletd2cab922015-07-28 16:03:47 +02002172 return -1;
Christopher Faulet30548802015-06-11 13:39:32 +02002173}
2174
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002175/* Compute the key of the certificate. */
Christopher Faulet30548802015-06-11 13:39:32 +02002176unsigned int
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002177ssl_sock_generated_cert_key(const void *data, size_t len)
Christopher Faulet30548802015-06-11 13:39:32 +02002178{
2179 return XXH32(data, len, ssl_ctx_lru_seed);
2180}
2181
Willy Tarreau2f63ef42015-10-20 15:16:01 +02002182/* Generate a cert and immediately assign it to the SSL session so that the cert's
2183 * refcount is maintained regardless of the cert's presence in the LRU cache.
2184 */
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002185static int
Christopher Faulet7969a332015-10-09 11:15:03 +02002186ssl_sock_generate_certificate(const char *servername, struct bind_conf *bind_conf, SSL *ssl)
Christopher Faulet31af49d2015-06-09 17:29:50 +02002187{
2188 X509 *cacert = bind_conf->ca_sign_cert;
Christopher Faulet31af49d2015-06-09 17:29:50 +02002189 SSL_CTX *ssl_ctx = NULL;
2190 struct lru64 *lru = NULL;
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002191 unsigned int key;
Christopher Faulet31af49d2015-06-09 17:29:50 +02002192
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002193 key = ssl_sock_generated_cert_key(servername, strlen(servername));
Christopher Faulet31af49d2015-06-09 17:29:50 +02002194 if (ssl_ctx_lru_tree) {
Christopher Faulet2a944ee2017-11-07 10:42:54 +01002195 HA_RWLOCK_WRLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002196 lru = lru64_get(key, ssl_ctx_lru_tree, cacert, 0);
Christopher Faulet31af49d2015-06-09 17:29:50 +02002197 if (lru && lru->domain)
2198 ssl_ctx = (SSL_CTX *)lru->data;
Christopher Fauletd2cab922015-07-28 16:03:47 +02002199 if (!ssl_ctx && lru) {
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002200 ssl_ctx = ssl_sock_do_create_cert(servername, bind_conf, ssl);
Christopher Faulet31af49d2015-06-09 17:29:50 +02002201 lru64_commit(lru, ssl_ctx, cacert, 0, (void (*)(void *))SSL_CTX_free);
Christopher Fauletd2cab922015-07-28 16:03:47 +02002202 }
Willy Tarreau2f63ef42015-10-20 15:16:01 +02002203 SSL_set_SSL_CTX(ssl, ssl_ctx);
Christopher Faulet2a944ee2017-11-07 10:42:54 +01002204 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002205 return 1;
Christopher Faulet31af49d2015-06-09 17:29:50 +02002206 }
Willy Tarreau2f63ef42015-10-20 15:16:01 +02002207 else {
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002208 ssl_ctx = ssl_sock_do_create_cert(servername, bind_conf, ssl);
Willy Tarreau2f63ef42015-10-20 15:16:01 +02002209 SSL_set_SSL_CTX(ssl, ssl_ctx);
2210 /* No LRU cache, this CTX will be released as soon as the session dies */
2211 SSL_CTX_free(ssl_ctx);
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002212 return 1;
Willy Tarreau2f63ef42015-10-20 15:16:01 +02002213 }
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002214 return 0;
2215}
2216static int
2217ssl_sock_generate_certificate_from_conn(struct bind_conf *bind_conf, SSL *ssl)
2218{
2219 unsigned int key;
Thierry FOURNIER28962c92018-06-17 21:37:05 +02002220 struct connection *conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002221
Willy Tarreauf5bdb642019-07-17 11:29:32 +02002222 if (conn_get_dst(conn)) {
Willy Tarreau085a1512019-07-17 14:47:35 +02002223 key = ssl_sock_generated_cert_key(conn->dst, get_addr_len(conn->dst));
Emeric Brun821bb9b2017-06-15 16:37:39 +02002224 if (ssl_sock_assign_generated_cert(key, bind_conf, ssl))
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002225 return 1;
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002226 }
2227 return 0;
Christopher Faulet31af49d2015-06-09 17:29:50 +02002228}
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002229#endif /* !defined SSL_NO_GENERATE_CERTIFICATES */
Christopher Faulet31af49d2015-06-09 17:29:50 +02002230
Willy Tarreau9a1ab082019-05-09 13:26:41 +02002231#if (HA_OPENSSL_VERSION_NUMBER < 0x1010000fL)
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002232typedef enum { SET_CLIENT, SET_SERVER } set_context_func;
2233
2234static void ctx_set_SSLv3_func(SSL_CTX *ctx, set_context_func c)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002235{
Emmanuel Hocdet23877ab2017-07-12 12:53:02 +02002236#if SSL_OP_NO_SSLv3
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002237 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, SSLv3_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002238 : SSL_CTX_set_ssl_version(ctx, SSLv3_client_method());
2239#endif
2240}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002241static void ctx_set_TLSv10_func(SSL_CTX *ctx, set_context_func c) {
2242 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, TLSv1_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002243 : SSL_CTX_set_ssl_version(ctx, TLSv1_client_method());
2244}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002245static void ctx_set_TLSv11_func(SSL_CTX *ctx, set_context_func c) {
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002246#if SSL_OP_NO_TLSv1_1
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002247 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, TLSv1_1_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002248 : SSL_CTX_set_ssl_version(ctx, TLSv1_1_client_method());
2249#endif
2250}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002251static void ctx_set_TLSv12_func(SSL_CTX *ctx, set_context_func c) {
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002252#if SSL_OP_NO_TLSv1_2
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002253 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, TLSv1_2_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002254 : SSL_CTX_set_ssl_version(ctx, TLSv1_2_client_method());
2255#endif
2256}
Bertrand Jacquina25282b2018-08-14 00:56:13 +01002257/* TLSv1.2 is the last supported version in this context. */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002258static void ctx_set_TLSv13_func(SSL_CTX *ctx, set_context_func c) {}
2259/* Unusable in this context. */
2260static void ssl_set_SSLv3_func(SSL *ssl, set_context_func c) {}
2261static void ssl_set_TLSv10_func(SSL *ssl, set_context_func c) {}
2262static void ssl_set_TLSv11_func(SSL *ssl, set_context_func c) {}
2263static void ssl_set_TLSv12_func(SSL *ssl, set_context_func c) {}
2264static void ssl_set_TLSv13_func(SSL *ssl, set_context_func c) {}
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002265#else /* openssl >= 1.1.0 */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002266typedef enum { SET_MIN, SET_MAX } set_context_func;
2267
2268static void ctx_set_SSLv3_func(SSL_CTX *ctx, set_context_func c) {
2269 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, SSL3_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002270 : SSL_CTX_set_min_proto_version(ctx, SSL3_VERSION);
2271}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002272static void ssl_set_SSLv3_func(SSL *ssl, set_context_func c) {
2273 c == SET_MAX ? SSL_set_max_proto_version(ssl, SSL3_VERSION)
2274 : SSL_set_min_proto_version(ssl, SSL3_VERSION);
2275}
2276static void ctx_set_TLSv10_func(SSL_CTX *ctx, set_context_func c) {
2277 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002278 : SSL_CTX_set_min_proto_version(ctx, TLS1_VERSION);
2279}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002280static void ssl_set_TLSv10_func(SSL *ssl, set_context_func c) {
2281 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_VERSION)
2282 : SSL_set_min_proto_version(ssl, TLS1_VERSION);
2283}
2284static void ctx_set_TLSv11_func(SSL_CTX *ctx, set_context_func c) {
2285 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_1_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002286 : SSL_CTX_set_min_proto_version(ctx, TLS1_1_VERSION);
2287}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002288static void ssl_set_TLSv11_func(SSL *ssl, set_context_func c) {
2289 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_1_VERSION)
2290 : SSL_set_min_proto_version(ssl, TLS1_1_VERSION);
2291}
2292static void ctx_set_TLSv12_func(SSL_CTX *ctx, set_context_func c) {
2293 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_2_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002294 : SSL_CTX_set_min_proto_version(ctx, TLS1_2_VERSION);
2295}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002296static void ssl_set_TLSv12_func(SSL *ssl, set_context_func c) {
2297 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_2_VERSION)
2298 : SSL_set_min_proto_version(ssl, TLS1_2_VERSION);
2299}
2300static void ctx_set_TLSv13_func(SSL_CTX *ctx, set_context_func c) {
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002301#if SSL_OP_NO_TLSv1_3
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002302 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_3_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002303 : SSL_CTX_set_min_proto_version(ctx, TLS1_3_VERSION);
2304#endif
2305}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002306static void ssl_set_TLSv13_func(SSL *ssl, set_context_func c) {
2307#if SSL_OP_NO_TLSv1_3
2308 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_3_VERSION)
2309 : SSL_set_min_proto_version(ssl, TLS1_3_VERSION);
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002310#endif
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002311}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002312#endif
2313static void ctx_set_None_func(SSL_CTX *ctx, set_context_func c) { }
2314static void ssl_set_None_func(SSL *ssl, set_context_func c) { }
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002315
2316static struct {
2317 int option;
2318 uint16_t flag;
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002319 void (*ctx_set_version)(SSL_CTX *, set_context_func);
2320 void (*ssl_set_version)(SSL *, set_context_func);
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002321 const char *name;
2322} methodVersions[] = {
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002323 {0, 0, ctx_set_None_func, ssl_set_None_func, "NONE"}, /* CONF_TLSV_NONE */
2324 {SSL_OP_NO_SSLv3, MC_SSL_O_NO_SSLV3, ctx_set_SSLv3_func, ssl_set_SSLv3_func, "SSLv3"}, /* CONF_SSLV3 */
2325 {SSL_OP_NO_TLSv1, MC_SSL_O_NO_TLSV10, ctx_set_TLSv10_func, ssl_set_TLSv10_func, "TLSv1.0"}, /* CONF_TLSV10 */
2326 {SSL_OP_NO_TLSv1_1, MC_SSL_O_NO_TLSV11, ctx_set_TLSv11_func, ssl_set_TLSv11_func, "TLSv1.1"}, /* CONF_TLSV11 */
2327 {SSL_OP_NO_TLSv1_2, MC_SSL_O_NO_TLSV12, ctx_set_TLSv12_func, ssl_set_TLSv12_func, "TLSv1.2"}, /* CONF_TLSV12 */
2328 {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 +02002329};
2330
Emmanuel Hocdet530141f2017-03-01 18:54:56 +01002331static void ssl_sock_switchctx_set(SSL *ssl, SSL_CTX *ctx)
2332{
2333 SSL_set_verify(ssl, SSL_CTX_get_verify_mode(ctx), ssl_sock_bind_verifycbk);
2334 SSL_set_client_CA_list(ssl, SSL_dup_CA_list(SSL_CTX_get_client_CA_list(ctx)));
2335 SSL_set_SSL_CTX(ssl, ctx);
2336}
2337
Willy Tarreau5db847a2019-05-09 14:13:35 +02002338#if ((HA_OPENSSL_VERSION_NUMBER >= 0x10101000L) || defined(OPENSSL_IS_BORINGSSL))
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002339
2340static int ssl_sock_switchctx_err_cbk(SSL *ssl, int *al, void *priv)
2341{
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002342 struct bind_conf *s = priv;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002343 (void)al; /* shut gcc stupid warning */
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002344
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002345 if (SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name) || s->generate_certs)
2346 return SSL_TLSEXT_ERR_OK;
2347 return SSL_TLSEXT_ERR_NOACK;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002348}
2349
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002350#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002351static int ssl_sock_switchctx_cbk(const struct ssl_early_callback_ctx *ctx)
2352{
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002353 SSL *ssl = ctx->ssl;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002354#else
2355static int ssl_sock_switchctx_cbk(SSL *ssl, int *al, void *arg)
2356{
2357#endif
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002358 struct connection *conn;
2359 struct bind_conf *s;
2360 const uint8_t *extension_data;
2361 size_t extension_len;
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002362 int has_rsa_sig = 0, has_ecdsa_sig = 0;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002363
2364 char *wildp = NULL;
2365 const uint8_t *servername;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002366 size_t servername_len;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002367 struct ebmb_node *node, *n, *node_ecdsa = NULL, *node_rsa = NULL, *node_anonymous = NULL;
Olivier Houchardc2aae742017-09-22 18:26:28 +02002368 int allow_early = 0;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002369 int i;
2370
Thierry FOURNIER28962c92018-06-17 21:37:05 +02002371 conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Willy Tarreaua8825522018-10-15 13:20:07 +02002372 s = __objt_listener(conn->target)->bind_conf;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002373
Olivier Houchard9679ac92017-10-27 14:58:08 +02002374 if (s->ssl_conf.early_data)
Olivier Houchardc2aae742017-09-22 18:26:28 +02002375 allow_early = 1;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002376#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002377 if (SSL_early_callback_ctx_extension_get(ctx, TLSEXT_TYPE_server_name,
2378 &extension_data, &extension_len)) {
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002379#else
2380 if (SSL_client_hello_get0_ext(ssl, TLSEXT_TYPE_server_name, &extension_data, &extension_len)) {
2381#endif
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002382 /*
2383 * The server_name extension was given too much extensibility when it
2384 * was written, so parsing the normal case is a bit complex.
2385 */
2386 size_t len;
2387 if (extension_len <= 2)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002388 goto abort;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002389 /* Extract the length of the supplied list of names. */
2390 len = (*extension_data++) << 8;
2391 len |= *extension_data++;
2392 if (len + 2 != extension_len)
2393 goto abort;
2394 /*
2395 * The list in practice only has a single element, so we only consider
2396 * the first one.
2397 */
2398 if (len == 0 || *extension_data++ != TLSEXT_NAMETYPE_host_name)
2399 goto abort;
2400 extension_len = len - 1;
2401 /* Now we can finally pull out the byte array with the actual hostname. */
2402 if (extension_len <= 2)
2403 goto abort;
2404 len = (*extension_data++) << 8;
2405 len |= *extension_data++;
2406 if (len == 0 || len + 2 > extension_len || len > TLSEXT_MAXLEN_host_name
2407 || memchr(extension_data, 0, len) != NULL)
2408 goto abort;
2409 servername = extension_data;
2410 servername_len = len;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002411 } else {
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002412#if (!defined SSL_NO_GENERATE_CERTIFICATES)
2413 if (s->generate_certs && ssl_sock_generate_certificate_from_conn(s, ssl)) {
Olivier Houchardc2aae742017-09-22 18:26:28 +02002414 goto allow_early;
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002415 }
2416#endif
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002417 /* without SNI extension, is the default_ctx (need SSL_TLSEXT_ERR_NOACK) */
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002418 if (!s->strict_sni) {
William Lallemand21724f02019-11-04 17:56:13 +01002419 HA_RWLOCK_RDLOCK(SNI_LOCK, &s->sni_lock);
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002420 ssl_sock_switchctx_set(ssl, s->default_ctx);
William Lallemand21724f02019-11-04 17:56:13 +01002421 HA_RWLOCK_RDUNLOCK(SNI_LOCK, &s->sni_lock);
Olivier Houchardc2aae742017-09-22 18:26:28 +02002422 goto allow_early;
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002423 }
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002424 goto abort;
2425 }
2426
2427 /* extract/check clientHello informations */
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002428#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002429 if (SSL_early_callback_ctx_extension_get(ctx, TLSEXT_TYPE_signature_algorithms, &extension_data, &extension_len)) {
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002430#else
2431 if (SSL_client_hello_get0_ext(ssl, TLSEXT_TYPE_signature_algorithms, &extension_data, &extension_len)) {
2432#endif
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002433 uint8_t sign;
2434 size_t len;
2435 if (extension_len < 2)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002436 goto abort;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002437 len = (*extension_data++) << 8;
2438 len |= *extension_data++;
2439 if (len + 2 != extension_len)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002440 goto abort;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002441 if (len % 2 != 0)
2442 goto abort;
2443 for (; len > 0; len -= 2) {
2444 extension_data++; /* hash */
2445 sign = *extension_data++;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002446 switch (sign) {
2447 case TLSEXT_signature_rsa:
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002448 has_rsa_sig = 1;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002449 break;
2450 case TLSEXT_signature_ecdsa:
2451 has_ecdsa_sig = 1;
2452 break;
2453 default:
2454 continue;
2455 }
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002456 if (has_ecdsa_sig && has_rsa_sig)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002457 break;
2458 }
2459 } else {
Bertrand Jacquina25282b2018-08-14 00:56:13 +01002460 /* without TLSEXT_TYPE_signature_algorithms extension (< TLSv1.2) */
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002461 has_rsa_sig = 1;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002462 }
2463 if (has_ecdsa_sig) { /* in very rare case: has ecdsa sign but not a ECDSA cipher */
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002464 const SSL_CIPHER *cipher;
2465 size_t len;
2466 const uint8_t *cipher_suites;
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002467 has_ecdsa_sig = 0;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002468#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002469 len = ctx->cipher_suites_len;
2470 cipher_suites = ctx->cipher_suites;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002471#else
2472 len = SSL_client_hello_get0_ciphers(ssl, &cipher_suites);
2473#endif
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002474 if (len % 2 != 0)
2475 goto abort;
2476 for (; len != 0; len -= 2, cipher_suites += 2) {
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002477#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002478 uint16_t cipher_suite = (cipher_suites[0] << 8) | cipher_suites[1];
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002479 cipher = SSL_get_cipher_by_value(cipher_suite);
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002480#else
2481 cipher = SSL_CIPHER_find(ssl, cipher_suites);
2482#endif
Emmanuel Hocdet019f9b12017-10-02 17:12:06 +02002483 if (cipher && SSL_CIPHER_get_auth_nid(cipher) == NID_auth_ecdsa) {
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002484 has_ecdsa_sig = 1;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002485 break;
2486 }
2487 }
2488 }
2489
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002490 for (i = 0; i < trash.size && i < servername_len; i++) {
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002491 trash.area[i] = tolower(servername[i]);
2492 if (!wildp && (trash.area[i] == '.'))
2493 wildp = &trash.area[i];
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002494 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002495 trash.area[i] = 0;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002496
William Lallemand150bfa82019-09-19 17:12:49 +02002497 HA_RWLOCK_RDLOCK(SNI_LOCK, &s->sni_lock);
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002498
Emmanuel Hocdet3777e3a2019-11-06 16:05:34 +01002499 for (i = 0; i < 2; i++) {
2500 if (i == 0) /* lookup in full qualified names */
2501 node = ebst_lookup(&s->sni_ctx, trash.area);
2502 else if (i == 1 && wildp) /* lookup in wildcards names */
2503 node = ebst_lookup(&s->sni_w_ctx, wildp);
2504 else
2505 break;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002506 for (n = node; n; n = ebmb_next_dup(n)) {
Emmanuel Hocdet3777e3a2019-11-06 16:05:34 +01002507 /* lookup a not neg filter */
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002508 if (!container_of(n, struct sni_ctx, name)->neg) {
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002509 switch(container_of(n, struct sni_ctx, name)->kinfo.sig) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002510 case TLSEXT_signature_ecdsa:
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002511 if (!node_ecdsa)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002512 node_ecdsa = n;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002513 break;
2514 case TLSEXT_signature_rsa:
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002515 if (!node_rsa)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002516 node_rsa = n;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002517 break;
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002518 default: /* TLSEXT_signature_anonymous|dsa */
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002519 if (!node_anonymous)
2520 node_anonymous = n;
2521 break;
2522 }
2523 }
2524 }
Emmanuel Hocdet3777e3a2019-11-06 16:05:34 +01002525 /* select by key_signature priority order */
2526 node = (has_ecdsa_sig && node_ecdsa) ? node_ecdsa
2527 : ((has_rsa_sig && node_rsa) ? node_rsa
2528 : (node_anonymous ? node_anonymous
2529 : (node_ecdsa ? node_ecdsa /* no ecdsa signature case (< TLSv1.2) */
2530 : node_rsa /* no rsa signature case (far far away) */
2531 )));
2532 if (node) {
2533 /* switch ctx */
2534 struct ssl_bind_conf *conf = container_of(node, struct sni_ctx, name)->conf;
2535 ssl_sock_switchctx_set(ssl, container_of(node, struct sni_ctx, name)->ctx);
Olivier Houchard35a63cc2017-11-02 19:04:38 +01002536 if (conf) {
2537 methodVersions[conf->ssl_methods.min].ssl_set_version(ssl, SET_MIN);
2538 methodVersions[conf->ssl_methods.max].ssl_set_version(ssl, SET_MAX);
2539 if (conf->early_data)
2540 allow_early = 1;
2541 }
William Lallemand02010472019-10-18 11:02:19 +02002542 HA_RWLOCK_RDUNLOCK(SNI_LOCK, &s->sni_lock);
Olivier Houchard35a63cc2017-11-02 19:04:38 +01002543 goto allow_early;
Emmanuel Hocdet3777e3a2019-11-06 16:05:34 +01002544 }
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002545 }
William Lallemand150bfa82019-09-19 17:12:49 +02002546
William Lallemand02010472019-10-18 11:02:19 +02002547 HA_RWLOCK_RDUNLOCK(SNI_LOCK, &s->sni_lock);
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002548#if (!defined SSL_NO_GENERATE_CERTIFICATES)
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002549 if (s->generate_certs && ssl_sock_generate_certificate(trash.area, s, ssl)) {
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002550 /* switch ctx done in ssl_sock_generate_certificate */
Olivier Houchardc2aae742017-09-22 18:26:28 +02002551 goto allow_early;
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002552 }
2553#endif
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002554 if (!s->strict_sni) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002555 /* no certificate match, is the default_ctx */
William Lallemand21724f02019-11-04 17:56:13 +01002556 HA_RWLOCK_RDLOCK(SNI_LOCK, &s->sni_lock);
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002557 ssl_sock_switchctx_set(ssl, s->default_ctx);
William Lallemand21724f02019-11-04 17:56:13 +01002558 HA_RWLOCK_RDUNLOCK(SNI_LOCK, &s->sni_lock);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002559 }
Olivier Houchardc2aae742017-09-22 18:26:28 +02002560allow_early:
2561#ifdef OPENSSL_IS_BORINGSSL
2562 if (allow_early)
2563 SSL_set_early_data_enabled(ssl, 1);
2564#else
2565 if (!allow_early)
2566 SSL_set_max_early_data(ssl, 0);
2567#endif
2568 return 1;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002569 abort:
2570 /* abort handshake (was SSL_TLSEXT_ERR_ALERT_FATAL) */
2571 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002572#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002573 return ssl_select_cert_error;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002574#else
2575 *al = SSL_AD_UNRECOGNIZED_NAME;
2576 return 0;
2577#endif
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002578}
2579
2580#else /* OPENSSL_IS_BORINGSSL */
2581
Emeric Brunfc0421f2012-09-07 17:30:07 +02002582/* Sets the SSL ctx of <ssl> to match the advertised server name. Returns a
2583 * warning when no match is found, which implies the default (first) cert
2584 * will keep being used.
2585 */
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002586static int ssl_sock_switchctx_cbk(SSL *ssl, int *al, void *priv)
Emeric Brunfc0421f2012-09-07 17:30:07 +02002587{
2588 const char *servername;
2589 const char *wildp = NULL;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002590 struct ebmb_node *node, *n;
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002591 struct bind_conf *s = priv;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002592 int i;
2593 (void)al; /* shut gcc stupid warning */
2594
2595 servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
Emmanuel Hocdet65623372013-01-24 17:17:15 +01002596 if (!servername) {
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002597#if (!defined SSL_NO_GENERATE_CERTIFICATES)
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002598 if (s->generate_certs && ssl_sock_generate_certificate_from_conn(s, ssl))
2599 return SSL_TLSEXT_ERR_OK;
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002600#endif
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002601 if (s->strict_sni)
2602 return SSL_TLSEXT_ERR_ALERT_FATAL;
William Lallemand21724f02019-11-04 17:56:13 +01002603 HA_RWLOCK_RDLOCK(SNI_LOCK, &s->sni_lock);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002604 ssl_sock_switchctx_set(ssl, s->default_ctx);
William Lallemand21724f02019-11-04 17:56:13 +01002605 HA_RWLOCK_RDUNLOCK(SNI_LOCK, &s->sni_lock);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002606 return SSL_TLSEXT_ERR_NOACK;
Emmanuel Hocdet65623372013-01-24 17:17:15 +01002607 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02002608
Willy Tarreau19d14ef2012-10-29 16:51:55 +01002609 for (i = 0; i < trash.size; i++) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02002610 if (!servername[i])
2611 break;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002612 trash.area[i] = tolower(servername[i]);
2613 if (!wildp && (trash.area[i] == '.'))
2614 wildp = &trash.area[i];
Emeric Brunfc0421f2012-09-07 17:30:07 +02002615 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002616 trash.area[i] = 0;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002617
William Lallemand150bfa82019-09-19 17:12:49 +02002618 HA_RWLOCK_RDLOCK(SNI_LOCK, &s->sni_lock);
Emmanuel Hocdetc5fdf0f2019-11-04 15:49:46 +01002619 node = NULL;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002620 /* lookup in full qualified names */
Emmanuel Hocdetc5fdf0f2019-11-04 15:49:46 +01002621 for (n = ebst_lookup(&s->sni_ctx, trash.area); n; n = ebmb_next_dup(n)) {
2622 /* lookup a not neg filter */
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002623 if (!container_of(n, struct sni_ctx, name)->neg) {
2624 node = n;
2625 break;
Emmanuel Hocdet65623372013-01-24 17:17:15 +01002626 }
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002627 }
2628 if (!node && wildp) {
2629 /* lookup in wildcards names */
Emmanuel Hocdetc5fdf0f2019-11-04 15:49:46 +01002630 for (n = ebst_lookup(&s->sni_w_ctx, wildp); n; n = ebmb_next_dup(n)) {
2631 /* lookup a not neg filter */
2632 if (!container_of(n, struct sni_ctx, name)->neg) {
2633 node = n;
2634 break;
2635 }
2636 }
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002637 }
Emmanuel Hocdetc5fdf0f2019-11-04 15:49:46 +01002638 if (!node) {
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002639#if (!defined SSL_NO_GENERATE_CERTIFICATES)
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002640 if (s->generate_certs && ssl_sock_generate_certificate(servername, s, ssl)) {
2641 /* switch ctx done in ssl_sock_generate_certificate */
William Lallemand150bfa82019-09-19 17:12:49 +02002642 HA_RWLOCK_RDUNLOCK(SNI_LOCK, &s->sni_lock);
Christopher Faulet31af49d2015-06-09 17:29:50 +02002643 return SSL_TLSEXT_ERR_OK;
2644 }
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002645#endif
William Lallemand21724f02019-11-04 17:56:13 +01002646 if (s->strict_sni) {
2647 HA_RWLOCK_RDUNLOCK(SNI_LOCK, &s->sni_lock);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002648 return SSL_TLSEXT_ERR_ALERT_FATAL;
William Lallemand21724f02019-11-04 17:56:13 +01002649 }
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002650 ssl_sock_switchctx_set(ssl, s->default_ctx);
William Lallemand21724f02019-11-04 17:56:13 +01002651 HA_RWLOCK_RDUNLOCK(SNI_LOCK, &s->sni_lock);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002652 return SSL_TLSEXT_ERR_OK;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002653 }
2654
2655 /* switch ctx */
Emmanuel Hocdet530141f2017-03-01 18:54:56 +01002656 ssl_sock_switchctx_set(ssl, container_of(node, struct sni_ctx, name)->ctx);
William Lallemand150bfa82019-09-19 17:12:49 +02002657 HA_RWLOCK_RDUNLOCK(SNI_LOCK, &s->sni_lock);
Emeric Brunfc0421f2012-09-07 17:30:07 +02002658 return SSL_TLSEXT_ERR_OK;
2659}
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002660#endif /* (!) OPENSSL_IS_BORINGSSL */
Emeric Brunfc0421f2012-09-07 17:30:07 +02002661#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
2662
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002663#ifndef OPENSSL_NO_DH
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002664
2665static DH * ssl_get_dh_1024(void)
2666{
Remi Gacogned3a341a2015-05-29 16:26:17 +02002667 static unsigned char dh1024_p[]={
2668 0xFA,0xF9,0x2A,0x22,0x2A,0xA7,0x7F,0xE1,0x67,0x4E,0x53,0xF7,
2669 0x56,0x13,0xC3,0xB1,0xE3,0x29,0x6B,0x66,0x31,0x6A,0x7F,0xB3,
2670 0xC2,0x68,0x6B,0xCB,0x1D,0x57,0x39,0x1D,0x1F,0xFF,0x1C,0xC9,
2671 0xA6,0xA4,0x98,0x82,0x31,0x5D,0x25,0xFF,0x8A,0xE0,0x73,0x96,
2672 0x81,0xC8,0x83,0x79,0xC1,0x5A,0x04,0xF8,0x37,0x0D,0xA8,0x3D,
2673 0xAE,0x74,0xBC,0xDB,0xB6,0xA4,0x75,0xD9,0x71,0x8A,0xA0,0x17,
2674 0x9E,0x2D,0xC8,0xA8,0xDF,0x2C,0x5F,0x82,0x95,0xF8,0x92,0x9B,
2675 0xA7,0x33,0x5F,0x89,0x71,0xC8,0x2D,0x6B,0x18,0x86,0xC4,0x94,
2676 0x22,0xA5,0x52,0x8D,0xF6,0xF6,0xD2,0x37,0x92,0x0F,0xA5,0xCC,
2677 0xDB,0x7B,0x1D,0x3D,0xA1,0x31,0xB7,0x80,0x8F,0x0B,0x67,0x5E,
2678 0x36,0xA5,0x60,0x0C,0xF1,0x95,0x33,0x8B,
2679 };
2680 static unsigned char dh1024_g[]={
2681 0x02,
2682 };
2683
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002684 BIGNUM *p;
2685 BIGNUM *g;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002686 DH *dh = DH_new();
2687 if (dh) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002688 p = BN_bin2bn(dh1024_p, sizeof dh1024_p, NULL);
2689 g = BN_bin2bn(dh1024_g, sizeof dh1024_g, NULL);
Remi Gacogned3a341a2015-05-29 16:26:17 +02002690
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002691 if (!p || !g) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002692 DH_free(dh);
2693 dh = NULL;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002694 } else {
2695 DH_set0_pqg(dh, p, NULL, g);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002696 }
2697 }
2698 return dh;
2699}
2700
2701static DH *ssl_get_dh_2048(void)
2702{
Remi Gacogned3a341a2015-05-29 16:26:17 +02002703 static unsigned char dh2048_p[]={
2704 0xEC,0x86,0xF8,0x70,0xA0,0x33,0x16,0xEC,0x05,0x1A,0x73,0x59,
2705 0xCD,0x1F,0x8B,0xF8,0x29,0xE4,0xD2,0xCF,0x52,0xDD,0xC2,0x24,
2706 0x8D,0xB5,0x38,0x9A,0xFB,0x5C,0xA4,0xE4,0xB2,0xDA,0xCE,0x66,
2707 0x50,0x74,0xA6,0x85,0x4D,0x4B,0x1D,0x30,0xB8,0x2B,0xF3,0x10,
2708 0xE9,0xA7,0x2D,0x05,0x71,0xE7,0x81,0xDF,0x8B,0x59,0x52,0x3B,
2709 0x5F,0x43,0x0B,0x68,0xF1,0xDB,0x07,0xBE,0x08,0x6B,0x1B,0x23,
2710 0xEE,0x4D,0xCC,0x9E,0x0E,0x43,0xA0,0x1E,0xDF,0x43,0x8C,0xEC,
2711 0xBE,0xBE,0x90,0xB4,0x51,0x54,0xB9,0x2F,0x7B,0x64,0x76,0x4E,
2712 0x5D,0xD4,0x2E,0xAE,0xC2,0x9E,0xAE,0x51,0x43,0x59,0xC7,0x77,
2713 0x9C,0x50,0x3C,0x0E,0xED,0x73,0x04,0x5F,0xF1,0x4C,0x76,0x2A,
2714 0xD8,0xF8,0xCF,0xFC,0x34,0x40,0xD1,0xB4,0x42,0x61,0x84,0x66,
2715 0x42,0x39,0x04,0xF8,0x68,0xB2,0x62,0xD7,0x55,0xED,0x1B,0x74,
2716 0x75,0x91,0xE0,0xC5,0x69,0xC1,0x31,0x5C,0xDB,0x7B,0x44,0x2E,
2717 0xCE,0x84,0x58,0x0D,0x1E,0x66,0x0C,0xC8,0x44,0x9E,0xFD,0x40,
2718 0x08,0x67,0x5D,0xFB,0xA7,0x76,0x8F,0x00,0x11,0x87,0xE9,0x93,
2719 0xF9,0x7D,0xC4,0xBC,0x74,0x55,0x20,0xD4,0x4A,0x41,0x2F,0x43,
2720 0x42,0x1A,0xC1,0xF2,0x97,0x17,0x49,0x27,0x37,0x6B,0x2F,0x88,
2721 0x7E,0x1C,0xA0,0xA1,0x89,0x92,0x27,0xD9,0x56,0x5A,0x71,0xC1,
2722 0x56,0x37,0x7E,0x3A,0x9D,0x05,0xE7,0xEE,0x5D,0x8F,0x82,0x17,
2723 0xBC,0xE9,0xC2,0x93,0x30,0x82,0xF9,0xF4,0xC9,0xAE,0x49,0xDB,
2724 0xD0,0x54,0xB4,0xD9,0x75,0x4D,0xFA,0x06,0xB8,0xD6,0x38,0x41,
2725 0xB7,0x1F,0x77,0xF3,
2726 };
2727 static unsigned char dh2048_g[]={
2728 0x02,
2729 };
2730
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002731 BIGNUM *p;
2732 BIGNUM *g;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002733 DH *dh = DH_new();
2734 if (dh) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002735 p = BN_bin2bn(dh2048_p, sizeof dh2048_p, NULL);
2736 g = BN_bin2bn(dh2048_g, sizeof dh2048_g, NULL);
Remi Gacogned3a341a2015-05-29 16:26:17 +02002737
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002738 if (!p || !g) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002739 DH_free(dh);
2740 dh = NULL;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002741 } else {
2742 DH_set0_pqg(dh, p, NULL, g);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002743 }
2744 }
2745 return dh;
2746}
2747
2748static DH *ssl_get_dh_4096(void)
2749{
Remi Gacogned3a341a2015-05-29 16:26:17 +02002750 static unsigned char dh4096_p[]={
2751 0xDE,0x16,0x94,0xCD,0x99,0x58,0x07,0xF1,0xF7,0x32,0x96,0x11,
2752 0x04,0x82,0xD4,0x84,0x72,0x80,0x99,0x06,0xCA,0xF0,0xA3,0x68,
2753 0x07,0xCE,0x64,0x50,0xE7,0x74,0x45,0x20,0x80,0x5E,0x4D,0xAD,
2754 0xA5,0xB6,0xED,0xFA,0x80,0x6C,0x3B,0x35,0xC4,0x9A,0x14,0x6B,
2755 0x32,0xBB,0xFD,0x1F,0x17,0x8E,0xB7,0x1F,0xD6,0xFA,0x3F,0x7B,
2756 0xEE,0x16,0xA5,0x62,0x33,0x0D,0xED,0xBC,0x4E,0x58,0xE5,0x47,
2757 0x4D,0xE9,0xAB,0x8E,0x38,0xD3,0x6E,0x90,0x57,0xE3,0x22,0x15,
2758 0x33,0xBD,0xF6,0x43,0x45,0xB5,0x10,0x0A,0xBE,0x2C,0xB4,0x35,
2759 0xB8,0x53,0x8D,0xAD,0xFB,0xA7,0x1F,0x85,0x58,0x41,0x7A,0x79,
2760 0x20,0x68,0xB3,0xE1,0x3D,0x08,0x76,0xBF,0x86,0x0D,0x49,0xE3,
2761 0x82,0x71,0x8C,0xB4,0x8D,0x81,0x84,0xD4,0xE7,0xBE,0x91,0xDC,
2762 0x26,0x39,0x48,0x0F,0x35,0xC4,0xCA,0x65,0xE3,0x40,0x93,0x52,
2763 0x76,0x58,0x7D,0xDD,0x51,0x75,0xDC,0x69,0x61,0xBF,0x47,0x2C,
2764 0x16,0x68,0x2D,0xC9,0x29,0xD3,0xE6,0xC0,0x99,0x48,0xA0,0x9A,
2765 0xC8,0x78,0xC0,0x6D,0x81,0x67,0x12,0x61,0x3F,0x71,0xBA,0x41,
2766 0x1F,0x6C,0x89,0x44,0x03,0xBA,0x3B,0x39,0x60,0xAA,0x28,0x55,
2767 0x59,0xAE,0xB8,0xFA,0xCB,0x6F,0xA5,0x1A,0xF7,0x2B,0xDD,0x52,
2768 0x8A,0x8B,0xE2,0x71,0xA6,0x5E,0x7E,0xD8,0x2E,0x18,0xE0,0x66,
2769 0xDF,0xDD,0x22,0x21,0x99,0x52,0x73,0xA6,0x33,0x20,0x65,0x0E,
2770 0x53,0xE7,0x6B,0x9B,0xC5,0xA3,0x2F,0x97,0x65,0x76,0xD3,0x47,
2771 0x23,0x77,0x12,0xB6,0x11,0x7B,0x24,0xED,0xF1,0xEF,0xC0,0xE2,
2772 0xA3,0x7E,0x67,0x05,0x3E,0x96,0x4D,0x45,0xC2,0x18,0xD1,0x73,
2773 0x9E,0x07,0xF3,0x81,0x6E,0x52,0x63,0xF6,0x20,0x76,0xB9,0x13,
2774 0xD2,0x65,0x30,0x18,0x16,0x09,0x16,0x9E,0x8F,0xF1,0xD2,0x10,
2775 0x5A,0xD3,0xD4,0xAF,0x16,0x61,0xDA,0x55,0x2E,0x18,0x5E,0x14,
2776 0x08,0x54,0x2E,0x2A,0x25,0xA2,0x1A,0x9B,0x8B,0x32,0xA9,0xFD,
2777 0xC2,0x48,0x96,0xE1,0x80,0xCA,0xE9,0x22,0x17,0xBB,0xCE,0x3E,
2778 0x9E,0xED,0xC7,0xF1,0x1F,0xEC,0x17,0x21,0xDC,0x7B,0x82,0x48,
2779 0x8E,0xBB,0x4B,0x9D,0x5B,0x04,0x04,0xDA,0xDB,0x39,0xDF,0x01,
2780 0x40,0xC3,0xAA,0x26,0x23,0x89,0x75,0xC6,0x0B,0xD0,0xA2,0x60,
2781 0x6A,0xF1,0xCC,0x65,0x18,0x98,0x1B,0x52,0xD2,0x74,0x61,0xCC,
2782 0xBD,0x60,0xAE,0xA3,0xA0,0x66,0x6A,0x16,0x34,0x92,0x3F,0x41,
2783 0x40,0x31,0x29,0xC0,0x2C,0x63,0xB2,0x07,0x8D,0xEB,0x94,0xB8,
2784 0xE8,0x47,0x92,0x52,0x93,0x6A,0x1B,0x7E,0x1A,0x61,0xB3,0x1B,
2785 0xF0,0xD6,0x72,0x9B,0xF1,0xB0,0xAF,0xBF,0x3E,0x65,0xEF,0x23,
2786 0x1D,0x6F,0xFF,0x70,0xCD,0x8A,0x4C,0x8A,0xA0,0x72,0x9D,0xBE,
2787 0xD4,0xBB,0x24,0x47,0x4A,0x68,0xB5,0xF5,0xC6,0xD5,0x7A,0xCD,
2788 0xCA,0x06,0x41,0x07,0xAD,0xC2,0x1E,0xE6,0x54,0xA7,0xAD,0x03,
2789 0xD9,0x12,0xC1,0x9C,0x13,0xB1,0xC9,0x0A,0x43,0x8E,0x1E,0x08,
2790 0xCE,0x50,0x82,0x73,0x5F,0xA7,0x55,0x1D,0xD9,0x59,0xAC,0xB5,
2791 0xEA,0x02,0x7F,0x6C,0x5B,0x74,0x96,0x98,0x67,0x24,0xA3,0x0F,
2792 0x15,0xFC,0xA9,0x7D,0x3E,0x67,0xD1,0x70,0xF8,0x97,0xF3,0x67,
2793 0xC5,0x8C,0x88,0x44,0x08,0x02,0xC7,0x2B,
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002794 };
Remi Gacogned3a341a2015-05-29 16:26:17 +02002795 static unsigned char dh4096_g[]={
2796 0x02,
2797 };
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002798
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002799 BIGNUM *p;
2800 BIGNUM *g;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002801 DH *dh = DH_new();
2802 if (dh) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002803 p = BN_bin2bn(dh4096_p, sizeof dh4096_p, NULL);
2804 g = BN_bin2bn(dh4096_g, sizeof dh4096_g, NULL);
Remi Gacogned3a341a2015-05-29 16:26:17 +02002805
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002806 if (!p || !g) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002807 DH_free(dh);
2808 dh = NULL;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002809 } else {
2810 DH_set0_pqg(dh, p, NULL, g);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002811 }
2812 }
2813 return dh;
2814}
2815
2816/* Returns Diffie-Hellman parameters matching the private key length
Willy Tarreauef934602016-12-22 23:12:01 +01002817 but not exceeding global_ssl.default_dh_param */
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002818static DH *ssl_get_tmp_dh(SSL *ssl, int export, int keylen)
2819{
2820 DH *dh = NULL;
2821 EVP_PKEY *pkey = SSL_get_privatekey(ssl);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002822 int type;
2823
2824 type = pkey ? EVP_PKEY_base_id(pkey) : EVP_PKEY_NONE;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002825
2826 /* The keylen supplied by OpenSSL can only be 512 or 1024.
2827 See ssl3_send_server_key_exchange() in ssl/s3_srvr.c
2828 */
2829 if (type == EVP_PKEY_RSA || type == EVP_PKEY_DSA) {
2830 keylen = EVP_PKEY_bits(pkey);
2831 }
2832
Willy Tarreauef934602016-12-22 23:12:01 +01002833 if (keylen > global_ssl.default_dh_param) {
2834 keylen = global_ssl.default_dh_param;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002835 }
2836
Remi Gacogned3a341a2015-05-29 16:26:17 +02002837 if (keylen >= 4096) {
Remi Gacogne8de54152014-07-15 11:36:40 +02002838 dh = local_dh_4096;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002839 }
2840 else if (keylen >= 2048) {
Remi Gacogne8de54152014-07-15 11:36:40 +02002841 dh = local_dh_2048;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002842 }
2843 else {
Remi Gacogne8de54152014-07-15 11:36:40 +02002844 dh = local_dh_1024;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002845 }
2846
2847 return dh;
2848}
2849
Remi Gacogne47783ef2015-05-29 15:53:22 +02002850static DH * ssl_sock_get_dh_from_file(const char *filename)
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002851{
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002852 DH *dh = NULL;
Remi Gacogne47783ef2015-05-29 15:53:22 +02002853 BIO *in = BIO_new(BIO_s_file());
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002854
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002855 if (in == NULL)
2856 goto end;
2857
Remi Gacogne47783ef2015-05-29 15:53:22 +02002858 if (BIO_read_filename(in, filename) <= 0)
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002859 goto end;
2860
Remi Gacogne47783ef2015-05-29 15:53:22 +02002861 dh = PEM_read_bio_DHparams(in, NULL, NULL, NULL);
2862
2863end:
2864 if (in)
2865 BIO_free(in);
2866
Emeric Brune1b4ed42018-08-16 15:14:12 +02002867 ERR_clear_error();
2868
Remi Gacogne47783ef2015-05-29 15:53:22 +02002869 return dh;
2870}
2871
2872int ssl_sock_load_global_dh_param_from_file(const char *filename)
2873{
2874 global_dh = ssl_sock_get_dh_from_file(filename);
2875
2876 if (global_dh) {
2877 return 0;
2878 }
2879
2880 return -1;
2881}
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002882#endif
2883
William Lallemand9117de92019-10-04 00:29:42 +02002884/* Alloc and init a ckch_inst */
2885static struct ckch_inst *ckch_inst_new()
2886{
2887 struct ckch_inst *ckch_inst;
2888
2889 ckch_inst = calloc(1, sizeof *ckch_inst);
2890 if (ckch_inst)
2891 LIST_INIT(&ckch_inst->sni_ctx);
2892
2893 return ckch_inst;
2894}
2895
2896
2897/* This function allocates a sni_ctx and adds it to the ckch_inst */
William Lallemand1d29c742019-10-04 00:53:29 +02002898static int ckch_inst_add_cert_sni(SSL_CTX *ctx, struct ckch_inst *ckch_inst,
William Lallemand9117de92019-10-04 00:29:42 +02002899 struct bind_conf *s, struct ssl_bind_conf *conf,
2900 struct pkey_info kinfo, char *name, int order)
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002901{
2902 struct sni_ctx *sc;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002903 int wild = 0, neg = 0;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002904
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002905 if (*name == '!') {
2906 neg = 1;
2907 name++;
2908 }
2909 if (*name == '*') {
2910 wild = 1;
2911 name++;
2912 }
2913 /* !* filter is a nop */
2914 if (neg && wild)
2915 return order;
2916 if (*name) {
2917 int j, len;
2918 len = strlen(name);
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002919 for (j = 0; j < len && j < trash.size; j++)
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002920 trash.area[j] = tolower(name[j]);
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002921 if (j >= trash.size)
William Lallemandfe49bb32019-10-03 23:46:33 +02002922 return -1;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002923 trash.area[j] = 0;
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002924
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002925 sc = malloc(sizeof(struct sni_ctx) + len + 1);
Thierry FOURNIER / OZON.IO7a3bd3b2016-10-06 10:35:29 +02002926 if (!sc)
William Lallemandfe49bb32019-10-03 23:46:33 +02002927 return -1;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002928 memcpy(sc->name.key, trash.area, len + 1);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002929 sc->ctx = ctx;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01002930 sc->conf = conf;
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002931 sc->kinfo = kinfo;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002932 sc->order = order++;
2933 sc->neg = neg;
William Lallemand1d29c742019-10-04 00:53:29 +02002934 sc->wild = wild;
2935 sc->name.node.leaf_p = NULL;
William Lallemand1d29c742019-10-04 00:53:29 +02002936 LIST_ADDQ(&ckch_inst->sni_ctx, &sc->by_ckch_inst);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002937 }
2938 return order;
2939}
2940
William Lallemand6af03992019-07-23 15:00:54 +02002941/*
William Lallemand1d29c742019-10-04 00:53:29 +02002942 * Insert the sni_ctxs that are listed in the ckch_inst, in the bind_conf's sni_ctx tree
2943 * This function can't return an error.
2944 *
2945 * *CAUTION*: The caller must lock the sni tree if called in multithreading mode
2946 */
2947static void ssl_sock_load_cert_sni(struct ckch_inst *ckch_inst, struct bind_conf *bind_conf)
2948{
2949
2950 struct sni_ctx *sc0, *sc0b, *sc1;
2951 struct ebmb_node *node;
William Lallemand21724f02019-11-04 17:56:13 +01002952 int def = 0;
William Lallemand1d29c742019-10-04 00:53:29 +02002953
2954 list_for_each_entry_safe(sc0, sc0b, &ckch_inst->sni_ctx, by_ckch_inst) {
2955
2956 /* ignore if sc0 was already inserted in a tree */
2957 if (sc0->name.node.leaf_p)
2958 continue;
2959
2960 /* Check for duplicates. */
2961 if (sc0->wild)
2962 node = ebst_lookup(&bind_conf->sni_w_ctx, (char *)sc0->name.key);
2963 else
2964 node = ebst_lookup(&bind_conf->sni_ctx, (char *)sc0->name.key);
2965
2966 for (; node; node = ebmb_next_dup(node)) {
2967 sc1 = ebmb_entry(node, struct sni_ctx, name);
2968 if (sc1->ctx == sc0->ctx && sc1->conf == sc0->conf
2969 && sc1->neg == sc0->neg && sc1->wild == sc0->wild) {
2970 /* it's a duplicate, we should remove and free it */
2971 LIST_DEL(&sc0->by_ckch_inst);
2972 free(sc0);
2973 sc0 = NULL;
William Lallemande15029b2019-10-14 10:46:58 +02002974 break;
William Lallemand1d29c742019-10-04 00:53:29 +02002975 }
2976 }
2977
2978 /* if duplicate, ignore the insertion */
2979 if (!sc0)
2980 continue;
2981
2982 if (sc0->wild)
2983 ebst_insert(&bind_conf->sni_w_ctx, &sc0->name);
2984 else
2985 ebst_insert(&bind_conf->sni_ctx, &sc0->name);
William Lallemand21724f02019-11-04 17:56:13 +01002986
2987 /* replace the default_ctx if required with the first ctx */
2988 if (ckch_inst->is_default && !def) {
2989 /* we don't need to free the default_ctx because the refcount was not incremented */
2990 bind_conf->default_ctx = sc0->ctx;
2991 def = 1;
2992 }
William Lallemand1d29c742019-10-04 00:53:29 +02002993 }
2994}
2995
2996/*
William Lallemande3af8fb2019-10-08 11:36:53 +02002997 * tree used to store the ckchs ordered by filename/bundle name
William Lallemand6af03992019-07-23 15:00:54 +02002998 */
William Lallemande3af8fb2019-10-08 11:36:53 +02002999struct eb_root ckchs_tree = EB_ROOT_UNIQUE;
William Lallemand6af03992019-07-23 15:00:54 +02003000
William Lallemandfa892222019-07-23 16:06:08 +02003001
Emeric Brun7a883362019-10-17 13:27:40 +02003002/* Loads Diffie-Hellman parameter from a ckchs to an SSL_CTX.
3003 * If there is no DH paramater availaible in the ckchs, the global
3004 * DH parameter is loaded into the SSL_CTX and if there is no
3005 * DH parameter available in ckchs nor in global, the default
3006 * DH parameters are applied on the SSL_CTX.
3007 * Returns a bitfield containing the flags:
3008 * ERR_FATAL in any fatal error case
3009 * ERR_ALERT if a reason of the error is availabine in err
3010 * ERR_WARN if a warning is available into err
3011 * The value 0 means there is no error nor warning and
3012 * the operation succeed.
3013 */
William Lallemandfa892222019-07-23 16:06:08 +02003014#ifndef OPENSSL_NO_DH
Emeric Brun7a883362019-10-17 13:27:40 +02003015static int ssl_sock_load_dh_params(SSL_CTX *ctx, const struct cert_key_and_chain *ckch,
3016 const char *path, char **err)
William Lallemandfa892222019-07-23 16:06:08 +02003017{
Emeric Brun7a883362019-10-17 13:27:40 +02003018 int ret = 0;
William Lallemandfa892222019-07-23 16:06:08 +02003019 DH *dh = NULL;
3020
William Lallemanda8c73742019-07-31 18:31:34 +02003021 if (ckch && ckch->dh) {
William Lallemandfa892222019-07-23 16:06:08 +02003022 dh = ckch->dh;
Emeric Bruna9363eb2019-10-17 14:53:03 +02003023 if (!SSL_CTX_set_tmp_dh(ctx, dh)) {
3024 memprintf(err, "%sunable to load the DH parameter specified in '%s'",
3025 err && *err ? *err : "", path);
3026#if defined(SSL_CTX_set_dh_auto)
3027 SSL_CTX_set_dh_auto(ctx, 1);
3028 memprintf(err, "%s, SSL library will use an automatically generated DH parameter.\n",
3029 err && *err ? *err : "");
3030#else
3031 memprintf(err, "%s, DH ciphers won't be available.\n",
3032 err && *err ? *err : "");
3033#endif
3034 ret |= ERR_WARN;
3035 goto end;
3036 }
William Lallemandfa892222019-07-23 16:06:08 +02003037
3038 if (ssl_dh_ptr_index >= 0) {
3039 /* store a pointer to the DH params to avoid complaining about
3040 ssl-default-dh-param not being set for this SSL_CTX */
3041 SSL_CTX_set_ex_data(ctx, ssl_dh_ptr_index, dh);
3042 }
3043 }
3044 else if (global_dh) {
Emeric Bruna9363eb2019-10-17 14:53:03 +02003045 if (!SSL_CTX_set_tmp_dh(ctx, global_dh)) {
3046 memprintf(err, "%sunable to use the global DH parameter for certificate '%s'",
3047 err && *err ? *err : "", path);
3048#if defined(SSL_CTX_set_dh_auto)
3049 SSL_CTX_set_dh_auto(ctx, 1);
3050 memprintf(err, "%s, SSL library will use an automatically generated DH parameter.\n",
3051 err && *err ? *err : "");
3052#else
3053 memprintf(err, "%s, DH ciphers won't be available.\n",
3054 err && *err ? *err : "");
3055#endif
3056 ret |= ERR_WARN;
3057 goto end;
3058 }
William Lallemandfa892222019-07-23 16:06:08 +02003059 }
3060 else {
3061 /* Clear openssl global errors stack */
3062 ERR_clear_error();
3063
3064 if (global_ssl.default_dh_param <= 1024) {
3065 /* we are limited to DH parameter of 1024 bits anyway */
3066 if (local_dh_1024 == NULL)
3067 local_dh_1024 = ssl_get_dh_1024();
3068
Emeric Brun7a883362019-10-17 13:27:40 +02003069 if (local_dh_1024 == NULL) {
3070 memprintf(err, "%sunable to load default 1024 bits DH parameter for certificate '%s'.\n",
3071 err && *err ? *err : "", path);
3072 ret |= ERR_ALERT | ERR_FATAL;
William Lallemandfa892222019-07-23 16:06:08 +02003073 goto end;
Emeric Brun7a883362019-10-17 13:27:40 +02003074 }
William Lallemandfa892222019-07-23 16:06:08 +02003075
Emeric Bruna9363eb2019-10-17 14:53:03 +02003076 if (!SSL_CTX_set_tmp_dh(ctx, local_dh_1024)) {
3077 memprintf(err, "%sunable to load default 1024 bits DH parameter for certificate '%s'.\n",
3078 err && *err ? *err : "", path);
3079#if defined(SSL_CTX_set_dh_auto)
3080 SSL_CTX_set_dh_auto(ctx, 1);
3081 memprintf(err, "%s, SSL library will use an automatically generated DH parameter.\n",
3082 err && *err ? *err : "");
3083#else
3084 memprintf(err, "%s, DH ciphers won't be available.\n",
3085 err && *err ? *err : "");
3086#endif
3087 ret |= ERR_WARN;
3088 goto end;
3089 }
William Lallemandfa892222019-07-23 16:06:08 +02003090 }
3091 else {
3092 SSL_CTX_set_tmp_dh_callback(ctx, ssl_get_tmp_dh);
3093 }
William Lallemandfa892222019-07-23 16:06:08 +02003094 }
3095
3096end:
William Lallemand4dd145a2020-02-05 11:46:33 +01003097 ERR_clear_error();
William Lallemandfa892222019-07-23 16:06:08 +02003098 return ret;
3099}
3100#endif
yanbzhu08ce6ab2015-12-02 13:01:29 -05003101
yanbzhu488a4d22015-12-01 15:16:07 -05003102/* Frees the contents of a cert_key_and_chain
3103 */
3104static void ssl_sock_free_cert_key_and_chain_contents(struct cert_key_and_chain *ckch)
3105{
yanbzhu488a4d22015-12-01 15:16:07 -05003106 if (!ckch)
3107 return;
3108
3109 /* Free the certificate and set pointer to NULL */
3110 if (ckch->cert)
3111 X509_free(ckch->cert);
3112 ckch->cert = NULL;
3113
3114 /* Free the key and set pointer to NULL */
3115 if (ckch->key)
3116 EVP_PKEY_free(ckch->key);
3117 ckch->key = NULL;
3118
3119 /* Free each certificate in the chain */
Emmanuel Hocdet9246f8b2018-11-30 16:00:21 +01003120 if (ckch->chain)
3121 sk_X509_pop_free(ckch->chain, X509_free);
3122 ckch->chain = NULL;
yanbzhu488a4d22015-12-01 15:16:07 -05003123
William Lallemand455af502019-10-17 18:04:45 +02003124 if (ckch->dh)
3125 DH_free(ckch->dh);
3126 ckch->dh = NULL;
3127
3128 if (ckch->sctl) {
3129 free(ckch->sctl->area);
3130 ckch->sctl->area = NULL;
3131 free(ckch->sctl);
3132 ckch->sctl = NULL;
3133 }
3134
3135 if (ckch->ocsp_response) {
3136 free(ckch->ocsp_response->area);
3137 ckch->ocsp_response->area = NULL;
3138 free(ckch->ocsp_response);
3139 ckch->ocsp_response = NULL;
3140 }
William Lallemand5c3c96f2020-01-23 11:53:13 +01003141
3142 if (ckch->ocsp_issuer)
William Lallemanddad239d2020-01-23 11:59:02 +01003143 X509_free(ckch->ocsp_issuer);
William Lallemand5c3c96f2020-01-23 11:53:13 +01003144 ckch->ocsp_issuer = NULL;
yanbzhu488a4d22015-12-01 15:16:07 -05003145}
3146
William Lallemand8d0f8932019-10-17 18:03:58 +02003147/*
3148 *
3149 * This function copy a cert_key_and_chain in memory
3150 *
3151 * It's used to try to apply changes on a ckch before committing them, because
3152 * most of the time it's not possible to revert those changes
3153 *
3154 * Return a the dst or NULL
3155 */
3156static struct cert_key_and_chain *ssl_sock_copy_cert_key_and_chain(struct cert_key_and_chain *src,
3157 struct cert_key_and_chain *dst)
3158{
3159 if (src->cert) {
3160 dst->cert = src->cert;
3161 X509_up_ref(src->cert);
3162 }
3163
3164 if (src->key) {
3165 dst->key = src->key;
3166 EVP_PKEY_up_ref(src->key);
3167 }
3168
3169 if (src->chain) {
3170 dst->chain = X509_chain_up_ref(src->chain);
3171 }
3172
3173 if (src->dh) {
3174 DH_up_ref(src->dh);
3175 dst->dh = src->dh;
3176 }
3177
3178 if (src->sctl) {
3179 struct buffer *sctl;
3180
3181 sctl = calloc(1, sizeof(*sctl));
3182 if (!chunk_dup(sctl, src->sctl)) {
3183 free(sctl);
3184 sctl = NULL;
3185 goto error;
3186 }
3187 dst->sctl = sctl;
3188 }
3189
3190 if (src->ocsp_response) {
3191 struct buffer *ocsp_response;
3192
3193 ocsp_response = calloc(1, sizeof(*ocsp_response));
3194 if (!chunk_dup(ocsp_response, src->ocsp_response)) {
3195 free(ocsp_response);
3196 ocsp_response = NULL;
3197 goto error;
3198 }
3199 dst->ocsp_response = ocsp_response;
3200 }
3201
3202 if (src->ocsp_issuer) {
3203 X509_up_ref(src->ocsp_issuer);
3204 dst->ocsp_issuer = src->ocsp_issuer;
3205 }
3206
3207 return dst;
3208
3209error:
3210
3211 /* free everything */
3212 ssl_sock_free_cert_key_and_chain_contents(dst);
3213
3214 return NULL;
3215}
3216
3217
yanbzhu488a4d22015-12-01 15:16:07 -05003218/* checks if a key and cert exists in the ckch
3219 */
William Lallemand1633e392019-09-30 12:58:13 +02003220#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
yanbzhu488a4d22015-12-01 15:16:07 -05003221static int ssl_sock_is_ckch_valid(struct cert_key_and_chain *ckch)
3222{
3223 return (ckch->cert != NULL && ckch->key != NULL);
3224}
William Lallemand1633e392019-09-30 12:58:13 +02003225#endif
yanbzhu488a4d22015-12-01 15:16:07 -05003226
William Lallemandf9568fc2019-10-16 18:27:58 +02003227/*
3228 * return 0 on success or != 0 on failure
3229 */
3230static int ssl_sock_load_issuer_file_into_ckch(const char *path, char *buf, struct cert_key_and_chain *ckch, char **err)
3231{
3232 int ret = 1;
3233 BIO *in = NULL;
3234 X509 *issuer;
3235
3236 if (buf) {
3237 /* reading from a buffer */
3238 in = BIO_new_mem_buf(buf, -1);
3239 if (in == NULL) {
3240 memprintf(err, "%sCan't allocate memory\n", err && *err ? *err : "");
3241 goto end;
3242 }
3243
3244 } else {
3245 /* reading from a file */
3246 in = BIO_new(BIO_s_file());
3247 if (in == NULL)
3248 goto end;
3249
3250 if (BIO_read_filename(in, path) <= 0)
3251 goto end;
3252 }
3253
3254 issuer = PEM_read_bio_X509_AUX(in, NULL, NULL, NULL);
3255 if (!issuer) {
3256 memprintf(err, "%s'%s' cannot be read or parsed'.\n",
Tim Duesterhus93128532019-11-23 23:45:10 +01003257 err && *err ? *err : "", path);
William Lallemandf9568fc2019-10-16 18:27:58 +02003258 goto end;
3259 }
Emmanuel Hocdeteb73dc32020-01-16 14:45:00 +01003260 /* no error, fill ckch with new context, old context must be free */
3261 if (ckch->ocsp_issuer)
3262 X509_free(ckch->ocsp_issuer);
William Lallemandf9568fc2019-10-16 18:27:58 +02003263 ckch->ocsp_issuer = issuer;
Emmanuel Hocdeteb73dc32020-01-16 14:45:00 +01003264 ret = 0;
William Lallemandf9568fc2019-10-16 18:27:58 +02003265
3266end:
3267
3268 ERR_clear_error();
3269 if (in)
3270 BIO_free(in);
3271
3272 return ret;
3273}
3274
William Lallemand96a9c972019-10-17 11:56:17 +02003275
3276/*
3277 * Try to load a PEM file from a <path> or a buffer <buf>
3278 * The PEM must contain at least a Private Key and a Certificate,
3279 * It could contain a DH and a certificate chain.
yanbzhu488a4d22015-12-01 15:16:07 -05003280 *
William Lallemand96a9c972019-10-17 11:56:17 +02003281 * If it failed you should not attempt to use the ckch but free it.
3282 *
3283 * Return 0 on success or != 0 on failure
yanbzhu488a4d22015-12-01 15:16:07 -05003284 */
William Lallemand96a9c972019-10-17 11:56:17 +02003285static 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 -05003286{
William Lallemandf11365b2019-09-19 14:25:58 +02003287 BIO *in = NULL;
yanbzhu488a4d22015-12-01 15:16:07 -05003288 int ret = 1;
Emmanuel Hocdet078156d2020-01-22 17:02:53 +01003289 int i;
Emmanuel Hocdet83cbd3c2019-10-25 11:55:03 +02003290 X509 *ca;
William Lallemand96a9c972019-10-17 11:56:17 +02003291 X509 *cert = NULL;
3292 EVP_PKEY *key = NULL;
Emmanuel Hocdet6b5b44e2019-12-20 17:47:12 +01003293 DH *dh = NULL;
3294 STACK_OF(X509) *chain = NULL;
William Lallemand96a9c972019-10-17 11:56:17 +02003295
3296 if (buf) {
3297 /* reading from a buffer */
3298 in = BIO_new_mem_buf(buf, -1);
3299 if (in == NULL) {
3300 memprintf(err, "%sCan't allocate memory\n", err && *err ? *err : "");
3301 goto end;
3302 }
yanbzhu488a4d22015-12-01 15:16:07 -05003303
William Lallemand96a9c972019-10-17 11:56:17 +02003304 } else {
3305 /* reading from a file */
William Lallemandf11365b2019-09-19 14:25:58 +02003306 in = BIO_new(BIO_s_file());
3307 if (in == NULL)
3308 goto end;
yanbzhu488a4d22015-12-01 15:16:07 -05003309
William Lallemandf11365b2019-09-19 14:25:58 +02003310 if (BIO_read_filename(in, path) <= 0)
3311 goto end;
William Lallemandf11365b2019-09-19 14:25:58 +02003312 }
yanbzhu488a4d22015-12-01 15:16:07 -05003313
yanbzhu488a4d22015-12-01 15:16:07 -05003314 /* Read Private Key */
William Lallemand96a9c972019-10-17 11:56:17 +02003315 key = PEM_read_bio_PrivateKey(in, NULL, NULL, NULL);
3316 if (key == NULL) {
yanbzhu488a4d22015-12-01 15:16:07 -05003317 memprintf(err, "%sunable to load private key from file '%s'.\n",
William Lallemand96a9c972019-10-17 11:56:17 +02003318 err && *err ? *err : "", path);
yanbzhu488a4d22015-12-01 15:16:07 -05003319 goto end;
3320 }
3321
Emmanuel Hocdet54227d82019-07-30 17:04:01 +02003322#ifndef OPENSSL_NO_DH
William Lallemandfa892222019-07-23 16:06:08 +02003323 /* Seek back to beginning of file */
3324 if (BIO_reset(in) == -1) {
3325 memprintf(err, "%san error occurred while reading the file '%s'.\n",
3326 err && *err ? *err : "", path);
3327 goto end;
3328 }
3329
William Lallemand96a9c972019-10-17 11:56:17 +02003330 dh = PEM_read_bio_DHparams(in, NULL, NULL, NULL);
3331 /* no need to return an error there, dh is not mandatory */
Emmanuel Hocdet54227d82019-07-30 17:04:01 +02003332#endif
William Lallemandfa892222019-07-23 16:06:08 +02003333
Willy Tarreaubb137a82016-04-06 19:02:38 +02003334 /* Seek back to beginning of file */
Thierry FOURNIER / OZON.IOd44ea3f2016-10-14 00:49:21 +02003335 if (BIO_reset(in) == -1) {
3336 memprintf(err, "%san error occurred while reading the file '%s'.\n",
3337 err && *err ? *err : "", path);
3338 goto end;
3339 }
Willy Tarreaubb137a82016-04-06 19:02:38 +02003340
3341 /* Read Certificate */
William Lallemand96a9c972019-10-17 11:56:17 +02003342 cert = PEM_read_bio_X509_AUX(in, NULL, NULL, NULL);
3343 if (cert == NULL) {
Willy Tarreaubb137a82016-04-06 19:02:38 +02003344 memprintf(err, "%sunable to load certificate from file '%s'.\n",
William Lallemand96a9c972019-10-17 11:56:17 +02003345 err && *err ? *err : "", path);
Willy Tarreaubb137a82016-04-06 19:02:38 +02003346 goto end;
3347 }
3348
William Lallemand96a9c972019-10-17 11:56:17 +02003349 if (!X509_check_private_key(cert, key)) {
Emmanuel Hocdet03e09f32019-07-30 14:21:25 +02003350 memprintf(err, "%sinconsistencies between private key and certificate loaded from PEM file '%s'.\n",
William Lallemand96a9c972019-10-17 11:56:17 +02003351 err && *err ? *err : "", path);
Emmanuel Hocdet03e09f32019-07-30 14:21:25 +02003352 goto end;
3353 }
3354
William Lallemand96a9c972019-10-17 11:56:17 +02003355 /* Look for a Certificate Chain */
Emmanuel Hocdet6b5b44e2019-12-20 17:47:12 +01003356 while ((ca = PEM_read_bio_X509(in, NULL, NULL, NULL))) {
3357 if (chain == NULL)
3358 chain = sk_X509_new_null();
3359 if (!sk_X509_push(chain, ca)) {
William Lallemand96a9c972019-10-17 11:56:17 +02003360 X509_free(ca);
3361 goto end;
3362 }
3363 }
yanbzhu488a4d22015-12-01 15:16:07 -05003364
Emmanuel Hocdeted17f472019-10-24 18:28:33 +02003365 /* no chain */
Emmanuel Hocdet6b5b44e2019-12-20 17:47:12 +01003366 if (chain == NULL) {
3367 chain = sk_X509_new_null();
Emmanuel Hocdeted17f472019-10-24 18:28:33 +02003368 }
3369
yanbzhu488a4d22015-12-01 15:16:07 -05003370 ret = ERR_get_error();
3371 if (ret && (ERR_GET_LIB(ret) != ERR_LIB_PEM && ERR_GET_REASON(ret) != PEM_R_NO_START_LINE)) {
3372 memprintf(err, "%sunable to load certificate chain from file '%s'.\n",
William Lallemand96a9c972019-10-17 11:56:17 +02003373 err && *err ? *err : "", path);
yanbzhu488a4d22015-12-01 15:16:07 -05003374 goto end;
William Lallemand246c0242019-10-11 08:59:13 +02003375 }
3376
William Lallemand75b15f72020-01-23 10:56:05 +01003377 /* once it loaded the PEM, it should remove everything else in the ckch */
3378 if (ckch->ocsp_response) {
3379 free(ckch->ocsp_response->area);
3380 ckch->ocsp_response->area = NULL;
3381 free(ckch->ocsp_response);
3382 ckch->ocsp_response = NULL;
3383 }
3384
3385 if (ckch->sctl) {
3386 free(ckch->sctl->area);
3387 ckch->sctl->area = NULL;
3388 free(ckch->sctl);
3389 ckch->sctl = NULL;
3390 }
3391
3392 if (ckch->ocsp_issuer) {
3393 X509_free(ckch->ocsp_issuer);
3394 ckch->ocsp_issuer = NULL;
3395 }
3396
Emmanuel Hocdet6b5b44e2019-12-20 17:47:12 +01003397 /* no error, fill ckch with new context, old context will be free at end: */
3398 SWAP(ckch->key, key);
3399 SWAP(ckch->dh, dh);
3400 SWAP(ckch->cert, cert);
3401 SWAP(ckch->chain, chain);
3402
Emmanuel Hocdet078156d2020-01-22 17:02:53 +01003403 /* check if one of the certificate of the chain is the issuer */
3404 for (i = 0; i < sk_X509_num(ckch->chain); i++) {
3405 X509 *issuer = sk_X509_value(ckch->chain, i);
3406 if (X509_check_issued(issuer, ckch->cert) == X509_V_OK) {
3407 ckch->ocsp_issuer = issuer;
3408 X509_up_ref(issuer);
3409 break;
3410 }
3411 }
William Lallemand246c0242019-10-11 08:59:13 +02003412 ret = 0;
3413
William Lallemand96a9c972019-10-17 11:56:17 +02003414end:
William Lallemand246c0242019-10-11 08:59:13 +02003415
3416 ERR_clear_error();
William Lallemand96a9c972019-10-17 11:56:17 +02003417 if (in)
William Lallemand246c0242019-10-11 08:59:13 +02003418 BIO_free(in);
Emmanuel Hocdet83cbd3c2019-10-25 11:55:03 +02003419 if (key)
3420 EVP_PKEY_free(key);
Emmanuel Hocdet6b5b44e2019-12-20 17:47:12 +01003421 if (dh)
3422 DH_free(dh);
Emmanuel Hocdet83cbd3c2019-10-25 11:55:03 +02003423 if (cert)
3424 X509_free(cert);
Emmanuel Hocdet6b5b44e2019-12-20 17:47:12 +01003425 if (chain)
3426 sk_X509_pop_free(chain, X509_free);
William Lallemanda17f4112019-10-10 15:16:44 +02003427
William Lallemand96a9c972019-10-17 11:56:17 +02003428 return ret;
3429}
3430
3431/*
3432 * Try to load in a ckch every files related to a ckch.
3433 * (PEM, sctl, ocsp, issuer etc.)
3434 *
3435 * This function is only used to load files during the configuration parsing,
3436 * it is not used with the CLI.
3437 *
3438 * This allows us to carry the contents of the file without having to read the
3439 * file multiple times. The caller must call
3440 * ssl_sock_free_cert_key_and_chain_contents.
3441 *
3442 * returns:
3443 * 0 on Success
3444 * 1 on SSL Failure
3445 */
3446static int ssl_sock_load_files_into_ckch(const char *path, struct cert_key_and_chain *ckch, char **err)
3447{
3448 int ret = 1;
3449
3450 /* try to load the PEM */
3451 if (ssl_sock_load_pem_into_ckch(path, NULL, ckch , err) != 0) {
3452 goto end;
3453 }
3454
William Lallemanda17f4112019-10-10 15:16:44 +02003455#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
3456 /* try to load the sctl file */
William Lallemand3af48e72020-02-03 17:15:52 +01003457 if (global_ssl.extra_files & SSL_GF_SCTL) {
William Lallemanda17f4112019-10-10 15:16:44 +02003458 char fp[MAXPATHLEN+1];
3459 struct stat st;
3460
3461 snprintf(fp, MAXPATHLEN+1, "%s.sctl", path);
3462 if (stat(fp, &st) == 0) {
William Lallemand0dfae6c2019-10-16 18:06:58 +02003463 if (ssl_sock_load_sctl_from_file(fp, NULL, ckch, err)) {
William Lallemanda17f4112019-10-10 15:16:44 +02003464 memprintf(err, "%s '%s.sctl' is present but cannot be read or parsed'.\n",
Tim Duesterhus93128532019-11-23 23:45:10 +01003465 err && *err ? *err : "", fp);
William Lallemanda17f4112019-10-10 15:16:44 +02003466 ret = 1;
3467 goto end;
3468 }
3469 }
3470 }
3471#endif
yanbzhu488a4d22015-12-01 15:16:07 -05003472
William Lallemand246c0242019-10-11 08:59:13 +02003473 /* try to load an ocsp response file */
William Lallemand3af48e72020-02-03 17:15:52 +01003474 if (global_ssl.extra_files & SSL_GF_OCSP) {
William Lallemand246c0242019-10-11 08:59:13 +02003475 char fp[MAXPATHLEN+1];
3476 struct stat st;
3477
3478 snprintf(fp, MAXPATHLEN+1, "%s.ocsp", path);
3479 if (stat(fp, &st) == 0) {
William Lallemand3b5f3602019-10-16 18:05:05 +02003480 if (ssl_sock_load_ocsp_response_from_file(fp, NULL, ckch, err)) {
William Lallemand246c0242019-10-11 08:59:13 +02003481 ret = 1;
3482 goto end;
3483 }
3484 }
3485 }
3486
Emmanuel Hocdeteaad5cc2019-10-25 12:19:00 +02003487#ifndef OPENSSL_IS_BORINGSSL /* Useless for BoringSSL */
William Lallemand3af48e72020-02-03 17:15:52 +01003488 if (ckch->ocsp_response && (global_ssl.extra_files & SSL_GF_OCSP_ISSUER)) {
William Lallemand246c0242019-10-11 08:59:13 +02003489 /* if no issuer was found, try to load an issuer from the .issuer */
Emmanuel Hocdet078156d2020-01-22 17:02:53 +01003490 if (!ckch->ocsp_issuer) {
William Lallemand246c0242019-10-11 08:59:13 +02003491 struct stat st;
3492 char fp[MAXPATHLEN+1];
3493
3494 snprintf(fp, MAXPATHLEN+1, "%s.issuer", path);
3495 if (stat(fp, &st) == 0) {
William Lallemandf9568fc2019-10-16 18:27:58 +02003496 if (ssl_sock_load_issuer_file_into_ckch(fp, NULL, ckch, err)) {
William Lallemand246c0242019-10-11 08:59:13 +02003497 ret = 1;
3498 goto end;
3499 }
3500
3501 if (X509_check_issued(ckch->ocsp_issuer, ckch->cert) != X509_V_OK) {
William Lallemand786188f2019-10-15 10:05:37 +02003502 memprintf(err, "%s '%s' is not an issuer'.\n",
Tim Duesterhus93128532019-11-23 23:45:10 +01003503 err && *err ? *err : "", fp);
William Lallemand246c0242019-10-11 08:59:13 +02003504 ret = 1;
3505 goto end;
3506 }
3507 } else {
3508 memprintf(err, "%sNo issuer found, cannot use the OCSP response'.\n",
Tim Duesterhus93128532019-11-23 23:45:10 +01003509 err && *err ? *err : "");
William Lallemand246c0242019-10-11 08:59:13 +02003510 ret = 1;
3511 goto end;
3512 }
3513 }
3514 }
Emmanuel Hocdeteaad5cc2019-10-25 12:19:00 +02003515#endif
William Lallemand246c0242019-10-11 08:59:13 +02003516
yanbzhu488a4d22015-12-01 15:16:07 -05003517 ret = 0;
3518
3519end:
3520
3521 ERR_clear_error();
yanbzhu488a4d22015-12-01 15:16:07 -05003522
3523 /* Something went wrong in one of the reads */
3524 if (ret != 0)
3525 ssl_sock_free_cert_key_and_chain_contents(ckch);
3526
3527 return ret;
3528}
3529
3530/* Loads the info in ckch into ctx
Emeric Bruna96b5822019-10-17 13:25:14 +02003531 * Returns a bitfield containing the flags:
3532 * ERR_FATAL in any fatal error case
3533 * ERR_ALERT if the reason of the error is available in err
3534 * ERR_WARN if a warning is available into err
3535 * The value 0 means there is no error nor warning and
3536 * the operation succeed.
yanbzhu488a4d22015-12-01 15:16:07 -05003537 */
3538static int ssl_sock_put_ckch_into_ctx(const char *path, const struct cert_key_and_chain *ckch, SSL_CTX *ctx, char **err)
3539{
Emeric Bruna96b5822019-10-17 13:25:14 +02003540 int errcode = 0;
3541
yanbzhu488a4d22015-12-01 15:16:07 -05003542 if (SSL_CTX_use_PrivateKey(ctx, ckch->key) <= 0) {
3543 memprintf(err, "%sunable to load SSL private key into SSL Context '%s'.\n",
3544 err && *err ? *err : "", path);
Emeric Bruna96b5822019-10-17 13:25:14 +02003545 errcode |= ERR_ALERT | ERR_FATAL;
3546 return errcode;
yanbzhu488a4d22015-12-01 15:16:07 -05003547 }
3548
3549 if (!SSL_CTX_use_certificate(ctx, ckch->cert)) {
3550 memprintf(err, "%sunable to load SSL certificate into SSL Context '%s'.\n",
3551 err && *err ? *err : "", path);
Emeric Bruna96b5822019-10-17 13:25:14 +02003552 errcode |= ERR_ALERT | ERR_FATAL;
3553 goto end;
yanbzhu488a4d22015-12-01 15:16:07 -05003554 }
3555
yanbzhu488a4d22015-12-01 15:16:07 -05003556 /* Load all certs in the ckch into the ctx_chain for the ssl_ctx */
Emmanuel Hocdet1c65fdd2018-12-03 18:07:44 +01003557#ifdef SSL_CTX_set1_chain
Emmanuel Hocdet9246f8b2018-11-30 16:00:21 +01003558 if (!SSL_CTX_set1_chain(ctx, ckch->chain)) {
3559 memprintf(err, "%sunable to load chain certificate into SSL Context '%s'. Make sure you are linking against Openssl >= 1.0.2.\n",
3560 err && *err ? *err : "", path);
Emeric Bruna96b5822019-10-17 13:25:14 +02003561 errcode |= ERR_ALERT | ERR_FATAL;
3562 goto end;
yanbzhu488a4d22015-12-01 15:16:07 -05003563 }
Emmanuel Hocdet1c65fdd2018-12-03 18:07:44 +01003564#else
3565 { /* legacy compat (< openssl 1.0.2) */
3566 X509 *ca;
Emmanuel Hocdet140b64f2019-10-24 18:33:10 +02003567 STACK_OF(X509) *chain;
3568 chain = X509_chain_up_ref(ckch->chain);
3569 while ((ca = sk_X509_shift(chain)))
Emmanuel Hocdet1c65fdd2018-12-03 18:07:44 +01003570 if (!SSL_CTX_add_extra_chain_cert(ctx, ca)) {
3571 memprintf(err, "%sunable to load chain certificate into SSL Context '%s'.\n",
3572 err && *err ? *err : "", path);
3573 X509_free(ca);
Emmanuel Hocdet140b64f2019-10-24 18:33:10 +02003574 sk_X509_pop_free(chain, X509_free);
Emeric Bruna96b5822019-10-17 13:25:14 +02003575 errcode |= ERR_ALERT | ERR_FATAL;
3576 goto end;
Emmanuel Hocdet1c65fdd2018-12-03 18:07:44 +01003577 }
3578 }
3579#endif
yanbzhu488a4d22015-12-01 15:16:07 -05003580
William Lallemandfa892222019-07-23 16:06:08 +02003581#ifndef OPENSSL_NO_DH
3582 /* store a NULL pointer to indicate we have not yet loaded
3583 a custom DH param file */
3584 if (ssl_dh_ptr_index >= 0) {
3585 SSL_CTX_set_ex_data(ctx, ssl_dh_ptr_index, NULL);
3586 }
3587
Emeric Brun7a883362019-10-17 13:27:40 +02003588 errcode |= ssl_sock_load_dh_params(ctx, ckch, path, err);
3589 if (errcode & ERR_CODE) {
William Lallemandfa892222019-07-23 16:06:08 +02003590 memprintf(err, "%sunable to load DH parameters from file '%s'.\n",
3591 err && *err ? *err : "", path);
Emeric Bruna96b5822019-10-17 13:25:14 +02003592 goto end;
William Lallemandfa892222019-07-23 16:06:08 +02003593 }
3594#endif
3595
William Lallemanda17f4112019-10-10 15:16:44 +02003596#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
3597 if (sctl_ex_index >= 0 && ckch->sctl) {
3598 if (ssl_sock_load_sctl(ctx, ckch->sctl) < 0) {
3599 memprintf(err, "%s '%s.sctl' is present but cannot be read or parsed'.\n",
Tim Duesterhus93128532019-11-23 23:45:10 +01003600 err && *err ? *err : "", path);
Emeric Bruna96b5822019-10-17 13:25:14 +02003601 errcode |= ERR_ALERT | ERR_FATAL;
3602 goto end;
William Lallemanda17f4112019-10-10 15:16:44 +02003603 }
3604 }
3605#endif
3606
William Lallemand4a660132019-10-14 14:51:41 +02003607#if ((defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP) || defined OPENSSL_IS_BORINGSSL)
William Lallemand246c0242019-10-11 08:59:13 +02003608 /* Load OCSP Info into context */
3609 if (ckch->ocsp_response) {
3610 if (ssl_sock_load_ocsp(ctx, ckch) < 0) {
Tim Duesterhus93128532019-11-23 23:45:10 +01003611 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",
3612 err && *err ? *err : "", path);
Emeric Bruna96b5822019-10-17 13:25:14 +02003613 errcode |= ERR_ALERT | ERR_FATAL;
3614 goto end;
William Lallemand246c0242019-10-11 08:59:13 +02003615 }
3616 }
William Lallemand246c0242019-10-11 08:59:13 +02003617#endif
3618
Emeric Bruna96b5822019-10-17 13:25:14 +02003619 end:
3620 return errcode;
yanbzhu488a4d22015-12-01 15:16:07 -05003621}
3622
William Lallemandc4ecddf2019-07-31 16:50:08 +02003623#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
yanbzhu08ce6ab2015-12-02 13:01:29 -05003624
William Lallemand28a8fce2019-10-04 17:36:55 +02003625static int ssl_sock_populate_sni_keytypes_hplr(const char *str, struct eb_root *sni_keytypes, int key_index)
yanbzhu08ce6ab2015-12-02 13:01:29 -05003626{
3627 struct sni_keytype *s_kt = NULL;
3628 struct ebmb_node *node;
3629 int i;
3630
3631 for (i = 0; i < trash.size; i++) {
3632 if (!str[i])
3633 break;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02003634 trash.area[i] = tolower(str[i]);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003635 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +02003636 trash.area[i] = 0;
3637 node = ebst_lookup(sni_keytypes, trash.area);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003638 if (!node) {
3639 /* CN not found in tree */
3640 s_kt = malloc(sizeof(struct sni_keytype) + i + 1);
3641 /* Using memcpy here instead of strncpy.
3642 * strncpy will cause sig_abrt errors under certain versions of gcc with -O2
3643 * See: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=60792
3644 */
William Lallemand28a8fce2019-10-04 17:36:55 +02003645 if (!s_kt)
3646 return -1;
3647
Willy Tarreau843b7cb2018-07-13 10:54:26 +02003648 memcpy(s_kt->name.key, trash.area, i+1);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003649 s_kt->keytypes = 0;
3650 ebst_insert(sni_keytypes, &s_kt->name);
3651 } else {
3652 /* CN found in tree */
3653 s_kt = container_of(node, struct sni_keytype, name);
3654 }
3655
3656 /* Mark that this CN has the keytype of key_index via keytypes mask */
3657 s_kt->keytypes |= 1<<key_index;
3658
William Lallemand28a8fce2019-10-04 17:36:55 +02003659 return 0;
3660
yanbzhu08ce6ab2015-12-02 13:01:29 -05003661}
3662
William Lallemandc4ecddf2019-07-31 16:50:08 +02003663#endif
William Lallemand8c1cdde2019-10-18 10:58:14 +02003664/*
3665 * Free a ckch_store and its ckch(s)
3666 * The linked ckch_inst are not free'd
3667 */
3668void ckchs_free(struct ckch_store *ckchs)
3669{
3670 if (!ckchs)
3671 return;
3672
3673#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
3674 if (ckchs->multi) {
3675 int n;
3676
3677 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++)
3678 ssl_sock_free_cert_key_and_chain_contents(&ckchs->ckch[n]);
3679 } else
3680#endif
3681 {
3682 ssl_sock_free_cert_key_and_chain_contents(ckchs->ckch);
3683 ckchs->ckch = NULL;
3684 }
3685
3686 free(ckchs);
3687}
3688
3689/* allocate and duplicate a ckch_store
3690 * Return a new ckch_store or NULL */
3691static struct ckch_store *ckchs_dup(const struct ckch_store *src)
3692{
3693 struct ckch_store *dst;
3694 int pathlen;
3695
3696 pathlen = strlen(src->path);
3697 dst = calloc(1, sizeof(*dst) + pathlen + 1);
3698 if (!dst)
3699 return NULL;
3700 /* copy previous key */
3701 memcpy(dst->path, src->path, pathlen + 1);
3702 dst->multi = src->multi;
3703 LIST_INIT(&dst->ckch_inst);
3704
3705 dst->ckch = calloc((src->multi ? SSL_SOCK_NUM_KEYTYPES : 1), sizeof(*dst->ckch));
3706 if (!dst->ckch)
3707 goto error;
3708
3709#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
3710 if (src->multi) {
3711 int n;
3712
3713 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
3714 if (&src->ckch[n]) {
3715 if (!ssl_sock_copy_cert_key_and_chain(&src->ckch[n], &dst->ckch[n]))
3716 goto error;
3717 }
3718 }
3719 } else
3720#endif
3721 {
3722 if (!ssl_sock_copy_cert_key_and_chain(src->ckch, dst->ckch))
3723 goto error;
3724 }
3725
3726 return dst;
3727
3728error:
3729 ckchs_free(dst);
3730
3731 return NULL;
3732}
William Lallemandc4ecddf2019-07-31 16:50:08 +02003733
William Lallemand36b84632019-07-18 19:28:17 +02003734/*
William Lallemande3af8fb2019-10-08 11:36:53 +02003735 * lookup a path into the ckchs tree.
William Lallemand6af03992019-07-23 15:00:54 +02003736 */
William Lallemande3af8fb2019-10-08 11:36:53 +02003737static inline struct ckch_store *ckchs_lookup(char *path)
William Lallemand6af03992019-07-23 15:00:54 +02003738{
3739 struct ebmb_node *eb;
3740
William Lallemande3af8fb2019-10-08 11:36:53 +02003741 eb = ebst_lookup(&ckchs_tree, path);
William Lallemand6af03992019-07-23 15:00:54 +02003742 if (!eb)
3743 return NULL;
3744
William Lallemande3af8fb2019-10-08 11:36:53 +02003745 return ebmb_entry(eb, struct ckch_store, node);
William Lallemand6af03992019-07-23 15:00:54 +02003746}
3747
3748/*
William Lallemande3af8fb2019-10-08 11:36:53 +02003749 * This function allocate a ckch_store and populate it with certificates from files.
William Lallemand36b84632019-07-18 19:28:17 +02003750 */
William Lallemande3af8fb2019-10-08 11:36:53 +02003751static struct ckch_store *ckchs_load_cert_file(char *path, int multi, char **err)
William Lallemand36b84632019-07-18 19:28:17 +02003752{
William Lallemande3af8fb2019-10-08 11:36:53 +02003753 struct ckch_store *ckchs;
William Lallemand36b84632019-07-18 19:28:17 +02003754
William Lallemande3af8fb2019-10-08 11:36:53 +02003755 ckchs = calloc(1, sizeof(*ckchs) + strlen(path) + 1);
3756 if (!ckchs) {
William Lallemand36b84632019-07-18 19:28:17 +02003757 memprintf(err, "%sunable to allocate memory.\n", err && *err ? *err : "");
3758 goto end;
3759 }
William Lallemande3af8fb2019-10-08 11:36:53 +02003760 ckchs->ckch = calloc(1, sizeof(*ckchs->ckch) * (multi ? SSL_SOCK_NUM_KEYTYPES : 1));
William Lallemand36b84632019-07-18 19:28:17 +02003761
William Lallemande3af8fb2019-10-08 11:36:53 +02003762 if (!ckchs->ckch) {
William Lallemand36b84632019-07-18 19:28:17 +02003763 memprintf(err, "%sunable to allocate memory.\n", err && *err ? *err : "");
3764 goto end;
3765 }
3766
William Lallemand9117de92019-10-04 00:29:42 +02003767 LIST_INIT(&ckchs->ckch_inst);
3768
William Lallemand36b84632019-07-18 19:28:17 +02003769 if (!multi) {
3770
William Lallemand96a9c972019-10-17 11:56:17 +02003771 if (ssl_sock_load_files_into_ckch(path, ckchs->ckch, err) == 1)
William Lallemand36b84632019-07-18 19:28:17 +02003772 goto end;
3773
William Lallemande3af8fb2019-10-08 11:36:53 +02003774 /* insert into the ckchs tree */
3775 memcpy(ckchs->path, path, strlen(path) + 1);
3776 ebst_insert(&ckchs_tree, &ckchs->node);
William Lallemand36b84632019-07-18 19:28:17 +02003777 } else {
3778 int found = 0;
William Lallemandc4ecddf2019-07-31 16:50:08 +02003779#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
3780 char fp[MAXPATHLEN+1] = {0};
3781 int n = 0;
William Lallemand36b84632019-07-18 19:28:17 +02003782
3783 /* Load all possible certs and keys */
3784 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
3785 struct stat buf;
3786 snprintf(fp, sizeof(fp), "%s.%s", path, SSL_SOCK_KEYTYPE_NAMES[n]);
3787 if (stat(fp, &buf) == 0) {
William Lallemand96a9c972019-10-17 11:56:17 +02003788 if (ssl_sock_load_files_into_ckch(fp, &ckchs->ckch[n], err) == 1)
William Lallemand36b84632019-07-18 19:28:17 +02003789 goto end;
3790 found = 1;
William Lallemande3af8fb2019-10-08 11:36:53 +02003791 ckchs->multi = 1;
William Lallemand36b84632019-07-18 19:28:17 +02003792 }
3793 }
William Lallemandc4ecddf2019-07-31 16:50:08 +02003794#endif
William Lallemand36b84632019-07-18 19:28:17 +02003795
3796 if (!found) {
William Lallemand6e5f2ce2019-08-01 14:43:20 +02003797 memprintf(err, "%sDidn't find any certificate for bundle '%s'.\n", err && *err ? *err : "", path);
William Lallemand36b84632019-07-18 19:28:17 +02003798 goto end;
3799 }
William Lallemande3af8fb2019-10-08 11:36:53 +02003800 /* insert into the ckchs tree */
3801 memcpy(ckchs->path, path, strlen(path) + 1);
3802 ebst_insert(&ckchs_tree, &ckchs->node);
William Lallemand36b84632019-07-18 19:28:17 +02003803 }
William Lallemande3af8fb2019-10-08 11:36:53 +02003804 return ckchs;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003805
William Lallemand36b84632019-07-18 19:28:17 +02003806end:
William Lallemande3af8fb2019-10-08 11:36:53 +02003807 if (ckchs) {
3808 free(ckchs->ckch);
3809 ebmb_delete(&ckchs->node);
William Lallemand6af03992019-07-23 15:00:54 +02003810 }
3811
William Lallemande3af8fb2019-10-08 11:36:53 +02003812 free(ckchs);
William Lallemand36b84632019-07-18 19:28:17 +02003813
3814 return NULL;
3815}
3816
William Lallemandc4ecddf2019-07-31 16:50:08 +02003817#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
3818
William Lallemand36b84632019-07-18 19:28:17 +02003819/*
William Lallemande3af8fb2019-10-08 11:36:53 +02003820 * Take a ckch_store which contains a multi-certificate bundle.
William Lallemand36b84632019-07-18 19:28:17 +02003821 * Group these certificates into a set of SSL_CTX*
yanbzhu08ce6ab2015-12-02 13:01:29 -05003822 * based on shared and unique CN and SAN entries. Add these SSL_CTX* to the SNI tree.
3823 *
Joseph Herlant017b3da2018-11-15 09:07:59 -08003824 * This will allow the user to explicitly group multiple cert/keys for a single purpose
yanbzhu08ce6ab2015-12-02 13:01:29 -05003825 *
Emeric Brun054563d2019-10-17 13:16:58 +02003826 * Returns a bitfield containing the flags:
3827 * ERR_FATAL in any fatal error case
3828 * ERR_ALERT if the reason of the error is available in err
3829 * ERR_WARN if a warning is available into err
William Lallemand36b84632019-07-18 19:28:17 +02003830 *
yanbzhu08ce6ab2015-12-02 13:01:29 -05003831 */
Emeric Brun054563d2019-10-17 13:16:58 +02003832static int ckch_inst_new_load_multi_store(const char *path, struct ckch_store *ckchs,
3833 struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
3834 char **sni_filter, int fcount, struct ckch_inst **ckchi, char **err)
yanbzhu08ce6ab2015-12-02 13:01:29 -05003835{
William Lallemand36b84632019-07-18 19:28:17 +02003836 int i = 0, n = 0;
3837 struct cert_key_and_chain *certs_and_keys;
William Lallemand4b989f22019-10-04 18:36:55 +02003838 struct eb_root sni_keytypes_map = EB_ROOT;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003839 struct ebmb_node *node;
3840 struct ebmb_node *next;
3841 /* Array of SSL_CTX pointers corresponding to each possible combo
3842 * of keytypes
3843 */
3844 struct key_combo_ctx key_combos[SSL_SOCK_POSSIBLE_KT_COMBOS] = { {0} };
Emeric Brun054563d2019-10-17 13:16:58 +02003845 int errcode = 0;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003846 X509_NAME *xname = NULL;
3847 char *str = NULL;
3848#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
3849 STACK_OF(GENERAL_NAME) *names = NULL;
3850#endif
William Lallemand614ca0d2019-10-07 13:52:11 +02003851 struct ckch_inst *ckch_inst;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003852
Emeric Brun054563d2019-10-17 13:16:58 +02003853 *ckchi = NULL;
3854
William Lallemande3af8fb2019-10-08 11:36:53 +02003855 if (!ckchs || !ckchs->ckch || !ckchs->multi) {
William Lallemand36b84632019-07-18 19:28:17 +02003856 memprintf(err, "%sunable to load SSL certificate file '%s' file does not exist.\n",
3857 err && *err ? *err : "", path);
Emeric Brun054563d2019-10-17 13:16:58 +02003858 return ERR_ALERT | ERR_FATAL;
William Lallemand614ca0d2019-10-07 13:52:11 +02003859 }
3860
3861 ckch_inst = ckch_inst_new();
3862 if (!ckch_inst) {
3863 memprintf(err, "%sunable to allocate SSL context for cert '%s'.\n",
3864 err && *err ? *err : "", path);
Emeric Brun054563d2019-10-17 13:16:58 +02003865 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemand614ca0d2019-10-07 13:52:11 +02003866 goto end;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003867 }
3868
William Lallemande3af8fb2019-10-08 11:36:53 +02003869 certs_and_keys = ckchs->ckch;
William Lallemand36b84632019-07-18 19:28:17 +02003870
William Lallemand150bfa82019-09-19 17:12:49 +02003871 /* at least one of the instances is using filters during the config
3872 * parsing, that's ok to inherit this during loading on CLI */
William Lallemand920b0352019-12-04 15:33:01 +01003873 ckchs->filters |= !!fcount;
William Lallemand150bfa82019-09-19 17:12:49 +02003874
yanbzhu08ce6ab2015-12-02 13:01:29 -05003875 /* Process each ckch and update keytypes for each CN/SAN
3876 * for example, if CN/SAN www.a.com is associated with
3877 * certs with keytype 0 and 2, then at the end of the loop,
3878 * www.a.com will have:
3879 * keyindex = 0 | 1 | 4 = 5
3880 */
3881 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
William Lallemand28a8fce2019-10-04 17:36:55 +02003882 int ret;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003883
3884 if (!ssl_sock_is_ckch_valid(&certs_and_keys[n]))
3885 continue;
3886
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003887 if (fcount) {
William Lallemand28a8fce2019-10-04 17:36:55 +02003888 for (i = 0; i < fcount; i++) {
3889 ret = ssl_sock_populate_sni_keytypes_hplr(sni_filter[i], &sni_keytypes_map, n);
3890 if (ret < 0) {
3891 memprintf(err, "%sunable to allocate SSL context.\n",
3892 err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02003893 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemand28a8fce2019-10-04 17:36:55 +02003894 goto end;
3895 }
3896 }
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003897 } else {
3898 /* A lot of the following code is OpenSSL boilerplate for processing CN's and SAN's,
3899 * so the line that contains logic is marked via comments
3900 */
3901 xname = X509_get_subject_name(certs_and_keys[n].cert);
3902 i = -1;
3903 while ((i = X509_NAME_get_index_by_NID(xname, NID_commonName, i)) != -1) {
3904 X509_NAME_ENTRY *entry = X509_NAME_get_entry(xname, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003905 ASN1_STRING *value;
3906 value = X509_NAME_ENTRY_get_data(entry);
3907 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003908 /* Important line is here */
William Lallemand28a8fce2019-10-04 17:36:55 +02003909 ret = ssl_sock_populate_sni_keytypes_hplr(str, &sni_keytypes_map, n);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003910
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003911 OPENSSL_free(str);
3912 str = NULL;
William Lallemand28a8fce2019-10-04 17:36:55 +02003913 if (ret < 0) {
3914 memprintf(err, "%sunable to allocate SSL context.\n",
3915 err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02003916 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemand28a8fce2019-10-04 17:36:55 +02003917 goto end;
3918 }
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003919 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003920 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003921
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003922 /* Do the above logic for each SAN */
yanbzhu08ce6ab2015-12-02 13:01:29 -05003923#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003924 names = X509_get_ext_d2i(certs_and_keys[n].cert, NID_subject_alt_name, NULL, NULL);
3925 if (names) {
3926 for (i = 0; i < sk_GENERAL_NAME_num(names); i++) {
3927 GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003928
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003929 if (name->type == GEN_DNS) {
3930 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
3931 /* Important line is here */
William Lallemand28a8fce2019-10-04 17:36:55 +02003932 ret = ssl_sock_populate_sni_keytypes_hplr(str, &sni_keytypes_map, n);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003933
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003934 OPENSSL_free(str);
3935 str = NULL;
William Lallemand28a8fce2019-10-04 17:36:55 +02003936 if (ret < 0) {
3937 memprintf(err, "%sunable to allocate SSL context.\n",
3938 err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02003939 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemand28a8fce2019-10-04 17:36:55 +02003940 goto end;
3941 }
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003942 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003943 }
3944 }
3945 }
3946 }
3947#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
3948 }
3949
3950 /* If no files found, return error */
3951 if (eb_is_empty(&sni_keytypes_map)) {
3952 memprintf(err, "%sunable to load SSL certificate file '%s' file does not exist.\n",
3953 err && *err ? *err : "", path);
Emeric Brun054563d2019-10-17 13:16:58 +02003954 errcode |= ERR_ALERT | ERR_FATAL;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003955 goto end;
3956 }
3957
3958 /* We now have a map of CN/SAN to keytypes that are loaded in
3959 * Iterate through the map to create the SSL_CTX's (if needed)
3960 * and add each CTX to the SNI tree
3961 *
3962 * Some math here:
Joseph Herlant017b3da2018-11-15 09:07:59 -08003963 * There are 2^n - 1 possible combinations, each unique
yanbzhu08ce6ab2015-12-02 13:01:29 -05003964 * combination is denoted by the key in the map. Each key
3965 * has a value between 1 and 2^n - 1. Conveniently, the array
3966 * of SSL_CTX* is sized 2^n. So, we can simply use the i'th
3967 * entry in the array to correspond to the unique combo (key)
3968 * associated with i. This unique key combo (i) will be associated
3969 * with combos[i-1]
3970 */
3971
3972 node = ebmb_first(&sni_keytypes_map);
3973 while (node) {
3974 SSL_CTX *cur_ctx;
Bertrand Jacquin33423092016-11-13 16:37:13 +00003975 char cur_file[MAXPATHLEN+1];
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003976 const struct pkey_info kinfo = { .sig = TLSEXT_signature_anonymous, .bits = 0 };
yanbzhu08ce6ab2015-12-02 13:01:29 -05003977
3978 str = (char *)container_of(node, struct sni_keytype, name)->name.key;
3979 i = container_of(node, struct sni_keytype, name)->keytypes;
3980 cur_ctx = key_combos[i-1].ctx;
3981
3982 if (cur_ctx == NULL) {
3983 /* need to create SSL_CTX */
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003984 cur_ctx = SSL_CTX_new(SSLv23_server_method());
yanbzhu08ce6ab2015-12-02 13:01:29 -05003985 if (cur_ctx == NULL) {
3986 memprintf(err, "%sunable to allocate SSL context.\n",
3987 err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02003988 errcode |= ERR_ALERT | ERR_FATAL;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003989 goto end;
3990 }
3991
yanbzhube2774d2015-12-10 15:07:30 -05003992 /* Load all required certs/keys/chains/OCSPs info into SSL_CTX */
yanbzhu08ce6ab2015-12-02 13:01:29 -05003993 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
3994 if (i & (1<<n)) {
3995 /* Key combo contains ckch[n] */
Bertrand Jacquin33423092016-11-13 16:37:13 +00003996 snprintf(cur_file, MAXPATHLEN+1, "%s.%s", path, SSL_SOCK_KEYTYPE_NAMES[n]);
Emeric Bruna96b5822019-10-17 13:25:14 +02003997 errcode |= ssl_sock_put_ckch_into_ctx(cur_file, &certs_and_keys[n], cur_ctx, err);
3998 if (errcode & ERR_CODE)
yanbzhu08ce6ab2015-12-02 13:01:29 -05003999 goto end;
yanbzhu08ce6ab2015-12-02 13:01:29 -05004000 }
4001 }
4002
yanbzhu08ce6ab2015-12-02 13:01:29 -05004003 /* Update key_combos */
4004 key_combos[i-1].ctx = cur_ctx;
4005 }
4006
4007 /* Update SNI Tree */
William Lallemand9117de92019-10-04 00:29:42 +02004008
William Lallemand1d29c742019-10-04 00:53:29 +02004009 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 +02004010 kinfo, str, key_combos[i-1].order);
4011 if (key_combos[i-1].order < 0) {
4012 memprintf(err, "%sunable to create a sni context.\n", err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02004013 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemandfe49bb32019-10-03 23:46:33 +02004014 goto end;
4015 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05004016 node = ebmb_next(node);
4017 }
4018
4019
4020 /* Mark a default context if none exists, using the ctx that has the most shared keys */
4021 if (!bind_conf->default_ctx) {
4022 for (i = SSL_SOCK_POSSIBLE_KT_COMBOS - 1; i >= 0; i--) {
4023 if (key_combos[i].ctx) {
4024 bind_conf->default_ctx = key_combos[i].ctx;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004025 bind_conf->default_ssl_conf = ssl_conf;
William Lallemand21724f02019-11-04 17:56:13 +01004026 ckch_inst->is_default = 1;
yanbzhu08ce6ab2015-12-02 13:01:29 -05004027 break;
4028 }
4029 }
4030 }
4031
William Lallemand614ca0d2019-10-07 13:52:11 +02004032 ckch_inst->bind_conf = bind_conf;
William Lallemand150bfa82019-09-19 17:12:49 +02004033 ckch_inst->ssl_conf = ssl_conf;
yanbzhu08ce6ab2015-12-02 13:01:29 -05004034end:
4035
4036 if (names)
4037 sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
4038
yanbzhu08ce6ab2015-12-02 13:01:29 -05004039 node = ebmb_first(&sni_keytypes_map);
4040 while (node) {
4041 next = ebmb_next(node);
4042 ebmb_delete(node);
William Lallemand8ed5b962019-10-04 17:24:39 +02004043 free(ebmb_entry(node, struct sni_keytype, name));
yanbzhu08ce6ab2015-12-02 13:01:29 -05004044 node = next;
4045 }
4046
Emeric Brun054563d2019-10-17 13:16:58 +02004047 if (errcode & ERR_CODE && ckch_inst) {
William Lallemand0c6d12f2019-10-04 18:38:51 +02004048 struct sni_ctx *sc0, *sc0b;
4049
4050 /* free the SSL_CTX in case of error */
4051 for (i = 0; i < SSL_SOCK_POSSIBLE_KT_COMBOS; i++) {
4052 if (key_combos[i].ctx)
4053 SSL_CTX_free(key_combos[i].ctx);
4054 }
4055
4056 /* free the sni_ctx in case of error */
4057 list_for_each_entry_safe(sc0, sc0b, &ckch_inst->sni_ctx, by_ckch_inst) {
4058
4059 ebmb_delete(&sc0->name);
4060 LIST_DEL(&sc0->by_ckch_inst);
4061 free(sc0);
4062 }
William Lallemand614ca0d2019-10-07 13:52:11 +02004063 free(ckch_inst);
4064 ckch_inst = NULL;
William Lallemand0c6d12f2019-10-04 18:38:51 +02004065 }
4066
Emeric Brun054563d2019-10-17 13:16:58 +02004067 *ckchi = ckch_inst;
4068 return errcode;
yanbzhu08ce6ab2015-12-02 13:01:29 -05004069}
4070#else
4071/* This is a dummy, that just logs an error and returns error */
Emeric Brun054563d2019-10-17 13:16:58 +02004072static int ckch_inst_new_load_multi_store(const char *path, struct ckch_store *ckchs,
4073 struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
4074 char **sni_filter, int fcount, struct ckch_inst **ckchi, char **err)
yanbzhu08ce6ab2015-12-02 13:01:29 -05004075{
4076 memprintf(err, "%sunable to stat SSL certificate from file '%s' : %s.\n",
4077 err && *err ? *err : "", path, strerror(errno));
Emeric Brun054563d2019-10-17 13:16:58 +02004078 return ERR_ALERT | ERR_FATAL;
yanbzhu08ce6ab2015-12-02 13:01:29 -05004079}
4080
Willy Tarreau9a1ab082019-05-09 13:26:41 +02004081#endif /* #if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL: Support for loading multiple certs into a single SSL_CTX */
yanbzhu488a4d22015-12-01 15:16:07 -05004082
William Lallemand614ca0d2019-10-07 13:52:11 +02004083/*
4084 * This function allocate a ckch_inst and create its snis
Emeric Brun054563d2019-10-17 13:16:58 +02004085 *
4086 * Returns a bitfield containing the flags:
4087 * ERR_FATAL in any fatal error case
4088 * ERR_ALERT if the reason of the error is available in err
4089 * ERR_WARN if a warning is available into err
William Lallemand614ca0d2019-10-07 13:52:11 +02004090 */
Emeric Brun054563d2019-10-17 13:16:58 +02004091static int ckch_inst_new_load_store(const char *path, struct ckch_store *ckchs, struct bind_conf *bind_conf,
4092 struct ssl_bind_conf *ssl_conf, char **sni_filter, int fcount, struct ckch_inst **ckchi, char **err)
Emeric Brunfc0421f2012-09-07 17:30:07 +02004093{
William Lallemandc9402072019-05-15 15:33:54 +02004094 SSL_CTX *ctx;
William Lallemandc9402072019-05-15 15:33:54 +02004095 int i;
Emeric Brunfc0421f2012-09-07 17:30:07 +02004096 int order = 0;
4097 X509_NAME *xname;
4098 char *str;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01004099 EVP_PKEY *pkey;
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02004100 struct pkey_info kinfo = { .sig = TLSEXT_signature_anonymous, .bits = 0 };
Emeric Brunfc0421f2012-09-07 17:30:07 +02004101#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
4102 STACK_OF(GENERAL_NAME) *names;
4103#endif
William Lallemand36b84632019-07-18 19:28:17 +02004104 struct cert_key_and_chain *ckch;
William Lallemand614ca0d2019-10-07 13:52:11 +02004105 struct ckch_inst *ckch_inst = NULL;
Emeric Brun054563d2019-10-17 13:16:58 +02004106 int errcode = 0;
4107
4108 *ckchi = NULL;
William Lallemanda59191b2019-05-15 16:08:56 +02004109
William Lallemande3af8fb2019-10-08 11:36:53 +02004110 if (!ckchs || !ckchs->ckch)
Emeric Brun054563d2019-10-17 13:16:58 +02004111 return ERR_FATAL;
Emeric Brunfc0421f2012-09-07 17:30:07 +02004112
William Lallemande3af8fb2019-10-08 11:36:53 +02004113 ckch = ckchs->ckch;
William Lallemand36b84632019-07-18 19:28:17 +02004114
William Lallemand150bfa82019-09-19 17:12:49 +02004115 /* at least one of the instances is using filters during the config
4116 * parsing, that's ok to inherit this during loading on CLI */
William Lallemand920b0352019-12-04 15:33:01 +01004117 ckchs->filters |= !!fcount;
William Lallemand150bfa82019-09-19 17:12:49 +02004118
William Lallemandc9402072019-05-15 15:33:54 +02004119 ctx = SSL_CTX_new(SSLv23_server_method());
4120 if (!ctx) {
4121 memprintf(err, "%sunable to allocate SSL context for cert '%s'.\n",
4122 err && *err ? *err : "", path);
Emeric Brun054563d2019-10-17 13:16:58 +02004123 errcode |= ERR_ALERT | ERR_FATAL;
4124 goto error;
William Lallemandc9402072019-05-15 15:33:54 +02004125 }
4126
Emeric Bruna96b5822019-10-17 13:25:14 +02004127 errcode |= ssl_sock_put_ckch_into_ctx(path, ckch, ctx, err);
4128 if (errcode & ERR_CODE)
William Lallemand614ca0d2019-10-07 13:52:11 +02004129 goto error;
William Lallemand614ca0d2019-10-07 13:52:11 +02004130
4131 ckch_inst = ckch_inst_new();
4132 if (!ckch_inst) {
4133 memprintf(err, "%sunable to allocate SSL context for cert '%s'.\n",
4134 err && *err ? *err : "", path);
Emeric Brun054563d2019-10-17 13:16:58 +02004135 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemandd9199372019-10-04 15:37:05 +02004136 goto error;
William Lallemandc9402072019-05-15 15:33:54 +02004137 }
4138
William Lallemand36b84632019-07-18 19:28:17 +02004139 pkey = X509_get_pubkey(ckch->cert);
Emmanuel Hocdet05942112017-02-20 16:11:50 +01004140 if (pkey) {
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02004141 kinfo.bits = EVP_PKEY_bits(pkey);
Emmanuel Hocdet05942112017-02-20 16:11:50 +01004142 switch(EVP_PKEY_base_id(pkey)) {
4143 case EVP_PKEY_RSA:
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02004144 kinfo.sig = TLSEXT_signature_rsa;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01004145 break;
4146 case EVP_PKEY_EC:
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02004147 kinfo.sig = TLSEXT_signature_ecdsa;
4148 break;
4149 case EVP_PKEY_DSA:
4150 kinfo.sig = TLSEXT_signature_dsa;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01004151 break;
4152 }
4153 EVP_PKEY_free(pkey);
4154 }
4155
Emeric Brun50bcecc2013-04-22 13:05:23 +02004156 if (fcount) {
William Lallemandfe49bb32019-10-03 23:46:33 +02004157 while (fcount--) {
William Lallemand1d29c742019-10-04 00:53:29 +02004158 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 +02004159 if (order < 0) {
4160 memprintf(err, "%sunable to create a sni context.\n", err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02004161 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemandd9199372019-10-04 15:37:05 +02004162 goto error;
William Lallemandfe49bb32019-10-03 23:46:33 +02004163 }
4164 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004165 }
4166 else {
Emeric Brunfc0421f2012-09-07 17:30:07 +02004167#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
William Lallemand36b84632019-07-18 19:28:17 +02004168 names = X509_get_ext_d2i(ckch->cert, NID_subject_alt_name, NULL, NULL);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004169 if (names) {
4170 for (i = 0; i < sk_GENERAL_NAME_num(names); i++) {
4171 GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i);
4172 if (name->type == GEN_DNS) {
4173 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
William Lallemand1d29c742019-10-04 00:53:29 +02004174 order = ckch_inst_add_cert_sni(ctx, ckch_inst, bind_conf, ssl_conf, kinfo, str, order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004175 OPENSSL_free(str);
William Lallemandfe49bb32019-10-03 23:46:33 +02004176 if (order < 0) {
4177 memprintf(err, "%sunable to create a sni context.\n", err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02004178 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemandd9199372019-10-04 15:37:05 +02004179 goto error;
William Lallemandfe49bb32019-10-03 23:46:33 +02004180 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004181 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004182 }
4183 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004184 sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004185 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004186#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
William Lallemand36b84632019-07-18 19:28:17 +02004187 xname = X509_get_subject_name(ckch->cert);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004188 i = -1;
4189 while ((i = X509_NAME_get_index_by_NID(xname, NID_commonName, i)) != -1) {
4190 X509_NAME_ENTRY *entry = X509_NAME_get_entry(xname, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02004191 ASN1_STRING *value;
4192
4193 value = X509_NAME_ENTRY_get_data(entry);
4194 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
William Lallemand1d29c742019-10-04 00:53:29 +02004195 order = ckch_inst_add_cert_sni(ctx, ckch_inst, bind_conf, ssl_conf, kinfo, str, order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004196 OPENSSL_free(str);
William Lallemandfe49bb32019-10-03 23:46:33 +02004197 if (order < 0) {
4198 memprintf(err, "%sunable to create a sni context.\n", err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02004199 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemandd9199372019-10-04 15:37:05 +02004200 goto error;
William Lallemandfe49bb32019-10-03 23:46:33 +02004201 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004202 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004203 }
4204 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004205 /* we must not free the SSL_CTX anymore below, since it's already in
4206 * the tree, so it will be discovered and cleaned in time.
4207 */
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02004208
Emeric Brunfc0421f2012-09-07 17:30:07 +02004209#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004210 if (bind_conf->default_ctx) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02004211 memprintf(err, "%sthis version of openssl cannot load multiple SSL certificates.\n",
4212 err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02004213 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemandd9199372019-10-04 15:37:05 +02004214 goto error;
Emeric Brunfc0421f2012-09-07 17:30:07 +02004215 }
4216#endif
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004217 if (!bind_conf->default_ctx) {
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004218 bind_conf->default_ctx = ctx;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004219 bind_conf->default_ssl_conf = ssl_conf;
William Lallemand21724f02019-11-04 17:56:13 +01004220 ckch_inst->is_default = 1;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004221 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004222
William Lallemand9117de92019-10-04 00:29:42 +02004223 /* everything succeed, the ckch instance can be used */
4224 ckch_inst->bind_conf = bind_conf;
William Lallemand150bfa82019-09-19 17:12:49 +02004225 ckch_inst->ssl_conf = ssl_conf;
William Lallemand9117de92019-10-04 00:29:42 +02004226
Emeric Brun054563d2019-10-17 13:16:58 +02004227 *ckchi = ckch_inst;
4228 return errcode;
William Lallemandd9199372019-10-04 15:37:05 +02004229
4230error:
4231 /* free the allocated sni_ctxs */
William Lallemand614ca0d2019-10-07 13:52:11 +02004232 if (ckch_inst) {
William Lallemandd9199372019-10-04 15:37:05 +02004233 struct sni_ctx *sc0, *sc0b;
4234
4235 list_for_each_entry_safe(sc0, sc0b, &ckch_inst->sni_ctx, by_ckch_inst) {
4236
4237 ebmb_delete(&sc0->name);
4238 LIST_DEL(&sc0->by_ckch_inst);
4239 free(sc0);
4240 }
William Lallemand614ca0d2019-10-07 13:52:11 +02004241 free(ckch_inst);
4242 ckch_inst = NULL;
William Lallemandd9199372019-10-04 15:37:05 +02004243 }
4244 /* We only created 1 SSL_CTX so we can free it there */
4245 SSL_CTX_free(ctx);
4246
Emeric Brun054563d2019-10-17 13:16:58 +02004247 return errcode;
Emeric Brunfc0421f2012-09-07 17:30:07 +02004248}
4249
Willy Tarreau8c5414a2019-10-16 17:06:25 +02004250/* Returns a set of ERR_* flags possibly with an error in <err>. */
William Lallemand614ca0d2019-10-07 13:52:11 +02004251static int ssl_sock_load_ckchs(const char *path, struct ckch_store *ckchs,
4252 struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
4253 char **sni_filter, int fcount, char **err)
4254{
4255 struct ckch_inst *ckch_inst = NULL;
Emeric Brun054563d2019-10-17 13:16:58 +02004256 int errcode = 0;
William Lallemand614ca0d2019-10-07 13:52:11 +02004257
4258 /* we found the ckchs in the tree, we can use it directly */
4259 if (ckchs->multi)
Emeric Brun054563d2019-10-17 13:16:58 +02004260 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 +02004261 else
Emeric Brun054563d2019-10-17 13:16:58 +02004262 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 +02004263
Emeric Brun054563d2019-10-17 13:16:58 +02004264 if (errcode & ERR_CODE)
4265 return errcode;
William Lallemand614ca0d2019-10-07 13:52:11 +02004266
4267 ssl_sock_load_cert_sni(ckch_inst, bind_conf);
4268
4269 /* succeed, add the instance to the ckch_store's list of instance */
4270 LIST_ADDQ(&ckchs->ckch_inst, &ckch_inst->by_ckchs);
Emeric Brun054563d2019-10-17 13:16:58 +02004271 return errcode;
William Lallemand614ca0d2019-10-07 13:52:11 +02004272}
4273
4274
Willy Tarreaubbc91962019-10-16 16:42:19 +02004275/* Returns a set of ERR_* flags possibly with an error in <err>. */
Willy Tarreau03209342016-12-22 17:08:28 +01004276int ssl_sock_load_cert(char *path, struct bind_conf *bind_conf, char **err)
Emeric Brunfc0421f2012-09-07 17:30:07 +02004277{
Cyril Bonté3180f7b2015-01-25 00:16:08 +01004278 struct dirent **de_list;
4279 int i, n;
Emeric Brunfc0421f2012-09-07 17:30:07 +02004280 struct stat buf;
Willy Tarreauee2663b2012-12-06 11:36:59 +01004281 char *end;
4282 char fp[MAXPATHLEN+1];
Emeric Brunfc0421f2012-09-07 17:30:07 +02004283 int cfgerr = 0;
William Lallemande3af8fb2019-10-08 11:36:53 +02004284 struct ckch_store *ckchs;
Willy Tarreau9a1ab082019-05-09 13:26:41 +02004285#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
yanbzhu63ea8462015-12-09 13:35:14 -05004286 int is_bundle;
4287 int j;
4288#endif
William Lallemande3af8fb2019-10-08 11:36:53 +02004289 if ((ckchs = ckchs_lookup(path))) {
William Lallemande3af8fb2019-10-08 11:36:53 +02004290 /* we found the ckchs in the tree, we can use it directly */
Willy Tarreau8c5414a2019-10-16 17:06:25 +02004291 return ssl_sock_load_ckchs(path, ckchs, bind_conf, NULL, NULL, 0, err);
William Lallemand6af03992019-07-23 15:00:54 +02004292 }
4293
yanbzhu08ce6ab2015-12-02 13:01:29 -05004294 if (stat(path, &buf) == 0) {
William Dauchy9a8ef7f2020-01-13 17:52:49 +01004295 if (S_ISDIR(buf.st_mode) == 0) {
William Lallemande3af8fb2019-10-08 11:36:53 +02004296 ckchs = ckchs_load_cert_file(path, 0, err);
4297 if (!ckchs)
Willy Tarreaubbc91962019-10-16 16:42:19 +02004298 return ERR_ALERT | ERR_FATAL;
4299
Willy Tarreau8c5414a2019-10-16 17:06:25 +02004300 return ssl_sock_load_ckchs(path, ckchs, bind_conf, NULL, NULL, 0, err);
William Lallemand36b84632019-07-18 19:28:17 +02004301 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004302
yanbzhu08ce6ab2015-12-02 13:01:29 -05004303 /* strip trailing slashes, including first one */
4304 for (end = path + strlen(path) - 1; end >= path && *end == '/'; end--)
4305 *end = 0;
Emeric Brunfc0421f2012-09-07 17:30:07 +02004306
yanbzhu08ce6ab2015-12-02 13:01:29 -05004307 n = scandir(path, &de_list, 0, alphasort);
4308 if (n < 0) {
4309 memprintf(err, "%sunable to scan directory '%s' : %s.\n",
4310 err && *err ? *err : "", path, strerror(errno));
Willy Tarreaubbc91962019-10-16 16:42:19 +02004311 cfgerr |= ERR_ALERT | ERR_FATAL;
yanbzhu08ce6ab2015-12-02 13:01:29 -05004312 }
4313 else {
4314 for (i = 0; i < n; i++) {
4315 struct dirent *de = de_list[i];
Emeric Brun2aab7222014-06-18 18:15:09 +02004316
yanbzhu08ce6ab2015-12-02 13:01:29 -05004317 end = strrchr(de->d_name, '.');
4318 if (end && (!strcmp(end, ".issuer") || !strcmp(end, ".ocsp") || !strcmp(end, ".sctl")))
4319 goto ignore_entry;
Cyril Bonté3180f7b2015-01-25 00:16:08 +01004320
yanbzhu08ce6ab2015-12-02 13:01:29 -05004321 snprintf(fp, sizeof(fp), "%s/%s", path, de->d_name);
4322 if (stat(fp, &buf) != 0) {
4323 memprintf(err, "%sunable to stat SSL certificate from file '%s' : %s.\n",
4324 err && *err ? *err : "", fp, strerror(errno));
Willy Tarreaubbc91962019-10-16 16:42:19 +02004325 cfgerr |= ERR_ALERT | ERR_FATAL;
yanbzhu08ce6ab2015-12-02 13:01:29 -05004326 goto ignore_entry;
4327 }
4328 if (!S_ISREG(buf.st_mode))
4329 goto ignore_entry;
yanbzhu63ea8462015-12-09 13:35:14 -05004330
Willy Tarreau9a1ab082019-05-09 13:26:41 +02004331#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
yanbzhu63ea8462015-12-09 13:35:14 -05004332 is_bundle = 0;
4333 /* Check if current entry in directory is part of a multi-cert bundle */
4334
William Lallemand3af48e72020-02-03 17:15:52 +01004335 if ((global_ssl.extra_files & SSL_GF_BUNDLE) && end) {
yanbzhu63ea8462015-12-09 13:35:14 -05004336 for (j = 0; j < SSL_SOCK_NUM_KEYTYPES; j++) {
4337 if (!strcmp(end + 1, SSL_SOCK_KEYTYPE_NAMES[j])) {
4338 is_bundle = 1;
4339 break;
4340 }
4341 }
4342
4343 if (is_bundle) {
yanbzhu63ea8462015-12-09 13:35:14 -05004344 int dp_len;
4345
4346 dp_len = end - de->d_name;
yanbzhu63ea8462015-12-09 13:35:14 -05004347
4348 /* increment i and free de until we get to a non-bundle cert
4349 * Note here that we look at de_list[i + 1] before freeing de
Willy Tarreau05800522019-10-29 10:48:50 +01004350 * this is important since ignore_entry will free de. This also
4351 * guarantees that de->d_name continues to hold the same prefix.
yanbzhu63ea8462015-12-09 13:35:14 -05004352 */
Willy Tarreau05800522019-10-29 10:48:50 +01004353 while (i + 1 < n && !strncmp(de_list[i + 1]->d_name, de->d_name, dp_len)) {
yanbzhu63ea8462015-12-09 13:35:14 -05004354 free(de);
4355 i++;
4356 de = de_list[i];
4357 }
4358
Willy Tarreau05800522019-10-29 10:48:50 +01004359 snprintf(fp, sizeof(fp), "%s/%.*s", path, dp_len, de->d_name);
William Lallemande3af8fb2019-10-08 11:36:53 +02004360 if ((ckchs = ckchs_lookup(fp)) == NULL)
4361 ckchs = ckchs_load_cert_file(fp, 1, err);
4362 if (!ckchs)
Willy Tarreaubbc91962019-10-16 16:42:19 +02004363 cfgerr |= ERR_ALERT | ERR_FATAL;
Willy Tarreau8c5414a2019-10-16 17:06:25 +02004364 else
4365 cfgerr |= ssl_sock_load_ckchs(path, ckchs, bind_conf, NULL, NULL, 0, err);
yanbzhu63ea8462015-12-09 13:35:14 -05004366 /* Successfully processed the bundle */
4367 goto ignore_entry;
4368 }
4369 }
4370
4371#endif
William Lallemande3af8fb2019-10-08 11:36:53 +02004372 if ((ckchs = ckchs_lookup(fp)) == NULL)
4373 ckchs = ckchs_load_cert_file(fp, 0, err);
4374 if (!ckchs)
Willy Tarreaubbc91962019-10-16 16:42:19 +02004375 cfgerr |= ERR_ALERT | ERR_FATAL;
William Lallemand614ca0d2019-10-07 13:52:11 +02004376 else
Willy Tarreau8c5414a2019-10-16 17:06:25 +02004377 cfgerr |= ssl_sock_load_ckchs(path, ckchs, bind_conf, NULL, NULL, 0, err);
William Lallemand36b84632019-07-18 19:28:17 +02004378
yanbzhu08ce6ab2015-12-02 13:01:29 -05004379ignore_entry:
4380 free(de);
Cyril Bonté3180f7b2015-01-25 00:16:08 +01004381 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05004382 free(de_list);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004383 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05004384 return cfgerr;
yanbzhu08ce6ab2015-12-02 13:01:29 -05004385
William Lallemand3af48e72020-02-03 17:15:52 +01004386 } else {
4387 /* stat failed */
Willy Tarreaubbc91962019-10-16 16:42:19 +02004388
William Lallemand3af48e72020-02-03 17:15:52 +01004389 if (global_ssl.extra_files & SSL_GF_BUNDLE) {
4390 /* try to load a bundle if it is permitted */
4391 ckchs = ckchs_load_cert_file(path, 1, err);
4392 if (!ckchs)
4393 return ERR_ALERT | ERR_FATAL;
4394 cfgerr |= ssl_sock_load_ckchs(path, ckchs, bind_conf, NULL, NULL, 0, err);
4395 } else {
4396 memprintf(err, "%sunable to stat SSL certificate from file '%s' : %s.\n",
4397 err && *err ? *err : "", fp, strerror(errno));
4398 cfgerr |= ERR_ALERT | ERR_FATAL;
4399 }
4400 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05004401
Emeric Brunfc0421f2012-09-07 17:30:07 +02004402 return cfgerr;
4403}
4404
Thierry Fournier383085f2013-01-24 14:15:43 +01004405/* Make sure openssl opens /dev/urandom before the chroot. The work is only
4406 * done once. Zero is returned if the operation fails. No error is returned
4407 * if the random is said as not implemented, because we expect that openssl
4408 * will use another method once needed.
4409 */
4410static int ssl_initialize_random()
4411{
4412 unsigned char random;
4413 static int random_initialized = 0;
4414
4415 if (!random_initialized && RAND_bytes(&random, 1) != 0)
4416 random_initialized = 1;
4417
4418 return random_initialized;
4419}
4420
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004421/* release ssl bind conf */
4422void ssl_sock_free_ssl_conf(struct ssl_bind_conf *conf)
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004423{
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004424 if (conf) {
Bernard Spil13c53f82018-02-15 13:34:58 +01004425#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004426 free(conf->npn_str);
4427 conf->npn_str = NULL;
4428#endif
4429#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
4430 free(conf->alpn_str);
4431 conf->alpn_str = NULL;
4432#endif
4433 free(conf->ca_file);
4434 conf->ca_file = NULL;
4435 free(conf->crl_file);
4436 conf->crl_file = NULL;
4437 free(conf->ciphers);
4438 conf->ciphers = NULL;
Emmanuel Hocdet839af572019-05-14 16:27:35 +02004439#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02004440 free(conf->ciphersuites);
4441 conf->ciphersuites = NULL;
4442#endif
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004443 free(conf->curves);
4444 conf->curves = NULL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004445 free(conf->ecdhe);
4446 conf->ecdhe = NULL;
4447 }
4448}
4449
Willy Tarreaubbc91962019-10-16 16:42:19 +02004450/* Returns a set of ERR_* flags possibly with an error in <err>. */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004451int ssl_sock_load_cert_list_file(char *file, struct bind_conf *bind_conf, struct proxy *curproxy, char **err)
4452{
4453 char thisline[CRT_LINESIZE];
4454 char path[MAXPATHLEN+1];
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004455 FILE *f;
yanbzhu1b04e5b2015-12-02 13:54:14 -05004456 struct stat buf;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004457 int linenum = 0;
4458 int cfgerr = 0;
William Lallemande3af8fb2019-10-08 11:36:53 +02004459 struct ckch_store *ckchs;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004460
Willy Tarreauad1731d2013-04-02 17:35:58 +02004461 if ((f = fopen(file, "r")) == NULL) {
4462 memprintf(err, "cannot open file '%s' : %s", file, strerror(errno));
Willy Tarreaubbc91962019-10-16 16:42:19 +02004463 return ERR_ALERT | ERR_FATAL;
Willy Tarreauad1731d2013-04-02 17:35:58 +02004464 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004465
4466 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004467 int arg, newarg, cur_arg, i, ssl_b = 0, ssl_e = 0;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004468 char *end;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004469 char *args[MAX_CRT_ARGS + 1];
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004470 char *line = thisline;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004471 char *crt_path;
4472 struct ssl_bind_conf *ssl_conf = NULL;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004473
4474 linenum++;
4475 end = line + strlen(line);
4476 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
4477 /* Check if we reached the limit and the last char is not \n.
4478 * Watch out for the last line without the terminating '\n'!
4479 */
Willy Tarreauad1731d2013-04-02 17:35:58 +02004480 memprintf(err, "line %d too long in file '%s', limit is %d characters",
4481 linenum, file, (int)sizeof(thisline)-1);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004482 cfgerr |= ERR_ALERT | ERR_FATAL;
Willy Tarreauad1731d2013-04-02 17:35:58 +02004483 break;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004484 }
4485
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004486 arg = 0;
Emeric Brun50bcecc2013-04-22 13:05:23 +02004487 newarg = 1;
4488 while (*line) {
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004489 if (*line == '#' || *line == '\n' || *line == '\r') {
4490 /* end of string, end of loop */
4491 *line = 0;
4492 break;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004493 } else if (isspace(*line)) {
Emeric Brun50bcecc2013-04-22 13:05:23 +02004494 newarg = 1;
4495 *line = 0;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004496 } else if (*line == '[') {
4497 if (ssl_b) {
4498 memprintf(err, "too many '[' on line %d in file '%s'.", linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004499 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004500 break;
4501 }
4502 if (!arg) {
4503 memprintf(err, "file must start with a cert on line %d in file '%s'", linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004504 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004505 break;
4506 }
4507 ssl_b = arg;
4508 newarg = 1;
4509 *line = 0;
4510 } else if (*line == ']') {
4511 if (ssl_e) {
4512 memprintf(err, "too many ']' on line %d in file '%s'.", linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004513 cfgerr |= ERR_ALERT | ERR_FATAL;
Emeric Brun50bcecc2013-04-22 13:05:23 +02004514 break;
4515 }
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004516 if (!ssl_b) {
4517 memprintf(err, "missing '[' in line %d in file '%s'.", linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004518 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004519 break;
4520 }
4521 ssl_e = arg;
4522 newarg = 1;
4523 *line = 0;
4524 } else if (newarg) {
4525 if (arg == MAX_CRT_ARGS) {
4526 memprintf(err, "too many args on line %d in file '%s'.", linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004527 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004528 break;
4529 }
Emeric Brun50bcecc2013-04-22 13:05:23 +02004530 newarg = 0;
4531 args[arg++] = line;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004532 }
Emeric Brun50bcecc2013-04-22 13:05:23 +02004533 line++;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004534 }
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02004535 if (cfgerr)
4536 break;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004537 args[arg++] = line;
Willy Tarreauad1731d2013-04-02 17:35:58 +02004538
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004539 /* empty line */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004540 if (!*args[0])
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004541 continue;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004542
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004543 crt_path = args[0];
4544 if (*crt_path != '/' && global_ssl.crt_base) {
4545 if ((strlen(global_ssl.crt_base) + 1 + strlen(crt_path)) > MAXPATHLEN) {
4546 memprintf(err, "'%s' : path too long on line %d in file '%s'",
4547 crt_path, linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004548 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004549 break;
4550 }
4551 snprintf(path, sizeof(path), "%s/%s", global_ssl.crt_base, crt_path);
4552 crt_path = path;
4553 }
4554
4555 ssl_conf = calloc(1, sizeof *ssl_conf);
4556 cur_arg = ssl_b ? ssl_b : 1;
4557 while (cur_arg < ssl_e) {
4558 newarg = 0;
4559 for (i = 0; ssl_bind_kws[i].kw != NULL; i++) {
4560 if (strcmp(ssl_bind_kws[i].kw, args[cur_arg]) == 0) {
4561 newarg = 1;
Willy Tarreaubbc91962019-10-16 16:42:19 +02004562 cfgerr |= ssl_bind_kws[i].parse(args, cur_arg, curproxy, ssl_conf, err);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004563 if (cur_arg + 1 + ssl_bind_kws[i].skip > ssl_e) {
4564 memprintf(err, "ssl args out of '[]' for %s on line %d in file '%s'",
4565 args[cur_arg], linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004566 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004567 }
4568 cur_arg += 1 + ssl_bind_kws[i].skip;
4569 break;
4570 }
4571 }
4572 if (!cfgerr && !newarg) {
4573 memprintf(err, "unknown ssl keyword %s on line %d in file '%s'.",
4574 args[cur_arg], linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004575 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004576 break;
4577 }
4578 }
Willy Tarreaubbc91962019-10-16 16:42:19 +02004579
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004580 if (cfgerr) {
4581 ssl_sock_free_ssl_conf(ssl_conf);
4582 free(ssl_conf);
4583 ssl_conf = NULL;
4584 break;
4585 }
4586
William Lallemande3af8fb2019-10-08 11:36:53 +02004587 if ((ckchs = ckchs_lookup(crt_path)) == NULL) {
William Lallemandeed4bf22019-10-10 11:38:13 +02004588 if (stat(crt_path, &buf) == 0)
William Lallemande3af8fb2019-10-08 11:36:53 +02004589 ckchs = ckchs_load_cert_file(crt_path, 0, err);
Emmanuel Hocdet1503e052019-07-31 18:30:33 +02004590 else
William Lallemande3af8fb2019-10-08 11:36:53 +02004591 ckchs = ckchs_load_cert_file(crt_path, 1, err);
yanbzhu1b04e5b2015-12-02 13:54:14 -05004592 }
4593
Willy Tarreau8c5414a2019-10-16 17:06:25 +02004594 if (!ckchs)
Willy Tarreaubbc91962019-10-16 16:42:19 +02004595 cfgerr |= ERR_ALERT | ERR_FATAL;
Willy Tarreau8c5414a2019-10-16 17:06:25 +02004596 else
4597 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 +02004598
Willy Tarreauad1731d2013-04-02 17:35:58 +02004599 if (cfgerr) {
4600 memprintf(err, "error processing line %d in file '%s' : %s", linenum, file, *err);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004601 break;
Willy Tarreauad1731d2013-04-02 17:35:58 +02004602 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004603 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004604 fclose(f);
4605 return cfgerr;
4606}
4607
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004608/* Create an initial CTX used to start the SSL connection before switchctx */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004609static int
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004610ssl_sock_initial_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02004611{
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004612 SSL_CTX *ctx = NULL;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004613 long options =
Emeric Brunfc0421f2012-09-07 17:30:07 +02004614 SSL_OP_ALL | /* all known workarounds for bugs */
4615 SSL_OP_NO_SSLv2 |
4616 SSL_OP_NO_COMPRESSION |
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02004617 SSL_OP_SINGLE_DH_USE |
Emeric Brun2b58d042012-09-20 17:10:03 +02004618 SSL_OP_SINGLE_ECDH_USE |
Emeric Brun3c4bc6e2012-10-04 18:44:19 +02004619 SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION |
Lukas Tribus926594f2018-05-18 17:55:57 +02004620 SSL_OP_PRIORITIZE_CHACHA |
Emeric Brun3c4bc6e2012-10-04 18:44:19 +02004621 SSL_OP_CIPHER_SERVER_PREFERENCE;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004622 long mode =
Emeric Brunfc0421f2012-09-07 17:30:07 +02004623 SSL_MODE_ENABLE_PARTIAL_WRITE |
4624 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
Willy Tarreau396a1862014-11-13 14:06:52 +01004625 SSL_MODE_RELEASE_BUFFERS |
4626 SSL_MODE_SMALL_BUFFERS;
Emmanuel Hocdet43664762017-08-09 18:26:20 +02004627 struct tls_version_filter *conf_ssl_methods = &bind_conf->ssl_conf.ssl_methods;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004628 int i, min, max, hole;
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004629 int flags = MC_SSL_O_ALL;
4630 int cfgerr = 0;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004631
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004632 ctx = SSL_CTX_new(SSLv23_server_method());
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004633 bind_conf->initial_ctx = ctx;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004634
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004635 if (conf_ssl_methods->flags && (conf_ssl_methods->min || conf_ssl_methods->max))
Christopher Faulet767a84b2017-11-24 16:50:31 +01004636 ha_warning("Proxy '%s': no-sslv3/no-tlsv1x are ignored for bind '%s' at [%s:%d]. "
4637 "Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
4638 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004639 else
4640 flags = conf_ssl_methods->flags;
4641
Emmanuel Hocdetbd695fe2017-05-15 15:53:41 +02004642 min = conf_ssl_methods->min;
4643 max = conf_ssl_methods->max;
4644 /* start with TLSv10 to remove SSLv3 per default */
4645 if (!min && (!max || max >= CONF_TLSV10))
4646 min = CONF_TLSV10;
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004647 /* Real min and max should be determinate with configuration and openssl's capabilities */
Emmanuel Hocdetbd695fe2017-05-15 15:53:41 +02004648 if (min)
4649 flags |= (methodVersions[min].flag - 1);
4650 if (max)
4651 flags |= ~((methodVersions[max].flag << 1) - 1);
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004652 /* find min, max and holes */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004653 min = max = CONF_TLSV_NONE;
4654 hole = 0;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004655 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004656 /* version is in openssl && version not disable in configuration */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004657 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004658 if (min) {
4659 if (hole) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004660 ha_warning("Proxy '%s': SSL/TLS versions range not contiguous for bind '%s' at [%s:%d]. "
4661 "Hole find for %s. Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
4662 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line,
4663 methodVersions[hole].name);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004664 hole = 0;
4665 }
4666 max = i;
4667 }
4668 else {
4669 min = max = i;
4670 }
4671 }
4672 else {
4673 if (min)
4674 hole = i;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004675 }
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004676 if (!min) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004677 ha_alert("Proxy '%s': all SSL/TLS versions are disabled for bind '%s' at [%s:%d].\n",
4678 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004679 cfgerr += 1;
4680 }
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02004681 /* save real min/max in bind_conf */
4682 conf_ssl_methods->min = min;
4683 conf_ssl_methods->max = max;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004684
Willy Tarreau9a1ab082019-05-09 13:26:41 +02004685#if (HA_OPENSSL_VERSION_NUMBER < 0x1010000fL)
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004686 /* Keep force-xxx implementation as it is in older haproxy. It's a
Joseph Herlant017b3da2018-11-15 09:07:59 -08004687 precautionary measure to avoid any surprise with older openssl version. */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004688 if (min == max)
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004689 methodVersions[min].ctx_set_version(ctx, SET_SERVER);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004690 else
4691 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
4692 if (flags & methodVersions[i].flag)
4693 options |= methodVersions[i].option;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004694#else /* openssl >= 1.1.0 */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004695 /* set the max_version is required to cap TLS version or activate new TLS (v1.3) */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004696 methodVersions[min].ctx_set_version(ctx, SET_MIN);
4697 methodVersions[max].ctx_set_version(ctx, SET_MAX);
Emeric Brunfa5c5c82017-04-28 16:19:51 +02004698#endif
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004699
4700 if (bind_conf->ssl_options & BC_SSL_O_NO_TLS_TICKETS)
4701 options |= SSL_OP_NO_TICKET;
4702 if (bind_conf->ssl_options & BC_SSL_O_PREF_CLIE_CIPH)
4703 options &= ~SSL_OP_CIPHER_SERVER_PREFERENCE;
Dirkjan Bussink526894f2019-01-21 09:35:03 -08004704
4705#ifdef SSL_OP_NO_RENEGOTIATION
4706 options |= SSL_OP_NO_RENEGOTIATION;
4707#endif
4708
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004709 SSL_CTX_set_options(ctx, options);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004710
Willy Tarreau5db847a2019-05-09 14:13:35 +02004711#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004712 if (global_ssl.async)
4713 mode |= SSL_MODE_ASYNC;
4714#endif
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004715 SSL_CTX_set_mode(ctx, mode);
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004716 if (global_ssl.life_time)
4717 SSL_CTX_set_timeout(ctx, global_ssl.life_time);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004718
4719#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
4720#ifdef OPENSSL_IS_BORINGSSL
4721 SSL_CTX_set_select_certificate_cb(ctx, ssl_sock_switchctx_cbk);
4722 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_err_cbk);
Ilya Shipitsine9ff8992020-01-19 12:20:14 +05004723#elif defined(SSL_OP_NO_ANTI_REPLAY)
Olivier Houchard545989f2019-12-17 15:39:54 +01004724 if (bind_conf->ssl_conf.early_data)
Olivier Houchard51088ce2019-01-02 18:46:41 +01004725 SSL_CTX_set_options(ctx, SSL_OP_NO_ANTI_REPLAY);
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02004726 SSL_CTX_set_client_hello_cb(ctx, ssl_sock_switchctx_cbk, NULL);
4727 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_err_cbk);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004728#else
4729 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_cbk);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004730#endif
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02004731 SSL_CTX_set_tlsext_servername_arg(ctx, bind_conf);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004732#endif
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004733 return cfgerr;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004734}
4735
William Lallemand4f45bb92017-10-30 20:08:51 +01004736
4737static inline void sh_ssl_sess_free_blocks(struct shared_block *first, struct shared_block *block)
4738{
4739 if (first == block) {
4740 struct sh_ssl_sess_hdr *sh_ssl_sess = (struct sh_ssl_sess_hdr *)first->data;
4741 if (first->len > 0)
4742 sh_ssl_sess_tree_delete(sh_ssl_sess);
4743 }
4744}
4745
4746/* return first block from sh_ssl_sess */
4747static inline struct shared_block *sh_ssl_sess_first_block(struct sh_ssl_sess_hdr *sh_ssl_sess)
4748{
4749 return (struct shared_block *)((unsigned char *)sh_ssl_sess - ((struct shared_block *)NULL)->data);
4750
4751}
4752
4753/* store a session into the cache
4754 * s_id : session id padded with zero to SSL_MAX_SSL_SESSION_ID_LENGTH
4755 * data: asn1 encoded session
4756 * data_len: asn1 encoded session length
4757 * Returns 1 id session was stored (else 0)
4758 */
4759static int sh_ssl_sess_store(unsigned char *s_id, unsigned char *data, int data_len)
4760{
4761 struct shared_block *first;
4762 struct sh_ssl_sess_hdr *sh_ssl_sess, *oldsh_ssl_sess;
4763
Frédéric Lécaille0bec8072018-10-22 17:55:57 +02004764 first = shctx_row_reserve_hot(ssl_shctx, NULL, data_len + sizeof(struct sh_ssl_sess_hdr));
William Lallemand4f45bb92017-10-30 20:08:51 +01004765 if (!first) {
4766 /* Could not retrieve enough free blocks to store that session */
4767 return 0;
4768 }
4769
4770 /* STORE the key in the first elem */
4771 sh_ssl_sess = (struct sh_ssl_sess_hdr *)first->data;
4772 memcpy(sh_ssl_sess->key_data, s_id, SSL_MAX_SSL_SESSION_ID_LENGTH);
4773 first->len = sizeof(struct sh_ssl_sess_hdr);
4774
4775 /* it returns the already existing node
4776 or current node if none, never returns null */
4777 oldsh_ssl_sess = sh_ssl_sess_tree_insert(sh_ssl_sess);
4778 if (oldsh_ssl_sess != sh_ssl_sess) {
4779 /* NOTE: Row couldn't be in use because we lock read & write function */
4780 /* release the reserved row */
4781 shctx_row_dec_hot(ssl_shctx, first);
4782 /* replace the previous session already in the tree */
4783 sh_ssl_sess = oldsh_ssl_sess;
4784 /* ignore the previous session data, only use the header */
4785 first = sh_ssl_sess_first_block(sh_ssl_sess);
4786 shctx_row_inc_hot(ssl_shctx, first);
4787 first->len = sizeof(struct sh_ssl_sess_hdr);
4788 }
4789
Frédéric Lécaille0bec8072018-10-22 17:55:57 +02004790 if (shctx_row_data_append(ssl_shctx, first, NULL, data, data_len) < 0) {
William Lallemand99b90af2018-01-03 19:15:51 +01004791 shctx_row_dec_hot(ssl_shctx, first);
William Lallemand4f45bb92017-10-30 20:08:51 +01004792 return 0;
William Lallemand99b90af2018-01-03 19:15:51 +01004793 }
4794
4795 shctx_row_dec_hot(ssl_shctx, first);
William Lallemand4f45bb92017-10-30 20:08:51 +01004796
4797 return 1;
4798}
William Lallemanded0b5ad2017-10-30 19:36:36 +01004799
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004800/* SSL callback used when a new session is created while connecting to a server */
4801static int ssl_sess_new_srv_cb(SSL *ssl, SSL_SESSION *sess)
4802{
Thierry FOURNIER28962c92018-06-17 21:37:05 +02004803 struct connection *conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Olivier Houcharde6060c52017-11-16 17:42:52 +01004804 struct server *s;
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004805
Willy Tarreau07d94e42018-09-20 10:57:52 +02004806 s = __objt_server(conn->target);
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004807
Olivier Houcharde6060c52017-11-16 17:42:52 +01004808 if (!(s->ssl_ctx.options & SRV_SSL_O_NO_REUSE)) {
4809 int len;
4810 unsigned char *ptr;
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004811
Olivier Houcharde6060c52017-11-16 17:42:52 +01004812 len = i2d_SSL_SESSION(sess, NULL);
4813 if (s->ssl_ctx.reused_sess[tid].ptr && s->ssl_ctx.reused_sess[tid].allocated_size >= len) {
4814 ptr = s->ssl_ctx.reused_sess[tid].ptr;
4815 } else {
4816 free(s->ssl_ctx.reused_sess[tid].ptr);
4817 ptr = s->ssl_ctx.reused_sess[tid].ptr = malloc(len);
4818 s->ssl_ctx.reused_sess[tid].allocated_size = len;
4819 }
4820 if (s->ssl_ctx.reused_sess[tid].ptr) {
4821 s->ssl_ctx.reused_sess[tid].size = i2d_SSL_SESSION(sess,
4822 &ptr);
4823 }
4824 } else {
4825 free(s->ssl_ctx.reused_sess[tid].ptr);
4826 s->ssl_ctx.reused_sess[tid].ptr = NULL;
4827 }
4828
4829 return 0;
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004830}
4831
Olivier Houcharde6060c52017-11-16 17:42:52 +01004832
William Lallemanded0b5ad2017-10-30 19:36:36 +01004833/* SSL callback used on new session creation */
William Lallemand4f45bb92017-10-30 20:08:51 +01004834int sh_ssl_sess_new_cb(SSL *ssl, SSL_SESSION *sess)
William Lallemanded0b5ad2017-10-30 19:36:36 +01004835{
4836 unsigned char encsess[SHSESS_MAX_DATA_LEN]; /* encoded session */
4837 unsigned char encid[SSL_MAX_SSL_SESSION_ID_LENGTH]; /* encoded id */
4838 unsigned char *p;
4839 int data_len;
Emeric Bruneb469652019-10-08 18:27:37 +02004840 unsigned int sid_length;
William Lallemanded0b5ad2017-10-30 19:36:36 +01004841 const unsigned char *sid_data;
William Lallemanded0b5ad2017-10-30 19:36:36 +01004842
4843 /* Session id is already stored in to key and session id is known
4844 * so we dont store it to keep size.
Emeric Bruneb469652019-10-08 18:27:37 +02004845 * note: SSL_SESSION_set1_id is using
4846 * a memcpy so we need to use a different pointer
4847 * than sid_data or sid_ctx_data to avoid valgrind
4848 * complaining.
William Lallemanded0b5ad2017-10-30 19:36:36 +01004849 */
4850
4851 sid_data = SSL_SESSION_get_id(sess, &sid_length);
Emeric Bruneb469652019-10-08 18:27:37 +02004852
4853 /* copy value in an other buffer */
4854 memcpy(encid, sid_data, sid_length);
4855
4856 /* pad with 0 */
4857 if (sid_length < SSL_MAX_SSL_SESSION_ID_LENGTH)
4858 memset(encid + sid_length, 0, SSL_MAX_SSL_SESSION_ID_LENGTH-sid_length);
4859
4860 /* force length to zero to avoid ASN1 encoding */
4861 SSL_SESSION_set1_id(sess, encid, 0);
4862
4863 /* force length to zero to avoid ASN1 encoding */
4864 SSL_SESSION_set1_id_context(sess, (const unsigned char *)SHCTX_APPNAME, 0);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004865
4866 /* check if buffer is large enough for the ASN1 encoded session */
4867 data_len = i2d_SSL_SESSION(sess, NULL);
4868 if (data_len > SHSESS_MAX_DATA_LEN)
4869 goto err;
4870
4871 p = encsess;
4872
4873 /* process ASN1 session encoding before the lock */
4874 i2d_SSL_SESSION(sess, &p);
4875
William Lallemanded0b5ad2017-10-30 19:36:36 +01004876
William Lallemanda3c77cf2017-10-30 23:44:40 +01004877 shctx_lock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004878 /* store to cache */
William Lallemand4f45bb92017-10-30 20:08:51 +01004879 sh_ssl_sess_store(encid, encsess, data_len);
William Lallemanda3c77cf2017-10-30 23:44:40 +01004880 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004881err:
4882 /* reset original length values */
Emeric Bruneb469652019-10-08 18:27:37 +02004883 SSL_SESSION_set1_id(sess, encid, sid_length);
4884 SSL_SESSION_set1_id_context(sess, (const unsigned char *)SHCTX_APPNAME, strlen(SHCTX_APPNAME));
William Lallemanded0b5ad2017-10-30 19:36:36 +01004885
4886 return 0; /* do not increment session reference count */
4887}
4888
4889/* SSL callback used on lookup an existing session cause none found in internal cache */
William Lallemand4f45bb92017-10-30 20:08:51 +01004890SSL_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 +01004891{
William Lallemand4f45bb92017-10-30 20:08:51 +01004892 struct sh_ssl_sess_hdr *sh_ssl_sess;
William Lallemanded0b5ad2017-10-30 19:36:36 +01004893 unsigned char data[SHSESS_MAX_DATA_LEN], *p;
4894 unsigned char tmpkey[SSL_MAX_SSL_SESSION_ID_LENGTH];
William Lallemanded0b5ad2017-10-30 19:36:36 +01004895 SSL_SESSION *sess;
William Lallemand4f45bb92017-10-30 20:08:51 +01004896 struct shared_block *first;
William Lallemanded0b5ad2017-10-30 19:36:36 +01004897
4898 global.shctx_lookups++;
4899
4900 /* allow the session to be freed automatically by openssl */
4901 *do_copy = 0;
4902
4903 /* tree key is zeros padded sessionid */
4904 if (key_len < SSL_MAX_SSL_SESSION_ID_LENGTH) {
4905 memcpy(tmpkey, key, key_len);
4906 memset(tmpkey + key_len, 0, SSL_MAX_SSL_SESSION_ID_LENGTH - key_len);
4907 key = tmpkey;
4908 }
4909
4910 /* lock cache */
William Lallemanda3c77cf2017-10-30 23:44:40 +01004911 shctx_lock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004912
4913 /* lookup for session */
William Lallemand4f45bb92017-10-30 20:08:51 +01004914 sh_ssl_sess = sh_ssl_sess_tree_lookup(key);
4915 if (!sh_ssl_sess) {
William Lallemanded0b5ad2017-10-30 19:36:36 +01004916 /* no session found: unlock cache and exit */
William Lallemanda3c77cf2017-10-30 23:44:40 +01004917 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004918 global.shctx_misses++;
4919 return NULL;
4920 }
4921
William Lallemand4f45bb92017-10-30 20:08:51 +01004922 /* sh_ssl_sess (shared_block->data) is at the end of shared_block */
4923 first = sh_ssl_sess_first_block(sh_ssl_sess);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004924
William Lallemand4f45bb92017-10-30 20:08:51 +01004925 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 +01004926
William Lallemanda3c77cf2017-10-30 23:44:40 +01004927 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004928
4929 /* decode ASN1 session */
4930 p = data;
William Lallemand4f45bb92017-10-30 20:08:51 +01004931 sess = d2i_SSL_SESSION(NULL, (const unsigned char **)&p, first->len-sizeof(struct sh_ssl_sess_hdr));
William Lallemanded0b5ad2017-10-30 19:36:36 +01004932 /* Reset session id and session id contenxt */
4933 if (sess) {
4934 SSL_SESSION_set1_id(sess, key, key_len);
4935 SSL_SESSION_set1_id_context(sess, (const unsigned char *)SHCTX_APPNAME, strlen(SHCTX_APPNAME));
4936 }
4937
4938 return sess;
4939}
4940
William Lallemand4f45bb92017-10-30 20:08:51 +01004941
William Lallemanded0b5ad2017-10-30 19:36:36 +01004942/* SSL callback used to signal session is no more used in internal cache */
William Lallemand4f45bb92017-10-30 20:08:51 +01004943void sh_ssl_sess_remove_cb(SSL_CTX *ctx, SSL_SESSION *sess)
William Lallemanded0b5ad2017-10-30 19:36:36 +01004944{
William Lallemand4f45bb92017-10-30 20:08:51 +01004945 struct sh_ssl_sess_hdr *sh_ssl_sess;
William Lallemanded0b5ad2017-10-30 19:36:36 +01004946 unsigned char tmpkey[SSL_MAX_SSL_SESSION_ID_LENGTH];
4947 unsigned int sid_length;
4948 const unsigned char *sid_data;
4949 (void)ctx;
4950
4951 sid_data = SSL_SESSION_get_id(sess, &sid_length);
4952 /* tree key is zeros padded sessionid */
4953 if (sid_length < SSL_MAX_SSL_SESSION_ID_LENGTH) {
4954 memcpy(tmpkey, sid_data, sid_length);
4955 memset(tmpkey+sid_length, 0, SSL_MAX_SSL_SESSION_ID_LENGTH - sid_length);
4956 sid_data = tmpkey;
4957 }
4958
William Lallemanda3c77cf2017-10-30 23:44:40 +01004959 shctx_lock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004960
4961 /* lookup for session */
William Lallemand4f45bb92017-10-30 20:08:51 +01004962 sh_ssl_sess = sh_ssl_sess_tree_lookup(sid_data);
4963 if (sh_ssl_sess) {
William Lallemanded0b5ad2017-10-30 19:36:36 +01004964 /* free session */
William Lallemand4f45bb92017-10-30 20:08:51 +01004965 sh_ssl_sess_tree_delete(sh_ssl_sess);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004966 }
4967
4968 /* unlock cache */
William Lallemanda3c77cf2017-10-30 23:44:40 +01004969 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004970}
4971
4972/* Set session cache mode to server and disable openssl internal cache.
4973 * Set shared cache callbacks on an ssl context.
4974 * Shared context MUST be firstly initialized */
William Lallemand4f45bb92017-10-30 20:08:51 +01004975void ssl_set_shctx(SSL_CTX *ctx)
William Lallemanded0b5ad2017-10-30 19:36:36 +01004976{
4977 SSL_CTX_set_session_id_context(ctx, (const unsigned char *)SHCTX_APPNAME, strlen(SHCTX_APPNAME));
4978
4979 if (!ssl_shctx) {
4980 SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF);
4981 return;
4982 }
4983
4984 SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_SERVER |
4985 SSL_SESS_CACHE_NO_INTERNAL |
4986 SSL_SESS_CACHE_NO_AUTO_CLEAR);
4987
4988 /* Set callbacks */
William Lallemand4f45bb92017-10-30 20:08:51 +01004989 SSL_CTX_sess_set_new_cb(ctx, sh_ssl_sess_new_cb);
4990 SSL_CTX_sess_set_get_cb(ctx, sh_ssl_sess_get_cb);
4991 SSL_CTX_sess_set_remove_cb(ctx, sh_ssl_sess_remove_cb);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004992}
4993
William Lallemand8b453912019-11-21 15:48:10 +01004994/*
4995 * This function applies the SSL configuration on a SSL_CTX
4996 * It returns an error code and fills the <err> buffer
4997 */
4998int 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 +01004999{
5000 struct proxy *curproxy = bind_conf->frontend;
5001 int cfgerr = 0;
5002 int verify = SSL_VERIFY_NONE;
Willy Tarreau5d4cafb2018-01-04 18:55:19 +01005003 struct ssl_bind_conf __maybe_unused *ssl_conf_cur;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005004 const char *conf_ciphers;
Emmanuel Hocdet839af572019-05-14 16:27:35 +02005005#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02005006 const char *conf_ciphersuites;
5007#endif
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01005008 const char *conf_curves = NULL;
Emeric Brunfc0421f2012-09-07 17:30:07 +02005009
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02005010 if (ssl_conf) {
5011 struct tls_version_filter *conf_ssl_methods = &ssl_conf->ssl_methods;
5012 int i, min, max;
5013 int flags = MC_SSL_O_ALL;
5014
5015 /* Real min and max should be determinate with configuration and openssl's capabilities */
Emmanuel Hocdet43664762017-08-09 18:26:20 +02005016 min = conf_ssl_methods->min ? conf_ssl_methods->min : bind_conf->ssl_conf.ssl_methods.min;
5017 max = conf_ssl_methods->max ? conf_ssl_methods->max : bind_conf->ssl_conf.ssl_methods.max;
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02005018 if (min)
5019 flags |= (methodVersions[min].flag - 1);
5020 if (max)
5021 flags |= ~((methodVersions[max].flag << 1) - 1);
5022 min = max = CONF_TLSV_NONE;
5023 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
5024 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
5025 if (min)
5026 max = i;
5027 else
5028 min = max = i;
5029 }
5030 /* save real min/max */
5031 conf_ssl_methods->min = min;
5032 conf_ssl_methods->max = max;
5033 if (!min) {
Tim Duesterhus93128532019-11-23 23:45:10 +01005034 memprintf(err, "%sProxy '%s': all SSL/TLS versions are disabled for bind '%s' at [%s:%d].\n",
5035 err && *err ? *err : "", bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
William Lallemand8b453912019-11-21 15:48:10 +01005036 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02005037 }
5038 }
5039
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005040 switch ((ssl_conf && ssl_conf->verify) ? ssl_conf->verify : bind_conf->ssl_conf.verify) {
Emeric Brun850efd52014-01-29 12:24:34 +01005041 case SSL_SOCK_VERIFY_NONE:
5042 verify = SSL_VERIFY_NONE;
5043 break;
5044 case SSL_SOCK_VERIFY_OPTIONAL:
5045 verify = SSL_VERIFY_PEER;
5046 break;
5047 case SSL_SOCK_VERIFY_REQUIRED:
5048 verify = SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
5049 break;
5050 }
5051 SSL_CTX_set_verify(ctx, verify, ssl_sock_bind_verifycbk);
5052 if (verify & SSL_VERIFY_PEER) {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005053 char *ca_file = (ssl_conf && ssl_conf->ca_file) ? ssl_conf->ca_file : bind_conf->ssl_conf.ca_file;
5054 char *crl_file = (ssl_conf && ssl_conf->crl_file) ? ssl_conf->crl_file : bind_conf->ssl_conf.crl_file;
5055 if (ca_file) {
Emmanuel Hocdetd4f9a602019-10-24 11:32:47 +02005056 /* set CAfile to verify */
5057 if (!ssl_set_verify_locations_file(ctx, ca_file)) {
5058 memprintf(err, "%sProxy '%s': unable to set CA file '%s' for bind '%s' at [%s:%d].\n",
Tim Duesterhus93128532019-11-23 23:45:10 +01005059 err && *err ? *err : "", curproxy->id, ca_file, bind_conf->arg, bind_conf->file, bind_conf->line);
William Lallemand8b453912019-11-21 15:48:10 +01005060 cfgerr |= ERR_ALERT | ERR_FATAL;
Emeric Brund94b3fe2012-09-20 18:23:56 +02005061 }
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02005062 if (!((ssl_conf && ssl_conf->no_ca_names) || bind_conf->ssl_conf.no_ca_names)) {
5063 /* set CA names for client cert request, function returns void */
Emmanuel Hocdet129d3282019-10-24 18:08:51 +02005064 SSL_CTX_set_client_CA_list(ctx, SSL_dup_CA_list(ssl_get_client_ca_file(ca_file)));
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02005065 }
Emeric Brund94b3fe2012-09-20 18:23:56 +02005066 }
Emeric Brun850efd52014-01-29 12:24:34 +01005067 else {
Tim Duesterhus93128532019-11-23 23:45:10 +01005068 memprintf(err, "%sProxy '%s': verify is enabled but no CA file specified for bind '%s' at [%s:%d].\n",
5069 err && *err ? *err : "", curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
William Lallemand8b453912019-11-21 15:48:10 +01005070 cfgerr |= ERR_ALERT | ERR_FATAL;
Emeric Brun850efd52014-01-29 12:24:34 +01005071 }
Emeric Brun051cdab2012-10-02 19:25:50 +02005072#ifdef X509_V_FLAG_CRL_CHECK
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005073 if (crl_file) {
Emeric Brund94b3fe2012-09-20 18:23:56 +02005074 X509_STORE *store = SSL_CTX_get_cert_store(ctx);
5075
Emmanuel Hocdetb270e812019-11-21 19:09:31 +01005076 if (!ssl_set_cert_crl_file(store, crl_file)) {
Tim Duesterhus93128532019-11-23 23:45:10 +01005077 memprintf(err, "%sProxy '%s': unable to configure CRL file '%s' for bind '%s' at [%s:%d].\n",
5078 err && *err ? *err : "", curproxy->id, crl_file, bind_conf->arg, bind_conf->file, bind_conf->line);
William Lallemand8b453912019-11-21 15:48:10 +01005079 cfgerr |= ERR_ALERT | ERR_FATAL;
Emeric Brund94b3fe2012-09-20 18:23:56 +02005080 }
Emeric Brun561e5742012-10-02 15:20:55 +02005081 else {
5082 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
5083 }
Emeric Brund94b3fe2012-09-20 18:23:56 +02005084 }
Emeric Brun051cdab2012-10-02 19:25:50 +02005085#endif
Emeric Brun644cde02012-12-14 11:21:13 +01005086 ERR_clear_error();
Emeric Brund94b3fe2012-09-20 18:23:56 +02005087 }
Nenad Merdanovic05552d42015-02-27 19:56:49 +01005088#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
Nenad Merdanovic146defa2015-05-09 08:46:00 +02005089 if(bind_conf->keys_ref) {
Nenad Merdanovic05552d42015-02-27 19:56:49 +01005090 if (!SSL_CTX_set_tlsext_ticket_key_cb(ctx, ssl_tlsext_ticket_key_cb)) {
Tim Duesterhus93128532019-11-23 23:45:10 +01005091 memprintf(err, "%sProxy '%s': unable to set callback for TLS ticket validation for bind '%s' at [%s:%d].\n",
5092 err && *err ? *err : "", curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
William Lallemand8b453912019-11-21 15:48:10 +01005093 cfgerr |= ERR_ALERT | ERR_FATAL;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01005094 }
5095 }
5096#endif
5097
William Lallemand4f45bb92017-10-30 20:08:51 +01005098 ssl_set_shctx(ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005099 conf_ciphers = (ssl_conf && ssl_conf->ciphers) ? ssl_conf->ciphers : bind_conf->ssl_conf.ciphers;
5100 if (conf_ciphers &&
5101 !SSL_CTX_set_cipher_list(ctx, conf_ciphers)) {
Tim Duesterhus93128532019-11-23 23:45:10 +01005102 memprintf(err, "%sProxy '%s': unable to set SSL cipher list to '%s' for bind '%s' at [%s:%d].\n",
5103 err && *err ? *err : "", curproxy->id, conf_ciphers, bind_conf->arg, bind_conf->file, bind_conf->line);
William Lallemand8b453912019-11-21 15:48:10 +01005104 cfgerr |= ERR_ALERT | ERR_FATAL;
Emeric Brunfc0421f2012-09-07 17:30:07 +02005105 }
5106
Emmanuel Hocdet839af572019-05-14 16:27:35 +02005107#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02005108 conf_ciphersuites = (ssl_conf && ssl_conf->ciphersuites) ? ssl_conf->ciphersuites : bind_conf->ssl_conf.ciphersuites;
5109 if (conf_ciphersuites &&
5110 !SSL_CTX_set_ciphersuites(ctx, conf_ciphersuites)) {
Tim Duesterhus93128532019-11-23 23:45:10 +01005111 memprintf(err, "%sProxy '%s': unable to set TLS 1.3 cipher suites to '%s' for bind '%s' at [%s:%d].\n",
5112 err && *err ? *err : "", curproxy->id, conf_ciphersuites, bind_conf->arg, bind_conf->file, bind_conf->line);
William Lallemand8b453912019-11-21 15:48:10 +01005113 cfgerr |= ERR_ALERT | ERR_FATAL;
Dirkjan Bussink415150f2018-09-14 11:14:21 +02005114 }
5115#endif
5116
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01005117#ifndef OPENSSL_NO_DH
Remi Gacogne47783ef2015-05-29 15:53:22 +02005118 /* If tune.ssl.default-dh-param has not been set,
5119 neither has ssl-default-dh-file and no static DH
5120 params were in the certificate file. */
Willy Tarreauef934602016-12-22 23:12:01 +01005121 if (global_ssl.default_dh_param == 0 &&
Remi Gacogne47783ef2015-05-29 15:53:22 +02005122 global_dh == NULL &&
Remi Gacogne4f902b82015-05-28 16:23:00 +02005123 (ssl_dh_ptr_index == -1 ||
5124 SSL_CTX_get_ex_data(ctx, ssl_dh_ptr_index) == NULL)) {
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01005125 STACK_OF(SSL_CIPHER) * ciphers = NULL;
5126 const SSL_CIPHER * cipher = NULL;
5127 char cipher_description[128];
5128 /* The description of ciphers using an Ephemeral Diffie Hellman key exchange
5129 contains " Kx=DH " or " Kx=DH(". Beware of " Kx=DH/",
5130 which is not ephemeral DH. */
5131 const char dhe_description[] = " Kx=DH ";
5132 const char dhe_export_description[] = " Kx=DH(";
5133 int idx = 0;
5134 int dhe_found = 0;
5135 SSL *ssl = NULL;
Lukas Tribus90132722014-08-18 00:56:33 +02005136
Remi Gacogne23d5d372014-10-10 17:04:26 +02005137 ssl = SSL_new(ctx);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02005138
Remi Gacogne23d5d372014-10-10 17:04:26 +02005139 if (ssl) {
5140 ciphers = SSL_get_ciphers(ssl);
5141
5142 if (ciphers) {
5143 for (idx = 0; idx < sk_SSL_CIPHER_num(ciphers); idx++) {
5144 cipher = sk_SSL_CIPHER_value(ciphers, idx);
5145 if (SSL_CIPHER_description(cipher, cipher_description, sizeof (cipher_description)) == cipher_description) {
5146 if (strstr(cipher_description, dhe_description) != NULL ||
5147 strstr(cipher_description, dhe_export_description) != NULL) {
5148 dhe_found = 1;
5149 break;
5150 }
Remi Gacognec1eab8c2014-06-12 18:20:11 +02005151 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02005152 }
5153 }
Remi Gacogne23d5d372014-10-10 17:04:26 +02005154 SSL_free(ssl);
5155 ssl = NULL;
Lukas Tribus90132722014-08-18 00:56:33 +02005156 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02005157
Lukas Tribus90132722014-08-18 00:56:33 +02005158 if (dhe_found) {
Tim Duesterhus93128532019-11-23 23:45:10 +01005159 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",
5160 err && *err ? *err : "");
William Lallemand8b453912019-11-21 15:48:10 +01005161 cfgerr |= ERR_WARN;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02005162 }
5163
Willy Tarreauef934602016-12-22 23:12:01 +01005164 global_ssl.default_dh_param = 1024;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02005165 }
Remi Gacogne8de54152014-07-15 11:36:40 +02005166
Willy Tarreauef934602016-12-22 23:12:01 +01005167 if (global_ssl.default_dh_param >= 1024) {
Remi Gacogne8de54152014-07-15 11:36:40 +02005168 if (local_dh_1024 == NULL) {
5169 local_dh_1024 = ssl_get_dh_1024();
5170 }
Willy Tarreauef934602016-12-22 23:12:01 +01005171 if (global_ssl.default_dh_param >= 2048) {
Remi Gacogne8de54152014-07-15 11:36:40 +02005172 if (local_dh_2048 == NULL) {
5173 local_dh_2048 = ssl_get_dh_2048();
5174 }
Willy Tarreauef934602016-12-22 23:12:01 +01005175 if (global_ssl.default_dh_param >= 4096) {
Remi Gacogne8de54152014-07-15 11:36:40 +02005176 if (local_dh_4096 == NULL) {
5177 local_dh_4096 = ssl_get_dh_4096();
5178 }
Remi Gacogne8de54152014-07-15 11:36:40 +02005179 }
5180 }
5181 }
5182#endif /* OPENSSL_NO_DH */
Remi Gacognef46cd6e2014-06-12 14:58:40 +02005183
Emeric Brunfc0421f2012-09-07 17:30:07 +02005184 SSL_CTX_set_info_callback(ctx, ssl_sock_infocbk);
Willy Tarreau9a1ab082019-05-09 13:26:41 +02005185#if HA_OPENSSL_VERSION_NUMBER >= 0x00907000L
Emeric Brun29f037d2014-04-25 19:05:36 +02005186 SSL_CTX_set_msg_callback(ctx, ssl_sock_msgcbk);
Willy Tarreau5cbe4ef2014-05-08 22:45:11 +02005187#endif
Emeric Brun29f037d2014-04-25 19:05:36 +02005188
Bernard Spil13c53f82018-02-15 13:34:58 +01005189#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005190 ssl_conf_cur = NULL;
5191 if (ssl_conf && ssl_conf->npn_str)
5192 ssl_conf_cur = ssl_conf;
5193 else if (bind_conf->ssl_conf.npn_str)
5194 ssl_conf_cur = &bind_conf->ssl_conf;
5195 if (ssl_conf_cur)
5196 SSL_CTX_set_next_protos_advertised_cb(ctx, ssl_sock_advertise_npn_protos, ssl_conf_cur);
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02005197#endif
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01005198#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005199 ssl_conf_cur = NULL;
5200 if (ssl_conf && ssl_conf->alpn_str)
5201 ssl_conf_cur = ssl_conf;
5202 else if (bind_conf->ssl_conf.alpn_str)
5203 ssl_conf_cur = &bind_conf->ssl_conf;
5204 if (ssl_conf_cur)
5205 SSL_CTX_set_alpn_select_cb(ctx, ssl_sock_advertise_alpn_protos, ssl_conf_cur);
Willy Tarreauab861d32013-04-02 02:30:41 +02005206#endif
Lukas Tribusd14b49c2019-11-24 18:20:40 +01005207#if ((HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL) || defined(LIBRESSL_VERSION_NUMBER))
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01005208 conf_curves = (ssl_conf && ssl_conf->curves) ? ssl_conf->curves : bind_conf->ssl_conf.curves;
5209 if (conf_curves) {
5210 if (!SSL_CTX_set1_curves_list(ctx, conf_curves)) {
Tim Duesterhus93128532019-11-23 23:45:10 +01005211 memprintf(err, "%sProxy '%s': unable to set SSL curves list to '%s' for bind '%s' at [%s:%d].\n",
5212 err && *err ? *err : "", curproxy->id, conf_curves, bind_conf->arg, bind_conf->file, bind_conf->line);
William Lallemand8b453912019-11-21 15:48:10 +01005213 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01005214 }
Emmanuel Hocdeta52bb152017-03-20 11:11:49 +01005215 (void)SSL_CTX_set_ecdh_auto(ctx, 1);
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01005216 }
5217#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02005218#if defined(SSL_CTX_set_tmp_ecdh) && !defined(OPENSSL_NO_ECDH)
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01005219 if (!conf_curves) {
Emeric Brun2b58d042012-09-20 17:10:03 +02005220 int i;
5221 EC_KEY *ecdh;
Willy Tarreau9a1ab082019-05-09 13:26:41 +02005222#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005223 const char *ecdhe = (ssl_conf && ssl_conf->ecdhe) ? ssl_conf->ecdhe :
Olivier Houchardc2aae742017-09-22 18:26:28 +02005224 (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe :
5225 NULL);
5226
5227 if (ecdhe == NULL) {
Eric Salama3c8bde82019-11-20 11:33:40 +01005228 (void)SSL_CTX_set_ecdh_auto(ctx, 1);
Olivier Houchardc2aae742017-09-22 18:26:28 +02005229 return cfgerr;
5230 }
5231#else
5232 const char *ecdhe = (ssl_conf && ssl_conf->ecdhe) ? ssl_conf->ecdhe :
5233 (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe :
5234 ECDHE_DEFAULT_CURVE);
5235#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02005236
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005237 i = OBJ_sn2nid(ecdhe);
Emeric Brun2b58d042012-09-20 17:10:03 +02005238 if (!i || ((ecdh = EC_KEY_new_by_curve_name(i)) == NULL)) {
Tim Duesterhus93128532019-11-23 23:45:10 +01005239 memprintf(err, "%sProxy '%s': unable to set elliptic named curve to '%s' for bind '%s' at [%s:%d].\n",
5240 err && *err ? *err : "", curproxy->id, ecdhe, bind_conf->arg, bind_conf->file, bind_conf->line);
William Lallemand8b453912019-11-21 15:48:10 +01005241 cfgerr |= ERR_ALERT | ERR_FATAL;
Emeric Brun2b58d042012-09-20 17:10:03 +02005242 }
5243 else {
5244 SSL_CTX_set_tmp_ecdh(ctx, ecdh);
5245 EC_KEY_free(ecdh);
5246 }
5247 }
5248#endif
5249
Emeric Brunfc0421f2012-09-07 17:30:07 +02005250 return cfgerr;
5251}
5252
Evan Broderbe554312013-06-27 00:05:25 -07005253static int ssl_sock_srv_hostcheck(const char *pattern, const char *hostname)
5254{
5255 const char *pattern_wildcard, *pattern_left_label_end, *hostname_left_label_end;
5256 size_t prefixlen, suffixlen;
5257
5258 /* Trivial case */
5259 if (strcmp(pattern, hostname) == 0)
5260 return 1;
5261
Evan Broderbe554312013-06-27 00:05:25 -07005262 /* The rest of this logic is based on RFC 6125, section 6.4.3
5263 * (http://tools.ietf.org/html/rfc6125#section-6.4.3) */
5264
Emeric Bruna848dae2013-10-08 11:27:28 +02005265 pattern_wildcard = NULL;
5266 pattern_left_label_end = pattern;
5267 while (*pattern_left_label_end != '.') {
5268 switch (*pattern_left_label_end) {
5269 case 0:
5270 /* End of label not found */
5271 return 0;
5272 case '*':
5273 /* If there is more than one wildcards */
5274 if (pattern_wildcard)
5275 return 0;
5276 pattern_wildcard = pattern_left_label_end;
5277 break;
5278 }
5279 pattern_left_label_end++;
5280 }
5281
5282 /* If it's not trivial and there is no wildcard, it can't
5283 * match */
5284 if (!pattern_wildcard)
Evan Broderbe554312013-06-27 00:05:25 -07005285 return 0;
5286
5287 /* Make sure all labels match except the leftmost */
5288 hostname_left_label_end = strchr(hostname, '.');
5289 if (!hostname_left_label_end
5290 || strcmp(pattern_left_label_end, hostname_left_label_end) != 0)
5291 return 0;
5292
5293 /* Make sure the leftmost label of the hostname is long enough
5294 * that the wildcard can match */
Emeric Brun369da852013-10-08 11:39:35 +02005295 if (hostname_left_label_end - hostname < (pattern_left_label_end - pattern) - 1)
Evan Broderbe554312013-06-27 00:05:25 -07005296 return 0;
5297
5298 /* Finally compare the string on either side of the
5299 * wildcard */
5300 prefixlen = pattern_wildcard - pattern;
5301 suffixlen = pattern_left_label_end - (pattern_wildcard + 1);
Emeric Bruna848dae2013-10-08 11:27:28 +02005302 if ((prefixlen && (memcmp(pattern, hostname, prefixlen) != 0))
5303 || (suffixlen && (memcmp(pattern_wildcard + 1, hostname_left_label_end - suffixlen, suffixlen) != 0)))
Evan Broderbe554312013-06-27 00:05:25 -07005304 return 0;
5305
5306 return 1;
5307}
5308
5309static int ssl_sock_srv_verifycbk(int ok, X509_STORE_CTX *ctx)
5310{
5311 SSL *ssl;
5312 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01005313 struct ssl_sock_ctx *ssl_ctx;
Willy Tarreau2ab88672017-07-05 18:23:03 +02005314 const char *servername;
Willy Tarreau71d058c2017-07-26 20:09:56 +02005315 const char *sni;
Evan Broderbe554312013-06-27 00:05:25 -07005316
5317 int depth;
5318 X509 *cert;
5319 STACK_OF(GENERAL_NAME) *alt_names;
5320 int i;
5321 X509_NAME *cert_subject;
5322 char *str;
5323
5324 if (ok == 0)
5325 return ok;
5326
5327 ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
Thierry FOURNIER28962c92018-06-17 21:37:05 +02005328 conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Olivier Houchard66ab4982019-02-26 18:37:15 +01005329 ssl_ctx = conn->xprt_ctx;
Evan Broderbe554312013-06-27 00:05:25 -07005330
Willy Tarreauad92a9a2017-07-28 11:38:41 +02005331 /* We're checking if the provided hostnames match the desired one. The
5332 * desired hostname comes from the SNI we presented if any, or if not
5333 * provided then it may have been explicitly stated using a "verifyhost"
5334 * directive. If neither is set, we don't care about the name so the
5335 * verification is OK.
Willy Tarreau2ab88672017-07-05 18:23:03 +02005336 */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005337 servername = SSL_get_servername(ssl_ctx->ssl, TLSEXT_NAMETYPE_host_name);
Willy Tarreau71d058c2017-07-26 20:09:56 +02005338 sni = servername;
Willy Tarreau2ab88672017-07-05 18:23:03 +02005339 if (!servername) {
Willy Tarreau07d94e42018-09-20 10:57:52 +02005340 servername = __objt_server(conn->target)->ssl_ctx.verify_host;
Willy Tarreau2ab88672017-07-05 18:23:03 +02005341 if (!servername)
5342 return ok;
5343 }
Evan Broderbe554312013-06-27 00:05:25 -07005344
5345 /* We only need to verify the CN on the actual server cert,
5346 * not the indirect CAs */
5347 depth = X509_STORE_CTX_get_error_depth(ctx);
5348 if (depth != 0)
5349 return ok;
5350
5351 /* At this point, the cert is *not* OK unless we can find a
5352 * hostname match */
5353 ok = 0;
5354
5355 cert = X509_STORE_CTX_get_current_cert(ctx);
5356 /* It seems like this might happen if verify peer isn't set */
5357 if (!cert)
5358 return ok;
5359
5360 alt_names = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
5361 if (alt_names) {
5362 for (i = 0; !ok && i < sk_GENERAL_NAME_num(alt_names); i++) {
5363 GENERAL_NAME *name = sk_GENERAL_NAME_value(alt_names, i);
5364 if (name->type == GEN_DNS) {
Willy Tarreau9a1ab082019-05-09 13:26:41 +02005365#if HA_OPENSSL_VERSION_NUMBER < 0x00907000L
Emeric Bruna33410c2013-09-17 15:47:48 +02005366 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.ia5) >= 0) {
5367#else
Evan Broderbe554312013-06-27 00:05:25 -07005368 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
Emeric Bruna33410c2013-09-17 15:47:48 +02005369#endif
Evan Broderbe554312013-06-27 00:05:25 -07005370 ok = ssl_sock_srv_hostcheck(str, servername);
5371 OPENSSL_free(str);
5372 }
5373 }
5374 }
Emeric Brun4ad50a42013-09-17 15:19:54 +02005375 sk_GENERAL_NAME_pop_free(alt_names, GENERAL_NAME_free);
Evan Broderbe554312013-06-27 00:05:25 -07005376 }
5377
5378 cert_subject = X509_get_subject_name(cert);
5379 i = -1;
5380 while (!ok && (i = X509_NAME_get_index_by_NID(cert_subject, NID_commonName, i)) != -1) {
5381 X509_NAME_ENTRY *entry = X509_NAME_get_entry(cert_subject, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005382 ASN1_STRING *value;
5383 value = X509_NAME_ENTRY_get_data(entry);
5384 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
Evan Broderbe554312013-06-27 00:05:25 -07005385 ok = ssl_sock_srv_hostcheck(str, servername);
5386 OPENSSL_free(str);
5387 }
5388 }
5389
Willy Tarreau71d058c2017-07-26 20:09:56 +02005390 /* report the mismatch and indicate if SNI was used or not */
5391 if (!ok && !conn->err_code)
5392 conn->err_code = sni ? CO_ER_SSL_MISMATCH_SNI : CO_ER_SSL_MISMATCH;
Evan Broderbe554312013-06-27 00:05:25 -07005393 return ok;
5394}
5395
Emeric Brun94324a42012-10-11 14:00:19 +02005396/* prepare ssl context from servers options. Returns an error count */
Willy Tarreau03209342016-12-22 17:08:28 +01005397int ssl_sock_prepare_srv_ctx(struct server *srv)
Emeric Brun94324a42012-10-11 14:00:19 +02005398{
Willy Tarreau03209342016-12-22 17:08:28 +01005399 struct proxy *curproxy = srv->proxy;
Emeric Brun94324a42012-10-11 14:00:19 +02005400 int cfgerr = 0;
Remi Gacogneaf5c3da2014-05-19 10:29:58 +02005401 long options =
Emeric Brun94324a42012-10-11 14:00:19 +02005402 SSL_OP_ALL | /* all known workarounds for bugs */
5403 SSL_OP_NO_SSLv2 |
5404 SSL_OP_NO_COMPRESSION;
Remi Gacogneaf5c3da2014-05-19 10:29:58 +02005405 long mode =
Emeric Brun94324a42012-10-11 14:00:19 +02005406 SSL_MODE_ENABLE_PARTIAL_WRITE |
5407 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
Willy Tarreau396a1862014-11-13 14:06:52 +01005408 SSL_MODE_RELEASE_BUFFERS |
5409 SSL_MODE_SMALL_BUFFERS;
Emeric Brun850efd52014-01-29 12:24:34 +01005410 int verify = SSL_VERIFY_NONE;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01005411 SSL_CTX *ctx = NULL;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005412 struct tls_version_filter *conf_ssl_methods = &srv->ssl_ctx.methods;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005413 int i, min, max, hole;
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005414 int flags = MC_SSL_O_ALL;
Emeric Brun94324a42012-10-11 14:00:19 +02005415
Thierry Fournier383085f2013-01-24 14:15:43 +01005416 /* Make sure openssl opens /dev/urandom before the chroot */
5417 if (!ssl_initialize_random()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005418 ha_alert("OpenSSL random data generator initialization failed.\n");
Thierry Fournier383085f2013-01-24 14:15:43 +01005419 cfgerr++;
5420 }
5421
Willy Tarreaufce03112015-01-15 21:32:40 +01005422 /* Automatic memory computations need to know we use SSL there */
5423 global.ssl_used_backend = 1;
5424
5425 /* Initiate SSL context for current server */
Emeric Brun821bb9b2017-06-15 16:37:39 +02005426 if (!srv->ssl_ctx.reused_sess) {
Olivier Houcharde6060c52017-11-16 17:42:52 +01005427 if ((srv->ssl_ctx.reused_sess = calloc(1, global.nbthread*sizeof(*srv->ssl_ctx.reused_sess))) == NULL) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005428 ha_alert("Proxy '%s', server '%s' [%s:%d] out of memory.\n",
5429 curproxy->id, srv->id,
5430 srv->conf.file, srv->conf.line);
Emeric Brun821bb9b2017-06-15 16:37:39 +02005431 cfgerr++;
5432 return cfgerr;
5433 }
5434 }
Emeric Brun94324a42012-10-11 14:00:19 +02005435 if (srv->use_ssl)
5436 srv->xprt = &ssl_sock;
5437 if (srv->check.use_ssl)
Cyril Bonté9ce13112014-11-15 22:41:27 +01005438 srv->check.xprt = &ssl_sock;
Emeric Brun94324a42012-10-11 14:00:19 +02005439
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005440 ctx = SSL_CTX_new(SSLv23_client_method());
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01005441 if (!ctx) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005442 ha_alert("config : %s '%s', server '%s': unable to allocate ssl context.\n",
5443 proxy_type_str(curproxy), curproxy->id,
5444 srv->id);
Emeric Brun94324a42012-10-11 14:00:19 +02005445 cfgerr++;
5446 return cfgerr;
5447 }
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005448
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005449 if (conf_ssl_methods->flags && (conf_ssl_methods->min || conf_ssl_methods->max))
Christopher Faulet767a84b2017-11-24 16:50:31 +01005450 ha_warning("config : %s '%s': no-sslv3/no-tlsv1x are ignored for server '%s'. "
5451 "Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
5452 proxy_type_str(curproxy), curproxy->id, srv->id);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005453 else
5454 flags = conf_ssl_methods->flags;
5455
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005456 /* Real min and max should be determinate with configuration and openssl's capabilities */
5457 if (conf_ssl_methods->min)
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005458 flags |= (methodVersions[conf_ssl_methods->min].flag - 1);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005459 if (conf_ssl_methods->max)
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005460 flags |= ~((methodVersions[conf_ssl_methods->max].flag << 1) - 1);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005461
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02005462 /* find min, max and holes */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005463 min = max = CONF_TLSV_NONE;
5464 hole = 0;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005465 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005466 /* version is in openssl && version not disable in configuration */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005467 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005468 if (min) {
5469 if (hole) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005470 ha_warning("config : %s '%s': SSL/TLS versions range not contiguous for server '%s'. "
5471 "Hole find for %s. Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
5472 proxy_type_str(curproxy), curproxy->id, srv->id,
5473 methodVersions[hole].name);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005474 hole = 0;
5475 }
5476 max = i;
5477 }
5478 else {
5479 min = max = i;
5480 }
5481 }
5482 else {
5483 if (min)
5484 hole = i;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005485 }
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005486 if (!min) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005487 ha_alert("config : %s '%s': all SSL/TLS versions are disabled for server '%s'.\n",
5488 proxy_type_str(curproxy), curproxy->id, srv->id);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005489 cfgerr += 1;
5490 }
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005491
Willy Tarreau9a1ab082019-05-09 13:26:41 +02005492#if (HA_OPENSSL_VERSION_NUMBER < 0x1010000fL)
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005493 /* Keep force-xxx implementation as it is in older haproxy. It's a
Joseph Herlant017b3da2018-11-15 09:07:59 -08005494 precautionary measure to avoid any surprise with older openssl version. */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005495 if (min == max)
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02005496 methodVersions[min].ctx_set_version(ctx, SET_CLIENT);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005497 else
5498 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
5499 if (flags & methodVersions[i].flag)
5500 options |= methodVersions[i].option;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005501#else /* openssl >= 1.1.0 */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005502 /* set the max_version is required to cap TLS version or activate new TLS (v1.3) */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02005503 methodVersions[min].ctx_set_version(ctx, SET_MIN);
5504 methodVersions[max].ctx_set_version(ctx, SET_MAX);
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005505#endif
5506
5507 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLS_TICKETS)
5508 options |= SSL_OP_NO_TICKET;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01005509 SSL_CTX_set_options(ctx, options);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005510
Willy Tarreau5db847a2019-05-09 14:13:35 +02005511#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005512 if (global_ssl.async)
5513 mode |= SSL_MODE_ASYNC;
5514#endif
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01005515 SSL_CTX_set_mode(ctx, mode);
5516 srv->ssl_ctx.ctx = ctx;
5517
Emeric Bruna7aa3092012-10-26 12:58:00 +02005518 if (srv->ssl_ctx.client_crt) {
5519 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 +01005520 ha_alert("config : %s '%s', server '%s': unable to load SSL private key from PEM file '%s'.\n",
5521 proxy_type_str(curproxy), curproxy->id,
5522 srv->id, srv->ssl_ctx.client_crt);
Emeric Bruna7aa3092012-10-26 12:58:00 +02005523 cfgerr++;
5524 }
5525 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 +01005526 ha_alert("config : %s '%s', server '%s': unable to load ssl certificate from PEM file '%s'.\n",
5527 proxy_type_str(curproxy), curproxy->id,
5528 srv->id, srv->ssl_ctx.client_crt);
Emeric Bruna7aa3092012-10-26 12:58:00 +02005529 cfgerr++;
5530 }
5531 else if (SSL_CTX_check_private_key(srv->ssl_ctx.ctx) <= 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005532 ha_alert("config : %s '%s', server '%s': inconsistencies between private key and certificate loaded from PEM file '%s'.\n",
5533 proxy_type_str(curproxy), curproxy->id,
5534 srv->id, srv->ssl_ctx.client_crt);
Emeric Bruna7aa3092012-10-26 12:58:00 +02005535 cfgerr++;
5536 }
5537 }
Emeric Brun94324a42012-10-11 14:00:19 +02005538
Emeric Brun850efd52014-01-29 12:24:34 +01005539 if (global.ssl_server_verify == SSL_SERVER_VERIFY_REQUIRED)
5540 verify = SSL_VERIFY_PEER;
Emeric Brun850efd52014-01-29 12:24:34 +01005541 switch (srv->ssl_ctx.verify) {
5542 case SSL_SOCK_VERIFY_NONE:
5543 verify = SSL_VERIFY_NONE;
5544 break;
5545 case SSL_SOCK_VERIFY_REQUIRED:
5546 verify = SSL_VERIFY_PEER;
5547 break;
5548 }
Evan Broderbe554312013-06-27 00:05:25 -07005549 SSL_CTX_set_verify(srv->ssl_ctx.ctx,
Emeric Brun850efd52014-01-29 12:24:34 +01005550 verify,
Willy Tarreau2ab88672017-07-05 18:23:03 +02005551 (srv->ssl_ctx.verify_host || (verify & SSL_VERIFY_PEER)) ? ssl_sock_srv_verifycbk : NULL);
Emeric Brun850efd52014-01-29 12:24:34 +01005552 if (verify & SSL_VERIFY_PEER) {
Emeric Brunef42d922012-10-11 16:11:36 +02005553 if (srv->ssl_ctx.ca_file) {
Emmanuel Hocdetd4f9a602019-10-24 11:32:47 +02005554 /* set CAfile to verify */
5555 if (!ssl_set_verify_locations_file(srv->ssl_ctx.ctx, srv->ssl_ctx.ca_file)) {
5556 ha_alert("Proxy '%s', server '%s' [%s:%d] unable to set CA file '%s'.\n",
Christopher Faulet767a84b2017-11-24 16:50:31 +01005557 curproxy->id, srv->id,
5558 srv->conf.file, srv->conf.line, srv->ssl_ctx.ca_file);
Emeric Brunef42d922012-10-11 16:11:36 +02005559 cfgerr++;
5560 }
5561 }
Emeric Brun850efd52014-01-29 12:24:34 +01005562 else {
5563 if (global.ssl_server_verify == SSL_SERVER_VERIFY_REQUIRED)
Christopher Faulet767a84b2017-11-24 16:50:31 +01005564 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",
5565 curproxy->id, srv->id,
5566 srv->conf.file, srv->conf.line);
Emeric Brun850efd52014-01-29 12:24:34 +01005567 else
Christopher Faulet767a84b2017-11-24 16:50:31 +01005568 ha_alert("Proxy '%s', server '%s' [%s:%d] verify is enabled but no CA file specified.\n",
5569 curproxy->id, srv->id,
5570 srv->conf.file, srv->conf.line);
Emeric Brun850efd52014-01-29 12:24:34 +01005571 cfgerr++;
5572 }
Emeric Brunef42d922012-10-11 16:11:36 +02005573#ifdef X509_V_FLAG_CRL_CHECK
5574 if (srv->ssl_ctx.crl_file) {
5575 X509_STORE *store = SSL_CTX_get_cert_store(srv->ssl_ctx.ctx);
5576
Emmanuel Hocdetb270e812019-11-21 19:09:31 +01005577 if (!ssl_set_cert_crl_file(store, srv->ssl_ctx.crl_file)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005578 ha_alert("Proxy '%s', server '%s' [%s:%d] unable to configure CRL file '%s'.\n",
5579 curproxy->id, srv->id,
5580 srv->conf.file, srv->conf.line, srv->ssl_ctx.crl_file);
Emeric Brunef42d922012-10-11 16:11:36 +02005581 cfgerr++;
5582 }
5583 else {
5584 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
5585 }
5586 }
5587#endif
5588 }
5589
Olivier Houchardbd84ac82017-11-03 13:43:35 +01005590 SSL_CTX_set_session_cache_mode(srv->ssl_ctx.ctx, SSL_SESS_CACHE_CLIENT |
5591 SSL_SESS_CACHE_NO_INTERNAL_STORE);
5592 SSL_CTX_sess_set_new_cb(srv->ssl_ctx.ctx, ssl_sess_new_srv_cb);
Emeric Brun94324a42012-10-11 14:00:19 +02005593 if (srv->ssl_ctx.ciphers &&
5594 !SSL_CTX_set_cipher_list(srv->ssl_ctx.ctx, srv->ssl_ctx.ciphers)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005595 ha_alert("Proxy '%s', server '%s' [%s:%d] : unable to set SSL cipher list to '%s'.\n",
5596 curproxy->id, srv->id,
5597 srv->conf.file, srv->conf.line, srv->ssl_ctx.ciphers);
Emeric Brun94324a42012-10-11 14:00:19 +02005598 cfgerr++;
5599 }
Dirkjan Bussink415150f2018-09-14 11:14:21 +02005600
Emmanuel Hocdet839af572019-05-14 16:27:35 +02005601#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02005602 if (srv->ssl_ctx.ciphersuites &&
Pierre Cheynierbc34cd12019-03-21 16:15:47 +00005603 !SSL_CTX_set_ciphersuites(srv->ssl_ctx.ctx, srv->ssl_ctx.ciphersuites)) {
Dirkjan Bussink415150f2018-09-14 11:14:21 +02005604 ha_alert("Proxy '%s', server '%s' [%s:%d] : unable to set TLS 1.3 cipher suites to '%s'.\n",
5605 curproxy->id, srv->id,
5606 srv->conf.file, srv->conf.line, srv->ssl_ctx.ciphersuites);
5607 cfgerr++;
5608 }
5609#endif
Olivier Houchardc7566002018-11-20 23:33:50 +01005610#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
5611 if (srv->ssl_ctx.npn_str)
5612 SSL_CTX_set_next_proto_select_cb(ctx, ssl_sock_srv_select_protos, srv);
5613#endif
5614#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
5615 if (srv->ssl_ctx.alpn_str)
5616 SSL_CTX_set_alpn_protos(ctx, (unsigned char *)srv->ssl_ctx.alpn_str, srv->ssl_ctx.alpn_len);
5617#endif
5618
Emeric Brun94324a42012-10-11 14:00:19 +02005619
5620 return cfgerr;
5621}
5622
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005623/* Walks down the two trees in bind_conf and prepares all certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +02005624 * be NULL, in which case nothing is done. Returns the number of errors
5625 * encountered.
5626 */
Willy Tarreau03209342016-12-22 17:08:28 +01005627int ssl_sock_prepare_all_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02005628{
5629 struct ebmb_node *node;
5630 struct sni_ctx *sni;
5631 int err = 0;
William Lallemand8b453912019-11-21 15:48:10 +01005632 int errcode = 0;
5633 char *errmsg = NULL;
Emeric Brunfc0421f2012-09-07 17:30:07 +02005634
Willy Tarreaufce03112015-01-15 21:32:40 +01005635 /* Automatic memory computations need to know we use SSL there */
5636 global.ssl_used_frontend = 1;
5637
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01005638 /* Make sure openssl opens /dev/urandom before the chroot */
5639 if (!ssl_initialize_random()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005640 ha_alert("OpenSSL random data generator initialization failed.\n");
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01005641 err++;
5642 }
5643 /* Create initial_ctx used to start the ssl connection before do switchctx */
5644 if (!bind_conf->initial_ctx) {
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005645 err += ssl_sock_initial_ctx(bind_conf);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01005646 /* It should not be necessary to call this function, but it's
5647 necessary first to check and move all initialisation related
5648 to initial_ctx in ssl_sock_initial_ctx. */
William Lallemand8b453912019-11-21 15:48:10 +01005649 errcode |= ssl_sock_prepare_ctx(bind_conf, NULL, bind_conf->initial_ctx, &errmsg);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01005650 }
Emeric Brun0bed9942014-10-30 19:25:24 +01005651 if (bind_conf->default_ctx)
William Lallemand8b453912019-11-21 15:48:10 +01005652 errcode |= ssl_sock_prepare_ctx(bind_conf, bind_conf->default_ssl_conf, bind_conf->default_ctx, &errmsg);
Emeric Brun0bed9942014-10-30 19:25:24 +01005653
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005654 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02005655 while (node) {
5656 sni = ebmb_entry(node, struct sni_ctx, name);
Emeric Brun0bed9942014-10-30 19:25:24 +01005657 if (!sni->order && sni->ctx != bind_conf->default_ctx)
5658 /* only initialize the CTX on its first occurrence and
5659 if it is not the default_ctx */
William Lallemand8b453912019-11-21 15:48:10 +01005660 errcode |= ssl_sock_prepare_ctx(bind_conf, sni->conf, sni->ctx, &errmsg);
Emeric Brunfc0421f2012-09-07 17:30:07 +02005661 node = ebmb_next(node);
5662 }
5663
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005664 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02005665 while (node) {
5666 sni = ebmb_entry(node, struct sni_ctx, name);
William Lallemand8b453912019-11-21 15:48:10 +01005667 if (!sni->order && sni->ctx != bind_conf->default_ctx) {
Emeric Brun0bed9942014-10-30 19:25:24 +01005668 /* only initialize the CTX on its first occurrence and
5669 if it is not the default_ctx */
William Lallemand8b453912019-11-21 15:48:10 +01005670 errcode |= ssl_sock_prepare_ctx(bind_conf, sni->conf, sni->ctx, &errmsg);
5671 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02005672 node = ebmb_next(node);
5673 }
William Lallemand8b453912019-11-21 15:48:10 +01005674
5675 if (errcode & ERR_WARN) {
Tim Duesterhusc0e820c2019-11-23 23:52:30 +01005676 ha_warning("%s", errmsg);
William Lallemand8b453912019-11-21 15:48:10 +01005677 } else if (errcode & ERR_CODE) {
Tim Duesterhusc0e820c2019-11-23 23:52:30 +01005678 ha_alert("%s", errmsg);
William Lallemand8b453912019-11-21 15:48:10 +01005679 err++;
5680 }
5681
5682 free(errmsg);
Emeric Brunfc0421f2012-09-07 17:30:07 +02005683 return err;
5684}
5685
Willy Tarreau55d37912016-12-21 23:38:39 +01005686/* Prepares all the contexts for a bind_conf and allocates the shared SSL
5687 * context if needed. Returns < 0 on error, 0 on success. The warnings and
5688 * alerts are directly emitted since the rest of the stack does it below.
5689 */
5690int ssl_sock_prepare_bind_conf(struct bind_conf *bind_conf)
5691{
5692 struct proxy *px = bind_conf->frontend;
5693 int alloc_ctx;
5694 int err;
5695
5696 if (!bind_conf->is_ssl) {
5697 if (bind_conf->default_ctx) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005698 ha_warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
5699 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreau55d37912016-12-21 23:38:39 +01005700 }
5701 return 0;
5702 }
5703 if (!bind_conf->default_ctx) {
Emmanuel Hocdetaa0d6372017-08-09 11:24:25 +02005704 if (bind_conf->strict_sni && !bind_conf->generate_certs) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005705 ha_warning("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d], ssl connections will fail (use 'crt').\n",
5706 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetaa0d6372017-08-09 11:24:25 +02005707 }
5708 else {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005709 ha_alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
5710 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetaa0d6372017-08-09 11:24:25 +02005711 return -1;
5712 }
Willy Tarreau55d37912016-12-21 23:38:39 +01005713 }
William Lallemandc61c0b32017-12-04 18:46:39 +01005714 if (!ssl_shctx && global.tune.sslcachesize) {
William Lallemandc3cd35f2017-11-28 11:04:43 +01005715 alloc_ctx = shctx_init(&ssl_shctx, global.tune.sslcachesize,
Frédéric Lécailleb7838af2018-10-22 16:21:39 +02005716 sizeof(struct sh_ssl_sess_hdr) + SHSESS_BLOCK_MIN_SIZE, -1,
William Lallemandc3cd35f2017-11-28 11:04:43 +01005717 sizeof(*sh_ssl_sess_tree),
5718 ((global.nbthread > 1) || (!global_ssl.private_cache && (global.nbproc > 1))) ? 1 : 0);
Frédéric Lécaille4c8aa112018-10-25 20:22:46 +02005719 if (alloc_ctx <= 0) {
William Lallemandc3cd35f2017-11-28 11:04:43 +01005720 if (alloc_ctx == SHCTX_E_INIT_LOCK)
5721 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");
5722 else
5723 ha_alert("Unable to allocate SSL session cache.\n");
5724 return -1;
5725 }
5726 /* free block callback */
5727 ssl_shctx->free_block = sh_ssl_sess_free_blocks;
5728 /* init the root tree within the extra space */
5729 sh_ssl_sess_tree = (void *)ssl_shctx + sizeof(struct shared_context);
5730 *sh_ssl_sess_tree = EB_ROOT_UNIQUE;
Willy Tarreau55d37912016-12-21 23:38:39 +01005731 }
Willy Tarreau55d37912016-12-21 23:38:39 +01005732 err = 0;
5733 /* initialize all certificate contexts */
5734 err += ssl_sock_prepare_all_ctx(bind_conf);
5735
5736 /* initialize CA variables if the certificates generation is enabled */
5737 err += ssl_sock_load_ca(bind_conf);
5738
5739 return -err;
5740}
Christopher Faulet77fe80c2015-07-29 13:02:40 +02005741
5742/* release ssl context allocated for servers. */
5743void ssl_sock_free_srv_ctx(struct server *srv)
5744{
Olivier Houchardc7566002018-11-20 23:33:50 +01005745#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
5746 if (srv->ssl_ctx.alpn_str)
5747 free(srv->ssl_ctx.alpn_str);
5748#endif
Lukas Tribusda95fd92018-11-25 13:21:27 +01005749#ifdef OPENSSL_NPN_NEGOTIATED
Olivier Houchardc7566002018-11-20 23:33:50 +01005750 if (srv->ssl_ctx.npn_str)
5751 free(srv->ssl_ctx.npn_str);
Lukas Tribus7706b852018-11-26 22:57:17 +01005752#endif
Christopher Faulet77fe80c2015-07-29 13:02:40 +02005753 if (srv->ssl_ctx.ctx)
5754 SSL_CTX_free(srv->ssl_ctx.ctx);
5755}
5756
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005757/* Walks down the two trees in bind_conf and frees all the certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +02005758 * be NULL, in which case nothing is done. The default_ctx is nullified too.
5759 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005760void ssl_sock_free_all_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02005761{
5762 struct ebmb_node *node, *back;
5763 struct sni_ctx *sni;
5764
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005765 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02005766 while (node) {
5767 sni = ebmb_entry(node, struct sni_ctx, name);
5768 back = ebmb_next(node);
5769 ebmb_delete(node);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005770 if (!sni->order) { /* only free the CTX on its first occurrence */
Emeric Brunfc0421f2012-09-07 17:30:07 +02005771 SSL_CTX_free(sni->ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005772 ssl_sock_free_ssl_conf(sni->conf);
5773 free(sni->conf);
5774 sni->conf = NULL;
5775 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02005776 free(sni);
5777 node = back;
5778 }
5779
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005780 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02005781 while (node) {
5782 sni = ebmb_entry(node, struct sni_ctx, name);
5783 back = ebmb_next(node);
5784 ebmb_delete(node);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005785 if (!sni->order) { /* only free the CTX on its first occurrence */
Emeric Brunfc0421f2012-09-07 17:30:07 +02005786 SSL_CTX_free(sni->ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005787 ssl_sock_free_ssl_conf(sni->conf);
5788 free(sni->conf);
5789 sni->conf = NULL;
5790 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02005791 free(sni);
5792 node = back;
5793 }
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01005794 SSL_CTX_free(bind_conf->initial_ctx);
5795 bind_conf->initial_ctx = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005796 bind_conf->default_ctx = NULL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005797 bind_conf->default_ssl_conf = NULL;
Emeric Brune1f38db2012-09-03 20:36:47 +02005798}
5799
Willy Tarreau795cdab2016-12-22 17:30:54 +01005800/* Destroys all the contexts for a bind_conf. This is used during deinit(). */
5801void ssl_sock_destroy_bind_conf(struct bind_conf *bind_conf)
5802{
5803 ssl_sock_free_ca(bind_conf);
5804 ssl_sock_free_all_ctx(bind_conf);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005805 ssl_sock_free_ssl_conf(&bind_conf->ssl_conf);
Willy Tarreau795cdab2016-12-22 17:30:54 +01005806 free(bind_conf->ca_sign_file);
5807 free(bind_conf->ca_sign_pass);
Willy Tarreau17b4aa12018-07-17 10:05:32 +02005808 if (bind_conf->keys_ref && !--bind_conf->keys_ref->refcount) {
Willy Tarreau795cdab2016-12-22 17:30:54 +01005809 free(bind_conf->keys_ref->filename);
5810 free(bind_conf->keys_ref->tlskeys);
5811 LIST_DEL(&bind_conf->keys_ref->list);
5812 free(bind_conf->keys_ref);
5813 }
5814 bind_conf->keys_ref = NULL;
Willy Tarreau795cdab2016-12-22 17:30:54 +01005815 bind_conf->ca_sign_pass = NULL;
5816 bind_conf->ca_sign_file = NULL;
Willy Tarreau795cdab2016-12-22 17:30:54 +01005817}
5818
Christopher Faulet31af49d2015-06-09 17:29:50 +02005819/* Load CA cert file and private key used to generate certificates */
5820int
Willy Tarreau03209342016-12-22 17:08:28 +01005821ssl_sock_load_ca(struct bind_conf *bind_conf)
Christopher Faulet31af49d2015-06-09 17:29:50 +02005822{
Willy Tarreau03209342016-12-22 17:08:28 +01005823 struct proxy *px = bind_conf->frontend;
Christopher Faulet31af49d2015-06-09 17:29:50 +02005824 FILE *fp;
5825 X509 *cacert = NULL;
5826 EVP_PKEY *capkey = NULL;
5827 int err = 0;
5828
Christopher Fauletf8bb0ce2017-09-15 09:52:49 +02005829 if (!bind_conf->generate_certs)
Christopher Faulet31af49d2015-06-09 17:29:50 +02005830 return err;
5831
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005832#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Emeric Brun821bb9b2017-06-15 16:37:39 +02005833 if (global_ssl.ctx_cache) {
Willy Tarreauef934602016-12-22 23:12:01 +01005834 ssl_ctx_lru_tree = lru64_new(global_ssl.ctx_cache);
Emeric Brun821bb9b2017-06-15 16:37:39 +02005835 }
Christopher Fauletd2cab922015-07-28 16:03:47 +02005836 ssl_ctx_lru_seed = (unsigned int)time(NULL);
Emeric Brun821bb9b2017-06-15 16:37:39 +02005837 ssl_ctx_serial = now_ms;
Willy Tarreaua84c2672015-10-09 12:10:13 +02005838#endif
Christopher Fauletd2cab922015-07-28 16:03:47 +02005839
Christopher Faulet31af49d2015-06-09 17:29:50 +02005840 if (!bind_conf->ca_sign_file) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005841 ha_alert("Proxy '%s': cannot enable certificate generation, "
5842 "no CA certificate File configured at [%s:%d].\n",
5843 px->id, bind_conf->file, bind_conf->line);
Christopher Faulet31af49d2015-06-09 17:29:50 +02005844 goto load_error;
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005845 }
Christopher Faulet31af49d2015-06-09 17:29:50 +02005846
5847 /* read in the CA certificate */
5848 if (!(fp = fopen(bind_conf->ca_sign_file, "r"))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005849 ha_alert("Proxy '%s': Failed to read CA certificate file '%s' at [%s:%d].\n",
5850 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Faulet31af49d2015-06-09 17:29:50 +02005851 goto load_error;
5852 }
5853 if (!(cacert = PEM_read_X509(fp, NULL, NULL, NULL))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005854 ha_alert("Proxy '%s': Failed to read CA certificate file '%s' at [%s:%d].\n",
5855 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005856 goto read_error;
Christopher Faulet31af49d2015-06-09 17:29:50 +02005857 }
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005858 rewind(fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02005859 if (!(capkey = PEM_read_PrivateKey(fp, NULL, NULL, bind_conf->ca_sign_pass))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005860 ha_alert("Proxy '%s': Failed to read CA private key file '%s' at [%s:%d].\n",
5861 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005862 goto read_error;
Christopher Faulet31af49d2015-06-09 17:29:50 +02005863 }
Christopher Faulet31af49d2015-06-09 17:29:50 +02005864
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005865 fclose (fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02005866 bind_conf->ca_sign_cert = cacert;
5867 bind_conf->ca_sign_pkey = capkey;
5868 return err;
5869
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005870 read_error:
5871 fclose (fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02005872 if (capkey) EVP_PKEY_free(capkey);
5873 if (cacert) X509_free(cacert);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005874 load_error:
5875 bind_conf->generate_certs = 0;
5876 err++;
Christopher Faulet31af49d2015-06-09 17:29:50 +02005877 return err;
5878}
5879
5880/* Release CA cert and private key used to generate certificated */
5881void
5882ssl_sock_free_ca(struct bind_conf *bind_conf)
5883{
Christopher Faulet31af49d2015-06-09 17:29:50 +02005884 if (bind_conf->ca_sign_pkey)
5885 EVP_PKEY_free(bind_conf->ca_sign_pkey);
5886 if (bind_conf->ca_sign_cert)
5887 X509_free(bind_conf->ca_sign_cert);
Willy Tarreau94ff03a2016-12-22 17:57:46 +01005888 bind_conf->ca_sign_pkey = NULL;
5889 bind_conf->ca_sign_cert = NULL;
Christopher Faulet31af49d2015-06-09 17:29:50 +02005890}
5891
Emeric Brun46591952012-05-18 15:47:34 +02005892/*
5893 * This function is called if SSL * context is not yet allocated. The function
5894 * is designed to be called before any other data-layer operation and sets the
5895 * handshake flag on the connection. It is safe to call it multiple times.
5896 * It returns 0 on success and -1 in error case.
5897 */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005898static int ssl_sock_init(struct connection *conn, void **xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02005899{
Olivier Houchard66ab4982019-02-26 18:37:15 +01005900 struct ssl_sock_ctx *ctx;
Emeric Brun46591952012-05-18 15:47:34 +02005901 /* already initialized */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005902 if (*xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02005903 return 0;
5904
Willy Tarreau3c728722014-01-23 13:50:42 +01005905 if (!conn_ctrl_ready(conn))
Willy Tarreauf79c8172013-10-21 16:30:56 +02005906 return 0;
5907
Olivier Houchard66ab4982019-02-26 18:37:15 +01005908 ctx = pool_alloc(ssl_sock_ctx_pool);
5909 if (!ctx) {
5910 conn->err_code = CO_ER_SSL_NO_MEM;
5911 return -1;
5912 }
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02005913 ctx->wait_event.tasklet = tasklet_new();
5914 if (!ctx->wait_event.tasklet) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02005915 conn->err_code = CO_ER_SSL_NO_MEM;
5916 pool_free(ssl_sock_ctx_pool, ctx);
5917 return -1;
5918 }
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02005919 ctx->wait_event.tasklet->process = ssl_sock_io_cb;
5920 ctx->wait_event.tasklet->context = ctx;
Olivier Houchardea8dd942019-05-20 14:02:16 +02005921 ctx->wait_event.events = 0;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01005922 ctx->sent_early_data = 0;
Olivier Houchard54907bb2019-12-19 15:02:39 +01005923 ctx->early_buf = BUF_NULL;
Olivier Houcharda8955d52019-04-07 22:00:38 +02005924 ctx->conn = conn;
Willy Tarreau113d52b2020-01-10 09:20:26 +01005925 ctx->subs = NULL;
Emeric Brun5762a0d2019-09-06 15:36:02 +02005926 ctx->xprt_st = 0;
5927 ctx->xprt_ctx = NULL;
Olivier Houcharda8955d52019-04-07 22:00:38 +02005928
5929 /* Only work with sockets for now, this should be adapted when we'll
5930 * add QUIC support.
5931 */
5932 ctx->xprt = xprt_get(XPRT_RAW);
Olivier Houchard19afb272019-05-23 18:24:07 +02005933 if (ctx->xprt->init) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02005934 if (ctx->xprt->init(conn, &ctx->xprt_ctx) != 0)
5935 goto err;
Olivier Houchard19afb272019-05-23 18:24:07 +02005936 }
Olivier Houchard66ab4982019-02-26 18:37:15 +01005937
Willy Tarreau20879a02012-12-03 16:32:10 +01005938 if (global.maxsslconn && sslconns >= global.maxsslconn) {
5939 conn->err_code = CO_ER_SSL_TOO_MANY;
Olivier Houchardea8dd942019-05-20 14:02:16 +02005940 goto err;
Willy Tarreau20879a02012-12-03 16:32:10 +01005941 }
Willy Tarreau403edff2012-09-06 11:58:37 +02005942
Emeric Brun46591952012-05-18 15:47:34 +02005943 /* If it is in client mode initiate SSL session
5944 in connect state otherwise accept state */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01005945 if (objt_server(conn->target)) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005946 int may_retry = 1;
5947
5948 retry_connect:
Emeric Brun46591952012-05-18 15:47:34 +02005949 /* Alloc a new SSL session ctx */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005950 ctx->ssl = SSL_new(__objt_server(conn->target)->ssl_ctx.ctx);
5951 if (!ctx->ssl) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005952 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005953 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005954 goto retry_connect;
5955 }
Willy Tarreau20879a02012-12-03 16:32:10 +01005956 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01005957 goto err;
Willy Tarreau20879a02012-12-03 16:32:10 +01005958 }
Olivier Houcharda8955d52019-04-07 22:00:38 +02005959 ctx->bio = BIO_new(ha_meth);
5960 if (!ctx->bio) {
Olivier Houchardefe5e8e2020-01-24 15:17:38 +01005961 SSL_free(ctx->ssl);
5962 ctx->ssl = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005963 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005964 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005965 goto retry_connect;
5966 }
Emeric Brun55476152014-11-12 17:35:37 +01005967 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01005968 goto err;
Emeric Brun55476152014-11-12 17:35:37 +01005969 }
Olivier Houcharda8955d52019-04-07 22:00:38 +02005970 BIO_set_data(ctx->bio, ctx);
Olivier Houcharda8955d52019-04-07 22:00:38 +02005971 SSL_set_bio(ctx->ssl, ctx->bio, ctx->bio);
Emeric Brun46591952012-05-18 15:47:34 +02005972
Evan Broderbe554312013-06-27 00:05:25 -07005973 /* set connection pointer */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005974 if (!SSL_set_ex_data(ctx->ssl, ssl_app_data_index, conn)) {
5975 SSL_free(ctx->ssl);
5976 ctx->ssl = NULL;
Emeric Brun55476152014-11-12 17:35:37 +01005977 conn->xprt_ctx = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005978 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005979 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005980 goto retry_connect;
5981 }
Emeric Brun55476152014-11-12 17:35:37 +01005982 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01005983 goto err;
Emeric Brun55476152014-11-12 17:35:37 +01005984 }
5985
Olivier Houchard66ab4982019-02-26 18:37:15 +01005986 SSL_set_connect_state(ctx->ssl);
Willy Tarreau07d94e42018-09-20 10:57:52 +02005987 if (__objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr) {
5988 const unsigned char *ptr = __objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr;
5989 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 +01005990 if (sess && !SSL_set_session(ctx->ssl, sess)) {
Olivier Houcharde6060c52017-11-16 17:42:52 +01005991 SSL_SESSION_free(sess);
Willy Tarreau07d94e42018-09-20 10:57:52 +02005992 free(__objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr);
5993 __objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr = NULL;
Olivier Houcharde6060c52017-11-16 17:42:52 +01005994 } else if (sess) {
5995 SSL_SESSION_free(sess);
Emeric Brun55476152014-11-12 17:35:37 +01005996 }
5997 }
Evan Broderbe554312013-06-27 00:05:25 -07005998
Emeric Brun46591952012-05-18 15:47:34 +02005999 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +02006000 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Willy Tarreau403edff2012-09-06 11:58:37 +02006001
Olivier Houchard2be5a4c2019-03-08 18:54:43 +01006002 _HA_ATOMIC_ADD(&sslconns, 1);
6003 _HA_ATOMIC_ADD(&totalsslconns, 1);
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006004 *xprt_ctx = ctx;
Olivier Houchardea8dd942019-05-20 14:02:16 +02006005 /* Start the handshake */
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02006006 tasklet_wakeup(ctx->wait_event.tasklet);
Emeric Brun46591952012-05-18 15:47:34 +02006007 return 0;
6008 }
Willy Tarreau3fdb3662012-11-12 00:42:33 +01006009 else if (objt_listener(conn->target)) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01006010 int may_retry = 1;
6011
6012 retry_accept:
Emeric Brun46591952012-05-18 15:47:34 +02006013 /* Alloc a new SSL session ctx */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006014 ctx->ssl = SSL_new(__objt_listener(conn->target)->bind_conf->initial_ctx);
6015 if (!ctx->ssl) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01006016 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01006017 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01006018 goto retry_accept;
6019 }
Willy Tarreau20879a02012-12-03 16:32:10 +01006020 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006021 goto err;
Willy Tarreau20879a02012-12-03 16:32:10 +01006022 }
Olivier Houcharda8955d52019-04-07 22:00:38 +02006023 ctx->bio = BIO_new(ha_meth);
6024 if (!ctx->bio) {
Olivier Houchardefe5e8e2020-01-24 15:17:38 +01006025 SSL_free(ctx->ssl);
6026 ctx->ssl = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01006027 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01006028 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01006029 goto retry_accept;
6030 }
Emeric Brun55476152014-11-12 17:35:37 +01006031 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006032 goto err;
Emeric Brun55476152014-11-12 17:35:37 +01006033 }
Olivier Houcharda8955d52019-04-07 22:00:38 +02006034 BIO_set_data(ctx->bio, ctx);
Olivier Houcharda8955d52019-04-07 22:00:38 +02006035 SSL_set_bio(ctx->ssl, ctx->bio, ctx->bio);
Emeric Brun46591952012-05-18 15:47:34 +02006036
Emeric Brune1f38db2012-09-03 20:36:47 +02006037 /* set connection pointer */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006038 if (!SSL_set_ex_data(ctx->ssl, ssl_app_data_index, conn)) {
6039 SSL_free(ctx->ssl);
6040 ctx->ssl = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01006041 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01006042 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01006043 goto retry_accept;
6044 }
Emeric Brun55476152014-11-12 17:35:37 +01006045 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006046 goto err;
Emeric Brun55476152014-11-12 17:35:37 +01006047 }
6048
Frédéric Lécaille3139c1b2020-01-24 14:56:18 +01006049#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
6050 if (__objt_listener(conn->target)->bind_conf->ssl_conf.early_data) {
6051 b_alloc(&ctx->early_buf);
6052 SSL_set_max_early_data(ctx->ssl,
6053 /* Only allow early data if we managed to allocate
6054 * a buffer.
6055 */
6056 (!b_is_null(&ctx->early_buf)) ?
6057 global.tune.bufsize - global.tune.maxrewrite : 0);
6058 }
6059#endif
6060
Olivier Houchard66ab4982019-02-26 18:37:15 +01006061 SSL_set_accept_state(ctx->ssl);
Emeric Brune1f38db2012-09-03 20:36:47 +02006062
Emeric Brun46591952012-05-18 15:47:34 +02006063 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +02006064 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Emmanuel Hocdetf967c312019-08-05 18:04:16 +02006065#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Olivier Houchardc2aae742017-09-22 18:26:28 +02006066 conn->flags |= CO_FL_EARLY_SSL_HS;
6067#endif
Willy Tarreau403edff2012-09-06 11:58:37 +02006068
Olivier Houchard2be5a4c2019-03-08 18:54:43 +01006069 _HA_ATOMIC_ADD(&sslconns, 1);
6070 _HA_ATOMIC_ADD(&totalsslconns, 1);
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006071 *xprt_ctx = ctx;
Olivier Houchardea8dd942019-05-20 14:02:16 +02006072 /* Start the handshake */
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02006073 tasklet_wakeup(ctx->wait_event.tasklet);
Emeric Brun46591952012-05-18 15:47:34 +02006074 return 0;
6075 }
6076 /* don't know how to handle such a target */
Willy Tarreau20879a02012-12-03 16:32:10 +01006077 conn->err_code = CO_ER_SSL_NO_TARGET;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006078err:
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02006079 if (ctx && ctx->wait_event.tasklet)
6080 tasklet_free(ctx->wait_event.tasklet);
Olivier Houchard66ab4982019-02-26 18:37:15 +01006081 pool_free(ssl_sock_ctx_pool, ctx);
Emeric Brun46591952012-05-18 15:47:34 +02006082 return -1;
6083}
6084
6085
6086/* This is the callback which is used when an SSL handshake is pending. It
6087 * updates the FD status if it wants some polling before being called again.
6088 * It returns 0 if it fails in a fatal way or needs to poll to go further,
6089 * otherwise it returns non-zero and removes itself from the connection's
6090 * flags (the bit is provided in <flag> by the caller).
6091 */
Olivier Houchard000694c2019-05-23 14:45:12 +02006092static int ssl_sock_handshake(struct connection *conn, unsigned int flag)
Emeric Brun46591952012-05-18 15:47:34 +02006093{
Olivier Houchard66ab4982019-02-26 18:37:15 +01006094 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
Emeric Brun46591952012-05-18 15:47:34 +02006095 int ret;
6096
Willy Tarreau3c728722014-01-23 13:50:42 +01006097 if (!conn_ctrl_ready(conn))
Willy Tarreauf79c8172013-10-21 16:30:56 +02006098 return 0;
6099
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02006100 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02006101 goto out_error;
6102
Willy Tarreau5db847a2019-05-09 14:13:35 +02006103#if HA_OPENSSL_VERSION_NUMBER >= 0x10101000L
Olivier Houchardc2aae742017-09-22 18:26:28 +02006104 /*
6105 * Check if we have early data. If we do, we have to read them
6106 * before SSL_do_handshake() is called, And there's no way to
6107 * detect early data, except to try to read them
6108 */
6109 if (conn->flags & CO_FL_EARLY_SSL_HS) {
Olivier Houchard54907bb2019-12-19 15:02:39 +01006110 size_t read_data = 0;
Olivier Houchardc2aae742017-09-22 18:26:28 +02006111
Olivier Houchard54907bb2019-12-19 15:02:39 +01006112 while (1) {
6113 ret = SSL_read_early_data(ctx->ssl,
6114 b_tail(&ctx->early_buf), b_room(&ctx->early_buf),
6115 &read_data);
6116 if (ret == SSL_READ_EARLY_DATA_ERROR)
6117 goto check_error;
6118 if (read_data > 0) {
6119 conn->flags |= CO_FL_EARLY_DATA;
6120 b_add(&ctx->early_buf, read_data);
6121 }
6122 if (ret == SSL_READ_EARLY_DATA_FINISH) {
6123 conn->flags &= ~CO_FL_EARLY_SSL_HS;
6124 if (!b_data(&ctx->early_buf))
6125 b_free(&ctx->early_buf);
6126 break;
6127 }
6128 }
Olivier Houchardc2aae742017-09-22 18:26:28 +02006129 }
6130#endif
Emeric Brun674b7432012-11-08 19:21:55 +01006131 /* If we use SSL_do_handshake to process a reneg initiated by
6132 * the remote peer, it sometimes returns SSL_ERROR_SSL.
6133 * Usually SSL_write and SSL_read are used and process implicitly
6134 * the reneg handshake.
6135 * Here we use SSL_peek as a workaround for reneg.
6136 */
Willy Tarreauc192b0a2020-01-23 09:11:58 +01006137 if (!(conn->flags & CO_FL_WAIT_L6_CONN) && SSL_renegotiate_pending(ctx->ssl)) {
Emeric Brun674b7432012-11-08 19:21:55 +01006138 char c;
6139
Olivier Houchard66ab4982019-02-26 18:37:15 +01006140 ret = SSL_peek(ctx->ssl, &c, 1);
Emeric Brun674b7432012-11-08 19:21:55 +01006141 if (ret <= 0) {
6142 /* handshake may have not been completed, let's find why */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006143 ret = SSL_get_error(ctx->ssl, ret);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006144
Emeric Brun674b7432012-11-08 19:21:55 +01006145 if (ret == SSL_ERROR_WANT_WRITE) {
6146 /* SSL handshake needs to write, L4 connection may not be ready */
Olivier Houchard03abf2d2019-05-28 10:12:02 +02006147 if (!(ctx->wait_event.events & SUB_RETRY_SEND))
Olivier Houchardea8dd942019-05-20 14:02:16 +02006148 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_SEND, &ctx->wait_event);
Emeric Brun674b7432012-11-08 19:21:55 +01006149 return 0;
6150 }
6151 else if (ret == SSL_ERROR_WANT_READ) {
6152 /* handshake may have been completed but we have
6153 * no more data to read.
6154 */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006155 if (!SSL_renegotiate_pending(ctx->ssl)) {
Emeric Brun674b7432012-11-08 19:21:55 +01006156 ret = 1;
6157 goto reneg_ok;
6158 }
6159 /* SSL handshake needs to read, L4 connection is ready */
Olivier Houchard03abf2d2019-05-28 10:12:02 +02006160 if (!(ctx->wait_event.events & SUB_RETRY_RECV))
Olivier Houchardea8dd942019-05-20 14:02:16 +02006161 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_RECV, &ctx->wait_event);
Emeric Brun674b7432012-11-08 19:21:55 +01006162 return 0;
6163 }
Willy Tarreau5db847a2019-05-09 14:13:35 +02006164#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006165 else if (ret == SSL_ERROR_WANT_ASYNC) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02006166 ssl_async_process_fds(ctx);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006167 return 0;
6168 }
6169#endif
Emeric Brun674b7432012-11-08 19:21:55 +01006170 else if (ret == SSL_ERROR_SYSCALL) {
6171 /* if errno is null, then connection was successfully established */
6172 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
6173 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Willy Tarreau20879a02012-12-03 16:32:10 +01006174 if (!conn->err_code) {
Lukas Tribus49799162019-07-08 14:29:15 +02006175#if defined(OPENSSL_IS_BORINGSSL) || defined(LIBRESSL_VERSION_NUMBER)
6176 /* do not handle empty handshakes in BoringSSL or LibreSSL */
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01006177 conn->err_code = CO_ER_SSL_HANDSHAKE;
6178#else
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006179 int empty_handshake;
Willy Tarreau5db847a2019-05-09 14:13:35 +02006180#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL)
Lukas Tribus49799162019-07-08 14:29:15 +02006181 /* use SSL_get_state() in OpenSSL >= 1.1.0; SSL_state() is broken */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006182 OSSL_HANDSHAKE_STATE state = SSL_get_state((SSL *)ctx->ssl);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006183 empty_handshake = state == TLS_ST_BEFORE;
6184#else
Lukas Tribus49799162019-07-08 14:29:15 +02006185 /* access packet_length directly in OpenSSL <= 1.0.2; SSL_state() is broken */
6186 empty_handshake = !ctx->ssl->packet_length;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006187#endif
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006188 if (empty_handshake) {
Emeric Brun29f037d2014-04-25 19:05:36 +02006189 if (!errno) {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006190 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emeric Brun29f037d2014-04-25 19:05:36 +02006191 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
6192 else
6193 conn->err_code = CO_ER_SSL_EMPTY;
6194 }
6195 else {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006196 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emeric Brun29f037d2014-04-25 19:05:36 +02006197 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
6198 else
6199 conn->err_code = CO_ER_SSL_ABORT;
6200 }
6201 }
6202 else {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006203 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emeric Brun29f037d2014-04-25 19:05:36 +02006204 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
Willy Tarreau20879a02012-12-03 16:32:10 +01006205 else
Emeric Brun29f037d2014-04-25 19:05:36 +02006206 conn->err_code = CO_ER_SSL_HANDSHAKE;
6207 }
Lukas Tribus49799162019-07-08 14:29:15 +02006208#endif /* BoringSSL or LibreSSL */
Willy Tarreau20879a02012-12-03 16:32:10 +01006209 }
Emeric Brun674b7432012-11-08 19:21:55 +01006210 goto out_error;
6211 }
6212 else {
6213 /* Fail on all other handshake errors */
6214 /* Note: OpenSSL may leave unread bytes in the socket's
6215 * buffer, causing an RST to be emitted upon close() on
6216 * TCP sockets. We first try to drain possibly pending
6217 * data to avoid this as much as possible.
6218 */
Willy Tarreaud85c4852015-03-13 00:40:28 +01006219 conn_sock_drain(conn);
Willy Tarreau20879a02012-12-03 16:32:10 +01006220 if (!conn->err_code)
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006221 conn->err_code = (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT) ?
Willy Tarreauf51c6982014-04-25 20:02:39 +02006222 CO_ER_SSL_KILLED_HB : CO_ER_SSL_HANDSHAKE;
Emeric Brun674b7432012-11-08 19:21:55 +01006223 goto out_error;
6224 }
6225 }
6226 /* read some data: consider handshake completed */
6227 goto reneg_ok;
6228 }
Olivier Houchard66ab4982019-02-26 18:37:15 +01006229 ret = SSL_do_handshake(ctx->ssl);
Olivier Houchardc2aae742017-09-22 18:26:28 +02006230check_error:
Emeric Brun46591952012-05-18 15:47:34 +02006231 if (ret != 1) {
6232 /* handshake did not complete, let's find why */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006233 ret = SSL_get_error(ctx->ssl, ret);
Emeric Brun46591952012-05-18 15:47:34 +02006234
6235 if (ret == SSL_ERROR_WANT_WRITE) {
6236 /* SSL handshake needs to write, L4 connection may not be ready */
Olivier Houchard03abf2d2019-05-28 10:12:02 +02006237 if (!(ctx->wait_event.events & SUB_RETRY_SEND))
Olivier Houchardea8dd942019-05-20 14:02:16 +02006238 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_SEND, &ctx->wait_event);
Emeric Brun46591952012-05-18 15:47:34 +02006239 return 0;
6240 }
6241 else if (ret == SSL_ERROR_WANT_READ) {
6242 /* SSL handshake needs to read, L4 connection is ready */
Olivier Houchardea8dd942019-05-20 14:02:16 +02006243 if (!(ctx->wait_event.events & SUB_RETRY_RECV))
Olivier Houchardea8dd942019-05-20 14:02:16 +02006244 ctx->xprt->subscribe(conn, ctx->xprt_ctx,
6245 SUB_RETRY_RECV, &ctx->wait_event);
Emeric Brun46591952012-05-18 15:47:34 +02006246 return 0;
6247 }
Willy Tarreau5db847a2019-05-09 14:13:35 +02006248#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006249 else if (ret == SSL_ERROR_WANT_ASYNC) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02006250 ssl_async_process_fds(ctx);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006251 return 0;
6252 }
6253#endif
Willy Tarreau89230192012-09-28 20:22:13 +02006254 else if (ret == SSL_ERROR_SYSCALL) {
6255 /* if errno is null, then connection was successfully established */
6256 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
6257 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01006258 if (!conn->err_code) {
Lukas Tribus49799162019-07-08 14:29:15 +02006259#if defined(OPENSSL_IS_BORINGSSL) || defined(LIBRESSL_VERSION_NUMBER)
6260 /* do not handle empty handshakes in BoringSSL or LibreSSL */
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01006261 conn->err_code = CO_ER_SSL_HANDSHAKE;
6262#else
6263 int empty_handshake;
Willy Tarreau5db847a2019-05-09 14:13:35 +02006264#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL)
Lukas Tribus49799162019-07-08 14:29:15 +02006265 /* use SSL_get_state() in OpenSSL >= 1.1.0; SSL_state() is broken */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006266 OSSL_HANDSHAKE_STATE state = SSL_get_state(ctx->ssl);
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01006267 empty_handshake = state == TLS_ST_BEFORE;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006268#else
Lukas Tribus49799162019-07-08 14:29:15 +02006269 /* access packet_length directly in OpenSSL <= 1.0.2; SSL_state() is broken */
6270 empty_handshake = !ctx->ssl->packet_length;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006271#endif
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01006272 if (empty_handshake) {
6273 if (!errno) {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006274 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01006275 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
6276 else
6277 conn->err_code = CO_ER_SSL_EMPTY;
6278 }
6279 else {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006280 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01006281 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
6282 else
6283 conn->err_code = CO_ER_SSL_ABORT;
6284 }
Emeric Brun29f037d2014-04-25 19:05:36 +02006285 }
6286 else {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006287 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emeric Brun29f037d2014-04-25 19:05:36 +02006288 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
6289 else
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01006290 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun29f037d2014-04-25 19:05:36 +02006291 }
Lukas Tribus49799162019-07-08 14:29:15 +02006292#endif /* BoringSSL or LibreSSL */
Emeric Brun29f037d2014-04-25 19:05:36 +02006293 }
Willy Tarreau89230192012-09-28 20:22:13 +02006294 goto out_error;
6295 }
Emeric Brun46591952012-05-18 15:47:34 +02006296 else {
6297 /* Fail on all other handshake errors */
Willy Tarreau566dc552012-10-19 20:52:18 +02006298 /* Note: OpenSSL may leave unread bytes in the socket's
6299 * buffer, causing an RST to be emitted upon close() on
6300 * TCP sockets. We first try to drain possibly pending
6301 * data to avoid this as much as possible.
6302 */
Willy Tarreaud85c4852015-03-13 00:40:28 +01006303 conn_sock_drain(conn);
Willy Tarreau20879a02012-12-03 16:32:10 +01006304 if (!conn->err_code)
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006305 conn->err_code = (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT) ?
Willy Tarreauf51c6982014-04-25 20:02:39 +02006306 CO_ER_SSL_KILLED_HB : CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02006307 goto out_error;
6308 }
6309 }
Willy Tarreau5db847a2019-05-09 14:13:35 +02006310#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Olivier Houchard522eea72017-11-03 16:27:47 +01006311 else {
6312 /*
6313 * If the server refused the early data, we have to send a
6314 * 425 to the client, as we no longer have the data to sent
6315 * them again.
6316 */
6317 if ((conn->flags & CO_FL_EARLY_DATA) && (objt_server(conn->target))) {
Olivier Houchard66ab4982019-02-26 18:37:15 +01006318 if (SSL_get_early_data_status(ctx->ssl) == SSL_EARLY_DATA_REJECTED) {
Olivier Houchard522eea72017-11-03 16:27:47 +01006319 conn->err_code = CO_ER_SSL_EARLY_FAILED;
6320 goto out_error;
6321 }
6322 }
6323 }
6324#endif
6325
Emeric Brun46591952012-05-18 15:47:34 +02006326
Emeric Brun674b7432012-11-08 19:21:55 +01006327reneg_ok:
Emeric Brunb5e42a82017-06-06 12:35:14 +00006328
Willy Tarreau5db847a2019-05-09 14:13:35 +02006329#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00006330 /* ASYNC engine API doesn't support moving read/write
6331 * buffers. So we disable ASYNC mode right after
6332 * the handshake to avoid buffer oveflows.
6333 */
6334 if (global_ssl.async)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006335 SSL_clear_mode(ctx->ssl, SSL_MODE_ASYNC);
Emeric Brunb5e42a82017-06-06 12:35:14 +00006336#endif
Emeric Brun46591952012-05-18 15:47:34 +02006337 /* Handshake succeeded */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006338 if (!SSL_session_reused(ctx->ssl)) {
Willy Tarreau0c9c2722014-05-28 12:28:58 +02006339 if (objt_server(conn->target)) {
6340 update_freq_ctr(&global.ssl_be_keys_per_sec, 1);
6341 if (global.ssl_be_keys_per_sec.curr_ctr > global.ssl_be_keys_max)
6342 global.ssl_be_keys_max = global.ssl_be_keys_per_sec.curr_ctr;
Emeric Brun46591952012-05-18 15:47:34 +02006343 }
Willy Tarreau0c9c2722014-05-28 12:28:58 +02006344 else {
6345 update_freq_ctr(&global.ssl_fe_keys_per_sec, 1);
6346 if (global.ssl_fe_keys_per_sec.curr_ctr > global.ssl_fe_keys_max)
6347 global.ssl_fe_keys_max = global.ssl_fe_keys_per_sec.curr_ctr;
6348 }
Emeric Brun46591952012-05-18 15:47:34 +02006349 }
6350
6351 /* The connection is now established at both layers, it's time to leave */
6352 conn->flags &= ~(flag | CO_FL_WAIT_L4_CONN | CO_FL_WAIT_L6_CONN);
6353 return 1;
6354
6355 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01006356 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02006357 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01006358 ERR_clear_error();
6359
Emeric Brun9fa89732012-10-04 17:09:56 +02006360 /* free resumed session if exists */
Willy Tarreau07d94e42018-09-20 10:57:52 +02006361 if (objt_server(conn->target) && __objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr) {
6362 free(__objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr);
6363 __objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr = NULL;
Emeric Brun9fa89732012-10-04 17:09:56 +02006364 }
6365
Emeric Brun46591952012-05-18 15:47:34 +02006366 /* Fail on all other handshake errors */
6367 conn->flags |= CO_FL_ERROR;
Willy Tarreau20879a02012-12-03 16:32:10 +01006368 if (!conn->err_code)
6369 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02006370 return 0;
6371}
6372
Willy Tarreauee1a6fc2020-01-17 07:52:13 +01006373/* Called from the upper layer, to subscribe <es> to events <event_type>. The
6374 * event subscriber <es> is not allowed to change from a previous call as long
6375 * as at least one event is still subscribed. The <event_type> must only be a
6376 * combination of SUB_RETRY_RECV and SUB_RETRY_SEND. It always returns 0,
6377 * unless the transport layer was already released.
6378 */
6379static int ssl_subscribe(struct connection *conn, void *xprt_ctx, int event_type, struct wait_event *es)
Olivier Houcharddf357842019-03-21 16:30:07 +01006380{
Olivier Houchardea8dd942019-05-20 14:02:16 +02006381 struct ssl_sock_ctx *ctx = xprt_ctx;
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006382
Olivier Houchard0ff28652019-06-24 18:57:39 +02006383 if (!ctx)
6384 return -1;
6385
Willy Tarreau113d52b2020-01-10 09:20:26 +01006386 BUG_ON(event_type & ~(SUB_RETRY_SEND|SUB_RETRY_RECV));
6387 BUG_ON(ctx->subs && ctx->subs->events & event_type);
Willy Tarreauee1a6fc2020-01-17 07:52:13 +01006388 BUG_ON(ctx->subs && ctx->subs != es);
Olivier Houchardea8dd942019-05-20 14:02:16 +02006389
Willy Tarreauee1a6fc2020-01-17 07:52:13 +01006390 ctx->subs = es;
6391 es->events |= event_type;
Willy Tarreau113d52b2020-01-10 09:20:26 +01006392
6393 /* we may have to subscribe to lower layers for new events */
6394 event_type &= ~ctx->wait_event.events;
6395 if (event_type && !(conn->flags & CO_FL_SSL_WAIT_HS))
6396 ctx->xprt->subscribe(conn, ctx->xprt_ctx, event_type, &ctx->wait_event);
Olivier Houchardea8dd942019-05-20 14:02:16 +02006397 return 0;
Olivier Houcharddf357842019-03-21 16:30:07 +01006398}
6399
Willy Tarreauee1a6fc2020-01-17 07:52:13 +01006400/* Called from the upper layer, to unsubscribe <es> from events <event_type>.
6401 * The <es> pointer is not allowed to differ from the one passed to the
6402 * subscribe() call. It always returns zero.
6403 */
6404static int ssl_unsubscribe(struct connection *conn, void *xprt_ctx, int event_type, struct wait_event *es)
Olivier Houcharddf357842019-03-21 16:30:07 +01006405{
Olivier Houchardea8dd942019-05-20 14:02:16 +02006406 struct ssl_sock_ctx *ctx = xprt_ctx;
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006407
Willy Tarreau113d52b2020-01-10 09:20:26 +01006408 BUG_ON(event_type & ~(SUB_RETRY_SEND|SUB_RETRY_RECV));
Willy Tarreauee1a6fc2020-01-17 07:52:13 +01006409 BUG_ON(ctx->subs && ctx->subs != es);
Olivier Houchardea8dd942019-05-20 14:02:16 +02006410
Willy Tarreauee1a6fc2020-01-17 07:52:13 +01006411 es->events &= ~event_type;
6412 if (!es->events)
Willy Tarreau113d52b2020-01-10 09:20:26 +01006413 ctx->subs = NULL;
6414
6415 /* If we subscribed, and we're not doing the handshake,
6416 * then we subscribed because the upper layer asked for it,
6417 * as the upper layer is no longer interested, we can
6418 * unsubscribe too.
6419 */
6420 event_type &= ctx->wait_event.events;
6421 if (event_type && !(ctx->conn->flags & CO_FL_SSL_WAIT_HS))
6422 conn_unsubscribe(conn, ctx->xprt_ctx, event_type, &ctx->wait_event);
Olivier Houchardea8dd942019-05-20 14:02:16 +02006423
6424 return 0;
Olivier Houcharddf357842019-03-21 16:30:07 +01006425}
6426
Olivier Houchard2e055482019-05-27 19:50:12 +02006427/* Use the provided XPRT as an underlying XPRT, and provide the old one.
6428 * Returns 0 on success, and non-zero on failure.
6429 */
6430static 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)
6431{
6432 struct ssl_sock_ctx *ctx = xprt_ctx;
6433
6434 if (oldxprt_ops != NULL)
6435 *oldxprt_ops = ctx->xprt;
6436 if (oldxprt_ctx != NULL)
6437 *oldxprt_ctx = ctx->xprt_ctx;
6438 ctx->xprt = toadd_ops;
6439 ctx->xprt_ctx = toadd_ctx;
6440 return 0;
6441}
6442
Olivier Houchard5149b592019-05-23 17:47:36 +02006443/* Remove the specified xprt. If if it our underlying XPRT, remove it and
6444 * return 0, otherwise just call the remove_xprt method from the underlying
6445 * XPRT.
6446 */
6447static int ssl_remove_xprt(struct connection *conn, void *xprt_ctx, void *toremove_ctx, const struct xprt_ops *newops, void *newctx)
6448{
6449 struct ssl_sock_ctx *ctx = xprt_ctx;
6450
6451 if (ctx->xprt_ctx == toremove_ctx) {
6452 ctx->xprt_ctx = newctx;
6453 ctx->xprt = newops;
6454 return 0;
6455 }
6456 return (ctx->xprt->remove_xprt(conn, ctx->xprt_ctx, toremove_ctx, newops, newctx));
6457}
6458
Olivier Houchardea8dd942019-05-20 14:02:16 +02006459static struct task *ssl_sock_io_cb(struct task *t, void *context, unsigned short state)
6460{
6461 struct ssl_sock_ctx *ctx = context;
6462
6463 /* First if we're doing an handshake, try that */
6464 if (ctx->conn->flags & CO_FL_SSL_WAIT_HS)
6465 ssl_sock_handshake(ctx->conn, CO_FL_SSL_WAIT_HS);
6466 /* If we had an error, or the handshake is done and I/O is available,
6467 * let the upper layer know.
Olivier Houchard477902b2020-01-22 18:08:48 +01006468 * If no mux was set up yet, then call conn_create_mux()
Olivier Houchardea8dd942019-05-20 14:02:16 +02006469 * we can't be sure conn_fd_handler() will be called again.
6470 */
6471 if ((ctx->conn->flags & CO_FL_ERROR) ||
6472 !(ctx->conn->flags & CO_FL_SSL_WAIT_HS)) {
6473 int ret = 0;
6474 int woke = 0;
6475
6476 /* On error, wake any waiter */
Willy Tarreau113d52b2020-01-10 09:20:26 +01006477 if (ctx->subs) {
6478 tasklet_wakeup(ctx->subs->tasklet);
6479 ctx->subs->events = 0;
Olivier Houchardea8dd942019-05-20 14:02:16 +02006480 woke = 1;
Willy Tarreau113d52b2020-01-10 09:20:26 +01006481 ctx->subs = NULL;
Olivier Houchardea8dd942019-05-20 14:02:16 +02006482 }
Willy Tarreau113d52b2020-01-10 09:20:26 +01006483
Olivier Houchardea8dd942019-05-20 14:02:16 +02006484 /* If we're the first xprt for the connection, let the
Olivier Houchard477902b2020-01-22 18:08:48 +01006485 * upper layers know. If we have no mux, create it,
6486 * and once we have a mux, call its wake method if we didn't
6487 * woke a tasklet already.
Olivier Houchardea8dd942019-05-20 14:02:16 +02006488 */
6489 if (ctx->conn->xprt_ctx == ctx) {
Olivier Houchard477902b2020-01-22 18:08:48 +01006490 if (!ctx->conn->mux)
6491 ret = conn_create_mux(ctx->conn);
Olivier Houchardea8dd942019-05-20 14:02:16 +02006492 if (ret >= 0 && !woke && ctx->conn->mux && ctx->conn->mux->wake)
6493 ctx->conn->mux->wake(ctx->conn);
6494 return NULL;
6495 }
6496 }
Olivier Houchard54907bb2019-12-19 15:02:39 +01006497#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
6498 /* If we have early data and somebody wants to receive, let them */
Willy Tarreau113d52b2020-01-10 09:20:26 +01006499 else if (b_data(&ctx->early_buf) && ctx->subs &&
6500 ctx->subs->events & SUB_RETRY_RECV) {
6501 tasklet_wakeup(ctx->subs->tasklet);
6502 ctx->subs->events &= ~SUB_RETRY_RECV;
6503 if (!ctx->subs->events)
6504 ctx->subs = NULL;
Olivier Houchard54907bb2019-12-19 15:02:39 +01006505 }
6506#endif
Olivier Houchardea8dd942019-05-20 14:02:16 +02006507 return NULL;
6508}
6509
Emeric Brun46591952012-05-18 15:47:34 +02006510/* Receive up to <count> bytes from connection <conn>'s socket and store them
Willy Tarreauabf08d92014-01-14 11:31:27 +01006511 * into buffer <buf>. Only one call to recv() is performed, unless the
Emeric Brun46591952012-05-18 15:47:34 +02006512 * buffer wraps, in which case a second call may be performed. The connection's
6513 * flags are updated with whatever special event is detected (error, read0,
6514 * empty). The caller is responsible for taking care of those events and
6515 * avoiding the call if inappropriate. The function does not call the
6516 * connection's polling update function, so the caller is responsible for this.
6517 */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006518static 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 +02006519{
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006520 struct ssl_sock_ctx *ctx = xprt_ctx;
Willy Tarreaubfc4d772018-07-18 11:22:03 +02006521 ssize_t ret;
6522 size_t try, done = 0;
Emeric Brun46591952012-05-18 15:47:34 +02006523
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006524 if (!ctx)
Emeric Brun46591952012-05-18 15:47:34 +02006525 goto out_error;
6526
Olivier Houchard54907bb2019-12-19 15:02:39 +01006527#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
6528 if (b_data(&ctx->early_buf)) {
6529 try = b_contig_space(buf);
6530 if (try > b_data(&ctx->early_buf))
6531 try = b_data(&ctx->early_buf);
6532 memcpy(b_tail(buf), b_head(&ctx->early_buf), try);
6533 b_add(buf, try);
6534 b_del(&ctx->early_buf, try);
6535 if (b_data(&ctx->early_buf) == 0)
6536 b_free(&ctx->early_buf);
6537 return try;
6538 }
6539#endif
6540
Willy Tarreau911db9b2020-01-23 16:27:54 +01006541 if (conn->flags & (CO_FL_WAIT_XPRT | CO_FL_SSL_WAIT_HS))
Emeric Brun46591952012-05-18 15:47:34 +02006542 /* a handshake was requested */
6543 return 0;
6544
Emeric Brun46591952012-05-18 15:47:34 +02006545 /* read the largest possible block. For this, we perform only one call
6546 * to recv() unless the buffer wraps and we exactly fill the first hunk,
6547 * in which case we accept to do it once again. A new attempt is made on
6548 * EINTR too.
6549 */
Willy Tarreau00b0fb92014-01-17 11:09:40 +01006550 while (count > 0) {
Olivier Houchardc2aae742017-09-22 18:26:28 +02006551
Willy Tarreau591d4452018-06-15 17:21:00 +02006552 try = b_contig_space(buf);
6553 if (!try)
6554 break;
6555
Willy Tarreauabf08d92014-01-14 11:31:27 +01006556 if (try > count)
6557 try = count;
Willy Tarreau591d4452018-06-15 17:21:00 +02006558
Olivier Houchard66ab4982019-02-26 18:37:15 +01006559 ret = SSL_read(ctx->ssl, b_tail(buf), try);
Emmanuel Hocdetf967c312019-08-05 18:04:16 +02006560
Emeric Brune1f38db2012-09-03 20:36:47 +02006561 if (conn->flags & CO_FL_ERROR) {
6562 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01006563 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02006564 }
Emeric Brun46591952012-05-18 15:47:34 +02006565 if (ret > 0) {
Olivier Houchardacd14032018-06-28 18:17:23 +02006566 b_add(buf, ret);
Emeric Brun46591952012-05-18 15:47:34 +02006567 done += ret;
Emeric Brun46591952012-05-18 15:47:34 +02006568 count -= ret;
Emeric Brun46591952012-05-18 15:47:34 +02006569 }
Emeric Brun46591952012-05-18 15:47:34 +02006570 else {
Olivier Houchard66ab4982019-02-26 18:37:15 +01006571 ret = SSL_get_error(ctx->ssl, ret);
Emeric Brun46591952012-05-18 15:47:34 +02006572 if (ret == SSL_ERROR_WANT_WRITE) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01006573 /* handshake is running, and it needs to enable write */
Emeric Brun46591952012-05-18 15:47:34 +02006574 conn->flags |= CO_FL_SSL_WAIT_HS;
Olivier Houchardea8dd942019-05-20 14:02:16 +02006575 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_SEND, &ctx->wait_event);
Willy Tarreau5db847a2019-05-09 14:13:35 +02006576#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00006577 /* Async mode can be re-enabled, because we're leaving data state.*/
6578 if (global_ssl.async)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006579 SSL_set_mode(ctx->ssl, SSL_MODE_ASYNC);
Emeric Brunb5e42a82017-06-06 12:35:14 +00006580#endif
Emeric Brun46591952012-05-18 15:47:34 +02006581 break;
6582 }
6583 else if (ret == SSL_ERROR_WANT_READ) {
Olivier Houchard66ab4982019-02-26 18:37:15 +01006584 if (SSL_renegotiate_pending(ctx->ssl)) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02006585 ctx->xprt->subscribe(conn, ctx->xprt_ctx,
6586 SUB_RETRY_RECV,
6587 &ctx->wait_event);
Emeric Brun282a76a2012-11-08 18:02:56 +01006588 /* handshake is running, and it may need to re-enable read */
6589 conn->flags |= CO_FL_SSL_WAIT_HS;
Willy Tarreau5db847a2019-05-09 14:13:35 +02006590#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00006591 /* Async mode can be re-enabled, because we're leaving data state.*/
6592 if (global_ssl.async)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006593 SSL_set_mode(ctx->ssl, SSL_MODE_ASYNC);
Emeric Brunb5e42a82017-06-06 12:35:14 +00006594#endif
Emeric Brun282a76a2012-11-08 18:02:56 +01006595 break;
6596 }
Emeric Brun46591952012-05-18 15:47:34 +02006597 break;
Olivier Houchardc2aae742017-09-22 18:26:28 +02006598 } else if (ret == SSL_ERROR_ZERO_RETURN)
6599 goto read0;
Christopher Faulet4ac77a92018-02-19 14:25:15 +01006600 /* For SSL_ERROR_SYSCALL, make sure to clear the error
6601 * stack before shutting down the connection for
6602 * reading. */
Olivier Houchard7e2e5052018-02-13 15:17:23 +01006603 if (ret == SSL_ERROR_SYSCALL && (!errno || errno == EAGAIN))
6604 goto clear_ssl_error;
Emeric Brun46591952012-05-18 15:47:34 +02006605 /* otherwise it's a real error */
6606 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
Christopher Faulet4ac77a92018-02-19 14:25:15 +01006612 clear_ssl_error:
6613 /* Clear openssl global errors stack */
6614 ssl_sock_dump_errors(conn);
6615 ERR_clear_error();
Emeric Brun46591952012-05-18 15:47:34 +02006616 read0:
6617 conn_sock_read0(conn);
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02006618 goto leave;
Christopher Faulet4ac77a92018-02-19 14:25:15 +01006619
Emeric Brun46591952012-05-18 15:47:34 +02006620 out_error:
Olivier Houchard7e2e5052018-02-13 15:17:23 +01006621 conn->flags |= CO_FL_ERROR;
Emeric Brun644cde02012-12-14 11:21:13 +01006622 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02006623 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01006624 ERR_clear_error();
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02006625 goto leave;
Emeric Brun46591952012-05-18 15:47:34 +02006626}
6627
6628
Willy Tarreau787db9a2018-06-14 18:31:46 +02006629/* Send up to <count> pending bytes from buffer <buf> to connection <conn>'s
6630 * socket. <flags> may contain some CO_SFL_* flags to hint the system about
6631 * other pending data for example, but this flag is ignored at the moment.
Emeric Brun46591952012-05-18 15:47:34 +02006632 * Only one call to send() is performed, unless the buffer wraps, in which case
6633 * a second call may be performed. The connection's flags are updated with
6634 * whatever special event is detected (error, empty). The caller is responsible
6635 * for taking care of those events and avoiding the call if inappropriate. The
6636 * function does not call the connection's polling update function, so the caller
Willy Tarreau787db9a2018-06-14 18:31:46 +02006637 * is responsible for this. The buffer's output is not adjusted, it's up to the
6638 * caller to take care of this. It's up to the caller to update the buffer's
6639 * contents based on the return value.
Emeric Brun46591952012-05-18 15:47:34 +02006640 */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006641static 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 +02006642{
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006643 struct ssl_sock_ctx *ctx = xprt_ctx;
Willy Tarreau787db9a2018-06-14 18:31:46 +02006644 ssize_t ret;
6645 size_t try, done;
Emeric Brun46591952012-05-18 15:47:34 +02006646
6647 done = 0;
6648
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006649 if (!ctx)
Emeric Brun46591952012-05-18 15:47:34 +02006650 goto out_error;
6651
Willy Tarreau911db9b2020-01-23 16:27:54 +01006652 if (conn->flags & (CO_FL_WAIT_XPRT | CO_FL_SSL_WAIT_HS | CO_FL_EARLY_SSL_HS))
Emeric Brun46591952012-05-18 15:47:34 +02006653 /* a handshake was requested */
6654 return 0;
6655
6656 /* send the largest possible block. For this we perform only one call
6657 * to send() unless the buffer wraps and we exactly fill the first hunk,
6658 * in which case we accept to do it once again.
6659 */
Willy Tarreau787db9a2018-06-14 18:31:46 +02006660 while (count) {
Willy Tarreau5db847a2019-05-09 14:13:35 +02006661#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Olivier Houchardc2aae742017-09-22 18:26:28 +02006662 size_t written_data;
6663#endif
6664
Willy Tarreau787db9a2018-06-14 18:31:46 +02006665 try = b_contig_data(buf, done);
6666 if (try > count)
6667 try = count;
Willy Tarreaubfd59462013-02-21 07:46:09 +01006668
Willy Tarreau7bed9452014-02-02 02:00:24 +01006669 if (!(flags & CO_SFL_STREAMER) &&
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006670 !(ctx->xprt_st & SSL_SOCK_SEND_UNLIMITED) &&
Willy Tarreauef934602016-12-22 23:12:01 +01006671 global_ssl.max_record && try > global_ssl.max_record) {
6672 try = global_ssl.max_record;
Willy Tarreau518cedd2014-02-17 15:43:01 +01006673 }
6674 else {
6675 /* we need to keep the information about the fact that
6676 * we're not limiting the upcoming send(), because if it
6677 * fails, we'll have to retry with at least as many data.
6678 */
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006679 ctx->xprt_st |= SSL_SOCK_SEND_UNLIMITED;
Willy Tarreau518cedd2014-02-17 15:43:01 +01006680 }
Willy Tarreaubfd59462013-02-21 07:46:09 +01006681
Willy Tarreau5db847a2019-05-09 14:13:35 +02006682#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Olivier Houchard010941f2019-05-03 20:56:19 +02006683 if (!SSL_is_init_finished(ctx->ssl) && conn_is_back(conn)) {
Olivier Houchardc2aae742017-09-22 18:26:28 +02006684 unsigned int max_early;
6685
Olivier Houchard522eea72017-11-03 16:27:47 +01006686 if (objt_listener(conn->target))
Olivier Houchard66ab4982019-02-26 18:37:15 +01006687 max_early = SSL_get_max_early_data(ctx->ssl);
Olivier Houchard522eea72017-11-03 16:27:47 +01006688 else {
Olivier Houchard66ab4982019-02-26 18:37:15 +01006689 if (SSL_get0_session(ctx->ssl))
6690 max_early = SSL_SESSION_get_max_early_data(SSL_get0_session(ctx->ssl));
Olivier Houchard522eea72017-11-03 16:27:47 +01006691 else
6692 max_early = 0;
6693 }
6694
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006695 if (try + ctx->sent_early_data > max_early) {
6696 try -= (try + ctx->sent_early_data) - max_early;
Olivier Houchard522eea72017-11-03 16:27:47 +01006697 if (try <= 0) {
Olivier Houchard010941f2019-05-03 20:56:19 +02006698 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Olivier Houchard965e84e2019-06-15 20:59:30 +02006699 tasklet_wakeup(ctx->wait_event.tasklet);
Olivier Houchardc2aae742017-09-22 18:26:28 +02006700 break;
Olivier Houchard522eea72017-11-03 16:27:47 +01006701 }
Olivier Houchardc2aae742017-09-22 18:26:28 +02006702 }
Olivier Houchard66ab4982019-02-26 18:37:15 +01006703 ret = SSL_write_early_data(ctx->ssl, b_peek(buf, done), try, &written_data);
Olivier Houchardc2aae742017-09-22 18:26:28 +02006704 if (ret == 1) {
6705 ret = written_data;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006706 ctx->sent_early_data += ret;
Olivier Houchard965e84e2019-06-15 20:59:30 +02006707 if (objt_server(conn->target)) {
Olivier Houchard522eea72017-11-03 16:27:47 +01006708 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN | CO_FL_EARLY_DATA;
Olivier Houchard965e84e2019-06-15 20:59:30 +02006709 /* Initiate the handshake, now */
6710 tasklet_wakeup(ctx->wait_event.tasklet);
6711 }
Olivier Houchard522eea72017-11-03 16:27:47 +01006712
Olivier Houchardc2aae742017-09-22 18:26:28 +02006713 }
6714
6715 } else
6716#endif
Olivier Houchard66ab4982019-02-26 18:37:15 +01006717 ret = SSL_write(ctx->ssl, b_peek(buf, done), try);
Willy Tarreau518cedd2014-02-17 15:43:01 +01006718
Emeric Brune1f38db2012-09-03 20:36:47 +02006719 if (conn->flags & CO_FL_ERROR) {
6720 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01006721 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02006722 }
Emeric Brun46591952012-05-18 15:47:34 +02006723 if (ret > 0) {
Willy Tarreauc192b0a2020-01-23 09:11:58 +01006724 /* A send succeeded, so we can consider ourself connected */
6725 conn->flags &= ~CO_FL_WAIT_L4L6;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006726 ctx->xprt_st &= ~SSL_SOCK_SEND_UNLIMITED;
Willy Tarreau787db9a2018-06-14 18:31:46 +02006727 count -= ret;
Emeric Brun46591952012-05-18 15:47:34 +02006728 done += ret;
Emeric Brun46591952012-05-18 15:47:34 +02006729 }
6730 else {
Olivier Houchard66ab4982019-02-26 18:37:15 +01006731 ret = SSL_get_error(ctx->ssl, ret);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006732
Emeric Brun46591952012-05-18 15:47:34 +02006733 if (ret == SSL_ERROR_WANT_WRITE) {
Olivier Houchard66ab4982019-02-26 18:37:15 +01006734 if (SSL_renegotiate_pending(ctx->ssl)) {
Emeric Brun282a76a2012-11-08 18:02:56 +01006735 /* handshake is running, and it may need to re-enable write */
6736 conn->flags |= CO_FL_SSL_WAIT_HS;
Olivier Houchardea8dd942019-05-20 14:02:16 +02006737 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_SEND, &ctx->wait_event);
Willy Tarreau5db847a2019-05-09 14:13:35 +02006738#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00006739 /* Async mode can be re-enabled, because we're leaving data state.*/
6740 if (global_ssl.async)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006741 SSL_set_mode(ctx->ssl, SSL_MODE_ASYNC);
Emeric Brunb5e42a82017-06-06 12:35:14 +00006742#endif
Emeric Brun282a76a2012-11-08 18:02:56 +01006743 break;
6744 }
Olivier Houchardea8dd942019-05-20 14:02:16 +02006745
Emeric Brun46591952012-05-18 15:47:34 +02006746 break;
6747 }
6748 else if (ret == SSL_ERROR_WANT_READ) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01006749 /* handshake is running, and it needs to enable read */
Emeric Brun46591952012-05-18 15:47:34 +02006750 conn->flags |= CO_FL_SSL_WAIT_HS;
Olivier Houchardea8dd942019-05-20 14:02:16 +02006751 ctx->xprt->subscribe(conn, ctx->xprt_ctx,
6752 SUB_RETRY_RECV,
6753 &ctx->wait_event);
Willy Tarreau5db847a2019-05-09 14:13:35 +02006754#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00006755 /* Async mode can be re-enabled, because we're leaving data state.*/
6756 if (global_ssl.async)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006757 SSL_set_mode(ctx->ssl, SSL_MODE_ASYNC);
Emeric Brunb5e42a82017-06-06 12:35:14 +00006758#endif
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006759 break;
6760 }
Emeric Brun46591952012-05-18 15:47:34 +02006761 goto out_error;
6762 }
6763 }
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02006764 leave:
Emeric Brun46591952012-05-18 15:47:34 +02006765 return done;
6766
6767 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01006768 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02006769 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01006770 ERR_clear_error();
6771
Emeric Brun46591952012-05-18 15:47:34 +02006772 conn->flags |= CO_FL_ERROR;
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02006773 goto leave;
Emeric Brun46591952012-05-18 15:47:34 +02006774}
6775
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006776static void ssl_sock_close(struct connection *conn, void *xprt_ctx) {
Emeric Brun46591952012-05-18 15:47:34 +02006777
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006778 struct ssl_sock_ctx *ctx = xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006779
Olivier Houchardea8dd942019-05-20 14:02:16 +02006780
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006781 if (ctx) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02006782 if (ctx->wait_event.events != 0)
6783 ctx->xprt->unsubscribe(ctx->conn, ctx->xprt_ctx,
6784 ctx->wait_event.events,
6785 &ctx->wait_event);
Willy Tarreau113d52b2020-01-10 09:20:26 +01006786 if (ctx->subs) {
6787 ctx->subs->events = 0;
6788 tasklet_wakeup(ctx->subs->tasklet);
Olivier Houchardea8dd942019-05-20 14:02:16 +02006789 }
Willy Tarreau113d52b2020-01-10 09:20:26 +01006790
Olivier Houchard692c1d02019-05-23 18:41:47 +02006791 if (ctx->xprt->close)
6792 ctx->xprt->close(conn, ctx->xprt_ctx);
Willy Tarreau5db847a2019-05-09 14:13:35 +02006793#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brun3854e012017-05-17 20:42:48 +02006794 if (global_ssl.async) {
6795 OSSL_ASYNC_FD all_fd[32], afd;
6796 size_t num_all_fds = 0;
6797 int i;
6798
Olivier Houchard66ab4982019-02-26 18:37:15 +01006799 SSL_get_all_async_fds(ctx->ssl, NULL, &num_all_fds);
Emeric Brun3854e012017-05-17 20:42:48 +02006800 if (num_all_fds > 32) {
6801 send_log(NULL, LOG_EMERG, "haproxy: openssl returns too many async fds. It seems a bug. Process may crash\n");
6802 return;
6803 }
6804
Olivier Houchard66ab4982019-02-26 18:37:15 +01006805 SSL_get_all_async_fds(ctx->ssl, all_fd, &num_all_fds);
Emeric Brun3854e012017-05-17 20:42:48 +02006806
6807 /* If an async job is pending, we must try to
6808 to catch the end using polling before calling
6809 SSL_free */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006810 if (num_all_fds && SSL_waiting_for_async(ctx->ssl)) {
Emeric Brun3854e012017-05-17 20:42:48 +02006811 for (i=0 ; i < num_all_fds ; i++) {
6812 /* switch on an handler designed to
6813 * handle the SSL_free
6814 */
6815 afd = all_fd[i];
6816 fdtab[afd].iocb = ssl_async_fd_free;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006817 fdtab[afd].owner = ctx->ssl;
Emeric Brun3854e012017-05-17 20:42:48 +02006818 fd_want_recv(afd);
Emeric Brunce9e01c2017-05-31 10:02:53 +00006819 /* To ensure that the fd cache won't be used
6820 * and we'll catch a real RD event.
6821 */
6822 fd_cant_recv(afd);
Emeric Brun3854e012017-05-17 20:42:48 +02006823 }
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02006824 tasklet_free(ctx->wait_event.tasklet);
Olivier Houchard66ab4982019-02-26 18:37:15 +01006825 pool_free(ssl_sock_ctx_pool, ctx);
Olivier Houchard2be5a4c2019-03-08 18:54:43 +01006826 _HA_ATOMIC_ADD(&jobs, 1);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006827 return;
6828 }
Emeric Brun3854e012017-05-17 20:42:48 +02006829 /* Else we can remove the fds from the fdtab
6830 * and call SSL_free.
6831 * note: we do a fd_remove and not a delete
6832 * because the fd is owned by the engine.
6833 * the engine is responsible to close
6834 */
6835 for (i=0 ; i < num_all_fds ; i++)
6836 fd_remove(all_fd[i]);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006837 }
6838#endif
Olivier Houchard66ab4982019-02-26 18:37:15 +01006839 SSL_free(ctx->ssl);
Olivier Houchard54907bb2019-12-19 15:02:39 +01006840 b_free(&ctx->early_buf);
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02006841 tasklet_free(ctx->wait_event.tasklet);
Olivier Houchard66ab4982019-02-26 18:37:15 +01006842 pool_free(ssl_sock_ctx_pool, ctx);
Olivier Houchard2be5a4c2019-03-08 18:54:43 +01006843 _HA_ATOMIC_SUB(&sslconns, 1);
Emeric Brun46591952012-05-18 15:47:34 +02006844 }
Emeric Brun46591952012-05-18 15:47:34 +02006845}
6846
6847/* This function tries to perform a clean shutdown on an SSL connection, and in
6848 * any case, flags the connection as reusable if no handshake was in progress.
6849 */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006850static void ssl_sock_shutw(struct connection *conn, void *xprt_ctx, int clean)
Emeric Brun46591952012-05-18 15:47:34 +02006851{
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006852 struct ssl_sock_ctx *ctx = xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006853
Willy Tarreau911db9b2020-01-23 16:27:54 +01006854 if (conn->flags & (CO_FL_WAIT_XPRT | CO_FL_SSL_WAIT_HS))
Emeric Brun46591952012-05-18 15:47:34 +02006855 return;
Emmanuel Hocdet405ff312017-01-08 14:07:39 +01006856 if (!clean)
6857 /* don't sent notify on SSL_shutdown */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006858 SSL_set_quiet_shutdown(ctx->ssl, 1);
Emeric Brun46591952012-05-18 15:47:34 +02006859 /* no handshake was in progress, try a clean ssl shutdown */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006860 if (SSL_shutdown(ctx->ssl) <= 0) {
Emeric Brun644cde02012-12-14 11:21:13 +01006861 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02006862 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01006863 ERR_clear_error();
6864 }
Emeric Brun46591952012-05-18 15:47:34 +02006865}
6866
William Lallemandd4f946c2019-12-05 10:26:40 +01006867/* fill a buffer with the algorithm and size of a public key */
6868static int cert_get_pkey_algo(X509 *crt, struct buffer *out)
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01006869{
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01006870 int bits = 0;
6871 int sig = TLSEXT_signature_anonymous;
6872 int len = -1;
Emmanuel Hocdetc3775d22019-11-04 18:19:32 +01006873 EVP_PKEY *pkey;
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01006874
Emmanuel Hocdetc3775d22019-11-04 18:19:32 +01006875 pkey = X509_get_pubkey(crt);
6876 if (pkey) {
6877 bits = EVP_PKEY_bits(pkey);
6878 switch(EVP_PKEY_base_id(pkey)) {
6879 case EVP_PKEY_RSA:
6880 sig = TLSEXT_signature_rsa;
6881 break;
6882 case EVP_PKEY_EC:
6883 sig = TLSEXT_signature_ecdsa;
6884 break;
6885 case EVP_PKEY_DSA:
6886 sig = TLSEXT_signature_dsa;
6887 break;
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01006888 }
Emmanuel Hocdetc3775d22019-11-04 18:19:32 +01006889 EVP_PKEY_free(pkey);
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01006890 }
6891
6892 switch(sig) {
6893 case TLSEXT_signature_rsa:
6894 len = chunk_printf(out, "RSA%d", bits);
6895 break;
6896 case TLSEXT_signature_ecdsa:
6897 len = chunk_printf(out, "EC%d", bits);
6898 break;
6899 case TLSEXT_signature_dsa:
6900 len = chunk_printf(out, "DSA%d", bits);
6901 break;
6902 default:
6903 return 0;
6904 }
6905 if (len < 0)
6906 return 0;
6907 return 1;
6908}
6909
William Lallemandd4f946c2019-12-05 10:26:40 +01006910/* used for ppv2 pkey alog (can be used for logging) */
6911int ssl_sock_get_pkey_algo(struct connection *conn, struct buffer *out)
6912{
6913 struct ssl_sock_ctx *ctx;
6914 X509 *crt;
6915
6916 if (!ssl_sock_is_ssl(conn))
6917 return 0;
6918
6919 ctx = conn->xprt_ctx;
6920
6921 crt = SSL_get_certificate(ctx->ssl);
6922 if (!crt)
6923 return 0;
6924
6925 return cert_get_pkey_algo(crt, out);
6926}
6927
Emmanuel Hocdet283e0042017-11-02 14:05:23 +01006928/* used for ppv2 cert signature (can be used for logging) */
6929const char *ssl_sock_get_cert_sig(struct connection *conn)
6930{
Christopher Faulet82004142019-09-10 10:12:03 +02006931 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006932
Emmanuel Hocdet283e0042017-11-02 14:05:23 +01006933 __OPENSSL_110_CONST__ ASN1_OBJECT *algorithm;
6934 X509 *crt;
6935
6936 if (!ssl_sock_is_ssl(conn))
6937 return NULL;
Christopher Faulet82004142019-09-10 10:12:03 +02006938 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006939 crt = SSL_get_certificate(ctx->ssl);
Emmanuel Hocdet283e0042017-11-02 14:05:23 +01006940 if (!crt)
6941 return NULL;
6942 X509_ALGOR_get0(&algorithm, NULL, NULL, X509_get0_tbs_sigalg(crt));
6943 return OBJ_nid2sn(OBJ_obj2nid(algorithm));
6944}
6945
Emmanuel Hocdet253c3b72018-02-01 18:29:59 +01006946/* used for ppv2 authority */
6947const char *ssl_sock_get_sni(struct connection *conn)
6948{
6949#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Christopher Faulet82004142019-09-10 10:12:03 +02006950 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006951
Emmanuel Hocdet253c3b72018-02-01 18:29:59 +01006952 if (!ssl_sock_is_ssl(conn))
6953 return NULL;
Christopher Faulet82004142019-09-10 10:12:03 +02006954 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006955 return SSL_get_servername(ctx->ssl, TLSEXT_NAMETYPE_host_name);
Emmanuel Hocdet253c3b72018-02-01 18:29:59 +01006956#else
Olivier Houchard66ab4982019-02-26 18:37:15 +01006957 return NULL;
Emmanuel Hocdet253c3b72018-02-01 18:29:59 +01006958#endif
6959}
6960
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02006961/* used for logging/ppv2, may be changed for a sample fetch later */
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02006962const char *ssl_sock_get_cipher_name(struct connection *conn)
6963{
Christopher Faulet82004142019-09-10 10:12:03 +02006964 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006965
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02006966 if (!ssl_sock_is_ssl(conn))
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02006967 return NULL;
Christopher Faulet82004142019-09-10 10:12:03 +02006968 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006969 return SSL_get_cipher_name(ctx->ssl);
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02006970}
6971
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02006972/* used for logging/ppv2, may be changed for a sample fetch later */
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02006973const char *ssl_sock_get_proto_version(struct connection *conn)
6974{
Christopher Faulet82004142019-09-10 10:12:03 +02006975 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006976
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02006977 if (!ssl_sock_is_ssl(conn))
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02006978 return NULL;
Christopher Faulet82004142019-09-10 10:12:03 +02006979 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006980 return SSL_get_version(ctx->ssl);
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02006981}
6982
Willy Tarreau8d598402012-10-22 17:58:39 +02006983/* Extract a serial from a cert, and copy it to a chunk.
6984 * Returns 1 if serial is found and copied, 0 if no serial found and
6985 * -1 if output is not large enough.
6986 */
6987static int
Willy Tarreau83061a82018-07-13 11:56:34 +02006988ssl_sock_get_serial(X509 *crt, struct buffer *out)
Willy Tarreau8d598402012-10-22 17:58:39 +02006989{
6990 ASN1_INTEGER *serial;
6991
6992 serial = X509_get_serialNumber(crt);
6993 if (!serial)
6994 return 0;
6995
6996 if (out->size < serial->length)
6997 return -1;
6998
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006999 memcpy(out->area, serial->data, serial->length);
7000 out->data = serial->length;
Willy Tarreau8d598402012-10-22 17:58:39 +02007001 return 1;
7002}
7003
Emeric Brun43e79582014-10-29 19:03:26 +01007004/* Extract a cert to der, and copy it to a chunk.
Joseph Herlant017b3da2018-11-15 09:07:59 -08007005 * Returns 1 if the cert is found and copied, 0 on der conversion failure
7006 * and -1 if the output is not large enough.
Emeric Brun43e79582014-10-29 19:03:26 +01007007 */
7008static int
Willy Tarreau83061a82018-07-13 11:56:34 +02007009ssl_sock_crt2der(X509 *crt, struct buffer *out)
Emeric Brun43e79582014-10-29 19:03:26 +01007010{
7011 int len;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007012 unsigned char *p = (unsigned char *) out->area;;
Emeric Brun43e79582014-10-29 19:03:26 +01007013
7014 len =i2d_X509(crt, NULL);
7015 if (len <= 0)
7016 return 1;
7017
7018 if (out->size < len)
7019 return -1;
7020
7021 i2d_X509(crt,&p);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007022 out->data = len;
Emeric Brun43e79582014-10-29 19:03:26 +01007023 return 1;
7024}
7025
Emeric Brunce5ad802012-10-22 14:11:22 +02007026
Willy Tarreau83061a82018-07-13 11:56:34 +02007027/* Copy Date in ASN1_UTCTIME format in struct buffer out.
Emeric Brunce5ad802012-10-22 14:11:22 +02007028 * Returns 1 if serial is found and copied, 0 if no valid time found
7029 * and -1 if output is not large enough.
7030 */
7031static int
Willy Tarreau83061a82018-07-13 11:56:34 +02007032ssl_sock_get_time(ASN1_TIME *tm, struct buffer *out)
Emeric Brunce5ad802012-10-22 14:11:22 +02007033{
7034 if (tm->type == V_ASN1_GENERALIZEDTIME) {
7035 ASN1_GENERALIZEDTIME *gentm = (ASN1_GENERALIZEDTIME *)tm;
7036
7037 if (gentm->length < 12)
7038 return 0;
7039 if (gentm->data[0] != 0x32 || gentm->data[1] != 0x30)
7040 return 0;
7041 if (out->size < gentm->length-2)
7042 return -1;
7043
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007044 memcpy(out->area, gentm->data+2, gentm->length-2);
7045 out->data = gentm->length-2;
Emeric Brunce5ad802012-10-22 14:11:22 +02007046 return 1;
7047 }
7048 else if (tm->type == V_ASN1_UTCTIME) {
7049 ASN1_UTCTIME *utctm = (ASN1_UTCTIME *)tm;
7050
7051 if (utctm->length < 10)
7052 return 0;
7053 if (utctm->data[0] >= 0x35)
7054 return 0;
7055 if (out->size < utctm->length)
7056 return -1;
7057
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007058 memcpy(out->area, utctm->data, utctm->length);
7059 out->data = utctm->length;
Emeric Brunce5ad802012-10-22 14:11:22 +02007060 return 1;
7061 }
7062
7063 return 0;
7064}
7065
Emeric Brun87855892012-10-17 17:39:35 +02007066/* Extract an entry from a X509_NAME and copy its value to an output chunk.
7067 * Returns 1 if entry found, 0 if entry not found, or -1 if output not large enough.
7068 */
7069static int
Willy Tarreau83061a82018-07-13 11:56:34 +02007070ssl_sock_get_dn_entry(X509_NAME *a, const struct buffer *entry, int pos,
7071 struct buffer *out)
Emeric Brun87855892012-10-17 17:39:35 +02007072{
7073 X509_NAME_ENTRY *ne;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007074 ASN1_OBJECT *obj;
7075 ASN1_STRING *data;
7076 const unsigned char *data_ptr;
7077 int data_len;
Emeric Brun87855892012-10-17 17:39:35 +02007078 int i, j, n;
7079 int cur = 0;
7080 const char *s;
7081 char tmp[128];
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007082 int name_count;
7083
7084 name_count = X509_NAME_entry_count(a);
Emeric Brun87855892012-10-17 17:39:35 +02007085
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007086 out->data = 0;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007087 for (i = 0; i < name_count; i++) {
Emeric Brun87855892012-10-17 17:39:35 +02007088 if (pos < 0)
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007089 j = (name_count-1) - i;
Emeric Brun87855892012-10-17 17:39:35 +02007090 else
7091 j = i;
7092
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007093 ne = X509_NAME_get_entry(a, j);
7094 obj = X509_NAME_ENTRY_get_object(ne);
7095 data = X509_NAME_ENTRY_get_data(ne);
7096 data_ptr = ASN1_STRING_get0_data(data);
7097 data_len = ASN1_STRING_length(data);
7098 n = OBJ_obj2nid(obj);
Emeric Brun87855892012-10-17 17:39:35 +02007099 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007100 i2t_ASN1_OBJECT(tmp, sizeof(tmp), obj);
Emeric Brun87855892012-10-17 17:39:35 +02007101 s = tmp;
7102 }
7103
7104 if (chunk_strcasecmp(entry, s) != 0)
7105 continue;
7106
7107 if (pos < 0)
7108 cur--;
7109 else
7110 cur++;
7111
7112 if (cur != pos)
7113 continue;
7114
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007115 if (data_len > out->size)
Emeric Brun87855892012-10-17 17:39:35 +02007116 return -1;
7117
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007118 memcpy(out->area, data_ptr, data_len);
7119 out->data = data_len;
Emeric Brun87855892012-10-17 17:39:35 +02007120 return 1;
7121 }
7122
7123 return 0;
7124
William Lallemandd4f946c2019-12-05 10:26:40 +01007125}
7126
7127/*
7128 * Extract and format the DNS SAN extensions and copy result into a chuink
7129 * Return 0;
7130 */
7131#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
7132static int ssl_sock_get_san_oneline(X509 *cert, struct buffer *out)
7133{
7134 int i;
7135 char *str;
7136 STACK_OF(GENERAL_NAME) *names = NULL;
7137
7138 names = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
7139 if (names) {
7140 for (i = 0; i < sk_GENERAL_NAME_num(names); i++) {
7141 GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i);
7142 if (i > 0)
7143 chunk_appendf(out, ", ");
7144 if (name->type == GEN_DNS) {
7145 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
7146 chunk_appendf(out, "DNS:%s", str);
7147 OPENSSL_free(str);
7148 }
7149 }
7150 }
7151 sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
7152 }
7153 return 0;
Emeric Brun87855892012-10-17 17:39:35 +02007154}
William Lallemandd4f946c2019-12-05 10:26:40 +01007155#endif
Emeric Brun87855892012-10-17 17:39:35 +02007156
Elliot Otchet71f82972020-01-15 08:12:14 -05007157/*
7158 * Extract the DN in the specified format from the X509_NAME and copy result to a chunk.
7159 * Currently supports rfc2253 for returning LDAP V3 DNs.
7160 * Returns 1 if dn entries exist, 0 if no dn entry was found.
7161 */
7162static int
7163ssl_sock_get_dn_formatted(X509_NAME *a, const struct buffer *format, struct buffer *out)
7164{
7165 BIO *bio = NULL;
7166 int ret = 0;
7167 int data_len = 0;
7168
7169 if (chunk_strcmp(format, "rfc2253") == 0) {
7170 bio = BIO_new(BIO_s_mem());
7171 if (bio == NULL)
7172 goto out;
7173
7174 if (X509_NAME_print_ex(bio, a, 0, XN_FLAG_RFC2253) < 0)
7175 goto out;
7176
7177 if ((data_len = BIO_read(bio, out->area, out->size)) <= 0)
7178 goto out;
7179
7180 out->data = data_len;
7181
7182 ret = 1;
7183 }
7184out:
7185 if (bio)
7186 BIO_free(bio);
7187 return ret;
7188}
7189
Emeric Brun87855892012-10-17 17:39:35 +02007190/* Extract and format full DN from a X509_NAME and copy result into a chunk
7191 * Returns 1 if dn entries exits, 0 if no dn entry found or -1 if output is not large enough.
7192 */
7193static int
Willy Tarreau83061a82018-07-13 11:56:34 +02007194ssl_sock_get_dn_oneline(X509_NAME *a, struct buffer *out)
Emeric Brun87855892012-10-17 17:39:35 +02007195{
7196 X509_NAME_ENTRY *ne;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007197 ASN1_OBJECT *obj;
7198 ASN1_STRING *data;
7199 const unsigned char *data_ptr;
7200 int data_len;
Emeric Brun87855892012-10-17 17:39:35 +02007201 int i, n, ln;
7202 int l = 0;
7203 const char *s;
7204 char *p;
7205 char tmp[128];
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007206 int name_count;
7207
7208
7209 name_count = X509_NAME_entry_count(a);
Emeric Brun87855892012-10-17 17:39:35 +02007210
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007211 out->data = 0;
7212 p = out->area;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007213 for (i = 0; i < name_count; i++) {
7214 ne = X509_NAME_get_entry(a, i);
7215 obj = X509_NAME_ENTRY_get_object(ne);
7216 data = X509_NAME_ENTRY_get_data(ne);
7217 data_ptr = ASN1_STRING_get0_data(data);
7218 data_len = ASN1_STRING_length(data);
7219 n = OBJ_obj2nid(obj);
Emeric Brun87855892012-10-17 17:39:35 +02007220 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007221 i2t_ASN1_OBJECT(tmp, sizeof(tmp), obj);
Emeric Brun87855892012-10-17 17:39:35 +02007222 s = tmp;
7223 }
7224 ln = strlen(s);
7225
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007226 l += 1 + ln + 1 + data_len;
Emeric Brun87855892012-10-17 17:39:35 +02007227 if (l > out->size)
7228 return -1;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007229 out->data = l;
Emeric Brun87855892012-10-17 17:39:35 +02007230
7231 *(p++)='/';
7232 memcpy(p, s, ln);
7233 p += ln;
7234 *(p++)='=';
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007235 memcpy(p, data_ptr, data_len);
7236 p += data_len;
Emeric Brun87855892012-10-17 17:39:35 +02007237 }
7238
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007239 if (!out->data)
Emeric Brun87855892012-10-17 17:39:35 +02007240 return 0;
7241
7242 return 1;
7243}
7244
Olivier Houchardab28a322018-12-21 19:45:40 +01007245void ssl_sock_set_alpn(struct connection *conn, const unsigned char *alpn, int len)
7246{
7247#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Christopher Faulet82004142019-09-10 10:12:03 +02007248 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007249
Olivier Houcharde488ea82019-06-28 14:10:33 +02007250 if (!ssl_sock_is_ssl(conn))
7251 return;
Christopher Faulet82004142019-09-10 10:12:03 +02007252 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007253 SSL_set_alpn_protos(ctx->ssl, alpn, len);
Olivier Houchardab28a322018-12-21 19:45:40 +01007254#endif
7255}
7256
Willy Tarreau119a4082016-12-22 21:58:38 +01007257/* Sets advertised SNI for outgoing connections. Please set <hostname> to NULL
7258 * to disable SNI.
7259 */
Willy Tarreau63076412015-07-10 11:33:32 +02007260void ssl_sock_set_servername(struct connection *conn, const char *hostname)
7261{
7262#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Christopher Faulet82004142019-09-10 10:12:03 +02007263 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007264
Willy Tarreau119a4082016-12-22 21:58:38 +01007265 char *prev_name;
7266
Willy Tarreau63076412015-07-10 11:33:32 +02007267 if (!ssl_sock_is_ssl(conn))
7268 return;
Christopher Faulet82004142019-09-10 10:12:03 +02007269 ctx = conn->xprt_ctx;
Willy Tarreau63076412015-07-10 11:33:32 +02007270
Willy Tarreau119a4082016-12-22 21:58:38 +01007271 /* if the SNI changes, we must destroy the reusable context so that a
7272 * new connection will present a new SNI. As an optimization we could
7273 * later imagine having a small cache of ssl_ctx to hold a few SNI per
7274 * server.
7275 */
Olivier Houchard66ab4982019-02-26 18:37:15 +01007276 prev_name = (char *)SSL_get_servername(ctx->ssl, TLSEXT_NAMETYPE_host_name);
Willy Tarreau119a4082016-12-22 21:58:38 +01007277 if ((!prev_name && hostname) ||
7278 (prev_name && (!hostname || strcmp(hostname, prev_name) != 0)))
Olivier Houchard66ab4982019-02-26 18:37:15 +01007279 SSL_set_session(ctx->ssl, NULL);
Willy Tarreau119a4082016-12-22 21:58:38 +01007280
Olivier Houchard66ab4982019-02-26 18:37:15 +01007281 SSL_set_tlsext_host_name(ctx->ssl, hostname);
Willy Tarreau63076412015-07-10 11:33:32 +02007282#endif
7283}
7284
Emeric Brun0abf8362014-06-24 18:26:41 +02007285/* Extract peer certificate's common name into the chunk dest
7286 * Returns
7287 * the len of the extracted common name
7288 * or 0 if no CN found in DN
7289 * or -1 on error case (i.e. no peer certificate)
7290 */
Willy Tarreau83061a82018-07-13 11:56:34 +02007291int ssl_sock_get_remote_common_name(struct connection *conn,
7292 struct buffer *dest)
David Safb76832014-05-08 23:42:08 -04007293{
Christopher Faulet82004142019-09-10 10:12:03 +02007294 struct ssl_sock_ctx *ctx;
David Safb76832014-05-08 23:42:08 -04007295 X509 *crt = NULL;
7296 X509_NAME *name;
David Safb76832014-05-08 23:42:08 -04007297 const char find_cn[] = "CN";
Willy Tarreau83061a82018-07-13 11:56:34 +02007298 const struct buffer find_cn_chunk = {
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007299 .area = (char *)&find_cn,
7300 .data = sizeof(find_cn)-1
David Safb76832014-05-08 23:42:08 -04007301 };
Emeric Brun0abf8362014-06-24 18:26:41 +02007302 int result = -1;
David Safb76832014-05-08 23:42:08 -04007303
7304 if (!ssl_sock_is_ssl(conn))
Emeric Brun0abf8362014-06-24 18:26:41 +02007305 goto out;
Christopher Faulet82004142019-09-10 10:12:03 +02007306 ctx = conn->xprt_ctx;
David Safb76832014-05-08 23:42:08 -04007307
7308 /* SSL_get_peer_certificate, it increase X509 * ref count */
Olivier Houchard66ab4982019-02-26 18:37:15 +01007309 crt = SSL_get_peer_certificate(ctx->ssl);
David Safb76832014-05-08 23:42:08 -04007310 if (!crt)
7311 goto out;
7312
7313 name = X509_get_subject_name(crt);
7314 if (!name)
7315 goto out;
David Safb76832014-05-08 23:42:08 -04007316
Emeric Brun0abf8362014-06-24 18:26:41 +02007317 result = ssl_sock_get_dn_entry(name, &find_cn_chunk, 1, dest);
7318out:
David Safb76832014-05-08 23:42:08 -04007319 if (crt)
7320 X509_free(crt);
7321
7322 return result;
7323}
7324
Dave McCowan328fb582014-07-30 10:39:13 -04007325/* returns 1 if client passed a certificate for this session, 0 if not */
7326int ssl_sock_get_cert_used_sess(struct connection *conn)
7327{
Christopher Faulet82004142019-09-10 10:12:03 +02007328 struct ssl_sock_ctx *ctx;
Dave McCowan328fb582014-07-30 10:39:13 -04007329 X509 *crt = NULL;
7330
7331 if (!ssl_sock_is_ssl(conn))
7332 return 0;
Christopher Faulet82004142019-09-10 10:12:03 +02007333 ctx = conn->xprt_ctx;
Dave McCowan328fb582014-07-30 10:39:13 -04007334
7335 /* SSL_get_peer_certificate, it increase X509 * ref count */
Olivier Houchard66ab4982019-02-26 18:37:15 +01007336 crt = SSL_get_peer_certificate(ctx->ssl);
Dave McCowan328fb582014-07-30 10:39:13 -04007337 if (!crt)
7338 return 0;
7339
7340 X509_free(crt);
7341 return 1;
7342}
7343
7344/* returns 1 if client passed a certificate for this connection, 0 if not */
7345int ssl_sock_get_cert_used_conn(struct connection *conn)
David Safb76832014-05-08 23:42:08 -04007346{
Christopher Faulet82004142019-09-10 10:12:03 +02007347 struct ssl_sock_ctx *ctx;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007348
David Safb76832014-05-08 23:42:08 -04007349 if (!ssl_sock_is_ssl(conn))
7350 return 0;
Christopher Faulet82004142019-09-10 10:12:03 +02007351 ctx = conn->xprt_ctx;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007352 return SSL_SOCK_ST_FL_VERIFY_DONE & ctx->xprt_st ? 1 : 0;
David Safb76832014-05-08 23:42:08 -04007353}
7354
7355/* returns result from SSL verify */
7356unsigned int ssl_sock_get_verify_result(struct connection *conn)
7357{
Christopher Faulet82004142019-09-10 10:12:03 +02007358 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007359
David Safb76832014-05-08 23:42:08 -04007360 if (!ssl_sock_is_ssl(conn))
7361 return (unsigned int)X509_V_ERR_APPLICATION_VERIFICATION;
Christopher Faulet82004142019-09-10 10:12:03 +02007362 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007363 return (unsigned int)SSL_get_verify_result(ctx->ssl);
David Safb76832014-05-08 23:42:08 -04007364}
7365
Willy Tarreau8743f7e2016-12-04 18:44:29 +01007366/* Returns the application layer protocol name in <str> and <len> when known.
7367 * Zero is returned if the protocol name was not found, otherwise non-zero is
7368 * returned. The string is allocated in the SSL context and doesn't have to be
7369 * freed by the caller. NPN is also checked if available since older versions
7370 * of openssl (1.0.1) which are more common in field only support this one.
7371 */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01007372static int ssl_sock_get_alpn(const struct connection *conn, void *xprt_ctx, const char **str, int *len)
Willy Tarreau8743f7e2016-12-04 18:44:29 +01007373{
Olivier Houchard66ab4982019-02-26 18:37:15 +01007374#if defined(TLSEXT_TYPE_application_layer_protocol_negotiation) || \
7375 defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Olivier Houcharde179d0e2019-03-21 18:27:17 +01007376 struct ssl_sock_ctx *ctx = xprt_ctx;
7377 if (!ctx)
Willy Tarreau8743f7e2016-12-04 18:44:29 +01007378 return 0;
7379
7380 *str = NULL;
7381
7382#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Olivier Houchard66ab4982019-02-26 18:37:15 +01007383 SSL_get0_alpn_selected(ctx->ssl, (const unsigned char **)str, (unsigned *)len);
Willy Tarreau8743f7e2016-12-04 18:44:29 +01007384 if (*str)
7385 return 1;
7386#endif
Bernard Spil13c53f82018-02-15 13:34:58 +01007387#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007388 SSL_get0_next_proto_negotiated(ctx->ssl, (const unsigned char **)str, (unsigned *)len);
Willy Tarreau8743f7e2016-12-04 18:44:29 +01007389 if (*str)
7390 return 1;
7391#endif
Olivier Houcharde179d0e2019-03-21 18:27:17 +01007392#endif
Willy Tarreau8743f7e2016-12-04 18:44:29 +01007393 return 0;
7394}
7395
Willy Tarreau7875d092012-09-10 08:20:03 +02007396/***** Below are some sample fetching functions for ACL/patterns *****/
7397
Olivier Houchardccaa7de2017-10-02 11:51:03 +02007398static int
7399smp_fetch_ssl_fc_has_early(const struct arg *args, struct sample *smp, const char *kw, void *private)
7400{
7401 struct connection *conn;
7402
7403 conn = objt_conn(smp->sess->origin);
7404 if (!conn || conn->xprt != &ssl_sock)
7405 return 0;
7406
7407 smp->flags = 0;
7408 smp->data.type = SMP_T_BOOL;
Emmanuel Hocdetc9858012019-08-07 14:44:49 +02007409#ifdef OPENSSL_IS_BORINGSSL
7410 {
7411 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
7412 smp->data.u.sint = (SSL_in_early_data(ctx->ssl) &&
7413 SSL_early_data_accepted(ctx->ssl));
7414 }
7415#else
Olivier Houchard25ae45a2017-11-29 19:51:19 +01007416 smp->data.u.sint = ((conn->flags & CO_FL_EARLY_DATA) &&
Olivier Houchard220a26c2020-01-23 14:57:36 +01007417 (conn->flags & (CO_FL_EARLY_SSL_HS | CO_FL_SSL_WAIT_HS))) ? 1 : 0;
Emmanuel Hocdetc9858012019-08-07 14:44:49 +02007418#endif
Olivier Houchardccaa7de2017-10-02 11:51:03 +02007419 return 1;
7420}
7421
Emeric Brune64aef12012-09-21 13:15:06 +02007422/* boolean, returns true if client cert was present */
7423static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007424smp_fetch_ssl_fc_has_crt(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brune64aef12012-09-21 13:15:06 +02007425{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007426 struct connection *conn;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007427 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007428
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007429 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007430 if (!conn || conn->xprt != &ssl_sock)
Emeric Brune64aef12012-09-21 13:15:06 +02007431 return 0;
7432
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007433 ctx = conn->xprt_ctx;
7434
Willy Tarreau911db9b2020-01-23 16:27:54 +01007435 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Brune64aef12012-09-21 13:15:06 +02007436 smp->flags |= SMP_F_MAY_CHANGE;
7437 return 0;
7438 }
7439
7440 smp->flags = 0;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007441 smp->data.type = SMP_T_BOOL;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007442 smp->data.u.sint = SSL_SOCK_ST_FL_VERIFY_DONE & ctx->xprt_st ? 1 : 0;
Emeric Brune64aef12012-09-21 13:15:06 +02007443
7444 return 1;
7445}
7446
Emeric Brun43e79582014-10-29 19:03:26 +01007447/* binary, returns a certificate in a binary chunk (der/raw).
7448 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7449 * should be use.
7450 */
7451static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007452smp_fetch_ssl_x_der(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun43e79582014-10-29 19:03:26 +01007453{
7454 int cert_peer = (kw[4] == 'c') ? 1 : 0;
7455 X509 *crt = NULL;
7456 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02007457 struct buffer *smp_trash;
Emeric Brun43e79582014-10-29 19:03:26 +01007458 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007459 struct ssl_sock_ctx *ctx;
Emeric Brun43e79582014-10-29 19:03:26 +01007460
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007461 conn = objt_conn(smp->sess->origin);
Emeric Brun43e79582014-10-29 19:03:26 +01007462 if (!conn || conn->xprt != &ssl_sock)
7463 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007464 ctx = conn->xprt_ctx;
Emeric Brun43e79582014-10-29 19:03:26 +01007465
Willy Tarreau911db9b2020-01-23 16:27:54 +01007466 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Brun43e79582014-10-29 19:03:26 +01007467 smp->flags |= SMP_F_MAY_CHANGE;
7468 return 0;
7469 }
7470
7471 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007472 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brun43e79582014-10-29 19:03:26 +01007473 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007474 crt = SSL_get_certificate(ctx->ssl);
Emeric Brun43e79582014-10-29 19:03:26 +01007475
7476 if (!crt)
7477 goto out;
7478
7479 smp_trash = get_trash_chunk();
7480 if (ssl_sock_crt2der(crt, smp_trash) <= 0)
7481 goto out;
7482
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007483 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007484 smp->data.type = SMP_T_BIN;
Emeric Brun43e79582014-10-29 19:03:26 +01007485 ret = 1;
7486out:
7487 /* SSL_get_peer_certificate, it increase X509 * ref count */
7488 if (cert_peer && crt)
7489 X509_free(crt);
7490 return ret;
7491}
7492
Emeric Brunba841a12014-04-30 17:05:08 +02007493/* binary, returns serial of certificate in a binary chunk.
7494 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7495 * should be use.
7496 */
Willy Tarreau8d598402012-10-22 17:58:39 +02007497static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007498smp_fetch_ssl_x_serial(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau8d598402012-10-22 17:58:39 +02007499{
Emeric Brunba841a12014-04-30 17:05:08 +02007500 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Willy Tarreau8d598402012-10-22 17:58:39 +02007501 X509 *crt = NULL;
7502 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02007503 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007504 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007505 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007506
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007507 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007508 if (!conn || conn->xprt != &ssl_sock)
Willy Tarreau8d598402012-10-22 17:58:39 +02007509 return 0;
7510
Olivier Houchard66ab4982019-02-26 18:37:15 +01007511 ctx = conn->xprt_ctx;
7512
Willy Tarreau911db9b2020-01-23 16:27:54 +01007513 if (conn->flags & CO_FL_WAIT_XPRT) {
Willy Tarreau8d598402012-10-22 17:58:39 +02007514 smp->flags |= SMP_F_MAY_CHANGE;
7515 return 0;
7516 }
7517
Emeric Brunba841a12014-04-30 17:05:08 +02007518 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007519 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007520 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007521 crt = SSL_get_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007522
Willy Tarreau8d598402012-10-22 17:58:39 +02007523 if (!crt)
7524 goto out;
7525
Willy Tarreau47ca5452012-12-23 20:22:19 +01007526 smp_trash = get_trash_chunk();
Willy Tarreau8d598402012-10-22 17:58:39 +02007527 if (ssl_sock_get_serial(crt, smp_trash) <= 0)
7528 goto out;
7529
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007530 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007531 smp->data.type = SMP_T_BIN;
Willy Tarreau8d598402012-10-22 17:58:39 +02007532 ret = 1;
7533out:
Emeric Brunba841a12014-04-30 17:05:08 +02007534 /* SSL_get_peer_certificate, it increase X509 * ref count */
7535 if (cert_peer && crt)
Willy Tarreau8d598402012-10-22 17:58:39 +02007536 X509_free(crt);
7537 return ret;
7538}
Emeric Brune64aef12012-09-21 13:15:06 +02007539
Emeric Brunba841a12014-04-30 17:05:08 +02007540/* binary, returns the client certificate's SHA-1 fingerprint (SHA-1 hash of DER-encoded certificate) in a binary chunk.
7541 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7542 * should be use.
7543 */
James Votha051b4a2013-05-14 20:37:59 +02007544static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007545smp_fetch_ssl_x_sha1(const struct arg *args, struct sample *smp, const char *kw, void *private)
James Votha051b4a2013-05-14 20:37:59 +02007546{
Emeric Brunba841a12014-04-30 17:05:08 +02007547 int cert_peer = (kw[4] == 'c') ? 1 : 0;
James Votha051b4a2013-05-14 20:37:59 +02007548 X509 *crt = NULL;
7549 const EVP_MD *digest;
7550 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02007551 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007552 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007553 struct ssl_sock_ctx *ctx;
James Votha051b4a2013-05-14 20:37:59 +02007554
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007555 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007556 if (!conn || conn->xprt != &ssl_sock)
7557 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007558 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007559
Willy Tarreau911db9b2020-01-23 16:27:54 +01007560 if (conn->flags & CO_FL_WAIT_XPRT) {
James Votha051b4a2013-05-14 20:37:59 +02007561 smp->flags |= SMP_F_MAY_CHANGE;
7562 return 0;
7563 }
7564
Emeric Brunba841a12014-04-30 17:05:08 +02007565 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007566 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007567 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007568 crt = SSL_get_certificate(ctx->ssl);
James Votha051b4a2013-05-14 20:37:59 +02007569 if (!crt)
7570 goto out;
7571
7572 smp_trash = get_trash_chunk();
7573 digest = EVP_sha1();
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007574 X509_digest(crt, digest, (unsigned char *) smp_trash->area,
7575 (unsigned int *)&smp_trash->data);
James Votha051b4a2013-05-14 20:37:59 +02007576
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007577 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007578 smp->data.type = SMP_T_BIN;
James Votha051b4a2013-05-14 20:37:59 +02007579 ret = 1;
7580out:
Emeric Brunba841a12014-04-30 17:05:08 +02007581 /* SSL_get_peer_certificate, it increase X509 * ref count */
7582 if (cert_peer && crt)
James Votha051b4a2013-05-14 20:37:59 +02007583 X509_free(crt);
7584 return ret;
7585}
7586
Emeric Brunba841a12014-04-30 17:05:08 +02007587/* string, returns certificate's notafter date in ASN1_UTCTIME format.
7588 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7589 * should be use.
7590 */
Emeric Brunce5ad802012-10-22 14:11:22 +02007591static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007592smp_fetch_ssl_x_notafter(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunce5ad802012-10-22 14:11:22 +02007593{
Emeric Brunba841a12014-04-30 17:05:08 +02007594 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brunce5ad802012-10-22 14:11:22 +02007595 X509 *crt = NULL;
7596 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02007597 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007598 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007599 struct ssl_sock_ctx *ctx;
Emeric Brunce5ad802012-10-22 14:11:22 +02007600
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007601 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007602 if (!conn || conn->xprt != &ssl_sock)
7603 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007604 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007605
Willy Tarreau911db9b2020-01-23 16:27:54 +01007606 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Brunce5ad802012-10-22 14:11:22 +02007607 smp->flags |= SMP_F_MAY_CHANGE;
7608 return 0;
7609 }
7610
Emeric Brunba841a12014-04-30 17:05:08 +02007611 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007612 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007613 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007614 crt = SSL_get_certificate(ctx->ssl);
Emeric Brunce5ad802012-10-22 14:11:22 +02007615 if (!crt)
7616 goto out;
7617
Willy Tarreau47ca5452012-12-23 20:22:19 +01007618 smp_trash = get_trash_chunk();
Rosen Penev68185952018-12-14 08:47:02 -08007619 if (ssl_sock_get_time(X509_getm_notAfter(crt), smp_trash) <= 0)
Emeric Brunce5ad802012-10-22 14:11:22 +02007620 goto out;
7621
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007622 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007623 smp->data.type = SMP_T_STR;
Emeric Brunce5ad802012-10-22 14:11:22 +02007624 ret = 1;
7625out:
Emeric Brunba841a12014-04-30 17:05:08 +02007626 /* SSL_get_peer_certificate, it increase X509 * ref count */
7627 if (cert_peer && crt)
Emeric Brunce5ad802012-10-22 14:11:22 +02007628 X509_free(crt);
7629 return ret;
7630}
7631
Emeric Brunba841a12014-04-30 17:05:08 +02007632/* string, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. of certificate's issuer
7633 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7634 * should be use.
7635 */
Emeric Brun87855892012-10-17 17:39:35 +02007636static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007637smp_fetch_ssl_x_i_dn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun87855892012-10-17 17:39:35 +02007638{
Emeric Brunba841a12014-04-30 17:05:08 +02007639 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun87855892012-10-17 17:39:35 +02007640 X509 *crt = NULL;
7641 X509_NAME *name;
7642 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02007643 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007644 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007645 struct ssl_sock_ctx *ctx;
Emeric Brun87855892012-10-17 17:39:35 +02007646
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007647 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007648 if (!conn || conn->xprt != &ssl_sock)
7649 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007650 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007651
Willy Tarreau911db9b2020-01-23 16:27:54 +01007652 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Brun87855892012-10-17 17:39:35 +02007653 smp->flags |= SMP_F_MAY_CHANGE;
7654 return 0;
7655 }
7656
Emeric Brunba841a12014-04-30 17:05:08 +02007657 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007658 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007659 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007660 crt = SSL_get_certificate(ctx->ssl);
Emeric Brun87855892012-10-17 17:39:35 +02007661 if (!crt)
7662 goto out;
7663
7664 name = X509_get_issuer_name(crt);
7665 if (!name)
7666 goto out;
7667
Willy Tarreau47ca5452012-12-23 20:22:19 +01007668 smp_trash = get_trash_chunk();
Elliot Otchet71f82972020-01-15 08:12:14 -05007669 if (args && args[0].type == ARGT_STR && args[0].data.str.data > 0) {
Emeric Brun87855892012-10-17 17:39:35 +02007670 int pos = 1;
7671
7672 if (args[1].type == ARGT_SINT)
7673 pos = args[1].data.sint;
Emeric Brun87855892012-10-17 17:39:35 +02007674
7675 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
7676 goto out;
7677 }
Elliot Otchet71f82972020-01-15 08:12:14 -05007678 else if (args && args[2].type == ARGT_STR && args[2].data.str.data > 0) {
7679 if (ssl_sock_get_dn_formatted(name, &args[2].data.str, smp_trash) <= 0)
7680 goto out;
7681 }
Emeric Brun87855892012-10-17 17:39:35 +02007682 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
7683 goto out;
7684
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007685 smp->data.type = SMP_T_STR;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007686 smp->data.u.str = *smp_trash;
Emeric Brun87855892012-10-17 17:39:35 +02007687 ret = 1;
7688out:
Emeric Brunba841a12014-04-30 17:05:08 +02007689 /* SSL_get_peer_certificate, it increase X509 * ref count */
7690 if (cert_peer && crt)
Emeric Brun87855892012-10-17 17:39:35 +02007691 X509_free(crt);
7692 return ret;
7693}
7694
Emeric Brunba841a12014-04-30 17:05:08 +02007695/* string, returns notbefore date in ASN1_UTCTIME format.
7696 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7697 * should be use.
7698 */
Emeric Brunce5ad802012-10-22 14:11:22 +02007699static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007700smp_fetch_ssl_x_notbefore(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunce5ad802012-10-22 14:11:22 +02007701{
Emeric Brunba841a12014-04-30 17:05:08 +02007702 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brunce5ad802012-10-22 14:11:22 +02007703 X509 *crt = NULL;
7704 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02007705 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007706 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007707 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007708
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007709 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007710 if (!conn || conn->xprt != &ssl_sock)
Emeric Brunce5ad802012-10-22 14:11:22 +02007711 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007712 ctx = conn->xprt_ctx;
Emeric Brunce5ad802012-10-22 14:11:22 +02007713
Willy Tarreau911db9b2020-01-23 16:27:54 +01007714 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Brunce5ad802012-10-22 14:11:22 +02007715 smp->flags |= SMP_F_MAY_CHANGE;
7716 return 0;
7717 }
7718
Emeric Brunba841a12014-04-30 17:05:08 +02007719 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007720 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007721 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007722 crt = SSL_get_certificate(ctx->ssl);
Emeric Brunce5ad802012-10-22 14:11:22 +02007723 if (!crt)
7724 goto out;
7725
Willy Tarreau47ca5452012-12-23 20:22:19 +01007726 smp_trash = get_trash_chunk();
Rosen Penev68185952018-12-14 08:47:02 -08007727 if (ssl_sock_get_time(X509_getm_notBefore(crt), smp_trash) <= 0)
Emeric Brunce5ad802012-10-22 14:11:22 +02007728 goto out;
7729
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007730 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007731 smp->data.type = SMP_T_STR;
Emeric Brunce5ad802012-10-22 14:11:22 +02007732 ret = 1;
7733out:
Emeric Brunba841a12014-04-30 17:05:08 +02007734 /* SSL_get_peer_certificate, it increase X509 * ref count */
7735 if (cert_peer && crt)
Emeric Brunce5ad802012-10-22 14:11:22 +02007736 X509_free(crt);
7737 return ret;
7738}
7739
Emeric Brunba841a12014-04-30 17:05:08 +02007740/* string, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. of certificate's subject
7741 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7742 * should be use.
7743 */
Emeric Brun87855892012-10-17 17:39:35 +02007744static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007745smp_fetch_ssl_x_s_dn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun87855892012-10-17 17:39:35 +02007746{
Emeric Brunba841a12014-04-30 17:05:08 +02007747 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun87855892012-10-17 17:39:35 +02007748 X509 *crt = NULL;
7749 X509_NAME *name;
7750 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02007751 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007752 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007753 struct ssl_sock_ctx *ctx;
Emeric Brun87855892012-10-17 17:39:35 +02007754
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007755 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007756 if (!conn || conn->xprt != &ssl_sock)
7757 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007758 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007759
Willy Tarreau911db9b2020-01-23 16:27:54 +01007760 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Brun87855892012-10-17 17:39:35 +02007761 smp->flags |= SMP_F_MAY_CHANGE;
7762 return 0;
7763 }
7764
Emeric Brunba841a12014-04-30 17:05:08 +02007765 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007766 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007767 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007768 crt = SSL_get_certificate(ctx->ssl);
Emeric Brun87855892012-10-17 17:39:35 +02007769 if (!crt)
7770 goto out;
7771
7772 name = X509_get_subject_name(crt);
7773 if (!name)
7774 goto out;
7775
Willy Tarreau47ca5452012-12-23 20:22:19 +01007776 smp_trash = get_trash_chunk();
Elliot Otchet71f82972020-01-15 08:12:14 -05007777 if (args && args[0].type == ARGT_STR && args[0].data.str.data > 0) {
Emeric Brun87855892012-10-17 17:39:35 +02007778 int pos = 1;
7779
7780 if (args[1].type == ARGT_SINT)
7781 pos = args[1].data.sint;
Emeric Brun87855892012-10-17 17:39:35 +02007782
7783 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
7784 goto out;
7785 }
Elliot Otchet71f82972020-01-15 08:12:14 -05007786 else if (args && args[2].type == ARGT_STR && args[2].data.str.data > 0) {
7787 if (ssl_sock_get_dn_formatted(name, &args[2].data.str, smp_trash) <= 0)
7788 goto out;
7789 }
Emeric Brun87855892012-10-17 17:39:35 +02007790 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
7791 goto out;
7792
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007793 smp->data.type = SMP_T_STR;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007794 smp->data.u.str = *smp_trash;
Emeric Brun87855892012-10-17 17:39:35 +02007795 ret = 1;
7796out:
Emeric Brunba841a12014-04-30 17:05:08 +02007797 /* SSL_get_peer_certificate, it increase X509 * ref count */
7798 if (cert_peer && crt)
Emeric Brun87855892012-10-17 17:39:35 +02007799 X509_free(crt);
7800 return ret;
7801}
Emeric Brun9143d372012-12-20 15:44:16 +01007802
7803/* integer, returns true if current session use a client certificate */
7804static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007805smp_fetch_ssl_c_used(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun9143d372012-12-20 15:44:16 +01007806{
7807 X509 *crt;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007808 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007809 struct ssl_sock_ctx *ctx;
Emeric Brun9143d372012-12-20 15:44:16 +01007810
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007811 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007812 if (!conn || conn->xprt != &ssl_sock)
7813 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007814 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007815
Willy Tarreau911db9b2020-01-23 16:27:54 +01007816 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Brun9143d372012-12-20 15:44:16 +01007817 smp->flags |= SMP_F_MAY_CHANGE;
7818 return 0;
7819 }
7820
7821 /* SSL_get_peer_certificate returns a ptr on allocated X509 struct */
Olivier Houchard66ab4982019-02-26 18:37:15 +01007822 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brun9143d372012-12-20 15:44:16 +01007823 if (crt) {
7824 X509_free(crt);
7825 }
7826
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007827 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007828 smp->data.u.sint = (crt != NULL);
Emeric Brun9143d372012-12-20 15:44:16 +01007829 return 1;
7830}
7831
Emeric Brunba841a12014-04-30 17:05:08 +02007832/* integer, returns the certificate version
7833 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7834 * should be use.
7835 */
Emeric Bruna7359fd2012-10-17 15:03:11 +02007836static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007837smp_fetch_ssl_x_version(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Bruna7359fd2012-10-17 15:03:11 +02007838{
Emeric Brunba841a12014-04-30 17:05:08 +02007839 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Bruna7359fd2012-10-17 15:03:11 +02007840 X509 *crt;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007841 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007842 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007843
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007844 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007845 if (!conn || conn->xprt != &ssl_sock)
Emeric Bruna7359fd2012-10-17 15:03:11 +02007846 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007847 ctx = conn->xprt_ctx;
Emeric Bruna7359fd2012-10-17 15:03:11 +02007848
Willy Tarreau911db9b2020-01-23 16:27:54 +01007849 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Bruna7359fd2012-10-17 15:03:11 +02007850 smp->flags |= SMP_F_MAY_CHANGE;
7851 return 0;
7852 }
7853
Emeric Brunba841a12014-04-30 17:05:08 +02007854 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007855 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007856 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007857 crt = SSL_get_certificate(ctx->ssl);
Emeric Bruna7359fd2012-10-17 15:03:11 +02007858 if (!crt)
7859 return 0;
7860
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007861 smp->data.u.sint = (unsigned int)(1 + X509_get_version(crt));
Emeric Brunba841a12014-04-30 17:05:08 +02007862 /* SSL_get_peer_certificate increase X509 * ref count */
7863 if (cert_peer)
7864 X509_free(crt);
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007865 smp->data.type = SMP_T_SINT;
Emeric Bruna7359fd2012-10-17 15:03:11 +02007866
7867 return 1;
7868}
7869
Emeric Brunba841a12014-04-30 17:05:08 +02007870/* string, returns the certificate's signature algorithm.
7871 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7872 * should be use.
7873 */
Emeric Brun7f56e742012-10-19 18:15:40 +02007874static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007875smp_fetch_ssl_x_sig_alg(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun7f56e742012-10-19 18:15:40 +02007876{
Emeric Brunba841a12014-04-30 17:05:08 +02007877 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun7f56e742012-10-19 18:15:40 +02007878 X509 *crt;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007879 __OPENSSL_110_CONST__ ASN1_OBJECT *algorithm;
Emeric Brun7f56e742012-10-19 18:15:40 +02007880 int nid;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007881 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007882 struct ssl_sock_ctx *ctx;
Emeric Brun7f56e742012-10-19 18:15:40 +02007883
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007884 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007885 if (!conn || conn->xprt != &ssl_sock)
7886 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007887 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007888
Willy Tarreau911db9b2020-01-23 16:27:54 +01007889 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Brun7f56e742012-10-19 18:15:40 +02007890 smp->flags |= SMP_F_MAY_CHANGE;
7891 return 0;
7892 }
7893
Emeric Brunba841a12014-04-30 17:05:08 +02007894 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007895 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007896 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007897 crt = SSL_get_certificate(ctx->ssl);
Emeric Brun7f56e742012-10-19 18:15:40 +02007898 if (!crt)
7899 return 0;
7900
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007901 X509_ALGOR_get0(&algorithm, NULL, NULL, X509_get0_tbs_sigalg(crt));
7902 nid = OBJ_obj2nid(algorithm);
Emeric Brun7f56e742012-10-19 18:15:40 +02007903
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007904 smp->data.u.str.area = (char *)OBJ_nid2sn(nid);
7905 if (!smp->data.u.str.area) {
Emeric Brunba841a12014-04-30 17:05:08 +02007906 /* SSL_get_peer_certificate increase X509 * ref count */
7907 if (cert_peer)
7908 X509_free(crt);
Emeric Brun7f56e742012-10-19 18:15:40 +02007909 return 0;
Emeric Brun9bf3ba22013-10-07 14:31:44 +02007910 }
Emeric Brun7f56e742012-10-19 18:15:40 +02007911
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007912 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01007913 smp->flags |= SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007914 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brunba841a12014-04-30 17:05:08 +02007915 /* SSL_get_peer_certificate increase X509 * ref count */
7916 if (cert_peer)
7917 X509_free(crt);
Emeric Brun7f56e742012-10-19 18:15:40 +02007918
7919 return 1;
7920}
7921
Emeric Brunba841a12014-04-30 17:05:08 +02007922/* string, returns the certificate's key algorithm.
7923 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7924 * should be use.
7925 */
Emeric Brun521a0112012-10-22 12:22:55 +02007926static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007927smp_fetch_ssl_x_key_alg(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun521a0112012-10-22 12:22:55 +02007928{
Emeric Brunba841a12014-04-30 17:05:08 +02007929 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun521a0112012-10-22 12:22:55 +02007930 X509 *crt;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007931 ASN1_OBJECT *algorithm;
Emeric Brun521a0112012-10-22 12:22:55 +02007932 int nid;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007933 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007934 struct ssl_sock_ctx *ctx;
Emeric Brun521a0112012-10-22 12:22:55 +02007935
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007936 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007937 if (!conn || conn->xprt != &ssl_sock)
7938 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007939 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007940
Willy Tarreau911db9b2020-01-23 16:27:54 +01007941 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Brun521a0112012-10-22 12:22:55 +02007942 smp->flags |= SMP_F_MAY_CHANGE;
7943 return 0;
7944 }
7945
Emeric Brunba841a12014-04-30 17:05:08 +02007946 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007947 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007948 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007949 crt = SSL_get_certificate(ctx->ssl);
Emeric Brun521a0112012-10-22 12:22:55 +02007950 if (!crt)
7951 return 0;
7952
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007953 X509_PUBKEY_get0_param(&algorithm, NULL, NULL, NULL, X509_get_X509_PUBKEY(crt));
7954 nid = OBJ_obj2nid(algorithm);
Emeric Brun521a0112012-10-22 12:22:55 +02007955
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007956 smp->data.u.str.area = (char *)OBJ_nid2sn(nid);
7957 if (!smp->data.u.str.area) {
Emeric Brunba841a12014-04-30 17:05:08 +02007958 /* SSL_get_peer_certificate increase X509 * ref count */
7959 if (cert_peer)
7960 X509_free(crt);
Emeric Brun521a0112012-10-22 12:22:55 +02007961 return 0;
Emeric Brun9bf3ba22013-10-07 14:31:44 +02007962 }
Emeric Brun521a0112012-10-22 12:22:55 +02007963
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007964 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01007965 smp->flags |= SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007966 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brunba841a12014-04-30 17:05:08 +02007967 if (cert_peer)
7968 X509_free(crt);
Emeric Brun521a0112012-10-22 12:22:55 +02007969
7970 return 1;
7971}
7972
Emeric Brun645ae792014-04-30 14:21:06 +02007973/* boolean, returns true if front conn. transport layer is SSL.
7974 * This function is also usable on backend conn if the fetch keyword 5th
7975 * char is 'b'.
7976 */
Willy Tarreau7875d092012-09-10 08:20:03 +02007977static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007978smp_fetch_ssl_fc(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02007979{
Emeric Bruneb8def92018-02-19 15:59:48 +01007980 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7981 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007982
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007983 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007984 smp->data.u.sint = (conn && conn->xprt == &ssl_sock);
Willy Tarreau7875d092012-09-10 08:20:03 +02007985 return 1;
7986}
7987
Emeric Brun2525b6b2012-10-18 15:59:43 +02007988/* boolean, returns true if client present a SNI */
Willy Tarreau7875d092012-09-10 08:20:03 +02007989static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007990smp_fetch_ssl_fc_has_sni(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02007991{
7992#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007993 struct connection *conn = objt_conn(smp->sess->origin);
Olivier Houchard66ab4982019-02-26 18:37:15 +01007994 struct ssl_sock_ctx *ctx = conn ? conn->xprt_ctx : NULL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007995
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007996 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007997 smp->data.u.sint = (conn && conn->xprt == &ssl_sock) &&
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007998 conn->xprt_ctx &&
Olivier Houchard66ab4982019-02-26 18:37:15 +01007999 SSL_get_servername(ctx->ssl, TLSEXT_NAMETYPE_host_name) != NULL;
Willy Tarreau7875d092012-09-10 08:20:03 +02008000 return 1;
8001#else
8002 return 0;
8003#endif
8004}
8005
Emeric Brun74f7ffa2018-02-19 16:14:12 +01008006/* boolean, returns true if client session has been resumed.
8007 * This function is also usable on backend conn if the fetch keyword 5th
8008 * char is 'b'.
8009 */
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02008010static int
8011smp_fetch_ssl_fc_is_resumed(const struct arg *args, struct sample *smp, const char *kw, void *private)
8012{
Emeric Brun74f7ffa2018-02-19 16:14:12 +01008013 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
8014 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008015 struct ssl_sock_ctx *ctx = conn ? conn->xprt_ctx : NULL;
Emeric Brun74f7ffa2018-02-19 16:14:12 +01008016
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02008017
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008018 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02008019 smp->data.u.sint = (conn && conn->xprt == &ssl_sock) &&
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02008020 conn->xprt_ctx &&
Olivier Houchard66ab4982019-02-26 18:37:15 +01008021 SSL_session_reused(ctx->ssl);
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02008022 return 1;
8023}
8024
Emeric Brun645ae792014-04-30 14:21:06 +02008025/* string, returns the used cipher if front conn. transport layer is SSL.
8026 * This function is also usable on backend conn if the fetch keyword 5th
8027 * char is 'b'.
8028 */
Emeric Brun589fcad2012-10-16 14:13:26 +02008029static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008030smp_fetch_ssl_fc_cipher(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02008031{
Emeric Bruneb8def92018-02-19 15:59:48 +01008032 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
8033 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008034 struct ssl_sock_ctx *ctx;
Emeric Brun589fcad2012-10-16 14:13:26 +02008035
Willy Tarreaube508f12016-03-10 11:47:01 +01008036 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008037 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02008038 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008039 ctx = conn->xprt_ctx;
Emeric Brun589fcad2012-10-16 14:13:26 +02008040
Olivier Houchard66ab4982019-02-26 18:37:15 +01008041 smp->data.u.str.area = (char *)SSL_get_cipher_name(ctx->ssl);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008042 if (!smp->data.u.str.area)
Emeric Brun589fcad2012-10-16 14:13:26 +02008043 return 0;
8044
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008045 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008046 smp->flags |= SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008047 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brun589fcad2012-10-16 14:13:26 +02008048
8049 return 1;
8050}
8051
Emeric Brun645ae792014-04-30 14:21:06 +02008052/* integer, returns the algoritm's keysize if front conn. transport layer
8053 * is SSL.
8054 * This function is also usable on backend conn if the fetch keyword 5th
8055 * char is 'b'.
8056 */
Emeric Brun589fcad2012-10-16 14:13:26 +02008057static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008058smp_fetch_ssl_fc_alg_keysize(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02008059{
Emeric Bruneb8def92018-02-19 15:59:48 +01008060 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
8061 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008062 struct ssl_sock_ctx *ctx;
Willy Tarreaue237fe12016-03-10 17:05:28 +01008063 int sint;
Willy Tarreaube508f12016-03-10 11:47:01 +01008064
Emeric Brun589fcad2012-10-16 14:13:26 +02008065 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008066 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02008067 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008068 ctx = conn->xprt_ctx;
Emeric Brun589fcad2012-10-16 14:13:26 +02008069
Olivier Houchard66ab4982019-02-26 18:37:15 +01008070 if (!SSL_get_cipher_bits(ctx->ssl, &sint))
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008071 return 0;
8072
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02008073 smp->data.u.sint = sint;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008074 smp->data.type = SMP_T_SINT;
Emeric Brun589fcad2012-10-16 14:13:26 +02008075
8076 return 1;
8077}
8078
Emeric Brun645ae792014-04-30 14:21:06 +02008079/* integer, returns the used keysize if front conn. transport layer is SSL.
8080 * This function is also usable on backend conn if the fetch keyword 5th
8081 * char is 'b'.
8082 */
Emeric Brun589fcad2012-10-16 14:13:26 +02008083static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008084smp_fetch_ssl_fc_use_keysize(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02008085{
Emeric Bruneb8def92018-02-19 15:59:48 +01008086 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
8087 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008088 struct ssl_sock_ctx *ctx;
Willy Tarreaube508f12016-03-10 11:47:01 +01008089
Emeric Brun589fcad2012-10-16 14:13:26 +02008090 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008091 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8092 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008093 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008094
Olivier Houchard66ab4982019-02-26 18:37:15 +01008095 smp->data.u.sint = (unsigned int)SSL_get_cipher_bits(ctx->ssl, NULL);
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02008096 if (!smp->data.u.sint)
Emeric Brun589fcad2012-10-16 14:13:26 +02008097 return 0;
8098
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008099 smp->data.type = SMP_T_SINT;
Emeric Brun589fcad2012-10-16 14:13:26 +02008100
8101 return 1;
8102}
8103
Bernard Spil13c53f82018-02-15 13:34:58 +01008104#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Willy Tarreau7875d092012-09-10 08:20:03 +02008105static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008106smp_fetch_ssl_fc_npn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreaua33c6542012-10-15 13:19:06 +02008107{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008108 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008109 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008110
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008111 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008112 smp->data.type = SMP_T_STR;
Willy Tarreaua33c6542012-10-15 13:19:06 +02008113
Olivier Houchard6b77f492018-11-22 18:18:29 +01008114 conn = (kw[4] != 'b' ) ? objt_conn(smp->sess->origin) :
8115 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008116 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8117 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008118 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008119
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008120 smp->data.u.str.area = NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008121 SSL_get0_next_proto_negotiated(ctx->ssl,
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008122 (const unsigned char **)&smp->data.u.str.area,
8123 (unsigned *)&smp->data.u.str.data);
Willy Tarreaua33c6542012-10-15 13:19:06 +02008124
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008125 if (!smp->data.u.str.area)
Willy Tarreaua33c6542012-10-15 13:19:06 +02008126 return 0;
8127
8128 return 1;
Willy Tarreaua33c6542012-10-15 13:19:06 +02008129}
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02008130#endif
Willy Tarreaua33c6542012-10-15 13:19:06 +02008131
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01008132#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02008133static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008134smp_fetch_ssl_fc_alpn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreauab861d32013-04-02 02:30:41 +02008135{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008136 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008137 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008138
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008139 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008140 smp->data.type = SMP_T_STR;
Willy Tarreauab861d32013-04-02 02:30:41 +02008141
Olivier Houchard6b77f492018-11-22 18:18:29 +01008142 conn = (kw[4] != 'b' ) ? objt_conn(smp->sess->origin) :
8143 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
8144
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008145 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Willy Tarreauab861d32013-04-02 02:30:41 +02008146 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008147 ctx = conn->xprt_ctx;
Willy Tarreauab861d32013-04-02 02:30:41 +02008148
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008149 smp->data.u.str.area = NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008150 SSL_get0_alpn_selected(ctx->ssl,
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008151 (const unsigned char **)&smp->data.u.str.area,
8152 (unsigned *)&smp->data.u.str.data);
Willy Tarreauab861d32013-04-02 02:30:41 +02008153
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008154 if (!smp->data.u.str.area)
Willy Tarreauab861d32013-04-02 02:30:41 +02008155 return 0;
8156
8157 return 1;
8158}
8159#endif
8160
Emeric Brun645ae792014-04-30 14:21:06 +02008161/* string, returns the used protocol if front conn. transport layer is SSL.
8162 * This function is also usable on backend conn if the fetch keyword 5th
8163 * char is 'b'.
8164 */
Willy Tarreaua33c6542012-10-15 13:19:06 +02008165static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008166smp_fetch_ssl_fc_protocol(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02008167{
Emeric Bruneb8def92018-02-19 15:59:48 +01008168 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
8169 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008170 struct ssl_sock_ctx *ctx;
Willy Tarreaube508f12016-03-10 11:47:01 +01008171
Emeric Brun589fcad2012-10-16 14:13:26 +02008172 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008173 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8174 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008175 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008176
Olivier Houchard66ab4982019-02-26 18:37:15 +01008177 smp->data.u.str.area = (char *)SSL_get_version(ctx->ssl);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008178 if (!smp->data.u.str.area)
Emeric Brun589fcad2012-10-16 14:13:26 +02008179 return 0;
8180
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008181 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008182 smp->flags = SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008183 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brun589fcad2012-10-16 14:13:26 +02008184
8185 return 1;
8186}
8187
Willy Tarreau87b09662015-04-03 00:22:06 +02008188/* binary, returns the SSL stream id if front conn. transport layer is SSL.
Emeric Brun645ae792014-04-30 14:21:06 +02008189 * This function is also usable on backend conn if the fetch keyword 5th
8190 * char is 'b'.
8191 */
Willy Tarreau9a1ab082019-05-09 13:26:41 +02008192#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
Emeric Brun589fcad2012-10-16 14:13:26 +02008193static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008194smp_fetch_ssl_fc_session_id(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunfe68f682012-10-16 14:59:28 +02008195{
Emeric Bruneb8def92018-02-19 15:59:48 +01008196 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
8197 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaue237fe12016-03-10 17:05:28 +01008198 SSL_SESSION *ssl_sess;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008199 struct ssl_sock_ctx *ctx;
Willy Tarreaube508f12016-03-10 11:47:01 +01008200
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008201 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008202 smp->data.type = SMP_T_BIN;
Emeric Brunfe68f682012-10-16 14:59:28 +02008203
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008204 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8205 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008206 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008207
Olivier Houchard66ab4982019-02-26 18:37:15 +01008208 ssl_sess = SSL_get_session(ctx->ssl);
Willy Tarreau192252e2015-04-04 01:47:55 +02008209 if (!ssl_sess)
Emeric Brunfe68f682012-10-16 14:59:28 +02008210 return 0;
8211
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008212 smp->data.u.str.area = (char *)SSL_SESSION_get_id(ssl_sess,
8213 (unsigned int *)&smp->data.u.str.data);
8214 if (!smp->data.u.str.area || !smp->data.u.str.data)
Emeric Brunfe68f682012-10-16 14:59:28 +02008215 return 0;
8216
8217 return 1;
Emeric Brunfe68f682012-10-16 14:59:28 +02008218}
Patrick Hemmer41966772018-04-28 19:15:48 -04008219#endif
8220
Emeric Brunfe68f682012-10-16 14:59:28 +02008221
Emmanuel Hocdet839af572019-05-14 16:27:35 +02008222#if HA_OPENSSL_VERSION_NUMBER >= 0x10100000L
Patrick Hemmere0275472018-04-28 19:15:51 -04008223static int
Patrick Hemmer65674662019-06-04 08:13:03 -04008224smp_fetch_ssl_fc_random(const struct arg *args, struct sample *smp, const char *kw, void *private)
8225{
8226 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
8227 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
8228 struct buffer *data;
8229 struct ssl_sock_ctx *ctx;
8230
8231 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8232 return 0;
8233 ctx = conn->xprt_ctx;
8234
8235 data = get_trash_chunk();
8236 if (kw[7] == 'c')
8237 data->data = SSL_get_client_random(ctx->ssl,
8238 (unsigned char *) data->area,
8239 data->size);
8240 else
8241 data->data = SSL_get_server_random(ctx->ssl,
8242 (unsigned char *) data->area,
8243 data->size);
8244 if (!data->data)
8245 return 0;
8246
8247 smp->flags = 0;
8248 smp->data.type = SMP_T_BIN;
8249 smp->data.u.str = *data;
8250
8251 return 1;
8252}
8253
8254static int
Patrick Hemmere0275472018-04-28 19:15:51 -04008255smp_fetch_ssl_fc_session_key(const struct arg *args, struct sample *smp, const char *kw, void *private)
8256{
8257 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
8258 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
8259 SSL_SESSION *ssl_sess;
Willy Tarreau83061a82018-07-13 11:56:34 +02008260 struct buffer *data;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008261 struct ssl_sock_ctx *ctx;
Patrick Hemmere0275472018-04-28 19:15:51 -04008262
8263 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8264 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008265 ctx = conn->xprt_ctx;
Patrick Hemmere0275472018-04-28 19:15:51 -04008266
Olivier Houchard66ab4982019-02-26 18:37:15 +01008267 ssl_sess = SSL_get_session(ctx->ssl);
Patrick Hemmere0275472018-04-28 19:15:51 -04008268 if (!ssl_sess)
8269 return 0;
8270
8271 data = get_trash_chunk();
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008272 data->data = SSL_SESSION_get_master_key(ssl_sess,
8273 (unsigned char *) data->area,
8274 data->size);
8275 if (!data->data)
Patrick Hemmere0275472018-04-28 19:15:51 -04008276 return 0;
8277
8278 smp->flags = 0;
8279 smp->data.type = SMP_T_BIN;
8280 smp->data.u.str = *data;
8281
8282 return 1;
8283}
8284#endif
8285
Patrick Hemmer41966772018-04-28 19:15:48 -04008286#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emeric Brunfe68f682012-10-16 14:59:28 +02008287static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008288smp_fetch_ssl_fc_sni(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02008289{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008290 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008291 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008292
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008293 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008294 smp->data.type = SMP_T_STR;
Willy Tarreau7875d092012-09-10 08:20:03 +02008295
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02008296 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008297 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8298 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008299 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008300
Olivier Houchard66ab4982019-02-26 18:37:15 +01008301 smp->data.u.str.area = (char *)SSL_get_servername(ctx->ssl, TLSEXT_NAMETYPE_host_name);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008302 if (!smp->data.u.str.area)
Willy Tarreau3e394c92012-09-14 23:56:58 +02008303 return 0;
8304
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008305 smp->data.u.str.data = strlen(smp->data.u.str.area);
Willy Tarreau7875d092012-09-10 08:20:03 +02008306 return 1;
Willy Tarreau7875d092012-09-10 08:20:03 +02008307}
Patrick Hemmer41966772018-04-28 19:15:48 -04008308#endif
Willy Tarreau7875d092012-09-10 08:20:03 +02008309
David Sc1ad52e2014-04-08 18:48:47 -04008310static int
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008311smp_fetch_ssl_fc_cl_bin(const struct arg *args, struct sample *smp, const char *kw, void *private)
8312{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008313 struct connection *conn;
8314 struct ssl_capture *capture;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008315 struct ssl_sock_ctx *ctx;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008316
8317 conn = objt_conn(smp->sess->origin);
8318 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8319 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008320 ctx = conn->xprt_ctx;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008321
Olivier Houchard66ab4982019-02-26 18:37:15 +01008322 capture = SSL_get_ex_data(ctx->ssl, ssl_capture_ptr_index);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008323 if (!capture)
8324 return 0;
8325
8326 smp->flags = SMP_F_CONST;
8327 smp->data.type = SMP_T_BIN;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008328 smp->data.u.str.area = capture->ciphersuite;
8329 smp->data.u.str.data = capture->ciphersuite_len;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008330 return 1;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008331}
8332
8333static int
8334smp_fetch_ssl_fc_cl_hex(const struct arg *args, struct sample *smp, const char *kw, void *private)
8335{
Willy Tarreau83061a82018-07-13 11:56:34 +02008336 struct buffer *data;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008337
8338 if (!smp_fetch_ssl_fc_cl_bin(args, smp, kw, private))
8339 return 0;
8340
8341 data = get_trash_chunk();
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008342 dump_binary(data, smp->data.u.str.area, smp->data.u.str.data);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008343 smp->data.type = SMP_T_BIN;
8344 smp->data.u.str = *data;
8345 return 1;
8346}
8347
8348static int
8349smp_fetch_ssl_fc_cl_xxh64(const struct arg *args, struct sample *smp, const char *kw, void *private)
8350{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008351 struct connection *conn;
8352 struct ssl_capture *capture;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008353 struct ssl_sock_ctx *ctx;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008354
8355 conn = objt_conn(smp->sess->origin);
8356 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8357 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008358 ctx = conn->xprt_ctx;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008359
Olivier Houchard66ab4982019-02-26 18:37:15 +01008360 capture = SSL_get_ex_data(ctx->ssl, ssl_capture_ptr_index);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008361 if (!capture)
8362 return 0;
8363
8364 smp->data.type = SMP_T_SINT;
8365 smp->data.u.sint = capture->xxh64;
8366 return 1;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008367}
8368
8369static int
8370smp_fetch_ssl_fc_cl_str(const struct arg *args, struct sample *smp, const char *kw, void *private)
8371{
Willy Tarreau5db847a2019-05-09 14:13:35 +02008372#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL)
Willy Tarreau83061a82018-07-13 11:56:34 +02008373 struct buffer *data;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008374 int i;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008375
8376 if (!smp_fetch_ssl_fc_cl_bin(args, smp, kw, private))
8377 return 0;
8378
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008379 data = get_trash_chunk();
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008380 for (i = 0; i + 1 < smp->data.u.str.data; i += 2) {
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02008381 const char *str;
8382 const SSL_CIPHER *cipher;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008383 const unsigned char *bin = (const unsigned char *) smp->data.u.str.area + i;
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02008384 uint16_t id = (bin[0] << 8) | bin[1];
8385#if defined(OPENSSL_IS_BORINGSSL)
8386 cipher = SSL_get_cipher_by_value(id);
8387#else
Willy Tarreaub7290772018-10-15 11:01:59 +02008388 struct connection *conn = __objt_conn(smp->sess->origin);
Olivier Houchard66ab4982019-02-26 18:37:15 +01008389 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
8390 cipher = SSL_CIPHER_find(ctx->ssl, bin);
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02008391#endif
8392 str = SSL_CIPHER_get_name(cipher);
8393 if (!str || strcmp(str, "(NONE)") == 0)
8394 chunk_appendf(data, "%sUNKNOWN(%04x)", i == 0 ? "" : ",", id);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008395 else
8396 chunk_appendf(data, "%s%s", i == 0 ? "" : ",", str);
8397 }
8398 smp->data.type = SMP_T_STR;
8399 smp->data.u.str = *data;
8400 return 1;
8401#else
8402 return smp_fetch_ssl_fc_cl_xxh64(args, smp, kw, private);
8403#endif
8404}
8405
Willy Tarreau9a1ab082019-05-09 13:26:41 +02008406#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008407static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008408smp_fetch_ssl_fc_unique_id(const struct arg *args, struct sample *smp, const char *kw, void *private)
David Sc1ad52e2014-04-08 18:48:47 -04008409{
Emeric Bruneb8def92018-02-19 15:59:48 +01008410 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
8411 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
David Sc1ad52e2014-04-08 18:48:47 -04008412 int finished_len;
Willy Tarreau83061a82018-07-13 11:56:34 +02008413 struct buffer *finished_trash;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008414 struct ssl_sock_ctx *ctx;
David Sc1ad52e2014-04-08 18:48:47 -04008415
8416 smp->flags = 0;
David Sc1ad52e2014-04-08 18:48:47 -04008417 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8418 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008419 ctx = conn->xprt_ctx;
David Sc1ad52e2014-04-08 18:48:47 -04008420
Willy Tarreau911db9b2020-01-23 16:27:54 +01008421 if (conn->flags & CO_FL_WAIT_XPRT) {
David Sc1ad52e2014-04-08 18:48:47 -04008422 smp->flags |= SMP_F_MAY_CHANGE;
8423 return 0;
8424 }
8425
8426 finished_trash = get_trash_chunk();
Olivier Houchard66ab4982019-02-26 18:37:15 +01008427 if (!SSL_session_reused(ctx->ssl))
8428 finished_len = SSL_get_peer_finished(ctx->ssl,
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008429 finished_trash->area,
8430 finished_trash->size);
David Sc1ad52e2014-04-08 18:48:47 -04008431 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01008432 finished_len = SSL_get_finished(ctx->ssl,
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008433 finished_trash->area,
8434 finished_trash->size);
David Sc1ad52e2014-04-08 18:48:47 -04008435
8436 if (!finished_len)
8437 return 0;
8438
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008439 finished_trash->data = finished_len;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02008440 smp->data.u.str = *finished_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008441 smp->data.type = SMP_T_BIN;
David Sc1ad52e2014-04-08 18:48:47 -04008442
8443 return 1;
David Sc1ad52e2014-04-08 18:48:47 -04008444}
Patrick Hemmer41966772018-04-28 19:15:48 -04008445#endif
David Sc1ad52e2014-04-08 18:48:47 -04008446
Emeric Brun2525b6b2012-10-18 15:59:43 +02008447/* integer, returns the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02008448static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008449smp_fetch_ssl_c_ca_err(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunf282a812012-09-21 15:27:54 +02008450{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008451 struct connection *conn;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008452 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008453
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02008454 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008455 if (!conn || conn->xprt != &ssl_sock)
8456 return 0;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008457 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008458
Willy Tarreau911db9b2020-01-23 16:27:54 +01008459 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Brunf282a812012-09-21 15:27:54 +02008460 smp->flags = SMP_F_MAY_CHANGE;
8461 return 0;
8462 }
8463
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008464 smp->data.type = SMP_T_SINT;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008465 smp->data.u.sint = (unsigned long long int)SSL_SOCK_ST_TO_CA_ERROR(ctx->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02008466 smp->flags = 0;
8467
8468 return 1;
8469}
8470
Emeric Brun2525b6b2012-10-18 15:59:43 +02008471/* integer, returns the depth of the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02008472static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008473smp_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 +02008474{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008475 struct connection *conn;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008476 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008477
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02008478 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008479 if (!conn || conn->xprt != &ssl_sock)
Emeric Brunf282a812012-09-21 15:27:54 +02008480 return 0;
8481
Willy Tarreau911db9b2020-01-23 16:27:54 +01008482 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Brunf282a812012-09-21 15:27:54 +02008483 smp->flags = SMP_F_MAY_CHANGE;
8484 return 0;
8485 }
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008486 ctx = conn->xprt_ctx;
Emeric Brunf282a812012-09-21 15:27:54 +02008487
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008488 smp->data.type = SMP_T_SINT;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008489 smp->data.u.sint = (long long int)SSL_SOCK_ST_TO_CAEDEPTH(ctx->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02008490 smp->flags = 0;
8491
8492 return 1;
8493}
8494
Emeric Brun2525b6b2012-10-18 15:59:43 +02008495/* integer, returns the first verify error on client certificate */
Emeric Brunf282a812012-09-21 15:27:54 +02008496static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008497smp_fetch_ssl_c_err(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunf282a812012-09-21 15:27:54 +02008498{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008499 struct connection *conn;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008500 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008501
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02008502 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008503 if (!conn || conn->xprt != &ssl_sock)
8504 return 0;
8505
Willy Tarreau911db9b2020-01-23 16:27:54 +01008506 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Brunf282a812012-09-21 15:27:54 +02008507 smp->flags = SMP_F_MAY_CHANGE;
8508 return 0;
8509 }
8510
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008511 ctx = conn->xprt_ctx;
8512
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008513 smp->data.type = SMP_T_SINT;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008514 smp->data.u.sint = (long long int)SSL_SOCK_ST_TO_CRTERROR(ctx->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02008515 smp->flags = 0;
8516
8517 return 1;
8518}
8519
Emeric Brun2525b6b2012-10-18 15:59:43 +02008520/* integer, returns the verify result on client cert */
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02008521static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008522smp_fetch_ssl_c_verify(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02008523{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008524 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008525 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008526
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02008527 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008528 if (!conn || conn->xprt != &ssl_sock)
8529 return 0;
8530
Willy Tarreau911db9b2020-01-23 16:27:54 +01008531 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02008532 smp->flags = SMP_F_MAY_CHANGE;
8533 return 0;
8534 }
8535
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008536 if (!conn->xprt_ctx)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02008537 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008538 ctx = conn->xprt_ctx;
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02008539
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008540 smp->data.type = SMP_T_SINT;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008541 smp->data.u.sint = (long long int)SSL_get_verify_result(ctx->ssl);
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02008542 smp->flags = 0;
8543
8544 return 1;
8545}
8546
Emeric Brunfb510ea2012-10-05 12:00:26 +02008547/* parse the "ca-file" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008548static 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 +02008549{
8550 if (!*args[cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01008551 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
Emeric Brund94b3fe2012-09-20 18:23:56 +02008552 return ERR_ALERT | ERR_FATAL;
8553 }
8554
Willy Tarreauef934602016-12-22 23:12:01 +01008555 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
8556 memprintf(&conf->ca_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02008557 else
8558 memprintf(&conf->ca_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02008559
Emmanuel Hocdetd4f9a602019-10-24 11:32:47 +02008560 if (!ssl_store_load_locations_file(conf->ca_file)) {
8561 memprintf(err, "'%s' : unable to load %s", args[cur_arg], conf->ca_file);
8562 return ERR_ALERT | ERR_FATAL;
8563 }
Emeric Brund94b3fe2012-09-20 18:23:56 +02008564 return 0;
8565}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008566static int bind_parse_ca_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8567{
8568 return ssl_bind_parse_ca_file(args, cur_arg, px, &conf->ssl_conf, err);
8569}
Emeric Brund94b3fe2012-09-20 18:23:56 +02008570
Christopher Faulet31af49d2015-06-09 17:29:50 +02008571/* parse the "ca-sign-file" bind keyword */
8572static int bind_parse_ca_sign_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8573{
8574 if (!*args[cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01008575 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
Christopher Faulet31af49d2015-06-09 17:29:50 +02008576 return ERR_ALERT | ERR_FATAL;
8577 }
8578
Willy Tarreauef934602016-12-22 23:12:01 +01008579 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
8580 memprintf(&conf->ca_sign_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Christopher Faulet31af49d2015-06-09 17:29:50 +02008581 else
8582 memprintf(&conf->ca_sign_file, "%s", args[cur_arg + 1]);
8583
8584 return 0;
8585}
8586
Bertrand Jacquinff13c062016-11-13 16:37:11 +00008587/* parse the "ca-sign-pass" bind keyword */
Christopher Faulet31af49d2015-06-09 17:29:50 +02008588static int bind_parse_ca_sign_pass(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8589{
8590 if (!*args[cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01008591 memprintf(err, "'%s' : missing CAkey password", args[cur_arg]);
Christopher Faulet31af49d2015-06-09 17:29:50 +02008592 return ERR_ALERT | ERR_FATAL;
8593 }
8594 memprintf(&conf->ca_sign_pass, "%s", args[cur_arg + 1]);
8595 return 0;
8596}
8597
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008598/* parse the "ciphers" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008599static 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 +02008600{
8601 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02008602 memprintf(err, "'%s' : missing cipher suite", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008603 return ERR_ALERT | ERR_FATAL;
8604 }
8605
Emeric Brun76d88952012-10-05 15:47:31 +02008606 free(conf->ciphers);
Willy Tarreau4348fad2012-09-20 16:48:07 +02008607 conf->ciphers = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008608 return 0;
8609}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008610static int bind_parse_ciphers(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8611{
8612 return ssl_bind_parse_ciphers(args, cur_arg, px, &conf->ssl_conf, err);
8613}
Dirkjan Bussink415150f2018-09-14 11:14:21 +02008614
Emmanuel Hocdet839af572019-05-14 16:27:35 +02008615#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02008616/* parse the "ciphersuites" bind keyword */
8617static int ssl_bind_parse_ciphersuites(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
8618{
8619 if (!*args[cur_arg + 1]) {
8620 memprintf(err, "'%s' : missing cipher suite", args[cur_arg]);
8621 return ERR_ALERT | ERR_FATAL;
8622 }
8623
8624 free(conf->ciphersuites);
8625 conf->ciphersuites = strdup(args[cur_arg + 1]);
8626 return 0;
8627}
8628static int bind_parse_ciphersuites(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8629{
8630 return ssl_bind_parse_ciphersuites(args, cur_arg, px, &conf->ssl_conf, err);
8631}
8632#endif
8633
Willy Tarreaubbc91962019-10-16 16:42:19 +02008634/* parse the "crt" bind keyword. Returns a set of ERR_* flags possibly with an error in <err>. */
Willy Tarreau4348fad2012-09-20 16:48:07 +02008635static 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 +02008636{
Willy Tarreau38011032013-08-13 16:59:39 +02008637 char path[MAXPATHLEN];
Willy Tarreaub75d6922014-04-14 18:05:41 +02008638
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008639 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02008640 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008641 return ERR_ALERT | ERR_FATAL;
8642 }
8643
Willy Tarreauef934602016-12-22 23:12:01 +01008644 if ((*args[cur_arg + 1] != '/' ) && global_ssl.crt_base) {
8645 if ((strlen(global_ssl.crt_base) + 1 + strlen(args[cur_arg + 1]) + 1) > MAXPATHLEN) {
Emeric Brunc8e8d122012-10-02 18:42:10 +02008646 memprintf(err, "'%s' : path too long", args[cur_arg]);
8647 return ERR_ALERT | ERR_FATAL;
8648 }
Willy Tarreauef934602016-12-22 23:12:01 +01008649 snprintf(path, sizeof(path), "%s/%s", global_ssl.crt_base, args[cur_arg + 1]);
Willy Tarreaubbc91962019-10-16 16:42:19 +02008650 return ssl_sock_load_cert(path, conf, err);
Emeric Brunc8e8d122012-10-02 18:42:10 +02008651 }
8652
Willy Tarreaubbc91962019-10-16 16:42:19 +02008653 return ssl_sock_load_cert(args[cur_arg + 1], conf, err);
Emeric Brund94b3fe2012-09-20 18:23:56 +02008654}
8655
Willy Tarreaubbc91962019-10-16 16:42:19 +02008656/* 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 +01008657static int bind_parse_crt_list(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8658{
Willy Tarreaubbc91962019-10-16 16:42:19 +02008659 int err_code;
8660
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01008661 if (!*args[cur_arg + 1]) {
8662 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
8663 return ERR_ALERT | ERR_FATAL;
8664 }
8665
Willy Tarreaubbc91962019-10-16 16:42:19 +02008666 err_code = ssl_sock_load_cert_list_file(args[cur_arg + 1], conf, px, err);
8667 if (err_code)
Willy Tarreauad1731d2013-04-02 17:35:58 +02008668 memprintf(err, "'%s' : %s", args[cur_arg], *err);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01008669
Willy Tarreaubbc91962019-10-16 16:42:19 +02008670 return err_code;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01008671}
8672
Emeric Brunfb510ea2012-10-05 12:00:26 +02008673/* parse the "crl-file" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008674static 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 +02008675{
Emeric Brun051cdab2012-10-02 19:25:50 +02008676#ifndef X509_V_FLAG_CRL_CHECK
Tim Duesterhus93128532019-11-23 23:45:10 +01008677 memprintf(err, "'%s' : library does not support CRL verify", args[cur_arg]);
Emeric Brun051cdab2012-10-02 19:25:50 +02008678 return ERR_ALERT | ERR_FATAL;
8679#else
Emeric Brund94b3fe2012-09-20 18:23:56 +02008680 if (!*args[cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01008681 memprintf(err, "'%s' : missing CRLfile path", args[cur_arg]);
Emeric Brund94b3fe2012-09-20 18:23:56 +02008682 return ERR_ALERT | ERR_FATAL;
8683 }
Emeric Brun2b58d042012-09-20 17:10:03 +02008684
Willy Tarreauef934602016-12-22 23:12:01 +01008685 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
8686 memprintf(&conf->crl_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02008687 else
8688 memprintf(&conf->crl_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02008689
Emmanuel Hocdetb270e812019-11-21 19:09:31 +01008690 if (!ssl_store_load_locations_file(conf->crl_file)) {
8691 memprintf(err, "'%s' : unable to load %s", args[cur_arg], conf->crl_file);
8692 return ERR_ALERT | ERR_FATAL;
8693 }
Emeric Brun2b58d042012-09-20 17:10:03 +02008694 return 0;
Emeric Brun051cdab2012-10-02 19:25:50 +02008695#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02008696}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008697static int bind_parse_crl_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8698{
8699 return ssl_bind_parse_crl_file(args, cur_arg, px, &conf->ssl_conf, err);
8700}
Emeric Brun2b58d042012-09-20 17:10:03 +02008701
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01008702/* parse the "curves" bind keyword keyword */
8703static int ssl_bind_parse_curves(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
8704{
Lukas Tribusd14b49c2019-11-24 18:20:40 +01008705#if ((HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL) || defined(LIBRESSL_VERSION_NUMBER))
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01008706 if (!*args[cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01008707 memprintf(err, "'%s' : missing curve suite", args[cur_arg]);
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01008708 return ERR_ALERT | ERR_FATAL;
8709 }
8710 conf->curves = strdup(args[cur_arg + 1]);
8711 return 0;
8712#else
Tim Duesterhus93128532019-11-23 23:45:10 +01008713 memprintf(err, "'%s' : library does not support curve suite", args[cur_arg]);
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01008714 return ERR_ALERT | ERR_FATAL;
8715#endif
8716}
8717static int bind_parse_curves(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8718{
8719 return ssl_bind_parse_curves(args, cur_arg, px, &conf->ssl_conf, err);
8720}
8721
Bertrand Jacquinff13c062016-11-13 16:37:11 +00008722/* parse the "ecdhe" bind keyword keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008723static 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 +02008724{
Willy Tarreau9a1ab082019-05-09 13:26:41 +02008725#if HA_OPENSSL_VERSION_NUMBER < 0x0090800fL
Tim Duesterhus93128532019-11-23 23:45:10 +01008726 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (too old)", args[cur_arg]);
Emeric Brun2b58d042012-09-20 17:10:03 +02008727 return ERR_ALERT | ERR_FATAL;
8728#elif defined(OPENSSL_NO_ECDH)
Tim Duesterhus93128532019-11-23 23:45:10 +01008729 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 +02008730 return ERR_ALERT | ERR_FATAL;
8731#else
8732 if (!*args[cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01008733 memprintf(err, "'%s' : missing named curve", args[cur_arg]);
Emeric Brun2b58d042012-09-20 17:10:03 +02008734 return ERR_ALERT | ERR_FATAL;
8735 }
8736
8737 conf->ecdhe = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008738
8739 return 0;
Emeric Brun2b58d042012-09-20 17:10:03 +02008740#endif
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008741}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008742static int bind_parse_ecdhe(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8743{
8744 return ssl_bind_parse_ecdhe(args, cur_arg, px, &conf->ssl_conf, err);
8745}
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008746
Bertrand Jacquinff13c062016-11-13 16:37:11 +00008747/* parse the "crt-ignore-err" and "ca-ignore-err" bind keywords */
Emeric Brun81c00f02012-09-21 14:31:21 +02008748static int bind_parse_ignore_err(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8749{
8750 int code;
8751 char *p = args[cur_arg + 1];
8752 unsigned long long *ignerr = &conf->crt_ignerr;
8753
8754 if (!*p) {
Tim Duesterhus93128532019-11-23 23:45:10 +01008755 memprintf(err, "'%s' : missing error IDs list", args[cur_arg]);
Emeric Brun81c00f02012-09-21 14:31:21 +02008756 return ERR_ALERT | ERR_FATAL;
8757 }
8758
8759 if (strcmp(args[cur_arg], "ca-ignore-err") == 0)
8760 ignerr = &conf->ca_ignerr;
8761
8762 if (strcmp(p, "all") == 0) {
8763 *ignerr = ~0ULL;
8764 return 0;
8765 }
8766
8767 while (p) {
8768 code = atoi(p);
8769 if ((code <= 0) || (code > 63)) {
Tim Duesterhus93128532019-11-23 23:45:10 +01008770 memprintf(err, "'%s' : ID '%d' out of range (1..63) in error IDs list '%s'",
8771 args[cur_arg], code, args[cur_arg + 1]);
Emeric Brun81c00f02012-09-21 14:31:21 +02008772 return ERR_ALERT | ERR_FATAL;
8773 }
8774 *ignerr |= 1ULL << code;
8775 p = strchr(p, ',');
8776 if (p)
8777 p++;
8778 }
8779
Emeric Brun2cb7ae52012-10-05 14:14:21 +02008780 return 0;
8781}
8782
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008783/* parse tls_method_options "no-xxx" and "force-xxx" */
8784static int parse_tls_method_options(char *arg, struct tls_version_filter *methods, char **err)
Emeric Brun2cb7ae52012-10-05 14:14:21 +02008785{
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008786 uint16_t v;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008787 char *p;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008788 p = strchr(arg, '-');
8789 if (!p)
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008790 goto fail;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008791 p++;
8792 if (!strcmp(p, "sslv3"))
8793 v = CONF_SSLV3;
8794 else if (!strcmp(p, "tlsv10"))
8795 v = CONF_TLSV10;
8796 else if (!strcmp(p, "tlsv11"))
8797 v = CONF_TLSV11;
8798 else if (!strcmp(p, "tlsv12"))
8799 v = CONF_TLSV12;
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +02008800 else if (!strcmp(p, "tlsv13"))
8801 v = CONF_TLSV13;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008802 else
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008803 goto fail;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008804 if (!strncmp(arg, "no-", 3))
8805 methods->flags |= methodVersions[v].flag;
8806 else if (!strncmp(arg, "force-", 6))
8807 methods->min = methods->max = v;
8808 else
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008809 goto fail;
Emeric Brun2d0c4822012-10-02 13:45:20 +02008810 return 0;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008811 fail:
Tim Duesterhus93128532019-11-23 23:45:10 +01008812 memprintf(err, "'%s' : option not implemented", arg);
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008813 return ERR_ALERT | ERR_FATAL;
Emeric Brun2d0c4822012-10-02 13:45:20 +02008814}
8815
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008816static 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 +02008817{
Emmanuel Hocdet43664762017-08-09 18:26:20 +02008818 return parse_tls_method_options(args[cur_arg], &conf->ssl_conf.ssl_methods, err);
Emeric Brun2cb7ae52012-10-05 14:14:21 +02008819}
8820
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008821static 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 +02008822{
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008823 return parse_tls_method_options(args[*cur_arg], &newsrv->ssl_ctx.methods, err);
8824}
8825
8826/* parse tls_method min/max: "ssl-min-ver" and "ssl-max-ver" */
8827static int parse_tls_method_minmax(char **args, int cur_arg, struct tls_version_filter *methods, char **err)
8828{
8829 uint16_t i, v = 0;
8830 char *argv = args[cur_arg + 1];
8831 if (!*argv) {
Tim Duesterhus93128532019-11-23 23:45:10 +01008832 memprintf(err, "'%s' : missing the ssl/tls version", args[cur_arg]);
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008833 return ERR_ALERT | ERR_FATAL;
8834 }
8835 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
8836 if (!strcmp(argv, methodVersions[i].name))
8837 v = i;
8838 if (!v) {
Tim Duesterhus93128532019-11-23 23:45:10 +01008839 memprintf(err, "'%s' : unknown ssl/tls version", args[cur_arg + 1]);
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008840 return ERR_ALERT | ERR_FATAL;
8841 }
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008842 if (!strcmp("ssl-min-ver", args[cur_arg]))
8843 methods->min = v;
8844 else if (!strcmp("ssl-max-ver", args[cur_arg]))
8845 methods->max = v;
8846 else {
Tim Duesterhus93128532019-11-23 23:45:10 +01008847 memprintf(err, "'%s' : option not implemented", args[cur_arg]);
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008848 return ERR_ALERT | ERR_FATAL;
8849 }
Emeric Brun2cb7ae52012-10-05 14:14:21 +02008850 return 0;
Emeric Brun2cb7ae52012-10-05 14:14:21 +02008851}
Emeric Brun2cb7ae52012-10-05 14:14:21 +02008852
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02008853static int ssl_bind_parse_tls_method_minmax(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
8854{
Willy Tarreau9a1ab082019-05-09 13:26:41 +02008855#if (HA_OPENSSL_VERSION_NUMBER < 0x10101000L) && !defined(OPENSSL_IS_BORINGSSL)
Christopher Faulet767a84b2017-11-24 16:50:31 +01008856 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 +02008857#endif
8858 return parse_tls_method_minmax(args, cur_arg, &conf->ssl_methods, err);
8859}
8860
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008861static int bind_parse_tls_method_minmax(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8862{
Emmanuel Hocdet43664762017-08-09 18:26:20 +02008863 return parse_tls_method_minmax(args, cur_arg, &conf->ssl_conf.ssl_methods, err);
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008864}
8865
8866static int srv_parse_tls_method_minmax(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8867{
8868 return parse_tls_method_minmax(args, *cur_arg, &newsrv->ssl_ctx.methods, err);
8869}
8870
Emeric Brun2d0c4822012-10-02 13:45:20 +02008871/* parse the "no-tls-tickets" bind keyword */
Emmanuel Hocdet4608ed92017-01-20 13:06:27 +01008872static 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 +02008873{
Emeric Brun89675492012-10-05 13:48:26 +02008874 conf->ssl_options |= BC_SSL_O_NO_TLS_TICKETS;
Emeric Brun81c00f02012-09-21 14:31:21 +02008875 return 0;
8876}
Emeric Brun2d0c4822012-10-02 13:45:20 +02008877
Olivier Houchardc2aae742017-09-22 18:26:28 +02008878/* parse the "allow-0rtt" bind keyword */
8879static int ssl_bind_parse_allow_0rtt(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
8880{
8881 conf->early_data = 1;
8882 return 0;
8883}
8884
8885static int bind_parse_allow_0rtt(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8886{
Olivier Houchard9679ac92017-10-27 14:58:08 +02008887 conf->ssl_conf.early_data = 1;
Olivier Houchardc2aae742017-09-22 18:26:28 +02008888 return 0;
8889}
8890
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02008891/* parse the "npn" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008892static 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 +02008893{
Bernard Spil13c53f82018-02-15 13:34:58 +01008894#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02008895 char *p1, *p2;
8896
8897 if (!*args[cur_arg + 1]) {
8898 memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[cur_arg]);
8899 return ERR_ALERT | ERR_FATAL;
8900 }
8901
8902 free(conf->npn_str);
8903
Willy Tarreau3724da12016-02-12 17:11:12 +01008904 /* the NPN string is built as a suite of (<len> <name>)*,
8905 * so we reuse each comma to store the next <len> and need
8906 * one more for the end of the string.
8907 */
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02008908 conf->npn_len = strlen(args[cur_arg + 1]) + 1;
Willy Tarreau3724da12016-02-12 17:11:12 +01008909 conf->npn_str = calloc(1, conf->npn_len + 1);
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02008910 memcpy(conf->npn_str + 1, args[cur_arg + 1], conf->npn_len);
8911
8912 /* replace commas with the name length */
8913 p1 = conf->npn_str;
8914 p2 = p1 + 1;
8915 while (1) {
8916 p2 = memchr(p1 + 1, ',', conf->npn_str + conf->npn_len - (p1 + 1));
8917 if (!p2)
8918 p2 = p1 + 1 + strlen(p1 + 1);
8919
8920 if (p2 - (p1 + 1) > 255) {
8921 *p2 = '\0';
8922 memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
8923 return ERR_ALERT | ERR_FATAL;
8924 }
8925
8926 *p1 = p2 - (p1 + 1);
8927 p1 = p2;
8928
8929 if (!*p2)
8930 break;
8931
8932 *(p2++) = '\0';
8933 }
8934 return 0;
8935#else
Tim Duesterhus93128532019-11-23 23:45:10 +01008936 memprintf(err, "'%s' : library does not support TLS NPN extension", args[cur_arg]);
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02008937 return ERR_ALERT | ERR_FATAL;
8938#endif
8939}
8940
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008941static int bind_parse_npn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8942{
8943 return ssl_bind_parse_npn(args, cur_arg, px, &conf->ssl_conf, err);
8944}
8945
Willy Tarreauab861d32013-04-02 02:30:41 +02008946/* parse the "alpn" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008947static 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 +02008948{
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01008949#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02008950 char *p1, *p2;
8951
8952 if (!*args[cur_arg + 1]) {
8953 memprintf(err, "'%s' : missing the comma-delimited ALPN protocol suite", args[cur_arg]);
8954 return ERR_ALERT | ERR_FATAL;
8955 }
8956
8957 free(conf->alpn_str);
8958
Marcoen Hirschbergbef60912016-02-12 17:05:24 +01008959 /* the ALPN string is built as a suite of (<len> <name>)*,
8960 * so we reuse each comma to store the next <len> and need
8961 * one more for the end of the string.
8962 */
Willy Tarreauab861d32013-04-02 02:30:41 +02008963 conf->alpn_len = strlen(args[cur_arg + 1]) + 1;
Marcoen Hirschbergbef60912016-02-12 17:05:24 +01008964 conf->alpn_str = calloc(1, conf->alpn_len + 1);
Willy Tarreauab861d32013-04-02 02:30:41 +02008965 memcpy(conf->alpn_str + 1, args[cur_arg + 1], conf->alpn_len);
8966
8967 /* replace commas with the name length */
8968 p1 = conf->alpn_str;
8969 p2 = p1 + 1;
8970 while (1) {
8971 p2 = memchr(p1 + 1, ',', conf->alpn_str + conf->alpn_len - (p1 + 1));
8972 if (!p2)
8973 p2 = p1 + 1 + strlen(p1 + 1);
8974
8975 if (p2 - (p1 + 1) > 255) {
8976 *p2 = '\0';
8977 memprintf(err, "'%s' : ALPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
8978 return ERR_ALERT | ERR_FATAL;
8979 }
8980
8981 *p1 = p2 - (p1 + 1);
8982 p1 = p2;
8983
8984 if (!*p2)
8985 break;
8986
8987 *(p2++) = '\0';
8988 }
8989 return 0;
8990#else
Tim Duesterhus93128532019-11-23 23:45:10 +01008991 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[cur_arg]);
Willy Tarreauab861d32013-04-02 02:30:41 +02008992 return ERR_ALERT | ERR_FATAL;
8993#endif
8994}
8995
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008996static int bind_parse_alpn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8997{
8998 return ssl_bind_parse_alpn(args, cur_arg, px, &conf->ssl_conf, err);
8999}
9000
Willy Tarreau79eeafa2012-09-14 07:53:05 +02009001/* parse the "ssl" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02009002static 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 +02009003{
Willy Tarreau71a8c7c2016-12-21 22:04:54 +01009004 conf->xprt = &ssl_sock;
Willy Tarreau4348fad2012-09-20 16:48:07 +02009005 conf->is_ssl = 1;
Emeric Brun76d88952012-10-05 15:47:31 +02009006
Emmanuel Hocdet98263292016-12-29 18:26:15 +01009007 if (global_ssl.listen_default_ciphers && !conf->ssl_conf.ciphers)
9008 conf->ssl_conf.ciphers = strdup(global_ssl.listen_default_ciphers);
Emmanuel Hocdet839af572019-05-14 16:27:35 +02009009#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009010 if (global_ssl.listen_default_ciphersuites && !conf->ssl_conf.ciphersuites)
9011 conf->ssl_conf.ciphersuites = strdup(global_ssl.listen_default_ciphersuites);
9012#endif
Emmanuel Hocdet4608ed92017-01-20 13:06:27 +01009013 conf->ssl_options |= global_ssl.listen_default_ssloptions;
Emmanuel Hocdet43664762017-08-09 18:26:20 +02009014 conf->ssl_conf.ssl_methods.flags |= global_ssl.listen_default_sslmethods.flags;
9015 if (!conf->ssl_conf.ssl_methods.min)
9016 conf->ssl_conf.ssl_methods.min = global_ssl.listen_default_sslmethods.min;
9017 if (!conf->ssl_conf.ssl_methods.max)
9018 conf->ssl_conf.ssl_methods.max = global_ssl.listen_default_sslmethods.max;
Emeric Brun76d88952012-10-05 15:47:31 +02009019
Willy Tarreau79eeafa2012-09-14 07:53:05 +02009020 return 0;
9021}
9022
Lukas Tribus53ae85c2017-05-04 15:45:40 +00009023/* parse the "prefer-client-ciphers" bind keyword */
9024static int bind_parse_pcc(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
9025{
9026 conf->ssl_options |= BC_SSL_O_PREF_CLIE_CIPH;
9027 return 0;
9028}
9029
Christopher Faulet31af49d2015-06-09 17:29:50 +02009030/* parse the "generate-certificates" bind keyword */
9031static int bind_parse_generate_certs(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
9032{
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01009033#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Christopher Faulet31af49d2015-06-09 17:29:50 +02009034 conf->generate_certs = 1;
9035#else
9036 memprintf(err, "%sthis version of openssl cannot generate SSL certificates.\n",
9037 err && *err ? *err : "");
9038#endif
9039 return 0;
9040}
9041
Emmanuel Hocdet65623372013-01-24 17:17:15 +01009042/* parse the "strict-sni" bind keyword */
9043static int bind_parse_strict_sni(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
9044{
9045 conf->strict_sni = 1;
9046 return 0;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009047}
9048
9049/* parse the "tls-ticket-keys" bind keyword */
9050static int bind_parse_tls_ticket_keys(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
9051{
9052#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
Christopher Faulete566f3d2019-10-21 09:55:49 +02009053 FILE *f = NULL;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009054 int i = 0;
9055 char thisline[LINESIZE];
Christopher Faulete566f3d2019-10-21 09:55:49 +02009056 struct tls_keys_ref *keys_ref = NULL;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009057
9058 if (!*args[cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009059 memprintf(err, "'%s' : missing TLS ticket keys file path", args[cur_arg]);
Christopher Faulete566f3d2019-10-21 09:55:49 +02009060 goto fail;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009061 }
9062
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02009063 keys_ref = tlskeys_ref_lookup(args[cur_arg + 1]);
Willy Tarreau17b4aa12018-07-17 10:05:32 +02009064 if (keys_ref) {
9065 keys_ref->refcount++;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02009066 conf->keys_ref = keys_ref;
9067 return 0;
9068 }
9069
Christopher Faulete566f3d2019-10-21 09:55:49 +02009070 keys_ref = calloc(1, sizeof(*keys_ref));
Emeric Brun09852f72019-01-10 10:51:13 +01009071 if (!keys_ref) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009072 memprintf(err, "'%s' : allocation error", args[cur_arg+1]);
Christopher Faulete566f3d2019-10-21 09:55:49 +02009073 goto fail;
Emeric Brun09852f72019-01-10 10:51:13 +01009074 }
9075
Emeric Brun9e754772019-01-10 17:51:55 +01009076 keys_ref->tlskeys = malloc(TLS_TICKETS_NO * sizeof(union tls_sess_key));
Emeric Brun09852f72019-01-10 10:51:13 +01009077 if (!keys_ref->tlskeys) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009078 memprintf(err, "'%s' : allocation error", args[cur_arg+1]);
Christopher Faulete566f3d2019-10-21 09:55:49 +02009079 goto fail;
Emeric Brun09852f72019-01-10 10:51:13 +01009080 }
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009081
9082 if ((f = fopen(args[cur_arg + 1], "r")) == NULL) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009083 memprintf(err, "'%s' : unable to load ssl tickets keys file", args[cur_arg+1]);
Christopher Faulete566f3d2019-10-21 09:55:49 +02009084 goto fail;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009085 }
9086
Nenad Merdanovic146defa2015-05-09 08:46:00 +02009087 keys_ref->filename = strdup(args[cur_arg + 1]);
Emeric Brun09852f72019-01-10 10:51:13 +01009088 if (!keys_ref->filename) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009089 memprintf(err, "'%s' : allocation error", args[cur_arg+1]);
Christopher Faulete566f3d2019-10-21 09:55:49 +02009090 goto fail;
Emeric Brun09852f72019-01-10 10:51:13 +01009091 }
Nenad Merdanovic146defa2015-05-09 08:46:00 +02009092
Emeric Brun9e754772019-01-10 17:51:55 +01009093 keys_ref->key_size_bits = 0;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009094 while (fgets(thisline, sizeof(thisline), f) != NULL) {
9095 int len = strlen(thisline);
Emeric Brun9e754772019-01-10 17:51:55 +01009096 int dec_size;
9097
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009098 /* Strip newline characters from the end */
9099 if(thisline[len - 1] == '\n')
9100 thisline[--len] = 0;
9101
9102 if(thisline[len - 1] == '\r')
9103 thisline[--len] = 0;
9104
Emeric Brun9e754772019-01-10 17:51:55 +01009105 dec_size = base64dec(thisline, len, (char *) (keys_ref->tlskeys + i % TLS_TICKETS_NO), sizeof(union tls_sess_key));
9106 if (dec_size < 0) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009107 memprintf(err, "'%s' : unable to decode base64 key on line %d", args[cur_arg+1], i + 1);
Christopher Faulete566f3d2019-10-21 09:55:49 +02009108 goto fail;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009109 }
Emeric Brun9e754772019-01-10 17:51:55 +01009110 else if (!keys_ref->key_size_bits && (dec_size == sizeof(struct tls_sess_key_128))) {
9111 keys_ref->key_size_bits = 128;
9112 }
9113 else if (!keys_ref->key_size_bits && (dec_size == sizeof(struct tls_sess_key_256))) {
9114 keys_ref->key_size_bits = 256;
9115 }
9116 else if (((dec_size != sizeof(struct tls_sess_key_128)) && (dec_size != sizeof(struct tls_sess_key_256)))
9117 || ((dec_size == sizeof(struct tls_sess_key_128) && (keys_ref->key_size_bits != 128)))
9118 || ((dec_size == sizeof(struct tls_sess_key_256) && (keys_ref->key_size_bits != 256)))) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009119 memprintf(err, "'%s' : wrong sized key on line %d", args[cur_arg+1], i + 1);
Christopher Faulete566f3d2019-10-21 09:55:49 +02009120 goto fail;
Emeric Brun9e754772019-01-10 17:51:55 +01009121 }
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009122 i++;
9123 }
9124
9125 if (i < TLS_TICKETS_NO) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009126 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 +02009127 goto fail;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009128 }
9129
9130 fclose(f);
9131
9132 /* Use penultimate key for encryption, handle when TLS_TICKETS_NO = 1 */
Nenad Merdanovic17891152016-03-25 22:16:57 +01009133 i -= 2;
9134 keys_ref->tls_ticket_enc_index = i < 0 ? 0 : i % TLS_TICKETS_NO;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02009135 keys_ref->unique_id = -1;
Willy Tarreau17b4aa12018-07-17 10:05:32 +02009136 keys_ref->refcount = 1;
Christopher Faulet16f45c82018-02-16 11:23:49 +01009137 HA_RWLOCK_INIT(&keys_ref->lock);
Nenad Merdanovic146defa2015-05-09 08:46:00 +02009138 conf->keys_ref = keys_ref;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009139
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02009140 LIST_ADD(&tlskeys_reference, &keys_ref->list);
9141
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009142 return 0;
Christopher Faulete566f3d2019-10-21 09:55:49 +02009143
9144 fail:
9145 if (f)
9146 fclose(f);
9147 if (keys_ref) {
9148 free(keys_ref->filename);
9149 free(keys_ref->tlskeys);
9150 free(keys_ref);
9151 }
9152 return ERR_ALERT | ERR_FATAL;
9153
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009154#else
Tim Duesterhus93128532019-11-23 23:45:10 +01009155 memprintf(err, "'%s' : TLS ticket callback extension not supported", args[cur_arg]);
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009156 return ERR_ALERT | ERR_FATAL;
9157#endif /* SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB */
Emmanuel Hocdet65623372013-01-24 17:17:15 +01009158}
9159
Emeric Brund94b3fe2012-09-20 18:23:56 +02009160/* parse the "verify" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01009161static 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 +02009162{
9163 if (!*args[cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009164 memprintf(err, "'%s' : missing verify method", args[cur_arg]);
Emeric Brund94b3fe2012-09-20 18:23:56 +02009165 return ERR_ALERT | ERR_FATAL;
9166 }
9167
9168 if (strcmp(args[cur_arg + 1], "none") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01009169 conf->verify = SSL_SOCK_VERIFY_NONE;
Emeric Brund94b3fe2012-09-20 18:23:56 +02009170 else if (strcmp(args[cur_arg + 1], "optional") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01009171 conf->verify = SSL_SOCK_VERIFY_OPTIONAL;
Emeric Brund94b3fe2012-09-20 18:23:56 +02009172 else if (strcmp(args[cur_arg + 1], "required") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01009173 conf->verify = SSL_SOCK_VERIFY_REQUIRED;
Emeric Brund94b3fe2012-09-20 18:23:56 +02009174 else {
Tim Duesterhus93128532019-11-23 23:45:10 +01009175 memprintf(err, "'%s' : unknown verify method '%s', only 'none', 'optional', and 'required' are supported\n",
9176 args[cur_arg], args[cur_arg + 1]);
Emeric Brund94b3fe2012-09-20 18:23:56 +02009177 return ERR_ALERT | ERR_FATAL;
9178 }
9179
9180 return 0;
9181}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01009182static int bind_parse_verify(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
9183{
9184 return ssl_bind_parse_verify(args, cur_arg, px, &conf->ssl_conf, err);
9185}
Emeric Brund94b3fe2012-09-20 18:23:56 +02009186
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02009187/* parse the "no-ca-names" bind keyword */
9188static int ssl_bind_parse_no_ca_names(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
9189{
9190 conf->no_ca_names = 1;
9191 return 0;
9192}
9193static int bind_parse_no_ca_names(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
9194{
9195 return ssl_bind_parse_no_ca_names(args, cur_arg, px, &conf->ssl_conf, err);
9196}
9197
Willy Tarreau92faadf2012-10-10 23:04:25 +02009198/************** "server" keywords ****************/
9199
Olivier Houchardc7566002018-11-20 23:33:50 +01009200/* parse the "npn" bind keyword */
9201static int srv_parse_npn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9202{
9203#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
9204 char *p1, *p2;
9205
9206 if (!*args[*cur_arg + 1]) {
9207 memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[*cur_arg]);
9208 return ERR_ALERT | ERR_FATAL;
9209 }
9210
9211 free(newsrv->ssl_ctx.npn_str);
9212
9213 /* the NPN string is built as a suite of (<len> <name>)*,
9214 * so we reuse each comma to store the next <len> and need
9215 * one more for the end of the string.
9216 */
9217 newsrv->ssl_ctx.npn_len = strlen(args[*cur_arg + 1]) + 1;
9218 newsrv->ssl_ctx.npn_str = calloc(1, newsrv->ssl_ctx.npn_len + 1);
9219 memcpy(newsrv->ssl_ctx.npn_str + 1, args[*cur_arg + 1],
9220 newsrv->ssl_ctx.npn_len);
9221
9222 /* replace commas with the name length */
9223 p1 = newsrv->ssl_ctx.npn_str;
9224 p2 = p1 + 1;
9225 while (1) {
9226 p2 = memchr(p1 + 1, ',', newsrv->ssl_ctx.npn_str +
9227 newsrv->ssl_ctx.npn_len - (p1 + 1));
9228 if (!p2)
9229 p2 = p1 + 1 + strlen(p1 + 1);
9230
9231 if (p2 - (p1 + 1) > 255) {
9232 *p2 = '\0';
9233 memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[*cur_arg], p1 + 1);
9234 return ERR_ALERT | ERR_FATAL;
9235 }
9236
9237 *p1 = p2 - (p1 + 1);
9238 p1 = p2;
9239
9240 if (!*p2)
9241 break;
9242
9243 *(p2++) = '\0';
9244 }
9245 return 0;
9246#else
Tim Duesterhus93128532019-11-23 23:45:10 +01009247 memprintf(err, "'%s' : library does not support TLS NPN extension", args[*cur_arg]);
Olivier Houchardc7566002018-11-20 23:33:50 +01009248 return ERR_ALERT | ERR_FATAL;
9249#endif
9250}
9251
Olivier Houchard92150142018-12-21 19:47:01 +01009252/* parse the "alpn" or the "check-alpn" server keyword */
Olivier Houchardc7566002018-11-20 23:33:50 +01009253static int srv_parse_alpn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9254{
9255#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
9256 char *p1, *p2;
Olivier Houchard92150142018-12-21 19:47:01 +01009257 char **alpn_str;
9258 int *alpn_len;
Olivier Houchardc7566002018-11-20 23:33:50 +01009259
Olivier Houchard92150142018-12-21 19:47:01 +01009260 if (*args[*cur_arg] == 'c') {
9261 alpn_str = &newsrv->check.alpn_str;
9262 alpn_len = &newsrv->check.alpn_len;
9263 } else {
9264 alpn_str = &newsrv->ssl_ctx.alpn_str;
9265 alpn_len = &newsrv->ssl_ctx.alpn_len;
9266
9267 }
Olivier Houchardc7566002018-11-20 23:33:50 +01009268 if (!*args[*cur_arg + 1]) {
9269 memprintf(err, "'%s' : missing the comma-delimited ALPN protocol suite", args[*cur_arg]);
9270 return ERR_ALERT | ERR_FATAL;
9271 }
9272
Olivier Houchard92150142018-12-21 19:47:01 +01009273 free(*alpn_str);
Olivier Houchardc7566002018-11-20 23:33:50 +01009274
9275 /* the ALPN string is built as a suite of (<len> <name>)*,
9276 * so we reuse each comma to store the next <len> and need
9277 * one more for the end of the string.
9278 */
Olivier Houchard92150142018-12-21 19:47:01 +01009279 *alpn_len = strlen(args[*cur_arg + 1]) + 1;
9280 *alpn_str = calloc(1, *alpn_len + 1);
9281 memcpy(*alpn_str + 1, args[*cur_arg + 1], *alpn_len);
Olivier Houchardc7566002018-11-20 23:33:50 +01009282
9283 /* replace commas with the name length */
Olivier Houchard92150142018-12-21 19:47:01 +01009284 p1 = *alpn_str;
Olivier Houchardc7566002018-11-20 23:33:50 +01009285 p2 = p1 + 1;
9286 while (1) {
Olivier Houchard92150142018-12-21 19:47:01 +01009287 p2 = memchr(p1 + 1, ',', *alpn_str + *alpn_len - (p1 + 1));
Olivier Houchardc7566002018-11-20 23:33:50 +01009288 if (!p2)
9289 p2 = p1 + 1 + strlen(p1 + 1);
9290
9291 if (p2 - (p1 + 1) > 255) {
9292 *p2 = '\0';
9293 memprintf(err, "'%s' : ALPN protocol name too long : '%s'", args[*cur_arg], p1 + 1);
9294 return ERR_ALERT | ERR_FATAL;
9295 }
9296
9297 *p1 = p2 - (p1 + 1);
9298 p1 = p2;
9299
9300 if (!*p2)
9301 break;
9302
9303 *(p2++) = '\0';
9304 }
9305 return 0;
9306#else
Tim Duesterhus93128532019-11-23 23:45:10 +01009307 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[*cur_arg]);
Olivier Houchardc7566002018-11-20 23:33:50 +01009308 return ERR_ALERT | ERR_FATAL;
9309#endif
9310}
9311
Emeric Brunef42d922012-10-11 16:11:36 +02009312/* parse the "ca-file" server keyword */
9313static int srv_parse_ca_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9314{
9315 if (!*args[*cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009316 memprintf(err, "'%s' : missing CAfile path", args[*cur_arg]);
Emeric Brunef42d922012-10-11 16:11:36 +02009317 return ERR_ALERT | ERR_FATAL;
9318 }
9319
Willy Tarreauef934602016-12-22 23:12:01 +01009320 if ((*args[*cur_arg + 1] != '/') && global_ssl.ca_base)
9321 memprintf(&newsrv->ssl_ctx.ca_file, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02009322 else
9323 memprintf(&newsrv->ssl_ctx.ca_file, "%s", args[*cur_arg + 1]);
9324
Emmanuel Hocdetd4f9a602019-10-24 11:32:47 +02009325 if (!ssl_store_load_locations_file(newsrv->ssl_ctx.ca_file)) {
9326 memprintf(err, "'%s' : unable to load %s", args[*cur_arg], newsrv->ssl_ctx.ca_file);
9327 return ERR_ALERT | ERR_FATAL;
9328 }
Emeric Brunef42d922012-10-11 16:11:36 +02009329 return 0;
9330}
9331
Olivier Houchard9130a962017-10-17 17:33:43 +02009332/* parse the "check-sni" server keyword */
9333static int srv_parse_check_sni(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 SNI", args[*cur_arg]);
Olivier Houchard9130a962017-10-17 17:33:43 +02009337 return ERR_ALERT | ERR_FATAL;
9338 }
9339
9340 newsrv->check.sni = strdup(args[*cur_arg + 1]);
9341 if (!newsrv->check.sni) {
9342 memprintf(err, "'%s' : failed to allocate memory", args[*cur_arg]);
9343 return ERR_ALERT | ERR_FATAL;
9344 }
9345 return 0;
9346
9347}
9348
Willy Tarreau92faadf2012-10-10 23:04:25 +02009349/* parse the "check-ssl" server keyword */
9350static int srv_parse_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9351{
9352 newsrv->check.use_ssl = 1;
Willy Tarreauef934602016-12-22 23:12:01 +01009353 if (global_ssl.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
9354 newsrv->ssl_ctx.ciphers = strdup(global_ssl.connect_default_ciphers);
Emmanuel Hocdet839af572019-05-14 16:27:35 +02009355#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009356 if (global_ssl.connect_default_ciphersuites && !newsrv->ssl_ctx.ciphersuites)
9357 newsrv->ssl_ctx.ciphersuites = strdup(global_ssl.connect_default_ciphersuites);
9358#endif
Willy Tarreauef934602016-12-22 23:12:01 +01009359 newsrv->ssl_ctx.options |= global_ssl.connect_default_ssloptions;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02009360 newsrv->ssl_ctx.methods.flags |= global_ssl.connect_default_sslmethods.flags;
9361 if (!newsrv->ssl_ctx.methods.min)
9362 newsrv->ssl_ctx.methods.min = global_ssl.connect_default_sslmethods.min;
9363 if (!newsrv->ssl_ctx.methods.max)
9364 newsrv->ssl_ctx.methods.max = global_ssl.connect_default_sslmethods.max;
9365
Willy Tarreau92faadf2012-10-10 23:04:25 +02009366 return 0;
9367}
9368
9369/* parse the "ciphers" server keyword */
9370static int srv_parse_ciphers(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9371{
9372 if (!*args[*cur_arg + 1]) {
9373 memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
9374 return ERR_ALERT | ERR_FATAL;
9375 }
9376
9377 free(newsrv->ssl_ctx.ciphers);
9378 newsrv->ssl_ctx.ciphers = strdup(args[*cur_arg + 1]);
9379 return 0;
9380}
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009381
Emmanuel Hocdet839af572019-05-14 16:27:35 +02009382#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009383/* parse the "ciphersuites" server keyword */
9384static int srv_parse_ciphersuites(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9385{
9386 if (!*args[*cur_arg + 1]) {
9387 memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
9388 return ERR_ALERT | ERR_FATAL;
9389 }
9390
9391 free(newsrv->ssl_ctx.ciphersuites);
9392 newsrv->ssl_ctx.ciphersuites = strdup(args[*cur_arg + 1]);
9393 return 0;
9394}
9395#endif
Willy Tarreau92faadf2012-10-10 23:04:25 +02009396
Emeric Brunef42d922012-10-11 16:11:36 +02009397/* parse the "crl-file" server keyword */
9398static int srv_parse_crl_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9399{
9400#ifndef X509_V_FLAG_CRL_CHECK
Tim Duesterhus93128532019-11-23 23:45:10 +01009401 memprintf(err, "'%s' : library does not support CRL verify", args[*cur_arg]);
Emeric Brunef42d922012-10-11 16:11:36 +02009402 return ERR_ALERT | ERR_FATAL;
9403#else
9404 if (!*args[*cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009405 memprintf(err, "'%s' : missing CRLfile path", args[*cur_arg]);
Emeric Brunef42d922012-10-11 16:11:36 +02009406 return ERR_ALERT | ERR_FATAL;
9407 }
9408
Willy Tarreauef934602016-12-22 23:12:01 +01009409 if ((*args[*cur_arg + 1] != '/') && global_ssl.ca_base)
9410 memprintf(&newsrv->ssl_ctx.crl_file, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02009411 else
9412 memprintf(&newsrv->ssl_ctx.crl_file, "%s", args[*cur_arg + 1]);
9413
Emmanuel Hocdetb270e812019-11-21 19:09:31 +01009414 if (!ssl_store_load_locations_file(newsrv->ssl_ctx.crl_file)) {
9415 memprintf(err, "'%s' : unable to load %s", args[*cur_arg], newsrv->ssl_ctx.crl_file);
9416 return ERR_ALERT | ERR_FATAL;
9417 }
Emeric Brunef42d922012-10-11 16:11:36 +02009418 return 0;
9419#endif
9420}
9421
Emeric Bruna7aa3092012-10-26 12:58:00 +02009422/* parse the "crt" server keyword */
9423static int srv_parse_crt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9424{
9425 if (!*args[*cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009426 memprintf(err, "'%s' : missing certificate file path", args[*cur_arg]);
Emeric Bruna7aa3092012-10-26 12:58:00 +02009427 return ERR_ALERT | ERR_FATAL;
9428 }
9429
Willy Tarreauef934602016-12-22 23:12:01 +01009430 if ((*args[*cur_arg + 1] != '/') && global_ssl.crt_base)
Christopher Fauletff3a41e2017-11-23 09:13:32 +01009431 memprintf(&newsrv->ssl_ctx.client_crt, "%s/%s", global_ssl.crt_base, args[*cur_arg + 1]);
Emeric Bruna7aa3092012-10-26 12:58:00 +02009432 else
9433 memprintf(&newsrv->ssl_ctx.client_crt, "%s", args[*cur_arg + 1]);
9434
9435 return 0;
9436}
Emeric Brunef42d922012-10-11 16:11:36 +02009437
Frédéric Lécaille340ae602017-03-13 10:38:04 +01009438/* parse the "no-check-ssl" server keyword */
9439static int srv_parse_no_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9440{
9441 newsrv->check.use_ssl = 0;
9442 free(newsrv->ssl_ctx.ciphers);
9443 newsrv->ssl_ctx.ciphers = NULL;
9444 newsrv->ssl_ctx.options &= ~global_ssl.connect_default_ssloptions;
9445 return 0;
9446}
9447
Frédéric Lécaillee892c4c2017-03-13 12:08:01 +01009448/* parse the "no-send-proxy-v2-ssl" server keyword */
9449static int srv_parse_no_send_proxy_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9450{
9451 newsrv->pp_opts &= ~SRV_PP_V2;
9452 newsrv->pp_opts &= ~SRV_PP_V2_SSL;
9453 return 0;
9454}
9455
9456/* parse the "no-send-proxy-v2-ssl-cn" server keyword */
9457static int srv_parse_no_send_proxy_cn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9458{
9459 newsrv->pp_opts &= ~SRV_PP_V2;
9460 newsrv->pp_opts &= ~SRV_PP_V2_SSL;
9461 newsrv->pp_opts &= ~SRV_PP_V2_SSL_CN;
9462 return 0;
9463}
9464
Frédéric Lécaillee381d762017-03-13 11:54:17 +01009465/* parse the "no-ssl" server keyword */
9466static int srv_parse_no_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9467{
9468 newsrv->use_ssl = 0;
9469 free(newsrv->ssl_ctx.ciphers);
9470 newsrv->ssl_ctx.ciphers = NULL;
9471 return 0;
9472}
9473
Olivier Houchard522eea72017-11-03 16:27:47 +01009474/* parse the "allow-0rtt" server keyword */
9475static int srv_parse_allow_0rtt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9476{
9477 newsrv->ssl_ctx.options |= SRV_SSL_O_EARLY_DATA;
9478 return 0;
9479}
9480
Willy Tarreau2a3fb1c2015-02-05 16:47:07 +01009481/* parse the "no-ssl-reuse" server keyword */
9482static int srv_parse_no_ssl_reuse(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9483{
9484 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_REUSE;
9485 return 0;
9486}
9487
Emeric Brunf9c5c472012-10-11 15:28:34 +02009488/* parse the "no-tls-tickets" server keyword */
9489static int srv_parse_no_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9490{
9491 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLS_TICKETS;
9492 return 0;
9493}
David Safb76832014-05-08 23:42:08 -04009494/* parse the "send-proxy-v2-ssl" server keyword */
9495static int srv_parse_send_proxy_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9496{
9497 newsrv->pp_opts |= SRV_PP_V2;
9498 newsrv->pp_opts |= SRV_PP_V2_SSL;
9499 return 0;
9500}
9501
9502/* parse the "send-proxy-v2-ssl-cn" server keyword */
9503static int srv_parse_send_proxy_cn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9504{
9505 newsrv->pp_opts |= SRV_PP_V2;
9506 newsrv->pp_opts |= SRV_PP_V2_SSL;
9507 newsrv->pp_opts |= SRV_PP_V2_SSL_CN;
9508 return 0;
9509}
Emeric Brunf9c5c472012-10-11 15:28:34 +02009510
Willy Tarreau732eac42015-07-09 11:40:25 +02009511/* parse the "sni" server keyword */
9512static int srv_parse_sni(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9513{
9514#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
9515 memprintf(err, "'%s' : the current SSL library doesn't support the SNI TLS extension", args[*cur_arg]);
9516 return ERR_ALERT | ERR_FATAL;
9517#else
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01009518 char *arg;
Willy Tarreau732eac42015-07-09 11:40:25 +02009519
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01009520 arg = args[*cur_arg + 1];
9521 if (!*arg) {
Willy Tarreau732eac42015-07-09 11:40:25 +02009522 memprintf(err, "'%s' : missing sni expression", args[*cur_arg]);
9523 return ERR_ALERT | ERR_FATAL;
9524 }
9525
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01009526 free(newsrv->sni_expr);
9527 newsrv->sni_expr = strdup(arg);
Willy Tarreau732eac42015-07-09 11:40:25 +02009528
Willy Tarreau732eac42015-07-09 11:40:25 +02009529 return 0;
9530#endif
9531}
9532
Willy Tarreau92faadf2012-10-10 23:04:25 +02009533/* parse the "ssl" server keyword */
9534static int srv_parse_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9535{
9536 newsrv->use_ssl = 1;
Willy Tarreauef934602016-12-22 23:12:01 +01009537 if (global_ssl.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
9538 newsrv->ssl_ctx.ciphers = strdup(global_ssl.connect_default_ciphers);
Emmanuel Hocdet839af572019-05-14 16:27:35 +02009539#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009540 if (global_ssl.connect_default_ciphersuites && !newsrv->ssl_ctx.ciphersuites)
9541 newsrv->ssl_ctx.ciphersuites = strdup(global_ssl.connect_default_ciphersuites);
9542#endif
Willy Tarreau92faadf2012-10-10 23:04:25 +02009543 return 0;
9544}
9545
Frédéric Lécaille2cfcdbe2017-03-13 11:32:20 +01009546/* parse the "ssl-reuse" server keyword */
9547static int srv_parse_ssl_reuse(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9548{
9549 newsrv->ssl_ctx.options &= ~SRV_SSL_O_NO_REUSE;
9550 return 0;
9551}
9552
Frédéric Lécaille2cfcdbe2017-03-13 11:32:20 +01009553/* parse the "tls-tickets" server keyword */
9554static int srv_parse_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9555{
9556 newsrv->ssl_ctx.options &= ~SRV_SSL_O_NO_TLS_TICKETS;
9557 return 0;
9558}
9559
Emeric Brunef42d922012-10-11 16:11:36 +02009560/* parse the "verify" server keyword */
9561static int srv_parse_verify(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9562{
9563 if (!*args[*cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009564 memprintf(err, "'%s' : missing verify method", args[*cur_arg]);
Emeric Brunef42d922012-10-11 16:11:36 +02009565 return ERR_ALERT | ERR_FATAL;
9566 }
9567
9568 if (strcmp(args[*cur_arg + 1], "none") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01009569 newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_NONE;
Emeric Brunef42d922012-10-11 16:11:36 +02009570 else if (strcmp(args[*cur_arg + 1], "required") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01009571 newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_REQUIRED;
Emeric Brunef42d922012-10-11 16:11:36 +02009572 else {
Tim Duesterhus93128532019-11-23 23:45:10 +01009573 memprintf(err, "'%s' : unknown verify method '%s', only 'none' and 'required' are supported\n",
9574 args[*cur_arg], args[*cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02009575 return ERR_ALERT | ERR_FATAL;
9576 }
9577
Evan Broderbe554312013-06-27 00:05:25 -07009578 return 0;
9579}
9580
9581/* parse the "verifyhost" server keyword */
9582static int srv_parse_verifyhost(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9583{
9584 if (!*args[*cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009585 memprintf(err, "'%s' : missing hostname to verify against", args[*cur_arg]);
Evan Broderbe554312013-06-27 00:05:25 -07009586 return ERR_ALERT | ERR_FATAL;
9587 }
9588
Frédéric Lécaille273f3212017-03-13 15:52:01 +01009589 free(newsrv->ssl_ctx.verify_host);
Evan Broderbe554312013-06-27 00:05:25 -07009590 newsrv->ssl_ctx.verify_host = strdup(args[*cur_arg + 1]);
9591
Emeric Brunef42d922012-10-11 16:11:36 +02009592 return 0;
9593}
9594
Emeric Brun2c86cbf2014-10-30 15:56:50 +01009595/* parse the "ssl-default-bind-options" keyword in global section */
9596static int ssl_parse_default_bind_options(char **args, int section_type, struct proxy *curpx,
9597 struct proxy *defpx, const char *file, int line,
9598 char **err) {
9599 int i = 1;
9600
9601 if (*(args[i]) == 0) {
9602 memprintf(err, "global statement '%s' expects an option as an argument.", args[0]);
9603 return -1;
9604 }
9605 while (*(args[i])) {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02009606 if (!strcmp(args[i], "no-tls-tickets"))
Willy Tarreauef934602016-12-22 23:12:01 +01009607 global_ssl.listen_default_ssloptions |= BC_SSL_O_NO_TLS_TICKETS;
Lukas Tribus53ae85c2017-05-04 15:45:40 +00009608 else if (!strcmp(args[i], "prefer-client-ciphers"))
9609 global_ssl.listen_default_ssloptions |= BC_SSL_O_PREF_CLIE_CIPH;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02009610 else if (!strcmp(args[i], "ssl-min-ver") || !strcmp(args[i], "ssl-max-ver")) {
9611 if (!parse_tls_method_minmax(args, i, &global_ssl.listen_default_sslmethods, err))
9612 i++;
9613 else {
9614 memprintf(err, "%s on global statement '%s'.", *err, args[0]);
9615 return -1;
9616 }
9617 }
9618 else if (parse_tls_method_options(args[i], &global_ssl.listen_default_sslmethods, err)) {
Emeric Brun2c86cbf2014-10-30 15:56:50 +01009619 memprintf(err, "unknown option '%s' on global statement '%s'.", args[i], args[0]);
9620 return -1;
9621 }
9622 i++;
9623 }
9624 return 0;
9625}
9626
9627/* parse the "ssl-default-server-options" keyword in global section */
9628static int ssl_parse_default_server_options(char **args, int section_type, struct proxy *curpx,
9629 struct proxy *defpx, const char *file, int line,
9630 char **err) {
9631 int i = 1;
9632
9633 if (*(args[i]) == 0) {
9634 memprintf(err, "global statement '%s' expects an option as an argument.", args[0]);
9635 return -1;
9636 }
9637 while (*(args[i])) {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02009638 if (!strcmp(args[i], "no-tls-tickets"))
Willy Tarreauef934602016-12-22 23:12:01 +01009639 global_ssl.connect_default_ssloptions |= SRV_SSL_O_NO_TLS_TICKETS;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02009640 else if (!strcmp(args[i], "ssl-min-ver") || !strcmp(args[i], "ssl-max-ver")) {
9641 if (!parse_tls_method_minmax(args, i, &global_ssl.connect_default_sslmethods, err))
9642 i++;
9643 else {
9644 memprintf(err, "%s on global statement '%s'.", *err, args[0]);
9645 return -1;
9646 }
9647 }
9648 else if (parse_tls_method_options(args[i], &global_ssl.connect_default_sslmethods, err)) {
Emeric Brun2c86cbf2014-10-30 15:56:50 +01009649 memprintf(err, "unknown option '%s' on global statement '%s'.", args[i], args[0]);
9650 return -1;
9651 }
9652 i++;
9653 }
9654 return 0;
9655}
9656
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01009657/* parse the "ca-base" / "crt-base" keywords in global section.
9658 * Returns <0 on alert, >0 on warning, 0 on success.
9659 */
9660static int ssl_parse_global_ca_crt_base(char **args, int section_type, struct proxy *curpx,
9661 struct proxy *defpx, const char *file, int line,
9662 char **err)
9663{
9664 char **target;
9665
Willy Tarreauef934602016-12-22 23:12:01 +01009666 target = (args[0][1] == 'a') ? &global_ssl.ca_base : &global_ssl.crt_base;
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01009667
9668 if (too_many_args(1, args, err, NULL))
9669 return -1;
9670
9671 if (*target) {
9672 memprintf(err, "'%s' already specified.", args[0]);
9673 return -1;
9674 }
9675
9676 if (*(args[1]) == 0) {
9677 memprintf(err, "global statement '%s' expects a directory path as an argument.", args[0]);
9678 return -1;
9679 }
9680 *target = strdup(args[1]);
9681 return 0;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00009682}
9683
9684/* parse the "ssl-mode-async" keyword in global section.
9685 * Returns <0 on alert, >0 on warning, 0 on success.
9686 */
9687static int ssl_parse_global_ssl_async(char **args, int section_type, struct proxy *curpx,
9688 struct proxy *defpx, const char *file, int line,
9689 char **err)
9690{
Willy Tarreau5db847a2019-05-09 14:13:35 +02009691#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00009692 global_ssl.async = 1;
Emeric Brunece0c332017-12-06 13:51:49 +01009693 global.ssl_used_async_engines = nb_engines;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00009694 return 0;
9695#else
9696 memprintf(err, "'%s': openssl library does not support async mode", args[0]);
9697 return -1;
9698#endif
9699}
9700
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02009701#ifndef OPENSSL_NO_ENGINE
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00009702static int ssl_check_async_engine_count(void) {
9703 int err_code = 0;
9704
Emeric Brun3854e012017-05-17 20:42:48 +02009705 if (global_ssl.async && (openssl_engines_initialized > 32)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01009706 ha_alert("ssl-mode-async only supports a maximum of 32 engines.\n");
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00009707 err_code = ERR_ABORT;
9708 }
9709 return err_code;
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01009710}
9711
Grant Zhang872f9c22017-01-21 01:10:18 +00009712/* parse the "ssl-engine" keyword in global section.
9713 * Returns <0 on alert, >0 on warning, 0 on success.
9714 */
9715static int ssl_parse_global_ssl_engine(char **args, int section_type, struct proxy *curpx,
9716 struct proxy *defpx, const char *file, int line,
9717 char **err)
9718{
9719 char *algo;
9720 int ret = -1;
9721
9722 if (*(args[1]) == 0) {
9723 memprintf(err, "global statement '%s' expects a valid engine name as an argument.", args[0]);
9724 return ret;
9725 }
9726
9727 if (*(args[2]) == 0) {
9728 /* if no list of algorithms is given, it defaults to ALL */
9729 algo = strdup("ALL");
9730 goto add_engine;
9731 }
9732
9733 /* otherwise the expected format is ssl-engine <engine_name> algo <list of algo> */
9734 if (strcmp(args[2], "algo") != 0) {
9735 memprintf(err, "global statement '%s' expects to have algo keyword.", args[0]);
9736 return ret;
9737 }
9738
9739 if (*(args[3]) == 0) {
9740 memprintf(err, "global statement '%s' expects algorithm names as an argument.", args[0]);
9741 return ret;
9742 }
9743 algo = strdup(args[3]);
9744
9745add_engine:
9746 if (ssl_init_single_engine(args[1], algo)==0) {
9747 openssl_engines_initialized++;
9748 ret = 0;
9749 }
9750 free(algo);
9751 return ret;
9752}
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02009753#endif
Grant Zhang872f9c22017-01-21 01:10:18 +00009754
Willy Tarreauf22e9682016-12-21 23:23:19 +01009755/* parse the "ssl-default-bind-ciphers" / "ssl-default-server-ciphers" keywords
9756 * in global section. Returns <0 on alert, >0 on warning, 0 on success.
9757 */
9758static int ssl_parse_global_ciphers(char **args, int section_type, struct proxy *curpx,
9759 struct proxy *defpx, const char *file, int line,
9760 char **err)
9761{
9762 char **target;
9763
Willy Tarreauef934602016-12-22 23:12:01 +01009764 target = (args[0][12] == 'b') ? &global_ssl.listen_default_ciphers : &global_ssl.connect_default_ciphers;
Willy Tarreauf22e9682016-12-21 23:23:19 +01009765
9766 if (too_many_args(1, args, err, NULL))
9767 return -1;
9768
9769 if (*(args[1]) == 0) {
9770 memprintf(err, "global statement '%s' expects a cipher suite as an argument.", args[0]);
9771 return -1;
9772 }
9773
9774 free(*target);
9775 *target = strdup(args[1]);
9776 return 0;
9777}
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009778
Emmanuel Hocdet839af572019-05-14 16:27:35 +02009779#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009780/* parse the "ssl-default-bind-ciphersuites" / "ssl-default-server-ciphersuites" keywords
9781 * in global section. Returns <0 on alert, >0 on warning, 0 on success.
9782 */
9783static int ssl_parse_global_ciphersuites(char **args, int section_type, struct proxy *curpx,
9784 struct proxy *defpx, const char *file, int line,
9785 char **err)
9786{
9787 char **target;
9788
9789 target = (args[0][12] == 'b') ? &global_ssl.listen_default_ciphersuites : &global_ssl.connect_default_ciphersuites;
9790
9791 if (too_many_args(1, args, err, NULL))
9792 return -1;
9793
9794 if (*(args[1]) == 0) {
9795 memprintf(err, "global statement '%s' expects a cipher suite as an argument.", args[0]);
9796 return -1;
9797 }
9798
9799 free(*target);
9800 *target = strdup(args[1]);
9801 return 0;
9802}
9803#endif
Willy Tarreauf22e9682016-12-21 23:23:19 +01009804
Willy Tarreau9ceda382016-12-21 23:13:03 +01009805/* parse various global tune.ssl settings consisting in positive integers.
9806 * Returns <0 on alert, >0 on warning, 0 on success.
9807 */
9808static int ssl_parse_global_int(char **args, int section_type, struct proxy *curpx,
9809 struct proxy *defpx, const char *file, int line,
9810 char **err)
9811{
9812 int *target;
9813
9814 if (strcmp(args[0], "tune.ssl.cachesize") == 0)
9815 target = &global.tune.sslcachesize;
9816 else if (strcmp(args[0], "tune.ssl.maxrecord") == 0)
Willy Tarreauef934602016-12-22 23:12:01 +01009817 target = (int *)&global_ssl.max_record;
Willy Tarreau9ceda382016-12-21 23:13:03 +01009818 else if (strcmp(args[0], "tune.ssl.ssl-ctx-cache-size") == 0)
Willy Tarreauef934602016-12-22 23:12:01 +01009819 target = &global_ssl.ctx_cache;
Willy Tarreau0bea58d2016-12-21 23:17:25 +01009820 else if (strcmp(args[0], "maxsslconn") == 0)
9821 target = &global.maxsslconn;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01009822 else if (strcmp(args[0], "tune.ssl.capture-cipherlist-size") == 0)
9823 target = &global_ssl.capture_cipherlist;
Willy Tarreau9ceda382016-12-21 23:13:03 +01009824 else {
9825 memprintf(err, "'%s' keyword not unhandled (please report this bug).", args[0]);
9826 return -1;
9827 }
9828
9829 if (too_many_args(1, args, err, NULL))
9830 return -1;
9831
9832 if (*(args[1]) == 0) {
9833 memprintf(err, "'%s' expects an integer argument.", args[0]);
9834 return -1;
9835 }
9836
9837 *target = atoi(args[1]);
9838 if (*target < 0) {
9839 memprintf(err, "'%s' expects a positive numeric value.", args[0]);
9840 return -1;
9841 }
9842 return 0;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01009843}
9844
9845static int ssl_parse_global_capture_cipherlist(char **args, int section_type, struct proxy *curpx,
9846 struct proxy *defpx, const char *file, int line,
9847 char **err)
9848{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01009849 int ret;
9850
9851 ret = ssl_parse_global_int(args, section_type, curpx, defpx, file, line, err);
9852 if (ret != 0)
9853 return ret;
9854
Willy Tarreaubafbe012017-11-24 17:34:44 +01009855 if (pool_head_ssl_capture) {
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01009856 memprintf(err, "'%s' is already configured.", args[0]);
9857 return -1;
9858 }
9859
Willy Tarreaubafbe012017-11-24 17:34:44 +01009860 pool_head_ssl_capture = create_pool("ssl-capture", sizeof(struct ssl_capture) + global_ssl.capture_cipherlist, MEM_F_SHARED);
9861 if (!pool_head_ssl_capture) {
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01009862 memprintf(err, "Out of memory error.");
9863 return -1;
9864 }
9865 return 0;
Willy Tarreau9ceda382016-12-21 23:13:03 +01009866}
9867
9868/* parse "ssl.force-private-cache".
9869 * Returns <0 on alert, >0 on warning, 0 on success.
9870 */
9871static int ssl_parse_global_private_cache(char **args, int section_type, struct proxy *curpx,
9872 struct proxy *defpx, const char *file, int line,
9873 char **err)
9874{
9875 if (too_many_args(0, args, err, NULL))
9876 return -1;
9877
Willy Tarreauef934602016-12-22 23:12:01 +01009878 global_ssl.private_cache = 1;
Willy Tarreau9ceda382016-12-21 23:13:03 +01009879 return 0;
9880}
9881
9882/* parse "ssl.lifetime".
9883 * Returns <0 on alert, >0 on warning, 0 on success.
9884 */
9885static int ssl_parse_global_lifetime(char **args, int section_type, struct proxy *curpx,
9886 struct proxy *defpx, const char *file, int line,
9887 char **err)
9888{
9889 const char *res;
9890
9891 if (too_many_args(1, args, err, NULL))
9892 return -1;
9893
9894 if (*(args[1]) == 0) {
9895 memprintf(err, "'%s' expects ssl sessions <lifetime> in seconds as argument.", args[0]);
9896 return -1;
9897 }
9898
Willy Tarreauef934602016-12-22 23:12:01 +01009899 res = parse_time_err(args[1], &global_ssl.life_time, TIME_UNIT_S);
Willy Tarreau9faebe32019-06-07 19:00:37 +02009900 if (res == PARSE_TIME_OVER) {
9901 memprintf(err, "timer overflow in argument '%s' to <%s> (maximum value is 2147483647 s or ~68 years).",
9902 args[1], args[0]);
9903 return -1;
9904 }
9905 else if (res == PARSE_TIME_UNDER) {
9906 memprintf(err, "timer underflow in argument '%s' to <%s> (minimum non-null value is 1 s).",
9907 args[1], args[0]);
9908 return -1;
9909 }
9910 else if (res) {
Willy Tarreau9ceda382016-12-21 23:13:03 +01009911 memprintf(err, "unexpected character '%c' in argument to <%s>.", *res, args[0]);
9912 return -1;
9913 }
9914 return 0;
9915}
9916
9917#ifndef OPENSSL_NO_DH
Willy Tarreau14e36a12016-12-21 23:28:13 +01009918/* parse "ssl-dh-param-file".
9919 * Returns <0 on alert, >0 on warning, 0 on success.
9920 */
9921static int ssl_parse_global_dh_param_file(char **args, int section_type, struct proxy *curpx,
9922 struct proxy *defpx, const char *file, int line,
9923 char **err)
9924{
9925 if (too_many_args(1, args, err, NULL))
9926 return -1;
9927
9928 if (*(args[1]) == 0) {
9929 memprintf(err, "'%s' expects a file path as an argument.", args[0]);
9930 return -1;
9931 }
9932
9933 if (ssl_sock_load_global_dh_param_from_file(args[1])) {
9934 memprintf(err, "'%s': unable to load DH parameters from file <%s>.", args[0], args[1]);
9935 return -1;
9936 }
9937 return 0;
9938}
9939
Willy Tarreau9ceda382016-12-21 23:13:03 +01009940/* parse "ssl.default-dh-param".
9941 * Returns <0 on alert, >0 on warning, 0 on success.
9942 */
9943static int ssl_parse_global_default_dh(char **args, int section_type, struct proxy *curpx,
9944 struct proxy *defpx, const char *file, int line,
9945 char **err)
9946{
9947 if (too_many_args(1, args, err, NULL))
9948 return -1;
9949
9950 if (*(args[1]) == 0) {
9951 memprintf(err, "'%s' expects an integer argument.", args[0]);
9952 return -1;
9953 }
9954
Willy Tarreauef934602016-12-22 23:12:01 +01009955 global_ssl.default_dh_param = atoi(args[1]);
9956 if (global_ssl.default_dh_param < 1024) {
Willy Tarreau9ceda382016-12-21 23:13:03 +01009957 memprintf(err, "'%s' expects a value >= 1024.", args[0]);
9958 return -1;
9959 }
9960 return 0;
9961}
9962#endif
9963
William Lallemand3af48e72020-02-03 17:15:52 +01009964
9965/*
9966 * parse "ssl-load-extra-files".
9967 * multiple arguments are allowed: "bundle", "sctl", "ocsp", "issuer", "all", "none"
9968 */
9969static int ssl_parse_global_extra_files(char **args, int section_type, struct proxy *curpx,
9970 struct proxy *defpx, const char *file, int line,
9971 char **err)
9972{
9973 int i;
9974 int gf = SSL_GF_NONE;
9975
9976 if (*(args[1]) == 0)
9977 goto err_arg;
9978
9979 for (i = 1; *args[i]; i++) {
9980
9981 if (!strcmp("bundle", args[i])) {
9982 gf |= SSL_GF_BUNDLE;
9983
9984 } else if (!strcmp("sctl", args[i])) {
9985 gf |= SSL_GF_SCTL;
9986
9987 } else if (!strcmp("ocsp", args[i])){
9988 gf |= SSL_GF_OCSP;
9989
9990 } else if (!strcmp("issuer", args[i])){
9991 gf |= SSL_GF_OCSP_ISSUER;
9992
9993 } else if (!strcmp("none", args[i])) {
9994 if (gf != SSL_GF_NONE)
9995 goto err_alone;
9996 gf = SSL_GF_NONE;
9997 i++;
9998 break;
9999
10000 } else if (!strcmp("all", args[i])) {
10001 if (gf != SSL_GF_NONE)
10002 goto err_alone;
10003 gf = SSL_GF_ALL;
10004 i++;
10005 break;
10006 } else {
10007 goto err_arg;
10008 }
10009 }
10010 /* break from loop but there are still arguments */
10011 if (*args[i])
10012 goto err_alone;
10013
10014 global_ssl.extra_files = gf;
10015
10016 return 0;
10017
10018err_alone:
10019 memprintf(err, "'%s' 'none' and 'all' can be only used alone", args[0]);
10020 return -1;
10021
10022err_arg:
10023 memprintf(err, "'%s' expects one or multiple arguments (none, all, bundle, sctl, ocsp, issuer).", args[0]);
10024 return -1;
10025}
10026
Willy Tarreau9ceda382016-12-21 23:13:03 +010010027
William Lallemand32af2032016-10-29 18:09:35 +020010028/* This function is used with TLS ticket keys management. It permits to browse
10029 * each reference. The variable <getnext> must contain the current node,
10030 * <end> point to the root node.
10031 */
10032#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
10033static inline
10034struct tls_keys_ref *tlskeys_list_get_next(struct tls_keys_ref *getnext, struct list *end)
10035{
10036 struct tls_keys_ref *ref = getnext;
10037
10038 while (1) {
10039
10040 /* Get next list entry. */
10041 ref = LIST_NEXT(&ref->list, struct tls_keys_ref *, list);
10042
10043 /* If the entry is the last of the list, return NULL. */
10044 if (&ref->list == end)
10045 return NULL;
10046
10047 return ref;
10048 }
10049}
10050
10051static inline
10052struct tls_keys_ref *tlskeys_ref_lookup_ref(const char *reference)
10053{
10054 int id;
10055 char *error;
10056
10057 /* If the reference starts by a '#', this is numeric id. */
10058 if (reference[0] == '#') {
10059 /* Try to convert the numeric id. If the conversion fails, the lookup fails. */
10060 id = strtol(reference + 1, &error, 10);
10061 if (*error != '\0')
10062 return NULL;
10063
10064 /* Perform the unique id lookup. */
10065 return tlskeys_ref_lookupid(id);
10066 }
10067
10068 /* Perform the string lookup. */
10069 return tlskeys_ref_lookup(reference);
10070}
10071#endif
10072
10073
10074#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
10075
10076static int cli_io_handler_tlskeys_files(struct appctx *appctx);
10077
10078static inline int cli_io_handler_tlskeys_entries(struct appctx *appctx) {
10079 return cli_io_handler_tlskeys_files(appctx);
10080}
10081
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010082/* dumps all tls keys. Relies on cli.i0 (non-null = only list file names), cli.i1
10083 * (next index to be dumped), and cli.p0 (next key reference).
10084 */
William Lallemand32af2032016-10-29 18:09:35 +020010085static int cli_io_handler_tlskeys_files(struct appctx *appctx) {
10086
10087 struct stream_interface *si = appctx->owner;
10088
10089 switch (appctx->st2) {
10090 case STAT_ST_INIT:
10091 /* Display the column headers. If the message cannot be sent,
Joseph Herlant017b3da2018-11-15 09:07:59 -080010092 * quit the function with returning 0. The function is called
William Lallemand32af2032016-10-29 18:09:35 +020010093 * later and restart at the state "STAT_ST_INIT".
10094 */
10095 chunk_reset(&trash);
10096
10097 if (appctx->io_handler == cli_io_handler_tlskeys_entries)
10098 chunk_appendf(&trash, "# id secret\n");
10099 else
10100 chunk_appendf(&trash, "# id (file)\n");
10101
Willy Tarreau06d80a92017-10-19 14:32:15 +020010102 if (ci_putchk(si_ic(si), &trash) == -1) {
Willy Tarreaudb398432018-11-15 11:08:52 +010010103 si_rx_room_blk(si);
William Lallemand32af2032016-10-29 18:09:35 +020010104 return 0;
10105 }
10106
William Lallemand32af2032016-10-29 18:09:35 +020010107 /* Now, we start the browsing of the references lists.
10108 * Note that the following call to LIST_ELEM return bad pointer. The only
10109 * available field of this pointer is <list>. It is used with the function
10110 * tlskeys_list_get_next() for retruning the first available entry
10111 */
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010112 if (appctx->ctx.cli.p0 == NULL) {
10113 appctx->ctx.cli.p0 = LIST_ELEM(&tlskeys_reference, struct tls_keys_ref *, list);
10114 appctx->ctx.cli.p0 = tlskeys_list_get_next(appctx->ctx.cli.p0, &tlskeys_reference);
William Lallemand32af2032016-10-29 18:09:35 +020010115 }
10116
10117 appctx->st2 = STAT_ST_LIST;
10118 /* fall through */
10119
10120 case STAT_ST_LIST:
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010121 while (appctx->ctx.cli.p0) {
10122 struct tls_keys_ref *ref = appctx->ctx.cli.p0;
William Lallemand32af2032016-10-29 18:09:35 +020010123
10124 chunk_reset(&trash);
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010125 if (appctx->io_handler == cli_io_handler_tlskeys_entries && appctx->ctx.cli.i1 == 0)
William Lallemand32af2032016-10-29 18:09:35 +020010126 chunk_appendf(&trash, "# ");
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010127
10128 if (appctx->ctx.cli.i1 == 0)
10129 chunk_appendf(&trash, "%d (%s)\n", ref->unique_id, ref->filename);
10130
William Lallemand32af2032016-10-29 18:09:35 +020010131 if (appctx->io_handler == cli_io_handler_tlskeys_entries) {
Christopher Faulet16f45c82018-02-16 11:23:49 +010010132 int head;
10133
10134 HA_RWLOCK_RDLOCK(TLSKEYS_REF_LOCK, &ref->lock);
10135 head = ref->tls_ticket_enc_index;
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010136 while (appctx->ctx.cli.i1 < TLS_TICKETS_NO) {
Willy Tarreau83061a82018-07-13 11:56:34 +020010137 struct buffer *t2 = get_trash_chunk();
William Lallemand32af2032016-10-29 18:09:35 +020010138
10139 chunk_reset(t2);
10140 /* should never fail here because we dump only a key in the t2 buffer */
Emeric Brun9e754772019-01-10 17:51:55 +010010141 if (ref->key_size_bits == 128) {
10142 t2->data = a2base64((char *)(ref->tlskeys + (head + 2 + appctx->ctx.cli.i1) % TLS_TICKETS_NO),
10143 sizeof(struct tls_sess_key_128),
10144 t2->area, t2->size);
10145 chunk_appendf(&trash, "%d.%d %s\n", ref->unique_id, appctx->ctx.cli.i1,
10146 t2->area);
10147 }
10148 else if (ref->key_size_bits == 256) {
10149 t2->data = a2base64((char *)(ref->tlskeys + (head + 2 + appctx->ctx.cli.i1) % TLS_TICKETS_NO),
10150 sizeof(struct tls_sess_key_256),
10151 t2->area, t2->size);
10152 chunk_appendf(&trash, "%d.%d %s\n", ref->unique_id, appctx->ctx.cli.i1,
10153 t2->area);
10154 }
10155 else {
10156 /* This case should never happen */
10157 chunk_appendf(&trash, "%d.%d <unknown>\n", ref->unique_id, appctx->ctx.cli.i1);
10158 }
William Lallemand32af2032016-10-29 18:09:35 +020010159
Willy Tarreau06d80a92017-10-19 14:32:15 +020010160 if (ci_putchk(si_ic(si), &trash) == -1) {
William Lallemand32af2032016-10-29 18:09:35 +020010161 /* let's try again later from this stream. We add ourselves into
10162 * this stream's users so that it can remove us upon termination.
10163 */
Christopher Faulet16f45c82018-02-16 11:23:49 +010010164 HA_RWLOCK_RDUNLOCK(TLSKEYS_REF_LOCK, &ref->lock);
Willy Tarreaudb398432018-11-15 11:08:52 +010010165 si_rx_room_blk(si);
William Lallemand32af2032016-10-29 18:09:35 +020010166 return 0;
10167 }
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010168 appctx->ctx.cli.i1++;
William Lallemand32af2032016-10-29 18:09:35 +020010169 }
Christopher Faulet16f45c82018-02-16 11:23:49 +010010170 HA_RWLOCK_RDUNLOCK(TLSKEYS_REF_LOCK, &ref->lock);
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010171 appctx->ctx.cli.i1 = 0;
William Lallemand32af2032016-10-29 18:09:35 +020010172 }
Willy Tarreau06d80a92017-10-19 14:32:15 +020010173 if (ci_putchk(si_ic(si), &trash) == -1) {
William Lallemand32af2032016-10-29 18:09:35 +020010174 /* let's try again later from this stream. We add ourselves into
10175 * this stream's users so that it can remove us upon termination.
10176 */
Willy Tarreaudb398432018-11-15 11:08:52 +010010177 si_rx_room_blk(si);
William Lallemand32af2032016-10-29 18:09:35 +020010178 return 0;
10179 }
10180
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010181 if (appctx->ctx.cli.i0 == 0) /* don't display everything if not necessary */
William Lallemand32af2032016-10-29 18:09:35 +020010182 break;
10183
10184 /* get next list entry and check the end of the list */
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010185 appctx->ctx.cli.p0 = tlskeys_list_get_next(appctx->ctx.cli.p0, &tlskeys_reference);
William Lallemand32af2032016-10-29 18:09:35 +020010186 }
10187
10188 appctx->st2 = STAT_ST_FIN;
10189 /* fall through */
10190
10191 default:
10192 appctx->st2 = STAT_ST_FIN;
10193 return 1;
10194 }
10195 return 0;
10196}
10197
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010198/* sets cli.i0 to non-zero if only file lists should be dumped */
Aurélien Nephtaliabbf6072018-04-18 13:26:46 +020010199static int cli_parse_show_tlskeys(char **args, char *payload, struct appctx *appctx, void *private)
William Lallemand32af2032016-10-29 18:09:35 +020010200{
William Lallemand32af2032016-10-29 18:09:35 +020010201 /* no parameter, shows only file list */
10202 if (!*args[2]) {
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010203 appctx->ctx.cli.i0 = 1;
William Lallemand32af2032016-10-29 18:09:35 +020010204 appctx->io_handler = cli_io_handler_tlskeys_files;
Willy Tarreau3067bfa2016-12-05 14:50:15 +010010205 return 0;
William Lallemand32af2032016-10-29 18:09:35 +020010206 }
10207
10208 if (args[2][0] == '*') {
10209 /* list every TLS ticket keys */
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010210 appctx->ctx.cli.i0 = 1;
William Lallemand32af2032016-10-29 18:09:35 +020010211 } else {
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010212 appctx->ctx.cli.p0 = tlskeys_ref_lookup_ref(args[2]);
Willy Tarreau9d008692019-08-09 11:21:01 +020010213 if (!appctx->ctx.cli.p0)
10214 return cli_err(appctx, "'show tls-keys' unable to locate referenced filename\n");
William Lallemand32af2032016-10-29 18:09:35 +020010215 }
William Lallemand32af2032016-10-29 18:09:35 +020010216 appctx->io_handler = cli_io_handler_tlskeys_entries;
Willy Tarreau3067bfa2016-12-05 14:50:15 +010010217 return 0;
William Lallemand32af2032016-10-29 18:09:35 +020010218}
10219
Aurélien Nephtaliabbf6072018-04-18 13:26:46 +020010220static int cli_parse_set_tlskeys(char **args, char *payload, struct appctx *appctx, void *private)
William Lallemand32af2032016-10-29 18:09:35 +020010221{
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010222 struct tls_keys_ref *ref;
Willy Tarreau1c913e42018-08-22 05:26:57 +020010223 int ret;
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010224
William Lallemand32af2032016-10-29 18:09:35 +020010225 /* Expect two parameters: the filename and the new new TLS key in encoding */
Willy Tarreau9d008692019-08-09 11:21:01 +020010226 if (!*args[3] || !*args[4])
10227 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 +020010228
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010229 ref = tlskeys_ref_lookup_ref(args[3]);
Willy Tarreau9d008692019-08-09 11:21:01 +020010230 if (!ref)
10231 return cli_err(appctx, "'set ssl tls-key' unable to locate referenced filename\n");
William Lallemand32af2032016-10-29 18:09:35 +020010232
Willy Tarreau1c913e42018-08-22 05:26:57 +020010233 ret = base64dec(args[4], strlen(args[4]), trash.area, trash.size);
Willy Tarreau9d008692019-08-09 11:21:01 +020010234 if (ret < 0)
10235 return cli_err(appctx, "'set ssl tls-key' received invalid base64 encoded TLS key.\n");
Emeric Brun9e754772019-01-10 17:51:55 +010010236
Willy Tarreau1c913e42018-08-22 05:26:57 +020010237 trash.data = ret;
Willy Tarreau9d008692019-08-09 11:21:01 +020010238 if (ssl_sock_update_tlskey_ref(ref, &trash) < 0)
10239 return cli_err(appctx, "'set ssl tls-key' received a key of wrong size.\n");
William Lallemand32af2032016-10-29 18:09:35 +020010240
Willy Tarreau9d008692019-08-09 11:21:01 +020010241 return cli_msg(appctx, LOG_INFO, "TLS ticket key updated!\n");
William Lallemand32af2032016-10-29 18:09:35 +020010242}
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +010010243#endif
William Lallemand32af2032016-10-29 18:09:35 +020010244
William Lallemand44b35322019-10-17 16:28:40 +020010245
10246/* Type of SSL payloads that can be updated over the CLI */
10247
10248enum {
10249 CERT_TYPE_PEM = 0,
Emmanuel Hocdetf6ac4fa2019-10-30 17:41:27 +010010250#if ((defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP) || defined OPENSSL_IS_BORINGSSL)
William Lallemand44b35322019-10-17 16:28:40 +020010251 CERT_TYPE_OCSP,
Emmanuel Hocdetf6ac4fa2019-10-30 17:41:27 +010010252#endif
William Lallemand44b35322019-10-17 16:28:40 +020010253 CERT_TYPE_ISSUER,
Emmanuel Hocdetf6ac4fa2019-10-30 17:41:27 +010010254#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
William Lallemand44b35322019-10-17 16:28:40 +020010255 CERT_TYPE_SCTL,
Emmanuel Hocdetf6ac4fa2019-10-30 17:41:27 +010010256#endif
William Lallemand44b35322019-10-17 16:28:40 +020010257 CERT_TYPE_MAX,
10258};
10259
10260struct {
10261 const char *ext;
10262 int type;
10263 int (*load)(const char *path, char *payload, struct cert_key_and_chain *ckch, char **err);
10264 /* add a parsing callback */
William Lallemandf29cdef2019-10-23 15:00:52 +020010265} cert_exts[CERT_TYPE_MAX+1] = {
William Lallemand44b35322019-10-17 16:28:40 +020010266 [CERT_TYPE_PEM] = { "", CERT_TYPE_PEM, &ssl_sock_load_pem_into_ckch }, /* default mode, no extensions */
William Lallemand541a5342019-10-23 14:11:54 +020010267#if ((defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP) || defined OPENSSL_IS_BORINGSSL)
William Lallemand44b35322019-10-17 16:28:40 +020010268 [CERT_TYPE_OCSP] = { "ocsp", CERT_TYPE_OCSP, &ssl_sock_load_ocsp_response_from_file },
William Lallemand541a5342019-10-23 14:11:54 +020010269#endif
10270#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
William Lallemand44b35322019-10-17 16:28:40 +020010271 [CERT_TYPE_SCTL] = { "sctl", CERT_TYPE_SCTL, &ssl_sock_load_sctl_from_file },
William Lallemand541a5342019-10-23 14:11:54 +020010272#endif
William Lallemand44b35322019-10-17 16:28:40 +020010273 [CERT_TYPE_ISSUER] = { "issuer", CERT_TYPE_ISSUER, &ssl_sock_load_issuer_file_into_ckch },
William Lallemandf29cdef2019-10-23 15:00:52 +020010274 [CERT_TYPE_MAX] = { NULL, CERT_TYPE_MAX, NULL },
William Lallemand44b35322019-10-17 16:28:40 +020010275};
10276
William Lallemand430413e2019-10-28 14:30:47 +010010277/* states of the CLI IO handler for 'set ssl cert' */
10278enum {
10279 SETCERT_ST_INIT = 0,
10280 SETCERT_ST_GEN,
10281 SETCERT_ST_INSERT,
10282 SETCERT_ST_FIN,
10283};
William Lallemand8f840d72019-10-23 10:53:05 +020010284
William Lallemandd4f946c2019-12-05 10:26:40 +010010285/* release function of the `show ssl cert' command */
10286static void cli_release_show_cert(struct appctx *appctx)
10287{
10288 HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
10289}
10290
10291/* IO handler of "show ssl cert <filename>" */
10292static int cli_io_handler_show_cert(struct appctx *appctx)
10293{
10294 struct buffer *trash = alloc_trash_chunk();
10295 struct ebmb_node *node;
10296 struct stream_interface *si = appctx->owner;
10297 struct ckch_store *ckchs;
William Lallemandd4f946c2019-12-05 10:26:40 +010010298
10299 if (trash == NULL)
10300 return 1;
10301
10302 if (!appctx->ctx.ssl.old_ckchs) {
10303 if (ckchs_transaction.old_ckchs) {
10304 ckchs = ckchs_transaction.old_ckchs;
10305 chunk_appendf(trash, "# transaction\n");
10306 if (!ckchs->multi) {
10307 chunk_appendf(trash, "*%s\n", ckchs->path);
William Lallemandba22e902019-12-18 20:36:01 +010010308#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
William Lallemandd4f946c2019-12-05 10:26:40 +010010309 } else {
William Lallemanda25a19f2020-01-29 00:04:24 +010010310 int n;
10311
William Lallemandd4f946c2019-12-05 10:26:40 +010010312 chunk_appendf(trash, "*%s:", ckchs->path);
10313 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
10314 if (ckchs->ckch[n].cert)
10315 chunk_appendf(trash, " %s.%s\n", ckchs->path, SSL_SOCK_KEYTYPE_NAMES[n]);
10316 }
10317 chunk_appendf(trash, "\n");
William Lallemandba22e902019-12-18 20:36:01 +010010318#endif
William Lallemandd4f946c2019-12-05 10:26:40 +010010319 }
10320 }
10321 }
10322
10323 if (!appctx->ctx.cli.p0) {
10324 chunk_appendf(trash, "# filename\n");
10325 node = ebmb_first(&ckchs_tree);
10326 } else {
10327 node = &((struct ckch_store *)appctx->ctx.cli.p0)->node;
10328 }
10329 while (node) {
10330 ckchs = ebmb_entry(node, struct ckch_store, node);
10331 if (!ckchs->multi) {
10332 chunk_appendf(trash, "%s\n", ckchs->path);
William Lallemandba22e902019-12-18 20:36:01 +010010333#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
William Lallemandd4f946c2019-12-05 10:26:40 +010010334 } else {
William Lallemanda25a19f2020-01-29 00:04:24 +010010335 int n;
10336
William Lallemandd4f946c2019-12-05 10:26:40 +010010337 chunk_appendf(trash, "%s:", ckchs->path);
10338 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
10339 if (ckchs->ckch[n].cert)
10340 chunk_appendf(trash, " %s.%s", ckchs->path, SSL_SOCK_KEYTYPE_NAMES[n]);
10341 }
10342 chunk_appendf(trash, "\n");
William Lallemandba22e902019-12-18 20:36:01 +010010343#endif
William Lallemandd4f946c2019-12-05 10:26:40 +010010344 }
10345
10346 node = ebmb_next(node);
10347 if (ci_putchk(si_ic(si), trash) == -1) {
10348 si_rx_room_blk(si);
10349 goto yield;
10350 }
10351 }
10352
10353 appctx->ctx.cli.p0 = NULL;
10354 free_trash_chunk(trash);
10355 return 1;
10356yield:
10357
10358 free_trash_chunk(trash);
10359 appctx->ctx.cli.p0 = ckchs;
10360 return 0; /* should come back */
10361}
10362
10363/* IO handler of the details "show ssl cert <filename>" */
10364static int cli_io_handler_show_cert_detail(struct appctx *appctx)
10365{
10366 struct stream_interface *si = appctx->owner;
10367 struct ckch_store *ckchs = appctx->ctx.cli.p0;
10368 struct buffer *out = alloc_trash_chunk();
10369 struct buffer *tmp = alloc_trash_chunk();
10370 X509_NAME *name = NULL;
10371 int write = -1;
10372 BIO *bio = NULL;
10373
10374 if (!tmp || !out)
10375 goto end;
10376
10377 if (!ckchs->multi) {
10378 chunk_appendf(out, "Filename: ");
10379 if (ckchs == ckchs_transaction.new_ckchs)
10380 chunk_appendf(out, "*");
10381 chunk_appendf(out, "%s\n", ckchs->path);
10382 chunk_appendf(out, "Serial: ");
10383 if (ssl_sock_get_serial(ckchs->ckch->cert, tmp) == -1)
10384 goto end;
10385 dump_binary(out, tmp->area, tmp->data);
10386 chunk_appendf(out, "\n");
10387
10388 chunk_appendf(out, "notBefore: ");
10389 chunk_reset(tmp);
10390 if ((bio = BIO_new(BIO_s_mem())) == NULL)
10391 goto end;
10392 if (ASN1_TIME_print(bio, X509_getm_notBefore(ckchs->ckch->cert)) == 0)
10393 goto end;
10394 write = BIO_read(bio, tmp->area, tmp->size-1);
10395 tmp->area[write] = '\0';
10396 BIO_free(bio);
10397 chunk_appendf(out, "%s\n", tmp->area);
10398
10399 chunk_appendf(out, "notAfter: ");
10400 chunk_reset(tmp);
10401 if ((bio = BIO_new(BIO_s_mem())) == NULL)
10402 goto end;
10403 if (ASN1_TIME_print(bio, X509_getm_notAfter(ckchs->ckch->cert)) == 0)
10404 goto end;
10405 if ((write = BIO_read(bio, tmp->area, tmp->size-1)) <= 0)
10406 goto end;
10407 tmp->area[write] = '\0';
10408 BIO_free(bio);
10409 chunk_appendf(out, "%s\n", tmp->area);
10410
10411
10412 chunk_appendf(out, "Issuer: ");
10413 if ((name = X509_get_issuer_name(ckchs->ckch->cert)) == NULL)
10414 goto end;
10415 if ((ssl_sock_get_dn_oneline(name, tmp)) == -1)
10416 goto end;
10417 *(tmp->area + tmp->data) = '\0';
10418 chunk_appendf(out, "%s\n", tmp->area);
10419
10420 chunk_appendf(out, "Subject: ");
10421 if ((name = X509_get_subject_name(ckchs->ckch->cert)) == NULL)
10422 goto end;
10423 if ((ssl_sock_get_dn_oneline(name, tmp)) == -1)
10424 goto end;
10425 *(tmp->area + tmp->data) = '\0';
10426 chunk_appendf(out, "%s\n", tmp->area);
10427
10428
10429#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
10430 chunk_appendf(out, "Subject Alternative Name: ");
10431 if (ssl_sock_get_san_oneline(ckchs->ckch->cert, out) == -1)
10432 goto end;
10433 *(out->area + out->data) = '\0';
10434 chunk_appendf(out, "\n");
10435#endif
10436 chunk_reset(tmp);
10437 chunk_appendf(out, "Algorithm: ");
10438 if (cert_get_pkey_algo(ckchs->ckch->cert, tmp) == 0)
10439 goto end;
10440 chunk_appendf(out, "%s\n", tmp->area);
10441
10442 chunk_reset(tmp);
10443 chunk_appendf(out, "SHA1 FingerPrint: ");
10444 if (X509_digest(ckchs->ckch->cert, EVP_sha1(), (unsigned char *) tmp->area,
10445 (unsigned int *)&tmp->data) == 0)
10446 goto end;
10447 dump_binary(out, tmp->area, tmp->data);
10448 chunk_appendf(out, "\n");
10449 }
10450
10451 if (ci_putchk(si_ic(si), out) == -1) {
10452 si_rx_room_blk(si);
10453 goto yield;
10454 }
10455
10456end:
10457 free_trash_chunk(tmp);
10458 free_trash_chunk(out);
10459 return 1;
10460yield:
10461 free_trash_chunk(tmp);
10462 free_trash_chunk(out);
10463 return 0; /* should come back */
10464}
10465
10466/* parsing function for 'show ssl cert [certfile]' */
10467static int cli_parse_show_cert(char **args, char *payload, struct appctx *appctx, void *private)
10468{
10469 struct ckch_store *ckchs;
10470
10471 if (!cli_has_level(appctx, ACCESS_LVL_OPER))
10472 return cli_err(appctx, "Can't allocate memory!\n");
10473
10474 /* The operations on the CKCH architecture are locked so we can
10475 * manipulate ckch_store and ckch_inst */
10476 if (HA_SPIN_TRYLOCK(CKCH_LOCK, &ckch_lock))
10477 return cli_err(appctx, "Can't show!\nOperations on certificates are currently locked!\n");
10478
10479 /* check if there is a certificate to lookup */
10480 if (*args[3]) {
10481 if (*args[3] == '*') {
10482 if (!ckchs_transaction.new_ckchs)
10483 goto error;
10484
10485 ckchs = ckchs_transaction.new_ckchs;
10486
10487 if (strcmp(args[3] + 1, ckchs->path))
10488 goto error;
10489
10490 } else {
10491 if ((ckchs = ckchs_lookup(args[3])) == NULL)
10492 goto error;
10493
10494 }
10495
10496 if (ckchs->multi)
10497 goto error;
10498
10499 appctx->ctx.cli.p0 = ckchs;
10500 /* use the IO handler that shows details */
10501 appctx->io_handler = cli_io_handler_show_cert_detail;
10502 }
10503
10504 return 0;
10505
10506error:
10507 HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
10508 return cli_err(appctx, "Can't display the certificate: Not found or the certificate is a bundle!\n");
10509}
10510
William Lallemand430413e2019-10-28 14:30:47 +010010511/* release function of the `set ssl cert' command, free things and unlock the spinlock */
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010512static void cli_release_commit_cert(struct appctx *appctx)
William Lallemand8f840d72019-10-23 10:53:05 +020010513{
10514 struct ckch_store *new_ckchs;
10515 struct ckch_inst *ckchi, *ckchis;
William Lallemand8f840d72019-10-23 10:53:05 +020010516
William Lallemand430413e2019-10-28 14:30:47 +010010517 HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
William Lallemand8f840d72019-10-23 10:53:05 +020010518
William Lallemand430413e2019-10-28 14:30:47 +010010519 if (appctx->st2 != SETCERT_ST_FIN) {
William Lallemand8f840d72019-10-23 10:53:05 +020010520 /* 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 +010010521 new_ckchs = appctx->ctx.ssl.new_ckchs;
William Lallemand8f840d72019-10-23 10:53:05 +020010522
William Lallemandbeea2a42019-10-30 17:45:33 +010010523 if (!new_ckchs)
10524 return;
William Lallemand8f840d72019-10-23 10:53:05 +020010525
William Lallemandbeea2a42019-10-30 17:45:33 +010010526 /* if the allocation failed, we need to free everything from the temporary list */
10527 list_for_each_entry_safe(ckchi, ckchis, &new_ckchs->ckch_inst, by_ckchs) {
10528 struct sni_ctx *sc0, *sc0s;
William Lallemand8f840d72019-10-23 10:53:05 +020010529
William Lallemandbeea2a42019-10-30 17:45:33 +010010530 list_for_each_entry_safe(sc0, sc0s, &ckchi->sni_ctx, by_ckch_inst) {
10531 if (sc0->order == 0) /* we only free if it's the first inserted */
10532 SSL_CTX_free(sc0->ctx);
10533 LIST_DEL(&sc0->by_ckch_inst);
10534 free(sc0);
William Lallemand8f840d72019-10-23 10:53:05 +020010535 }
William Lallemandbeea2a42019-10-30 17:45:33 +010010536 LIST_DEL(&ckchi->by_ckchs);
10537 free(ckchi);
William Lallemand8f840d72019-10-23 10:53:05 +020010538 }
William Lallemandbeea2a42019-10-30 17:45:33 +010010539 ckchs_free(new_ckchs);
William Lallemand8f840d72019-10-23 10:53:05 +020010540 }
10541}
10542
10543
10544/*
10545 * This function tries to create the new ckch_inst and their SNIs
10546 */
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010547static int cli_io_handler_commit_cert(struct appctx *appctx)
William Lallemand8f840d72019-10-23 10:53:05 +020010548{
10549 struct stream_interface *si = appctx->owner;
10550 int y = 0;
10551 char *err = NULL;
10552 int errcode = 0;
10553 struct ckch_store *old_ckchs, *new_ckchs = NULL;
10554 struct ckch_inst *ckchi, *ckchis;
William Lallemand8f840d72019-10-23 10:53:05 +020010555 struct buffer *trash = alloc_trash_chunk();
William Lallemand8ef0c2a2019-11-21 16:30:34 +010010556 struct sni_ctx *sc0, *sc0s;
William Lallemand8f840d72019-10-23 10:53:05 +020010557
William Lallemand33cc76f2019-10-31 11:43:45 +010010558 if (trash == NULL)
10559 goto error;
10560
William Lallemand8f840d72019-10-23 10:53:05 +020010561 if (unlikely(si_ic(si)->flags & (CF_WRITE_ERROR|CF_SHUTW)))
10562 goto error;
10563
William Lallemand430413e2019-10-28 14:30:47 +010010564 while (1) {
10565 switch (appctx->st2) {
10566 case SETCERT_ST_INIT:
10567 /* This state just print the update message */
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010568 chunk_printf(trash, "Committing %s", ckchs_transaction.path);
William Lallemand430413e2019-10-28 14:30:47 +010010569 if (ci_putchk(si_ic(si), trash) == -1) {
10570 si_rx_room_blk(si);
William Lallemand8f840d72019-10-23 10:53:05 +020010571 goto yield;
William Lallemand430413e2019-10-28 14:30:47 +010010572 }
10573 appctx->st2 = SETCERT_ST_GEN;
10574 /* fallthrough */
10575 case SETCERT_ST_GEN:
10576 /*
10577 * This state generates the ckch instances with their
10578 * sni_ctxs and SSL_CTX.
10579 *
William Lallemand430413e2019-10-28 14:30:47 +010010580 * Since the SSL_CTX generation can be CPU consumer, we
10581 * yield every 10 instances.
10582 */
William Lallemand8f840d72019-10-23 10:53:05 +020010583
William Lallemandbeea2a42019-10-30 17:45:33 +010010584 old_ckchs = appctx->ctx.ssl.old_ckchs;
10585 new_ckchs = appctx->ctx.ssl.new_ckchs;
William Lallemand8f840d72019-10-23 10:53:05 +020010586
William Lallemandbeea2a42019-10-30 17:45:33 +010010587 if (!new_ckchs)
10588 continue;
William Lallemand8f840d72019-10-23 10:53:05 +020010589
William Lallemandbeea2a42019-10-30 17:45:33 +010010590 /* get the next ckchi to regenerate */
10591 ckchi = appctx->ctx.ssl.next_ckchi;
10592 /* we didn't start yet, set it to the first elem */
10593 if (ckchi == NULL)
10594 ckchi = LIST_ELEM(old_ckchs->ckch_inst.n, typeof(ckchi), by_ckchs);
William Lallemand8f840d72019-10-23 10:53:05 +020010595
William Lallemandbeea2a42019-10-30 17:45:33 +010010596 /* walk through the old ckch_inst and creates new ckch_inst using the updated ckchs */
10597 list_for_each_entry_from(ckchi, &old_ckchs->ckch_inst, by_ckchs) {
10598 struct ckch_inst *new_inst;
William Lallemand8f840d72019-10-23 10:53:05 +020010599
William Lallemandbeea2a42019-10-30 17:45:33 +010010600 /* it takes a lot of CPU to creates SSL_CTXs, so we yield every 10 CKCH instances */
10601 if (y >= 10) {
10602 /* save the next ckchi to compute */
10603 appctx->ctx.ssl.next_ckchi = ckchi;
10604 goto yield;
10605 }
William Lallemand8f840d72019-10-23 10:53:05 +020010606
William Lallemandbeea2a42019-10-30 17:45:33 +010010607 if (new_ckchs->multi)
10608 errcode |= ckch_inst_new_load_multi_store(new_ckchs->path, new_ckchs, ckchi->bind_conf, ckchi->ssl_conf, NULL, 0, &new_inst, &err);
10609 else
10610 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 +020010611
William Lallemandbeea2a42019-10-30 17:45:33 +010010612 if (errcode & ERR_CODE)
10613 goto error;
William Lallemand8f840d72019-10-23 10:53:05 +020010614
William Lallemand21724f02019-11-04 17:56:13 +010010615 /* if the previous ckchi was used as the default */
10616 if (ckchi->is_default)
10617 new_inst->is_default = 1;
10618
William Lallemand8ef0c2a2019-11-21 16:30:34 +010010619 /* we need to initialize the SSL_CTX generated */
10620 /* TODO: the prepare_ctx function need to be reworked to be safer there */
10621 list_for_each_entry_safe(sc0, sc0s, &ckchi->sni_ctx, by_ckch_inst) {
10622 if (!sc0->order) { /* we initiliazed only the first SSL_CTX because it's the same in the other sni_ctx's */
10623 errcode |= ssl_sock_prepare_ctx(ckchi->bind_conf, ckchi->ssl_conf, sc0->ctx, &err);
10624 if (errcode & ERR_CODE)
10625 goto error;
10626 }
10627 }
10628
10629
William Lallemandbeea2a42019-10-30 17:45:33 +010010630 /* display one dot per new instance */
10631 chunk_appendf(trash, ".");
10632 /* link the new ckch_inst to the duplicate */
10633 LIST_ADDQ(&new_ckchs->ckch_inst, &new_inst->by_ckchs);
10634 y++;
10635 }
William Lallemand430413e2019-10-28 14:30:47 +010010636 appctx->st2 = SETCERT_ST_INSERT;
10637 /* fallthrough */
10638 case SETCERT_ST_INSERT:
10639 /* The generation is finished, we can insert everything */
William Lallemand8f840d72019-10-23 10:53:05 +020010640
William Lallemandbeea2a42019-10-30 17:45:33 +010010641 old_ckchs = appctx->ctx.ssl.old_ckchs;
10642 new_ckchs = appctx->ctx.ssl.new_ckchs;
William Lallemand8f840d72019-10-23 10:53:05 +020010643
William Lallemandbeea2a42019-10-30 17:45:33 +010010644 if (!new_ckchs)
10645 continue;
William Lallemand430413e2019-10-28 14:30:47 +010010646
William Lallemand21724f02019-11-04 17:56:13 +010010647 /* First, we insert every new SNIs in the trees, also replace the default_ctx */
William Lallemandbeea2a42019-10-30 17:45:33 +010010648 list_for_each_entry_safe(ckchi, ckchis, &new_ckchs->ckch_inst, by_ckchs) {
10649 HA_RWLOCK_WRLOCK(SNI_LOCK, &ckchi->bind_conf->sni_lock);
10650 ssl_sock_load_cert_sni(ckchi, ckchi->bind_conf);
10651 HA_RWLOCK_WRUNLOCK(SNI_LOCK, &ckchi->bind_conf->sni_lock);
10652 }
William Lallemand8f840d72019-10-23 10:53:05 +020010653
William Lallemandbeea2a42019-10-30 17:45:33 +010010654 /* delete the old sni_ctx, the old ckch_insts and the ckch_store */
10655 list_for_each_entry_safe(ckchi, ckchis, &old_ckchs->ckch_inst, by_ckchs) {
William Lallemand430413e2019-10-28 14:30:47 +010010656
William Lallemandbeea2a42019-10-30 17:45:33 +010010657 HA_RWLOCK_WRLOCK(SNI_LOCK, &ckchi->bind_conf->sni_lock);
10658 list_for_each_entry_safe(sc0, sc0s, &ckchi->sni_ctx, by_ckch_inst) {
10659 ebmb_delete(&sc0->name);
10660 LIST_DEL(&sc0->by_ckch_inst);
10661 free(sc0);
William Lallemand430413e2019-10-28 14:30:47 +010010662 }
William Lallemandbeea2a42019-10-30 17:45:33 +010010663 HA_RWLOCK_WRUNLOCK(SNI_LOCK, &ckchi->bind_conf->sni_lock);
10664 LIST_DEL(&ckchi->by_ckchs);
10665 free(ckchi);
10666 }
William Lallemand8f840d72019-10-23 10:53:05 +020010667
William Lallemandbeea2a42019-10-30 17:45:33 +010010668 /* Replace the old ckchs by the new one */
10669 ebmb_delete(&old_ckchs->node);
10670 ckchs_free(old_ckchs);
10671 ebst_insert(&ckchs_tree, &new_ckchs->node);
William Lallemand430413e2019-10-28 14:30:47 +010010672 appctx->st2 = SETCERT_ST_FIN;
10673 /* fallthrough */
10674 case SETCERT_ST_FIN:
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010675 /* we achieved the transaction, we can set everything to NULL */
10676 free(ckchs_transaction.path);
10677 ckchs_transaction.path = NULL;
10678 ckchs_transaction.new_ckchs = NULL;
10679 ckchs_transaction.old_ckchs = NULL;
William Lallemand430413e2019-10-28 14:30:47 +010010680 goto end;
10681 }
William Lallemand8f840d72019-10-23 10:53:05 +020010682 }
William Lallemand430413e2019-10-28 14:30:47 +010010683end:
William Lallemand8f840d72019-10-23 10:53:05 +020010684
William Lallemanded442432019-11-21 16:41:07 +010010685 chunk_appendf(trash, "\n");
10686 if (errcode & ERR_WARN)
Tim Duesterhusc0e820c2019-11-23 23:52:30 +010010687 chunk_appendf(trash, "%s", err);
William Lallemanded442432019-11-21 16:41:07 +010010688 chunk_appendf(trash, "Success!\n");
William Lallemand430413e2019-10-28 14:30:47 +010010689 if (ci_putchk(si_ic(si), trash) == -1)
10690 si_rx_room_blk(si);
10691 free_trash_chunk(trash);
10692 /* success: call the release function and don't come back */
10693 return 1;
William Lallemand8f840d72019-10-23 10:53:05 +020010694yield:
10695 /* store the state */
10696 if (ci_putchk(si_ic(si), trash) == -1)
10697 si_rx_room_blk(si);
10698 free_trash_chunk(trash);
10699 si_rx_endp_more(si); /* let's come back later */
William Lallemand8f840d72019-10-23 10:53:05 +020010700 return 0; /* should come back */
10701
10702error:
10703 /* spin unlock and free are done in the release function */
William Lallemand33cc76f2019-10-31 11:43:45 +010010704 if (trash) {
10705 chunk_appendf(trash, "\n%sFailed!\n", err);
10706 if (ci_putchk(si_ic(si), trash) == -1)
10707 si_rx_room_blk(si);
10708 free_trash_chunk(trash);
10709 }
William Lallemand430413e2019-10-28 14:30:47 +010010710 /* error: call the release function and don't come back */
10711 return 1;
William Lallemand8f840d72019-10-23 10:53:05 +020010712}
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010713
10714/*
10715 * Parsing function of 'commit ssl cert'
10716 */
10717static int cli_parse_commit_cert(char **args, char *payload, struct appctx *appctx, void *private)
10718{
10719 char *err = NULL;
10720
William Lallemand230662a2019-12-03 13:32:54 +010010721 if (!cli_has_level(appctx, ACCESS_LVL_ADMIN))
10722 return 1;
10723
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010724 if (!*args[3])
10725 return cli_err(appctx, "'commit ssl cert expects a filename\n");
10726
10727 /* The operations on the CKCH architecture are locked so we can
10728 * manipulate ckch_store and ckch_inst */
10729 if (HA_SPIN_TRYLOCK(CKCH_LOCK, &ckch_lock))
10730 return cli_err(appctx, "Can't commit the certificate!\nOperations on certificates are currently locked!\n");
10731
10732 if (!ckchs_transaction.path) {
10733 memprintf(&err, "No ongoing transaction! !\n");
10734 goto error;
10735 }
10736
10737 if (strcmp(ckchs_transaction.path, args[3]) != 0) {
10738 memprintf(&err, "The ongoing transaction is about '%s' but you are trying to set '%s'\n", ckchs_transaction.path, args[3]);
10739 goto error;
10740 }
10741
10742 /* init the appctx structure */
10743 appctx->st2 = SETCERT_ST_INIT;
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010744 appctx->ctx.ssl.next_ckchi = NULL;
10745 appctx->ctx.ssl.new_ckchs = ckchs_transaction.new_ckchs;
10746 appctx->ctx.ssl.old_ckchs = ckchs_transaction.old_ckchs;
10747
10748 /* we don't unlock there, it will be unlock after the IO handler, in the release handler */
10749 return 0;
10750
10751error:
10752
10753 HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
10754 err = memprintf(&err, "%sCan't commit %s!\n", err ? err : "", args[3]);
10755
10756 return cli_dynerr(appctx, err);
10757}
10758
10759
William Lallemand8f840d72019-10-23 10:53:05 +020010760/*
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010761 * Parsing function of `set ssl cert`, it updates or creates a temporary ckch.
William Lallemand8f840d72019-10-23 10:53:05 +020010762 */
William Lallemand150bfa82019-09-19 17:12:49 +020010763static int cli_parse_set_cert(char **args, char *payload, struct appctx *appctx, void *private)
10764{
William Lallemand0c3b7d92019-10-18 11:27:07 +020010765 struct ckch_store *new_ckchs = NULL;
William Lallemand8f840d72019-10-23 10:53:05 +020010766 struct ckch_store *old_ckchs = NULL;
William Lallemand150bfa82019-09-19 17:12:49 +020010767 char *err = NULL;
William Lallemand963b2e72019-10-14 11:38:36 +020010768 int i;
William Lallemand849eed62019-10-17 16:23:50 +020010769 int bundle = -1; /* TRUE if >= 0 (ckch index) */
Emeric Brunf69ed1d2019-10-17 11:56:56 +020010770 int errcode = 0;
William Lallemand44b35322019-10-17 16:28:40 +020010771 char *end;
10772 int type = CERT_TYPE_PEM;
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010773 struct cert_key_and_chain *ckch;
10774 struct buffer *buf;
William Lallemand8f840d72019-10-23 10:53:05 +020010775
William Lallemand230662a2019-12-03 13:32:54 +010010776 if (!cli_has_level(appctx, ACCESS_LVL_ADMIN))
10777 return 1;
10778
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010779 if ((buf = alloc_trash_chunk()) == NULL)
10780 return cli_err(appctx, "Can't allocate memory\n");
William Lallemand150bfa82019-09-19 17:12:49 +020010781
10782 if (!*args[3] || !payload)
10783 return cli_err(appctx, "'set ssl cert expects a filename and a certificat as a payload\n");
10784
10785 /* The operations on the CKCH architecture are locked so we can
10786 * manipulate ckch_store and ckch_inst */
10787 if (HA_SPIN_TRYLOCK(CKCH_LOCK, &ckch_lock))
10788 return cli_err(appctx, "Can't update the certificate!\nOperations on certificates are currently locked!\n");
10789
William Lallemand8f840d72019-10-23 10:53:05 +020010790 if (!chunk_strcpy(buf, args[3])) {
10791 memprintf(&err, "%sCan't allocate memory\n", err ? err : "");
10792 errcode |= ERR_ALERT | ERR_FATAL;
10793 goto end;
10794 }
10795
William Lallemand44b35322019-10-17 16:28:40 +020010796 /* check which type of file we want to update */
William Lallemandf29cdef2019-10-23 15:00:52 +020010797 for (i = 0; cert_exts[i].type < CERT_TYPE_MAX; i++) {
William Lallemand8f840d72019-10-23 10:53:05 +020010798 end = strrchr(buf->area, '.');
William Lallemand44b35322019-10-17 16:28:40 +020010799 if (end && *cert_exts[i].ext && (!strcmp(end + 1, cert_exts[i].ext))) {
10800 *end = '\0';
10801 type = cert_exts[i].type;
10802 break;
10803 }
10804 }
10805
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010806 appctx->ctx.ssl.old_ckchs = NULL;
10807 appctx->ctx.ssl.new_ckchs = NULL;
William Lallemand849eed62019-10-17 16:23:50 +020010808
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010809 /* if there is an ongoing transaction */
10810 if (ckchs_transaction.path) {
10811 /* 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 +020010812#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010813 if (ckchs_transaction.new_ckchs->multi) {
Emmanuel Hocdet40f2f1e2019-10-30 17:31:28 +010010814 char *end;
William Lallemand963b2e72019-10-14 11:38:36 +020010815 int j;
William Lallemand150bfa82019-09-19 17:12:49 +020010816
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010817 /* check if it was used in a bundle by removing the
William Lallemand963b2e72019-10-14 11:38:36 +020010818 * .dsa/.rsa/.ecdsa at the end of the filename */
William Lallemand8f840d72019-10-23 10:53:05 +020010819 end = strrchr(buf->area, '.');
Emmanuel Hocdet40f2f1e2019-10-30 17:31:28 +010010820 for (j = 0; end && j < SSL_SOCK_NUM_KEYTYPES; j++) {
William Lallemand963b2e72019-10-14 11:38:36 +020010821 if (!strcmp(end + 1, SSL_SOCK_KEYTYPE_NAMES[j])) {
10822 bundle = j; /* keep the type of certificate so we insert it at the right place */
10823 *end = '\0'; /* it's a bundle let's end the string*/
10824 break;
10825 }
William Lallemand150bfa82019-09-19 17:12:49 +020010826 }
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010827 if (bundle < 0) {
10828 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);
10829 errcode |= ERR_ALERT | ERR_FATAL;
10830 goto end;
10831 }
10832 }
10833#endif
10834
10835 /* if there is an ongoing transaction, check if this is the same file */
10836 if (strcmp(ckchs_transaction.path, buf->area) != 0) {
10837 memprintf(&err, "The ongoing transaction is about '%s' but you are trying to set '%s'\n", ckchs_transaction.path, buf->area);
10838 errcode |= ERR_ALERT | ERR_FATAL;
10839 goto end;
William Lallemand150bfa82019-09-19 17:12:49 +020010840 }
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010841
10842 appctx->ctx.ssl.old_ckchs = ckchs_transaction.new_ckchs;
10843
10844 } else {
10845 struct ckch_store *find_ckchs[2] = { NULL, NULL };
10846
10847 /* lookup for the certificate in the tree:
10848 * check if this is used as a bundle AND as a unique certificate */
10849 for (i = 0; i < 2; i++) {
10850
10851 if ((find_ckchs[i] = ckchs_lookup(buf->area)) != NULL) {
10852 /* only the bundle name is in the tree and you should
10853 * never update a bundle name, only a filename */
10854 if (bundle < 0 && find_ckchs[i]->multi) {
10855 /* we tried to look for a non-bundle and we found a bundle */
10856 memprintf(&err, "%s%s is a multi-cert bundle. Try updating %s.{dsa,rsa,ecdsa}\n",
10857 err ? err : "", args[3], args[3]);
10858 errcode |= ERR_ALERT | ERR_FATAL;
10859 goto end;
10860 }
William Lallemand3246d942019-11-04 14:02:11 +010010861 /* If we want a bundle but this is not a bundle
10862 * example: When you try to update <file>.rsa, but
10863 * <file> is a regular file */
10864 if (bundle >= 0 && find_ckchs[i]->multi == 0) {
10865 find_ckchs[i] = NULL;
10866 break;
10867 }
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010868 }
10869#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
10870 {
Emmanuel Hocdet40f2f1e2019-10-30 17:31:28 +010010871 char *end;
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010872 int j;
10873
10874 /* check if it was used in a bundle by removing the
10875 * .dsa/.rsa/.ecdsa at the end of the filename */
10876 end = strrchr(buf->area, '.');
Emmanuel Hocdet40f2f1e2019-10-30 17:31:28 +010010877 for (j = 0; end && j < SSL_SOCK_NUM_KEYTYPES; j++) {
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010878 if (!strcmp(end + 1, SSL_SOCK_KEYTYPE_NAMES[j])) {
10879 bundle = j; /* keep the type of certificate so we insert it at the right place */
10880 *end = '\0'; /* it's a bundle let's end the string*/
10881 break;
10882 }
10883 }
William Lallemand37031b82019-11-04 13:38:53 +010010884 if (bundle < 0) /* we didn't find a bundle extension */
10885 break;
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010886 }
William Lallemand963b2e72019-10-14 11:38:36 +020010887#else
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010888 /* bundles are not supported here, so we don't need to lookup again */
10889 break;
William Lallemand963b2e72019-10-14 11:38:36 +020010890#endif
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010891 }
10892
10893 if (find_ckchs[0] && find_ckchs[1]) {
10894 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",
10895 err ? err : "", find_ckchs[0]->path, find_ckchs[1]->path);
10896 errcode |= ERR_ALERT | ERR_FATAL;
10897 goto end;
10898 }
10899
10900 appctx->ctx.ssl.old_ckchs = find_ckchs[0] ? find_ckchs[0] : find_ckchs[1];
William Lallemand150bfa82019-09-19 17:12:49 +020010901 }
10902
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010903 if (!appctx->ctx.ssl.old_ckchs) {
10904 memprintf(&err, "%sCan't replace a certificate which is not referenced by the configuration!\n",
William Lallemand150bfa82019-09-19 17:12:49 +020010905 err ? err : "");
Emeric Brunf69ed1d2019-10-17 11:56:56 +020010906 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemand8f840d72019-10-23 10:53:05 +020010907 goto end;
William Lallemand150bfa82019-09-19 17:12:49 +020010908 }
10909
William Lallemand8a7fdf02019-11-04 10:59:32 +010010910 if (!appctx->ctx.ssl.path) {
10911 /* this is a new transaction, set the path of the transaction */
10912 appctx->ctx.ssl.path = strdup(appctx->ctx.ssl.old_ckchs->path);
10913 if (!appctx->ctx.ssl.path) {
10914 memprintf(&err, "%sCan't allocate memory\n", err ? err : "");
10915 errcode |= ERR_ALERT | ERR_FATAL;
10916 goto end;
10917 }
10918 }
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010919
10920 old_ckchs = appctx->ctx.ssl.old_ckchs;
10921
10922 /* TODO: handle filters */
10923 if (old_ckchs->filters) {
10924 memprintf(&err, "%sCertificates used in crt-list with filters are not supported!\n",
10925 err ? err : "");
10926 errcode |= ERR_ALERT | ERR_FATAL;
10927 goto end;
10928 }
10929
10930 /* duplicate the ckch store */
10931 new_ckchs = ckchs_dup(old_ckchs);
10932 if (!new_ckchs) {
10933 memprintf(&err, "%sCannot allocate memory!\n",
10934 err ? err : "");
10935 errcode |= ERR_ALERT | ERR_FATAL;
10936 goto end;
10937 }
10938
10939 if (!new_ckchs->multi)
10940 ckch = new_ckchs->ckch;
10941 else
10942 ckch = &new_ckchs->ckch[bundle];
10943
10944 /* appply the change on the duplicate */
10945 if (cert_exts[type].load(buf->area, payload, ckch, &err) != 0) {
10946 memprintf(&err, "%sCan't load the payload\n", err ? err : "");
10947 errcode |= ERR_ALERT | ERR_FATAL;
10948 goto end;
10949 }
10950
10951 appctx->ctx.ssl.new_ckchs = new_ckchs;
10952
10953 /* we succeed, we can save the ckchs in the transaction */
10954
10955 /* if there wasn't a transaction, update the old ckchs */
William Dauchyc8bb1532019-11-24 15:04:20 +010010956 if (!ckchs_transaction.old_ckchs) {
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010957 ckchs_transaction.old_ckchs = appctx->ctx.ssl.old_ckchs;
10958 ckchs_transaction.path = appctx->ctx.ssl.path;
10959 err = memprintf(&err, "Transaction created for certificate %s!\n", ckchs_transaction.path);
10960 } else {
10961 err = memprintf(&err, "Transaction updated for certificate %s!\n", ckchs_transaction.path);
10962
10963 }
10964
10965 /* free the previous ckchs if there was a transaction */
10966 ckchs_free(ckchs_transaction.new_ckchs);
10967
10968 ckchs_transaction.new_ckchs = appctx->ctx.ssl.new_ckchs;
10969
10970
William Lallemand8f840d72019-10-23 10:53:05 +020010971 /* creates the SNI ctxs later in the IO handler */
William Lallemand150bfa82019-09-19 17:12:49 +020010972
William Lallemand8f840d72019-10-23 10:53:05 +020010973end:
10974 free_trash_chunk(buf);
William Lallemand150bfa82019-09-19 17:12:49 +020010975
Emeric Brunf69ed1d2019-10-17 11:56:56 +020010976 if (errcode & ERR_CODE) {
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010977
10978 ckchs_free(appctx->ctx.ssl.new_ckchs);
10979 appctx->ctx.ssl.new_ckchs = NULL;
10980
10981 appctx->ctx.ssl.old_ckchs = NULL;
10982
10983 free(appctx->ctx.ssl.path);
10984 appctx->ctx.ssl.path = NULL;
10985
10986 HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
William Lallemand44b35322019-10-17 16:28:40 +020010987 return cli_dynerr(appctx, memprintf(&err, "%sCan't update %s!\n", err ? err : "", args[3]));
William Lallemand430413e2019-10-28 14:30:47 +010010988 } else {
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010989
10990 HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
10991 return cli_dynmsg(appctx, LOG_NOTICE, err);
William Lallemand430413e2019-10-28 14:30:47 +010010992 }
William Lallemand8f840d72019-10-23 10:53:05 +020010993 /* TODO: handle the ERR_WARN which are not handled because of the io_handler */
William Lallemand150bfa82019-09-19 17:12:49 +020010994}
10995
William Lallemand0bc9c8a2019-11-19 15:51:51 +010010996/* parsing function of 'abort ssl cert' */
10997static int cli_parse_abort_cert(char **args, char *payload, struct appctx *appctx, void *private)
10998{
10999 char *err = NULL;
11000
William Lallemand230662a2019-12-03 13:32:54 +010011001 if (!cli_has_level(appctx, ACCESS_LVL_ADMIN))
11002 return 1;
11003
William Lallemand0bc9c8a2019-11-19 15:51:51 +010011004 if (!*args[3])
11005 return cli_err(appctx, "'abort ssl cert' expects a filename\n");
11006
11007 /* The operations on the CKCH architecture are locked so we can
11008 * manipulate ckch_store and ckch_inst */
11009 if (HA_SPIN_TRYLOCK(CKCH_LOCK, &ckch_lock))
11010 return cli_err(appctx, "Can't abort!\nOperations on certificates are currently locked!\n");
11011
11012 if (!ckchs_transaction.path) {
11013 memprintf(&err, "No ongoing transaction!\n");
11014 goto error;
11015 }
11016
11017 if (strcmp(ckchs_transaction.path, args[3]) != 0) {
11018 memprintf(&err, "The ongoing transaction is about '%s' but you are trying to abort a transaction for '%s'\n", ckchs_transaction.path, args[3]);
11019 goto error;
11020 }
11021
11022 /* Only free the ckchs there, because the SNI and instances were not generated yet */
11023 ckchs_free(ckchs_transaction.new_ckchs);
11024 ckchs_transaction.new_ckchs = NULL;
11025 ckchs_free(ckchs_transaction.old_ckchs);
11026 ckchs_transaction.old_ckchs = NULL;
11027 free(ckchs_transaction.path);
11028 ckchs_transaction.path = NULL;
11029
11030 HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
11031
11032 err = memprintf(&err, "Transaction aborted for certificate '%s'!\n", args[3]);
11033 return cli_dynmsg(appctx, LOG_NOTICE, err);
11034
11035error:
11036 HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
11037
11038 return cli_dynerr(appctx, err);
11039}
11040
Aurélien Nephtaliabbf6072018-04-18 13:26:46 +020011041static int cli_parse_set_ocspresponse(char **args, char *payload, struct appctx *appctx, void *private)
William Lallemand32af2032016-10-29 18:09:35 +020011042{
11043#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
11044 char *err = NULL;
Willy Tarreau1c913e42018-08-22 05:26:57 +020011045 int i, j, ret;
Aurélien Nephtali1e0867c2018-04-18 14:04:58 +020011046
11047 if (!payload)
11048 payload = args[3];
William Lallemand32af2032016-10-29 18:09:35 +020011049
11050 /* Expect one parameter: the new response in base64 encoding */
Willy Tarreau9d008692019-08-09 11:21:01 +020011051 if (!*payload)
11052 return cli_err(appctx, "'set ssl ocsp-response' expects response in base64 encoding.\n");
Aurélien Nephtali1e0867c2018-04-18 14:04:58 +020011053
11054 /* remove \r and \n from the payload */
11055 for (i = 0, j = 0; payload[i]; i++) {
11056 if (payload[i] == '\r' || payload[i] == '\n')
11057 continue;
11058 payload[j++] = payload[i];
11059 }
11060 payload[j] = 0;
William Lallemand32af2032016-10-29 18:09:35 +020011061
Willy Tarreau1c913e42018-08-22 05:26:57 +020011062 ret = base64dec(payload, j, trash.area, trash.size);
Willy Tarreau9d008692019-08-09 11:21:01 +020011063 if (ret < 0)
11064 return cli_err(appctx, "'set ssl ocsp-response' received invalid base64 encoded response.\n");
William Lallemand32af2032016-10-29 18:09:35 +020011065
Willy Tarreau1c913e42018-08-22 05:26:57 +020011066 trash.data = ret;
William Lallemand32af2032016-10-29 18:09:35 +020011067 if (ssl_sock_update_ocsp_response(&trash, &err)) {
Willy Tarreau9d008692019-08-09 11:21:01 +020011068 if (err)
11069 return cli_dynerr(appctx, memprintf(&err, "%s.\n", err));
11070 else
11071 return cli_err(appctx, "Failed to update OCSP response.\n");
William Lallemand32af2032016-10-29 18:09:35 +020011072 }
Willy Tarreau9d008692019-08-09 11:21:01 +020011073
11074 return cli_msg(appctx, LOG_INFO, "OCSP Response updated!\n");
William Lallemand32af2032016-10-29 18:09:35 +020011075#else
Willy Tarreau9d008692019-08-09 11:21:01 +020011076 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 +020011077#endif
11078
Nenad Merdanovicc31499d2019-03-23 11:00:32 +010011079}
11080
Willy Tarreau86a394e2019-05-09 14:15:32 +020011081#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000100fL)
Nenad Merdanovicc31499d2019-03-23 11:00:32 +010011082static inline int sample_conv_var2smp_str(const struct arg *arg, struct sample *smp)
11083{
11084 switch (arg->type) {
11085 case ARGT_STR:
11086 smp->data.type = SMP_T_STR;
11087 smp->data.u.str = arg->data.str;
11088 return 1;
11089 case ARGT_VAR:
11090 if (!vars_get_by_desc(&arg->data.var, smp))
11091 return 0;
11092 if (!sample_casts[smp->data.type][SMP_T_STR])
11093 return 0;
11094 if (!sample_casts[smp->data.type][SMP_T_STR](smp))
11095 return 0;
11096 return 1;
11097 default:
11098 return 0;
11099 }
11100}
11101
11102static int check_aes_gcm(struct arg *args, struct sample_conv *conv,
11103 const char *file, int line, char **err)
11104{
11105 switch(args[0].data.sint) {
11106 case 128:
11107 case 192:
11108 case 256:
11109 break;
11110 default:
11111 memprintf(err, "key size must be 128, 192 or 256 (bits).");
11112 return 0;
11113 }
11114 /* Try to decode a variable. */
11115 vars_check_arg(&args[1], NULL);
11116 vars_check_arg(&args[2], NULL);
11117 vars_check_arg(&args[3], NULL);
11118 return 1;
11119}
11120
11121/* Arguements: AES size in bits, nonce, key, tag. The last three arguments are base64 encoded */
11122static int sample_conv_aes_gcm_dec(const struct arg *arg_p, struct sample *smp, void *private)
11123{
11124 struct sample nonce, key, aead_tag;
11125 struct buffer *smp_trash, *smp_trash_alloc;
11126 EVP_CIPHER_CTX *ctx;
11127 int dec_size, ret;
11128
11129 smp_set_owner(&nonce, smp->px, smp->sess, smp->strm, smp->opt);
11130 if (!sample_conv_var2smp_str(&arg_p[1], &nonce))
11131 return 0;
11132
11133 smp_set_owner(&key, smp->px, smp->sess, smp->strm, smp->opt);
11134 if (!sample_conv_var2smp_str(&arg_p[2], &key))
11135 return 0;
11136
11137 smp_set_owner(&aead_tag, smp->px, smp->sess, smp->strm, smp->opt);
11138 if (!sample_conv_var2smp_str(&arg_p[3], &aead_tag))
11139 return 0;
11140
11141 smp_trash = get_trash_chunk();
11142 smp_trash_alloc = alloc_trash_chunk();
11143 if (!smp_trash_alloc)
11144 return 0;
11145
11146 ctx = EVP_CIPHER_CTX_new();
11147
11148 if (!ctx)
11149 goto err;
11150
11151 dec_size = base64dec(nonce.data.u.str.area, nonce.data.u.str.data, smp_trash->area, smp_trash->size);
11152 if (dec_size < 0)
11153 goto err;
11154 smp_trash->data = dec_size;
11155
11156 /* Set cipher type and mode */
11157 switch(arg_p[0].data.sint) {
11158 case 128:
11159 EVP_DecryptInit_ex(ctx, EVP_aes_128_gcm(), NULL, NULL, NULL);
11160 break;
11161 case 192:
11162 EVP_DecryptInit_ex(ctx, EVP_aes_192_gcm(), NULL, NULL, NULL);
11163 break;
11164 case 256:
11165 EVP_DecryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL);
11166 break;
11167 }
11168
11169 EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, smp_trash->data, NULL);
11170
11171 /* Initialise IV */
11172 if(!EVP_DecryptInit_ex(ctx, NULL, NULL, NULL, (unsigned char *) smp_trash->area))
11173 goto err;
11174
11175 dec_size = base64dec(key.data.u.str.area, key.data.u.str.data, smp_trash->area, smp_trash->size);
11176 if (dec_size < 0)
11177 goto err;
11178 smp_trash->data = dec_size;
11179
11180 /* Initialise key */
11181 if (!EVP_DecryptInit_ex(ctx, NULL, NULL, (unsigned char *) smp_trash->area, NULL))
11182 goto err;
11183
11184 if (!EVP_DecryptUpdate(ctx, (unsigned char *) smp_trash->area, (int *) &smp_trash->data,
11185 (unsigned char *) smp->data.u.str.area, (int) smp->data.u.str.data))
11186 goto err;
11187
11188 dec_size = base64dec(aead_tag.data.u.str.area, aead_tag.data.u.str.data, smp_trash_alloc->area, smp_trash_alloc->size);
11189 if (dec_size < 0)
11190 goto err;
11191 smp_trash_alloc->data = dec_size;
11192 dec_size = smp_trash->data;
11193
11194 EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, smp_trash_alloc->data, (void *) smp_trash_alloc->area);
11195 ret = EVP_DecryptFinal_ex(ctx, (unsigned char *) smp_trash->area + smp_trash->data, (int *) &smp_trash->data);
11196
11197 if (ret <= 0)
11198 goto err;
11199
11200 smp->data.u.str.data = dec_size + smp_trash->data;
11201 smp->data.u.str.area = smp_trash->area;
11202 smp->data.type = SMP_T_BIN;
11203 smp->flags &= ~SMP_F_CONST;
11204 free_trash_chunk(smp_trash_alloc);
11205 return 1;
11206
11207err:
11208 free_trash_chunk(smp_trash_alloc);
11209 return 0;
William Lallemand32af2032016-10-29 18:09:35 +020011210}
Nenad Merdanovicc31499d2019-03-23 11:00:32 +010011211# endif
William Lallemand32af2032016-10-29 18:09:35 +020011212
Elliot Otchet71f82972020-01-15 08:12:14 -050011213/* Argument validation functions */
11214
11215/* This function is used to validate the arguments passed to any "x_dn" ssl
11216 * keywords. These keywords support specifying a third parameter that must be
11217 * either empty or the value "rfc2253". Returns 0 on error, non-zero if OK.
11218 */
11219int val_dnfmt(struct arg *arg, char **err_msg)
11220{
11221 if (arg && arg[2].type == ARGT_STR && arg[2].data.str.data > 0 && (strcmp(arg[2].data.str.area, "rfc2253") != 0)) {
11222 memprintf(err_msg, "only rfc2253 or a blank value are currently supported as the format argument.");
11223 return 0;
11224 }
11225 return 1;
11226}
11227
William Lallemand32af2032016-10-29 18:09:35 +020011228/* register cli keywords */
11229static struct cli_kw_list cli_kws = {{ },{
11230#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
11231 { { "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 +020011232 { { "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 +020011233#endif
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +010011234 { { "set", "ssl", "ocsp-response", NULL }, NULL, cli_parse_set_ocspresponse, NULL },
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011235 { { "set", "ssl", "cert", NULL }, "set ssl cert <certfile> <payload> : replace a certificate file", cli_parse_set_cert, NULL, NULL },
11236 { { "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 +010011237 { { "abort", "ssl", "cert", NULL }, "abort ssl cert <certfile> : abort a transaction for a certificate file", cli_parse_abort_cert, NULL, NULL },
William Lallemandd4f946c2019-12-05 10:26:40 +010011238 { { "show", "ssl", "cert", NULL }, "show ssl cert [<certfile>] : display the SSL certificates used in memory, or the details of a <certfile>", cli_parse_show_cert, cli_io_handler_show_cert, cli_release_show_cert },
William Lallemand32af2032016-10-29 18:09:35 +020011239 { { NULL }, NULL, NULL, NULL }
11240}};
11241
Willy Tarreau0108d902018-11-25 19:14:37 +010011242INITCALL1(STG_REGISTER, cli_register_kw, &cli_kws);
William Lallemand32af2032016-10-29 18:09:35 +020011243
Willy Tarreau7875d092012-09-10 08:20:03 +020011244/* Note: must not be declared <const> as its list will be overwritten.
11245 * Please take care of keeping this list alphabetically sorted.
11246 */
Willy Tarreaudc13c112013-06-21 23:16:39 +020011247static struct sample_fetch_kw_list sample_fetch_keywords = {ILH, {
Emeric Brun645ae792014-04-30 14:21:06 +020011248 { "ssl_bc", smp_fetch_ssl_fc, 0, NULL, SMP_T_BOOL, SMP_USE_L5SRV },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +020011249 { "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 +010011250#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Jérôme Magnine064a802018-12-03 22:21:04 +010011251 { "ssl_bc_alpn", smp_fetch_ssl_fc_alpn, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
Olivier Houchard6b77f492018-11-22 18:18:29 +010011252#endif
Emeric Brun645ae792014-04-30 14:21:06 +020011253 { "ssl_bc_cipher", smp_fetch_ssl_fc_cipher, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
Olivier Houchard6b77f492018-11-22 18:18:29 +010011254#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
11255 { "ssl_bc_npn", smp_fetch_ssl_fc_npn, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
11256#endif
Emeric Brun74f7ffa2018-02-19 16:14:12 +010011257 { "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 +020011258 { "ssl_bc_protocol", smp_fetch_ssl_fc_protocol, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
Emeric Brunb73a9b02014-04-30 18:49:19 +020011259 { "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 +020011260 { "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 +020011261#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
Emeric Brun645ae792014-04-30 14:21:06 +020011262 { "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 -040011263#endif
Emmanuel Hocdet839af572019-05-14 16:27:35 +020011264#if HA_OPENSSL_VERSION_NUMBER >= 0x10100000L
Patrick Hemmer65674662019-06-04 08:13:03 -040011265 { "ssl_bc_client_random", smp_fetch_ssl_fc_random, 0, NULL, SMP_T_BIN, SMP_USE_L5SRV },
11266 { "ssl_bc_server_random", smp_fetch_ssl_fc_random, 0, NULL, SMP_T_BIN, SMP_USE_L5SRV },
Patrick Hemmere0275472018-04-28 19:15:51 -040011267 { "ssl_bc_session_key", smp_fetch_ssl_fc_session_key, 0, NULL, SMP_T_BIN, SMP_USE_L5SRV },
11268#endif
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +020011269 { "ssl_c_ca_err", smp_fetch_ssl_c_ca_err, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
11270 { "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 +010011271 { "ssl_c_der", smp_fetch_ssl_x_der, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +020011272 { "ssl_c_err", smp_fetch_ssl_c_err, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Elliot Otchet71f82972020-01-15 08:12:14 -050011273 { "ssl_c_i_dn", smp_fetch_ssl_x_i_dn, ARG3(0,STR,SINT,STR),val_dnfmt, SMP_T_STR, SMP_USE_L5CLI },
Emeric Brunba841a12014-04-30 17:05:08 +020011274 { "ssl_c_key_alg", smp_fetch_ssl_x_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
11275 { "ssl_c_notafter", smp_fetch_ssl_x_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
11276 { "ssl_c_notbefore", smp_fetch_ssl_x_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
11277 { "ssl_c_sig_alg", smp_fetch_ssl_x_sig_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Elliot Otchet71f82972020-01-15 08:12:14 -050011278 { "ssl_c_s_dn", smp_fetch_ssl_x_s_dn, ARG3(0,STR,SINT,STR),val_dnfmt, SMP_T_STR, SMP_USE_L5CLI },
Emeric Brunba841a12014-04-30 17:05:08 +020011279 { "ssl_c_serial", smp_fetch_ssl_x_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
11280 { "ssl_c_sha1", smp_fetch_ssl_x_sha1, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +010011281 { "ssl_c_used", smp_fetch_ssl_c_used, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +020011282 { "ssl_c_verify", smp_fetch_ssl_c_verify, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
11283 { "ssl_c_version", smp_fetch_ssl_x_version, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Emeric Brun43e79582014-10-29 19:03:26 +010011284 { "ssl_f_der", smp_fetch_ssl_x_der, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Elliot Otchet71f82972020-01-15 08:12:14 -050011285 { "ssl_f_i_dn", smp_fetch_ssl_x_i_dn, ARG3(0,STR,SINT,STR),val_dnfmt, SMP_T_STR, SMP_USE_L5CLI },
Emeric Brunba841a12014-04-30 17:05:08 +020011286 { "ssl_f_key_alg", smp_fetch_ssl_x_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
11287 { "ssl_f_notafter", smp_fetch_ssl_x_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
11288 { "ssl_f_notbefore", smp_fetch_ssl_x_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
11289 { "ssl_f_sig_alg", smp_fetch_ssl_x_sig_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Elliot Otchet71f82972020-01-15 08:12:14 -050011290 { "ssl_f_s_dn", smp_fetch_ssl_x_s_dn, ARG3(0,STR,SINT,STR),val_dnfmt, SMP_T_STR, SMP_USE_L5CLI },
Emeric Brunba841a12014-04-30 17:05:08 +020011291 { "ssl_f_serial", smp_fetch_ssl_x_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Emeric Brun55f4fa82014-04-30 17:11:25 +020011292 { "ssl_f_sha1", smp_fetch_ssl_x_sha1, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +020011293 { "ssl_f_version", smp_fetch_ssl_x_version, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +010011294 { "ssl_fc", smp_fetch_ssl_fc, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +020011295 { "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 +010011296 { "ssl_fc_cipher", smp_fetch_ssl_fc_cipher, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +010011297 { "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 +020011298 { "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 +010011299 { "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 +020011300 { "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 +010011301#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +010011302 { "ssl_fc_npn", smp_fetch_ssl_fc_npn, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreaua33c6542012-10-15 13:19:06 +020011303#endif
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +010011304#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +010011305 { "ssl_fc_alpn", smp_fetch_ssl_fc_alpn, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreauab861d32013-04-02 02:30:41 +020011306#endif
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +010011307 { "ssl_fc_protocol", smp_fetch_ssl_fc_protocol, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreau9a1ab082019-05-09 13:26:41 +020011308#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
Emeric Brunb73a9b02014-04-30 18:49:19 +020011309 { "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 -040011310#endif
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +020011311 { "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 +020011312#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +010011313 { "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 -040011314#endif
Emmanuel Hocdet839af572019-05-14 16:27:35 +020011315#if HA_OPENSSL_VERSION_NUMBER >= 0x10100000L
Patrick Hemmer65674662019-06-04 08:13:03 -040011316 { "ssl_fc_client_random", smp_fetch_ssl_fc_random, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
11317 { "ssl_fc_server_random", smp_fetch_ssl_fc_random, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Patrick Hemmere0275472018-04-28 19:15:51 -040011318 { "ssl_fc_session_key", smp_fetch_ssl_fc_session_key, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
11319#endif
Patrick Hemmer41966772018-04-28 19:15:48 -040011320#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +010011321 { "ssl_fc_sni", smp_fetch_ssl_fc_sni, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Patrick Hemmer41966772018-04-28 19:15:48 -040011322#endif
Thierry FOURNIER5bf77322017-02-25 12:45:22 +010011323 { "ssl_fc_cipherlist_bin", smp_fetch_ssl_fc_cl_bin, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
11324 { "ssl_fc_cipherlist_hex", smp_fetch_ssl_fc_cl_hex, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
11325 { "ssl_fc_cipherlist_str", smp_fetch_ssl_fc_cl_str, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
11326 { "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 +020011327 { NULL, NULL, 0, 0, 0 },
11328}};
11329
Willy Tarreau0108d902018-11-25 19:14:37 +010011330INITCALL1(STG_REGISTER, sample_register_fetches, &sample_fetch_keywords);
11331
Willy Tarreau7875d092012-09-10 08:20:03 +020011332/* Note: must not be declared <const> as its list will be overwritten.
11333 * Please take care of keeping this list alphabetically sorted.
11334 */
Willy Tarreaudc13c112013-06-21 23:16:39 +020011335static struct acl_kw_list acl_kws = {ILH, {
Thierry FOURNIERc5a4e982014-03-05 16:07:08 +010011336 { "ssl_fc_sni_end", "ssl_fc_sni", PAT_MATCH_END },
11337 { "ssl_fc_sni_reg", "ssl_fc_sni", PAT_MATCH_REG },
Willy Tarreau8ed669b2013-01-11 15:49:37 +010011338 { /* END */ },
Willy Tarreau7875d092012-09-10 08:20:03 +020011339}};
11340
Willy Tarreau0108d902018-11-25 19:14:37 +010011341INITCALL1(STG_REGISTER, acl_register_keywords, &acl_kws);
11342
Willy Tarreau79eeafa2012-09-14 07:53:05 +020011343/* Note: must not be declared <const> as its list will be overwritten.
11344 * Please take care of keeping this list alphabetically sorted, doing so helps
11345 * all code contributors.
11346 * Optional keywords are also declared with a NULL ->parse() function so that
11347 * the config parser can report an appropriate error when a known keyword was
11348 * not enabled.
11349 */
Emmanuel Hocdet98263292016-12-29 18:26:15 +010011350static struct ssl_bind_kw ssl_bind_kws[] = {
Olivier Houchardc2aae742017-09-22 18:26:28 +020011351 { "allow-0rtt", ssl_bind_parse_allow_0rtt, 0 }, /* allow 0-RTT */
Emmanuel Hocdet98263292016-12-29 18:26:15 +010011352 { "alpn", ssl_bind_parse_alpn, 1 }, /* set ALPN supported protocols */
11353 { "ca-file", ssl_bind_parse_ca_file, 1 }, /* set CAfile to process verify on client cert */
11354 { "ciphers", ssl_bind_parse_ciphers, 1 }, /* set SSL cipher suite */
Emmanuel Hocdet839af572019-05-14 16:27:35 +020011355#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +020011356 { "ciphersuites", ssl_bind_parse_ciphersuites, 1 }, /* set TLS 1.3 cipher suite */
11357#endif
Emmanuel Hocdet98263292016-12-29 18:26:15 +010011358 { "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 +010011359 { "curves", ssl_bind_parse_curves, 1 }, /* set SSL curve suite */
Emmanuel Hocdet98263292016-12-29 18:26:15 +010011360 { "ecdhe", ssl_bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +020011361 { "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 +010011362 { "npn", ssl_bind_parse_npn, 1 }, /* set NPN supported protocols */
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +020011363 { "ssl-min-ver", ssl_bind_parse_tls_method_minmax,1 }, /* minimum version */
11364 { "ssl-max-ver", ssl_bind_parse_tls_method_minmax,1 }, /* maximum version */
Emmanuel Hocdet98263292016-12-29 18:26:15 +010011365 { "verify", ssl_bind_parse_verify, 1 }, /* set SSL verify method */
11366 { NULL, NULL, 0 },
11367};
11368
Willy Tarreau0108d902018-11-25 19:14:37 +010011369/* no initcall for ssl_bind_kws, these ones are parsed in the parser loop */
11370
Willy Tarreau51fb7652012-09-18 18:24:39 +020011371static struct bind_kw_list bind_kws = { "SSL", { }, {
Olivier Houchardc2aae742017-09-22 18:26:28 +020011372 { "allow-0rtt", bind_parse_allow_0rtt, 0 }, /* Allow 0RTT */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +020011373 { "alpn", bind_parse_alpn, 1 }, /* set ALPN supported protocols */
11374 { "ca-file", bind_parse_ca_file, 1 }, /* set CAfile to process verify on client cert */
11375 { "ca-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ignore on verify depth > 0 */
11376 { "ca-sign-file", bind_parse_ca_sign_file, 1 }, /* set CAFile used to generate and sign server certs */
11377 { "ca-sign-pass", bind_parse_ca_sign_pass, 1 }, /* set CAKey passphrase */
11378 { "ciphers", bind_parse_ciphers, 1 }, /* set SSL cipher suite */
Emmanuel Hocdet839af572019-05-14 16:27:35 +020011379#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +020011380 { "ciphersuites", bind_parse_ciphersuites, 1 }, /* set TLS 1.3 cipher suite */
11381#endif
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +020011382 { "crl-file", bind_parse_crl_file, 1 }, /* set certificat revocation list file use on client cert verify */
11383 { "crt", bind_parse_crt, 1 }, /* load SSL certificates from this location */
11384 { "crt-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ingore on verify depth == 0 */
11385 { "crt-list", bind_parse_crt_list, 1 }, /* load a list of crt from this location */
11386 { "curves", bind_parse_curves, 1 }, /* set SSL curve suite */
11387 { "ecdhe", bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
11388 { "force-sslv3", bind_parse_tls_method_options, 0 }, /* force SSLv3 */
11389 { "force-tlsv10", bind_parse_tls_method_options, 0 }, /* force TLSv10 */
11390 { "force-tlsv11", bind_parse_tls_method_options, 0 }, /* force TLSv11 */
11391 { "force-tlsv12", bind_parse_tls_method_options, 0 }, /* force TLSv12 */
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +020011392 { "force-tlsv13", bind_parse_tls_method_options, 0 }, /* force TLSv13 */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +020011393 { "generate-certificates", bind_parse_generate_certs, 0 }, /* enable the server certificates generation */
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +020011394 { "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 +020011395 { "no-sslv3", bind_parse_tls_method_options, 0 }, /* disable SSLv3 */
11396 { "no-tlsv10", bind_parse_tls_method_options, 0 }, /* disable TLSv10 */
11397 { "no-tlsv11", bind_parse_tls_method_options, 0 }, /* disable TLSv11 */
11398 { "no-tlsv12", bind_parse_tls_method_options, 0 }, /* disable TLSv12 */
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +020011399 { "no-tlsv13", bind_parse_tls_method_options, 0 }, /* disable TLSv13 */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +020011400 { "no-tls-tickets", bind_parse_no_tls_tickets, 0 }, /* disable session resumption tickets */
11401 { "ssl", bind_parse_ssl, 0 }, /* enable SSL processing */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +020011402 { "ssl-min-ver", bind_parse_tls_method_minmax, 1 }, /* minimum version */
11403 { "ssl-max-ver", bind_parse_tls_method_minmax, 1 }, /* maximum version */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +020011404 { "strict-sni", bind_parse_strict_sni, 0 }, /* refuse negotiation if sni doesn't match a certificate */
11405 { "tls-ticket-keys", bind_parse_tls_ticket_keys, 1 }, /* set file to load TLS ticket keys from */
11406 { "verify", bind_parse_verify, 1 }, /* set SSL verify method */
11407 { "npn", bind_parse_npn, 1 }, /* set NPN supported protocols */
11408 { "prefer-client-ciphers", bind_parse_pcc, 0 }, /* prefer client ciphers */
Willy Tarreau79eeafa2012-09-14 07:53:05 +020011409 { NULL, NULL, 0 },
11410}};
Emeric Brun46591952012-05-18 15:47:34 +020011411
Willy Tarreau0108d902018-11-25 19:14:37 +010011412INITCALL1(STG_REGISTER, bind_register_keywords, &bind_kws);
11413
Willy Tarreau92faadf2012-10-10 23:04:25 +020011414/* Note: must not be declared <const> as its list will be overwritten.
11415 * Please take care of keeping this list alphabetically sorted, doing so helps
11416 * all code contributors.
11417 * Optional keywords are also declared with a NULL ->parse() function so that
11418 * the config parser can report an appropriate error when a known keyword was
11419 * not enabled.
11420 */
11421static struct srv_kw_list srv_kws = { "SSL", { }, {
Olivier Houchard522eea72017-11-03 16:27:47 +010011422 { "allow-0rtt", srv_parse_allow_0rtt, 0, 1 }, /* Allow using early data on this server */
Olivier Houchardc7566002018-11-20 23:33:50 +010011423 { "alpn", srv_parse_alpn, 1, 1 }, /* Set ALPN supported protocols */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +020011424 { "ca-file", srv_parse_ca_file, 1, 1 }, /* set CAfile to process verify server cert */
Olivier Houchard92150142018-12-21 19:47:01 +010011425 { "check-alpn", srv_parse_alpn, 1, 1 }, /* Set ALPN used for checks */
Olivier Houchard9130a962017-10-17 17:33:43 +020011426 { "check-sni", srv_parse_check_sni, 1, 1 }, /* set SNI */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +020011427 { "check-ssl", srv_parse_check_ssl, 0, 1 }, /* enable SSL for health checks */
11428 { "ciphers", srv_parse_ciphers, 1, 1 }, /* select the cipher suite */
Emmanuel Hocdet839af572019-05-14 16:27:35 +020011429#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +020011430 { "ciphersuites", srv_parse_ciphersuites, 1, 1 }, /* select the cipher suite */
11431#endif
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +020011432 { "crl-file", srv_parse_crl_file, 1, 1 }, /* set certificate revocation list file use on server cert verify */
11433 { "crt", srv_parse_crt, 1, 1 }, /* set client certificate */
11434 { "force-sslv3", srv_parse_tls_method_options, 0, 1 }, /* force SSLv3 */
11435 { "force-tlsv10", srv_parse_tls_method_options, 0, 1 }, /* force TLSv10 */
11436 { "force-tlsv11", srv_parse_tls_method_options, 0, 1 }, /* force TLSv11 */
11437 { "force-tlsv12", srv_parse_tls_method_options, 0, 1 }, /* force TLSv12 */
11438 { "force-tlsv13", srv_parse_tls_method_options, 0, 1 }, /* force TLSv13 */
11439 { "no-check-ssl", srv_parse_no_check_ssl, 0, 1 }, /* disable SSL for health checks */
11440 { "no-send-proxy-v2-ssl", srv_parse_no_send_proxy_ssl, 0, 1 }, /* do not send PROXY protocol header v2 with SSL info */
11441 { "no-send-proxy-v2-ssl-cn", srv_parse_no_send_proxy_cn, 0, 1 }, /* do not send PROXY protocol header v2 with CN */
11442 { "no-ssl", srv_parse_no_ssl, 0, 1 }, /* disable SSL processing */
11443 { "no-ssl-reuse", srv_parse_no_ssl_reuse, 0, 1 }, /* disable session reuse */
11444 { "no-sslv3", srv_parse_tls_method_options, 0, 0 }, /* disable SSLv3 */
11445 { "no-tlsv10", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv10 */
11446 { "no-tlsv11", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv11 */
11447 { "no-tlsv12", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv12 */
11448 { "no-tlsv13", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv13 */
11449 { "no-tls-tickets", srv_parse_no_tls_tickets, 0, 1 }, /* disable session resumption tickets */
Olivier Houchardc7566002018-11-20 23:33:50 +010011450 { "npn", srv_parse_npn, 1, 1 }, /* Set NPN supported protocols */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +020011451 { "send-proxy-v2-ssl", srv_parse_send_proxy_ssl, 0, 1 }, /* send PROXY protocol header v2 with SSL info */
11452 { "send-proxy-v2-ssl-cn", srv_parse_send_proxy_cn, 0, 1 }, /* send PROXY protocol header v2 with CN */
11453 { "sni", srv_parse_sni, 1, 1 }, /* send SNI extension */
11454 { "ssl", srv_parse_ssl, 0, 1 }, /* enable SSL processing */
11455 { "ssl-min-ver", srv_parse_tls_method_minmax, 1, 1 }, /* minimum version */
11456 { "ssl-max-ver", srv_parse_tls_method_minmax, 1, 1 }, /* maximum version */
11457 { "ssl-reuse", srv_parse_ssl_reuse, 0, 1 }, /* enable session reuse */
11458 { "tls-tickets", srv_parse_tls_tickets, 0, 1 }, /* enable session resumption tickets */
11459 { "verify", srv_parse_verify, 1, 1 }, /* set SSL verify method */
11460 { "verifyhost", srv_parse_verifyhost, 1, 1 }, /* require that SSL cert verifies for hostname */
Willy Tarreau92faadf2012-10-10 23:04:25 +020011461 { NULL, NULL, 0, 0 },
11462}};
11463
Willy Tarreau0108d902018-11-25 19:14:37 +010011464INITCALL1(STG_REGISTER, srv_register_keywords, &srv_kws);
11465
Emeric Brun2c86cbf2014-10-30 15:56:50 +010011466static struct cfg_kw_list cfg_kws = {ILH, {
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +010011467 { CFG_GLOBAL, "ca-base", ssl_parse_global_ca_crt_base },
11468 { CFG_GLOBAL, "crt-base", ssl_parse_global_ca_crt_base },
Willy Tarreau0bea58d2016-12-21 23:17:25 +010011469 { CFG_GLOBAL, "maxsslconn", ssl_parse_global_int },
Emeric Brun2c86cbf2014-10-30 15:56:50 +010011470 { CFG_GLOBAL, "ssl-default-bind-options", ssl_parse_default_bind_options },
11471 { CFG_GLOBAL, "ssl-default-server-options", ssl_parse_default_server_options },
Willy Tarreau14e36a12016-12-21 23:28:13 +010011472#ifndef OPENSSL_NO_DH
11473 { CFG_GLOBAL, "ssl-dh-param-file", ssl_parse_global_dh_param_file },
11474#endif
Grant Zhangfa6c7ee2017-01-14 01:42:15 +000011475 { CFG_GLOBAL, "ssl-mode-async", ssl_parse_global_ssl_async },
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020011476#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +000011477 { CFG_GLOBAL, "ssl-engine", ssl_parse_global_ssl_engine },
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020011478#endif
Willy Tarreau9ceda382016-12-21 23:13:03 +010011479 { CFG_GLOBAL, "tune.ssl.cachesize", ssl_parse_global_int },
11480#ifndef OPENSSL_NO_DH
11481 { CFG_GLOBAL, "tune.ssl.default-dh-param", ssl_parse_global_default_dh },
11482#endif
11483 { CFG_GLOBAL, "tune.ssl.force-private-cache", ssl_parse_global_private_cache },
11484 { CFG_GLOBAL, "tune.ssl.lifetime", ssl_parse_global_lifetime },
11485 { CFG_GLOBAL, "tune.ssl.maxrecord", ssl_parse_global_int },
11486 { CFG_GLOBAL, "tune.ssl.ssl-ctx-cache-size", ssl_parse_global_int },
Thierry FOURNIER5bf77322017-02-25 12:45:22 +010011487 { CFG_GLOBAL, "tune.ssl.capture-cipherlist-size", ssl_parse_global_capture_cipherlist },
Willy Tarreauf22e9682016-12-21 23:23:19 +010011488 { CFG_GLOBAL, "ssl-default-bind-ciphers", ssl_parse_global_ciphers },
11489 { CFG_GLOBAL, "ssl-default-server-ciphers", ssl_parse_global_ciphers },
Emmanuel Hocdet839af572019-05-14 16:27:35 +020011490#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +020011491 { CFG_GLOBAL, "ssl-default-bind-ciphersuites", ssl_parse_global_ciphersuites },
11492 { CFG_GLOBAL, "ssl-default-server-ciphersuites", ssl_parse_global_ciphersuites },
11493#endif
William Lallemand3af48e72020-02-03 17:15:52 +010011494 { CFG_GLOBAL, "ssl-load-extra-files", ssl_parse_global_extra_files },
Emeric Brun2c86cbf2014-10-30 15:56:50 +010011495 { 0, NULL, NULL },
11496}};
11497
Willy Tarreau0108d902018-11-25 19:14:37 +010011498INITCALL1(STG_REGISTER, cfg_register_keywords, &cfg_kws);
11499
Nenad Merdanovicc31499d2019-03-23 11:00:32 +010011500/* Note: must not be declared <const> as its list will be overwritten */
11501static struct sample_conv_kw_list conv_kws = {ILH, {
Willy Tarreau86a394e2019-05-09 14:15:32 +020011502#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000100fL)
Nenad Merdanovicc31499d2019-03-23 11:00:32 +010011503 { "aes_gcm_dec", sample_conv_aes_gcm_dec, ARG4(4,SINT,STR,STR,STR), check_aes_gcm, SMP_T_BIN, SMP_T_BIN },
11504#endif
11505 { NULL, NULL, 0, 0, 0 },
11506}};
11507
11508INITCALL1(STG_REGISTER, sample_register_convs, &conv_kws);
11509
Willy Tarreauf7bc57c2012-10-03 00:19:48 +020011510/* transport-layer operations for SSL sockets */
Willy Tarreaud9f5cca2016-12-22 21:08:52 +010011511static struct xprt_ops ssl_sock = {
Emeric Brun46591952012-05-18 15:47:34 +020011512 .snd_buf = ssl_sock_from_buf,
11513 .rcv_buf = ssl_sock_to_buf,
Olivier Houcharddf357842019-03-21 16:30:07 +010011514 .subscribe = ssl_subscribe,
11515 .unsubscribe = ssl_unsubscribe,
Olivier Houchard5149b592019-05-23 17:47:36 +020011516 .remove_xprt = ssl_remove_xprt,
Olivier Houchard2e055482019-05-27 19:50:12 +020011517 .add_xprt = ssl_add_xprt,
Emeric Brun46591952012-05-18 15:47:34 +020011518 .rcv_pipe = NULL,
11519 .snd_pipe = NULL,
11520 .shutr = NULL,
11521 .shutw = ssl_sock_shutw,
11522 .close = ssl_sock_close,
11523 .init = ssl_sock_init,
Willy Tarreau55d37912016-12-21 23:38:39 +010011524 .prepare_bind_conf = ssl_sock_prepare_bind_conf,
Willy Tarreau795cdab2016-12-22 17:30:54 +010011525 .destroy_bind_conf = ssl_sock_destroy_bind_conf,
Willy Tarreau17d45382016-12-22 21:16:08 +010011526 .prepare_srv = ssl_sock_prepare_srv_ctx,
11527 .destroy_srv = ssl_sock_free_srv_ctx,
Willy Tarreau8743f7e2016-12-04 18:44:29 +010011528 .get_alpn = ssl_sock_get_alpn,
Willy Tarreau8e0bb0a2016-11-24 16:58:12 +010011529 .name = "SSL",
Emeric Brun46591952012-05-18 15:47:34 +020011530};
11531
Olivier Houchardccaa7de2017-10-02 11:51:03 +020011532enum act_return ssl_action_wait_for_hs(struct act_rule *rule, struct proxy *px,
11533 struct session *sess, struct stream *s, int flags)
11534{
11535 struct connection *conn;
Olivier Houchard6fa63d92017-11-27 18:41:32 +010011536 struct conn_stream *cs;
Olivier Houchardccaa7de2017-10-02 11:51:03 +020011537
11538 conn = objt_conn(sess->origin);
Olivier Houchard6fa63d92017-11-27 18:41:32 +010011539 cs = objt_cs(s->si[0].end);
Olivier Houchardccaa7de2017-10-02 11:51:03 +020011540
Olivier Houchard6fa63d92017-11-27 18:41:32 +010011541 if (conn && cs) {
Olivier Houchardccaa7de2017-10-02 11:51:03 +020011542 if (conn->flags & (CO_FL_EARLY_SSL_HS | CO_FL_SSL_WAIT_HS)) {
Olivier Houchard6fa63d92017-11-27 18:41:32 +010011543 cs->flags |= CS_FL_WAIT_FOR_HS;
Olivier Houchardccaa7de2017-10-02 11:51:03 +020011544 s->req.flags |= CF_READ_NULL;
11545 return ACT_RET_YIELD;
11546 }
11547 }
11548 return (ACT_RET_CONT);
11549}
11550
11551static enum act_parse_ret ssl_parse_wait_for_hs(const char **args, int *orig_arg, struct proxy *px, struct act_rule *rule, char **err)
11552{
11553 rule->action_ptr = ssl_action_wait_for_hs;
11554
11555 return ACT_RET_PRS_OK;
11556}
11557
11558static struct action_kw_list http_req_actions = {ILH, {
11559 { "wait-for-handshake", ssl_parse_wait_for_hs },
11560 { /* END */ }
11561}};
11562
Willy Tarreau0108d902018-11-25 19:14:37 +010011563INITCALL1(STG_REGISTER, http_req_keywords_register, &http_req_actions);
11564
Willy Tarreau5db847a2019-05-09 14:13:35 +020011565#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +010011566
11567static void ssl_sock_sctl_free_func(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, long argl, void *argp)
11568{
11569 if (ptr) {
11570 chunk_destroy(ptr);
11571 free(ptr);
11572 }
11573}
11574
11575#endif
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +010011576static void ssl_sock_capture_free_func(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, long argl, void *argp)
11577{
Willy Tarreaubafbe012017-11-24 17:34:44 +010011578 pool_free(pool_head_ssl_capture, ptr);
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +010011579}
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +010011580
Emeric Brun46591952012-05-18 15:47:34 +020011581__attribute__((constructor))
Willy Tarreau92faadf2012-10-10 23:04:25 +020011582static void __ssl_sock_init(void)
11583{
Ilya Shipitsin0590f442019-05-25 19:30:50 +050011584#if (!defined(OPENSSL_NO_COMP) && !defined(SSL_OP_NO_COMPRESSION))
Emeric Brun46591952012-05-18 15:47:34 +020011585 STACK_OF(SSL_COMP)* cm;
Ilya Shipitsine242f3d2019-05-25 03:38:14 +050011586 int n;
Ilya Shipitsin0590f442019-05-25 19:30:50 +050011587#endif
Emeric Brun46591952012-05-18 15:47:34 +020011588
Willy Tarreauef934602016-12-22 23:12:01 +010011589 if (global_ssl.listen_default_ciphers)
11590 global_ssl.listen_default_ciphers = strdup(global_ssl.listen_default_ciphers);
11591 if (global_ssl.connect_default_ciphers)
11592 global_ssl.connect_default_ciphers = strdup(global_ssl.connect_default_ciphers);
Emmanuel Hocdet839af572019-05-14 16:27:35 +020011593#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +020011594 if (global_ssl.listen_default_ciphersuites)
11595 global_ssl.listen_default_ciphersuites = strdup(global_ssl.listen_default_ciphersuites);
11596 if (global_ssl.connect_default_ciphersuites)
11597 global_ssl.connect_default_ciphersuites = strdup(global_ssl.connect_default_ciphersuites);
11598#endif
Willy Tarreau610f04b2014-02-13 11:36:41 +010011599
Willy Tarreau13e14102016-12-22 20:25:26 +010011600 xprt_register(XPRT_SSL, &ssl_sock);
Willy Tarreau9a1ab082019-05-09 13:26:41 +020011601#if HA_OPENSSL_VERSION_NUMBER < 0x10100000L
Emeric Brun46591952012-05-18 15:47:34 +020011602 SSL_library_init();
Rosen Penev68185952018-12-14 08:47:02 -080011603#endif
Ilya Shipitsin0590f442019-05-25 19:30:50 +050011604#if (!defined(OPENSSL_NO_COMP) && !defined(SSL_OP_NO_COMPRESSION))
Emeric Brun46591952012-05-18 15:47:34 +020011605 cm = SSL_COMP_get_compression_methods();
Ilya Shipitsine242f3d2019-05-25 03:38:14 +050011606 n = sk_SSL_COMP_num(cm);
11607 while (n--) {
11608 (void) sk_SSL_COMP_pop(cm);
11609 }
Ilya Shipitsin0590f442019-05-25 19:30:50 +050011610#endif
Ilya Shipitsine242f3d2019-05-25 03:38:14 +050011611
Willy Tarreau5db847a2019-05-09 14:13:35 +020011612#if defined(USE_THREAD) && (HA_OPENSSL_VERSION_NUMBER < 0x10100000L)
Emeric Brun821bb9b2017-06-15 16:37:39 +020011613 ssl_locking_init();
11614#endif
Willy Tarreau5db847a2019-05-09 14:13:35 +020011615#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +010011616 sctl_ex_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, ssl_sock_sctl_free_func);
11617#endif
Thierry FOURNIER28962c92018-06-17 21:37:05 +020011618 ssl_app_data_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL);
Thierry FOURNIER16ff0502018-06-17 21:33:01 +020011619 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 +020011620#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +000011621 ENGINE_load_builtin_engines();
Grant Zhangfa6c7ee2017-01-14 01:42:15 +000011622 hap_register_post_check(ssl_check_async_engine_count);
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020011623#endif
Willy Tarreaud1c57502016-12-22 22:46:15 +010011624#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
11625 hap_register_post_check(tlskeys_finalize_config);
11626#endif
Willy Tarreau80713382018-11-26 10:19:54 +010011627
11628 global.ssl_session_max_cost = SSL_SESSION_MAX_COST;
11629 global.ssl_handshake_max_cost = SSL_HANDSHAKE_MAX_COST;
11630
11631#ifndef OPENSSL_NO_DH
11632 ssl_dh_ptr_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, NULL);
11633 hap_register_post_deinit(ssl_free_dh);
11634#endif
11635#ifndef OPENSSL_NO_ENGINE
11636 hap_register_post_deinit(ssl_free_engines);
11637#endif
11638 /* Load SSL string for the verbose & debug mode. */
11639 ERR_load_SSL_strings();
Olivier Houcharda8955d52019-04-07 22:00:38 +020011640 ha_meth = BIO_meth_new(0x666, "ha methods");
11641 BIO_meth_set_write(ha_meth, ha_ssl_write);
11642 BIO_meth_set_read(ha_meth, ha_ssl_read);
11643 BIO_meth_set_ctrl(ha_meth, ha_ssl_ctrl);
11644 BIO_meth_set_create(ha_meth, ha_ssl_new);
11645 BIO_meth_set_destroy(ha_meth, ha_ssl_free);
11646 BIO_meth_set_puts(ha_meth, ha_ssl_puts);
11647 BIO_meth_set_gets(ha_meth, ha_ssl_gets);
William Lallemand150bfa82019-09-19 17:12:49 +020011648
11649 HA_SPIN_INIT(&ckch_lock);
Willy Tarreau80713382018-11-26 10:19:54 +010011650}
Willy Tarreaud92aa5c2015-01-15 21:34:39 +010011651
Willy Tarreau80713382018-11-26 10:19:54 +010011652/* Compute and register the version string */
11653static void ssl_register_build_options()
11654{
11655 char *ptr = NULL;
11656 int i;
11657
Willy Tarreauc2c0b612016-12-21 19:23:20 +010011658 memprintf(&ptr, "Built with OpenSSL version : "
11659#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet50e25e12017-03-24 15:20:03 +010011660 "BoringSSL");
Willy Tarreauc2c0b612016-12-21 19:23:20 +010011661#else /* OPENSSL_IS_BORINGSSL */
11662 OPENSSL_VERSION_TEXT
11663 "\nRunning on OpenSSL version : %s%s",
Rosen Penev68185952018-12-14 08:47:02 -080011664 OpenSSL_version(OPENSSL_VERSION),
Willy Tarreau1d158ab2019-05-09 13:41:45 +020011665 ((OPENSSL_VERSION_NUMBER ^ OpenSSL_version_num()) >> 8) ? " (VERSIONS DIFFER!)" : "");
Willy Tarreauc2c0b612016-12-21 19:23:20 +010011666#endif
11667 memprintf(&ptr, "%s\nOpenSSL library supports TLS extensions : "
Willy Tarreau9a1ab082019-05-09 13:26:41 +020011668#if HA_OPENSSL_VERSION_NUMBER < 0x00907000L
Willy Tarreauc2c0b612016-12-21 19:23:20 +010011669 "no (library version too old)"
11670#elif defined(OPENSSL_NO_TLSEXT)
11671 "no (disabled via OPENSSL_NO_TLSEXT)"
11672#else
11673 "yes"
11674#endif
11675 "", ptr);
11676
11677 memprintf(&ptr, "%s\nOpenSSL library supports SNI : "
11678#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
11679 "yes"
11680#else
11681#ifdef OPENSSL_NO_TLSEXT
11682 "no (because of OPENSSL_NO_TLSEXT)"
11683#else
11684 "no (version might be too old, 0.9.8f min needed)"
11685#endif
11686#endif
11687 "", ptr);
11688
Emmanuel Hocdetf80bc242017-07-12 14:25:38 +020011689 memprintf(&ptr, "%s\nOpenSSL library supports :", ptr);
11690 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
11691 if (methodVersions[i].option)
11692 memprintf(&ptr, "%s %s", ptr, methodVersions[i].name);
Emmanuel Hocdet50e25e12017-03-24 15:20:03 +010011693
Willy Tarreauc2c0b612016-12-21 19:23:20 +010011694 hap_register_build_opts(ptr, 1);
Willy Tarreau80713382018-11-26 10:19:54 +010011695}
Willy Tarreauc2c0b612016-12-21 19:23:20 +010011696
Willy Tarreau80713382018-11-26 10:19:54 +010011697INITCALL0(STG_REGISTER, ssl_register_build_options);
Remi Gacogne4f902b82015-05-28 16:23:00 +020011698
Emeric Brun46591952012-05-18 15:47:34 +020011699
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020011700#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +000011701void ssl_free_engines(void) {
11702 struct ssl_engine_list *wl, *wlb;
11703 /* free up engine list */
11704 list_for_each_entry_safe(wl, wlb, &openssl_engines, list) {
11705 ENGINE_finish(wl->e);
11706 ENGINE_free(wl->e);
11707 LIST_DEL(&wl->list);
11708 free(wl);
11709 }
11710}
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020011711#endif
Christopher Faulet31af49d2015-06-09 17:29:50 +020011712
Remi Gacogned3a23c32015-05-28 16:39:47 +020011713#ifndef OPENSSL_NO_DH
Grant Zhang872f9c22017-01-21 01:10:18 +000011714void ssl_free_dh(void) {
11715 if (local_dh_1024) {
11716 DH_free(local_dh_1024);
11717 local_dh_1024 = NULL;
11718 }
11719 if (local_dh_2048) {
11720 DH_free(local_dh_2048);
11721 local_dh_2048 = NULL;
11722 }
11723 if (local_dh_4096) {
11724 DH_free(local_dh_4096);
11725 local_dh_4096 = NULL;
11726 }
Remi Gacogne47783ef2015-05-29 15:53:22 +020011727 if (global_dh) {
11728 DH_free(global_dh);
11729 global_dh = NULL;
11730 }
Grant Zhang872f9c22017-01-21 01:10:18 +000011731}
11732#endif
11733
11734__attribute__((destructor))
11735static void __ssl_sock_deinit(void)
11736{
11737#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Emeric Brun821bb9b2017-06-15 16:37:39 +020011738 if (ssl_ctx_lru_tree) {
11739 lru64_destroy(ssl_ctx_lru_tree);
Christopher Faulet2a944ee2017-11-07 10:42:54 +010011740 HA_RWLOCK_DESTROY(&ssl_ctx_lru_rwlock);
Emeric Brun821bb9b2017-06-15 16:37:39 +020011741 }
Remi Gacogned3a23c32015-05-28 16:39:47 +020011742#endif
11743
Willy Tarreau5db847a2019-05-09 14:13:35 +020011744#if (HA_OPENSSL_VERSION_NUMBER < 0x10100000L)
Remi Gacogned3a23c32015-05-28 16:39:47 +020011745 ERR_remove_state(0);
11746 ERR_free_strings();
11747
11748 EVP_cleanup();
Rosen Penev68185952018-12-14 08:47:02 -080011749#endif
Remi Gacogned3a23c32015-05-28 16:39:47 +020011750
Willy Tarreau5db847a2019-05-09 14:13:35 +020011751#if (HA_OPENSSL_VERSION_NUMBER >= 0x00907000L) && (HA_OPENSSL_VERSION_NUMBER < 0x10100000L)
Remi Gacogned3a23c32015-05-28 16:39:47 +020011752 CRYPTO_cleanup_all_ex_data();
11753#endif
Olivier Houcharda8955d52019-04-07 22:00:38 +020011754 BIO_meth_free(ha_meth);
Remi Gacogned3a23c32015-05-28 16:39:47 +020011755}
11756
11757
Emeric Brun46591952012-05-18 15:47:34 +020011758/*
11759 * Local variables:
11760 * c-indent-level: 8
11761 * c-basic-offset: 8
11762 * End:
11763 */