blob: 86894cb4401d192cec4c255116e413be897784d6 [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 */
William Lallemand4c5adbf2020-02-24 14:23:22 +0100133#define SSL_GF_KEY 0x00000010 /* try to open the .key file to load a private key */
William Lallemand3af48e72020-02-03 17:15:52 +0100134
William Lallemand4c5adbf2020-02-24 14:23:22 +0100135#define SSL_GF_ALL (SSL_GF_BUNDLE|SSL_GF_SCTL|SSL_GF_OCSP|SSL_GF_OCSP_ISSUER|SSL_GF_KEY)
William Lallemand3af48e72020-02-03 17:15:52 +0100136
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200137/* ssl_methods versions */
138enum {
139 CONF_TLSV_NONE = 0,
140 CONF_TLSV_MIN = 1,
141 CONF_SSLV3 = 1,
142 CONF_TLSV10 = 2,
143 CONF_TLSV11 = 3,
144 CONF_TLSV12 = 4,
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +0200145 CONF_TLSV13 = 5,
146 CONF_TLSV_MAX = 5,
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200147};
148
Emeric Brun850efd52014-01-29 12:24:34 +0100149/* server and bind verify method, it uses a global value as default */
150enum {
151 SSL_SOCK_VERIFY_DEFAULT = 0,
152 SSL_SOCK_VERIFY_REQUIRED = 1,
153 SSL_SOCK_VERIFY_OPTIONAL = 2,
154 SSL_SOCK_VERIFY_NONE = 3,
155};
156
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
William Lallemande0f3fd52020-02-25 14:53:06 +0100162static struct eb_root cert_issuer_tree = EB_ROOT; /* issuers tree from "issuers-chain-path" */
Emmanuel Hocdet75a7aa12020-02-18 15:19:24 +0100163static struct issuer_chain* ssl_get_issuer_chain(X509 *cert);
William Lallemande0f3fd52020-02-25 14:53:06 +0100164
Willy Tarreauef934602016-12-22 23:12:01 +0100165static struct {
166 char *crt_base; /* base directory path for certificates */
167 char *ca_base; /* base directory path for CAs and CRLs */
Emmanuel Hocdet70df7bf2019-01-04 11:08:20 +0100168 char *issuers_chain_path; /* from "issuers-chain-path" */
Emmanuel Hocdet70df7bf2019-01-04 11:08:20 +0100169
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000170 int async; /* whether we use ssl async mode */
Willy Tarreauef934602016-12-22 23:12:01 +0100171
172 char *listen_default_ciphers;
173 char *connect_default_ciphers;
Emmanuel Hocdet839af572019-05-14 16:27:35 +0200174#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +0200175 char *listen_default_ciphersuites;
176 char *connect_default_ciphersuites;
177#endif
Willy Tarreauef934602016-12-22 23:12:01 +0100178 int listen_default_ssloptions;
179 int connect_default_ssloptions;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200180 struct tls_version_filter listen_default_sslmethods;
181 struct tls_version_filter connect_default_sslmethods;
Willy Tarreauef934602016-12-22 23:12:01 +0100182
183 int private_cache; /* Force to use a private session cache even if nbproc > 1 */
184 unsigned int life_time; /* SSL session lifetime in seconds */
185 unsigned int max_record; /* SSL max record size */
186 unsigned int default_dh_param; /* SSL maximum DH parameter size */
187 int ctx_cache; /* max number of entries in the ssl_ctx cache. */
Thierry FOURNIER5bf77322017-02-25 12:45:22 +0100188 int capture_cipherlist; /* Size of the cipherlist buffer. */
William Lallemand3af48e72020-02-03 17:15:52 +0100189 int extra_files; /* which files not defined in the configuration file are we looking for */
Willy Tarreauef934602016-12-22 23:12:01 +0100190} global_ssl = {
191#ifdef LISTEN_DEFAULT_CIPHERS
192 .listen_default_ciphers = LISTEN_DEFAULT_CIPHERS,
193#endif
194#ifdef CONNECT_DEFAULT_CIPHERS
195 .connect_default_ciphers = CONNECT_DEFAULT_CIPHERS,
196#endif
Emmanuel Hocdet839af572019-05-14 16:27:35 +0200197#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +0200198#ifdef LISTEN_DEFAULT_CIPHERSUITES
199 .listen_default_ciphersuites = LISTEN_DEFAULT_CIPHERSUITES,
200#endif
201#ifdef CONNECT_DEFAULT_CIPHERSUITES
202 .connect_default_ciphersuites = CONNECT_DEFAULT_CIPHERSUITES,
203#endif
204#endif
Willy Tarreauef934602016-12-22 23:12:01 +0100205 .listen_default_ssloptions = BC_SSL_O_NONE,
206 .connect_default_ssloptions = SRV_SSL_O_NONE,
207
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200208 .listen_default_sslmethods.flags = MC_SSL_O_ALL,
209 .listen_default_sslmethods.min = CONF_TLSV_NONE,
210 .listen_default_sslmethods.max = CONF_TLSV_NONE,
211 .connect_default_sslmethods.flags = MC_SSL_O_ALL,
212 .connect_default_sslmethods.min = CONF_TLSV_NONE,
213 .connect_default_sslmethods.max = CONF_TLSV_NONE,
214
Willy Tarreauef934602016-12-22 23:12:01 +0100215#ifdef DEFAULT_SSL_MAX_RECORD
216 .max_record = DEFAULT_SSL_MAX_RECORD,
217#endif
218 .default_dh_param = SSL_DEFAULT_DH_PARAM,
219 .ctx_cache = DEFAULT_SSL_CTX_CACHE,
Thierry FOURNIER5bf77322017-02-25 12:45:22 +0100220 .capture_cipherlist = 0,
William Lallemand3af48e72020-02-03 17:15:52 +0100221 .extra_files = SSL_GF_ALL,
Willy Tarreauef934602016-12-22 23:12:01 +0100222};
223
Olivier Houcharda8955d52019-04-07 22:00:38 +0200224static BIO_METHOD *ha_meth;
225
Olivier Houchard66ab4982019-02-26 18:37:15 +0100226struct ssl_sock_ctx {
Olivier Houcharda8955d52019-04-07 22:00:38 +0200227 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +0100228 SSL *ssl;
Olivier Houcharda8955d52019-04-07 22:00:38 +0200229 BIO *bio;
Olivier Houchard5149b592019-05-23 17:47:36 +0200230 const struct xprt_ops *xprt;
Olivier Houchard66ab4982019-02-26 18:37:15 +0100231 void *xprt_ctx;
Olivier Houchardea8dd942019-05-20 14:02:16 +0200232 struct wait_event wait_event;
Willy Tarreau113d52b2020-01-10 09:20:26 +0100233 struct wait_event *subs;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +0100234 int xprt_st; /* transport layer state, initialized to zero */
Olivier Houchard54907bb2019-12-19 15:02:39 +0100235 struct buffer early_buf; /* buffer to store the early data received */
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +0100236 int sent_early_data; /* Amount of early data we sent so far */
237
Olivier Houchard66ab4982019-02-26 18:37:15 +0100238};
239
240DECLARE_STATIC_POOL(ssl_sock_ctx_pool, "ssl_sock_ctx_pool", sizeof(struct ssl_sock_ctx));
241
Olivier Houchardea8dd942019-05-20 14:02:16 +0200242static struct task *ssl_sock_io_cb(struct task *, void *, unsigned short);
Olivier Houchard000694c2019-05-23 14:45:12 +0200243static int ssl_sock_handshake(struct connection *conn, unsigned int flag);
Olivier Houchardea8dd942019-05-20 14:02:16 +0200244
Olivier Houcharda8955d52019-04-07 22:00:38 +0200245/* Methods to implement OpenSSL BIO */
246static int ha_ssl_write(BIO *h, const char *buf, int num)
247{
248 struct buffer tmpbuf;
249 struct ssl_sock_ctx *ctx;
250 int ret;
251
252 ctx = BIO_get_data(h);
253 tmpbuf.size = num;
254 tmpbuf.area = (void *)(uintptr_t)buf;
255 tmpbuf.data = num;
256 tmpbuf.head = 0;
257 ret = ctx->xprt->snd_buf(ctx->conn, ctx->xprt_ctx, &tmpbuf, num, 0);
Olivier Houchardb51937e2019-05-01 17:24:36 +0200258 if (ret == 0 && !(ctx->conn->flags & (CO_FL_ERROR | CO_FL_SOCK_WR_SH))) {
Olivier Houcharda8955d52019-04-07 22:00:38 +0200259 BIO_set_retry_write(h);
Olivier Houcharda28454e2019-04-24 12:04:36 +0200260 ret = -1;
Olivier Houchardb51937e2019-05-01 17:24:36 +0200261 } else if (ret == 0)
262 BIO_clear_retry_flags(h);
Olivier Houcharda8955d52019-04-07 22:00:38 +0200263 return ret;
264}
265
266static int ha_ssl_gets(BIO *h, char *buf, int size)
267{
268
269 return 0;
270}
271
272static int ha_ssl_puts(BIO *h, const char *str)
273{
274
275 return ha_ssl_write(h, str, strlen(str));
276}
277
278static int ha_ssl_read(BIO *h, char *buf, int size)
279{
280 struct buffer tmpbuf;
281 struct ssl_sock_ctx *ctx;
282 int ret;
283
284 ctx = BIO_get_data(h);
285 tmpbuf.size = size;
286 tmpbuf.area = buf;
287 tmpbuf.data = 0;
288 tmpbuf.head = 0;
289 ret = ctx->xprt->rcv_buf(ctx->conn, ctx->xprt_ctx, &tmpbuf, size, 0);
Olivier Houchardb51937e2019-05-01 17:24:36 +0200290 if (ret == 0 && !(ctx->conn->flags & (CO_FL_ERROR | CO_FL_SOCK_RD_SH))) {
Olivier Houcharda8955d52019-04-07 22:00:38 +0200291 BIO_set_retry_read(h);
Olivier Houcharda28454e2019-04-24 12:04:36 +0200292 ret = -1;
Olivier Houchardb51937e2019-05-01 17:24:36 +0200293 } else if (ret == 0)
294 BIO_clear_retry_flags(h);
Olivier Houcharda8955d52019-04-07 22:00:38 +0200295
296 return ret;
297}
298
299static long ha_ssl_ctrl(BIO *h, int cmd, long arg1, void *arg2)
300{
301 int ret = 0;
302 switch (cmd) {
303 case BIO_CTRL_DUP:
304 case BIO_CTRL_FLUSH:
305 ret = 1;
306 break;
307 }
308 return ret;
309}
310
311static int ha_ssl_new(BIO *h)
312{
313 BIO_set_init(h, 1);
314 BIO_set_data(h, NULL);
315 BIO_clear_flags(h, ~0);
316 return 1;
317}
318
319static int ha_ssl_free(BIO *data)
320{
321
322 return 1;
323}
324
325
Willy Tarreau5db847a2019-05-09 14:13:35 +0200326#if defined(USE_THREAD) && (HA_OPENSSL_VERSION_NUMBER < 0x10100000L)
Christopher Faulet9dcf9b62017-11-13 10:34:01 +0100327
Emeric Brun821bb9b2017-06-15 16:37:39 +0200328static HA_RWLOCK_T *ssl_rwlocks;
329
330
331unsigned long ssl_id_function(void)
332{
333 return (unsigned long)tid;
334}
335
336void ssl_locking_function(int mode, int n, const char * file, int line)
337{
338 if (mode & CRYPTO_LOCK) {
339 if (mode & CRYPTO_READ)
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100340 HA_RWLOCK_RDLOCK(SSL_LOCK, &ssl_rwlocks[n]);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200341 else
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100342 HA_RWLOCK_WRLOCK(SSL_LOCK, &ssl_rwlocks[n]);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200343 }
344 else {
345 if (mode & CRYPTO_READ)
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100346 HA_RWLOCK_RDUNLOCK(SSL_LOCK, &ssl_rwlocks[n]);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200347 else
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100348 HA_RWLOCK_WRUNLOCK(SSL_LOCK, &ssl_rwlocks[n]);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200349 }
350}
351
352static int ssl_locking_init(void)
353{
354 int i;
355
356 ssl_rwlocks = malloc(sizeof(HA_RWLOCK_T)*CRYPTO_num_locks());
357 if (!ssl_rwlocks)
358 return -1;
359
360 for (i = 0 ; i < CRYPTO_num_locks() ; i++)
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100361 HA_RWLOCK_INIT(&ssl_rwlocks[i]);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200362
363 CRYPTO_set_id_callback(ssl_id_function);
364 CRYPTO_set_locking_callback(ssl_locking_function);
365
366 return 0;
367}
Christopher Faulet9dcf9b62017-11-13 10:34:01 +0100368
Emeric Brun821bb9b2017-06-15 16:37:39 +0200369#endif
370
William Lallemand150bfa82019-09-19 17:12:49 +0200371__decl_hathreads(HA_SPINLOCK_T ckch_lock);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200372
William Lallemandbc6ca7c2019-10-29 23:48:19 +0100373/* Uncommitted CKCH transaction */
374
375static struct {
376 struct ckch_store *new_ckchs;
377 struct ckch_store *old_ckchs;
378 char *path;
379} ckchs_transaction;
380
Emmanuel Hocdetd4f9a602019-10-24 11:32:47 +0200381/*
Emmanuel Hocdetb270e812019-11-21 19:09:31 +0100382 * deduplicate cafile (and crlfile)
Emmanuel Hocdetd4f9a602019-10-24 11:32:47 +0200383 */
384struct cafile_entry {
385 X509_STORE *ca_store;
Emmanuel Hocdet129d3282019-10-24 18:08:51 +0200386 STACK_OF(X509_NAME) *ca_list;
Emmanuel Hocdetd4f9a602019-10-24 11:32:47 +0200387 struct ebmb_node node;
388 char path[0];
389};
390
391static struct eb_root cafile_tree = EB_ROOT_UNIQUE;
392
393static X509_STORE* ssl_store_get0_locations_file(char *path)
394{
395 struct ebmb_node *eb;
396
397 eb = ebst_lookup(&cafile_tree, path);
398 if (eb) {
399 struct cafile_entry *ca_e;
400 ca_e = ebmb_entry(eb, struct cafile_entry, node);
401 return ca_e->ca_store;
402 }
403 return NULL;
404}
405
406static int ssl_store_load_locations_file(char *path)
407{
408 if (ssl_store_get0_locations_file(path) == NULL) {
409 struct cafile_entry *ca_e;
410 X509_STORE *store = X509_STORE_new();
411 if (X509_STORE_load_locations(store, path, NULL)) {
412 int pathlen;
413 pathlen = strlen(path);
414 ca_e = calloc(1, sizeof(*ca_e) + pathlen + 1);
415 if (ca_e) {
416 memcpy(ca_e->path, path, pathlen + 1);
417 ca_e->ca_store = store;
418 ebst_insert(&cafile_tree, &ca_e->node);
419 return 1;
420 }
421 }
422 X509_STORE_free(store);
423 return 0;
424 }
425 return 1;
426}
427
428/* mimic what X509_STORE_load_locations do with store_ctx */
429static int ssl_set_cert_crl_file(X509_STORE *store_ctx, char *path)
430{
431 X509_STORE *store;
432 store = ssl_store_get0_locations_file(path);
433 if (store_ctx && store) {
434 int i;
435 X509_OBJECT *obj;
436 STACK_OF(X509_OBJECT) *objs = X509_STORE_get0_objects(store);
437 for (i = 0; i < sk_X509_OBJECT_num(objs); i++) {
438 obj = sk_X509_OBJECT_value(objs, i);
439 switch (X509_OBJECT_get_type(obj)) {
440 case X509_LU_X509:
441 X509_STORE_add_cert(store_ctx, X509_OBJECT_get0_X509(obj));
442 break;
443 case X509_LU_CRL:
444 X509_STORE_add_crl(store_ctx, X509_OBJECT_get0_X509_CRL(obj));
445 break;
446 default:
447 break;
448 }
449 }
450 return 1;
451 }
452 return 0;
453}
454
455/* SSL_CTX_load_verify_locations substitute, internaly call X509_STORE_load_locations */
456static int ssl_set_verify_locations_file(SSL_CTX *ctx, char *path)
457{
458 X509_STORE *store_ctx = SSL_CTX_get_cert_store(ctx);
459 return ssl_set_cert_crl_file(store_ctx, path);
460}
461
Emmanuel Hocdet129d3282019-10-24 18:08:51 +0200462/*
463 Extract CA_list from CA_file already in tree.
464 Duplicate ca_name is tracking with ebtree. It's simplify openssl compatibility.
465 Return a shared ca_list: SSL_dup_CA_list must be used before set it on SSL_CTX.
466*/
467static STACK_OF(X509_NAME)* ssl_get_client_ca_file(char *path)
468{
469 struct ebmb_node *eb;
470 struct cafile_entry *ca_e;
471
472 eb = ebst_lookup(&cafile_tree, path);
473 if (!eb)
474 return NULL;
475 ca_e = ebmb_entry(eb, struct cafile_entry, node);
476
477 if (ca_e->ca_list == NULL) {
478 int i;
479 unsigned long key;
480 struct eb_root ca_name_tree = EB_ROOT;
481 struct eb64_node *node, *back;
482 struct {
483 struct eb64_node node;
484 X509_NAME *xname;
485 } *ca_name;
486 STACK_OF(X509_OBJECT) *objs;
487 STACK_OF(X509_NAME) *skn;
488 X509 *x;
489 X509_NAME *xn;
490
491 skn = sk_X509_NAME_new_null();
492 /* take x509 from cafile_tree */
493 objs = X509_STORE_get0_objects(ca_e->ca_store);
494 for (i = 0; i < sk_X509_OBJECT_num(objs); i++) {
495 x = X509_OBJECT_get0_X509(sk_X509_OBJECT_value(objs, i));
496 if (!x)
497 continue;
498 xn = X509_get_subject_name(x);
499 if (!xn)
500 continue;
501 /* Check for duplicates. */
502 key = X509_NAME_hash(xn);
503 for (node = eb64_lookup(&ca_name_tree, key), ca_name = NULL;
504 node && ca_name == NULL;
505 node = eb64_next(node)) {
506 ca_name = container_of(node, typeof(*ca_name), node);
507 if (X509_NAME_cmp(xn, ca_name->xname) != 0)
508 ca_name = NULL;
509 }
510 /* find a duplicate */
511 if (ca_name)
512 continue;
513 ca_name = calloc(1, sizeof *ca_name);
514 xn = X509_NAME_dup(xn);
515 if (!ca_name ||
516 !xn ||
517 !sk_X509_NAME_push(skn, xn)) {
518 free(ca_name);
519 X509_NAME_free(xn);
520 sk_X509_NAME_pop_free(skn, X509_NAME_free);
521 sk_X509_NAME_free(skn);
522 skn = NULL;
523 break;
524 }
525 ca_name->node.key = key;
526 ca_name->xname = xn;
527 eb64_insert(&ca_name_tree, &ca_name->node);
528 }
529 ca_e->ca_list = skn;
530 /* remove temporary ca_name tree */
531 node = eb64_first(&ca_name_tree);
532 while (node) {
533 ca_name = container_of(node, typeof(*ca_name), node);
534 back = eb64_next(node);
535 eb64_delete(node);
536 free(ca_name);
537 node = back;
538 }
539 }
540 return ca_e->ca_list;
541}
542
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +0100543/* This memory pool is used for capturing clienthello parameters. */
Thierry FOURNIER5bf77322017-02-25 12:45:22 +0100544struct ssl_capture {
Thierry FOURNIER5bf77322017-02-25 12:45:22 +0100545 unsigned long long int xxh64;
546 unsigned char ciphersuite_len;
547 char ciphersuite[0];
548};
Willy Tarreaubafbe012017-11-24 17:34:44 +0100549struct pool_head *pool_head_ssl_capture = NULL;
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +0100550static int ssl_capture_ptr_index = -1;
Thierry FOURNIER28962c92018-06-17 21:37:05 +0200551static int ssl_app_data_index = -1;
Willy Tarreauef934602016-12-22 23:12:01 +0100552
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200553#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
554struct list tlskeys_reference = LIST_HEAD_INIT(tlskeys_reference);
555#endif
556
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +0200557#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +0000558static unsigned int openssl_engines_initialized;
559struct list openssl_engines = LIST_HEAD_INIT(openssl_engines);
560struct ssl_engine_list {
561 struct list list;
562 ENGINE *e;
563};
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +0200564#endif
Grant Zhang872f9c22017-01-21 01:10:18 +0000565
Remi Gacogne8de54152014-07-15 11:36:40 +0200566#ifndef OPENSSL_NO_DH
Remi Gacogne4f902b82015-05-28 16:23:00 +0200567static int ssl_dh_ptr_index = -1;
Remi Gacogne47783ef2015-05-29 15:53:22 +0200568static DH *global_dh = NULL;
Remi Gacogne8de54152014-07-15 11:36:40 +0200569static DH *local_dh_1024 = NULL;
570static DH *local_dh_2048 = NULL;
571static DH *local_dh_4096 = NULL;
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +0100572static DH *ssl_get_tmp_dh(SSL *ssl, int export, int keylen);
Remi Gacogne8de54152014-07-15 11:36:40 +0200573#endif /* OPENSSL_NO_DH */
574
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100575#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Christopher Faulet31af49d2015-06-09 17:29:50 +0200576/* X509V3 Extensions that will be added on generated certificates */
577#define X509V3_EXT_SIZE 5
578static char *x509v3_ext_names[X509V3_EXT_SIZE] = {
579 "basicConstraints",
580 "nsComment",
581 "subjectKeyIdentifier",
582 "authorityKeyIdentifier",
583 "keyUsage",
584};
585static char *x509v3_ext_values[X509V3_EXT_SIZE] = {
586 "CA:FALSE",
587 "\"OpenSSL Generated Certificate\"",
588 "hash",
589 "keyid,issuer:always",
590 "nonRepudiation,digitalSignature,keyEncipherment"
591};
Christopher Faulet31af49d2015-06-09 17:29:50 +0200592/* LRU cache to store generated certificate */
593static struct lru64_head *ssl_ctx_lru_tree = NULL;
594static unsigned int ssl_ctx_lru_seed = 0;
Emeric Brun821bb9b2017-06-15 16:37:39 +0200595static unsigned int ssl_ctx_serial;
Willy Tarreau86abe442018-11-25 20:12:18 +0100596__decl_rwlock(ssl_ctx_lru_rwlock);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200597
Willy Tarreauc8ad3be2015-06-17 15:48:26 +0200598#endif // SSL_CTRL_SET_TLSEXT_HOSTNAME
599
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100600static struct ssl_bind_kw ssl_bind_kws[];
601
Willy Tarreau9a1ab082019-05-09 13:26:41 +0200602#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
yanbzhube2774d2015-12-10 15:07:30 -0500603/* The order here matters for picking a default context,
604 * keep the most common keytype at the bottom of the list
605 */
606const char *SSL_SOCK_KEYTYPE_NAMES[] = {
607 "dsa",
608 "ecdsa",
609 "rsa"
610};
611#define SSL_SOCK_NUM_KEYTYPES 3
Willy Tarreau30da7ad2015-12-14 11:28:33 +0100612#else
613#define SSL_SOCK_NUM_KEYTYPES 1
yanbzhube2774d2015-12-10 15:07:30 -0500614#endif
615
William Lallemandc3cd35f2017-11-28 11:04:43 +0100616static struct shared_context *ssl_shctx = NULL; /* ssl shared session cache */
William Lallemand4f45bb92017-10-30 20:08:51 +0100617static struct eb_root *sh_ssl_sess_tree; /* ssl shared session tree */
618
619#define sh_ssl_sess_tree_delete(s) ebmb_delete(&(s)->key);
620
621#define sh_ssl_sess_tree_insert(s) (struct sh_ssl_sess_hdr *)ebmb_insert(sh_ssl_sess_tree, \
622 &(s)->key, SSL_MAX_SSL_SESSION_ID_LENGTH);
623
624#define sh_ssl_sess_tree_lookup(k) (struct sh_ssl_sess_hdr *)ebmb_lookup(sh_ssl_sess_tree, \
625 (k), SSL_MAX_SSL_SESSION_ID_LENGTH);
William Lallemand3f85c9a2017-10-09 16:30:50 +0200626
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100627/*
628 * This function gives the detail of the SSL error. It is used only
629 * if the debug mode and the verbose mode are activated. It dump all
630 * the SSL error until the stack was empty.
631 */
632static forceinline void ssl_sock_dump_errors(struct connection *conn)
633{
634 unsigned long ret;
635
636 if (unlikely(global.mode & MODE_DEBUG)) {
637 while(1) {
638 ret = ERR_get_error();
639 if (ret == 0)
640 return;
641 fprintf(stderr, "fd[%04x] OpenSSL error[0x%lx] %s: %s\n",
Willy Tarreau585744b2017-08-24 14:31:19 +0200642 (unsigned short)conn->handle.fd, ret,
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100643 ERR_func_error_string(ret), ERR_reason_error_string(ret));
644 }
645 }
646}
647
yanbzhube2774d2015-12-10 15:07:30 -0500648
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +0200649#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +0000650static int ssl_init_single_engine(const char *engine_id, const char *def_algorithms)
651{
652 int err_code = ERR_ABORT;
653 ENGINE *engine;
654 struct ssl_engine_list *el;
655
656 /* grab the structural reference to the engine */
657 engine = ENGINE_by_id(engine_id);
658 if (engine == NULL) {
Christopher Faulet767a84b2017-11-24 16:50:31 +0100659 ha_alert("ssl-engine %s: failed to get structural reference\n", engine_id);
Grant Zhang872f9c22017-01-21 01:10:18 +0000660 goto fail_get;
661 }
662
663 if (!ENGINE_init(engine)) {
664 /* the engine couldn't initialise, release it */
Christopher Faulet767a84b2017-11-24 16:50:31 +0100665 ha_alert("ssl-engine %s: failed to initialize\n", engine_id);
Grant Zhang872f9c22017-01-21 01:10:18 +0000666 goto fail_init;
667 }
668
669 if (ENGINE_set_default_string(engine, def_algorithms) == 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +0100670 ha_alert("ssl-engine %s: failed on ENGINE_set_default_string\n", engine_id);
Grant Zhang872f9c22017-01-21 01:10:18 +0000671 goto fail_set_method;
672 }
673
674 el = calloc(1, sizeof(*el));
675 el->e = engine;
676 LIST_ADD(&openssl_engines, &el->list);
Emeric Brunece0c332017-12-06 13:51:49 +0100677 nb_engines++;
678 if (global_ssl.async)
679 global.ssl_used_async_engines = nb_engines;
Grant Zhang872f9c22017-01-21 01:10:18 +0000680 return 0;
681
682fail_set_method:
683 /* release the functional reference from ENGINE_init() */
684 ENGINE_finish(engine);
685
686fail_init:
687 /* release the structural reference from ENGINE_by_id() */
688 ENGINE_free(engine);
689
690fail_get:
691 return err_code;
692}
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +0200693#endif
Grant Zhang872f9c22017-01-21 01:10:18 +0000694
Willy Tarreau5db847a2019-05-09 14:13:35 +0200695#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brun3854e012017-05-17 20:42:48 +0200696/*
697 * openssl async fd handler
698 */
Emeric Brund0e095c2019-04-19 17:15:28 +0200699void ssl_async_fd_handler(int fd)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000700{
Olivier Houchardea8dd942019-05-20 14:02:16 +0200701 struct ssl_sock_ctx *ctx = fdtab[fd].owner;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000702
Emeric Brun3854e012017-05-17 20:42:48 +0200703 /* fd is an async enfine fd, we must stop
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000704 * to poll this fd until it is requested
705 */
Emeric Brunbbc16542017-06-02 15:54:06 +0000706 fd_stop_recv(fd);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000707 fd_cant_recv(fd);
708
709 /* crypto engine is available, let's notify the associated
710 * connection that it can pursue its processing.
711 */
Olivier Houchard03abf2d2019-05-28 10:12:02 +0200712 ssl_sock_io_cb(NULL, ctx, 0);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000713}
714
Emeric Brun3854e012017-05-17 20:42:48 +0200715/*
716 * openssl async delayed SSL_free handler
717 */
Emeric Brund0e095c2019-04-19 17:15:28 +0200718void ssl_async_fd_free(int fd)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000719{
720 SSL *ssl = fdtab[fd].owner;
Emeric Brun3854e012017-05-17 20:42:48 +0200721 OSSL_ASYNC_FD all_fd[32];
722 size_t num_all_fds = 0;
723 int i;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000724
Emeric Brun3854e012017-05-17 20:42:48 +0200725 /* We suppose that the async job for a same SSL *
726 * are serialized. So if we are awake it is
727 * because the running job has just finished
728 * and we can remove all async fds safely
729 */
730 SSL_get_all_async_fds(ssl, NULL, &num_all_fds);
731 if (num_all_fds > 32) {
732 send_log(NULL, LOG_EMERG, "haproxy: openssl returns too many async fds. It seems a bug. Process may crash\n");
733 return;
734 }
735
736 SSL_get_all_async_fds(ssl, all_fd, &num_all_fds);
737 for (i=0 ; i < num_all_fds ; i++)
738 fd_remove(all_fd[i]);
739
740 /* Now we can safely call SSL_free, no more pending job in engines */
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000741 SSL_free(ssl);
Olivier Houchard2be5a4c2019-03-08 18:54:43 +0100742 _HA_ATOMIC_SUB(&sslconns, 1);
743 _HA_ATOMIC_SUB(&jobs, 1);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000744}
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000745/*
Emeric Brun3854e012017-05-17 20:42:48 +0200746 * function used to manage a returned SSL_ERROR_WANT_ASYNC
747 * and enable/disable polling for async fds
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000748 */
Olivier Houchardea8dd942019-05-20 14:02:16 +0200749static inline void ssl_async_process_fds(struct ssl_sock_ctx *ctx)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000750{
Willy Tarreaua9786b62018-01-25 07:22:13 +0100751 OSSL_ASYNC_FD add_fd[32];
Emeric Brun3854e012017-05-17 20:42:48 +0200752 OSSL_ASYNC_FD del_fd[32];
Olivier Houchardea8dd942019-05-20 14:02:16 +0200753 SSL *ssl = ctx->ssl;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000754 size_t num_add_fds = 0;
755 size_t num_del_fds = 0;
Emeric Brun3854e012017-05-17 20:42:48 +0200756 int i;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000757
758 SSL_get_changed_async_fds(ssl, NULL, &num_add_fds, NULL,
759 &num_del_fds);
Emeric Brun3854e012017-05-17 20:42:48 +0200760 if (num_add_fds > 32 || num_del_fds > 32) {
761 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 +0000762 return;
763 }
764
Emeric Brun3854e012017-05-17 20:42:48 +0200765 SSL_get_changed_async_fds(ssl, add_fd, &num_add_fds, del_fd, &num_del_fds);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000766
Emeric Brun3854e012017-05-17 20:42:48 +0200767 /* We remove unused fds from the fdtab */
768 for (i=0 ; i < num_del_fds ; i++)
769 fd_remove(del_fd[i]);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000770
Emeric Brun3854e012017-05-17 20:42:48 +0200771 /* We add new fds to the fdtab */
772 for (i=0 ; i < num_add_fds ; i++) {
Olivier Houchardea8dd942019-05-20 14:02:16 +0200773 fd_insert(add_fd[i], ctx, ssl_async_fd_handler, tid_bit);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000774 }
775
Emeric Brun3854e012017-05-17 20:42:48 +0200776 num_add_fds = 0;
777 SSL_get_all_async_fds(ssl, NULL, &num_add_fds);
778 if (num_add_fds > 32) {
779 send_log(NULL, LOG_EMERG, "haproxy: openssl returns too many async fds. It seems a bug. Process may crash\n");
780 return;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000781 }
Emeric Brun3854e012017-05-17 20:42:48 +0200782
783 /* We activate the polling for all known async fds */
784 SSL_get_all_async_fds(ssl, add_fd, &num_add_fds);
Emeric Brunce9e01c2017-05-31 10:02:53 +0000785 for (i=0 ; i < num_add_fds ; i++) {
Emeric Brun3854e012017-05-17 20:42:48 +0200786 fd_want_recv(add_fd[i]);
Emeric Brunce9e01c2017-05-31 10:02:53 +0000787 /* To ensure that the fd cache won't be used
788 * We'll prefer to catch a real RD event
789 * because handling an EAGAIN on this fd will
790 * result in a context switch and also
791 * some engines uses a fd in blocking mode.
792 */
793 fd_cant_recv(add_fd[i]);
794 }
Emeric Brun3854e012017-05-17 20:42:48 +0200795
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000796}
797#endif
798
William Lallemand104a7a62019-10-14 14:14:59 +0200799#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
Emeric Brun4f3c87a2014-06-20 15:46:13 +0200800/*
801 * This function returns the number of seconds elapsed
802 * since the Epoch, 1970-01-01 00:00:00 +0000 (UTC) and the
803 * date presented un ASN1_GENERALIZEDTIME.
804 *
805 * In parsing error case, it returns -1.
806 */
807static long asn1_generalizedtime_to_epoch(ASN1_GENERALIZEDTIME *d)
808{
809 long epoch;
810 char *p, *end;
811 const unsigned short month_offset[12] = {
812 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
813 };
814 int year, month;
815
816 if (!d || (d->type != V_ASN1_GENERALIZEDTIME)) return -1;
817
818 p = (char *)d->data;
819 end = p + d->length;
820
821 if (end - p < 4) return -1;
822 year = 1000 * (p[0] - '0') + 100 * (p[1] - '0') + 10 * (p[2] - '0') + p[3] - '0';
823 p += 4;
824 if (end - p < 2) return -1;
825 month = 10 * (p[0] - '0') + p[1] - '0';
826 if (month < 1 || month > 12) return -1;
827 /* Compute the number of seconds since 1 jan 1970 and the beginning of current month
828 We consider leap years and the current month (<marsh or not) */
829 epoch = ( ((year - 1970) * 365)
830 + ((year - (month < 3)) / 4 - (year - (month < 3)) / 100 + (year - (month < 3)) / 400)
831 - ((1970 - 1) / 4 - (1970 - 1) / 100 + (1970 - 1) / 400)
832 + month_offset[month-1]
833 ) * 24 * 60 * 60;
834 p += 2;
835 if (end - p < 2) return -1;
836 /* Add the number of seconds of completed days of current month */
837 epoch += (10 * (p[0] - '0') + p[1] - '0' - 1) * 24 * 60 * 60;
838 p += 2;
839 if (end - p < 2) return -1;
840 /* Add the completed hours of the current day */
841 epoch += (10 * (p[0] - '0') + p[1] - '0') * 60 * 60;
842 p += 2;
843 if (end - p < 2) return -1;
844 /* Add the completed minutes of the current hour */
845 epoch += (10 * (p[0] - '0') + p[1] - '0') * 60;
846 p += 2;
847 if (p == end) return -1;
848 /* Test if there is available seconds */
849 if (p[0] < '0' || p[0] > '9')
850 goto nosec;
851 if (end - p < 2) return -1;
852 /* Add the seconds of the current minute */
853 epoch += 10 * (p[0] - '0') + p[1] - '0';
854 p += 2;
855 if (p == end) return -1;
856 /* Ignore seconds float part if present */
857 if (p[0] == '.') {
858 do {
859 if (++p == end) return -1;
860 } while (p[0] >= '0' && p[0] <= '9');
861 }
862
863nosec:
864 if (p[0] == 'Z') {
865 if (end - p != 1) return -1;
866 return epoch;
867 }
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 else if (p[0] == '-') {
874 if (end - p != 5) return -1;
875 /* Apply timezone offset */
Frederik Deweerdt953917a2017-10-16 07:37:31 -0700876 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 +0200877 }
878
879 return -1;
880}
881
William Lallemand104a7a62019-10-14 14:14:59 +0200882/*
883 * struct alignment works here such that the key.key is the same as key_data
884 * Do not change the placement of key_data
885 */
886struct certificate_ocsp {
887 struct ebmb_node key;
888 unsigned char key_data[OCSP_MAX_CERTID_ASN1_LENGTH];
889 struct buffer response;
890 long expire;
891};
892
893struct ocsp_cbk_arg {
894 int is_single;
895 int single_kt;
896 union {
897 struct certificate_ocsp *s_ocsp;
898 /*
899 * m_ocsp will have multiple entries dependent on key type
900 * Entry 0 - DSA
901 * Entry 1 - ECDSA
902 * Entry 2 - RSA
903 */
904 struct certificate_ocsp *m_ocsp[SSL_SOCK_NUM_KEYTYPES];
905 };
906};
907
Emeric Brun1d3865b2014-06-20 15:37:32 +0200908static struct eb_root cert_ocsp_tree = EB_ROOT_UNIQUE;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200909
910/* This function starts to check if the OCSP response (in DER format) contained
911 * in chunk 'ocsp_response' is valid (else exits on error).
912 * If 'cid' is not NULL, it will be compared to the OCSP certificate ID
913 * contained in the OCSP Response and exits on error if no match.
914 * If it's a valid OCSP Response:
915 * If 'ocsp' is not NULL, the chunk is copied in the OCSP response's container
916 * pointed by 'ocsp'.
917 * If 'ocsp' is NULL, the function looks up into the OCSP response's
918 * containers tree (using as index the ASN1 form of the OCSP Certificate ID extracted
919 * from the response) and exits on error if not found. Finally, If an OCSP response is
920 * already present in the container, it will be overwritten.
921 *
922 * Note: OCSP response containing more than one OCSP Single response is not
923 * considered valid.
924 *
925 * Returns 0 on success, 1 in error case.
926 */
Willy Tarreau83061a82018-07-13 11:56:34 +0200927static int ssl_sock_load_ocsp_response(struct buffer *ocsp_response,
928 struct certificate_ocsp *ocsp,
929 OCSP_CERTID *cid, char **err)
Emeric Brun4147b2e2014-06-16 18:36:30 +0200930{
931 OCSP_RESPONSE *resp;
932 OCSP_BASICRESP *bs = NULL;
933 OCSP_SINGLERESP *sr;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200934 OCSP_CERTID *id;
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200935 unsigned char *p = (unsigned char *) ocsp_response->area;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200936 int rc , count_sr;
Emeric Brun13a6b482014-06-20 15:44:34 +0200937 ASN1_GENERALIZEDTIME *revtime, *thisupd, *nextupd = NULL;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200938 int reason;
939 int ret = 1;
940
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200941 resp = d2i_OCSP_RESPONSE(NULL, (const unsigned char **)&p,
942 ocsp_response->data);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200943 if (!resp) {
944 memprintf(err, "Unable to parse OCSP response");
945 goto out;
946 }
947
948 rc = OCSP_response_status(resp);
949 if (rc != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
950 memprintf(err, "OCSP response status not successful");
951 goto out;
952 }
953
954 bs = OCSP_response_get1_basic(resp);
955 if (!bs) {
956 memprintf(err, "Failed to get basic response from OCSP Response");
957 goto out;
958 }
959
960 count_sr = OCSP_resp_count(bs);
961 if (count_sr > 1) {
962 memprintf(err, "OCSP response ignored because contains multiple single responses (%d)", count_sr);
963 goto out;
964 }
965
966 sr = OCSP_resp_get0(bs, 0);
967 if (!sr) {
968 memprintf(err, "Failed to get OCSP single response");
969 goto out;
970 }
971
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200972 id = (OCSP_CERTID*)OCSP_SINGLERESP_get0_id(sr);
973
Emeric Brun4147b2e2014-06-16 18:36:30 +0200974 rc = OCSP_single_get0_status(sr, &reason, &revtime, &thisupd, &nextupd);
Emmanuel Hocdetef607052017-10-24 14:57:16 +0200975 if (rc != V_OCSP_CERTSTATUS_GOOD && rc != V_OCSP_CERTSTATUS_REVOKED) {
Emmanuel Hocdet872085c2017-10-10 15:18:52 +0200976 memprintf(err, "OCSP single response: certificate status is unknown");
Emeric Brun4147b2e2014-06-16 18:36:30 +0200977 goto out;
978 }
979
Emeric Brun13a6b482014-06-20 15:44:34 +0200980 if (!nextupd) {
981 memprintf(err, "OCSP single response: missing nextupdate");
982 goto out;
983 }
984
Emeric Brunc8b27b62014-06-19 14:16:17 +0200985 rc = OCSP_check_validity(thisupd, nextupd, OCSP_MAX_RESPONSE_TIME_SKEW, -1);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200986 if (!rc) {
987 memprintf(err, "OCSP single response: no longer valid.");
988 goto out;
989 }
990
991 if (cid) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200992 if (OCSP_id_cmp(id, cid)) {
Emeric Brun4147b2e2014-06-16 18:36:30 +0200993 memprintf(err, "OCSP single response: Certificate ID does not match certificate and issuer");
994 goto out;
995 }
996 }
997
998 if (!ocsp) {
999 unsigned char key[OCSP_MAX_CERTID_ASN1_LENGTH];
1000 unsigned char *p;
1001
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001002 rc = i2d_OCSP_CERTID(id, NULL);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001003 if (!rc) {
1004 memprintf(err, "OCSP single response: Unable to encode Certificate ID");
1005 goto out;
1006 }
1007
1008 if (rc > OCSP_MAX_CERTID_ASN1_LENGTH) {
1009 memprintf(err, "OCSP single response: Certificate ID too long");
1010 goto out;
1011 }
1012
1013 p = key;
1014 memset(key, 0, OCSP_MAX_CERTID_ASN1_LENGTH);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001015 i2d_OCSP_CERTID(id, &p);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001016 ocsp = (struct certificate_ocsp *)ebmb_lookup(&cert_ocsp_tree, key, OCSP_MAX_CERTID_ASN1_LENGTH);
1017 if (!ocsp) {
1018 memprintf(err, "OCSP single response: Certificate ID does not match any certificate or issuer");
1019 goto out;
1020 }
1021 }
1022
1023 /* According to comments on "chunk_dup", the
1024 previous chunk buffer will be freed */
1025 if (!chunk_dup(&ocsp->response, ocsp_response)) {
1026 memprintf(err, "OCSP response: Memory allocation error");
1027 goto out;
1028 }
1029
Emeric Brun4f3c87a2014-06-20 15:46:13 +02001030 ocsp->expire = asn1_generalizedtime_to_epoch(nextupd) - OCSP_MAX_RESPONSE_TIME_SKEW;
1031
Emeric Brun4147b2e2014-06-16 18:36:30 +02001032 ret = 0;
1033out:
Janusz Dziemidowicz8d710492017-03-08 16:59:41 +01001034 ERR_clear_error();
1035
Emeric Brun4147b2e2014-06-16 18:36:30 +02001036 if (bs)
1037 OCSP_BASICRESP_free(bs);
1038
1039 if (resp)
1040 OCSP_RESPONSE_free(resp);
1041
1042 return ret;
1043}
1044/*
1045 * External function use to update the OCSP response in the OCSP response's
1046 * containers tree. The chunk 'ocsp_response' must contain the OCSP response
1047 * to update in DER format.
1048 *
1049 * Returns 0 on success, 1 in error case.
1050 */
Willy Tarreau83061a82018-07-13 11:56:34 +02001051int ssl_sock_update_ocsp_response(struct buffer *ocsp_response, char **err)
Emeric Brun4147b2e2014-06-16 18:36:30 +02001052{
1053 return ssl_sock_load_ocsp_response(ocsp_response, NULL, NULL, err);
1054}
1055
William Lallemand4a660132019-10-14 14:51:41 +02001056#endif
1057
1058#if ((defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP) || defined OPENSSL_IS_BORINGSSL)
Emeric Brun4147b2e2014-06-16 18:36:30 +02001059/*
1060 * This function load the OCSP Resonse in DER format contained in file at
William Lallemand3b5f3602019-10-16 18:05:05 +02001061 * path 'ocsp_path' or base64 in a buffer <buf>
Emeric Brun4147b2e2014-06-16 18:36:30 +02001062 *
1063 * Returns 0 on success, 1 in error case.
1064 */
William Lallemand3b5f3602019-10-16 18:05:05 +02001065static 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 +02001066{
1067 int fd = -1;
1068 int r = 0;
1069 int ret = 1;
William Lallemand3b5f3602019-10-16 18:05:05 +02001070 struct buffer *ocsp_response;
1071 struct buffer *src = NULL;
Emeric Brun4147b2e2014-06-16 18:36:30 +02001072
William Lallemand3b5f3602019-10-16 18:05:05 +02001073 if (buf) {
1074 int i, j;
1075 /* if it's from a buffer it will be base64 */
Emeric Brun4147b2e2014-06-16 18:36:30 +02001076
William Lallemand3b5f3602019-10-16 18:05:05 +02001077 /* remove \r and \n from the payload */
1078 for (i = 0, j = 0; buf[i]; i++) {
1079 if (buf[i] == '\r' || buf[i] == '\n')
Emeric Brun4147b2e2014-06-16 18:36:30 +02001080 continue;
William Lallemand3b5f3602019-10-16 18:05:05 +02001081 buf[j++] = buf[i];
1082 }
1083 buf[j] = 0;
Emeric Brun4147b2e2014-06-16 18:36:30 +02001084
William Lallemand3b5f3602019-10-16 18:05:05 +02001085 ret = base64dec(buf, j, trash.area, trash.size);
1086 if (ret < 0) {
1087 memprintf(err, "Error reading OCSP response in base64 format");
Emeric Brun4147b2e2014-06-16 18:36:30 +02001088 goto end;
1089 }
William Lallemand3b5f3602019-10-16 18:05:05 +02001090 trash.data = ret;
1091 src = &trash;
1092 } else {
1093 fd = open(ocsp_path, O_RDONLY);
1094 if (fd == -1) {
1095 memprintf(err, "Error opening OCSP response file");
1096 goto end;
Emeric Brun4147b2e2014-06-16 18:36:30 +02001097 }
William Lallemand3b5f3602019-10-16 18:05:05 +02001098
1099 trash.data = 0;
1100 while (trash.data < trash.size) {
1101 r = read(fd, trash.area + trash.data, trash.size - trash.data);
1102 if (r < 0) {
1103 if (errno == EINTR)
1104 continue;
1105
1106 memprintf(err, "Error reading OCSP response from file");
1107 goto end;
1108 }
1109 else if (r == 0) {
1110 break;
1111 }
1112 trash.data += r;
1113 }
1114 close(fd);
1115 fd = -1;
1116 src = &trash;
Emeric Brun4147b2e2014-06-16 18:36:30 +02001117 }
1118
William Lallemand3b5f3602019-10-16 18:05:05 +02001119 ocsp_response = calloc(1, sizeof(*ocsp_response));
1120 if (!chunk_dup(ocsp_response, src)) {
1121 free(ocsp_response);
1122 ocsp_response = NULL;
William Lallemand246c0242019-10-11 08:59:13 +02001123 goto end;
1124 }
Emmanuel Hocdet0667fae2020-01-16 14:41:36 +01001125 /* no error, fill ckch with new context, old context must be free */
1126 if (ckch->ocsp_response) {
1127 free(ckch->ocsp_response->area);
1128 ckch->ocsp_response->area = NULL;
1129 free(ckch->ocsp_response);
1130 }
William Lallemand3b5f3602019-10-16 18:05:05 +02001131 ckch->ocsp_response = ocsp_response;
William Lallemande0f48ae2019-10-15 13:44:57 +02001132 ret = 0;
Emeric Brun4147b2e2014-06-16 18:36:30 +02001133end:
1134 if (fd != -1)
1135 close(fd);
1136
1137 return ret;
1138}
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01001139#endif
Emeric Brun4147b2e2014-06-16 18:36:30 +02001140
Nenad Merdanovic05552d42015-02-27 19:56:49 +01001141#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
1142static 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)
1143{
Christopher Faulet16f45c82018-02-16 11:23:49 +01001144 struct tls_keys_ref *ref;
Emeric Brun9e754772019-01-10 17:51:55 +01001145 union tls_sess_key *keys;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01001146 struct connection *conn;
1147 int head;
1148 int i;
Christopher Faulet16f45c82018-02-16 11:23:49 +01001149 int ret = -1; /* error by default */
Nenad Merdanovic05552d42015-02-27 19:56:49 +01001150
Thierry FOURNIER28962c92018-06-17 21:37:05 +02001151 conn = SSL_get_ex_data(s, ssl_app_data_index);
Willy Tarreau07d94e42018-09-20 10:57:52 +02001152 ref = __objt_listener(conn->target)->bind_conf->keys_ref;
Christopher Faulet16f45c82018-02-16 11:23:49 +01001153 HA_RWLOCK_RDLOCK(TLSKEYS_REF_LOCK, &ref->lock);
1154
1155 keys = ref->tlskeys;
1156 head = ref->tls_ticket_enc_index;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01001157
1158 if (enc) {
1159 memcpy(key_name, keys[head].name, 16);
1160
1161 if(!RAND_pseudo_bytes(iv, EVP_MAX_IV_LENGTH))
Christopher Faulet16f45c82018-02-16 11:23:49 +01001162 goto end;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01001163
Emeric Brun9e754772019-01-10 17:51:55 +01001164 if (ref->key_size_bits == 128) {
Nenad Merdanovic05552d42015-02-27 19:56:49 +01001165
Emeric Brun9e754772019-01-10 17:51:55 +01001166 if(!EVP_EncryptInit_ex(ectx, EVP_aes_128_cbc(), NULL, keys[head].key_128.aes_key, iv))
1167 goto end;
1168
Willy Tarreau9356dac2019-05-10 09:22:53 +02001169 HMAC_Init_ex(hctx, keys[head].key_128.hmac_key, 16, TLS_TICKET_HASH_FUNCT(), NULL);
Emeric Brun9e754772019-01-10 17:51:55 +01001170 ret = 1;
1171 }
1172 else if (ref->key_size_bits == 256 ) {
1173
1174 if(!EVP_EncryptInit_ex(ectx, EVP_aes_256_cbc(), NULL, keys[head].key_256.aes_key, iv))
1175 goto end;
1176
Willy Tarreau9356dac2019-05-10 09:22:53 +02001177 HMAC_Init_ex(hctx, keys[head].key_256.hmac_key, 32, TLS_TICKET_HASH_FUNCT(), NULL);
Emeric Brun9e754772019-01-10 17:51:55 +01001178 ret = 1;
1179 }
Nenad Merdanovic05552d42015-02-27 19:56:49 +01001180 } else {
1181 for (i = 0; i < TLS_TICKETS_NO; i++) {
1182 if (!memcmp(key_name, keys[(head + i) % TLS_TICKETS_NO].name, 16))
1183 goto found;
1184 }
Christopher Faulet16f45c82018-02-16 11:23:49 +01001185 ret = 0;
1186 goto end;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01001187
Christopher Faulet16f45c82018-02-16 11:23:49 +01001188 found:
Emeric Brun9e754772019-01-10 17:51:55 +01001189 if (ref->key_size_bits == 128) {
Willy Tarreau9356dac2019-05-10 09:22:53 +02001190 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 +01001191 if(!EVP_DecryptInit_ex(ectx, EVP_aes_128_cbc(), NULL, keys[(head + i) % TLS_TICKETS_NO].key_128.aes_key, iv))
1192 goto end;
1193 /* 2 for key renewal, 1 if current key is still valid */
1194 ret = i ? 2 : 1;
1195 }
1196 else if (ref->key_size_bits == 256) {
Willy Tarreau9356dac2019-05-10 09:22:53 +02001197 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 +01001198 if(!EVP_DecryptInit_ex(ectx, EVP_aes_256_cbc(), NULL, keys[(head + i) % TLS_TICKETS_NO].key_256.aes_key, iv))
1199 goto end;
1200 /* 2 for key renewal, 1 if current key is still valid */
1201 ret = i ? 2 : 1;
1202 }
Nenad Merdanovic05552d42015-02-27 19:56:49 +01001203 }
Emeric Brun9e754772019-01-10 17:51:55 +01001204
Christopher Faulet16f45c82018-02-16 11:23:49 +01001205 end:
1206 HA_RWLOCK_RDUNLOCK(TLSKEYS_REF_LOCK, &ref->lock);
1207 return ret;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02001208}
1209
1210struct tls_keys_ref *tlskeys_ref_lookup(const char *filename)
1211{
1212 struct tls_keys_ref *ref;
1213
1214 list_for_each_entry(ref, &tlskeys_reference, list)
1215 if (ref->filename && strcmp(filename, ref->filename) == 0)
1216 return ref;
1217 return NULL;
1218}
1219
1220struct tls_keys_ref *tlskeys_ref_lookupid(int unique_id)
1221{
1222 struct tls_keys_ref *ref;
1223
1224 list_for_each_entry(ref, &tlskeys_reference, list)
1225 if (ref->unique_id == unique_id)
1226 return ref;
1227 return NULL;
1228}
1229
Emeric Brun9e754772019-01-10 17:51:55 +01001230/* Update the key into ref: if keysize doesnt
1231 * match existing ones, this function returns -1
1232 * else it returns 0 on success.
1233 */
1234int ssl_sock_update_tlskey_ref(struct tls_keys_ref *ref,
Willy Tarreau83061a82018-07-13 11:56:34 +02001235 struct buffer *tlskey)
Christopher Faulet16f45c82018-02-16 11:23:49 +01001236{
Emeric Brun9e754772019-01-10 17:51:55 +01001237 if (ref->key_size_bits == 128) {
1238 if (tlskey->data != sizeof(struct tls_sess_key_128))
1239 return -1;
1240 }
1241 else if (ref->key_size_bits == 256) {
1242 if (tlskey->data != sizeof(struct tls_sess_key_256))
1243 return -1;
1244 }
1245 else
1246 return -1;
1247
Christopher Faulet16f45c82018-02-16 11:23:49 +01001248 HA_RWLOCK_WRLOCK(TLSKEYS_REF_LOCK, &ref->lock);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001249 memcpy((char *) (ref->tlskeys + ((ref->tls_ticket_enc_index + 2) % TLS_TICKETS_NO)),
1250 tlskey->area, tlskey->data);
Christopher Faulet16f45c82018-02-16 11:23:49 +01001251 ref->tls_ticket_enc_index = (ref->tls_ticket_enc_index + 1) % TLS_TICKETS_NO;
1252 HA_RWLOCK_WRUNLOCK(TLSKEYS_REF_LOCK, &ref->lock);
Emeric Brun9e754772019-01-10 17:51:55 +01001253
1254 return 0;
Christopher Faulet16f45c82018-02-16 11:23:49 +01001255}
1256
Willy Tarreau83061a82018-07-13 11:56:34 +02001257int ssl_sock_update_tlskey(char *filename, struct buffer *tlskey, char **err)
Christopher Faulet16f45c82018-02-16 11:23:49 +01001258{
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02001259 struct tls_keys_ref *ref = tlskeys_ref_lookup(filename);
1260
1261 if(!ref) {
1262 memprintf(err, "Unable to locate the referenced filename: %s", filename);
1263 return 1;
1264 }
Emeric Brun9e754772019-01-10 17:51:55 +01001265 if (ssl_sock_update_tlskey_ref(ref, tlskey) < 0) {
1266 memprintf(err, "Invalid key size");
1267 return 1;
1268 }
1269
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02001270 return 0;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01001271}
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02001272
1273/* This function finalize the configuration parsing. Its set all the
Willy Tarreaud1c57502016-12-22 22:46:15 +01001274 * automatic ids. It's called just after the basic checks. It returns
1275 * 0 on success otherwise ERR_*.
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02001276 */
Willy Tarreaud1c57502016-12-22 22:46:15 +01001277static int tlskeys_finalize_config(void)
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02001278{
1279 int i = 0;
1280 struct tls_keys_ref *ref, *ref2, *ref3;
1281 struct list tkr = LIST_HEAD_INIT(tkr);
1282
1283 list_for_each_entry(ref, &tlskeys_reference, list) {
1284 if (ref->unique_id == -1) {
1285 /* Look for the first free id. */
1286 while (1) {
1287 list_for_each_entry(ref2, &tlskeys_reference, list) {
1288 if (ref2->unique_id == i) {
1289 i++;
1290 break;
1291 }
1292 }
1293 if (&ref2->list == &tlskeys_reference)
1294 break;
1295 }
1296
1297 /* Uses the unique id and increment it for the next entry. */
1298 ref->unique_id = i;
1299 i++;
1300 }
1301 }
1302
1303 /* This sort the reference list by id. */
1304 list_for_each_entry_safe(ref, ref2, &tlskeys_reference, list) {
1305 LIST_DEL(&ref->list);
1306 list_for_each_entry(ref3, &tkr, list) {
1307 if (ref->unique_id < ref3->unique_id) {
1308 LIST_ADDQ(&ref3->list, &ref->list);
1309 break;
1310 }
1311 }
1312 if (&ref3->list == &tkr)
1313 LIST_ADDQ(&tkr, &ref->list);
1314 }
1315
1316 /* swap root */
1317 LIST_ADD(&tkr, &tlskeys_reference);
1318 LIST_DEL(&tkr);
Willy Tarreaud1c57502016-12-22 22:46:15 +01001319 return 0;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02001320}
Nenad Merdanovic05552d42015-02-27 19:56:49 +01001321#endif /* SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB */
1322
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01001323#ifndef OPENSSL_NO_OCSP
yanbzhube2774d2015-12-10 15:07:30 -05001324int ssl_sock_get_ocsp_arg_kt_index(int evp_keytype)
1325{
1326 switch (evp_keytype) {
1327 case EVP_PKEY_RSA:
1328 return 2;
1329 case EVP_PKEY_DSA:
1330 return 0;
1331 case EVP_PKEY_EC:
1332 return 1;
1333 }
1334
1335 return -1;
1336}
1337
Emeric Brun4147b2e2014-06-16 18:36:30 +02001338/*
1339 * Callback used to set OCSP status extension content in server hello.
1340 */
1341int ssl_sock_ocsp_stapling_cbk(SSL *ssl, void *arg)
1342{
yanbzhube2774d2015-12-10 15:07:30 -05001343 struct certificate_ocsp *ocsp;
1344 struct ocsp_cbk_arg *ocsp_arg;
1345 char *ssl_buf;
1346 EVP_PKEY *ssl_pkey;
1347 int key_type;
1348 int index;
1349
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02001350 ocsp_arg = arg;
yanbzhube2774d2015-12-10 15:07:30 -05001351
1352 ssl_pkey = SSL_get_privatekey(ssl);
1353 if (!ssl_pkey)
1354 return SSL_TLSEXT_ERR_NOACK;
1355
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001356 key_type = EVP_PKEY_base_id(ssl_pkey);
yanbzhube2774d2015-12-10 15:07:30 -05001357
1358 if (ocsp_arg->is_single && ocsp_arg->single_kt == key_type)
1359 ocsp = ocsp_arg->s_ocsp;
1360 else {
1361 /* For multiple certs per context, we have to find the correct OCSP response based on
1362 * the certificate type
1363 */
1364 index = ssl_sock_get_ocsp_arg_kt_index(key_type);
1365
1366 if (index < 0)
1367 return SSL_TLSEXT_ERR_NOACK;
1368
1369 ocsp = ocsp_arg->m_ocsp[index];
1370
1371 }
Emeric Brun4147b2e2014-06-16 18:36:30 +02001372
1373 if (!ocsp ||
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001374 !ocsp->response.area ||
1375 !ocsp->response.data ||
Emeric Brun4f3c87a2014-06-20 15:46:13 +02001376 (ocsp->expire < now.tv_sec))
Emeric Brun4147b2e2014-06-16 18:36:30 +02001377 return SSL_TLSEXT_ERR_NOACK;
1378
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001379 ssl_buf = OPENSSL_malloc(ocsp->response.data);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001380 if (!ssl_buf)
1381 return SSL_TLSEXT_ERR_NOACK;
1382
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001383 memcpy(ssl_buf, ocsp->response.area, ocsp->response.data);
1384 SSL_set_tlsext_status_ocsp_resp(ssl, ssl_buf, ocsp->response.data);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001385
1386 return SSL_TLSEXT_ERR_OK;
1387}
1388
William Lallemand4a660132019-10-14 14:51:41 +02001389#endif
1390
1391#if ((defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP) || defined OPENSSL_IS_BORINGSSL)
Emeric Brun4147b2e2014-06-16 18:36:30 +02001392/*
1393 * This function enables the handling of OCSP status extension on 'ctx' if a
William Lallemand246c0242019-10-11 08:59:13 +02001394 * ocsp_response buffer was found in the cert_key_and_chain. To enable OCSP
1395 * status extension, the issuer's certificate is mandatory. It should be
1396 * present in ckch->ocsp_issuer.
Emeric Brun4147b2e2014-06-16 18:36:30 +02001397 *
William Lallemand246c0242019-10-11 08:59:13 +02001398 * In addition, the ckch->ocsp_reponse buffer is loaded as a DER format of an
1399 * OCSP response. If file is empty or content is not a valid OCSP response,
1400 * OCSP status extension is enabled but OCSP response is ignored (a warning is
1401 * displayed).
Emeric Brun4147b2e2014-06-16 18:36:30 +02001402 *
1403 * Returns 1 if no ".ocsp" file found, 0 if OCSP status extension is
Joseph Herlant017b3da2018-11-15 09:07:59 -08001404 * successfully enabled, or -1 in other error case.
Emeric Brun4147b2e2014-06-16 18:36:30 +02001405 */
William Lallemand4a660132019-10-14 14:51:41 +02001406#ifndef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet6f507c72020-02-18 15:56:39 +01001407static int ssl_sock_load_ocsp(SSL_CTX *ctx, const struct cert_key_and_chain *ckch, STACK_OF(X509) *chain)
Emeric Brun4147b2e2014-06-16 18:36:30 +02001408{
Emmanuel Hocdet6f507c72020-02-18 15:56:39 +01001409 X509 *x, *issuer;
Emeric Brun4147b2e2014-06-16 18:36:30 +02001410 OCSP_CERTID *cid = NULL;
Emeric Brun4147b2e2014-06-16 18:36:30 +02001411 int i, ret = -1;
Emeric Brun4147b2e2014-06-16 18:36:30 +02001412 struct certificate_ocsp *ocsp = NULL, *iocsp;
1413 char *warn = NULL;
1414 unsigned char *p;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001415 void (*callback) (void);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001416
Emeric Brun4147b2e2014-06-16 18:36:30 +02001417
William Lallemand246c0242019-10-11 08:59:13 +02001418 x = ckch->cert;
Emeric Brun4147b2e2014-06-16 18:36:30 +02001419 if (!x)
1420 goto out;
1421
William Lallemand246c0242019-10-11 08:59:13 +02001422 issuer = ckch->ocsp_issuer;
Emmanuel Hocdet6f507c72020-02-18 15:56:39 +01001423 /* take issuer from chain over ocsp_issuer, is what is done historicaly */
1424 if (chain) {
1425 /* check if one of the certificate of the chain is the issuer */
1426 for (i = 0; i < sk_X509_num(chain); i++) {
1427 X509 *ti = sk_X509_value(chain, i);
1428 if (X509_check_issued(ti, x) == X509_V_OK) {
1429 issuer = ti;
1430 break;
1431 }
1432 }
1433 }
William Lallemand246c0242019-10-11 08:59:13 +02001434 if (!issuer)
1435 goto out;
Emeric Brun4147b2e2014-06-16 18:36:30 +02001436
1437 cid = OCSP_cert_to_id(0, x, issuer);
1438 if (!cid)
1439 goto out;
1440
1441 i = i2d_OCSP_CERTID(cid, NULL);
1442 if (!i || (i > OCSP_MAX_CERTID_ASN1_LENGTH))
1443 goto out;
1444
Vincent Bernat02779b62016-04-03 13:48:43 +02001445 ocsp = calloc(1, sizeof(*ocsp));
Emeric Brun4147b2e2014-06-16 18:36:30 +02001446 if (!ocsp)
1447 goto out;
1448
1449 p = ocsp->key_data;
1450 i2d_OCSP_CERTID(cid, &p);
1451
1452 iocsp = (struct certificate_ocsp *)ebmb_insert(&cert_ocsp_tree, &ocsp->key, OCSP_MAX_CERTID_ASN1_LENGTH);
1453 if (iocsp == ocsp)
1454 ocsp = NULL;
1455
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001456#ifndef SSL_CTX_get_tlsext_status_cb
1457# define SSL_CTX_get_tlsext_status_cb(ctx, cb) \
1458 *cb = (void (*) (void))ctx->tlsext_status_cb;
1459#endif
1460 SSL_CTX_get_tlsext_status_cb(ctx, &callback);
1461
1462 if (!callback) {
Vincent Bernat02779b62016-04-03 13:48:43 +02001463 struct ocsp_cbk_arg *cb_arg = calloc(1, sizeof(*cb_arg));
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001464 EVP_PKEY *pkey;
yanbzhube2774d2015-12-10 15:07:30 -05001465
1466 cb_arg->is_single = 1;
1467 cb_arg->s_ocsp = iocsp;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001468
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001469 pkey = X509_get_pubkey(x);
1470 cb_arg->single_kt = EVP_PKEY_base_id(pkey);
1471 EVP_PKEY_free(pkey);
yanbzhube2774d2015-12-10 15:07:30 -05001472
1473 SSL_CTX_set_tlsext_status_cb(ctx, ssl_sock_ocsp_stapling_cbk);
1474 SSL_CTX_set_tlsext_status_arg(ctx, cb_arg);
1475 } else {
1476 /*
1477 * If the ctx has a status CB, then we have previously set an OCSP staple for this ctx
1478 * Update that cb_arg with the new cert's staple
1479 */
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001480 struct ocsp_cbk_arg *cb_arg;
yanbzhube2774d2015-12-10 15:07:30 -05001481 struct certificate_ocsp *tmp_ocsp;
1482 int index;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001483 int key_type;
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001484 EVP_PKEY *pkey;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001485
1486#ifdef SSL_CTX_get_tlsext_status_arg
1487 SSL_CTX_ctrl(ctx, SSL_CTRL_GET_TLSEXT_STATUS_REQ_CB_ARG, 0, &cb_arg);
1488#else
1489 cb_arg = ctx->tlsext_status_arg;
1490#endif
yanbzhube2774d2015-12-10 15:07:30 -05001491
1492 /*
1493 * The following few lines will convert cb_arg from a single ocsp to multi ocsp
1494 * the order of operations below matter, take care when changing it
1495 */
1496 tmp_ocsp = cb_arg->s_ocsp;
1497 index = ssl_sock_get_ocsp_arg_kt_index(cb_arg->single_kt);
1498 cb_arg->s_ocsp = NULL;
1499 cb_arg->m_ocsp[index] = tmp_ocsp;
1500 cb_arg->is_single = 0;
1501 cb_arg->single_kt = 0;
1502
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001503 pkey = X509_get_pubkey(x);
1504 key_type = EVP_PKEY_base_id(pkey);
1505 EVP_PKEY_free(pkey);
1506
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001507 index = ssl_sock_get_ocsp_arg_kt_index(key_type);
yanbzhube2774d2015-12-10 15:07:30 -05001508 if (index >= 0 && !cb_arg->m_ocsp[index])
1509 cb_arg->m_ocsp[index] = iocsp;
1510
1511 }
Emeric Brun4147b2e2014-06-16 18:36:30 +02001512
1513 ret = 0;
1514
1515 warn = NULL;
William Lallemand246c0242019-10-11 08:59:13 +02001516 if (ssl_sock_load_ocsp_response(ckch->ocsp_response, ocsp, cid, &warn)) {
William Lallemand3b5f3602019-10-16 18:05:05 +02001517 memprintf(&warn, "Loading: %s. Content will be ignored", warn ? warn : "failure");
Christopher Faulet767a84b2017-11-24 16:50:31 +01001518 ha_warning("%s.\n", warn);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001519 }
1520
1521out:
Emeric Brun4147b2e2014-06-16 18:36:30 +02001522 if (cid)
1523 OCSP_CERTID_free(cid);
1524
1525 if (ocsp)
1526 free(ocsp);
1527
1528 if (warn)
1529 free(warn);
1530
Emeric Brun4147b2e2014-06-16 18:36:30 +02001531 return ret;
1532}
William Lallemand4a660132019-10-14 14:51:41 +02001533#else /* OPENSSL_IS_BORINGSSL */
Emmanuel Hocdet6f507c72020-02-18 15:56:39 +01001534static int ssl_sock_load_ocsp(SSL_CTX *ctx, const struct cert_key_and_chain *ckch, STACK_OF(X509) *chain)
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02001535{
William Lallemand4a660132019-10-14 14:51:41 +02001536 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 +02001537}
1538#endif
1539
William Lallemand4a660132019-10-14 14:51:41 +02001540#endif
1541
1542
Willy Tarreau5db847a2019-05-09 14:13:35 +02001543#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001544
1545#define CT_EXTENSION_TYPE 18
1546
1547static int sctl_ex_index = -1;
1548
1549/*
1550 * Try to parse Signed Certificate Timestamp List structure. This function
1551 * makes only basic test if the data seems like SCTL. No signature validation
1552 * is performed.
1553 */
Willy Tarreau83061a82018-07-13 11:56:34 +02001554static int ssl_sock_parse_sctl(struct buffer *sctl)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001555{
1556 int ret = 1;
1557 int len, pos, sct_len;
1558 unsigned char *data;
1559
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001560 if (sctl->data < 2)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001561 goto out;
1562
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001563 data = (unsigned char *) sctl->area;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001564 len = (data[0] << 8) | data[1];
1565
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001566 if (len + 2 != sctl->data)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001567 goto out;
1568
1569 data = data + 2;
1570 pos = 0;
1571 while (pos < len) {
1572 if (len - pos < 2)
1573 goto out;
1574
1575 sct_len = (data[pos] << 8) | data[pos + 1];
1576 if (pos + sct_len + 2 > len)
1577 goto out;
1578
1579 pos += sct_len + 2;
1580 }
1581
1582 ret = 0;
1583
1584out:
1585 return ret;
1586}
1587
William Lallemand0dfae6c2019-10-16 18:06:58 +02001588/* Try to load a sctl from a buffer <buf> if not NULL, or read the file <sctl_path>
1589 * It fills the ckch->sctl buffer
1590 * return 0 on success or != 0 on failure */
1591static 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 +01001592{
1593 int fd = -1;
1594 int r = 0;
1595 int ret = 1;
William Lallemand0dfae6c2019-10-16 18:06:58 +02001596 struct buffer tmp;
1597 struct buffer *src;
1598 struct buffer *sctl;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001599
William Lallemand0dfae6c2019-10-16 18:06:58 +02001600 if (buf) {
1601 tmp.area = buf;
1602 tmp.data = strlen(buf);
1603 tmp.size = tmp.data + 1;
1604 src = &tmp;
1605 } else {
1606 fd = open(sctl_path, O_RDONLY);
1607 if (fd == -1)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001608 goto end;
William Lallemand0dfae6c2019-10-16 18:06:58 +02001609
1610 trash.data = 0;
1611 while (trash.data < trash.size) {
1612 r = read(fd, trash.area + trash.data, trash.size - trash.data);
1613 if (r < 0) {
1614 if (errno == EINTR)
1615 continue;
1616 goto end;
1617 }
1618 else if (r == 0) {
1619 break;
1620 }
1621 trash.data += r;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001622 }
William Lallemand0dfae6c2019-10-16 18:06:58 +02001623 src = &trash;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001624 }
1625
William Lallemand0dfae6c2019-10-16 18:06:58 +02001626 ret = ssl_sock_parse_sctl(src);
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001627 if (ret)
1628 goto end;
1629
William Lallemand0dfae6c2019-10-16 18:06:58 +02001630 sctl = calloc(1, sizeof(*sctl));
1631 if (!chunk_dup(sctl, src)) {
1632 free(sctl);
1633 sctl = NULL;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001634 goto end;
1635 }
Emmanuel Hocdet224a0872020-01-16 15:15:49 +01001636 /* no error, fill ckch with new context, old context must be free */
1637 if (ckch->sctl) {
1638 free(ckch->sctl->area);
1639 ckch->sctl->area = NULL;
1640 free(ckch->sctl);
1641 }
William Lallemand0dfae6c2019-10-16 18:06:58 +02001642 ckch->sctl = sctl;
Emmanuel Hocdet224a0872020-01-16 15:15:49 +01001643 ret = 0;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001644end:
1645 if (fd != -1)
1646 close(fd);
1647
1648 return ret;
1649}
1650
1651int ssl_sock_sctl_add_cbk(SSL *ssl, unsigned ext_type, const unsigned char **out, size_t *outlen, int *al, void *add_arg)
1652{
Willy Tarreau83061a82018-07-13 11:56:34 +02001653 struct buffer *sctl = add_arg;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001654
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001655 *out = (unsigned char *) sctl->area;
1656 *outlen = sctl->data;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001657
1658 return 1;
1659}
1660
1661int ssl_sock_sctl_parse_cbk(SSL *s, unsigned int ext_type, const unsigned char *in, size_t inlen, int *al, void *parse_arg)
1662{
1663 return 1;
1664}
1665
William Lallemanda17f4112019-10-10 15:16:44 +02001666static int ssl_sock_load_sctl(SSL_CTX *ctx, struct buffer *sctl)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001667{
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001668 int ret = -1;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001669
William Lallemanda17f4112019-10-10 15:16:44 +02001670 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 +01001671 goto out;
1672
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001673 SSL_CTX_set_ex_data(ctx, sctl_ex_index, sctl);
1674
1675 ret = 0;
1676
1677out:
1678 return ret;
1679}
1680
1681#endif
1682
Emeric Brune1f38db2012-09-03 20:36:47 +02001683void ssl_sock_infocbk(const SSL *ssl, int where, int ret)
1684{
Thierry FOURNIER28962c92018-06-17 21:37:05 +02001685 struct connection *conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001686 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
Emeric Brund8b2bb52014-01-28 15:43:53 +01001687 BIO *write_bio;
Willy Tarreau622317d2015-02-27 16:36:16 +01001688 (void)ret; /* shut gcc stupid warning */
Emeric Brune1f38db2012-09-03 20:36:47 +02001689
Dirkjan Bussink526894f2019-01-21 09:35:03 -08001690#ifndef SSL_OP_NO_RENEGOTIATION
1691 /* Please note that BoringSSL defines this macro to zero so don't
1692 * change this to #if and do not assign a default value to this macro!
1693 */
Emeric Brune1f38db2012-09-03 20:36:47 +02001694 if (where & SSL_CB_HANDSHAKE_START) {
1695 /* Disable renegotiation (CVE-2009-3555) */
Willy Tarreauc192b0a2020-01-23 09:11:58 +01001696 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 +02001697 conn->flags |= CO_FL_ERROR;
Willy Tarreau20879a02012-12-03 16:32:10 +01001698 conn->err_code = CO_ER_SSL_RENEG;
1699 }
Emeric Brune1f38db2012-09-03 20:36:47 +02001700 }
Dirkjan Bussink526894f2019-01-21 09:35:03 -08001701#endif
Emeric Brund8b2bb52014-01-28 15:43:53 +01001702
1703 if ((where & SSL_CB_ACCEPT_LOOP) == SSL_CB_ACCEPT_LOOP) {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001704 if (!(ctx->xprt_st & SSL_SOCK_ST_FL_16K_WBFSIZE)) {
Emeric Brund8b2bb52014-01-28 15:43:53 +01001705 /* Long certificate chains optimz
1706 If write and read bios are differents, we
1707 consider that the buffering was activated,
1708 so we rise the output buffer size from 4k
1709 to 16k */
1710 write_bio = SSL_get_wbio(ssl);
1711 if (write_bio != SSL_get_rbio(ssl)) {
1712 BIO_set_write_buffer_size(write_bio, 16384);
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001713 ctx->xprt_st |= SSL_SOCK_ST_FL_16K_WBFSIZE;
Emeric Brund8b2bb52014-01-28 15:43:53 +01001714 }
1715 }
1716 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02001717}
1718
Emeric Brune64aef12012-09-21 13:15:06 +02001719/* Callback is called for each certificate of the chain during a verify
1720 ok is set to 1 if preverify detect no error on current certificate.
1721 Returns 0 to break the handshake, 1 otherwise. */
Evan Broderbe554312013-06-27 00:05:25 -07001722int ssl_sock_bind_verifycbk(int ok, X509_STORE_CTX *x_store)
Emeric Brune64aef12012-09-21 13:15:06 +02001723{
1724 SSL *ssl;
1725 struct connection *conn;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001726 struct ssl_sock_ctx *ctx;
Emeric Brun81c00f02012-09-21 14:31:21 +02001727 int err, depth;
Emeric Brune64aef12012-09-21 13:15:06 +02001728
1729 ssl = X509_STORE_CTX_get_ex_data(x_store, SSL_get_ex_data_X509_STORE_CTX_idx());
Thierry FOURNIER28962c92018-06-17 21:37:05 +02001730 conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Emeric Brune64aef12012-09-21 13:15:06 +02001731
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001732 ctx = conn->xprt_ctx;
1733
1734 ctx->xprt_st |= SSL_SOCK_ST_FL_VERIFY_DONE;
Emeric Brune64aef12012-09-21 13:15:06 +02001735
Emeric Brun81c00f02012-09-21 14:31:21 +02001736 if (ok) /* no errors */
1737 return ok;
1738
1739 depth = X509_STORE_CTX_get_error_depth(x_store);
1740 err = X509_STORE_CTX_get_error(x_store);
1741
1742 /* check if CA error needs to be ignored */
1743 if (depth > 0) {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001744 if (!SSL_SOCK_ST_TO_CA_ERROR(ctx->xprt_st)) {
1745 ctx->xprt_st |= SSL_SOCK_CA_ERROR_TO_ST(err);
1746 ctx->xprt_st |= SSL_SOCK_CAEDEPTH_TO_ST(depth);
Emeric Brunf282a812012-09-21 15:27:54 +02001747 }
1748
Willy Tarreau731248f2020-02-04 14:02:02 +01001749 if (err < 64 && __objt_listener(conn->target)->bind_conf->ca_ignerr & (1ULL << err)) {
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02001750 ssl_sock_dump_errors(conn);
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001751 ERR_clear_error();
Emeric Brun81c00f02012-09-21 14:31:21 +02001752 return 1;
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001753 }
Emeric Brun81c00f02012-09-21 14:31:21 +02001754
Willy Tarreau20879a02012-12-03 16:32:10 +01001755 conn->err_code = CO_ER_SSL_CA_FAIL;
Emeric Brun81c00f02012-09-21 14:31:21 +02001756 return 0;
1757 }
1758
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001759 if (!SSL_SOCK_ST_TO_CRTERROR(ctx->xprt_st))
1760 ctx->xprt_st |= SSL_SOCK_CRTERROR_TO_ST(err);
Emeric Brunf282a812012-09-21 15:27:54 +02001761
Emeric Brun81c00f02012-09-21 14:31:21 +02001762 /* check if certificate error needs to be ignored */
Willy Tarreau731248f2020-02-04 14:02:02 +01001763 if (err < 64 && __objt_listener(conn->target)->bind_conf->crt_ignerr & (1ULL << err)) {
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02001764 ssl_sock_dump_errors(conn);
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001765 ERR_clear_error();
Emeric Brun81c00f02012-09-21 14:31:21 +02001766 return 1;
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001767 }
Emeric Brun81c00f02012-09-21 14:31:21 +02001768
Willy Tarreau20879a02012-12-03 16:32:10 +01001769 conn->err_code = CO_ER_SSL_CRT_FAIL;
Emeric Brun81c00f02012-09-21 14:31:21 +02001770 return 0;
Emeric Brune64aef12012-09-21 13:15:06 +02001771}
1772
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001773static inline
1774void ssl_sock_parse_clienthello(int write_p, int version, int content_type,
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001775 const void *buf, size_t len, SSL *ssl)
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001776{
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001777 struct ssl_capture *capture;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001778 unsigned char *msg;
1779 unsigned char *end;
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001780 size_t rec_len;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001781
1782 /* This function is called for "from client" and "to server"
1783 * connections. The combination of write_p == 0 and content_type == 22
Joseph Herlant017b3da2018-11-15 09:07:59 -08001784 * is only available during "from client" connection.
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001785 */
1786
1787 /* "write_p" is set to 0 is the bytes are received messages,
1788 * otherwise it is set to 1.
1789 */
1790 if (write_p != 0)
1791 return;
1792
1793 /* content_type contains the type of message received or sent
1794 * according with the SSL/TLS protocol spec. This message is
1795 * encoded with one byte. The value 256 (two bytes) is used
1796 * for designing the SSL/TLS record layer. According with the
1797 * rfc6101, the expected message (other than 256) are:
1798 * - change_cipher_spec(20)
1799 * - alert(21)
1800 * - handshake(22)
1801 * - application_data(23)
1802 * - (255)
1803 * We are interessed by the handshake and specially the client
1804 * hello.
1805 */
1806 if (content_type != 22)
1807 return;
1808
1809 /* The message length is at least 4 bytes, containing the
1810 * message type and the message length.
1811 */
1812 if (len < 4)
1813 return;
1814
1815 /* First byte of the handshake message id the type of
1816 * message. The konwn types are:
1817 * - hello_request(0)
1818 * - client_hello(1)
1819 * - server_hello(2)
1820 * - certificate(11)
1821 * - server_key_exchange (12)
1822 * - certificate_request(13)
1823 * - server_hello_done(14)
1824 * We are interested by the client hello.
1825 */
1826 msg = (unsigned char *)buf;
1827 if (msg[0] != 1)
1828 return;
1829
1830 /* Next three bytes are the length of the message. The total length
1831 * must be this decoded length + 4. If the length given as argument
1832 * is not the same, we abort the protocol dissector.
1833 */
1834 rec_len = (msg[1] << 16) + (msg[2] << 8) + msg[3];
1835 if (len < rec_len + 4)
1836 return;
1837 msg += 4;
1838 end = msg + rec_len;
1839 if (end < msg)
1840 return;
1841
1842 /* Expect 2 bytes for protocol version (1 byte for major and 1 byte
1843 * for minor, the random, composed by 4 bytes for the unix time and
Baptiste Assmann6be139f2018-11-28 15:20:25 +01001844 * 28 bytes for unix payload. So we jump 1 + 1 + 4 + 28.
1845 */
1846 msg += 1 + 1 + 4 + 28;
1847 if (msg > end)
1848 return;
1849
1850 /* Next, is session id:
1851 * if present, we have to jump by length + 1 for the size information
1852 * if not present, we have to jump by 1 only
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001853 */
Baptiste Assmann6be139f2018-11-28 15:20:25 +01001854 if (msg[0] > 0)
1855 msg += msg[0];
1856 msg += 1;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001857 if (msg > end)
1858 return;
1859
1860 /* Next two bytes are the ciphersuite length. */
1861 if (msg + 2 > end)
1862 return;
1863 rec_len = (msg[0] << 8) + msg[1];
1864 msg += 2;
1865 if (msg + rec_len > end || msg + rec_len < msg)
1866 return;
1867
Willy Tarreaubafbe012017-11-24 17:34:44 +01001868 capture = pool_alloc_dirty(pool_head_ssl_capture);
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001869 if (!capture)
1870 return;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001871 /* Compute the xxh64 of the ciphersuite. */
1872 capture->xxh64 = XXH64(msg, rec_len, 0);
1873
1874 /* Capture the ciphersuite. */
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001875 capture->ciphersuite_len = (global_ssl.capture_cipherlist < rec_len) ?
1876 global_ssl.capture_cipherlist : rec_len;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001877 memcpy(capture->ciphersuite, msg, capture->ciphersuite_len);
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001878
1879 SSL_set_ex_data(ssl, ssl_capture_ptr_index, capture);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001880}
1881
Emeric Brun29f037d2014-04-25 19:05:36 +02001882/* Callback is called for ssl protocol analyse */
1883void ssl_sock_msgcbk(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg)
1884{
Emeric Brun29f037d2014-04-25 19:05:36 +02001885#ifdef TLS1_RT_HEARTBEAT
1886 /* test heartbeat received (write_p is set to 0
1887 for a received record) */
Willy Tarreauf51c6982014-04-25 20:02:39 +02001888 if ((content_type == TLS1_RT_HEARTBEAT) && (write_p == 0)) {
Thierry FOURNIER28962c92018-06-17 21:37:05 +02001889 struct connection *conn = SSL_get_ex_data(ssl, ssl_app_data_index);
William Lallemand7e1770b2019-05-13 14:31:34 +02001890 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
Willy Tarreauf51c6982014-04-25 20:02:39 +02001891 const unsigned char *p = buf;
1892 unsigned int payload;
1893
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001894 ctx->xprt_st |= SSL_SOCK_RECV_HEARTBEAT;
Willy Tarreauf51c6982014-04-25 20:02:39 +02001895
1896 /* Check if this is a CVE-2014-0160 exploitation attempt. */
1897 if (*p != TLS1_HB_REQUEST)
1898 return;
1899
Willy Tarreauaeed6722014-04-25 23:59:58 +02001900 if (len < 1 + 2 + 16) /* 1 type + 2 size + 0 payload + 16 padding */
Willy Tarreauf51c6982014-04-25 20:02:39 +02001901 goto kill_it;
1902
1903 payload = (p[1] * 256) + p[2];
Willy Tarreau3b2fdb62014-04-25 23:44:22 +02001904 if (3 + payload + 16 <= len)
Willy Tarreauf51c6982014-04-25 20:02:39 +02001905 return; /* OK no problem */
Willy Tarreauaeed6722014-04-25 23:59:58 +02001906 kill_it:
Willy Tarreau3b2fdb62014-04-25 23:44:22 +02001907 /* We have a clear heartbleed attack (CVE-2014-0160), the
1908 * advertised payload is larger than the advertised packet
1909 * length, so we have garbage in the buffer between the
1910 * payload and the end of the buffer (p+len). We can't know
1911 * if the SSL stack is patched, and we don't know if we can
1912 * safely wipe out the area between p+3+len and payload.
1913 * So instead, we prevent the response from being sent by
1914 * setting the max_send_fragment to 0 and we report an SSL
1915 * error, which will kill this connection. It will be reported
1916 * above as SSL_ERROR_SSL while an other handshake failure with
Willy Tarreauf51c6982014-04-25 20:02:39 +02001917 * a heartbeat message will be reported as SSL_ERROR_SYSCALL.
1918 */
Willy Tarreau3b2fdb62014-04-25 23:44:22 +02001919 ssl->max_send_fragment = 0;
Willy Tarreauf51c6982014-04-25 20:02:39 +02001920 SSLerr(SSL_F_TLS1_HEARTBEAT, SSL_R_SSL_HANDSHAKE_FAILURE);
1921 return;
1922 }
Emeric Brun29f037d2014-04-25 19:05:36 +02001923#endif
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001924 if (global_ssl.capture_cipherlist > 0)
1925 ssl_sock_parse_clienthello(write_p, version, content_type, buf, len, ssl);
Emeric Brun29f037d2014-04-25 19:05:36 +02001926}
1927
Bernard Spil13c53f82018-02-15 13:34:58 +01001928#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Olivier Houchardc7566002018-11-20 23:33:50 +01001929static int ssl_sock_srv_select_protos(SSL *s, unsigned char **out, unsigned char *outlen,
1930 const unsigned char *in, unsigned int inlen,
1931 void *arg)
1932{
1933 struct server *srv = arg;
1934
1935 if (SSL_select_next_proto(out, outlen, in, inlen, (unsigned char *)srv->ssl_ctx.npn_str,
1936 srv->ssl_ctx.npn_len) == OPENSSL_NPN_NEGOTIATED)
1937 return SSL_TLSEXT_ERR_OK;
1938 return SSL_TLSEXT_ERR_NOACK;
1939}
1940#endif
1941
1942#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02001943/* This callback is used so that the server advertises the list of
1944 * negociable protocols for NPN.
1945 */
1946static int ssl_sock_advertise_npn_protos(SSL *s, const unsigned char **data,
1947 unsigned int *len, void *arg)
1948{
Emmanuel Hocdet98263292016-12-29 18:26:15 +01001949 struct ssl_bind_conf *conf = arg;
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02001950
1951 *data = (const unsigned char *)conf->npn_str;
1952 *len = conf->npn_len;
1953 return SSL_TLSEXT_ERR_OK;
1954}
1955#endif
1956
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01001957#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02001958/* This callback is used so that the server advertises the list of
1959 * negociable protocols for ALPN.
1960 */
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01001961static int ssl_sock_advertise_alpn_protos(SSL *s, const unsigned char **out,
1962 unsigned char *outlen,
1963 const unsigned char *server,
1964 unsigned int server_len, void *arg)
Willy Tarreauab861d32013-04-02 02:30:41 +02001965{
Emmanuel Hocdet98263292016-12-29 18:26:15 +01001966 struct ssl_bind_conf *conf = arg;
Willy Tarreauab861d32013-04-02 02:30:41 +02001967
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01001968 if (SSL_select_next_proto((unsigned char**) out, outlen, (const unsigned char *)conf->alpn_str,
1969 conf->alpn_len, server, server_len) != OPENSSL_NPN_NEGOTIATED) {
1970 return SSL_TLSEXT_ERR_NOACK;
1971 }
Willy Tarreauab861d32013-04-02 02:30:41 +02001972 return SSL_TLSEXT_ERR_OK;
1973}
1974#endif
1975
Willy Tarreauc8ad3be2015-06-17 15:48:26 +02001976#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01001977#ifndef SSL_NO_GENERATE_CERTIFICATES
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001978
Christopher Faulet30548802015-06-11 13:39:32 +02001979/* Create a X509 certificate with the specified servername and serial. This
1980 * function returns a SSL_CTX object or NULL if an error occurs. */
Christopher Faulet7969a332015-10-09 11:15:03 +02001981static SSL_CTX *
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001982ssl_sock_do_create_cert(const char *servername, struct bind_conf *bind_conf, SSL *ssl)
Christopher Faulet31af49d2015-06-09 17:29:50 +02001983{
Christopher Faulet7969a332015-10-09 11:15:03 +02001984 X509 *cacert = bind_conf->ca_sign_cert;
1985 EVP_PKEY *capkey = bind_conf->ca_sign_pkey;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001986 SSL_CTX *ssl_ctx = NULL;
1987 X509 *newcrt = NULL;
1988 EVP_PKEY *pkey = NULL;
Emmanuel Hocdet15969292017-08-11 10:56:00 +02001989 SSL *tmp_ssl = NULL;
Emmanuel Hocdeta9b84022018-10-01 18:41:36 +02001990 CONF *ctmp = NULL;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001991 X509_NAME *name;
1992 const EVP_MD *digest;
1993 X509V3_CTX ctx;
1994 unsigned int i;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001995 int key_type;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001996
Christopher Faulet48a83322017-07-28 16:56:09 +02001997 /* Get the private key of the default certificate and use it */
Willy Tarreau5db847a2019-05-09 14:13:35 +02001998#if (HA_OPENSSL_VERSION_NUMBER >= 0x10002000L)
Emmanuel Hocdet15969292017-08-11 10:56:00 +02001999 pkey = SSL_CTX_get0_privatekey(bind_conf->default_ctx);
2000#else
2001 tmp_ssl = SSL_new(bind_conf->default_ctx);
2002 if (tmp_ssl)
2003 pkey = SSL_get_privatekey(tmp_ssl);
2004#endif
2005 if (!pkey)
Christopher Faulet31af49d2015-06-09 17:29:50 +02002006 goto mkcert_error;
2007
2008 /* Create the certificate */
2009 if (!(newcrt = X509_new()))
2010 goto mkcert_error;
2011
2012 /* Set version number for the certificate (X509v3) and the serial
2013 * number */
2014 if (X509_set_version(newcrt, 2L) != 1)
2015 goto mkcert_error;
Olivier Houchard2be5a4c2019-03-08 18:54:43 +01002016 ASN1_INTEGER_set(X509_get_serialNumber(newcrt), _HA_ATOMIC_ADD(&ssl_ctx_serial, 1));
Christopher Faulet31af49d2015-06-09 17:29:50 +02002017
2018 /* Set duration for the certificate */
Rosen Penev68185952018-12-14 08:47:02 -08002019 if (!X509_gmtime_adj(X509_getm_notBefore(newcrt), (long)-60*60*24) ||
2020 !X509_gmtime_adj(X509_getm_notAfter(newcrt),(long)60*60*24*365))
Christopher Faulet31af49d2015-06-09 17:29:50 +02002021 goto mkcert_error;
2022
2023 /* set public key in the certificate */
2024 if (X509_set_pubkey(newcrt, pkey) != 1)
2025 goto mkcert_error;
2026
2027 /* Set issuer name from the CA */
2028 if (!(name = X509_get_subject_name(cacert)))
2029 goto mkcert_error;
2030 if (X509_set_issuer_name(newcrt, name) != 1)
2031 goto mkcert_error;
2032
2033 /* Set the subject name using the same, but the CN */
2034 name = X509_NAME_dup(name);
2035 if (X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC,
2036 (const unsigned char *)servername,
2037 -1, -1, 0) != 1) {
2038 X509_NAME_free(name);
2039 goto mkcert_error;
2040 }
2041 if (X509_set_subject_name(newcrt, name) != 1) {
2042 X509_NAME_free(name);
2043 goto mkcert_error;
2044 }
2045 X509_NAME_free(name);
2046
2047 /* Add x509v3 extensions as specified */
Emmanuel Hocdeta9b84022018-10-01 18:41:36 +02002048 ctmp = NCONF_new(NULL);
Christopher Faulet31af49d2015-06-09 17:29:50 +02002049 X509V3_set_ctx(&ctx, cacert, newcrt, NULL, NULL, 0);
2050 for (i = 0; i < X509V3_EXT_SIZE; i++) {
2051 X509_EXTENSION *ext;
2052
Emmanuel Hocdeta9b84022018-10-01 18:41:36 +02002053 if (!(ext = X509V3_EXT_nconf(ctmp, &ctx, x509v3_ext_names[i], x509v3_ext_values[i])))
Christopher Faulet31af49d2015-06-09 17:29:50 +02002054 goto mkcert_error;
2055 if (!X509_add_ext(newcrt, ext, -1)) {
2056 X509_EXTENSION_free(ext);
2057 goto mkcert_error;
2058 }
2059 X509_EXTENSION_free(ext);
2060 }
2061
2062 /* Sign the certificate with the CA private key */
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002063
2064 key_type = EVP_PKEY_base_id(capkey);
2065
2066 if (key_type == EVP_PKEY_DSA)
2067 digest = EVP_sha1();
2068 else if (key_type == EVP_PKEY_RSA)
Christopher Faulet31af49d2015-06-09 17:29:50 +02002069 digest = EVP_sha256();
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002070 else if (key_type == EVP_PKEY_EC)
Christopher Faulet7969a332015-10-09 11:15:03 +02002071 digest = EVP_sha256();
2072 else {
Willy Tarreau9a1ab082019-05-09 13:26:41 +02002073#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000000fL) && !defined(OPENSSL_IS_BORINGSSL)
Christopher Faulet7969a332015-10-09 11:15:03 +02002074 int nid;
2075
2076 if (EVP_PKEY_get_default_digest_nid(capkey, &nid) <= 0)
2077 goto mkcert_error;
2078 if (!(digest = EVP_get_digestbynid(nid)))
2079 goto mkcert_error;
Christopher Faulete7db2162015-10-19 13:59:24 +02002080#else
2081 goto mkcert_error;
2082#endif
Christopher Faulet7969a332015-10-09 11:15:03 +02002083 }
2084
Christopher Faulet31af49d2015-06-09 17:29:50 +02002085 if (!(X509_sign(newcrt, capkey, digest)))
2086 goto mkcert_error;
2087
2088 /* Create and set the new SSL_CTX */
2089 if (!(ssl_ctx = SSL_CTX_new(SSLv23_server_method())))
2090 goto mkcert_error;
2091 if (!SSL_CTX_use_PrivateKey(ssl_ctx, pkey))
2092 goto mkcert_error;
2093 if (!SSL_CTX_use_certificate(ssl_ctx, newcrt))
2094 goto mkcert_error;
2095 if (!SSL_CTX_check_private_key(ssl_ctx))
2096 goto mkcert_error;
2097
2098 if (newcrt) X509_free(newcrt);
Christopher Faulet7969a332015-10-09 11:15:03 +02002099
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01002100#ifndef OPENSSL_NO_DH
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02002101 SSL_CTX_set_tmp_dh_callback(ssl_ctx, ssl_get_tmp_dh);
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01002102#endif
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02002103#if defined(SSL_CTX_set_tmp_ecdh) && !defined(OPENSSL_NO_ECDH)
2104 {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01002105 const char *ecdhe = (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe : ECDHE_DEFAULT_CURVE);
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02002106 EC_KEY *ecc;
2107 int nid;
2108
2109 if ((nid = OBJ_sn2nid(ecdhe)) == NID_undef)
2110 goto end;
2111 if (!(ecc = EC_KEY_new_by_curve_name(nid)))
2112 goto end;
2113 SSL_CTX_set_tmp_ecdh(ssl_ctx, ecc);
2114 EC_KEY_free(ecc);
2115 }
2116#endif
2117 end:
Christopher Faulet31af49d2015-06-09 17:29:50 +02002118 return ssl_ctx;
2119
2120 mkcert_error:
Emmanuel Hocdeta9b84022018-10-01 18:41:36 +02002121 if (ctmp) NCONF_free(ctmp);
Emmanuel Hocdet15969292017-08-11 10:56:00 +02002122 if (tmp_ssl) SSL_free(tmp_ssl);
Christopher Faulet31af49d2015-06-09 17:29:50 +02002123 if (ssl_ctx) SSL_CTX_free(ssl_ctx);
2124 if (newcrt) X509_free(newcrt);
Christopher Faulet31af49d2015-06-09 17:29:50 +02002125 return NULL;
2126}
2127
Christopher Faulet7969a332015-10-09 11:15:03 +02002128SSL_CTX *
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002129ssl_sock_create_cert(struct connection *conn, const char *servername, unsigned int key)
Christopher Faulet7969a332015-10-09 11:15:03 +02002130{
Willy Tarreau07d94e42018-09-20 10:57:52 +02002131 struct bind_conf *bind_conf = __objt_listener(conn->target)->bind_conf;
Olivier Houchard66ab4982019-02-26 18:37:15 +01002132 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002133
Olivier Houchard66ab4982019-02-26 18:37:15 +01002134 return ssl_sock_do_create_cert(servername, bind_conf, ctx->ssl);
Christopher Faulet7969a332015-10-09 11:15:03 +02002135}
2136
Christopher Faulet30548802015-06-11 13:39:32 +02002137/* Do a lookup for a certificate in the LRU cache used to store generated
Emeric Brun821bb9b2017-06-15 16:37:39 +02002138 * certificates and immediately assign it to the SSL session if not null. */
Christopher Faulet30548802015-06-11 13:39:32 +02002139SSL_CTX *
Emeric Brun821bb9b2017-06-15 16:37:39 +02002140ssl_sock_assign_generated_cert(unsigned int key, struct bind_conf *bind_conf, SSL *ssl)
Christopher Faulet30548802015-06-11 13:39:32 +02002141{
2142 struct lru64 *lru = NULL;
2143
2144 if (ssl_ctx_lru_tree) {
Willy Tarreau03f4ec42018-05-17 10:56:47 +02002145 HA_RWLOCK_WRLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002146 lru = lru64_lookup(key, ssl_ctx_lru_tree, bind_conf->ca_sign_cert, 0);
Emeric Brun821bb9b2017-06-15 16:37:39 +02002147 if (lru && lru->domain) {
2148 if (ssl)
2149 SSL_set_SSL_CTX(ssl, (SSL_CTX *)lru->data);
Willy Tarreau03f4ec42018-05-17 10:56:47 +02002150 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet30548802015-06-11 13:39:32 +02002151 return (SSL_CTX *)lru->data;
Emeric Brun821bb9b2017-06-15 16:37:39 +02002152 }
Willy Tarreau03f4ec42018-05-17 10:56:47 +02002153 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet30548802015-06-11 13:39:32 +02002154 }
2155 return NULL;
2156}
2157
Emeric Brun821bb9b2017-06-15 16:37:39 +02002158/* Same as <ssl_sock_assign_generated_cert> but without SSL session. This
2159 * function is not thread-safe, it should only be used to check if a certificate
2160 * exists in the lru cache (with no warranty it will not be removed by another
2161 * thread). It is kept for backward compatibility. */
2162SSL_CTX *
2163ssl_sock_get_generated_cert(unsigned int key, struct bind_conf *bind_conf)
2164{
2165 return ssl_sock_assign_generated_cert(key, bind_conf, NULL);
2166}
2167
Christopher Fauletd2cab922015-07-28 16:03:47 +02002168/* Set a certificate int the LRU cache used to store generated
2169 * certificate. Return 0 on success, otherwise -1 */
2170int
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002171ssl_sock_set_generated_cert(SSL_CTX *ssl_ctx, unsigned int key, struct bind_conf *bind_conf)
Christopher Faulet30548802015-06-11 13:39:32 +02002172{
2173 struct lru64 *lru = NULL;
2174
2175 if (ssl_ctx_lru_tree) {
Christopher Faulet2a944ee2017-11-07 10:42:54 +01002176 HA_RWLOCK_WRLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002177 lru = lru64_get(key, ssl_ctx_lru_tree, bind_conf->ca_sign_cert, 0);
Emeric Brun821bb9b2017-06-15 16:37:39 +02002178 if (!lru) {
Christopher Faulet2a944ee2017-11-07 10:42:54 +01002179 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Fauletd2cab922015-07-28 16:03:47 +02002180 return -1;
Emeric Brun821bb9b2017-06-15 16:37:39 +02002181 }
Christopher Faulet30548802015-06-11 13:39:32 +02002182 if (lru->domain && lru->data)
2183 lru->free((SSL_CTX *)lru->data);
Christopher Faulet7969a332015-10-09 11:15:03 +02002184 lru64_commit(lru, ssl_ctx, bind_conf->ca_sign_cert, 0, (void (*)(void *))SSL_CTX_free);
Christopher Faulet2a944ee2017-11-07 10:42:54 +01002185 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Fauletd2cab922015-07-28 16:03:47 +02002186 return 0;
Christopher Faulet30548802015-06-11 13:39:32 +02002187 }
Christopher Fauletd2cab922015-07-28 16:03:47 +02002188 return -1;
Christopher Faulet30548802015-06-11 13:39:32 +02002189}
2190
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002191/* Compute the key of the certificate. */
Christopher Faulet30548802015-06-11 13:39:32 +02002192unsigned int
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002193ssl_sock_generated_cert_key(const void *data, size_t len)
Christopher Faulet30548802015-06-11 13:39:32 +02002194{
2195 return XXH32(data, len, ssl_ctx_lru_seed);
2196}
2197
Willy Tarreau2f63ef42015-10-20 15:16:01 +02002198/* Generate a cert and immediately assign it to the SSL session so that the cert's
2199 * refcount is maintained regardless of the cert's presence in the LRU cache.
2200 */
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002201static int
Christopher Faulet7969a332015-10-09 11:15:03 +02002202ssl_sock_generate_certificate(const char *servername, struct bind_conf *bind_conf, SSL *ssl)
Christopher Faulet31af49d2015-06-09 17:29:50 +02002203{
2204 X509 *cacert = bind_conf->ca_sign_cert;
Christopher Faulet31af49d2015-06-09 17:29:50 +02002205 SSL_CTX *ssl_ctx = NULL;
2206 struct lru64 *lru = NULL;
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002207 unsigned int key;
Christopher Faulet31af49d2015-06-09 17:29:50 +02002208
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002209 key = ssl_sock_generated_cert_key(servername, strlen(servername));
Christopher Faulet31af49d2015-06-09 17:29:50 +02002210 if (ssl_ctx_lru_tree) {
Christopher Faulet2a944ee2017-11-07 10:42:54 +01002211 HA_RWLOCK_WRLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002212 lru = lru64_get(key, ssl_ctx_lru_tree, cacert, 0);
Christopher Faulet31af49d2015-06-09 17:29:50 +02002213 if (lru && lru->domain)
2214 ssl_ctx = (SSL_CTX *)lru->data;
Christopher Fauletd2cab922015-07-28 16:03:47 +02002215 if (!ssl_ctx && lru) {
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002216 ssl_ctx = ssl_sock_do_create_cert(servername, bind_conf, ssl);
Christopher Faulet31af49d2015-06-09 17:29:50 +02002217 lru64_commit(lru, ssl_ctx, cacert, 0, (void (*)(void *))SSL_CTX_free);
Christopher Fauletd2cab922015-07-28 16:03:47 +02002218 }
Willy Tarreau2f63ef42015-10-20 15:16:01 +02002219 SSL_set_SSL_CTX(ssl, ssl_ctx);
Christopher Faulet2a944ee2017-11-07 10:42:54 +01002220 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002221 return 1;
Christopher Faulet31af49d2015-06-09 17:29:50 +02002222 }
Willy Tarreau2f63ef42015-10-20 15:16:01 +02002223 else {
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002224 ssl_ctx = ssl_sock_do_create_cert(servername, bind_conf, ssl);
Willy Tarreau2f63ef42015-10-20 15:16:01 +02002225 SSL_set_SSL_CTX(ssl, ssl_ctx);
2226 /* No LRU cache, this CTX will be released as soon as the session dies */
2227 SSL_CTX_free(ssl_ctx);
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002228 return 1;
Willy Tarreau2f63ef42015-10-20 15:16:01 +02002229 }
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002230 return 0;
2231}
2232static int
2233ssl_sock_generate_certificate_from_conn(struct bind_conf *bind_conf, SSL *ssl)
2234{
2235 unsigned int key;
Thierry FOURNIER28962c92018-06-17 21:37:05 +02002236 struct connection *conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002237
Willy Tarreauf5bdb642019-07-17 11:29:32 +02002238 if (conn_get_dst(conn)) {
Willy Tarreau085a1512019-07-17 14:47:35 +02002239 key = ssl_sock_generated_cert_key(conn->dst, get_addr_len(conn->dst));
Emeric Brun821bb9b2017-06-15 16:37:39 +02002240 if (ssl_sock_assign_generated_cert(key, bind_conf, ssl))
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002241 return 1;
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002242 }
2243 return 0;
Christopher Faulet31af49d2015-06-09 17:29:50 +02002244}
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002245#endif /* !defined SSL_NO_GENERATE_CERTIFICATES */
Christopher Faulet31af49d2015-06-09 17:29:50 +02002246
Willy Tarreau9a1ab082019-05-09 13:26:41 +02002247#if (HA_OPENSSL_VERSION_NUMBER < 0x1010000fL)
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002248typedef enum { SET_CLIENT, SET_SERVER } set_context_func;
2249
2250static void ctx_set_SSLv3_func(SSL_CTX *ctx, set_context_func c)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002251{
Emmanuel Hocdet23877ab2017-07-12 12:53:02 +02002252#if SSL_OP_NO_SSLv3
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002253 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, SSLv3_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002254 : SSL_CTX_set_ssl_version(ctx, SSLv3_client_method());
2255#endif
2256}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002257static void ctx_set_TLSv10_func(SSL_CTX *ctx, set_context_func c) {
2258 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, TLSv1_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002259 : SSL_CTX_set_ssl_version(ctx, TLSv1_client_method());
2260}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002261static void ctx_set_TLSv11_func(SSL_CTX *ctx, set_context_func c) {
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002262#if SSL_OP_NO_TLSv1_1
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002263 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, TLSv1_1_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002264 : SSL_CTX_set_ssl_version(ctx, TLSv1_1_client_method());
2265#endif
2266}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002267static void ctx_set_TLSv12_func(SSL_CTX *ctx, set_context_func c) {
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002268#if SSL_OP_NO_TLSv1_2
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002269 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, TLSv1_2_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002270 : SSL_CTX_set_ssl_version(ctx, TLSv1_2_client_method());
2271#endif
2272}
Bertrand Jacquina25282b2018-08-14 00:56:13 +01002273/* TLSv1.2 is the last supported version in this context. */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002274static void ctx_set_TLSv13_func(SSL_CTX *ctx, set_context_func c) {}
2275/* Unusable in this context. */
2276static void ssl_set_SSLv3_func(SSL *ssl, set_context_func c) {}
2277static void ssl_set_TLSv10_func(SSL *ssl, set_context_func c) {}
2278static void ssl_set_TLSv11_func(SSL *ssl, set_context_func c) {}
2279static void ssl_set_TLSv12_func(SSL *ssl, set_context_func c) {}
2280static void ssl_set_TLSv13_func(SSL *ssl, set_context_func c) {}
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002281#else /* openssl >= 1.1.0 */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002282typedef enum { SET_MIN, SET_MAX } set_context_func;
2283
2284static void ctx_set_SSLv3_func(SSL_CTX *ctx, set_context_func c) {
2285 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, SSL3_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002286 : SSL_CTX_set_min_proto_version(ctx, SSL3_VERSION);
2287}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002288static void ssl_set_SSLv3_func(SSL *ssl, set_context_func c) {
2289 c == SET_MAX ? SSL_set_max_proto_version(ssl, SSL3_VERSION)
2290 : SSL_set_min_proto_version(ssl, SSL3_VERSION);
2291}
2292static void ctx_set_TLSv10_func(SSL_CTX *ctx, set_context_func c) {
2293 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002294 : SSL_CTX_set_min_proto_version(ctx, TLS1_VERSION);
2295}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002296static void ssl_set_TLSv10_func(SSL *ssl, set_context_func c) {
2297 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_VERSION)
2298 : SSL_set_min_proto_version(ssl, TLS1_VERSION);
2299}
2300static void ctx_set_TLSv11_func(SSL_CTX *ctx, set_context_func c) {
2301 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_1_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002302 : SSL_CTX_set_min_proto_version(ctx, TLS1_1_VERSION);
2303}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002304static void ssl_set_TLSv11_func(SSL *ssl, set_context_func c) {
2305 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_1_VERSION)
2306 : SSL_set_min_proto_version(ssl, TLS1_1_VERSION);
2307}
2308static void ctx_set_TLSv12_func(SSL_CTX *ctx, set_context_func c) {
2309 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_2_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002310 : SSL_CTX_set_min_proto_version(ctx, TLS1_2_VERSION);
2311}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002312static void ssl_set_TLSv12_func(SSL *ssl, set_context_func c) {
2313 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_2_VERSION)
2314 : SSL_set_min_proto_version(ssl, TLS1_2_VERSION);
2315}
2316static void ctx_set_TLSv13_func(SSL_CTX *ctx, set_context_func c) {
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002317#if SSL_OP_NO_TLSv1_3
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002318 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_3_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002319 : SSL_CTX_set_min_proto_version(ctx, TLS1_3_VERSION);
2320#endif
2321}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002322static void ssl_set_TLSv13_func(SSL *ssl, set_context_func c) {
2323#if SSL_OP_NO_TLSv1_3
2324 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_3_VERSION)
2325 : SSL_set_min_proto_version(ssl, TLS1_3_VERSION);
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002326#endif
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002327}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002328#endif
2329static void ctx_set_None_func(SSL_CTX *ctx, set_context_func c) { }
2330static void ssl_set_None_func(SSL *ssl, set_context_func c) { }
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002331
2332static struct {
2333 int option;
2334 uint16_t flag;
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002335 void (*ctx_set_version)(SSL_CTX *, set_context_func);
2336 void (*ssl_set_version)(SSL *, set_context_func);
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002337 const char *name;
2338} methodVersions[] = {
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002339 {0, 0, ctx_set_None_func, ssl_set_None_func, "NONE"}, /* CONF_TLSV_NONE */
2340 {SSL_OP_NO_SSLv3, MC_SSL_O_NO_SSLV3, ctx_set_SSLv3_func, ssl_set_SSLv3_func, "SSLv3"}, /* CONF_SSLV3 */
2341 {SSL_OP_NO_TLSv1, MC_SSL_O_NO_TLSV10, ctx_set_TLSv10_func, ssl_set_TLSv10_func, "TLSv1.0"}, /* CONF_TLSV10 */
2342 {SSL_OP_NO_TLSv1_1, MC_SSL_O_NO_TLSV11, ctx_set_TLSv11_func, ssl_set_TLSv11_func, "TLSv1.1"}, /* CONF_TLSV11 */
2343 {SSL_OP_NO_TLSv1_2, MC_SSL_O_NO_TLSV12, ctx_set_TLSv12_func, ssl_set_TLSv12_func, "TLSv1.2"}, /* CONF_TLSV12 */
2344 {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 +02002345};
2346
Emmanuel Hocdet530141f2017-03-01 18:54:56 +01002347static void ssl_sock_switchctx_set(SSL *ssl, SSL_CTX *ctx)
2348{
2349 SSL_set_verify(ssl, SSL_CTX_get_verify_mode(ctx), ssl_sock_bind_verifycbk);
2350 SSL_set_client_CA_list(ssl, SSL_dup_CA_list(SSL_CTX_get_client_CA_list(ctx)));
2351 SSL_set_SSL_CTX(ssl, ctx);
2352}
2353
Willy Tarreau5db847a2019-05-09 14:13:35 +02002354#if ((HA_OPENSSL_VERSION_NUMBER >= 0x10101000L) || defined(OPENSSL_IS_BORINGSSL))
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002355
2356static int ssl_sock_switchctx_err_cbk(SSL *ssl, int *al, void *priv)
2357{
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002358 struct bind_conf *s = priv;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002359 (void)al; /* shut gcc stupid warning */
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002360
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002361 if (SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name) || s->generate_certs)
2362 return SSL_TLSEXT_ERR_OK;
2363 return SSL_TLSEXT_ERR_NOACK;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002364}
2365
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002366#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002367static int ssl_sock_switchctx_cbk(const struct ssl_early_callback_ctx *ctx)
2368{
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002369 SSL *ssl = ctx->ssl;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002370#else
2371static int ssl_sock_switchctx_cbk(SSL *ssl, int *al, void *arg)
2372{
2373#endif
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002374 struct connection *conn;
2375 struct bind_conf *s;
2376 const uint8_t *extension_data;
2377 size_t extension_len;
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002378 int has_rsa_sig = 0, has_ecdsa_sig = 0;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002379
2380 char *wildp = NULL;
2381 const uint8_t *servername;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002382 size_t servername_len;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002383 struct ebmb_node *node, *n, *node_ecdsa = NULL, *node_rsa = NULL, *node_anonymous = NULL;
Olivier Houchardc2aae742017-09-22 18:26:28 +02002384 int allow_early = 0;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002385 int i;
2386
Thierry FOURNIER28962c92018-06-17 21:37:05 +02002387 conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Willy Tarreaua8825522018-10-15 13:20:07 +02002388 s = __objt_listener(conn->target)->bind_conf;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002389
Olivier Houchard9679ac92017-10-27 14:58:08 +02002390 if (s->ssl_conf.early_data)
Olivier Houchardc2aae742017-09-22 18:26:28 +02002391 allow_early = 1;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002392#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002393 if (SSL_early_callback_ctx_extension_get(ctx, TLSEXT_TYPE_server_name,
2394 &extension_data, &extension_len)) {
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002395#else
2396 if (SSL_client_hello_get0_ext(ssl, TLSEXT_TYPE_server_name, &extension_data, &extension_len)) {
2397#endif
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002398 /*
2399 * The server_name extension was given too much extensibility when it
2400 * was written, so parsing the normal case is a bit complex.
2401 */
2402 size_t len;
2403 if (extension_len <= 2)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002404 goto abort;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002405 /* Extract the length of the supplied list of names. */
2406 len = (*extension_data++) << 8;
2407 len |= *extension_data++;
2408 if (len + 2 != extension_len)
2409 goto abort;
2410 /*
2411 * The list in practice only has a single element, so we only consider
2412 * the first one.
2413 */
2414 if (len == 0 || *extension_data++ != TLSEXT_NAMETYPE_host_name)
2415 goto abort;
2416 extension_len = len - 1;
2417 /* Now we can finally pull out the byte array with the actual hostname. */
2418 if (extension_len <= 2)
2419 goto abort;
2420 len = (*extension_data++) << 8;
2421 len |= *extension_data++;
2422 if (len == 0 || len + 2 > extension_len || len > TLSEXT_MAXLEN_host_name
2423 || memchr(extension_data, 0, len) != NULL)
2424 goto abort;
2425 servername = extension_data;
2426 servername_len = len;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002427 } else {
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002428#if (!defined SSL_NO_GENERATE_CERTIFICATES)
2429 if (s->generate_certs && ssl_sock_generate_certificate_from_conn(s, ssl)) {
Olivier Houchardc2aae742017-09-22 18:26:28 +02002430 goto allow_early;
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002431 }
2432#endif
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002433 /* without SNI extension, is the default_ctx (need SSL_TLSEXT_ERR_NOACK) */
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002434 if (!s->strict_sni) {
William Lallemand21724f02019-11-04 17:56:13 +01002435 HA_RWLOCK_RDLOCK(SNI_LOCK, &s->sni_lock);
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002436 ssl_sock_switchctx_set(ssl, s->default_ctx);
William Lallemand21724f02019-11-04 17:56:13 +01002437 HA_RWLOCK_RDUNLOCK(SNI_LOCK, &s->sni_lock);
Olivier Houchardc2aae742017-09-22 18:26:28 +02002438 goto allow_early;
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002439 }
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002440 goto abort;
2441 }
2442
2443 /* extract/check clientHello informations */
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002444#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002445 if (SSL_early_callback_ctx_extension_get(ctx, TLSEXT_TYPE_signature_algorithms, &extension_data, &extension_len)) {
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002446#else
2447 if (SSL_client_hello_get0_ext(ssl, TLSEXT_TYPE_signature_algorithms, &extension_data, &extension_len)) {
2448#endif
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002449 uint8_t sign;
2450 size_t len;
2451 if (extension_len < 2)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002452 goto abort;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002453 len = (*extension_data++) << 8;
2454 len |= *extension_data++;
2455 if (len + 2 != extension_len)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002456 goto abort;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002457 if (len % 2 != 0)
2458 goto abort;
2459 for (; len > 0; len -= 2) {
2460 extension_data++; /* hash */
2461 sign = *extension_data++;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002462 switch (sign) {
2463 case TLSEXT_signature_rsa:
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002464 has_rsa_sig = 1;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002465 break;
2466 case TLSEXT_signature_ecdsa:
2467 has_ecdsa_sig = 1;
2468 break;
2469 default:
2470 continue;
2471 }
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002472 if (has_ecdsa_sig && has_rsa_sig)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002473 break;
2474 }
2475 } else {
Bertrand Jacquina25282b2018-08-14 00:56:13 +01002476 /* without TLSEXT_TYPE_signature_algorithms extension (< TLSv1.2) */
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002477 has_rsa_sig = 1;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002478 }
2479 if (has_ecdsa_sig) { /* in very rare case: has ecdsa sign but not a ECDSA cipher */
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002480 const SSL_CIPHER *cipher;
2481 size_t len;
2482 const uint8_t *cipher_suites;
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002483 has_ecdsa_sig = 0;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002484#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002485 len = ctx->cipher_suites_len;
2486 cipher_suites = ctx->cipher_suites;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002487#else
2488 len = SSL_client_hello_get0_ciphers(ssl, &cipher_suites);
2489#endif
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002490 if (len % 2 != 0)
2491 goto abort;
2492 for (; len != 0; len -= 2, cipher_suites += 2) {
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002493#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002494 uint16_t cipher_suite = (cipher_suites[0] << 8) | cipher_suites[1];
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002495 cipher = SSL_get_cipher_by_value(cipher_suite);
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002496#else
2497 cipher = SSL_CIPHER_find(ssl, cipher_suites);
2498#endif
Emmanuel Hocdet019f9b12017-10-02 17:12:06 +02002499 if (cipher && SSL_CIPHER_get_auth_nid(cipher) == NID_auth_ecdsa) {
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002500 has_ecdsa_sig = 1;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002501 break;
2502 }
2503 }
2504 }
2505
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002506 for (i = 0; i < trash.size && i < servername_len; i++) {
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002507 trash.area[i] = tolower(servername[i]);
2508 if (!wildp && (trash.area[i] == '.'))
2509 wildp = &trash.area[i];
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002510 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002511 trash.area[i] = 0;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002512
William Lallemand150bfa82019-09-19 17:12:49 +02002513 HA_RWLOCK_RDLOCK(SNI_LOCK, &s->sni_lock);
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002514
Emmanuel Hocdet3777e3a2019-11-06 16:05:34 +01002515 for (i = 0; i < 2; i++) {
2516 if (i == 0) /* lookup in full qualified names */
2517 node = ebst_lookup(&s->sni_ctx, trash.area);
2518 else if (i == 1 && wildp) /* lookup in wildcards names */
2519 node = ebst_lookup(&s->sni_w_ctx, wildp);
2520 else
2521 break;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002522 for (n = node; n; n = ebmb_next_dup(n)) {
Emmanuel Hocdet3777e3a2019-11-06 16:05:34 +01002523 /* lookup a not neg filter */
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002524 if (!container_of(n, struct sni_ctx, name)->neg) {
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002525 switch(container_of(n, struct sni_ctx, name)->kinfo.sig) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002526 case TLSEXT_signature_ecdsa:
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002527 if (!node_ecdsa)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002528 node_ecdsa = n;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002529 break;
2530 case TLSEXT_signature_rsa:
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002531 if (!node_rsa)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002532 node_rsa = n;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002533 break;
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002534 default: /* TLSEXT_signature_anonymous|dsa */
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002535 if (!node_anonymous)
2536 node_anonymous = n;
2537 break;
2538 }
2539 }
2540 }
Emmanuel Hocdet3777e3a2019-11-06 16:05:34 +01002541 /* select by key_signature priority order */
2542 node = (has_ecdsa_sig && node_ecdsa) ? node_ecdsa
2543 : ((has_rsa_sig && node_rsa) ? node_rsa
2544 : (node_anonymous ? node_anonymous
2545 : (node_ecdsa ? node_ecdsa /* no ecdsa signature case (< TLSv1.2) */
2546 : node_rsa /* no rsa signature case (far far away) */
2547 )));
2548 if (node) {
2549 /* switch ctx */
2550 struct ssl_bind_conf *conf = container_of(node, struct sni_ctx, name)->conf;
2551 ssl_sock_switchctx_set(ssl, container_of(node, struct sni_ctx, name)->ctx);
Olivier Houchard35a63cc2017-11-02 19:04:38 +01002552 if (conf) {
2553 methodVersions[conf->ssl_methods.min].ssl_set_version(ssl, SET_MIN);
2554 methodVersions[conf->ssl_methods.max].ssl_set_version(ssl, SET_MAX);
2555 if (conf->early_data)
2556 allow_early = 1;
2557 }
William Lallemand02010472019-10-18 11:02:19 +02002558 HA_RWLOCK_RDUNLOCK(SNI_LOCK, &s->sni_lock);
Olivier Houchard35a63cc2017-11-02 19:04:38 +01002559 goto allow_early;
Emmanuel Hocdet3777e3a2019-11-06 16:05:34 +01002560 }
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002561 }
William Lallemand150bfa82019-09-19 17:12:49 +02002562
William Lallemand02010472019-10-18 11:02:19 +02002563 HA_RWLOCK_RDUNLOCK(SNI_LOCK, &s->sni_lock);
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002564#if (!defined SSL_NO_GENERATE_CERTIFICATES)
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002565 if (s->generate_certs && ssl_sock_generate_certificate(trash.area, s, ssl)) {
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002566 /* switch ctx done in ssl_sock_generate_certificate */
Olivier Houchardc2aae742017-09-22 18:26:28 +02002567 goto allow_early;
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002568 }
2569#endif
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002570 if (!s->strict_sni) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002571 /* no certificate match, is the default_ctx */
William Lallemand21724f02019-11-04 17:56:13 +01002572 HA_RWLOCK_RDLOCK(SNI_LOCK, &s->sni_lock);
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002573 ssl_sock_switchctx_set(ssl, s->default_ctx);
William Lallemand21724f02019-11-04 17:56:13 +01002574 HA_RWLOCK_RDUNLOCK(SNI_LOCK, &s->sni_lock);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002575 }
Olivier Houchardc2aae742017-09-22 18:26:28 +02002576allow_early:
2577#ifdef OPENSSL_IS_BORINGSSL
2578 if (allow_early)
2579 SSL_set_early_data_enabled(ssl, 1);
2580#else
2581 if (!allow_early)
2582 SSL_set_max_early_data(ssl, 0);
2583#endif
2584 return 1;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002585 abort:
2586 /* abort handshake (was SSL_TLSEXT_ERR_ALERT_FATAL) */
2587 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002588#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002589 return ssl_select_cert_error;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002590#else
2591 *al = SSL_AD_UNRECOGNIZED_NAME;
2592 return 0;
2593#endif
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002594}
2595
2596#else /* OPENSSL_IS_BORINGSSL */
2597
Emeric Brunfc0421f2012-09-07 17:30:07 +02002598/* Sets the SSL ctx of <ssl> to match the advertised server name. Returns a
2599 * warning when no match is found, which implies the default (first) cert
2600 * will keep being used.
2601 */
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002602static int ssl_sock_switchctx_cbk(SSL *ssl, int *al, void *priv)
Emeric Brunfc0421f2012-09-07 17:30:07 +02002603{
2604 const char *servername;
2605 const char *wildp = NULL;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002606 struct ebmb_node *node, *n;
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002607 struct bind_conf *s = priv;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002608 int i;
2609 (void)al; /* shut gcc stupid warning */
2610
2611 servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
Emmanuel Hocdet65623372013-01-24 17:17:15 +01002612 if (!servername) {
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002613#if (!defined SSL_NO_GENERATE_CERTIFICATES)
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002614 if (s->generate_certs && ssl_sock_generate_certificate_from_conn(s, ssl))
2615 return SSL_TLSEXT_ERR_OK;
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002616#endif
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002617 if (s->strict_sni)
2618 return SSL_TLSEXT_ERR_ALERT_FATAL;
William Lallemand21724f02019-11-04 17:56:13 +01002619 HA_RWLOCK_RDLOCK(SNI_LOCK, &s->sni_lock);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002620 ssl_sock_switchctx_set(ssl, s->default_ctx);
William Lallemand21724f02019-11-04 17:56:13 +01002621 HA_RWLOCK_RDUNLOCK(SNI_LOCK, &s->sni_lock);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002622 return SSL_TLSEXT_ERR_NOACK;
Emmanuel Hocdet65623372013-01-24 17:17:15 +01002623 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02002624
Willy Tarreau19d14ef2012-10-29 16:51:55 +01002625 for (i = 0; i < trash.size; i++) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02002626 if (!servername[i])
2627 break;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002628 trash.area[i] = tolower(servername[i]);
2629 if (!wildp && (trash.area[i] == '.'))
2630 wildp = &trash.area[i];
Emeric Brunfc0421f2012-09-07 17:30:07 +02002631 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002632 trash.area[i] = 0;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002633
William Lallemand150bfa82019-09-19 17:12:49 +02002634 HA_RWLOCK_RDLOCK(SNI_LOCK, &s->sni_lock);
Emmanuel Hocdetc5fdf0f2019-11-04 15:49:46 +01002635 node = NULL;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002636 /* lookup in full qualified names */
Emmanuel Hocdetc5fdf0f2019-11-04 15:49:46 +01002637 for (n = ebst_lookup(&s->sni_ctx, trash.area); n; n = ebmb_next_dup(n)) {
2638 /* lookup a not neg filter */
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002639 if (!container_of(n, struct sni_ctx, name)->neg) {
2640 node = n;
2641 break;
Emmanuel Hocdet65623372013-01-24 17:17:15 +01002642 }
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002643 }
2644 if (!node && wildp) {
2645 /* lookup in wildcards names */
Emmanuel Hocdetc5fdf0f2019-11-04 15:49:46 +01002646 for (n = ebst_lookup(&s->sni_w_ctx, wildp); n; n = ebmb_next_dup(n)) {
2647 /* lookup a not neg filter */
2648 if (!container_of(n, struct sni_ctx, name)->neg) {
2649 node = n;
2650 break;
2651 }
2652 }
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002653 }
Emmanuel Hocdetc5fdf0f2019-11-04 15:49:46 +01002654 if (!node) {
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002655#if (!defined SSL_NO_GENERATE_CERTIFICATES)
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002656 if (s->generate_certs && ssl_sock_generate_certificate(servername, s, ssl)) {
2657 /* switch ctx done in ssl_sock_generate_certificate */
William Lallemand150bfa82019-09-19 17:12:49 +02002658 HA_RWLOCK_RDUNLOCK(SNI_LOCK, &s->sni_lock);
Christopher Faulet31af49d2015-06-09 17:29:50 +02002659 return SSL_TLSEXT_ERR_OK;
2660 }
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002661#endif
William Lallemand21724f02019-11-04 17:56:13 +01002662 if (s->strict_sni) {
2663 HA_RWLOCK_RDUNLOCK(SNI_LOCK, &s->sni_lock);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002664 return SSL_TLSEXT_ERR_ALERT_FATAL;
William Lallemand21724f02019-11-04 17:56:13 +01002665 }
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002666 ssl_sock_switchctx_set(ssl, s->default_ctx);
William Lallemand21724f02019-11-04 17:56:13 +01002667 HA_RWLOCK_RDUNLOCK(SNI_LOCK, &s->sni_lock);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002668 return SSL_TLSEXT_ERR_OK;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002669 }
2670
2671 /* switch ctx */
Emmanuel Hocdet530141f2017-03-01 18:54:56 +01002672 ssl_sock_switchctx_set(ssl, container_of(node, struct sni_ctx, name)->ctx);
William Lallemand150bfa82019-09-19 17:12:49 +02002673 HA_RWLOCK_RDUNLOCK(SNI_LOCK, &s->sni_lock);
Emeric Brunfc0421f2012-09-07 17:30:07 +02002674 return SSL_TLSEXT_ERR_OK;
2675}
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002676#endif /* (!) OPENSSL_IS_BORINGSSL */
Emeric Brunfc0421f2012-09-07 17:30:07 +02002677#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
2678
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002679#ifndef OPENSSL_NO_DH
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002680
2681static DH * ssl_get_dh_1024(void)
2682{
Remi Gacogned3a341a2015-05-29 16:26:17 +02002683 static unsigned char dh1024_p[]={
2684 0xFA,0xF9,0x2A,0x22,0x2A,0xA7,0x7F,0xE1,0x67,0x4E,0x53,0xF7,
2685 0x56,0x13,0xC3,0xB1,0xE3,0x29,0x6B,0x66,0x31,0x6A,0x7F,0xB3,
2686 0xC2,0x68,0x6B,0xCB,0x1D,0x57,0x39,0x1D,0x1F,0xFF,0x1C,0xC9,
2687 0xA6,0xA4,0x98,0x82,0x31,0x5D,0x25,0xFF,0x8A,0xE0,0x73,0x96,
2688 0x81,0xC8,0x83,0x79,0xC1,0x5A,0x04,0xF8,0x37,0x0D,0xA8,0x3D,
2689 0xAE,0x74,0xBC,0xDB,0xB6,0xA4,0x75,0xD9,0x71,0x8A,0xA0,0x17,
2690 0x9E,0x2D,0xC8,0xA8,0xDF,0x2C,0x5F,0x82,0x95,0xF8,0x92,0x9B,
2691 0xA7,0x33,0x5F,0x89,0x71,0xC8,0x2D,0x6B,0x18,0x86,0xC4,0x94,
2692 0x22,0xA5,0x52,0x8D,0xF6,0xF6,0xD2,0x37,0x92,0x0F,0xA5,0xCC,
2693 0xDB,0x7B,0x1D,0x3D,0xA1,0x31,0xB7,0x80,0x8F,0x0B,0x67,0x5E,
2694 0x36,0xA5,0x60,0x0C,0xF1,0x95,0x33,0x8B,
2695 };
2696 static unsigned char dh1024_g[]={
2697 0x02,
2698 };
2699
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002700 BIGNUM *p;
2701 BIGNUM *g;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002702 DH *dh = DH_new();
2703 if (dh) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002704 p = BN_bin2bn(dh1024_p, sizeof dh1024_p, NULL);
2705 g = BN_bin2bn(dh1024_g, sizeof dh1024_g, NULL);
Remi Gacogned3a341a2015-05-29 16:26:17 +02002706
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002707 if (!p || !g) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002708 DH_free(dh);
2709 dh = NULL;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002710 } else {
2711 DH_set0_pqg(dh, p, NULL, g);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002712 }
2713 }
2714 return dh;
2715}
2716
2717static DH *ssl_get_dh_2048(void)
2718{
Remi Gacogned3a341a2015-05-29 16:26:17 +02002719 static unsigned char dh2048_p[]={
2720 0xEC,0x86,0xF8,0x70,0xA0,0x33,0x16,0xEC,0x05,0x1A,0x73,0x59,
2721 0xCD,0x1F,0x8B,0xF8,0x29,0xE4,0xD2,0xCF,0x52,0xDD,0xC2,0x24,
2722 0x8D,0xB5,0x38,0x9A,0xFB,0x5C,0xA4,0xE4,0xB2,0xDA,0xCE,0x66,
2723 0x50,0x74,0xA6,0x85,0x4D,0x4B,0x1D,0x30,0xB8,0x2B,0xF3,0x10,
2724 0xE9,0xA7,0x2D,0x05,0x71,0xE7,0x81,0xDF,0x8B,0x59,0x52,0x3B,
2725 0x5F,0x43,0x0B,0x68,0xF1,0xDB,0x07,0xBE,0x08,0x6B,0x1B,0x23,
2726 0xEE,0x4D,0xCC,0x9E,0x0E,0x43,0xA0,0x1E,0xDF,0x43,0x8C,0xEC,
2727 0xBE,0xBE,0x90,0xB4,0x51,0x54,0xB9,0x2F,0x7B,0x64,0x76,0x4E,
2728 0x5D,0xD4,0x2E,0xAE,0xC2,0x9E,0xAE,0x51,0x43,0x59,0xC7,0x77,
2729 0x9C,0x50,0x3C,0x0E,0xED,0x73,0x04,0x5F,0xF1,0x4C,0x76,0x2A,
2730 0xD8,0xF8,0xCF,0xFC,0x34,0x40,0xD1,0xB4,0x42,0x61,0x84,0x66,
2731 0x42,0x39,0x04,0xF8,0x68,0xB2,0x62,0xD7,0x55,0xED,0x1B,0x74,
2732 0x75,0x91,0xE0,0xC5,0x69,0xC1,0x31,0x5C,0xDB,0x7B,0x44,0x2E,
2733 0xCE,0x84,0x58,0x0D,0x1E,0x66,0x0C,0xC8,0x44,0x9E,0xFD,0x40,
2734 0x08,0x67,0x5D,0xFB,0xA7,0x76,0x8F,0x00,0x11,0x87,0xE9,0x93,
2735 0xF9,0x7D,0xC4,0xBC,0x74,0x55,0x20,0xD4,0x4A,0x41,0x2F,0x43,
2736 0x42,0x1A,0xC1,0xF2,0x97,0x17,0x49,0x27,0x37,0x6B,0x2F,0x88,
2737 0x7E,0x1C,0xA0,0xA1,0x89,0x92,0x27,0xD9,0x56,0x5A,0x71,0xC1,
2738 0x56,0x37,0x7E,0x3A,0x9D,0x05,0xE7,0xEE,0x5D,0x8F,0x82,0x17,
2739 0xBC,0xE9,0xC2,0x93,0x30,0x82,0xF9,0xF4,0xC9,0xAE,0x49,0xDB,
2740 0xD0,0x54,0xB4,0xD9,0x75,0x4D,0xFA,0x06,0xB8,0xD6,0x38,0x41,
2741 0xB7,0x1F,0x77,0xF3,
2742 };
2743 static unsigned char dh2048_g[]={
2744 0x02,
2745 };
2746
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002747 BIGNUM *p;
2748 BIGNUM *g;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002749 DH *dh = DH_new();
2750 if (dh) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002751 p = BN_bin2bn(dh2048_p, sizeof dh2048_p, NULL);
2752 g = BN_bin2bn(dh2048_g, sizeof dh2048_g, NULL);
Remi Gacogned3a341a2015-05-29 16:26:17 +02002753
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002754 if (!p || !g) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002755 DH_free(dh);
2756 dh = NULL;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002757 } else {
2758 DH_set0_pqg(dh, p, NULL, g);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002759 }
2760 }
2761 return dh;
2762}
2763
2764static DH *ssl_get_dh_4096(void)
2765{
Remi Gacogned3a341a2015-05-29 16:26:17 +02002766 static unsigned char dh4096_p[]={
2767 0xDE,0x16,0x94,0xCD,0x99,0x58,0x07,0xF1,0xF7,0x32,0x96,0x11,
2768 0x04,0x82,0xD4,0x84,0x72,0x80,0x99,0x06,0xCA,0xF0,0xA3,0x68,
2769 0x07,0xCE,0x64,0x50,0xE7,0x74,0x45,0x20,0x80,0x5E,0x4D,0xAD,
2770 0xA5,0xB6,0xED,0xFA,0x80,0x6C,0x3B,0x35,0xC4,0x9A,0x14,0x6B,
2771 0x32,0xBB,0xFD,0x1F,0x17,0x8E,0xB7,0x1F,0xD6,0xFA,0x3F,0x7B,
2772 0xEE,0x16,0xA5,0x62,0x33,0x0D,0xED,0xBC,0x4E,0x58,0xE5,0x47,
2773 0x4D,0xE9,0xAB,0x8E,0x38,0xD3,0x6E,0x90,0x57,0xE3,0x22,0x15,
2774 0x33,0xBD,0xF6,0x43,0x45,0xB5,0x10,0x0A,0xBE,0x2C,0xB4,0x35,
2775 0xB8,0x53,0x8D,0xAD,0xFB,0xA7,0x1F,0x85,0x58,0x41,0x7A,0x79,
2776 0x20,0x68,0xB3,0xE1,0x3D,0x08,0x76,0xBF,0x86,0x0D,0x49,0xE3,
2777 0x82,0x71,0x8C,0xB4,0x8D,0x81,0x84,0xD4,0xE7,0xBE,0x91,0xDC,
2778 0x26,0x39,0x48,0x0F,0x35,0xC4,0xCA,0x65,0xE3,0x40,0x93,0x52,
2779 0x76,0x58,0x7D,0xDD,0x51,0x75,0xDC,0x69,0x61,0xBF,0x47,0x2C,
2780 0x16,0x68,0x2D,0xC9,0x29,0xD3,0xE6,0xC0,0x99,0x48,0xA0,0x9A,
2781 0xC8,0x78,0xC0,0x6D,0x81,0x67,0x12,0x61,0x3F,0x71,0xBA,0x41,
2782 0x1F,0x6C,0x89,0x44,0x03,0xBA,0x3B,0x39,0x60,0xAA,0x28,0x55,
2783 0x59,0xAE,0xB8,0xFA,0xCB,0x6F,0xA5,0x1A,0xF7,0x2B,0xDD,0x52,
2784 0x8A,0x8B,0xE2,0x71,0xA6,0x5E,0x7E,0xD8,0x2E,0x18,0xE0,0x66,
2785 0xDF,0xDD,0x22,0x21,0x99,0x52,0x73,0xA6,0x33,0x20,0x65,0x0E,
2786 0x53,0xE7,0x6B,0x9B,0xC5,0xA3,0x2F,0x97,0x65,0x76,0xD3,0x47,
2787 0x23,0x77,0x12,0xB6,0x11,0x7B,0x24,0xED,0xF1,0xEF,0xC0,0xE2,
2788 0xA3,0x7E,0x67,0x05,0x3E,0x96,0x4D,0x45,0xC2,0x18,0xD1,0x73,
2789 0x9E,0x07,0xF3,0x81,0x6E,0x52,0x63,0xF6,0x20,0x76,0xB9,0x13,
2790 0xD2,0x65,0x30,0x18,0x16,0x09,0x16,0x9E,0x8F,0xF1,0xD2,0x10,
2791 0x5A,0xD3,0xD4,0xAF,0x16,0x61,0xDA,0x55,0x2E,0x18,0x5E,0x14,
2792 0x08,0x54,0x2E,0x2A,0x25,0xA2,0x1A,0x9B,0x8B,0x32,0xA9,0xFD,
2793 0xC2,0x48,0x96,0xE1,0x80,0xCA,0xE9,0x22,0x17,0xBB,0xCE,0x3E,
2794 0x9E,0xED,0xC7,0xF1,0x1F,0xEC,0x17,0x21,0xDC,0x7B,0x82,0x48,
2795 0x8E,0xBB,0x4B,0x9D,0x5B,0x04,0x04,0xDA,0xDB,0x39,0xDF,0x01,
2796 0x40,0xC3,0xAA,0x26,0x23,0x89,0x75,0xC6,0x0B,0xD0,0xA2,0x60,
2797 0x6A,0xF1,0xCC,0x65,0x18,0x98,0x1B,0x52,0xD2,0x74,0x61,0xCC,
2798 0xBD,0x60,0xAE,0xA3,0xA0,0x66,0x6A,0x16,0x34,0x92,0x3F,0x41,
2799 0x40,0x31,0x29,0xC0,0x2C,0x63,0xB2,0x07,0x8D,0xEB,0x94,0xB8,
2800 0xE8,0x47,0x92,0x52,0x93,0x6A,0x1B,0x7E,0x1A,0x61,0xB3,0x1B,
2801 0xF0,0xD6,0x72,0x9B,0xF1,0xB0,0xAF,0xBF,0x3E,0x65,0xEF,0x23,
2802 0x1D,0x6F,0xFF,0x70,0xCD,0x8A,0x4C,0x8A,0xA0,0x72,0x9D,0xBE,
2803 0xD4,0xBB,0x24,0x47,0x4A,0x68,0xB5,0xF5,0xC6,0xD5,0x7A,0xCD,
2804 0xCA,0x06,0x41,0x07,0xAD,0xC2,0x1E,0xE6,0x54,0xA7,0xAD,0x03,
2805 0xD9,0x12,0xC1,0x9C,0x13,0xB1,0xC9,0x0A,0x43,0x8E,0x1E,0x08,
2806 0xCE,0x50,0x82,0x73,0x5F,0xA7,0x55,0x1D,0xD9,0x59,0xAC,0xB5,
2807 0xEA,0x02,0x7F,0x6C,0x5B,0x74,0x96,0x98,0x67,0x24,0xA3,0x0F,
2808 0x15,0xFC,0xA9,0x7D,0x3E,0x67,0xD1,0x70,0xF8,0x97,0xF3,0x67,
2809 0xC5,0x8C,0x88,0x44,0x08,0x02,0xC7,0x2B,
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002810 };
Remi Gacogned3a341a2015-05-29 16:26:17 +02002811 static unsigned char dh4096_g[]={
2812 0x02,
2813 };
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002814
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002815 BIGNUM *p;
2816 BIGNUM *g;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002817 DH *dh = DH_new();
2818 if (dh) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002819 p = BN_bin2bn(dh4096_p, sizeof dh4096_p, NULL);
2820 g = BN_bin2bn(dh4096_g, sizeof dh4096_g, NULL);
Remi Gacogned3a341a2015-05-29 16:26:17 +02002821
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002822 if (!p || !g) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002823 DH_free(dh);
2824 dh = NULL;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002825 } else {
2826 DH_set0_pqg(dh, p, NULL, g);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002827 }
2828 }
2829 return dh;
2830}
2831
2832/* Returns Diffie-Hellman parameters matching the private key length
Willy Tarreauef934602016-12-22 23:12:01 +01002833 but not exceeding global_ssl.default_dh_param */
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002834static DH *ssl_get_tmp_dh(SSL *ssl, int export, int keylen)
2835{
2836 DH *dh = NULL;
2837 EVP_PKEY *pkey = SSL_get_privatekey(ssl);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002838 int type;
2839
2840 type = pkey ? EVP_PKEY_base_id(pkey) : EVP_PKEY_NONE;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002841
2842 /* The keylen supplied by OpenSSL can only be 512 or 1024.
2843 See ssl3_send_server_key_exchange() in ssl/s3_srvr.c
2844 */
2845 if (type == EVP_PKEY_RSA || type == EVP_PKEY_DSA) {
2846 keylen = EVP_PKEY_bits(pkey);
2847 }
2848
Willy Tarreauef934602016-12-22 23:12:01 +01002849 if (keylen > global_ssl.default_dh_param) {
2850 keylen = global_ssl.default_dh_param;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002851 }
2852
Remi Gacogned3a341a2015-05-29 16:26:17 +02002853 if (keylen >= 4096) {
Remi Gacogne8de54152014-07-15 11:36:40 +02002854 dh = local_dh_4096;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002855 }
2856 else if (keylen >= 2048) {
Remi Gacogne8de54152014-07-15 11:36:40 +02002857 dh = local_dh_2048;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002858 }
2859 else {
Remi Gacogne8de54152014-07-15 11:36:40 +02002860 dh = local_dh_1024;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002861 }
2862
2863 return dh;
2864}
2865
Remi Gacogne47783ef2015-05-29 15:53:22 +02002866static DH * ssl_sock_get_dh_from_file(const char *filename)
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002867{
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002868 DH *dh = NULL;
Remi Gacogne47783ef2015-05-29 15:53:22 +02002869 BIO *in = BIO_new(BIO_s_file());
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002870
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002871 if (in == NULL)
2872 goto end;
2873
Remi Gacogne47783ef2015-05-29 15:53:22 +02002874 if (BIO_read_filename(in, filename) <= 0)
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002875 goto end;
2876
Remi Gacogne47783ef2015-05-29 15:53:22 +02002877 dh = PEM_read_bio_DHparams(in, NULL, NULL, NULL);
2878
2879end:
2880 if (in)
2881 BIO_free(in);
2882
Emeric Brune1b4ed42018-08-16 15:14:12 +02002883 ERR_clear_error();
2884
Remi Gacogne47783ef2015-05-29 15:53:22 +02002885 return dh;
2886}
2887
2888int ssl_sock_load_global_dh_param_from_file(const char *filename)
2889{
2890 global_dh = ssl_sock_get_dh_from_file(filename);
2891
2892 if (global_dh) {
2893 return 0;
2894 }
2895
2896 return -1;
2897}
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002898#endif
2899
William Lallemand9117de92019-10-04 00:29:42 +02002900/* Alloc and init a ckch_inst */
2901static struct ckch_inst *ckch_inst_new()
2902{
2903 struct ckch_inst *ckch_inst;
2904
2905 ckch_inst = calloc(1, sizeof *ckch_inst);
2906 if (ckch_inst)
2907 LIST_INIT(&ckch_inst->sni_ctx);
2908
2909 return ckch_inst;
2910}
2911
2912
2913/* This function allocates a sni_ctx and adds it to the ckch_inst */
William Lallemand1d29c742019-10-04 00:53:29 +02002914static int ckch_inst_add_cert_sni(SSL_CTX *ctx, struct ckch_inst *ckch_inst,
William Lallemand9117de92019-10-04 00:29:42 +02002915 struct bind_conf *s, struct ssl_bind_conf *conf,
2916 struct pkey_info kinfo, char *name, int order)
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002917{
2918 struct sni_ctx *sc;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002919 int wild = 0, neg = 0;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002920
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002921 if (*name == '!') {
2922 neg = 1;
2923 name++;
2924 }
2925 if (*name == '*') {
2926 wild = 1;
2927 name++;
2928 }
2929 /* !* filter is a nop */
2930 if (neg && wild)
2931 return order;
2932 if (*name) {
2933 int j, len;
2934 len = strlen(name);
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002935 for (j = 0; j < len && j < trash.size; j++)
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002936 trash.area[j] = tolower(name[j]);
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002937 if (j >= trash.size)
William Lallemandfe49bb32019-10-03 23:46:33 +02002938 return -1;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002939 trash.area[j] = 0;
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002940
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002941 sc = malloc(sizeof(struct sni_ctx) + len + 1);
Thierry FOURNIER / OZON.IO7a3bd3b2016-10-06 10:35:29 +02002942 if (!sc)
William Lallemandfe49bb32019-10-03 23:46:33 +02002943 return -1;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002944 memcpy(sc->name.key, trash.area, len + 1);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002945 sc->ctx = ctx;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01002946 sc->conf = conf;
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002947 sc->kinfo = kinfo;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002948 sc->order = order++;
2949 sc->neg = neg;
William Lallemand1d29c742019-10-04 00:53:29 +02002950 sc->wild = wild;
2951 sc->name.node.leaf_p = NULL;
William Lallemand1d29c742019-10-04 00:53:29 +02002952 LIST_ADDQ(&ckch_inst->sni_ctx, &sc->by_ckch_inst);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002953 }
2954 return order;
2955}
2956
William Lallemand6af03992019-07-23 15:00:54 +02002957/*
William Lallemand1d29c742019-10-04 00:53:29 +02002958 * Insert the sni_ctxs that are listed in the ckch_inst, in the bind_conf's sni_ctx tree
2959 * This function can't return an error.
2960 *
2961 * *CAUTION*: The caller must lock the sni tree if called in multithreading mode
2962 */
2963static void ssl_sock_load_cert_sni(struct ckch_inst *ckch_inst, struct bind_conf *bind_conf)
2964{
2965
2966 struct sni_ctx *sc0, *sc0b, *sc1;
2967 struct ebmb_node *node;
William Lallemand21724f02019-11-04 17:56:13 +01002968 int def = 0;
William Lallemand1d29c742019-10-04 00:53:29 +02002969
2970 list_for_each_entry_safe(sc0, sc0b, &ckch_inst->sni_ctx, by_ckch_inst) {
2971
2972 /* ignore if sc0 was already inserted in a tree */
2973 if (sc0->name.node.leaf_p)
2974 continue;
2975
2976 /* Check for duplicates. */
2977 if (sc0->wild)
2978 node = ebst_lookup(&bind_conf->sni_w_ctx, (char *)sc0->name.key);
2979 else
2980 node = ebst_lookup(&bind_conf->sni_ctx, (char *)sc0->name.key);
2981
2982 for (; node; node = ebmb_next_dup(node)) {
2983 sc1 = ebmb_entry(node, struct sni_ctx, name);
2984 if (sc1->ctx == sc0->ctx && sc1->conf == sc0->conf
2985 && sc1->neg == sc0->neg && sc1->wild == sc0->wild) {
2986 /* it's a duplicate, we should remove and free it */
2987 LIST_DEL(&sc0->by_ckch_inst);
2988 free(sc0);
2989 sc0 = NULL;
William Lallemande15029b2019-10-14 10:46:58 +02002990 break;
William Lallemand1d29c742019-10-04 00:53:29 +02002991 }
2992 }
2993
2994 /* if duplicate, ignore the insertion */
2995 if (!sc0)
2996 continue;
2997
2998 if (sc0->wild)
2999 ebst_insert(&bind_conf->sni_w_ctx, &sc0->name);
3000 else
3001 ebst_insert(&bind_conf->sni_ctx, &sc0->name);
William Lallemand21724f02019-11-04 17:56:13 +01003002
3003 /* replace the default_ctx if required with the first ctx */
3004 if (ckch_inst->is_default && !def) {
3005 /* we don't need to free the default_ctx because the refcount was not incremented */
3006 bind_conf->default_ctx = sc0->ctx;
3007 def = 1;
3008 }
William Lallemand1d29c742019-10-04 00:53:29 +02003009 }
3010}
3011
3012/*
William Lallemande3af8fb2019-10-08 11:36:53 +02003013 * tree used to store the ckchs ordered by filename/bundle name
William Lallemand6af03992019-07-23 15:00:54 +02003014 */
William Lallemande3af8fb2019-10-08 11:36:53 +02003015struct eb_root ckchs_tree = EB_ROOT_UNIQUE;
William Lallemand6af03992019-07-23 15:00:54 +02003016
William Lallemandfa892222019-07-23 16:06:08 +02003017
Emeric Brun7a883362019-10-17 13:27:40 +02003018/* Loads Diffie-Hellman parameter from a ckchs to an SSL_CTX.
3019 * If there is no DH paramater availaible in the ckchs, the global
3020 * DH parameter is loaded into the SSL_CTX and if there is no
3021 * DH parameter available in ckchs nor in global, the default
3022 * DH parameters are applied on the SSL_CTX.
3023 * Returns a bitfield containing the flags:
3024 * ERR_FATAL in any fatal error case
3025 * ERR_ALERT if a reason of the error is availabine in err
3026 * ERR_WARN if a warning is available into err
3027 * The value 0 means there is no error nor warning and
3028 * the operation succeed.
3029 */
William Lallemandfa892222019-07-23 16:06:08 +02003030#ifndef OPENSSL_NO_DH
Emeric Brun7a883362019-10-17 13:27:40 +02003031static int ssl_sock_load_dh_params(SSL_CTX *ctx, const struct cert_key_and_chain *ckch,
3032 const char *path, char **err)
William Lallemandfa892222019-07-23 16:06:08 +02003033{
Emeric Brun7a883362019-10-17 13:27:40 +02003034 int ret = 0;
William Lallemandfa892222019-07-23 16:06:08 +02003035 DH *dh = NULL;
3036
William Lallemanda8c73742019-07-31 18:31:34 +02003037 if (ckch && ckch->dh) {
William Lallemandfa892222019-07-23 16:06:08 +02003038 dh = ckch->dh;
Emeric Bruna9363eb2019-10-17 14:53:03 +02003039 if (!SSL_CTX_set_tmp_dh(ctx, dh)) {
3040 memprintf(err, "%sunable to load the DH parameter specified in '%s'",
3041 err && *err ? *err : "", path);
3042#if defined(SSL_CTX_set_dh_auto)
3043 SSL_CTX_set_dh_auto(ctx, 1);
3044 memprintf(err, "%s, SSL library will use an automatically generated DH parameter.\n",
3045 err && *err ? *err : "");
3046#else
3047 memprintf(err, "%s, DH ciphers won't be available.\n",
3048 err && *err ? *err : "");
3049#endif
3050 ret |= ERR_WARN;
3051 goto end;
3052 }
William Lallemandfa892222019-07-23 16:06:08 +02003053
3054 if (ssl_dh_ptr_index >= 0) {
3055 /* store a pointer to the DH params to avoid complaining about
3056 ssl-default-dh-param not being set for this SSL_CTX */
3057 SSL_CTX_set_ex_data(ctx, ssl_dh_ptr_index, dh);
3058 }
3059 }
3060 else if (global_dh) {
Emeric Bruna9363eb2019-10-17 14:53:03 +02003061 if (!SSL_CTX_set_tmp_dh(ctx, global_dh)) {
3062 memprintf(err, "%sunable to use the global DH parameter for certificate '%s'",
3063 err && *err ? *err : "", path);
3064#if defined(SSL_CTX_set_dh_auto)
3065 SSL_CTX_set_dh_auto(ctx, 1);
3066 memprintf(err, "%s, SSL library will use an automatically generated DH parameter.\n",
3067 err && *err ? *err : "");
3068#else
3069 memprintf(err, "%s, DH ciphers won't be available.\n",
3070 err && *err ? *err : "");
3071#endif
3072 ret |= ERR_WARN;
3073 goto end;
3074 }
William Lallemandfa892222019-07-23 16:06:08 +02003075 }
3076 else {
3077 /* Clear openssl global errors stack */
3078 ERR_clear_error();
3079
3080 if (global_ssl.default_dh_param <= 1024) {
3081 /* we are limited to DH parameter of 1024 bits anyway */
3082 if (local_dh_1024 == NULL)
3083 local_dh_1024 = ssl_get_dh_1024();
3084
Emeric Brun7a883362019-10-17 13:27:40 +02003085 if (local_dh_1024 == NULL) {
3086 memprintf(err, "%sunable to load default 1024 bits DH parameter for certificate '%s'.\n",
3087 err && *err ? *err : "", path);
3088 ret |= ERR_ALERT | ERR_FATAL;
William Lallemandfa892222019-07-23 16:06:08 +02003089 goto end;
Emeric Brun7a883362019-10-17 13:27:40 +02003090 }
William Lallemandfa892222019-07-23 16:06:08 +02003091
Emeric Bruna9363eb2019-10-17 14:53:03 +02003092 if (!SSL_CTX_set_tmp_dh(ctx, local_dh_1024)) {
3093 memprintf(err, "%sunable to load default 1024 bits DH parameter for certificate '%s'.\n",
3094 err && *err ? *err : "", path);
3095#if defined(SSL_CTX_set_dh_auto)
3096 SSL_CTX_set_dh_auto(ctx, 1);
3097 memprintf(err, "%s, SSL library will use an automatically generated DH parameter.\n",
3098 err && *err ? *err : "");
3099#else
3100 memprintf(err, "%s, DH ciphers won't be available.\n",
3101 err && *err ? *err : "");
3102#endif
3103 ret |= ERR_WARN;
3104 goto end;
3105 }
William Lallemandfa892222019-07-23 16:06:08 +02003106 }
3107 else {
3108 SSL_CTX_set_tmp_dh_callback(ctx, ssl_get_tmp_dh);
3109 }
William Lallemandfa892222019-07-23 16:06:08 +02003110 }
3111
3112end:
William Lallemand4dd145a2020-02-05 11:46:33 +01003113 ERR_clear_error();
William Lallemandfa892222019-07-23 16:06:08 +02003114 return ret;
3115}
3116#endif
yanbzhu08ce6ab2015-12-02 13:01:29 -05003117
yanbzhu488a4d22015-12-01 15:16:07 -05003118/* Frees the contents of a cert_key_and_chain
3119 */
3120static void ssl_sock_free_cert_key_and_chain_contents(struct cert_key_and_chain *ckch)
3121{
yanbzhu488a4d22015-12-01 15:16:07 -05003122 if (!ckch)
3123 return;
3124
3125 /* Free the certificate and set pointer to NULL */
3126 if (ckch->cert)
3127 X509_free(ckch->cert);
3128 ckch->cert = NULL;
3129
3130 /* Free the key and set pointer to NULL */
3131 if (ckch->key)
3132 EVP_PKEY_free(ckch->key);
3133 ckch->key = NULL;
3134
3135 /* Free each certificate in the chain */
Emmanuel Hocdet9246f8b2018-11-30 16:00:21 +01003136 if (ckch->chain)
3137 sk_X509_pop_free(ckch->chain, X509_free);
3138 ckch->chain = NULL;
yanbzhu488a4d22015-12-01 15:16:07 -05003139
William Lallemand455af502019-10-17 18:04:45 +02003140 if (ckch->dh)
3141 DH_free(ckch->dh);
3142 ckch->dh = NULL;
3143
3144 if (ckch->sctl) {
3145 free(ckch->sctl->area);
3146 ckch->sctl->area = NULL;
3147 free(ckch->sctl);
3148 ckch->sctl = NULL;
3149 }
3150
3151 if (ckch->ocsp_response) {
3152 free(ckch->ocsp_response->area);
3153 ckch->ocsp_response->area = NULL;
3154 free(ckch->ocsp_response);
3155 ckch->ocsp_response = NULL;
3156 }
William Lallemand5c3c96f2020-01-23 11:53:13 +01003157
3158 if (ckch->ocsp_issuer)
William Lallemanddad239d2020-01-23 11:59:02 +01003159 X509_free(ckch->ocsp_issuer);
William Lallemand5c3c96f2020-01-23 11:53:13 +01003160 ckch->ocsp_issuer = NULL;
yanbzhu488a4d22015-12-01 15:16:07 -05003161}
3162
William Lallemand8d0f8932019-10-17 18:03:58 +02003163/*
3164 *
3165 * This function copy a cert_key_and_chain in memory
3166 *
3167 * It's used to try to apply changes on a ckch before committing them, because
3168 * most of the time it's not possible to revert those changes
3169 *
3170 * Return a the dst or NULL
3171 */
3172static struct cert_key_and_chain *ssl_sock_copy_cert_key_and_chain(struct cert_key_and_chain *src,
3173 struct cert_key_and_chain *dst)
3174{
3175 if (src->cert) {
3176 dst->cert = src->cert;
3177 X509_up_ref(src->cert);
3178 }
3179
3180 if (src->key) {
3181 dst->key = src->key;
3182 EVP_PKEY_up_ref(src->key);
3183 }
3184
3185 if (src->chain) {
3186 dst->chain = X509_chain_up_ref(src->chain);
3187 }
3188
3189 if (src->dh) {
3190 DH_up_ref(src->dh);
3191 dst->dh = src->dh;
3192 }
3193
3194 if (src->sctl) {
3195 struct buffer *sctl;
3196
3197 sctl = calloc(1, sizeof(*sctl));
3198 if (!chunk_dup(sctl, src->sctl)) {
3199 free(sctl);
3200 sctl = NULL;
3201 goto error;
3202 }
3203 dst->sctl = sctl;
3204 }
3205
3206 if (src->ocsp_response) {
3207 struct buffer *ocsp_response;
3208
3209 ocsp_response = calloc(1, sizeof(*ocsp_response));
3210 if (!chunk_dup(ocsp_response, src->ocsp_response)) {
3211 free(ocsp_response);
3212 ocsp_response = NULL;
3213 goto error;
3214 }
3215 dst->ocsp_response = ocsp_response;
3216 }
3217
3218 if (src->ocsp_issuer) {
3219 X509_up_ref(src->ocsp_issuer);
3220 dst->ocsp_issuer = src->ocsp_issuer;
3221 }
3222
3223 return dst;
3224
3225error:
3226
3227 /* free everything */
3228 ssl_sock_free_cert_key_and_chain_contents(dst);
3229
3230 return NULL;
3231}
3232
3233
yanbzhu488a4d22015-12-01 15:16:07 -05003234/* checks if a key and cert exists in the ckch
3235 */
William Lallemand1633e392019-09-30 12:58:13 +02003236#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
yanbzhu488a4d22015-12-01 15:16:07 -05003237static int ssl_sock_is_ckch_valid(struct cert_key_and_chain *ckch)
3238{
3239 return (ckch->cert != NULL && ckch->key != NULL);
3240}
William Lallemand1633e392019-09-30 12:58:13 +02003241#endif
yanbzhu488a4d22015-12-01 15:16:07 -05003242
William Lallemandf9568fc2019-10-16 18:27:58 +02003243/*
3244 * return 0 on success or != 0 on failure
3245 */
3246static int ssl_sock_load_issuer_file_into_ckch(const char *path, char *buf, struct cert_key_and_chain *ckch, char **err)
3247{
3248 int ret = 1;
3249 BIO *in = NULL;
3250 X509 *issuer;
3251
3252 if (buf) {
3253 /* reading from a buffer */
3254 in = BIO_new_mem_buf(buf, -1);
3255 if (in == NULL) {
3256 memprintf(err, "%sCan't allocate memory\n", err && *err ? *err : "");
3257 goto end;
3258 }
3259
3260 } else {
3261 /* reading from a file */
3262 in = BIO_new(BIO_s_file());
3263 if (in == NULL)
3264 goto end;
3265
3266 if (BIO_read_filename(in, path) <= 0)
3267 goto end;
3268 }
3269
3270 issuer = PEM_read_bio_X509_AUX(in, NULL, NULL, NULL);
3271 if (!issuer) {
3272 memprintf(err, "%s'%s' cannot be read or parsed'.\n",
Tim Duesterhus93128532019-11-23 23:45:10 +01003273 err && *err ? *err : "", path);
William Lallemandf9568fc2019-10-16 18:27:58 +02003274 goto end;
3275 }
Emmanuel Hocdeteb73dc32020-01-16 14:45:00 +01003276 /* no error, fill ckch with new context, old context must be free */
3277 if (ckch->ocsp_issuer)
3278 X509_free(ckch->ocsp_issuer);
William Lallemandf9568fc2019-10-16 18:27:58 +02003279 ckch->ocsp_issuer = issuer;
Emmanuel Hocdeteb73dc32020-01-16 14:45:00 +01003280 ret = 0;
William Lallemandf9568fc2019-10-16 18:27:58 +02003281
3282end:
3283
3284 ERR_clear_error();
3285 if (in)
3286 BIO_free(in);
3287
3288 return ret;
3289}
3290
William Lallemand96a9c972019-10-17 11:56:17 +02003291
3292/*
3293 * Try to load a PEM file from a <path> or a buffer <buf>
William Lallemand4c5adbf2020-02-24 14:23:22 +01003294 * The PEM must contain at least a Certificate,
3295 * It could contain a DH, a certificate chain and a PrivateKey.
yanbzhu488a4d22015-12-01 15:16:07 -05003296 *
William Lallemand96a9c972019-10-17 11:56:17 +02003297 * If it failed you should not attempt to use the ckch but free it.
3298 *
3299 * Return 0 on success or != 0 on failure
yanbzhu488a4d22015-12-01 15:16:07 -05003300 */
William Lallemand96a9c972019-10-17 11:56:17 +02003301static 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 -05003302{
William Lallemandf11365b2019-09-19 14:25:58 +02003303 BIO *in = NULL;
yanbzhu488a4d22015-12-01 15:16:07 -05003304 int ret = 1;
Emmanuel Hocdet83cbd3c2019-10-25 11:55:03 +02003305 X509 *ca;
William Lallemand96a9c972019-10-17 11:56:17 +02003306 X509 *cert = NULL;
3307 EVP_PKEY *key = NULL;
Emmanuel Hocdet6b5b44e2019-12-20 17:47:12 +01003308 DH *dh = NULL;
3309 STACK_OF(X509) *chain = NULL;
William Lallemand96a9c972019-10-17 11:56:17 +02003310
3311 if (buf) {
3312 /* reading from a buffer */
3313 in = BIO_new_mem_buf(buf, -1);
3314 if (in == NULL) {
3315 memprintf(err, "%sCan't allocate memory\n", err && *err ? *err : "");
3316 goto end;
3317 }
yanbzhu488a4d22015-12-01 15:16:07 -05003318
William Lallemand96a9c972019-10-17 11:56:17 +02003319 } else {
3320 /* reading from a file */
William Lallemandf11365b2019-09-19 14:25:58 +02003321 in = BIO_new(BIO_s_file());
3322 if (in == NULL)
3323 goto end;
yanbzhu488a4d22015-12-01 15:16:07 -05003324
William Lallemandf11365b2019-09-19 14:25:58 +02003325 if (BIO_read_filename(in, path) <= 0)
3326 goto end;
William Lallemandf11365b2019-09-19 14:25:58 +02003327 }
yanbzhu488a4d22015-12-01 15:16:07 -05003328
yanbzhu488a4d22015-12-01 15:16:07 -05003329 /* Read Private Key */
William Lallemand96a9c972019-10-17 11:56:17 +02003330 key = PEM_read_bio_PrivateKey(in, NULL, NULL, NULL);
William Lallemand4c5adbf2020-02-24 14:23:22 +01003331 /* no need to check for errors here, because the private key could be loaded later */
yanbzhu488a4d22015-12-01 15:16:07 -05003332
Emmanuel Hocdet54227d82019-07-30 17:04:01 +02003333#ifndef OPENSSL_NO_DH
William Lallemandfa892222019-07-23 16:06:08 +02003334 /* Seek back to beginning of file */
3335 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 }
3340
William Lallemand96a9c972019-10-17 11:56:17 +02003341 dh = PEM_read_bio_DHparams(in, NULL, NULL, NULL);
3342 /* no need to return an error there, dh is not mandatory */
Emmanuel Hocdet54227d82019-07-30 17:04:01 +02003343#endif
William Lallemandfa892222019-07-23 16:06:08 +02003344
Willy Tarreaubb137a82016-04-06 19:02:38 +02003345 /* Seek back to beginning of file */
Thierry FOURNIER / OZON.IOd44ea3f2016-10-14 00:49:21 +02003346 if (BIO_reset(in) == -1) {
3347 memprintf(err, "%san error occurred while reading the file '%s'.\n",
3348 err && *err ? *err : "", path);
3349 goto end;
3350 }
Willy Tarreaubb137a82016-04-06 19:02:38 +02003351
3352 /* Read Certificate */
William Lallemand96a9c972019-10-17 11:56:17 +02003353 cert = PEM_read_bio_X509_AUX(in, NULL, NULL, NULL);
3354 if (cert == NULL) {
Willy Tarreaubb137a82016-04-06 19:02:38 +02003355 memprintf(err, "%sunable to load certificate from file '%s'.\n",
William Lallemand96a9c972019-10-17 11:56:17 +02003356 err && *err ? *err : "", path);
Willy Tarreaubb137a82016-04-06 19:02:38 +02003357 goto end;
3358 }
3359
William Lallemand96a9c972019-10-17 11:56:17 +02003360 /* Look for a Certificate Chain */
Emmanuel Hocdet6b5b44e2019-12-20 17:47:12 +01003361 while ((ca = PEM_read_bio_X509(in, NULL, NULL, NULL))) {
3362 if (chain == NULL)
3363 chain = sk_X509_new_null();
3364 if (!sk_X509_push(chain, ca)) {
William Lallemand96a9c972019-10-17 11:56:17 +02003365 X509_free(ca);
3366 goto end;
3367 }
3368 }
Emmanuel Hocdeted17f472019-10-24 18:28:33 +02003369
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
William Lallemand246c0242019-10-11 08:59:13 +02003403 ret = 0;
3404
William Lallemand96a9c972019-10-17 11:56:17 +02003405end:
William Lallemand246c0242019-10-11 08:59:13 +02003406
3407 ERR_clear_error();
William Lallemand96a9c972019-10-17 11:56:17 +02003408 if (in)
William Lallemand246c0242019-10-11 08:59:13 +02003409 BIO_free(in);
Emmanuel Hocdet83cbd3c2019-10-25 11:55:03 +02003410 if (key)
3411 EVP_PKEY_free(key);
Emmanuel Hocdet6b5b44e2019-12-20 17:47:12 +01003412 if (dh)
3413 DH_free(dh);
Emmanuel Hocdet83cbd3c2019-10-25 11:55:03 +02003414 if (cert)
3415 X509_free(cert);
Emmanuel Hocdet6b5b44e2019-12-20 17:47:12 +01003416 if (chain)
3417 sk_X509_pop_free(chain, X509_free);
William Lallemanda17f4112019-10-10 15:16:44 +02003418
William Lallemand96a9c972019-10-17 11:56:17 +02003419 return ret;
3420}
3421
3422/*
William Lallemand4c5adbf2020-02-24 14:23:22 +01003423 * Try to load a private key file from a <path> or a buffer <buf>
3424 *
3425 * If it failed you should not attempt to use the ckch but free it.
3426 *
3427 * Return 0 on success or != 0 on failure
3428 */
3429static int ssl_sock_load_key_into_ckch(const char *path, char *buf, struct cert_key_and_chain *ckch , char **err)
3430{
3431 BIO *in = NULL;
3432 int ret = 1;
3433 EVP_PKEY *key = NULL;
3434
3435 if (buf) {
3436 /* reading from a buffer */
3437 in = BIO_new_mem_buf(buf, -1);
3438 if (in == NULL) {
3439 memprintf(err, "%sCan't allocate memory\n", err && *err ? *err : "");
3440 goto end;
3441 }
3442
3443 } else {
3444 /* reading from a file */
3445 in = BIO_new(BIO_s_file());
3446 if (in == NULL)
3447 goto end;
3448
3449 if (BIO_read_filename(in, path) <= 0)
3450 goto end;
3451 }
3452
3453 /* Read Private Key */
3454 key = PEM_read_bio_PrivateKey(in, NULL, NULL, NULL);
3455 if (key == NULL) {
3456 memprintf(err, "%sunable to load private key from file '%s'.\n",
3457 err && *err ? *err : "", path);
3458 goto end;
3459 }
3460
3461 ret = 0;
3462
3463 SWAP(ckch->key, key);
3464
3465end:
3466
3467 ERR_clear_error();
3468 if (in)
3469 BIO_free(in);
3470 if (key)
3471 EVP_PKEY_free(key);
3472
3473 return ret;
3474}
3475
3476/*
William Lallemand96a9c972019-10-17 11:56:17 +02003477 * Try to load in a ckch every files related to a ckch.
3478 * (PEM, sctl, ocsp, issuer etc.)
3479 *
3480 * This function is only used to load files during the configuration parsing,
3481 * it is not used with the CLI.
3482 *
3483 * This allows us to carry the contents of the file without having to read the
3484 * file multiple times. The caller must call
3485 * ssl_sock_free_cert_key_and_chain_contents.
3486 *
3487 * returns:
3488 * 0 on Success
3489 * 1 on SSL Failure
3490 */
3491static int ssl_sock_load_files_into_ckch(const char *path, struct cert_key_and_chain *ckch, char **err)
3492{
3493 int ret = 1;
3494
3495 /* try to load the PEM */
3496 if (ssl_sock_load_pem_into_ckch(path, NULL, ckch , err) != 0) {
3497 goto end;
3498 }
3499
William Lallemand4c5adbf2020-02-24 14:23:22 +01003500 /* try to load an external private key if it wasn't in the PEM */
3501 if ((ckch->key == NULL) && (global_ssl.extra_files & SSL_GF_KEY)) {
3502 char fp[MAXPATHLEN+1];
3503 struct stat st;
3504
3505 snprintf(fp, MAXPATHLEN+1, "%s.key", path);
3506 if (stat(fp, &st) == 0) {
3507 if (ssl_sock_load_key_into_ckch(fp, NULL, ckch, err)) {
3508 memprintf(err, "%s '%s' is present but cannot be read or parsed'.\n",
3509 err && *err ? *err : "", fp);
3510 goto end;
3511 }
3512 }
3513 }
3514
3515 if (ckch->key == NULL) {
3516 memprintf(err, "%sNo Private Key found in '%s' or '%s.key'.\n", err && *err ? *err : "", path, path);
3517 goto end;
3518 }
3519
3520 if (!X509_check_private_key(ckch->cert, ckch->key)) {
3521 memprintf(err, "%sinconsistencies between private key and certificate loaded '%s'.\n",
3522 err && *err ? *err : "", path);
3523 goto end;
3524 }
3525
William Lallemanda17f4112019-10-10 15:16:44 +02003526#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
3527 /* try to load the sctl file */
William Lallemand3af48e72020-02-03 17:15:52 +01003528 if (global_ssl.extra_files & SSL_GF_SCTL) {
William Lallemanda17f4112019-10-10 15:16:44 +02003529 char fp[MAXPATHLEN+1];
3530 struct stat st;
3531
3532 snprintf(fp, MAXPATHLEN+1, "%s.sctl", path);
3533 if (stat(fp, &st) == 0) {
William Lallemand0dfae6c2019-10-16 18:06:58 +02003534 if (ssl_sock_load_sctl_from_file(fp, NULL, ckch, err)) {
William Lallemanda17f4112019-10-10 15:16:44 +02003535 memprintf(err, "%s '%s.sctl' is present but cannot be read or parsed'.\n",
Tim Duesterhus93128532019-11-23 23:45:10 +01003536 err && *err ? *err : "", fp);
William Lallemanda17f4112019-10-10 15:16:44 +02003537 ret = 1;
3538 goto end;
3539 }
3540 }
3541 }
3542#endif
yanbzhu488a4d22015-12-01 15:16:07 -05003543
William Lallemand246c0242019-10-11 08:59:13 +02003544 /* try to load an ocsp response file */
William Lallemand3af48e72020-02-03 17:15:52 +01003545 if (global_ssl.extra_files & SSL_GF_OCSP) {
William Lallemand246c0242019-10-11 08:59:13 +02003546 char fp[MAXPATHLEN+1];
3547 struct stat st;
3548
3549 snprintf(fp, MAXPATHLEN+1, "%s.ocsp", path);
3550 if (stat(fp, &st) == 0) {
William Lallemand3b5f3602019-10-16 18:05:05 +02003551 if (ssl_sock_load_ocsp_response_from_file(fp, NULL, ckch, err)) {
William Lallemand246c0242019-10-11 08:59:13 +02003552 ret = 1;
3553 goto end;
3554 }
3555 }
3556 }
3557
Emmanuel Hocdeteaad5cc2019-10-25 12:19:00 +02003558#ifndef OPENSSL_IS_BORINGSSL /* Useless for BoringSSL */
William Lallemand3af48e72020-02-03 17:15:52 +01003559 if (ckch->ocsp_response && (global_ssl.extra_files & SSL_GF_OCSP_ISSUER)) {
William Lallemand246c0242019-10-11 08:59:13 +02003560 /* if no issuer was found, try to load an issuer from the .issuer */
Emmanuel Hocdet078156d2020-01-22 17:02:53 +01003561 if (!ckch->ocsp_issuer) {
William Lallemand246c0242019-10-11 08:59:13 +02003562 struct stat st;
3563 char fp[MAXPATHLEN+1];
3564
3565 snprintf(fp, MAXPATHLEN+1, "%s.issuer", path);
3566 if (stat(fp, &st) == 0) {
William Lallemandf9568fc2019-10-16 18:27:58 +02003567 if (ssl_sock_load_issuer_file_into_ckch(fp, NULL, ckch, err)) {
William Lallemand246c0242019-10-11 08:59:13 +02003568 ret = 1;
3569 goto end;
3570 }
3571
3572 if (X509_check_issued(ckch->ocsp_issuer, ckch->cert) != X509_V_OK) {
William Lallemand786188f2019-10-15 10:05:37 +02003573 memprintf(err, "%s '%s' is not an issuer'.\n",
Tim Duesterhus93128532019-11-23 23:45:10 +01003574 err && *err ? *err : "", fp);
William Lallemand246c0242019-10-11 08:59:13 +02003575 ret = 1;
3576 goto end;
3577 }
William Lallemand246c0242019-10-11 08:59:13 +02003578 }
3579 }
3580 }
Emmanuel Hocdeteaad5cc2019-10-25 12:19:00 +02003581#endif
William Lallemand246c0242019-10-11 08:59:13 +02003582
yanbzhu488a4d22015-12-01 15:16:07 -05003583 ret = 0;
3584
3585end:
3586
3587 ERR_clear_error();
yanbzhu488a4d22015-12-01 15:16:07 -05003588
3589 /* Something went wrong in one of the reads */
3590 if (ret != 0)
3591 ssl_sock_free_cert_key_and_chain_contents(ckch);
3592
3593 return ret;
3594}
3595
3596/* Loads the info in ckch into ctx
Emeric Bruna96b5822019-10-17 13:25:14 +02003597 * Returns a bitfield containing the flags:
3598 * ERR_FATAL in any fatal error case
3599 * ERR_ALERT if the reason of the error is available in err
3600 * ERR_WARN if a warning is available into err
3601 * The value 0 means there is no error nor warning and
3602 * the operation succeed.
yanbzhu488a4d22015-12-01 15:16:07 -05003603 */
3604static int ssl_sock_put_ckch_into_ctx(const char *path, const struct cert_key_and_chain *ckch, SSL_CTX *ctx, char **err)
3605{
Emeric Bruna96b5822019-10-17 13:25:14 +02003606 int errcode = 0;
Emmanuel Hocdetb90d2cb2020-02-18 15:27:32 +01003607 STACK_OF(X509) *find_chain = NULL;
Emeric Bruna96b5822019-10-17 13:25:14 +02003608
yanbzhu488a4d22015-12-01 15:16:07 -05003609 if (SSL_CTX_use_PrivateKey(ctx, ckch->key) <= 0) {
3610 memprintf(err, "%sunable to load SSL private key into SSL Context '%s'.\n",
3611 err && *err ? *err : "", path);
Emeric Bruna96b5822019-10-17 13:25:14 +02003612 errcode |= ERR_ALERT | ERR_FATAL;
3613 return errcode;
yanbzhu488a4d22015-12-01 15:16:07 -05003614 }
3615
3616 if (!SSL_CTX_use_certificate(ctx, ckch->cert)) {
3617 memprintf(err, "%sunable to load SSL certificate into SSL Context '%s'.\n",
3618 err && *err ? *err : "", path);
Emeric Bruna96b5822019-10-17 13:25:14 +02003619 errcode |= ERR_ALERT | ERR_FATAL;
3620 goto end;
yanbzhu488a4d22015-12-01 15:16:07 -05003621 }
3622
Emmanuel Hocdetb90d2cb2020-02-18 15:27:32 +01003623 if (ckch->chain) {
3624 find_chain = ckch->chain;
3625 } else {
3626 /* Find Certificate Chain in global */
3627 struct issuer_chain *issuer;
3628 issuer = ssl_get_issuer_chain(ckch->cert);
3629 if (issuer)
3630 find_chain = issuer->chain;
3631 }
William Lallemand85888572020-02-27 14:48:35 +01003632
3633 /* If we didn't find a chain we *MUST* use an empty X509 structure */
3634 if (find_chain == NULL)
3635 find_chain = sk_X509_new_null();
3636
yanbzhu488a4d22015-12-01 15:16:07 -05003637 /* Load all certs in the ckch into the ctx_chain for the ssl_ctx */
Emmanuel Hocdet1c65fdd2018-12-03 18:07:44 +01003638#ifdef SSL_CTX_set1_chain
Emmanuel Hocdetb90d2cb2020-02-18 15:27:32 +01003639 if (!SSL_CTX_set1_chain(ctx, find_chain)) {
Emmanuel Hocdet9246f8b2018-11-30 16:00:21 +01003640 memprintf(err, "%sunable to load chain certificate into SSL Context '%s'. Make sure you are linking against Openssl >= 1.0.2.\n",
3641 err && *err ? *err : "", path);
Emeric Bruna96b5822019-10-17 13:25:14 +02003642 errcode |= ERR_ALERT | ERR_FATAL;
3643 goto end;
yanbzhu488a4d22015-12-01 15:16:07 -05003644 }
Emmanuel Hocdet1c65fdd2018-12-03 18:07:44 +01003645#else
3646 { /* legacy compat (< openssl 1.0.2) */
3647 X509 *ca;
Emmanuel Hocdet140b64f2019-10-24 18:33:10 +02003648 STACK_OF(X509) *chain;
Emmanuel Hocdetb90d2cb2020-02-18 15:27:32 +01003649 chain = X509_chain_up_ref(find_chain);
Emmanuel Hocdet140b64f2019-10-24 18:33:10 +02003650 while ((ca = sk_X509_shift(chain)))
Emmanuel Hocdet1c65fdd2018-12-03 18:07:44 +01003651 if (!SSL_CTX_add_extra_chain_cert(ctx, ca)) {
3652 memprintf(err, "%sunable to load chain certificate into SSL Context '%s'.\n",
3653 err && *err ? *err : "", path);
3654 X509_free(ca);
Emmanuel Hocdet140b64f2019-10-24 18:33:10 +02003655 sk_X509_pop_free(chain, X509_free);
Emeric Bruna96b5822019-10-17 13:25:14 +02003656 errcode |= ERR_ALERT | ERR_FATAL;
3657 goto end;
Emmanuel Hocdet1c65fdd2018-12-03 18:07:44 +01003658 }
3659 }
3660#endif
yanbzhu488a4d22015-12-01 15:16:07 -05003661
William Lallemandfa892222019-07-23 16:06:08 +02003662#ifndef OPENSSL_NO_DH
3663 /* store a NULL pointer to indicate we have not yet loaded
3664 a custom DH param file */
3665 if (ssl_dh_ptr_index >= 0) {
3666 SSL_CTX_set_ex_data(ctx, ssl_dh_ptr_index, NULL);
3667 }
3668
Emeric Brun7a883362019-10-17 13:27:40 +02003669 errcode |= ssl_sock_load_dh_params(ctx, ckch, path, err);
3670 if (errcode & ERR_CODE) {
William Lallemandfa892222019-07-23 16:06:08 +02003671 memprintf(err, "%sunable to load DH parameters from file '%s'.\n",
3672 err && *err ? *err : "", path);
Emeric Bruna96b5822019-10-17 13:25:14 +02003673 goto end;
William Lallemandfa892222019-07-23 16:06:08 +02003674 }
3675#endif
3676
William Lallemanda17f4112019-10-10 15:16:44 +02003677#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
3678 if (sctl_ex_index >= 0 && ckch->sctl) {
3679 if (ssl_sock_load_sctl(ctx, ckch->sctl) < 0) {
3680 memprintf(err, "%s '%s.sctl' is present but cannot be read or parsed'.\n",
Tim Duesterhus93128532019-11-23 23:45:10 +01003681 err && *err ? *err : "", path);
Emeric Bruna96b5822019-10-17 13:25:14 +02003682 errcode |= ERR_ALERT | ERR_FATAL;
3683 goto end;
William Lallemanda17f4112019-10-10 15:16:44 +02003684 }
3685 }
3686#endif
3687
William Lallemand4a660132019-10-14 14:51:41 +02003688#if ((defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP) || defined OPENSSL_IS_BORINGSSL)
William Lallemand246c0242019-10-11 08:59:13 +02003689 /* Load OCSP Info into context */
3690 if (ckch->ocsp_response) {
Emmanuel Hocdet6f507c72020-02-18 15:56:39 +01003691 if (ssl_sock_load_ocsp(ctx, ckch, find_chain) < 0) {
Tim Duesterhus93128532019-11-23 23:45:10 +01003692 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",
3693 err && *err ? *err : "", path);
Emeric Bruna96b5822019-10-17 13:25:14 +02003694 errcode |= ERR_ALERT | ERR_FATAL;
3695 goto end;
William Lallemand246c0242019-10-11 08:59:13 +02003696 }
3697 }
William Lallemand246c0242019-10-11 08:59:13 +02003698#endif
3699
Emeric Bruna96b5822019-10-17 13:25:14 +02003700 end:
3701 return errcode;
yanbzhu488a4d22015-12-01 15:16:07 -05003702}
3703
William Lallemandc4ecddf2019-07-31 16:50:08 +02003704#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
yanbzhu08ce6ab2015-12-02 13:01:29 -05003705
William Lallemand28a8fce2019-10-04 17:36:55 +02003706static int ssl_sock_populate_sni_keytypes_hplr(const char *str, struct eb_root *sni_keytypes, int key_index)
yanbzhu08ce6ab2015-12-02 13:01:29 -05003707{
3708 struct sni_keytype *s_kt = NULL;
3709 struct ebmb_node *node;
3710 int i;
3711
3712 for (i = 0; i < trash.size; i++) {
3713 if (!str[i])
3714 break;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02003715 trash.area[i] = tolower(str[i]);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003716 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +02003717 trash.area[i] = 0;
3718 node = ebst_lookup(sni_keytypes, trash.area);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003719 if (!node) {
3720 /* CN not found in tree */
3721 s_kt = malloc(sizeof(struct sni_keytype) + i + 1);
3722 /* Using memcpy here instead of strncpy.
3723 * strncpy will cause sig_abrt errors under certain versions of gcc with -O2
3724 * See: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=60792
3725 */
William Lallemand28a8fce2019-10-04 17:36:55 +02003726 if (!s_kt)
3727 return -1;
3728
Willy Tarreau843b7cb2018-07-13 10:54:26 +02003729 memcpy(s_kt->name.key, trash.area, i+1);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003730 s_kt->keytypes = 0;
3731 ebst_insert(sni_keytypes, &s_kt->name);
3732 } else {
3733 /* CN found in tree */
3734 s_kt = container_of(node, struct sni_keytype, name);
3735 }
3736
3737 /* Mark that this CN has the keytype of key_index via keytypes mask */
3738 s_kt->keytypes |= 1<<key_index;
3739
William Lallemand28a8fce2019-10-04 17:36:55 +02003740 return 0;
3741
yanbzhu08ce6ab2015-12-02 13:01:29 -05003742}
3743
William Lallemandc4ecddf2019-07-31 16:50:08 +02003744#endif
William Lallemand8c1cdde2019-10-18 10:58:14 +02003745/*
3746 * Free a ckch_store and its ckch(s)
3747 * The linked ckch_inst are not free'd
3748 */
3749void ckchs_free(struct ckch_store *ckchs)
3750{
3751 if (!ckchs)
3752 return;
3753
3754#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
3755 if (ckchs->multi) {
3756 int n;
3757
3758 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++)
3759 ssl_sock_free_cert_key_and_chain_contents(&ckchs->ckch[n]);
3760 } else
3761#endif
3762 {
3763 ssl_sock_free_cert_key_and_chain_contents(ckchs->ckch);
3764 ckchs->ckch = NULL;
3765 }
3766
3767 free(ckchs);
3768}
3769
3770/* allocate and duplicate a ckch_store
3771 * Return a new ckch_store or NULL */
3772static struct ckch_store *ckchs_dup(const struct ckch_store *src)
3773{
3774 struct ckch_store *dst;
3775 int pathlen;
3776
3777 pathlen = strlen(src->path);
3778 dst = calloc(1, sizeof(*dst) + pathlen + 1);
3779 if (!dst)
3780 return NULL;
3781 /* copy previous key */
3782 memcpy(dst->path, src->path, pathlen + 1);
3783 dst->multi = src->multi;
3784 LIST_INIT(&dst->ckch_inst);
3785
3786 dst->ckch = calloc((src->multi ? SSL_SOCK_NUM_KEYTYPES : 1), sizeof(*dst->ckch));
3787 if (!dst->ckch)
3788 goto error;
3789
3790#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
3791 if (src->multi) {
3792 int n;
3793
3794 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
3795 if (&src->ckch[n]) {
3796 if (!ssl_sock_copy_cert_key_and_chain(&src->ckch[n], &dst->ckch[n]))
3797 goto error;
3798 }
3799 }
3800 } else
3801#endif
3802 {
3803 if (!ssl_sock_copy_cert_key_and_chain(src->ckch, dst->ckch))
3804 goto error;
3805 }
3806
3807 return dst;
3808
3809error:
3810 ckchs_free(dst);
3811
3812 return NULL;
3813}
William Lallemandc4ecddf2019-07-31 16:50:08 +02003814
William Lallemand36b84632019-07-18 19:28:17 +02003815/*
William Lallemande3af8fb2019-10-08 11:36:53 +02003816 * lookup a path into the ckchs tree.
William Lallemand6af03992019-07-23 15:00:54 +02003817 */
William Lallemande3af8fb2019-10-08 11:36:53 +02003818static inline struct ckch_store *ckchs_lookup(char *path)
William Lallemand6af03992019-07-23 15:00:54 +02003819{
3820 struct ebmb_node *eb;
3821
William Lallemande3af8fb2019-10-08 11:36:53 +02003822 eb = ebst_lookup(&ckchs_tree, path);
William Lallemand6af03992019-07-23 15:00:54 +02003823 if (!eb)
3824 return NULL;
3825
William Lallemande3af8fb2019-10-08 11:36:53 +02003826 return ebmb_entry(eb, struct ckch_store, node);
William Lallemand6af03992019-07-23 15:00:54 +02003827}
3828
3829/*
William Lallemande3af8fb2019-10-08 11:36:53 +02003830 * This function allocate a ckch_store and populate it with certificates from files.
William Lallemand36b84632019-07-18 19:28:17 +02003831 */
William Lallemande3af8fb2019-10-08 11:36:53 +02003832static struct ckch_store *ckchs_load_cert_file(char *path, int multi, char **err)
William Lallemand36b84632019-07-18 19:28:17 +02003833{
William Lallemande3af8fb2019-10-08 11:36:53 +02003834 struct ckch_store *ckchs;
William Lallemand36b84632019-07-18 19:28:17 +02003835
William Lallemande3af8fb2019-10-08 11:36:53 +02003836 ckchs = calloc(1, sizeof(*ckchs) + strlen(path) + 1);
3837 if (!ckchs) {
William Lallemand36b84632019-07-18 19:28:17 +02003838 memprintf(err, "%sunable to allocate memory.\n", err && *err ? *err : "");
3839 goto end;
3840 }
William Lallemande3af8fb2019-10-08 11:36:53 +02003841 ckchs->ckch = calloc(1, sizeof(*ckchs->ckch) * (multi ? SSL_SOCK_NUM_KEYTYPES : 1));
William Lallemand36b84632019-07-18 19:28:17 +02003842
William Lallemande3af8fb2019-10-08 11:36:53 +02003843 if (!ckchs->ckch) {
William Lallemand36b84632019-07-18 19:28:17 +02003844 memprintf(err, "%sunable to allocate memory.\n", err && *err ? *err : "");
3845 goto end;
3846 }
3847
William Lallemand9117de92019-10-04 00:29:42 +02003848 LIST_INIT(&ckchs->ckch_inst);
3849
William Lallemand36b84632019-07-18 19:28:17 +02003850 if (!multi) {
3851
William Lallemand96a9c972019-10-17 11:56:17 +02003852 if (ssl_sock_load_files_into_ckch(path, ckchs->ckch, err) == 1)
William Lallemand36b84632019-07-18 19:28:17 +02003853 goto end;
3854
William Lallemande3af8fb2019-10-08 11:36:53 +02003855 /* insert into the ckchs tree */
3856 memcpy(ckchs->path, path, strlen(path) + 1);
3857 ebst_insert(&ckchs_tree, &ckchs->node);
William Lallemand36b84632019-07-18 19:28:17 +02003858 } else {
3859 int found = 0;
William Lallemandc4ecddf2019-07-31 16:50:08 +02003860#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
3861 char fp[MAXPATHLEN+1] = {0};
3862 int n = 0;
William Lallemand36b84632019-07-18 19:28:17 +02003863
3864 /* Load all possible certs and keys */
3865 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
3866 struct stat buf;
3867 snprintf(fp, sizeof(fp), "%s.%s", path, SSL_SOCK_KEYTYPE_NAMES[n]);
3868 if (stat(fp, &buf) == 0) {
William Lallemand96a9c972019-10-17 11:56:17 +02003869 if (ssl_sock_load_files_into_ckch(fp, &ckchs->ckch[n], err) == 1)
William Lallemand36b84632019-07-18 19:28:17 +02003870 goto end;
3871 found = 1;
William Lallemande3af8fb2019-10-08 11:36:53 +02003872 ckchs->multi = 1;
William Lallemand36b84632019-07-18 19:28:17 +02003873 }
3874 }
William Lallemandc4ecddf2019-07-31 16:50:08 +02003875#endif
William Lallemand36b84632019-07-18 19:28:17 +02003876
3877 if (!found) {
William Lallemand6e5f2ce2019-08-01 14:43:20 +02003878 memprintf(err, "%sDidn't find any certificate for bundle '%s'.\n", err && *err ? *err : "", path);
William Lallemand36b84632019-07-18 19:28:17 +02003879 goto end;
3880 }
William Lallemande3af8fb2019-10-08 11:36:53 +02003881 /* insert into the ckchs tree */
3882 memcpy(ckchs->path, path, strlen(path) + 1);
3883 ebst_insert(&ckchs_tree, &ckchs->node);
William Lallemand36b84632019-07-18 19:28:17 +02003884 }
William Lallemande3af8fb2019-10-08 11:36:53 +02003885 return ckchs;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003886
William Lallemand36b84632019-07-18 19:28:17 +02003887end:
William Lallemande3af8fb2019-10-08 11:36:53 +02003888 if (ckchs) {
3889 free(ckchs->ckch);
3890 ebmb_delete(&ckchs->node);
William Lallemand6af03992019-07-23 15:00:54 +02003891 }
3892
William Lallemande3af8fb2019-10-08 11:36:53 +02003893 free(ckchs);
William Lallemand36b84632019-07-18 19:28:17 +02003894
3895 return NULL;
3896}
3897
William Lallemand38df1c82019-12-04 15:39:35 +01003898
3899/*
3900 * Free a sni filters array generated by ckch_inst_sni_ctx_to_sni_filters()
3901 */
3902static inline void free_sni_filters(char **sni_filter, int fcount)
3903{
3904 int i;
3905
3906 if (sni_filter) {
3907 for (i = 0; i < fcount; i++) {
3908 if (sni_filter[i]) {
3909 free(sni_filter[i]);
3910 sni_filter[i] = NULL;
3911 }
3912 }
3913 free(sni_filter);
3914 }
3915}
3916
3917/*
3918 * Fill <*sni_filter> with an allocated array of ptr to the existing filters,
3919 * The caller should free <*sni_filter>.
3920 * Fill <*fcount> with the number of filters
3921 * Return an ERR_* code.
3922 */
3923static int ckch_inst_sni_ctx_to_sni_filters(const struct ckch_inst *ckchi, char ***sni_filter, int *fcount, char **err)
3924{
3925 struct sni_ctx *sc0;
3926 int errcode = 0;
3927 int i = 0;
3928 char **tmp_filter;
3929 int tmp_fcount = 0;
3930
3931 list_for_each_entry(sc0, &ckchi->sni_ctx, by_ckch_inst) {
3932 tmp_fcount++;
3933 }
3934
3935 if (!tmp_fcount)
3936 goto end;
3937
3938 tmp_filter = malloc(sizeof(*tmp_filter) * tmp_fcount);
3939 if (!tmp_filter) {
3940 errcode |= ERR_FATAL|ERR_ALERT;
3941 goto error;
3942 }
3943
3944 list_for_each_entry(sc0, &ckchi->sni_ctx, by_ckch_inst) {
3945 size_t len = strlen((char *)sc0->name.key);
3946
3947 /* we need to alloc and copy to insert a '!' or/and a '*' */
3948 tmp_filter[i] = calloc(1, len + sc0->neg + sc0->wild + 1);
3949 if (!tmp_filter[i]) {
3950 errcode |= ERR_FATAL|ERR_ALERT;
3951 goto error;
3952 }
3953
3954 if (sc0->neg)
3955 *tmp_filter[i] = '!';
3956 if (sc0->wild)
3957 *(tmp_filter[i] + sc0->neg) = '*';
3958
3959 memcpy(tmp_filter[i] + sc0->neg + sc0->wild, (char *)sc0->name.key, len + 1);
3960 i++;
3961 }
3962end:
3963 *sni_filter = tmp_filter;
3964 *fcount = tmp_fcount;
3965
3966 return errcode;
3967error:
3968 memprintf(err, "%sUnable to generate filters!",
3969 err && *err ? *err : "");
3970 free_sni_filters(tmp_filter, tmp_fcount);
3971
3972 return errcode;
3973}
3974
3975
William Lallemandc4ecddf2019-07-31 16:50:08 +02003976#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
3977
William Lallemand36b84632019-07-18 19:28:17 +02003978/*
William Lallemande3af8fb2019-10-08 11:36:53 +02003979 * Take a ckch_store which contains a multi-certificate bundle.
William Lallemand36b84632019-07-18 19:28:17 +02003980 * Group these certificates into a set of SSL_CTX*
yanbzhu08ce6ab2015-12-02 13:01:29 -05003981 * based on shared and unique CN and SAN entries. Add these SSL_CTX* to the SNI tree.
3982 *
Joseph Herlant017b3da2018-11-15 09:07:59 -08003983 * This will allow the user to explicitly group multiple cert/keys for a single purpose
yanbzhu08ce6ab2015-12-02 13:01:29 -05003984 *
Emeric Brun054563d2019-10-17 13:16:58 +02003985 * Returns a bitfield containing the flags:
3986 * ERR_FATAL in any fatal error case
3987 * ERR_ALERT if the reason of the error is available in err
3988 * ERR_WARN if a warning is available into err
William Lallemand36b84632019-07-18 19:28:17 +02003989 *
yanbzhu08ce6ab2015-12-02 13:01:29 -05003990 */
Emeric Brun054563d2019-10-17 13:16:58 +02003991static int ckch_inst_new_load_multi_store(const char *path, struct ckch_store *ckchs,
3992 struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
3993 char **sni_filter, int fcount, struct ckch_inst **ckchi, char **err)
yanbzhu08ce6ab2015-12-02 13:01:29 -05003994{
William Lallemand36b84632019-07-18 19:28:17 +02003995 int i = 0, n = 0;
3996 struct cert_key_and_chain *certs_and_keys;
William Lallemand4b989f22019-10-04 18:36:55 +02003997 struct eb_root sni_keytypes_map = EB_ROOT;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003998 struct ebmb_node *node;
3999 struct ebmb_node *next;
4000 /* Array of SSL_CTX pointers corresponding to each possible combo
4001 * of keytypes
4002 */
4003 struct key_combo_ctx key_combos[SSL_SOCK_POSSIBLE_KT_COMBOS] = { {0} };
Emeric Brun054563d2019-10-17 13:16:58 +02004004 int errcode = 0;
yanbzhu08ce6ab2015-12-02 13:01:29 -05004005 X509_NAME *xname = NULL;
4006 char *str = NULL;
4007#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
4008 STACK_OF(GENERAL_NAME) *names = NULL;
4009#endif
William Lallemand614ca0d2019-10-07 13:52:11 +02004010 struct ckch_inst *ckch_inst;
yanbzhu08ce6ab2015-12-02 13:01:29 -05004011
Emeric Brun054563d2019-10-17 13:16:58 +02004012 *ckchi = NULL;
4013
William Lallemande3af8fb2019-10-08 11:36:53 +02004014 if (!ckchs || !ckchs->ckch || !ckchs->multi) {
William Lallemand36b84632019-07-18 19:28:17 +02004015 memprintf(err, "%sunable to load SSL certificate file '%s' file does not exist.\n",
4016 err && *err ? *err : "", path);
Emeric Brun054563d2019-10-17 13:16:58 +02004017 return ERR_ALERT | ERR_FATAL;
William Lallemand614ca0d2019-10-07 13:52:11 +02004018 }
4019
4020 ckch_inst = ckch_inst_new();
4021 if (!ckch_inst) {
4022 memprintf(err, "%sunable to allocate SSL context for cert '%s'.\n",
4023 err && *err ? *err : "", path);
Emeric Brun054563d2019-10-17 13:16:58 +02004024 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemand614ca0d2019-10-07 13:52:11 +02004025 goto end;
yanbzhu08ce6ab2015-12-02 13:01:29 -05004026 }
4027
William Lallemande3af8fb2019-10-08 11:36:53 +02004028 certs_and_keys = ckchs->ckch;
William Lallemand36b84632019-07-18 19:28:17 +02004029
yanbzhu08ce6ab2015-12-02 13:01:29 -05004030 /* Process each ckch and update keytypes for each CN/SAN
4031 * for example, if CN/SAN www.a.com is associated with
4032 * certs with keytype 0 and 2, then at the end of the loop,
4033 * www.a.com will have:
4034 * keyindex = 0 | 1 | 4 = 5
4035 */
4036 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
William Lallemand28a8fce2019-10-04 17:36:55 +02004037 int ret;
yanbzhu08ce6ab2015-12-02 13:01:29 -05004038
4039 if (!ssl_sock_is_ckch_valid(&certs_and_keys[n]))
4040 continue;
4041
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02004042 if (fcount) {
William Lallemand28a8fce2019-10-04 17:36:55 +02004043 for (i = 0; i < fcount; i++) {
4044 ret = ssl_sock_populate_sni_keytypes_hplr(sni_filter[i], &sni_keytypes_map, n);
4045 if (ret < 0) {
4046 memprintf(err, "%sunable to allocate SSL context.\n",
4047 err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02004048 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemand28a8fce2019-10-04 17:36:55 +02004049 goto end;
4050 }
4051 }
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02004052 } else {
4053 /* A lot of the following code is OpenSSL boilerplate for processing CN's and SAN's,
4054 * so the line that contains logic is marked via comments
4055 */
4056 xname = X509_get_subject_name(certs_and_keys[n].cert);
4057 i = -1;
4058 while ((i = X509_NAME_get_index_by_NID(xname, NID_commonName, i)) != -1) {
4059 X509_NAME_ENTRY *entry = X509_NAME_get_entry(xname, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02004060 ASN1_STRING *value;
4061 value = X509_NAME_ENTRY_get_data(entry);
4062 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02004063 /* Important line is here */
William Lallemand28a8fce2019-10-04 17:36:55 +02004064 ret = ssl_sock_populate_sni_keytypes_hplr(str, &sni_keytypes_map, n);
yanbzhu08ce6ab2015-12-02 13:01:29 -05004065
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02004066 OPENSSL_free(str);
4067 str = NULL;
William Lallemand28a8fce2019-10-04 17:36:55 +02004068 if (ret < 0) {
4069 memprintf(err, "%sunable to allocate SSL context.\n",
4070 err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02004071 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemand28a8fce2019-10-04 17:36:55 +02004072 goto end;
4073 }
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02004074 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05004075 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05004076
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02004077 /* Do the above logic for each SAN */
yanbzhu08ce6ab2015-12-02 13:01:29 -05004078#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02004079 names = X509_get_ext_d2i(certs_and_keys[n].cert, NID_subject_alt_name, NULL, NULL);
4080 if (names) {
4081 for (i = 0; i < sk_GENERAL_NAME_num(names); i++) {
4082 GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i);
yanbzhu08ce6ab2015-12-02 13:01:29 -05004083
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02004084 if (name->type == GEN_DNS) {
4085 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
4086 /* Important line is here */
William Lallemand28a8fce2019-10-04 17:36:55 +02004087 ret = ssl_sock_populate_sni_keytypes_hplr(str, &sni_keytypes_map, n);
yanbzhu08ce6ab2015-12-02 13:01:29 -05004088
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02004089 OPENSSL_free(str);
4090 str = NULL;
William Lallemand28a8fce2019-10-04 17:36:55 +02004091 if (ret < 0) {
4092 memprintf(err, "%sunable to allocate SSL context.\n",
4093 err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02004094 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemand28a8fce2019-10-04 17:36:55 +02004095 goto end;
4096 }
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02004097 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05004098 }
4099 }
4100 }
4101 }
4102#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
4103 }
4104
4105 /* If no files found, return error */
4106 if (eb_is_empty(&sni_keytypes_map)) {
4107 memprintf(err, "%sunable to load SSL certificate file '%s' file does not exist.\n",
4108 err && *err ? *err : "", path);
Emeric Brun054563d2019-10-17 13:16:58 +02004109 errcode |= ERR_ALERT | ERR_FATAL;
yanbzhu08ce6ab2015-12-02 13:01:29 -05004110 goto end;
4111 }
4112
4113 /* We now have a map of CN/SAN to keytypes that are loaded in
4114 * Iterate through the map to create the SSL_CTX's (if needed)
4115 * and add each CTX to the SNI tree
4116 *
4117 * Some math here:
Joseph Herlant017b3da2018-11-15 09:07:59 -08004118 * There are 2^n - 1 possible combinations, each unique
yanbzhu08ce6ab2015-12-02 13:01:29 -05004119 * combination is denoted by the key in the map. Each key
4120 * has a value between 1 and 2^n - 1. Conveniently, the array
4121 * of SSL_CTX* is sized 2^n. So, we can simply use the i'th
4122 * entry in the array to correspond to the unique combo (key)
4123 * associated with i. This unique key combo (i) will be associated
4124 * with combos[i-1]
4125 */
4126
4127 node = ebmb_first(&sni_keytypes_map);
4128 while (node) {
4129 SSL_CTX *cur_ctx;
Bertrand Jacquin33423092016-11-13 16:37:13 +00004130 char cur_file[MAXPATHLEN+1];
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02004131 const struct pkey_info kinfo = { .sig = TLSEXT_signature_anonymous, .bits = 0 };
yanbzhu08ce6ab2015-12-02 13:01:29 -05004132
4133 str = (char *)container_of(node, struct sni_keytype, name)->name.key;
4134 i = container_of(node, struct sni_keytype, name)->keytypes;
4135 cur_ctx = key_combos[i-1].ctx;
4136
4137 if (cur_ctx == NULL) {
4138 /* need to create SSL_CTX */
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004139 cur_ctx = SSL_CTX_new(SSLv23_server_method());
yanbzhu08ce6ab2015-12-02 13:01:29 -05004140 if (cur_ctx == NULL) {
4141 memprintf(err, "%sunable to allocate SSL context.\n",
4142 err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02004143 errcode |= ERR_ALERT | ERR_FATAL;
yanbzhu08ce6ab2015-12-02 13:01:29 -05004144 goto end;
4145 }
4146
yanbzhube2774d2015-12-10 15:07:30 -05004147 /* Load all required certs/keys/chains/OCSPs info into SSL_CTX */
yanbzhu08ce6ab2015-12-02 13:01:29 -05004148 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
4149 if (i & (1<<n)) {
4150 /* Key combo contains ckch[n] */
Bertrand Jacquin33423092016-11-13 16:37:13 +00004151 snprintf(cur_file, MAXPATHLEN+1, "%s.%s", path, SSL_SOCK_KEYTYPE_NAMES[n]);
Emeric Bruna96b5822019-10-17 13:25:14 +02004152 errcode |= ssl_sock_put_ckch_into_ctx(cur_file, &certs_and_keys[n], cur_ctx, err);
4153 if (errcode & ERR_CODE)
yanbzhu08ce6ab2015-12-02 13:01:29 -05004154 goto end;
yanbzhu08ce6ab2015-12-02 13:01:29 -05004155 }
4156 }
4157
yanbzhu08ce6ab2015-12-02 13:01:29 -05004158 /* Update key_combos */
4159 key_combos[i-1].ctx = cur_ctx;
4160 }
4161
4162 /* Update SNI Tree */
William Lallemand9117de92019-10-04 00:29:42 +02004163
William Lallemand1d29c742019-10-04 00:53:29 +02004164 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 +02004165 kinfo, str, key_combos[i-1].order);
4166 if (key_combos[i-1].order < 0) {
4167 memprintf(err, "%sunable to create a sni context.\n", err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02004168 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemandfe49bb32019-10-03 23:46:33 +02004169 goto end;
4170 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05004171 node = ebmb_next(node);
4172 }
4173
4174
4175 /* Mark a default context if none exists, using the ctx that has the most shared keys */
4176 if (!bind_conf->default_ctx) {
4177 for (i = SSL_SOCK_POSSIBLE_KT_COMBOS - 1; i >= 0; i--) {
4178 if (key_combos[i].ctx) {
4179 bind_conf->default_ctx = key_combos[i].ctx;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004180 bind_conf->default_ssl_conf = ssl_conf;
William Lallemand21724f02019-11-04 17:56:13 +01004181 ckch_inst->is_default = 1;
yanbzhu08ce6ab2015-12-02 13:01:29 -05004182 break;
4183 }
4184 }
4185 }
4186
William Lallemand614ca0d2019-10-07 13:52:11 +02004187 ckch_inst->bind_conf = bind_conf;
William Lallemand150bfa82019-09-19 17:12:49 +02004188 ckch_inst->ssl_conf = ssl_conf;
yanbzhu08ce6ab2015-12-02 13:01:29 -05004189end:
4190
4191 if (names)
4192 sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
4193
yanbzhu08ce6ab2015-12-02 13:01:29 -05004194 node = ebmb_first(&sni_keytypes_map);
4195 while (node) {
4196 next = ebmb_next(node);
4197 ebmb_delete(node);
William Lallemand8ed5b962019-10-04 17:24:39 +02004198 free(ebmb_entry(node, struct sni_keytype, name));
yanbzhu08ce6ab2015-12-02 13:01:29 -05004199 node = next;
4200 }
4201
Emeric Brun054563d2019-10-17 13:16:58 +02004202 if (errcode & ERR_CODE && ckch_inst) {
William Lallemand0c6d12f2019-10-04 18:38:51 +02004203 struct sni_ctx *sc0, *sc0b;
4204
4205 /* free the SSL_CTX in case of error */
4206 for (i = 0; i < SSL_SOCK_POSSIBLE_KT_COMBOS; i++) {
4207 if (key_combos[i].ctx)
4208 SSL_CTX_free(key_combos[i].ctx);
4209 }
4210
4211 /* free the sni_ctx in case of error */
4212 list_for_each_entry_safe(sc0, sc0b, &ckch_inst->sni_ctx, by_ckch_inst) {
4213
4214 ebmb_delete(&sc0->name);
4215 LIST_DEL(&sc0->by_ckch_inst);
4216 free(sc0);
4217 }
William Lallemand614ca0d2019-10-07 13:52:11 +02004218 free(ckch_inst);
4219 ckch_inst = NULL;
William Lallemand0c6d12f2019-10-04 18:38:51 +02004220 }
4221
Emeric Brun054563d2019-10-17 13:16:58 +02004222 *ckchi = ckch_inst;
4223 return errcode;
yanbzhu08ce6ab2015-12-02 13:01:29 -05004224}
4225#else
4226/* This is a dummy, that just logs an error and returns error */
Emeric Brun054563d2019-10-17 13:16:58 +02004227static int ckch_inst_new_load_multi_store(const char *path, struct ckch_store *ckchs,
4228 struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
4229 char **sni_filter, int fcount, struct ckch_inst **ckchi, char **err)
yanbzhu08ce6ab2015-12-02 13:01:29 -05004230{
4231 memprintf(err, "%sunable to stat SSL certificate from file '%s' : %s.\n",
4232 err && *err ? *err : "", path, strerror(errno));
Emeric Brun054563d2019-10-17 13:16:58 +02004233 return ERR_ALERT | ERR_FATAL;
yanbzhu08ce6ab2015-12-02 13:01:29 -05004234}
4235
Willy Tarreau9a1ab082019-05-09 13:26:41 +02004236#endif /* #if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL: Support for loading multiple certs into a single SSL_CTX */
yanbzhu488a4d22015-12-01 15:16:07 -05004237
William Lallemand614ca0d2019-10-07 13:52:11 +02004238/*
4239 * This function allocate a ckch_inst and create its snis
Emeric Brun054563d2019-10-17 13:16:58 +02004240 *
4241 * Returns a bitfield containing the flags:
4242 * ERR_FATAL in any fatal error case
4243 * ERR_ALERT if the reason of the error is available in err
4244 * ERR_WARN if a warning is available into err
William Lallemand614ca0d2019-10-07 13:52:11 +02004245 */
Emeric Brun054563d2019-10-17 13:16:58 +02004246static int ckch_inst_new_load_store(const char *path, struct ckch_store *ckchs, struct bind_conf *bind_conf,
4247 struct ssl_bind_conf *ssl_conf, char **sni_filter, int fcount, struct ckch_inst **ckchi, char **err)
Emeric Brunfc0421f2012-09-07 17:30:07 +02004248{
William Lallemandc9402072019-05-15 15:33:54 +02004249 SSL_CTX *ctx;
William Lallemandc9402072019-05-15 15:33:54 +02004250 int i;
Emeric Brunfc0421f2012-09-07 17:30:07 +02004251 int order = 0;
4252 X509_NAME *xname;
4253 char *str;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01004254 EVP_PKEY *pkey;
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02004255 struct pkey_info kinfo = { .sig = TLSEXT_signature_anonymous, .bits = 0 };
Emeric Brunfc0421f2012-09-07 17:30:07 +02004256#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
4257 STACK_OF(GENERAL_NAME) *names;
4258#endif
William Lallemand36b84632019-07-18 19:28:17 +02004259 struct cert_key_and_chain *ckch;
William Lallemand614ca0d2019-10-07 13:52:11 +02004260 struct ckch_inst *ckch_inst = NULL;
Emeric Brun054563d2019-10-17 13:16:58 +02004261 int errcode = 0;
4262
4263 *ckchi = NULL;
William Lallemanda59191b2019-05-15 16:08:56 +02004264
William Lallemande3af8fb2019-10-08 11:36:53 +02004265 if (!ckchs || !ckchs->ckch)
Emeric Brun054563d2019-10-17 13:16:58 +02004266 return ERR_FATAL;
Emeric Brunfc0421f2012-09-07 17:30:07 +02004267
William Lallemande3af8fb2019-10-08 11:36:53 +02004268 ckch = ckchs->ckch;
William Lallemand36b84632019-07-18 19:28:17 +02004269
William Lallemandc9402072019-05-15 15:33:54 +02004270 ctx = SSL_CTX_new(SSLv23_server_method());
4271 if (!ctx) {
4272 memprintf(err, "%sunable to allocate SSL context for cert '%s'.\n",
4273 err && *err ? *err : "", path);
Emeric Brun054563d2019-10-17 13:16:58 +02004274 errcode |= ERR_ALERT | ERR_FATAL;
4275 goto error;
William Lallemandc9402072019-05-15 15:33:54 +02004276 }
4277
Emeric Bruna96b5822019-10-17 13:25:14 +02004278 errcode |= ssl_sock_put_ckch_into_ctx(path, ckch, ctx, err);
4279 if (errcode & ERR_CODE)
William Lallemand614ca0d2019-10-07 13:52:11 +02004280 goto error;
William Lallemand614ca0d2019-10-07 13:52:11 +02004281
4282 ckch_inst = ckch_inst_new();
4283 if (!ckch_inst) {
4284 memprintf(err, "%sunable to allocate SSL context for cert '%s'.\n",
4285 err && *err ? *err : "", path);
Emeric Brun054563d2019-10-17 13:16:58 +02004286 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemandd9199372019-10-04 15:37:05 +02004287 goto error;
William Lallemandc9402072019-05-15 15:33:54 +02004288 }
4289
William Lallemand36b84632019-07-18 19:28:17 +02004290 pkey = X509_get_pubkey(ckch->cert);
Emmanuel Hocdet05942112017-02-20 16:11:50 +01004291 if (pkey) {
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02004292 kinfo.bits = EVP_PKEY_bits(pkey);
Emmanuel Hocdet05942112017-02-20 16:11:50 +01004293 switch(EVP_PKEY_base_id(pkey)) {
4294 case EVP_PKEY_RSA:
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02004295 kinfo.sig = TLSEXT_signature_rsa;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01004296 break;
4297 case EVP_PKEY_EC:
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02004298 kinfo.sig = TLSEXT_signature_ecdsa;
4299 break;
4300 case EVP_PKEY_DSA:
4301 kinfo.sig = TLSEXT_signature_dsa;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01004302 break;
4303 }
4304 EVP_PKEY_free(pkey);
4305 }
4306
Emeric Brun50bcecc2013-04-22 13:05:23 +02004307 if (fcount) {
William Lallemandfe49bb32019-10-03 23:46:33 +02004308 while (fcount--) {
William Lallemand1d29c742019-10-04 00:53:29 +02004309 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 +02004310 if (order < 0) {
4311 memprintf(err, "%sunable to create a sni context.\n", err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02004312 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemandd9199372019-10-04 15:37:05 +02004313 goto error;
William Lallemandfe49bb32019-10-03 23:46:33 +02004314 }
4315 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004316 }
4317 else {
Emeric Brunfc0421f2012-09-07 17:30:07 +02004318#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
William Lallemand36b84632019-07-18 19:28:17 +02004319 names = X509_get_ext_d2i(ckch->cert, NID_subject_alt_name, NULL, NULL);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004320 if (names) {
4321 for (i = 0; i < sk_GENERAL_NAME_num(names); i++) {
4322 GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i);
4323 if (name->type == GEN_DNS) {
4324 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
William Lallemand1d29c742019-10-04 00:53:29 +02004325 order = ckch_inst_add_cert_sni(ctx, ckch_inst, bind_conf, ssl_conf, kinfo, str, order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004326 OPENSSL_free(str);
William Lallemandfe49bb32019-10-03 23:46:33 +02004327 if (order < 0) {
4328 memprintf(err, "%sunable to create a sni context.\n", err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02004329 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemandd9199372019-10-04 15:37:05 +02004330 goto error;
William Lallemandfe49bb32019-10-03 23:46:33 +02004331 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004332 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004333 }
4334 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004335 sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004336 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004337#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
William Lallemand36b84632019-07-18 19:28:17 +02004338 xname = X509_get_subject_name(ckch->cert);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004339 i = -1;
4340 while ((i = X509_NAME_get_index_by_NID(xname, NID_commonName, i)) != -1) {
4341 X509_NAME_ENTRY *entry = X509_NAME_get_entry(xname, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02004342 ASN1_STRING *value;
4343
4344 value = X509_NAME_ENTRY_get_data(entry);
4345 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
William Lallemand1d29c742019-10-04 00:53:29 +02004346 order = ckch_inst_add_cert_sni(ctx, ckch_inst, bind_conf, ssl_conf, kinfo, str, order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004347 OPENSSL_free(str);
William Lallemandfe49bb32019-10-03 23:46:33 +02004348 if (order < 0) {
4349 memprintf(err, "%sunable to create a sni context.\n", err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02004350 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemandd9199372019-10-04 15:37:05 +02004351 goto error;
William Lallemandfe49bb32019-10-03 23:46:33 +02004352 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004353 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004354 }
4355 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004356 /* we must not free the SSL_CTX anymore below, since it's already in
4357 * the tree, so it will be discovered and cleaned in time.
4358 */
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02004359
Emeric Brunfc0421f2012-09-07 17:30:07 +02004360#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004361 if (bind_conf->default_ctx) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02004362 memprintf(err, "%sthis version of openssl cannot load multiple SSL certificates.\n",
4363 err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02004364 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemandd9199372019-10-04 15:37:05 +02004365 goto error;
Emeric Brunfc0421f2012-09-07 17:30:07 +02004366 }
4367#endif
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004368 if (!bind_conf->default_ctx) {
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004369 bind_conf->default_ctx = ctx;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004370 bind_conf->default_ssl_conf = ssl_conf;
William Lallemand21724f02019-11-04 17:56:13 +01004371 ckch_inst->is_default = 1;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004372 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004373
William Lallemand9117de92019-10-04 00:29:42 +02004374 /* everything succeed, the ckch instance can be used */
4375 ckch_inst->bind_conf = bind_conf;
William Lallemand150bfa82019-09-19 17:12:49 +02004376 ckch_inst->ssl_conf = ssl_conf;
William Lallemand9117de92019-10-04 00:29:42 +02004377
Emeric Brun054563d2019-10-17 13:16:58 +02004378 *ckchi = ckch_inst;
4379 return errcode;
William Lallemandd9199372019-10-04 15:37:05 +02004380
4381error:
4382 /* free the allocated sni_ctxs */
William Lallemand614ca0d2019-10-07 13:52:11 +02004383 if (ckch_inst) {
William Lallemandd9199372019-10-04 15:37:05 +02004384 struct sni_ctx *sc0, *sc0b;
4385
4386 list_for_each_entry_safe(sc0, sc0b, &ckch_inst->sni_ctx, by_ckch_inst) {
4387
4388 ebmb_delete(&sc0->name);
4389 LIST_DEL(&sc0->by_ckch_inst);
4390 free(sc0);
4391 }
William Lallemand614ca0d2019-10-07 13:52:11 +02004392 free(ckch_inst);
4393 ckch_inst = NULL;
William Lallemandd9199372019-10-04 15:37:05 +02004394 }
4395 /* We only created 1 SSL_CTX so we can free it there */
4396 SSL_CTX_free(ctx);
4397
Emeric Brun054563d2019-10-17 13:16:58 +02004398 return errcode;
Emeric Brunfc0421f2012-09-07 17:30:07 +02004399}
4400
Willy Tarreau8c5414a2019-10-16 17:06:25 +02004401/* Returns a set of ERR_* flags possibly with an error in <err>. */
William Lallemand614ca0d2019-10-07 13:52:11 +02004402static int ssl_sock_load_ckchs(const char *path, struct ckch_store *ckchs,
4403 struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
4404 char **sni_filter, int fcount, char **err)
4405{
4406 struct ckch_inst *ckch_inst = NULL;
Emeric Brun054563d2019-10-17 13:16:58 +02004407 int errcode = 0;
William Lallemand614ca0d2019-10-07 13:52:11 +02004408
4409 /* we found the ckchs in the tree, we can use it directly */
4410 if (ckchs->multi)
Emeric Brun054563d2019-10-17 13:16:58 +02004411 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 +02004412 else
Emeric Brun054563d2019-10-17 13:16:58 +02004413 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 +02004414
Emeric Brun054563d2019-10-17 13:16:58 +02004415 if (errcode & ERR_CODE)
4416 return errcode;
William Lallemand614ca0d2019-10-07 13:52:11 +02004417
4418 ssl_sock_load_cert_sni(ckch_inst, bind_conf);
4419
4420 /* succeed, add the instance to the ckch_store's list of instance */
4421 LIST_ADDQ(&ckchs->ckch_inst, &ckch_inst->by_ckchs);
Emeric Brun054563d2019-10-17 13:16:58 +02004422 return errcode;
William Lallemand614ca0d2019-10-07 13:52:11 +02004423}
4424
4425
Willy Tarreaubbc91962019-10-16 16:42:19 +02004426/* Returns a set of ERR_* flags possibly with an error in <err>. */
Willy Tarreau03209342016-12-22 17:08:28 +01004427int ssl_sock_load_cert(char *path, struct bind_conf *bind_conf, char **err)
Emeric Brunfc0421f2012-09-07 17:30:07 +02004428{
Cyril Bonté3180f7b2015-01-25 00:16:08 +01004429 struct dirent **de_list;
4430 int i, n;
Emeric Brunfc0421f2012-09-07 17:30:07 +02004431 struct stat buf;
Willy Tarreauee2663b2012-12-06 11:36:59 +01004432 char *end;
4433 char fp[MAXPATHLEN+1];
Emeric Brunfc0421f2012-09-07 17:30:07 +02004434 int cfgerr = 0;
William Lallemande3af8fb2019-10-08 11:36:53 +02004435 struct ckch_store *ckchs;
Willy Tarreau9a1ab082019-05-09 13:26:41 +02004436#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
yanbzhu63ea8462015-12-09 13:35:14 -05004437 int is_bundle;
4438 int j;
4439#endif
William Lallemande3af8fb2019-10-08 11:36:53 +02004440 if ((ckchs = ckchs_lookup(path))) {
William Lallemande3af8fb2019-10-08 11:36:53 +02004441 /* we found the ckchs in the tree, we can use it directly */
Willy Tarreau8c5414a2019-10-16 17:06:25 +02004442 return ssl_sock_load_ckchs(path, ckchs, bind_conf, NULL, NULL, 0, err);
William Lallemand6af03992019-07-23 15:00:54 +02004443 }
4444
yanbzhu08ce6ab2015-12-02 13:01:29 -05004445 if (stat(path, &buf) == 0) {
William Dauchy9a8ef7f2020-01-13 17:52:49 +01004446 if (S_ISDIR(buf.st_mode) == 0) {
William Lallemande3af8fb2019-10-08 11:36:53 +02004447 ckchs = ckchs_load_cert_file(path, 0, err);
4448 if (!ckchs)
Willy Tarreaubbc91962019-10-16 16:42:19 +02004449 return ERR_ALERT | ERR_FATAL;
4450
Willy Tarreau8c5414a2019-10-16 17:06:25 +02004451 return ssl_sock_load_ckchs(path, ckchs, bind_conf, NULL, NULL, 0, err);
William Lallemand36b84632019-07-18 19:28:17 +02004452 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004453
yanbzhu08ce6ab2015-12-02 13:01:29 -05004454 /* strip trailing slashes, including first one */
4455 for (end = path + strlen(path) - 1; end >= path && *end == '/'; end--)
4456 *end = 0;
Emeric Brunfc0421f2012-09-07 17:30:07 +02004457
yanbzhu08ce6ab2015-12-02 13:01:29 -05004458 n = scandir(path, &de_list, 0, alphasort);
4459 if (n < 0) {
4460 memprintf(err, "%sunable to scan directory '%s' : %s.\n",
4461 err && *err ? *err : "", path, strerror(errno));
Willy Tarreaubbc91962019-10-16 16:42:19 +02004462 cfgerr |= ERR_ALERT | ERR_FATAL;
yanbzhu08ce6ab2015-12-02 13:01:29 -05004463 }
4464 else {
4465 for (i = 0; i < n; i++) {
4466 struct dirent *de = de_list[i];
Emeric Brun2aab7222014-06-18 18:15:09 +02004467
yanbzhu08ce6ab2015-12-02 13:01:29 -05004468 end = strrchr(de->d_name, '.');
William Lallemand3f25ae32020-02-24 16:30:12 +01004469 if (end && (!strcmp(end, ".issuer") || !strcmp(end, ".ocsp") || !strcmp(end, ".sctl") || !strcmp(end, ".key")))
yanbzhu08ce6ab2015-12-02 13:01:29 -05004470 goto ignore_entry;
Cyril Bonté3180f7b2015-01-25 00:16:08 +01004471
yanbzhu08ce6ab2015-12-02 13:01:29 -05004472 snprintf(fp, sizeof(fp), "%s/%s", path, de->d_name);
4473 if (stat(fp, &buf) != 0) {
4474 memprintf(err, "%sunable to stat SSL certificate from file '%s' : %s.\n",
4475 err && *err ? *err : "", fp, strerror(errno));
Willy Tarreaubbc91962019-10-16 16:42:19 +02004476 cfgerr |= ERR_ALERT | ERR_FATAL;
yanbzhu08ce6ab2015-12-02 13:01:29 -05004477 goto ignore_entry;
4478 }
4479 if (!S_ISREG(buf.st_mode))
4480 goto ignore_entry;
yanbzhu63ea8462015-12-09 13:35:14 -05004481
Willy Tarreau9a1ab082019-05-09 13:26:41 +02004482#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
yanbzhu63ea8462015-12-09 13:35:14 -05004483 is_bundle = 0;
4484 /* Check if current entry in directory is part of a multi-cert bundle */
4485
William Lallemand3af48e72020-02-03 17:15:52 +01004486 if ((global_ssl.extra_files & SSL_GF_BUNDLE) && end) {
yanbzhu63ea8462015-12-09 13:35:14 -05004487 for (j = 0; j < SSL_SOCK_NUM_KEYTYPES; j++) {
4488 if (!strcmp(end + 1, SSL_SOCK_KEYTYPE_NAMES[j])) {
4489 is_bundle = 1;
4490 break;
4491 }
4492 }
4493
4494 if (is_bundle) {
yanbzhu63ea8462015-12-09 13:35:14 -05004495 int dp_len;
4496
4497 dp_len = end - de->d_name;
yanbzhu63ea8462015-12-09 13:35:14 -05004498
4499 /* increment i and free de until we get to a non-bundle cert
4500 * Note here that we look at de_list[i + 1] before freeing de
Willy Tarreau05800522019-10-29 10:48:50 +01004501 * this is important since ignore_entry will free de. This also
4502 * guarantees that de->d_name continues to hold the same prefix.
yanbzhu63ea8462015-12-09 13:35:14 -05004503 */
Willy Tarreau05800522019-10-29 10:48:50 +01004504 while (i + 1 < n && !strncmp(de_list[i + 1]->d_name, de->d_name, dp_len)) {
yanbzhu63ea8462015-12-09 13:35:14 -05004505 free(de);
4506 i++;
4507 de = de_list[i];
4508 }
4509
Willy Tarreau05800522019-10-29 10:48:50 +01004510 snprintf(fp, sizeof(fp), "%s/%.*s", path, dp_len, de->d_name);
William Lallemande3af8fb2019-10-08 11:36:53 +02004511 if ((ckchs = ckchs_lookup(fp)) == NULL)
4512 ckchs = ckchs_load_cert_file(fp, 1, err);
4513 if (!ckchs)
Willy Tarreaubbc91962019-10-16 16:42:19 +02004514 cfgerr |= ERR_ALERT | ERR_FATAL;
Willy Tarreau8c5414a2019-10-16 17:06:25 +02004515 else
4516 cfgerr |= ssl_sock_load_ckchs(path, ckchs, bind_conf, NULL, NULL, 0, err);
yanbzhu63ea8462015-12-09 13:35:14 -05004517 /* Successfully processed the bundle */
4518 goto ignore_entry;
4519 }
4520 }
4521
4522#endif
William Lallemande3af8fb2019-10-08 11:36:53 +02004523 if ((ckchs = ckchs_lookup(fp)) == NULL)
4524 ckchs = ckchs_load_cert_file(fp, 0, err);
4525 if (!ckchs)
Willy Tarreaubbc91962019-10-16 16:42:19 +02004526 cfgerr |= ERR_ALERT | ERR_FATAL;
William Lallemand614ca0d2019-10-07 13:52:11 +02004527 else
Willy Tarreau8c5414a2019-10-16 17:06:25 +02004528 cfgerr |= ssl_sock_load_ckchs(path, ckchs, bind_conf, NULL, NULL, 0, err);
William Lallemand36b84632019-07-18 19:28:17 +02004529
yanbzhu08ce6ab2015-12-02 13:01:29 -05004530ignore_entry:
4531 free(de);
Cyril Bonté3180f7b2015-01-25 00:16:08 +01004532 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05004533 free(de_list);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004534 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05004535 return cfgerr;
yanbzhu08ce6ab2015-12-02 13:01:29 -05004536
William Lallemand3af48e72020-02-03 17:15:52 +01004537 } else {
4538 /* stat failed */
Willy Tarreaubbc91962019-10-16 16:42:19 +02004539
William Lallemand3af48e72020-02-03 17:15:52 +01004540 if (global_ssl.extra_files & SSL_GF_BUNDLE) {
4541 /* try to load a bundle if it is permitted */
4542 ckchs = ckchs_load_cert_file(path, 1, err);
4543 if (!ckchs)
4544 return ERR_ALERT | ERR_FATAL;
4545 cfgerr |= ssl_sock_load_ckchs(path, ckchs, bind_conf, NULL, NULL, 0, err);
4546 } else {
4547 memprintf(err, "%sunable to stat SSL certificate from file '%s' : %s.\n",
4548 err && *err ? *err : "", fp, strerror(errno));
4549 cfgerr |= ERR_ALERT | ERR_FATAL;
4550 }
4551 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05004552
Emeric Brunfc0421f2012-09-07 17:30:07 +02004553 return cfgerr;
4554}
4555
Thierry Fournier383085f2013-01-24 14:15:43 +01004556/* Make sure openssl opens /dev/urandom before the chroot. The work is only
4557 * done once. Zero is returned if the operation fails. No error is returned
4558 * if the random is said as not implemented, because we expect that openssl
4559 * will use another method once needed.
4560 */
4561static int ssl_initialize_random()
4562{
4563 unsigned char random;
4564 static int random_initialized = 0;
4565
4566 if (!random_initialized && RAND_bytes(&random, 1) != 0)
4567 random_initialized = 1;
4568
4569 return random_initialized;
4570}
4571
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004572/* release ssl bind conf */
4573void ssl_sock_free_ssl_conf(struct ssl_bind_conf *conf)
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004574{
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004575 if (conf) {
Bernard Spil13c53f82018-02-15 13:34:58 +01004576#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004577 free(conf->npn_str);
4578 conf->npn_str = NULL;
4579#endif
4580#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
4581 free(conf->alpn_str);
4582 conf->alpn_str = NULL;
4583#endif
4584 free(conf->ca_file);
4585 conf->ca_file = NULL;
Emmanuel Hocdet842e94e2019-12-16 16:39:17 +01004586 free(conf->ca_verify_file);
4587 conf->ca_verify_file = NULL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004588 free(conf->crl_file);
4589 conf->crl_file = NULL;
4590 free(conf->ciphers);
4591 conf->ciphers = NULL;
Emmanuel Hocdet839af572019-05-14 16:27:35 +02004592#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02004593 free(conf->ciphersuites);
4594 conf->ciphersuites = NULL;
4595#endif
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004596 free(conf->curves);
4597 conf->curves = NULL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004598 free(conf->ecdhe);
4599 conf->ecdhe = NULL;
4600 }
4601}
4602
Willy Tarreaubbc91962019-10-16 16:42:19 +02004603/* Returns a set of ERR_* flags possibly with an error in <err>. */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004604int ssl_sock_load_cert_list_file(char *file, struct bind_conf *bind_conf, struct proxy *curproxy, char **err)
4605{
4606 char thisline[CRT_LINESIZE];
4607 char path[MAXPATHLEN+1];
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004608 FILE *f;
yanbzhu1b04e5b2015-12-02 13:54:14 -05004609 struct stat buf;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004610 int linenum = 0;
4611 int cfgerr = 0;
William Lallemande3af8fb2019-10-08 11:36:53 +02004612 struct ckch_store *ckchs;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004613
Willy Tarreauad1731d2013-04-02 17:35:58 +02004614 if ((f = fopen(file, "r")) == NULL) {
4615 memprintf(err, "cannot open file '%s' : %s", file, strerror(errno));
Willy Tarreaubbc91962019-10-16 16:42:19 +02004616 return ERR_ALERT | ERR_FATAL;
Willy Tarreauad1731d2013-04-02 17:35:58 +02004617 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004618
4619 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004620 int arg, newarg, cur_arg, i, ssl_b = 0, ssl_e = 0;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004621 char *end;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004622 char *args[MAX_CRT_ARGS + 1];
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004623 char *line = thisline;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004624 char *crt_path;
4625 struct ssl_bind_conf *ssl_conf = NULL;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004626
4627 linenum++;
4628 end = line + strlen(line);
4629 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
4630 /* Check if we reached the limit and the last char is not \n.
4631 * Watch out for the last line without the terminating '\n'!
4632 */
Willy Tarreauad1731d2013-04-02 17:35:58 +02004633 memprintf(err, "line %d too long in file '%s', limit is %d characters",
4634 linenum, file, (int)sizeof(thisline)-1);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004635 cfgerr |= ERR_ALERT | ERR_FATAL;
Willy Tarreauad1731d2013-04-02 17:35:58 +02004636 break;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004637 }
4638
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004639 arg = 0;
Emeric Brun50bcecc2013-04-22 13:05:23 +02004640 newarg = 1;
4641 while (*line) {
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004642 if (*line == '#' || *line == '\n' || *line == '\r') {
4643 /* end of string, end of loop */
4644 *line = 0;
4645 break;
Willy Tarreauded15b72020-02-25 07:51:59 +01004646 } else if (isspace((unsigned char)*line)) {
Emeric Brun50bcecc2013-04-22 13:05:23 +02004647 newarg = 1;
4648 *line = 0;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004649 } else if (*line == '[') {
4650 if (ssl_b) {
4651 memprintf(err, "too many '[' on line %d in file '%s'.", linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004652 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004653 break;
4654 }
4655 if (!arg) {
4656 memprintf(err, "file must start with a cert on line %d in file '%s'", linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004657 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004658 break;
4659 }
4660 ssl_b = arg;
4661 newarg = 1;
4662 *line = 0;
4663 } else if (*line == ']') {
4664 if (ssl_e) {
4665 memprintf(err, "too many ']' on line %d in file '%s'.", linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004666 cfgerr |= ERR_ALERT | ERR_FATAL;
Emeric Brun50bcecc2013-04-22 13:05:23 +02004667 break;
4668 }
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004669 if (!ssl_b) {
4670 memprintf(err, "missing '[' in line %d in file '%s'.", linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004671 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004672 break;
4673 }
4674 ssl_e = arg;
4675 newarg = 1;
4676 *line = 0;
4677 } else if (newarg) {
4678 if (arg == MAX_CRT_ARGS) {
4679 memprintf(err, "too many args on line %d in file '%s'.", linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004680 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004681 break;
4682 }
Emeric Brun50bcecc2013-04-22 13:05:23 +02004683 newarg = 0;
4684 args[arg++] = line;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004685 }
Emeric Brun50bcecc2013-04-22 13:05:23 +02004686 line++;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004687 }
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02004688 if (cfgerr)
4689 break;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004690 args[arg++] = line;
Willy Tarreauad1731d2013-04-02 17:35:58 +02004691
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004692 /* empty line */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004693 if (!*args[0])
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004694 continue;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004695
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004696 crt_path = args[0];
4697 if (*crt_path != '/' && global_ssl.crt_base) {
4698 if ((strlen(global_ssl.crt_base) + 1 + strlen(crt_path)) > MAXPATHLEN) {
4699 memprintf(err, "'%s' : path too long on line %d in file '%s'",
4700 crt_path, linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004701 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004702 break;
4703 }
4704 snprintf(path, sizeof(path), "%s/%s", global_ssl.crt_base, crt_path);
4705 crt_path = path;
4706 }
4707
4708 ssl_conf = calloc(1, sizeof *ssl_conf);
4709 cur_arg = ssl_b ? ssl_b : 1;
4710 while (cur_arg < ssl_e) {
4711 newarg = 0;
4712 for (i = 0; ssl_bind_kws[i].kw != NULL; i++) {
4713 if (strcmp(ssl_bind_kws[i].kw, args[cur_arg]) == 0) {
4714 newarg = 1;
Willy Tarreaubbc91962019-10-16 16:42:19 +02004715 cfgerr |= ssl_bind_kws[i].parse(args, cur_arg, curproxy, ssl_conf, err);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004716 if (cur_arg + 1 + ssl_bind_kws[i].skip > ssl_e) {
4717 memprintf(err, "ssl args out of '[]' for %s on line %d in file '%s'",
4718 args[cur_arg], linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004719 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004720 }
4721 cur_arg += 1 + ssl_bind_kws[i].skip;
4722 break;
4723 }
4724 }
4725 if (!cfgerr && !newarg) {
4726 memprintf(err, "unknown ssl keyword %s on line %d in file '%s'.",
4727 args[cur_arg], linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004728 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004729 break;
4730 }
4731 }
Willy Tarreaubbc91962019-10-16 16:42:19 +02004732
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004733 if (cfgerr) {
4734 ssl_sock_free_ssl_conf(ssl_conf);
4735 free(ssl_conf);
4736 ssl_conf = NULL;
4737 break;
4738 }
4739
William Lallemande3af8fb2019-10-08 11:36:53 +02004740 if ((ckchs = ckchs_lookup(crt_path)) == NULL) {
William Lallemandeed4bf22019-10-10 11:38:13 +02004741 if (stat(crt_path, &buf) == 0)
William Lallemande3af8fb2019-10-08 11:36:53 +02004742 ckchs = ckchs_load_cert_file(crt_path, 0, err);
Emmanuel Hocdet1503e052019-07-31 18:30:33 +02004743 else
William Lallemande3af8fb2019-10-08 11:36:53 +02004744 ckchs = ckchs_load_cert_file(crt_path, 1, err);
yanbzhu1b04e5b2015-12-02 13:54:14 -05004745 }
4746
Willy Tarreau8c5414a2019-10-16 17:06:25 +02004747 if (!ckchs)
Willy Tarreaubbc91962019-10-16 16:42:19 +02004748 cfgerr |= ERR_ALERT | ERR_FATAL;
Willy Tarreau8c5414a2019-10-16 17:06:25 +02004749 else
4750 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 +02004751
Willy Tarreauad1731d2013-04-02 17:35:58 +02004752 if (cfgerr) {
4753 memprintf(err, "error processing line %d in file '%s' : %s", linenum, file, *err);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004754 break;
Willy Tarreauad1731d2013-04-02 17:35:58 +02004755 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004756 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004757 fclose(f);
4758 return cfgerr;
4759}
4760
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004761/* Create an initial CTX used to start the SSL connection before switchctx */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004762static int
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004763ssl_sock_initial_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02004764{
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004765 SSL_CTX *ctx = NULL;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004766 long options =
Emeric Brunfc0421f2012-09-07 17:30:07 +02004767 SSL_OP_ALL | /* all known workarounds for bugs */
4768 SSL_OP_NO_SSLv2 |
4769 SSL_OP_NO_COMPRESSION |
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02004770 SSL_OP_SINGLE_DH_USE |
Emeric Brun2b58d042012-09-20 17:10:03 +02004771 SSL_OP_SINGLE_ECDH_USE |
Emeric Brun3c4bc6e2012-10-04 18:44:19 +02004772 SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION |
Lukas Tribus926594f2018-05-18 17:55:57 +02004773 SSL_OP_PRIORITIZE_CHACHA |
Emeric Brun3c4bc6e2012-10-04 18:44:19 +02004774 SSL_OP_CIPHER_SERVER_PREFERENCE;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004775 long mode =
Emeric Brunfc0421f2012-09-07 17:30:07 +02004776 SSL_MODE_ENABLE_PARTIAL_WRITE |
4777 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
Willy Tarreau396a1862014-11-13 14:06:52 +01004778 SSL_MODE_RELEASE_BUFFERS |
4779 SSL_MODE_SMALL_BUFFERS;
Emmanuel Hocdet43664762017-08-09 18:26:20 +02004780 struct tls_version_filter *conf_ssl_methods = &bind_conf->ssl_conf.ssl_methods;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004781 int i, min, max, hole;
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004782 int flags = MC_SSL_O_ALL;
4783 int cfgerr = 0;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004784
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004785 ctx = SSL_CTX_new(SSLv23_server_method());
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004786 bind_conf->initial_ctx = ctx;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004787
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004788 if (conf_ssl_methods->flags && (conf_ssl_methods->min || conf_ssl_methods->max))
Christopher Faulet767a84b2017-11-24 16:50:31 +01004789 ha_warning("Proxy '%s': no-sslv3/no-tlsv1x are ignored for bind '%s' at [%s:%d]. "
4790 "Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
4791 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004792 else
4793 flags = conf_ssl_methods->flags;
4794
Emmanuel Hocdetbd695fe2017-05-15 15:53:41 +02004795 min = conf_ssl_methods->min;
4796 max = conf_ssl_methods->max;
4797 /* start with TLSv10 to remove SSLv3 per default */
4798 if (!min && (!max || max >= CONF_TLSV10))
4799 min = CONF_TLSV10;
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004800 /* Real min and max should be determinate with configuration and openssl's capabilities */
Emmanuel Hocdetbd695fe2017-05-15 15:53:41 +02004801 if (min)
4802 flags |= (methodVersions[min].flag - 1);
4803 if (max)
4804 flags |= ~((methodVersions[max].flag << 1) - 1);
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004805 /* find min, max and holes */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004806 min = max = CONF_TLSV_NONE;
4807 hole = 0;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004808 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004809 /* version is in openssl && version not disable in configuration */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004810 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004811 if (min) {
4812 if (hole) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004813 ha_warning("Proxy '%s': SSL/TLS versions range not contiguous for bind '%s' at [%s:%d]. "
4814 "Hole find for %s. Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
4815 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line,
4816 methodVersions[hole].name);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004817 hole = 0;
4818 }
4819 max = i;
4820 }
4821 else {
4822 min = max = i;
4823 }
4824 }
4825 else {
4826 if (min)
4827 hole = i;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004828 }
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004829 if (!min) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004830 ha_alert("Proxy '%s': all SSL/TLS versions are disabled for bind '%s' at [%s:%d].\n",
4831 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004832 cfgerr += 1;
4833 }
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02004834 /* save real min/max in bind_conf */
4835 conf_ssl_methods->min = min;
4836 conf_ssl_methods->max = max;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004837
Willy Tarreau9a1ab082019-05-09 13:26:41 +02004838#if (HA_OPENSSL_VERSION_NUMBER < 0x1010000fL)
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004839 /* Keep force-xxx implementation as it is in older haproxy. It's a
Joseph Herlant017b3da2018-11-15 09:07:59 -08004840 precautionary measure to avoid any surprise with older openssl version. */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004841 if (min == max)
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004842 methodVersions[min].ctx_set_version(ctx, SET_SERVER);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004843 else
4844 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
4845 if (flags & methodVersions[i].flag)
4846 options |= methodVersions[i].option;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004847#else /* openssl >= 1.1.0 */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004848 /* set the max_version is required to cap TLS version or activate new TLS (v1.3) */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004849 methodVersions[min].ctx_set_version(ctx, SET_MIN);
4850 methodVersions[max].ctx_set_version(ctx, SET_MAX);
Emeric Brunfa5c5c82017-04-28 16:19:51 +02004851#endif
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004852
4853 if (bind_conf->ssl_options & BC_SSL_O_NO_TLS_TICKETS)
4854 options |= SSL_OP_NO_TICKET;
4855 if (bind_conf->ssl_options & BC_SSL_O_PREF_CLIE_CIPH)
4856 options &= ~SSL_OP_CIPHER_SERVER_PREFERENCE;
Dirkjan Bussink526894f2019-01-21 09:35:03 -08004857
4858#ifdef SSL_OP_NO_RENEGOTIATION
4859 options |= SSL_OP_NO_RENEGOTIATION;
4860#endif
4861
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004862 SSL_CTX_set_options(ctx, options);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004863
Willy Tarreau5db847a2019-05-09 14:13:35 +02004864#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004865 if (global_ssl.async)
4866 mode |= SSL_MODE_ASYNC;
4867#endif
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004868 SSL_CTX_set_mode(ctx, mode);
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004869 if (global_ssl.life_time)
4870 SSL_CTX_set_timeout(ctx, global_ssl.life_time);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004871
4872#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
4873#ifdef OPENSSL_IS_BORINGSSL
4874 SSL_CTX_set_select_certificate_cb(ctx, ssl_sock_switchctx_cbk);
4875 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_err_cbk);
Ilya Shipitsine9ff8992020-01-19 12:20:14 +05004876#elif defined(SSL_OP_NO_ANTI_REPLAY)
Olivier Houchard545989f2019-12-17 15:39:54 +01004877 if (bind_conf->ssl_conf.early_data)
Olivier Houchard51088ce2019-01-02 18:46:41 +01004878 SSL_CTX_set_options(ctx, SSL_OP_NO_ANTI_REPLAY);
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02004879 SSL_CTX_set_client_hello_cb(ctx, ssl_sock_switchctx_cbk, NULL);
4880 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_err_cbk);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004881#else
4882 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_cbk);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004883#endif
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02004884 SSL_CTX_set_tlsext_servername_arg(ctx, bind_conf);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004885#endif
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004886 return cfgerr;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004887}
4888
William Lallemand4f45bb92017-10-30 20:08:51 +01004889
4890static inline void sh_ssl_sess_free_blocks(struct shared_block *first, struct shared_block *block)
4891{
4892 if (first == block) {
4893 struct sh_ssl_sess_hdr *sh_ssl_sess = (struct sh_ssl_sess_hdr *)first->data;
4894 if (first->len > 0)
4895 sh_ssl_sess_tree_delete(sh_ssl_sess);
4896 }
4897}
4898
4899/* return first block from sh_ssl_sess */
4900static inline struct shared_block *sh_ssl_sess_first_block(struct sh_ssl_sess_hdr *sh_ssl_sess)
4901{
4902 return (struct shared_block *)((unsigned char *)sh_ssl_sess - ((struct shared_block *)NULL)->data);
4903
4904}
4905
4906/* store a session into the cache
4907 * s_id : session id padded with zero to SSL_MAX_SSL_SESSION_ID_LENGTH
4908 * data: asn1 encoded session
4909 * data_len: asn1 encoded session length
4910 * Returns 1 id session was stored (else 0)
4911 */
4912static int sh_ssl_sess_store(unsigned char *s_id, unsigned char *data, int data_len)
4913{
4914 struct shared_block *first;
4915 struct sh_ssl_sess_hdr *sh_ssl_sess, *oldsh_ssl_sess;
4916
Frédéric Lécaille0bec8072018-10-22 17:55:57 +02004917 first = shctx_row_reserve_hot(ssl_shctx, NULL, data_len + sizeof(struct sh_ssl_sess_hdr));
William Lallemand4f45bb92017-10-30 20:08:51 +01004918 if (!first) {
4919 /* Could not retrieve enough free blocks to store that session */
4920 return 0;
4921 }
4922
4923 /* STORE the key in the first elem */
4924 sh_ssl_sess = (struct sh_ssl_sess_hdr *)first->data;
4925 memcpy(sh_ssl_sess->key_data, s_id, SSL_MAX_SSL_SESSION_ID_LENGTH);
4926 first->len = sizeof(struct sh_ssl_sess_hdr);
4927
4928 /* it returns the already existing node
4929 or current node if none, never returns null */
4930 oldsh_ssl_sess = sh_ssl_sess_tree_insert(sh_ssl_sess);
4931 if (oldsh_ssl_sess != sh_ssl_sess) {
4932 /* NOTE: Row couldn't be in use because we lock read & write function */
4933 /* release the reserved row */
4934 shctx_row_dec_hot(ssl_shctx, first);
4935 /* replace the previous session already in the tree */
4936 sh_ssl_sess = oldsh_ssl_sess;
4937 /* ignore the previous session data, only use the header */
4938 first = sh_ssl_sess_first_block(sh_ssl_sess);
4939 shctx_row_inc_hot(ssl_shctx, first);
4940 first->len = sizeof(struct sh_ssl_sess_hdr);
4941 }
4942
Frédéric Lécaille0bec8072018-10-22 17:55:57 +02004943 if (shctx_row_data_append(ssl_shctx, first, NULL, data, data_len) < 0) {
William Lallemand99b90af2018-01-03 19:15:51 +01004944 shctx_row_dec_hot(ssl_shctx, first);
William Lallemand4f45bb92017-10-30 20:08:51 +01004945 return 0;
William Lallemand99b90af2018-01-03 19:15:51 +01004946 }
4947
4948 shctx_row_dec_hot(ssl_shctx, first);
William Lallemand4f45bb92017-10-30 20:08:51 +01004949
4950 return 1;
4951}
William Lallemanded0b5ad2017-10-30 19:36:36 +01004952
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004953/* SSL callback used when a new session is created while connecting to a server */
4954static int ssl_sess_new_srv_cb(SSL *ssl, SSL_SESSION *sess)
4955{
Thierry FOURNIER28962c92018-06-17 21:37:05 +02004956 struct connection *conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Olivier Houcharde6060c52017-11-16 17:42:52 +01004957 struct server *s;
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004958
Willy Tarreau07d94e42018-09-20 10:57:52 +02004959 s = __objt_server(conn->target);
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004960
Olivier Houcharde6060c52017-11-16 17:42:52 +01004961 if (!(s->ssl_ctx.options & SRV_SSL_O_NO_REUSE)) {
4962 int len;
4963 unsigned char *ptr;
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004964
Olivier Houcharde6060c52017-11-16 17:42:52 +01004965 len = i2d_SSL_SESSION(sess, NULL);
4966 if (s->ssl_ctx.reused_sess[tid].ptr && s->ssl_ctx.reused_sess[tid].allocated_size >= len) {
4967 ptr = s->ssl_ctx.reused_sess[tid].ptr;
4968 } else {
4969 free(s->ssl_ctx.reused_sess[tid].ptr);
4970 ptr = s->ssl_ctx.reused_sess[tid].ptr = malloc(len);
4971 s->ssl_ctx.reused_sess[tid].allocated_size = len;
4972 }
4973 if (s->ssl_ctx.reused_sess[tid].ptr) {
4974 s->ssl_ctx.reused_sess[tid].size = i2d_SSL_SESSION(sess,
4975 &ptr);
4976 }
4977 } else {
4978 free(s->ssl_ctx.reused_sess[tid].ptr);
4979 s->ssl_ctx.reused_sess[tid].ptr = NULL;
4980 }
4981
4982 return 0;
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004983}
4984
Olivier Houcharde6060c52017-11-16 17:42:52 +01004985
William Lallemanded0b5ad2017-10-30 19:36:36 +01004986/* SSL callback used on new session creation */
William Lallemand4f45bb92017-10-30 20:08:51 +01004987int sh_ssl_sess_new_cb(SSL *ssl, SSL_SESSION *sess)
William Lallemanded0b5ad2017-10-30 19:36:36 +01004988{
4989 unsigned char encsess[SHSESS_MAX_DATA_LEN]; /* encoded session */
4990 unsigned char encid[SSL_MAX_SSL_SESSION_ID_LENGTH]; /* encoded id */
4991 unsigned char *p;
4992 int data_len;
Emeric Bruneb469652019-10-08 18:27:37 +02004993 unsigned int sid_length;
William Lallemanded0b5ad2017-10-30 19:36:36 +01004994 const unsigned char *sid_data;
William Lallemanded0b5ad2017-10-30 19:36:36 +01004995
4996 /* Session id is already stored in to key and session id is known
4997 * so we dont store it to keep size.
Emeric Bruneb469652019-10-08 18:27:37 +02004998 * note: SSL_SESSION_set1_id is using
4999 * a memcpy so we need to use a different pointer
5000 * than sid_data or sid_ctx_data to avoid valgrind
5001 * complaining.
William Lallemanded0b5ad2017-10-30 19:36:36 +01005002 */
5003
5004 sid_data = SSL_SESSION_get_id(sess, &sid_length);
Emeric Bruneb469652019-10-08 18:27:37 +02005005
5006 /* copy value in an other buffer */
5007 memcpy(encid, sid_data, sid_length);
5008
5009 /* pad with 0 */
5010 if (sid_length < SSL_MAX_SSL_SESSION_ID_LENGTH)
5011 memset(encid + sid_length, 0, SSL_MAX_SSL_SESSION_ID_LENGTH-sid_length);
5012
5013 /* force length to zero to avoid ASN1 encoding */
5014 SSL_SESSION_set1_id(sess, encid, 0);
5015
5016 /* force length to zero to avoid ASN1 encoding */
5017 SSL_SESSION_set1_id_context(sess, (const unsigned char *)SHCTX_APPNAME, 0);
William Lallemanded0b5ad2017-10-30 19:36:36 +01005018
5019 /* check if buffer is large enough for the ASN1 encoded session */
5020 data_len = i2d_SSL_SESSION(sess, NULL);
5021 if (data_len > SHSESS_MAX_DATA_LEN)
5022 goto err;
5023
5024 p = encsess;
5025
5026 /* process ASN1 session encoding before the lock */
5027 i2d_SSL_SESSION(sess, &p);
5028
William Lallemanded0b5ad2017-10-30 19:36:36 +01005029
William Lallemanda3c77cf2017-10-30 23:44:40 +01005030 shctx_lock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01005031 /* store to cache */
William Lallemand4f45bb92017-10-30 20:08:51 +01005032 sh_ssl_sess_store(encid, encsess, data_len);
William Lallemanda3c77cf2017-10-30 23:44:40 +01005033 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01005034err:
5035 /* reset original length values */
Emeric Bruneb469652019-10-08 18:27:37 +02005036 SSL_SESSION_set1_id(sess, encid, sid_length);
5037 SSL_SESSION_set1_id_context(sess, (const unsigned char *)SHCTX_APPNAME, strlen(SHCTX_APPNAME));
William Lallemanded0b5ad2017-10-30 19:36:36 +01005038
5039 return 0; /* do not increment session reference count */
5040}
5041
5042/* SSL callback used on lookup an existing session cause none found in internal cache */
William Lallemand4f45bb92017-10-30 20:08:51 +01005043SSL_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 +01005044{
William Lallemand4f45bb92017-10-30 20:08:51 +01005045 struct sh_ssl_sess_hdr *sh_ssl_sess;
William Lallemanded0b5ad2017-10-30 19:36:36 +01005046 unsigned char data[SHSESS_MAX_DATA_LEN], *p;
5047 unsigned char tmpkey[SSL_MAX_SSL_SESSION_ID_LENGTH];
William Lallemanded0b5ad2017-10-30 19:36:36 +01005048 SSL_SESSION *sess;
William Lallemand4f45bb92017-10-30 20:08:51 +01005049 struct shared_block *first;
William Lallemanded0b5ad2017-10-30 19:36:36 +01005050
5051 global.shctx_lookups++;
5052
5053 /* allow the session to be freed automatically by openssl */
5054 *do_copy = 0;
5055
5056 /* tree key is zeros padded sessionid */
5057 if (key_len < SSL_MAX_SSL_SESSION_ID_LENGTH) {
5058 memcpy(tmpkey, key, key_len);
5059 memset(tmpkey + key_len, 0, SSL_MAX_SSL_SESSION_ID_LENGTH - key_len);
5060 key = tmpkey;
5061 }
5062
5063 /* lock cache */
William Lallemanda3c77cf2017-10-30 23:44:40 +01005064 shctx_lock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01005065
5066 /* lookup for session */
William Lallemand4f45bb92017-10-30 20:08:51 +01005067 sh_ssl_sess = sh_ssl_sess_tree_lookup(key);
5068 if (!sh_ssl_sess) {
William Lallemanded0b5ad2017-10-30 19:36:36 +01005069 /* no session found: unlock cache and exit */
William Lallemanda3c77cf2017-10-30 23:44:40 +01005070 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01005071 global.shctx_misses++;
5072 return NULL;
5073 }
5074
William Lallemand4f45bb92017-10-30 20:08:51 +01005075 /* sh_ssl_sess (shared_block->data) is at the end of shared_block */
5076 first = sh_ssl_sess_first_block(sh_ssl_sess);
William Lallemanded0b5ad2017-10-30 19:36:36 +01005077
William Lallemand4f45bb92017-10-30 20:08:51 +01005078 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 +01005079
William Lallemanda3c77cf2017-10-30 23:44:40 +01005080 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01005081
5082 /* decode ASN1 session */
5083 p = data;
William Lallemand4f45bb92017-10-30 20:08:51 +01005084 sess = d2i_SSL_SESSION(NULL, (const unsigned char **)&p, first->len-sizeof(struct sh_ssl_sess_hdr));
William Lallemanded0b5ad2017-10-30 19:36:36 +01005085 /* Reset session id and session id contenxt */
5086 if (sess) {
5087 SSL_SESSION_set1_id(sess, key, key_len);
5088 SSL_SESSION_set1_id_context(sess, (const unsigned char *)SHCTX_APPNAME, strlen(SHCTX_APPNAME));
5089 }
5090
5091 return sess;
5092}
5093
William Lallemand4f45bb92017-10-30 20:08:51 +01005094
William Lallemanded0b5ad2017-10-30 19:36:36 +01005095/* SSL callback used to signal session is no more used in internal cache */
William Lallemand4f45bb92017-10-30 20:08:51 +01005096void sh_ssl_sess_remove_cb(SSL_CTX *ctx, SSL_SESSION *sess)
William Lallemanded0b5ad2017-10-30 19:36:36 +01005097{
William Lallemand4f45bb92017-10-30 20:08:51 +01005098 struct sh_ssl_sess_hdr *sh_ssl_sess;
William Lallemanded0b5ad2017-10-30 19:36:36 +01005099 unsigned char tmpkey[SSL_MAX_SSL_SESSION_ID_LENGTH];
5100 unsigned int sid_length;
5101 const unsigned char *sid_data;
5102 (void)ctx;
5103
5104 sid_data = SSL_SESSION_get_id(sess, &sid_length);
5105 /* tree key is zeros padded sessionid */
5106 if (sid_length < SSL_MAX_SSL_SESSION_ID_LENGTH) {
5107 memcpy(tmpkey, sid_data, sid_length);
5108 memset(tmpkey+sid_length, 0, SSL_MAX_SSL_SESSION_ID_LENGTH - sid_length);
5109 sid_data = tmpkey;
5110 }
5111
William Lallemanda3c77cf2017-10-30 23:44:40 +01005112 shctx_lock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01005113
5114 /* lookup for session */
William Lallemand4f45bb92017-10-30 20:08:51 +01005115 sh_ssl_sess = sh_ssl_sess_tree_lookup(sid_data);
5116 if (sh_ssl_sess) {
William Lallemanded0b5ad2017-10-30 19:36:36 +01005117 /* free session */
William Lallemand4f45bb92017-10-30 20:08:51 +01005118 sh_ssl_sess_tree_delete(sh_ssl_sess);
William Lallemanded0b5ad2017-10-30 19:36:36 +01005119 }
5120
5121 /* unlock cache */
William Lallemanda3c77cf2017-10-30 23:44:40 +01005122 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01005123}
5124
5125/* Set session cache mode to server and disable openssl internal cache.
5126 * Set shared cache callbacks on an ssl context.
5127 * Shared context MUST be firstly initialized */
William Lallemand4f45bb92017-10-30 20:08:51 +01005128void ssl_set_shctx(SSL_CTX *ctx)
William Lallemanded0b5ad2017-10-30 19:36:36 +01005129{
5130 SSL_CTX_set_session_id_context(ctx, (const unsigned char *)SHCTX_APPNAME, strlen(SHCTX_APPNAME));
5131
5132 if (!ssl_shctx) {
5133 SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF);
5134 return;
5135 }
5136
5137 SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_SERVER |
5138 SSL_SESS_CACHE_NO_INTERNAL |
5139 SSL_SESS_CACHE_NO_AUTO_CLEAR);
5140
5141 /* Set callbacks */
William Lallemand4f45bb92017-10-30 20:08:51 +01005142 SSL_CTX_sess_set_new_cb(ctx, sh_ssl_sess_new_cb);
5143 SSL_CTX_sess_set_get_cb(ctx, sh_ssl_sess_get_cb);
5144 SSL_CTX_sess_set_remove_cb(ctx, sh_ssl_sess_remove_cb);
William Lallemanded0b5ad2017-10-30 19:36:36 +01005145}
5146
William Lallemand8b453912019-11-21 15:48:10 +01005147/*
5148 * This function applies the SSL configuration on a SSL_CTX
5149 * It returns an error code and fills the <err> buffer
5150 */
5151int 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 +01005152{
5153 struct proxy *curproxy = bind_conf->frontend;
5154 int cfgerr = 0;
5155 int verify = SSL_VERIFY_NONE;
Willy Tarreau5d4cafb2018-01-04 18:55:19 +01005156 struct ssl_bind_conf __maybe_unused *ssl_conf_cur;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005157 const char *conf_ciphers;
Emmanuel Hocdet839af572019-05-14 16:27:35 +02005158#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02005159 const char *conf_ciphersuites;
5160#endif
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01005161 const char *conf_curves = NULL;
Emeric Brunfc0421f2012-09-07 17:30:07 +02005162
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02005163 if (ssl_conf) {
5164 struct tls_version_filter *conf_ssl_methods = &ssl_conf->ssl_methods;
5165 int i, min, max;
5166 int flags = MC_SSL_O_ALL;
5167
5168 /* Real min and max should be determinate with configuration and openssl's capabilities */
Emmanuel Hocdet43664762017-08-09 18:26:20 +02005169 min = conf_ssl_methods->min ? conf_ssl_methods->min : bind_conf->ssl_conf.ssl_methods.min;
5170 max = conf_ssl_methods->max ? conf_ssl_methods->max : bind_conf->ssl_conf.ssl_methods.max;
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02005171 if (min)
5172 flags |= (methodVersions[min].flag - 1);
5173 if (max)
5174 flags |= ~((methodVersions[max].flag << 1) - 1);
5175 min = max = CONF_TLSV_NONE;
5176 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
5177 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
5178 if (min)
5179 max = i;
5180 else
5181 min = max = i;
5182 }
5183 /* save real min/max */
5184 conf_ssl_methods->min = min;
5185 conf_ssl_methods->max = max;
5186 if (!min) {
Tim Duesterhus93128532019-11-23 23:45:10 +01005187 memprintf(err, "%sProxy '%s': all SSL/TLS versions are disabled for bind '%s' at [%s:%d].\n",
5188 err && *err ? *err : "", bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
William Lallemand8b453912019-11-21 15:48:10 +01005189 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02005190 }
5191 }
5192
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005193 switch ((ssl_conf && ssl_conf->verify) ? ssl_conf->verify : bind_conf->ssl_conf.verify) {
Emeric Brun850efd52014-01-29 12:24:34 +01005194 case SSL_SOCK_VERIFY_NONE:
5195 verify = SSL_VERIFY_NONE;
5196 break;
5197 case SSL_SOCK_VERIFY_OPTIONAL:
5198 verify = SSL_VERIFY_PEER;
5199 break;
5200 case SSL_SOCK_VERIFY_REQUIRED:
5201 verify = SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
5202 break;
5203 }
5204 SSL_CTX_set_verify(ctx, verify, ssl_sock_bind_verifycbk);
5205 if (verify & SSL_VERIFY_PEER) {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005206 char *ca_file = (ssl_conf && ssl_conf->ca_file) ? ssl_conf->ca_file : bind_conf->ssl_conf.ca_file;
Emmanuel Hocdet842e94e2019-12-16 16:39:17 +01005207 char *ca_verify_file = (ssl_conf && ssl_conf->ca_verify_file) ? ssl_conf->ca_verify_file : bind_conf->ssl_conf.ca_verify_file;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005208 char *crl_file = (ssl_conf && ssl_conf->crl_file) ? ssl_conf->crl_file : bind_conf->ssl_conf.crl_file;
Emmanuel Hocdet842e94e2019-12-16 16:39:17 +01005209 if (ca_file || ca_verify_file) {
Emmanuel Hocdetd4f9a602019-10-24 11:32:47 +02005210 /* set CAfile to verify */
Emmanuel Hocdet842e94e2019-12-16 16:39:17 +01005211 if (ca_file && !ssl_set_verify_locations_file(ctx, ca_file)) {
Emmanuel Hocdetd4f9a602019-10-24 11:32:47 +02005212 memprintf(err, "%sProxy '%s': unable to set CA file '%s' for bind '%s' at [%s:%d].\n",
Tim Duesterhus93128532019-11-23 23:45:10 +01005213 err && *err ? *err : "", curproxy->id, ca_file, bind_conf->arg, bind_conf->file, bind_conf->line);
William Lallemand8b453912019-11-21 15:48:10 +01005214 cfgerr |= ERR_ALERT | ERR_FATAL;
Emeric Brund94b3fe2012-09-20 18:23:56 +02005215 }
Emmanuel Hocdet842e94e2019-12-16 16:39:17 +01005216 if (ca_verify_file && !ssl_set_verify_locations_file(ctx, ca_verify_file)) {
5217 memprintf(err, "%sProxy '%s': unable to set CA-no-names file '%s' for bind '%s' at [%s:%d].\n",
5218 err && *err ? *err : "", curproxy->id, ca_verify_file, bind_conf->arg, bind_conf->file, bind_conf->line);
5219 cfgerr |= ERR_ALERT | ERR_FATAL;
5220 }
5221 if (ca_file && !((ssl_conf && ssl_conf->no_ca_names) || bind_conf->ssl_conf.no_ca_names)) {
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02005222 /* set CA names for client cert request, function returns void */
Emmanuel Hocdet129d3282019-10-24 18:08:51 +02005223 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 +02005224 }
Emeric Brund94b3fe2012-09-20 18:23:56 +02005225 }
Emeric Brun850efd52014-01-29 12:24:34 +01005226 else {
Tim Duesterhus93128532019-11-23 23:45:10 +01005227 memprintf(err, "%sProxy '%s': verify is enabled but no CA file specified for bind '%s' at [%s:%d].\n",
5228 err && *err ? *err : "", curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
William Lallemand8b453912019-11-21 15:48:10 +01005229 cfgerr |= ERR_ALERT | ERR_FATAL;
Emeric Brun850efd52014-01-29 12:24:34 +01005230 }
Emeric Brun051cdab2012-10-02 19:25:50 +02005231#ifdef X509_V_FLAG_CRL_CHECK
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005232 if (crl_file) {
Emeric Brund94b3fe2012-09-20 18:23:56 +02005233 X509_STORE *store = SSL_CTX_get_cert_store(ctx);
5234
Emmanuel Hocdetb270e812019-11-21 19:09:31 +01005235 if (!ssl_set_cert_crl_file(store, crl_file)) {
Tim Duesterhus93128532019-11-23 23:45:10 +01005236 memprintf(err, "%sProxy '%s': unable to configure CRL file '%s' for bind '%s' at [%s:%d].\n",
5237 err && *err ? *err : "", curproxy->id, crl_file, bind_conf->arg, bind_conf->file, bind_conf->line);
William Lallemand8b453912019-11-21 15:48:10 +01005238 cfgerr |= ERR_ALERT | ERR_FATAL;
Emeric Brund94b3fe2012-09-20 18:23:56 +02005239 }
Emeric Brun561e5742012-10-02 15:20:55 +02005240 else {
5241 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
5242 }
Emeric Brund94b3fe2012-09-20 18:23:56 +02005243 }
Emeric Brun051cdab2012-10-02 19:25:50 +02005244#endif
Emeric Brun644cde02012-12-14 11:21:13 +01005245 ERR_clear_error();
Emeric Brund94b3fe2012-09-20 18:23:56 +02005246 }
Nenad Merdanovic05552d42015-02-27 19:56:49 +01005247#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
Nenad Merdanovic146defa2015-05-09 08:46:00 +02005248 if(bind_conf->keys_ref) {
Nenad Merdanovic05552d42015-02-27 19:56:49 +01005249 if (!SSL_CTX_set_tlsext_ticket_key_cb(ctx, ssl_tlsext_ticket_key_cb)) {
Tim Duesterhus93128532019-11-23 23:45:10 +01005250 memprintf(err, "%sProxy '%s': unable to set callback for TLS ticket validation for bind '%s' at [%s:%d].\n",
5251 err && *err ? *err : "", curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
William Lallemand8b453912019-11-21 15:48:10 +01005252 cfgerr |= ERR_ALERT | ERR_FATAL;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01005253 }
5254 }
5255#endif
5256
William Lallemand4f45bb92017-10-30 20:08:51 +01005257 ssl_set_shctx(ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005258 conf_ciphers = (ssl_conf && ssl_conf->ciphers) ? ssl_conf->ciphers : bind_conf->ssl_conf.ciphers;
5259 if (conf_ciphers &&
5260 !SSL_CTX_set_cipher_list(ctx, conf_ciphers)) {
Tim Duesterhus93128532019-11-23 23:45:10 +01005261 memprintf(err, "%sProxy '%s': unable to set SSL cipher list to '%s' for bind '%s' at [%s:%d].\n",
5262 err && *err ? *err : "", curproxy->id, conf_ciphers, bind_conf->arg, bind_conf->file, bind_conf->line);
William Lallemand8b453912019-11-21 15:48:10 +01005263 cfgerr |= ERR_ALERT | ERR_FATAL;
Emeric Brunfc0421f2012-09-07 17:30:07 +02005264 }
5265
Emmanuel Hocdet839af572019-05-14 16:27:35 +02005266#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02005267 conf_ciphersuites = (ssl_conf && ssl_conf->ciphersuites) ? ssl_conf->ciphersuites : bind_conf->ssl_conf.ciphersuites;
5268 if (conf_ciphersuites &&
5269 !SSL_CTX_set_ciphersuites(ctx, conf_ciphersuites)) {
Tim Duesterhus93128532019-11-23 23:45:10 +01005270 memprintf(err, "%sProxy '%s': unable to set TLS 1.3 cipher suites to '%s' for bind '%s' at [%s:%d].\n",
5271 err && *err ? *err : "", curproxy->id, conf_ciphersuites, bind_conf->arg, bind_conf->file, bind_conf->line);
William Lallemand8b453912019-11-21 15:48:10 +01005272 cfgerr |= ERR_ALERT | ERR_FATAL;
Dirkjan Bussink415150f2018-09-14 11:14:21 +02005273 }
5274#endif
5275
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01005276#ifndef OPENSSL_NO_DH
Remi Gacogne47783ef2015-05-29 15:53:22 +02005277 /* If tune.ssl.default-dh-param has not been set,
5278 neither has ssl-default-dh-file and no static DH
5279 params were in the certificate file. */
Willy Tarreauef934602016-12-22 23:12:01 +01005280 if (global_ssl.default_dh_param == 0 &&
Remi Gacogne47783ef2015-05-29 15:53:22 +02005281 global_dh == NULL &&
Remi Gacogne4f902b82015-05-28 16:23:00 +02005282 (ssl_dh_ptr_index == -1 ||
5283 SSL_CTX_get_ex_data(ctx, ssl_dh_ptr_index) == NULL)) {
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01005284 STACK_OF(SSL_CIPHER) * ciphers = NULL;
5285 const SSL_CIPHER * cipher = NULL;
5286 char cipher_description[128];
5287 /* The description of ciphers using an Ephemeral Diffie Hellman key exchange
5288 contains " Kx=DH " or " Kx=DH(". Beware of " Kx=DH/",
5289 which is not ephemeral DH. */
5290 const char dhe_description[] = " Kx=DH ";
5291 const char dhe_export_description[] = " Kx=DH(";
5292 int idx = 0;
5293 int dhe_found = 0;
5294 SSL *ssl = NULL;
Lukas Tribus90132722014-08-18 00:56:33 +02005295
Remi Gacogne23d5d372014-10-10 17:04:26 +02005296 ssl = SSL_new(ctx);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02005297
Remi Gacogne23d5d372014-10-10 17:04:26 +02005298 if (ssl) {
5299 ciphers = SSL_get_ciphers(ssl);
5300
5301 if (ciphers) {
5302 for (idx = 0; idx < sk_SSL_CIPHER_num(ciphers); idx++) {
5303 cipher = sk_SSL_CIPHER_value(ciphers, idx);
5304 if (SSL_CIPHER_description(cipher, cipher_description, sizeof (cipher_description)) == cipher_description) {
5305 if (strstr(cipher_description, dhe_description) != NULL ||
5306 strstr(cipher_description, dhe_export_description) != NULL) {
5307 dhe_found = 1;
5308 break;
5309 }
Remi Gacognec1eab8c2014-06-12 18:20:11 +02005310 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02005311 }
5312 }
Remi Gacogne23d5d372014-10-10 17:04:26 +02005313 SSL_free(ssl);
5314 ssl = NULL;
Lukas Tribus90132722014-08-18 00:56:33 +02005315 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02005316
Lukas Tribus90132722014-08-18 00:56:33 +02005317 if (dhe_found) {
Tim Duesterhus93128532019-11-23 23:45:10 +01005318 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",
5319 err && *err ? *err : "");
William Lallemand8b453912019-11-21 15:48:10 +01005320 cfgerr |= ERR_WARN;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02005321 }
5322
Willy Tarreauef934602016-12-22 23:12:01 +01005323 global_ssl.default_dh_param = 1024;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02005324 }
Remi Gacogne8de54152014-07-15 11:36:40 +02005325
Willy Tarreauef934602016-12-22 23:12:01 +01005326 if (global_ssl.default_dh_param >= 1024) {
Remi Gacogne8de54152014-07-15 11:36:40 +02005327 if (local_dh_1024 == NULL) {
5328 local_dh_1024 = ssl_get_dh_1024();
5329 }
Willy Tarreauef934602016-12-22 23:12:01 +01005330 if (global_ssl.default_dh_param >= 2048) {
Remi Gacogne8de54152014-07-15 11:36:40 +02005331 if (local_dh_2048 == NULL) {
5332 local_dh_2048 = ssl_get_dh_2048();
5333 }
Willy Tarreauef934602016-12-22 23:12:01 +01005334 if (global_ssl.default_dh_param >= 4096) {
Remi Gacogne8de54152014-07-15 11:36:40 +02005335 if (local_dh_4096 == NULL) {
5336 local_dh_4096 = ssl_get_dh_4096();
5337 }
Remi Gacogne8de54152014-07-15 11:36:40 +02005338 }
5339 }
5340 }
5341#endif /* OPENSSL_NO_DH */
Remi Gacognef46cd6e2014-06-12 14:58:40 +02005342
Emeric Brunfc0421f2012-09-07 17:30:07 +02005343 SSL_CTX_set_info_callback(ctx, ssl_sock_infocbk);
Willy Tarreau9a1ab082019-05-09 13:26:41 +02005344#if HA_OPENSSL_VERSION_NUMBER >= 0x00907000L
Emeric Brun29f037d2014-04-25 19:05:36 +02005345 SSL_CTX_set_msg_callback(ctx, ssl_sock_msgcbk);
Willy Tarreau5cbe4ef2014-05-08 22:45:11 +02005346#endif
Emeric Brun29f037d2014-04-25 19:05:36 +02005347
Bernard Spil13c53f82018-02-15 13:34:58 +01005348#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005349 ssl_conf_cur = NULL;
5350 if (ssl_conf && ssl_conf->npn_str)
5351 ssl_conf_cur = ssl_conf;
5352 else if (bind_conf->ssl_conf.npn_str)
5353 ssl_conf_cur = &bind_conf->ssl_conf;
5354 if (ssl_conf_cur)
5355 SSL_CTX_set_next_protos_advertised_cb(ctx, ssl_sock_advertise_npn_protos, ssl_conf_cur);
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02005356#endif
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01005357#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005358 ssl_conf_cur = NULL;
5359 if (ssl_conf && ssl_conf->alpn_str)
5360 ssl_conf_cur = ssl_conf;
5361 else if (bind_conf->ssl_conf.alpn_str)
5362 ssl_conf_cur = &bind_conf->ssl_conf;
5363 if (ssl_conf_cur)
5364 SSL_CTX_set_alpn_select_cb(ctx, ssl_sock_advertise_alpn_protos, ssl_conf_cur);
Willy Tarreauab861d32013-04-02 02:30:41 +02005365#endif
Lukas Tribusd14b49c2019-11-24 18:20:40 +01005366#if ((HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL) || defined(LIBRESSL_VERSION_NUMBER))
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01005367 conf_curves = (ssl_conf && ssl_conf->curves) ? ssl_conf->curves : bind_conf->ssl_conf.curves;
5368 if (conf_curves) {
5369 if (!SSL_CTX_set1_curves_list(ctx, conf_curves)) {
Tim Duesterhus93128532019-11-23 23:45:10 +01005370 memprintf(err, "%sProxy '%s': unable to set SSL curves list to '%s' for bind '%s' at [%s:%d].\n",
5371 err && *err ? *err : "", curproxy->id, conf_curves, bind_conf->arg, bind_conf->file, bind_conf->line);
William Lallemand8b453912019-11-21 15:48:10 +01005372 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01005373 }
Emmanuel Hocdeta52bb152017-03-20 11:11:49 +01005374 (void)SSL_CTX_set_ecdh_auto(ctx, 1);
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01005375 }
5376#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02005377#if defined(SSL_CTX_set_tmp_ecdh) && !defined(OPENSSL_NO_ECDH)
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01005378 if (!conf_curves) {
Emeric Brun2b58d042012-09-20 17:10:03 +02005379 int i;
5380 EC_KEY *ecdh;
Willy Tarreau9a1ab082019-05-09 13:26:41 +02005381#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005382 const char *ecdhe = (ssl_conf && ssl_conf->ecdhe) ? ssl_conf->ecdhe :
Olivier Houchardc2aae742017-09-22 18:26:28 +02005383 (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe :
5384 NULL);
5385
5386 if (ecdhe == NULL) {
Eric Salama3c8bde82019-11-20 11:33:40 +01005387 (void)SSL_CTX_set_ecdh_auto(ctx, 1);
Olivier Houchardc2aae742017-09-22 18:26:28 +02005388 return cfgerr;
5389 }
5390#else
5391 const char *ecdhe = (ssl_conf && ssl_conf->ecdhe) ? ssl_conf->ecdhe :
5392 (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe :
5393 ECDHE_DEFAULT_CURVE);
5394#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02005395
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005396 i = OBJ_sn2nid(ecdhe);
Emeric Brun2b58d042012-09-20 17:10:03 +02005397 if (!i || ((ecdh = EC_KEY_new_by_curve_name(i)) == NULL)) {
Tim Duesterhus93128532019-11-23 23:45:10 +01005398 memprintf(err, "%sProxy '%s': unable to set elliptic named curve to '%s' for bind '%s' at [%s:%d].\n",
5399 err && *err ? *err : "", curproxy->id, ecdhe, bind_conf->arg, bind_conf->file, bind_conf->line);
William Lallemand8b453912019-11-21 15:48:10 +01005400 cfgerr |= ERR_ALERT | ERR_FATAL;
Emeric Brun2b58d042012-09-20 17:10:03 +02005401 }
5402 else {
5403 SSL_CTX_set_tmp_ecdh(ctx, ecdh);
5404 EC_KEY_free(ecdh);
5405 }
5406 }
5407#endif
5408
Emeric Brunfc0421f2012-09-07 17:30:07 +02005409 return cfgerr;
5410}
5411
Evan Broderbe554312013-06-27 00:05:25 -07005412static int ssl_sock_srv_hostcheck(const char *pattern, const char *hostname)
5413{
5414 const char *pattern_wildcard, *pattern_left_label_end, *hostname_left_label_end;
5415 size_t prefixlen, suffixlen;
5416
5417 /* Trivial case */
5418 if (strcmp(pattern, hostname) == 0)
5419 return 1;
5420
Evan Broderbe554312013-06-27 00:05:25 -07005421 /* The rest of this logic is based on RFC 6125, section 6.4.3
5422 * (http://tools.ietf.org/html/rfc6125#section-6.4.3) */
5423
Emeric Bruna848dae2013-10-08 11:27:28 +02005424 pattern_wildcard = NULL;
5425 pattern_left_label_end = pattern;
5426 while (*pattern_left_label_end != '.') {
5427 switch (*pattern_left_label_end) {
5428 case 0:
5429 /* End of label not found */
5430 return 0;
5431 case '*':
5432 /* If there is more than one wildcards */
5433 if (pattern_wildcard)
5434 return 0;
5435 pattern_wildcard = pattern_left_label_end;
5436 break;
5437 }
5438 pattern_left_label_end++;
5439 }
5440
5441 /* If it's not trivial and there is no wildcard, it can't
5442 * match */
5443 if (!pattern_wildcard)
Evan Broderbe554312013-06-27 00:05:25 -07005444 return 0;
5445
5446 /* Make sure all labels match except the leftmost */
5447 hostname_left_label_end = strchr(hostname, '.');
5448 if (!hostname_left_label_end
5449 || strcmp(pattern_left_label_end, hostname_left_label_end) != 0)
5450 return 0;
5451
5452 /* Make sure the leftmost label of the hostname is long enough
5453 * that the wildcard can match */
Emeric Brun369da852013-10-08 11:39:35 +02005454 if (hostname_left_label_end - hostname < (pattern_left_label_end - pattern) - 1)
Evan Broderbe554312013-06-27 00:05:25 -07005455 return 0;
5456
5457 /* Finally compare the string on either side of the
5458 * wildcard */
5459 prefixlen = pattern_wildcard - pattern;
5460 suffixlen = pattern_left_label_end - (pattern_wildcard + 1);
Emeric Bruna848dae2013-10-08 11:27:28 +02005461 if ((prefixlen && (memcmp(pattern, hostname, prefixlen) != 0))
5462 || (suffixlen && (memcmp(pattern_wildcard + 1, hostname_left_label_end - suffixlen, suffixlen) != 0)))
Evan Broderbe554312013-06-27 00:05:25 -07005463 return 0;
5464
5465 return 1;
5466}
5467
5468static int ssl_sock_srv_verifycbk(int ok, X509_STORE_CTX *ctx)
5469{
5470 SSL *ssl;
5471 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01005472 struct ssl_sock_ctx *ssl_ctx;
Willy Tarreau2ab88672017-07-05 18:23:03 +02005473 const char *servername;
Willy Tarreau71d058c2017-07-26 20:09:56 +02005474 const char *sni;
Evan Broderbe554312013-06-27 00:05:25 -07005475
5476 int depth;
5477 X509 *cert;
5478 STACK_OF(GENERAL_NAME) *alt_names;
5479 int i;
5480 X509_NAME *cert_subject;
5481 char *str;
5482
5483 if (ok == 0)
5484 return ok;
5485
5486 ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
Thierry FOURNIER28962c92018-06-17 21:37:05 +02005487 conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Olivier Houchard66ab4982019-02-26 18:37:15 +01005488 ssl_ctx = conn->xprt_ctx;
Evan Broderbe554312013-06-27 00:05:25 -07005489
Willy Tarreauad92a9a2017-07-28 11:38:41 +02005490 /* We're checking if the provided hostnames match the desired one. The
5491 * desired hostname comes from the SNI we presented if any, or if not
5492 * provided then it may have been explicitly stated using a "verifyhost"
5493 * directive. If neither is set, we don't care about the name so the
5494 * verification is OK.
Willy Tarreau2ab88672017-07-05 18:23:03 +02005495 */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005496 servername = SSL_get_servername(ssl_ctx->ssl, TLSEXT_NAMETYPE_host_name);
Willy Tarreau71d058c2017-07-26 20:09:56 +02005497 sni = servername;
Willy Tarreau2ab88672017-07-05 18:23:03 +02005498 if (!servername) {
Willy Tarreau07d94e42018-09-20 10:57:52 +02005499 servername = __objt_server(conn->target)->ssl_ctx.verify_host;
Willy Tarreau2ab88672017-07-05 18:23:03 +02005500 if (!servername)
5501 return ok;
5502 }
Evan Broderbe554312013-06-27 00:05:25 -07005503
5504 /* We only need to verify the CN on the actual server cert,
5505 * not the indirect CAs */
5506 depth = X509_STORE_CTX_get_error_depth(ctx);
5507 if (depth != 0)
5508 return ok;
5509
5510 /* At this point, the cert is *not* OK unless we can find a
5511 * hostname match */
5512 ok = 0;
5513
5514 cert = X509_STORE_CTX_get_current_cert(ctx);
5515 /* It seems like this might happen if verify peer isn't set */
5516 if (!cert)
5517 return ok;
5518
5519 alt_names = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
5520 if (alt_names) {
5521 for (i = 0; !ok && i < sk_GENERAL_NAME_num(alt_names); i++) {
5522 GENERAL_NAME *name = sk_GENERAL_NAME_value(alt_names, i);
5523 if (name->type == GEN_DNS) {
Willy Tarreau9a1ab082019-05-09 13:26:41 +02005524#if HA_OPENSSL_VERSION_NUMBER < 0x00907000L
Emeric Bruna33410c2013-09-17 15:47:48 +02005525 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.ia5) >= 0) {
5526#else
Evan Broderbe554312013-06-27 00:05:25 -07005527 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
Emeric Bruna33410c2013-09-17 15:47:48 +02005528#endif
Evan Broderbe554312013-06-27 00:05:25 -07005529 ok = ssl_sock_srv_hostcheck(str, servername);
5530 OPENSSL_free(str);
5531 }
5532 }
5533 }
Emeric Brun4ad50a42013-09-17 15:19:54 +02005534 sk_GENERAL_NAME_pop_free(alt_names, GENERAL_NAME_free);
Evan Broderbe554312013-06-27 00:05:25 -07005535 }
5536
5537 cert_subject = X509_get_subject_name(cert);
5538 i = -1;
5539 while (!ok && (i = X509_NAME_get_index_by_NID(cert_subject, NID_commonName, i)) != -1) {
5540 X509_NAME_ENTRY *entry = X509_NAME_get_entry(cert_subject, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005541 ASN1_STRING *value;
5542 value = X509_NAME_ENTRY_get_data(entry);
5543 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
Evan Broderbe554312013-06-27 00:05:25 -07005544 ok = ssl_sock_srv_hostcheck(str, servername);
5545 OPENSSL_free(str);
5546 }
5547 }
5548
Willy Tarreau71d058c2017-07-26 20:09:56 +02005549 /* report the mismatch and indicate if SNI was used or not */
5550 if (!ok && !conn->err_code)
5551 conn->err_code = sni ? CO_ER_SSL_MISMATCH_SNI : CO_ER_SSL_MISMATCH;
Evan Broderbe554312013-06-27 00:05:25 -07005552 return ok;
5553}
5554
Emeric Brun94324a42012-10-11 14:00:19 +02005555/* prepare ssl context from servers options. Returns an error count */
Willy Tarreau03209342016-12-22 17:08:28 +01005556int ssl_sock_prepare_srv_ctx(struct server *srv)
Emeric Brun94324a42012-10-11 14:00:19 +02005557{
Willy Tarreau03209342016-12-22 17:08:28 +01005558 struct proxy *curproxy = srv->proxy;
Emeric Brun94324a42012-10-11 14:00:19 +02005559 int cfgerr = 0;
Remi Gacogneaf5c3da2014-05-19 10:29:58 +02005560 long options =
Emeric Brun94324a42012-10-11 14:00:19 +02005561 SSL_OP_ALL | /* all known workarounds for bugs */
5562 SSL_OP_NO_SSLv2 |
5563 SSL_OP_NO_COMPRESSION;
Remi Gacogneaf5c3da2014-05-19 10:29:58 +02005564 long mode =
Emeric Brun94324a42012-10-11 14:00:19 +02005565 SSL_MODE_ENABLE_PARTIAL_WRITE |
5566 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
Willy Tarreau396a1862014-11-13 14:06:52 +01005567 SSL_MODE_RELEASE_BUFFERS |
5568 SSL_MODE_SMALL_BUFFERS;
Emeric Brun850efd52014-01-29 12:24:34 +01005569 int verify = SSL_VERIFY_NONE;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01005570 SSL_CTX *ctx = NULL;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005571 struct tls_version_filter *conf_ssl_methods = &srv->ssl_ctx.methods;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005572 int i, min, max, hole;
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005573 int flags = MC_SSL_O_ALL;
Emeric Brun94324a42012-10-11 14:00:19 +02005574
Thierry Fournier383085f2013-01-24 14:15:43 +01005575 /* Make sure openssl opens /dev/urandom before the chroot */
5576 if (!ssl_initialize_random()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005577 ha_alert("OpenSSL random data generator initialization failed.\n");
Thierry Fournier383085f2013-01-24 14:15:43 +01005578 cfgerr++;
5579 }
5580
Willy Tarreaufce03112015-01-15 21:32:40 +01005581 /* Automatic memory computations need to know we use SSL there */
5582 global.ssl_used_backend = 1;
5583
5584 /* Initiate SSL context for current server */
Emeric Brun821bb9b2017-06-15 16:37:39 +02005585 if (!srv->ssl_ctx.reused_sess) {
Olivier Houcharde6060c52017-11-16 17:42:52 +01005586 if ((srv->ssl_ctx.reused_sess = calloc(1, global.nbthread*sizeof(*srv->ssl_ctx.reused_sess))) == NULL) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005587 ha_alert("Proxy '%s', server '%s' [%s:%d] out of memory.\n",
5588 curproxy->id, srv->id,
5589 srv->conf.file, srv->conf.line);
Emeric Brun821bb9b2017-06-15 16:37:39 +02005590 cfgerr++;
5591 return cfgerr;
5592 }
5593 }
Emeric Brun94324a42012-10-11 14:00:19 +02005594 if (srv->use_ssl)
5595 srv->xprt = &ssl_sock;
5596 if (srv->check.use_ssl)
Cyril Bonté9ce13112014-11-15 22:41:27 +01005597 srv->check.xprt = &ssl_sock;
Emeric Brun94324a42012-10-11 14:00:19 +02005598
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005599 ctx = SSL_CTX_new(SSLv23_client_method());
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01005600 if (!ctx) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005601 ha_alert("config : %s '%s', server '%s': unable to allocate ssl context.\n",
5602 proxy_type_str(curproxy), curproxy->id,
5603 srv->id);
Emeric Brun94324a42012-10-11 14:00:19 +02005604 cfgerr++;
5605 return cfgerr;
5606 }
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005607
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005608 if (conf_ssl_methods->flags && (conf_ssl_methods->min || conf_ssl_methods->max))
Christopher Faulet767a84b2017-11-24 16:50:31 +01005609 ha_warning("config : %s '%s': no-sslv3/no-tlsv1x are ignored for server '%s'. "
5610 "Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
5611 proxy_type_str(curproxy), curproxy->id, srv->id);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005612 else
5613 flags = conf_ssl_methods->flags;
5614
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005615 /* Real min and max should be determinate with configuration and openssl's capabilities */
5616 if (conf_ssl_methods->min)
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005617 flags |= (methodVersions[conf_ssl_methods->min].flag - 1);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005618 if (conf_ssl_methods->max)
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005619 flags |= ~((methodVersions[conf_ssl_methods->max].flag << 1) - 1);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005620
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02005621 /* find min, max and holes */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005622 min = max = CONF_TLSV_NONE;
5623 hole = 0;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005624 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005625 /* version is in openssl && version not disable in configuration */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005626 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005627 if (min) {
5628 if (hole) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005629 ha_warning("config : %s '%s': SSL/TLS versions range not contiguous for server '%s'. "
5630 "Hole find for %s. Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
5631 proxy_type_str(curproxy), curproxy->id, srv->id,
5632 methodVersions[hole].name);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005633 hole = 0;
5634 }
5635 max = i;
5636 }
5637 else {
5638 min = max = i;
5639 }
5640 }
5641 else {
5642 if (min)
5643 hole = i;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005644 }
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005645 if (!min) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005646 ha_alert("config : %s '%s': all SSL/TLS versions are disabled for server '%s'.\n",
5647 proxy_type_str(curproxy), curproxy->id, srv->id);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005648 cfgerr += 1;
5649 }
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005650
Willy Tarreau9a1ab082019-05-09 13:26:41 +02005651#if (HA_OPENSSL_VERSION_NUMBER < 0x1010000fL)
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005652 /* Keep force-xxx implementation as it is in older haproxy. It's a
Joseph Herlant017b3da2018-11-15 09:07:59 -08005653 precautionary measure to avoid any surprise with older openssl version. */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005654 if (min == max)
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02005655 methodVersions[min].ctx_set_version(ctx, SET_CLIENT);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005656 else
5657 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
5658 if (flags & methodVersions[i].flag)
5659 options |= methodVersions[i].option;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005660#else /* openssl >= 1.1.0 */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005661 /* set the max_version is required to cap TLS version or activate new TLS (v1.3) */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02005662 methodVersions[min].ctx_set_version(ctx, SET_MIN);
5663 methodVersions[max].ctx_set_version(ctx, SET_MAX);
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005664#endif
5665
5666 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLS_TICKETS)
5667 options |= SSL_OP_NO_TICKET;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01005668 SSL_CTX_set_options(ctx, options);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005669
Willy Tarreau5db847a2019-05-09 14:13:35 +02005670#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005671 if (global_ssl.async)
5672 mode |= SSL_MODE_ASYNC;
5673#endif
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01005674 SSL_CTX_set_mode(ctx, mode);
5675 srv->ssl_ctx.ctx = ctx;
5676
Emeric Bruna7aa3092012-10-26 12:58:00 +02005677 if (srv->ssl_ctx.client_crt) {
5678 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 +01005679 ha_alert("config : %s '%s', server '%s': unable to load SSL private key from PEM file '%s'.\n",
5680 proxy_type_str(curproxy), curproxy->id,
5681 srv->id, srv->ssl_ctx.client_crt);
Emeric Bruna7aa3092012-10-26 12:58:00 +02005682 cfgerr++;
5683 }
5684 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 +01005685 ha_alert("config : %s '%s', server '%s': unable to load ssl certificate from PEM file '%s'.\n",
5686 proxy_type_str(curproxy), curproxy->id,
5687 srv->id, srv->ssl_ctx.client_crt);
Emeric Bruna7aa3092012-10-26 12:58:00 +02005688 cfgerr++;
5689 }
5690 else if (SSL_CTX_check_private_key(srv->ssl_ctx.ctx) <= 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005691 ha_alert("config : %s '%s', server '%s': inconsistencies between private key and certificate loaded from PEM file '%s'.\n",
5692 proxy_type_str(curproxy), curproxy->id,
5693 srv->id, srv->ssl_ctx.client_crt);
Emeric Bruna7aa3092012-10-26 12:58:00 +02005694 cfgerr++;
5695 }
5696 }
Emeric Brun94324a42012-10-11 14:00:19 +02005697
Emeric Brun850efd52014-01-29 12:24:34 +01005698 if (global.ssl_server_verify == SSL_SERVER_VERIFY_REQUIRED)
5699 verify = SSL_VERIFY_PEER;
Emeric Brun850efd52014-01-29 12:24:34 +01005700 switch (srv->ssl_ctx.verify) {
5701 case SSL_SOCK_VERIFY_NONE:
5702 verify = SSL_VERIFY_NONE;
5703 break;
5704 case SSL_SOCK_VERIFY_REQUIRED:
5705 verify = SSL_VERIFY_PEER;
5706 break;
5707 }
Evan Broderbe554312013-06-27 00:05:25 -07005708 SSL_CTX_set_verify(srv->ssl_ctx.ctx,
Emeric Brun850efd52014-01-29 12:24:34 +01005709 verify,
Willy Tarreau2ab88672017-07-05 18:23:03 +02005710 (srv->ssl_ctx.verify_host || (verify & SSL_VERIFY_PEER)) ? ssl_sock_srv_verifycbk : NULL);
Emeric Brun850efd52014-01-29 12:24:34 +01005711 if (verify & SSL_VERIFY_PEER) {
Emeric Brunef42d922012-10-11 16:11:36 +02005712 if (srv->ssl_ctx.ca_file) {
Emmanuel Hocdetd4f9a602019-10-24 11:32:47 +02005713 /* set CAfile to verify */
5714 if (!ssl_set_verify_locations_file(srv->ssl_ctx.ctx, srv->ssl_ctx.ca_file)) {
5715 ha_alert("Proxy '%s', server '%s' [%s:%d] unable to set CA file '%s'.\n",
Christopher Faulet767a84b2017-11-24 16:50:31 +01005716 curproxy->id, srv->id,
5717 srv->conf.file, srv->conf.line, srv->ssl_ctx.ca_file);
Emeric Brunef42d922012-10-11 16:11:36 +02005718 cfgerr++;
5719 }
5720 }
Emeric Brun850efd52014-01-29 12:24:34 +01005721 else {
5722 if (global.ssl_server_verify == SSL_SERVER_VERIFY_REQUIRED)
Christopher Faulet767a84b2017-11-24 16:50:31 +01005723 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",
5724 curproxy->id, srv->id,
5725 srv->conf.file, srv->conf.line);
Emeric Brun850efd52014-01-29 12:24:34 +01005726 else
Christopher Faulet767a84b2017-11-24 16:50:31 +01005727 ha_alert("Proxy '%s', server '%s' [%s:%d] verify is enabled but no CA file specified.\n",
5728 curproxy->id, srv->id,
5729 srv->conf.file, srv->conf.line);
Emeric Brun850efd52014-01-29 12:24:34 +01005730 cfgerr++;
5731 }
Emeric Brunef42d922012-10-11 16:11:36 +02005732#ifdef X509_V_FLAG_CRL_CHECK
5733 if (srv->ssl_ctx.crl_file) {
5734 X509_STORE *store = SSL_CTX_get_cert_store(srv->ssl_ctx.ctx);
5735
Emmanuel Hocdetb270e812019-11-21 19:09:31 +01005736 if (!ssl_set_cert_crl_file(store, srv->ssl_ctx.crl_file)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005737 ha_alert("Proxy '%s', server '%s' [%s:%d] unable to configure CRL file '%s'.\n",
5738 curproxy->id, srv->id,
5739 srv->conf.file, srv->conf.line, srv->ssl_ctx.crl_file);
Emeric Brunef42d922012-10-11 16:11:36 +02005740 cfgerr++;
5741 }
5742 else {
5743 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
5744 }
5745 }
5746#endif
5747 }
5748
Olivier Houchardbd84ac82017-11-03 13:43:35 +01005749 SSL_CTX_set_session_cache_mode(srv->ssl_ctx.ctx, SSL_SESS_CACHE_CLIENT |
5750 SSL_SESS_CACHE_NO_INTERNAL_STORE);
5751 SSL_CTX_sess_set_new_cb(srv->ssl_ctx.ctx, ssl_sess_new_srv_cb);
Emeric Brun94324a42012-10-11 14:00:19 +02005752 if (srv->ssl_ctx.ciphers &&
5753 !SSL_CTX_set_cipher_list(srv->ssl_ctx.ctx, srv->ssl_ctx.ciphers)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005754 ha_alert("Proxy '%s', server '%s' [%s:%d] : unable to set SSL cipher list to '%s'.\n",
5755 curproxy->id, srv->id,
5756 srv->conf.file, srv->conf.line, srv->ssl_ctx.ciphers);
Emeric Brun94324a42012-10-11 14:00:19 +02005757 cfgerr++;
5758 }
Dirkjan Bussink415150f2018-09-14 11:14:21 +02005759
Emmanuel Hocdet839af572019-05-14 16:27:35 +02005760#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02005761 if (srv->ssl_ctx.ciphersuites &&
Pierre Cheynierbc34cd12019-03-21 16:15:47 +00005762 !SSL_CTX_set_ciphersuites(srv->ssl_ctx.ctx, srv->ssl_ctx.ciphersuites)) {
Dirkjan Bussink415150f2018-09-14 11:14:21 +02005763 ha_alert("Proxy '%s', server '%s' [%s:%d] : unable to set TLS 1.3 cipher suites to '%s'.\n",
5764 curproxy->id, srv->id,
5765 srv->conf.file, srv->conf.line, srv->ssl_ctx.ciphersuites);
5766 cfgerr++;
5767 }
5768#endif
Olivier Houchardc7566002018-11-20 23:33:50 +01005769#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
5770 if (srv->ssl_ctx.npn_str)
5771 SSL_CTX_set_next_proto_select_cb(ctx, ssl_sock_srv_select_protos, srv);
5772#endif
5773#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
5774 if (srv->ssl_ctx.alpn_str)
5775 SSL_CTX_set_alpn_protos(ctx, (unsigned char *)srv->ssl_ctx.alpn_str, srv->ssl_ctx.alpn_len);
5776#endif
5777
Emeric Brun94324a42012-10-11 14:00:19 +02005778
5779 return cfgerr;
5780}
5781
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005782/* Walks down the two trees in bind_conf and prepares all certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +02005783 * be NULL, in which case nothing is done. Returns the number of errors
5784 * encountered.
5785 */
Willy Tarreau03209342016-12-22 17:08:28 +01005786int ssl_sock_prepare_all_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02005787{
5788 struct ebmb_node *node;
5789 struct sni_ctx *sni;
5790 int err = 0;
William Lallemand8b453912019-11-21 15:48:10 +01005791 int errcode = 0;
5792 char *errmsg = NULL;
Emeric Brunfc0421f2012-09-07 17:30:07 +02005793
Willy Tarreaufce03112015-01-15 21:32:40 +01005794 /* Automatic memory computations need to know we use SSL there */
5795 global.ssl_used_frontend = 1;
5796
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01005797 /* Make sure openssl opens /dev/urandom before the chroot */
5798 if (!ssl_initialize_random()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005799 ha_alert("OpenSSL random data generator initialization failed.\n");
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01005800 err++;
5801 }
5802 /* Create initial_ctx used to start the ssl connection before do switchctx */
5803 if (!bind_conf->initial_ctx) {
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005804 err += ssl_sock_initial_ctx(bind_conf);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01005805 /* It should not be necessary to call this function, but it's
5806 necessary first to check and move all initialisation related
5807 to initial_ctx in ssl_sock_initial_ctx. */
William Lallemand8b453912019-11-21 15:48:10 +01005808 errcode |= ssl_sock_prepare_ctx(bind_conf, NULL, bind_conf->initial_ctx, &errmsg);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01005809 }
Emeric Brun0bed9942014-10-30 19:25:24 +01005810 if (bind_conf->default_ctx)
William Lallemand8b453912019-11-21 15:48:10 +01005811 errcode |= ssl_sock_prepare_ctx(bind_conf, bind_conf->default_ssl_conf, bind_conf->default_ctx, &errmsg);
Emeric Brun0bed9942014-10-30 19:25:24 +01005812
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005813 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02005814 while (node) {
5815 sni = ebmb_entry(node, struct sni_ctx, name);
Emeric Brun0bed9942014-10-30 19:25:24 +01005816 if (!sni->order && sni->ctx != bind_conf->default_ctx)
5817 /* only initialize the CTX on its first occurrence and
5818 if it is not the default_ctx */
William Lallemand8b453912019-11-21 15:48:10 +01005819 errcode |= ssl_sock_prepare_ctx(bind_conf, sni->conf, sni->ctx, &errmsg);
Emeric Brunfc0421f2012-09-07 17:30:07 +02005820 node = ebmb_next(node);
5821 }
5822
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005823 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02005824 while (node) {
5825 sni = ebmb_entry(node, struct sni_ctx, name);
William Lallemand8b453912019-11-21 15:48:10 +01005826 if (!sni->order && sni->ctx != bind_conf->default_ctx) {
Emeric Brun0bed9942014-10-30 19:25:24 +01005827 /* only initialize the CTX on its first occurrence and
5828 if it is not the default_ctx */
William Lallemand8b453912019-11-21 15:48:10 +01005829 errcode |= ssl_sock_prepare_ctx(bind_conf, sni->conf, sni->ctx, &errmsg);
5830 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02005831 node = ebmb_next(node);
5832 }
William Lallemand8b453912019-11-21 15:48:10 +01005833
5834 if (errcode & ERR_WARN) {
Tim Duesterhusc0e820c2019-11-23 23:52:30 +01005835 ha_warning("%s", errmsg);
William Lallemand8b453912019-11-21 15:48:10 +01005836 } else if (errcode & ERR_CODE) {
Tim Duesterhusc0e820c2019-11-23 23:52:30 +01005837 ha_alert("%s", errmsg);
William Lallemand8b453912019-11-21 15:48:10 +01005838 err++;
5839 }
5840
5841 free(errmsg);
Emeric Brunfc0421f2012-09-07 17:30:07 +02005842 return err;
5843}
5844
Willy Tarreau55d37912016-12-21 23:38:39 +01005845/* Prepares all the contexts for a bind_conf and allocates the shared SSL
5846 * context if needed. Returns < 0 on error, 0 on success. The warnings and
5847 * alerts are directly emitted since the rest of the stack does it below.
5848 */
5849int ssl_sock_prepare_bind_conf(struct bind_conf *bind_conf)
5850{
5851 struct proxy *px = bind_conf->frontend;
5852 int alloc_ctx;
5853 int err;
5854
5855 if (!bind_conf->is_ssl) {
5856 if (bind_conf->default_ctx) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005857 ha_warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
5858 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreau55d37912016-12-21 23:38:39 +01005859 }
5860 return 0;
5861 }
5862 if (!bind_conf->default_ctx) {
Emmanuel Hocdetaa0d6372017-08-09 11:24:25 +02005863 if (bind_conf->strict_sni && !bind_conf->generate_certs) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005864 ha_warning("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d], ssl connections will fail (use 'crt').\n",
5865 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetaa0d6372017-08-09 11:24:25 +02005866 }
5867 else {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005868 ha_alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
5869 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetaa0d6372017-08-09 11:24:25 +02005870 return -1;
5871 }
Willy Tarreau55d37912016-12-21 23:38:39 +01005872 }
William Lallemandc61c0b32017-12-04 18:46:39 +01005873 if (!ssl_shctx && global.tune.sslcachesize) {
William Lallemandc3cd35f2017-11-28 11:04:43 +01005874 alloc_ctx = shctx_init(&ssl_shctx, global.tune.sslcachesize,
Frédéric Lécailleb7838af2018-10-22 16:21:39 +02005875 sizeof(struct sh_ssl_sess_hdr) + SHSESS_BLOCK_MIN_SIZE, -1,
William Lallemandc3cd35f2017-11-28 11:04:43 +01005876 sizeof(*sh_ssl_sess_tree),
5877 ((global.nbthread > 1) || (!global_ssl.private_cache && (global.nbproc > 1))) ? 1 : 0);
Frédéric Lécaille4c8aa112018-10-25 20:22:46 +02005878 if (alloc_ctx <= 0) {
William Lallemandc3cd35f2017-11-28 11:04:43 +01005879 if (alloc_ctx == SHCTX_E_INIT_LOCK)
5880 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");
5881 else
5882 ha_alert("Unable to allocate SSL session cache.\n");
5883 return -1;
5884 }
5885 /* free block callback */
5886 ssl_shctx->free_block = sh_ssl_sess_free_blocks;
5887 /* init the root tree within the extra space */
5888 sh_ssl_sess_tree = (void *)ssl_shctx + sizeof(struct shared_context);
5889 *sh_ssl_sess_tree = EB_ROOT_UNIQUE;
Willy Tarreau55d37912016-12-21 23:38:39 +01005890 }
Willy Tarreau55d37912016-12-21 23:38:39 +01005891 err = 0;
5892 /* initialize all certificate contexts */
5893 err += ssl_sock_prepare_all_ctx(bind_conf);
5894
5895 /* initialize CA variables if the certificates generation is enabled */
5896 err += ssl_sock_load_ca(bind_conf);
5897
5898 return -err;
5899}
Christopher Faulet77fe80c2015-07-29 13:02:40 +02005900
5901/* release ssl context allocated for servers. */
5902void ssl_sock_free_srv_ctx(struct server *srv)
5903{
Olivier Houchardc7566002018-11-20 23:33:50 +01005904#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
5905 if (srv->ssl_ctx.alpn_str)
5906 free(srv->ssl_ctx.alpn_str);
5907#endif
Lukas Tribusda95fd92018-11-25 13:21:27 +01005908#ifdef OPENSSL_NPN_NEGOTIATED
Olivier Houchardc7566002018-11-20 23:33:50 +01005909 if (srv->ssl_ctx.npn_str)
5910 free(srv->ssl_ctx.npn_str);
Lukas Tribus7706b852018-11-26 22:57:17 +01005911#endif
Christopher Faulet77fe80c2015-07-29 13:02:40 +02005912 if (srv->ssl_ctx.ctx)
5913 SSL_CTX_free(srv->ssl_ctx.ctx);
5914}
5915
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005916/* Walks down the two trees in bind_conf and frees all the certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +02005917 * be NULL, in which case nothing is done. The default_ctx is nullified too.
5918 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005919void ssl_sock_free_all_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02005920{
5921 struct ebmb_node *node, *back;
5922 struct sni_ctx *sni;
5923
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005924 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02005925 while (node) {
5926 sni = ebmb_entry(node, struct sni_ctx, name);
5927 back = ebmb_next(node);
5928 ebmb_delete(node);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005929 if (!sni->order) { /* only free the CTX on its first occurrence */
Emeric Brunfc0421f2012-09-07 17:30:07 +02005930 SSL_CTX_free(sni->ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005931 ssl_sock_free_ssl_conf(sni->conf);
5932 free(sni->conf);
5933 sni->conf = NULL;
5934 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02005935 free(sni);
5936 node = back;
5937 }
5938
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005939 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02005940 while (node) {
5941 sni = ebmb_entry(node, struct sni_ctx, name);
5942 back = ebmb_next(node);
5943 ebmb_delete(node);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005944 if (!sni->order) { /* only free the CTX on its first occurrence */
Emeric Brunfc0421f2012-09-07 17:30:07 +02005945 SSL_CTX_free(sni->ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005946 ssl_sock_free_ssl_conf(sni->conf);
5947 free(sni->conf);
5948 sni->conf = NULL;
5949 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02005950 free(sni);
5951 node = back;
5952 }
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01005953 SSL_CTX_free(bind_conf->initial_ctx);
5954 bind_conf->initial_ctx = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005955 bind_conf->default_ctx = NULL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005956 bind_conf->default_ssl_conf = NULL;
Emeric Brune1f38db2012-09-03 20:36:47 +02005957}
5958
Willy Tarreau795cdab2016-12-22 17:30:54 +01005959/* Destroys all the contexts for a bind_conf. This is used during deinit(). */
5960void ssl_sock_destroy_bind_conf(struct bind_conf *bind_conf)
5961{
5962 ssl_sock_free_ca(bind_conf);
5963 ssl_sock_free_all_ctx(bind_conf);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005964 ssl_sock_free_ssl_conf(&bind_conf->ssl_conf);
Willy Tarreau795cdab2016-12-22 17:30:54 +01005965 free(bind_conf->ca_sign_file);
5966 free(bind_conf->ca_sign_pass);
Willy Tarreau17b4aa12018-07-17 10:05:32 +02005967 if (bind_conf->keys_ref && !--bind_conf->keys_ref->refcount) {
Willy Tarreau795cdab2016-12-22 17:30:54 +01005968 free(bind_conf->keys_ref->filename);
5969 free(bind_conf->keys_ref->tlskeys);
5970 LIST_DEL(&bind_conf->keys_ref->list);
5971 free(bind_conf->keys_ref);
5972 }
5973 bind_conf->keys_ref = NULL;
Willy Tarreau795cdab2016-12-22 17:30:54 +01005974 bind_conf->ca_sign_pass = NULL;
5975 bind_conf->ca_sign_file = NULL;
Willy Tarreau795cdab2016-12-22 17:30:54 +01005976}
5977
Christopher Faulet31af49d2015-06-09 17:29:50 +02005978/* Load CA cert file and private key used to generate certificates */
5979int
Willy Tarreau03209342016-12-22 17:08:28 +01005980ssl_sock_load_ca(struct bind_conf *bind_conf)
Christopher Faulet31af49d2015-06-09 17:29:50 +02005981{
Willy Tarreau03209342016-12-22 17:08:28 +01005982 struct proxy *px = bind_conf->frontend;
Christopher Faulet31af49d2015-06-09 17:29:50 +02005983 FILE *fp;
5984 X509 *cacert = NULL;
5985 EVP_PKEY *capkey = NULL;
5986 int err = 0;
5987
Christopher Fauletf8bb0ce2017-09-15 09:52:49 +02005988 if (!bind_conf->generate_certs)
Christopher Faulet31af49d2015-06-09 17:29:50 +02005989 return err;
5990
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005991#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Emeric Brun821bb9b2017-06-15 16:37:39 +02005992 if (global_ssl.ctx_cache) {
Willy Tarreauef934602016-12-22 23:12:01 +01005993 ssl_ctx_lru_tree = lru64_new(global_ssl.ctx_cache);
Emeric Brun821bb9b2017-06-15 16:37:39 +02005994 }
Christopher Fauletd2cab922015-07-28 16:03:47 +02005995 ssl_ctx_lru_seed = (unsigned int)time(NULL);
Emeric Brun821bb9b2017-06-15 16:37:39 +02005996 ssl_ctx_serial = now_ms;
Willy Tarreaua84c2672015-10-09 12:10:13 +02005997#endif
Christopher Fauletd2cab922015-07-28 16:03:47 +02005998
Christopher Faulet31af49d2015-06-09 17:29:50 +02005999 if (!bind_conf->ca_sign_file) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01006000 ha_alert("Proxy '%s': cannot enable certificate generation, "
6001 "no CA certificate File configured at [%s:%d].\n",
6002 px->id, bind_conf->file, bind_conf->line);
Christopher Faulet31af49d2015-06-09 17:29:50 +02006003 goto load_error;
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02006004 }
Christopher Faulet31af49d2015-06-09 17:29:50 +02006005
6006 /* read in the CA certificate */
6007 if (!(fp = fopen(bind_conf->ca_sign_file, "r"))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01006008 ha_alert("Proxy '%s': Failed to read CA certificate file '%s' at [%s:%d].\n",
6009 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Faulet31af49d2015-06-09 17:29:50 +02006010 goto load_error;
6011 }
6012 if (!(cacert = PEM_read_X509(fp, NULL, NULL, NULL))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01006013 ha_alert("Proxy '%s': Failed to read CA certificate file '%s' at [%s:%d].\n",
6014 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02006015 goto read_error;
Christopher Faulet31af49d2015-06-09 17:29:50 +02006016 }
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02006017 rewind(fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02006018 if (!(capkey = PEM_read_PrivateKey(fp, NULL, NULL, bind_conf->ca_sign_pass))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01006019 ha_alert("Proxy '%s': Failed to read CA private key file '%s' at [%s:%d].\n",
6020 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02006021 goto read_error;
Christopher Faulet31af49d2015-06-09 17:29:50 +02006022 }
Christopher Faulet31af49d2015-06-09 17:29:50 +02006023
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02006024 fclose (fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02006025 bind_conf->ca_sign_cert = cacert;
6026 bind_conf->ca_sign_pkey = capkey;
6027 return err;
6028
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02006029 read_error:
6030 fclose (fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02006031 if (capkey) EVP_PKEY_free(capkey);
6032 if (cacert) X509_free(cacert);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02006033 load_error:
6034 bind_conf->generate_certs = 0;
6035 err++;
Christopher Faulet31af49d2015-06-09 17:29:50 +02006036 return err;
6037}
6038
6039/* Release CA cert and private key used to generate certificated */
6040void
6041ssl_sock_free_ca(struct bind_conf *bind_conf)
6042{
Christopher Faulet31af49d2015-06-09 17:29:50 +02006043 if (bind_conf->ca_sign_pkey)
6044 EVP_PKEY_free(bind_conf->ca_sign_pkey);
6045 if (bind_conf->ca_sign_cert)
6046 X509_free(bind_conf->ca_sign_cert);
Willy Tarreau94ff03a2016-12-22 17:57:46 +01006047 bind_conf->ca_sign_pkey = NULL;
6048 bind_conf->ca_sign_cert = NULL;
Christopher Faulet31af49d2015-06-09 17:29:50 +02006049}
6050
Emeric Brun46591952012-05-18 15:47:34 +02006051/*
6052 * This function is called if SSL * context is not yet allocated. The function
6053 * is designed to be called before any other data-layer operation and sets the
6054 * handshake flag on the connection. It is safe to call it multiple times.
6055 * It returns 0 on success and -1 in error case.
6056 */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006057static int ssl_sock_init(struct connection *conn, void **xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02006058{
Olivier Houchard66ab4982019-02-26 18:37:15 +01006059 struct ssl_sock_ctx *ctx;
Emeric Brun46591952012-05-18 15:47:34 +02006060 /* already initialized */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006061 if (*xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02006062 return 0;
6063
Willy Tarreau3c728722014-01-23 13:50:42 +01006064 if (!conn_ctrl_ready(conn))
Willy Tarreauf79c8172013-10-21 16:30:56 +02006065 return 0;
6066
Olivier Houchard66ab4982019-02-26 18:37:15 +01006067 ctx = pool_alloc(ssl_sock_ctx_pool);
6068 if (!ctx) {
6069 conn->err_code = CO_ER_SSL_NO_MEM;
6070 return -1;
6071 }
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02006072 ctx->wait_event.tasklet = tasklet_new();
6073 if (!ctx->wait_event.tasklet) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02006074 conn->err_code = CO_ER_SSL_NO_MEM;
6075 pool_free(ssl_sock_ctx_pool, ctx);
6076 return -1;
6077 }
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02006078 ctx->wait_event.tasklet->process = ssl_sock_io_cb;
6079 ctx->wait_event.tasklet->context = ctx;
Olivier Houchardea8dd942019-05-20 14:02:16 +02006080 ctx->wait_event.events = 0;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006081 ctx->sent_early_data = 0;
Olivier Houchard54907bb2019-12-19 15:02:39 +01006082 ctx->early_buf = BUF_NULL;
Olivier Houcharda8955d52019-04-07 22:00:38 +02006083 ctx->conn = conn;
Willy Tarreau113d52b2020-01-10 09:20:26 +01006084 ctx->subs = NULL;
Emeric Brun5762a0d2019-09-06 15:36:02 +02006085 ctx->xprt_st = 0;
6086 ctx->xprt_ctx = NULL;
Olivier Houcharda8955d52019-04-07 22:00:38 +02006087
6088 /* Only work with sockets for now, this should be adapted when we'll
6089 * add QUIC support.
6090 */
6091 ctx->xprt = xprt_get(XPRT_RAW);
Olivier Houchard19afb272019-05-23 18:24:07 +02006092 if (ctx->xprt->init) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02006093 if (ctx->xprt->init(conn, &ctx->xprt_ctx) != 0)
6094 goto err;
Olivier Houchard19afb272019-05-23 18:24:07 +02006095 }
Olivier Houchard66ab4982019-02-26 18:37:15 +01006096
Willy Tarreau20879a02012-12-03 16:32:10 +01006097 if (global.maxsslconn && sslconns >= global.maxsslconn) {
6098 conn->err_code = CO_ER_SSL_TOO_MANY;
Olivier Houchardea8dd942019-05-20 14:02:16 +02006099 goto err;
Willy Tarreau20879a02012-12-03 16:32:10 +01006100 }
Willy Tarreau403edff2012-09-06 11:58:37 +02006101
Emeric Brun46591952012-05-18 15:47:34 +02006102 /* If it is in client mode initiate SSL session
6103 in connect state otherwise accept state */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01006104 if (objt_server(conn->target)) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01006105 int may_retry = 1;
6106
6107 retry_connect:
Emeric Brun46591952012-05-18 15:47:34 +02006108 /* Alloc a new SSL session ctx */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006109 ctx->ssl = SSL_new(__objt_server(conn->target)->ssl_ctx.ctx);
6110 if (!ctx->ssl) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01006111 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01006112 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01006113 goto retry_connect;
6114 }
Willy Tarreau20879a02012-12-03 16:32:10 +01006115 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006116 goto err;
Willy Tarreau20879a02012-12-03 16:32:10 +01006117 }
Olivier Houcharda8955d52019-04-07 22:00:38 +02006118 ctx->bio = BIO_new(ha_meth);
6119 if (!ctx->bio) {
Olivier Houchardefe5e8e2020-01-24 15:17:38 +01006120 SSL_free(ctx->ssl);
6121 ctx->ssl = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01006122 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01006123 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01006124 goto retry_connect;
6125 }
Emeric Brun55476152014-11-12 17:35:37 +01006126 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006127 goto err;
Emeric Brun55476152014-11-12 17:35:37 +01006128 }
Olivier Houcharda8955d52019-04-07 22:00:38 +02006129 BIO_set_data(ctx->bio, ctx);
Olivier Houcharda8955d52019-04-07 22:00:38 +02006130 SSL_set_bio(ctx->ssl, ctx->bio, ctx->bio);
Emeric Brun46591952012-05-18 15:47:34 +02006131
Evan Broderbe554312013-06-27 00:05:25 -07006132 /* set connection pointer */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006133 if (!SSL_set_ex_data(ctx->ssl, ssl_app_data_index, conn)) {
6134 SSL_free(ctx->ssl);
6135 ctx->ssl = NULL;
Emeric Brun55476152014-11-12 17:35:37 +01006136 conn->xprt_ctx = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01006137 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01006138 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01006139 goto retry_connect;
6140 }
Emeric Brun55476152014-11-12 17:35:37 +01006141 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006142 goto err;
Emeric Brun55476152014-11-12 17:35:37 +01006143 }
6144
Olivier Houchard66ab4982019-02-26 18:37:15 +01006145 SSL_set_connect_state(ctx->ssl);
Willy Tarreau07d94e42018-09-20 10:57:52 +02006146 if (__objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr) {
6147 const unsigned char *ptr = __objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr;
6148 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 +01006149 if (sess && !SSL_set_session(ctx->ssl, sess)) {
Olivier Houcharde6060c52017-11-16 17:42:52 +01006150 SSL_SESSION_free(sess);
Willy Tarreau07d94e42018-09-20 10:57:52 +02006151 free(__objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr);
6152 __objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr = NULL;
Olivier Houcharde6060c52017-11-16 17:42:52 +01006153 } else if (sess) {
6154 SSL_SESSION_free(sess);
Emeric Brun55476152014-11-12 17:35:37 +01006155 }
6156 }
Evan Broderbe554312013-06-27 00:05:25 -07006157
Emeric Brun46591952012-05-18 15:47:34 +02006158 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +02006159 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Willy Tarreau403edff2012-09-06 11:58:37 +02006160
Olivier Houchard2be5a4c2019-03-08 18:54:43 +01006161 _HA_ATOMIC_ADD(&sslconns, 1);
6162 _HA_ATOMIC_ADD(&totalsslconns, 1);
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006163 *xprt_ctx = ctx;
Olivier Houchardea8dd942019-05-20 14:02:16 +02006164 /* Start the handshake */
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02006165 tasklet_wakeup(ctx->wait_event.tasklet);
Emeric Brun46591952012-05-18 15:47:34 +02006166 return 0;
6167 }
Willy Tarreau3fdb3662012-11-12 00:42:33 +01006168 else if (objt_listener(conn->target)) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01006169 int may_retry = 1;
6170
6171 retry_accept:
Emeric Brun46591952012-05-18 15:47:34 +02006172 /* Alloc a new SSL session ctx */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006173 ctx->ssl = SSL_new(__objt_listener(conn->target)->bind_conf->initial_ctx);
6174 if (!ctx->ssl) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01006175 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01006176 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01006177 goto retry_accept;
6178 }
Willy Tarreau20879a02012-12-03 16:32:10 +01006179 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006180 goto err;
Willy Tarreau20879a02012-12-03 16:32:10 +01006181 }
Olivier Houcharda8955d52019-04-07 22:00:38 +02006182 ctx->bio = BIO_new(ha_meth);
6183 if (!ctx->bio) {
Olivier Houchardefe5e8e2020-01-24 15:17:38 +01006184 SSL_free(ctx->ssl);
6185 ctx->ssl = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01006186 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01006187 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01006188 goto retry_accept;
6189 }
Emeric Brun55476152014-11-12 17:35:37 +01006190 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006191 goto err;
Emeric Brun55476152014-11-12 17:35:37 +01006192 }
Olivier Houcharda8955d52019-04-07 22:00:38 +02006193 BIO_set_data(ctx->bio, ctx);
Olivier Houcharda8955d52019-04-07 22:00:38 +02006194 SSL_set_bio(ctx->ssl, ctx->bio, ctx->bio);
Emeric Brun46591952012-05-18 15:47:34 +02006195
Emeric Brune1f38db2012-09-03 20:36:47 +02006196 /* set connection pointer */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006197 if (!SSL_set_ex_data(ctx->ssl, ssl_app_data_index, conn)) {
6198 SSL_free(ctx->ssl);
6199 ctx->ssl = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01006200 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01006201 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01006202 goto retry_accept;
6203 }
Emeric Brun55476152014-11-12 17:35:37 +01006204 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006205 goto err;
Emeric Brun55476152014-11-12 17:35:37 +01006206 }
6207
Frédéric Lécaille3139c1b2020-01-24 14:56:18 +01006208#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
6209 if (__objt_listener(conn->target)->bind_conf->ssl_conf.early_data) {
6210 b_alloc(&ctx->early_buf);
6211 SSL_set_max_early_data(ctx->ssl,
6212 /* Only allow early data if we managed to allocate
6213 * a buffer.
6214 */
6215 (!b_is_null(&ctx->early_buf)) ?
6216 global.tune.bufsize - global.tune.maxrewrite : 0);
6217 }
6218#endif
6219
Olivier Houchard66ab4982019-02-26 18:37:15 +01006220 SSL_set_accept_state(ctx->ssl);
Emeric Brune1f38db2012-09-03 20:36:47 +02006221
Emeric Brun46591952012-05-18 15:47:34 +02006222 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +02006223 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Emmanuel Hocdetf967c312019-08-05 18:04:16 +02006224#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Olivier Houchardc2aae742017-09-22 18:26:28 +02006225 conn->flags |= CO_FL_EARLY_SSL_HS;
6226#endif
Willy Tarreau403edff2012-09-06 11:58:37 +02006227
Olivier Houchard2be5a4c2019-03-08 18:54:43 +01006228 _HA_ATOMIC_ADD(&sslconns, 1);
6229 _HA_ATOMIC_ADD(&totalsslconns, 1);
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006230 *xprt_ctx = ctx;
Olivier Houchardea8dd942019-05-20 14:02:16 +02006231 /* Start the handshake */
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02006232 tasklet_wakeup(ctx->wait_event.tasklet);
Emeric Brun46591952012-05-18 15:47:34 +02006233 return 0;
6234 }
6235 /* don't know how to handle such a target */
Willy Tarreau20879a02012-12-03 16:32:10 +01006236 conn->err_code = CO_ER_SSL_NO_TARGET;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006237err:
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02006238 if (ctx && ctx->wait_event.tasklet)
6239 tasklet_free(ctx->wait_event.tasklet);
Olivier Houchard66ab4982019-02-26 18:37:15 +01006240 pool_free(ssl_sock_ctx_pool, ctx);
Emeric Brun46591952012-05-18 15:47:34 +02006241 return -1;
6242}
6243
6244
6245/* This is the callback which is used when an SSL handshake is pending. It
6246 * updates the FD status if it wants some polling before being called again.
6247 * It returns 0 if it fails in a fatal way or needs to poll to go further,
6248 * otherwise it returns non-zero and removes itself from the connection's
6249 * flags (the bit is provided in <flag> by the caller).
6250 */
Olivier Houchard000694c2019-05-23 14:45:12 +02006251static int ssl_sock_handshake(struct connection *conn, unsigned int flag)
Emeric Brun46591952012-05-18 15:47:34 +02006252{
Olivier Houchard66ab4982019-02-26 18:37:15 +01006253 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
Emeric Brun46591952012-05-18 15:47:34 +02006254 int ret;
6255
Willy Tarreau3c728722014-01-23 13:50:42 +01006256 if (!conn_ctrl_ready(conn))
Willy Tarreauf79c8172013-10-21 16:30:56 +02006257 return 0;
6258
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02006259 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02006260 goto out_error;
6261
Willy Tarreau5db847a2019-05-09 14:13:35 +02006262#if HA_OPENSSL_VERSION_NUMBER >= 0x10101000L
Olivier Houchardc2aae742017-09-22 18:26:28 +02006263 /*
6264 * Check if we have early data. If we do, we have to read them
6265 * before SSL_do_handshake() is called, And there's no way to
6266 * detect early data, except to try to read them
6267 */
6268 if (conn->flags & CO_FL_EARLY_SSL_HS) {
Olivier Houchard54907bb2019-12-19 15:02:39 +01006269 size_t read_data = 0;
Olivier Houchardc2aae742017-09-22 18:26:28 +02006270
Olivier Houchard54907bb2019-12-19 15:02:39 +01006271 while (1) {
6272 ret = SSL_read_early_data(ctx->ssl,
6273 b_tail(&ctx->early_buf), b_room(&ctx->early_buf),
6274 &read_data);
6275 if (ret == SSL_READ_EARLY_DATA_ERROR)
6276 goto check_error;
6277 if (read_data > 0) {
6278 conn->flags |= CO_FL_EARLY_DATA;
6279 b_add(&ctx->early_buf, read_data);
6280 }
6281 if (ret == SSL_READ_EARLY_DATA_FINISH) {
6282 conn->flags &= ~CO_FL_EARLY_SSL_HS;
6283 if (!b_data(&ctx->early_buf))
6284 b_free(&ctx->early_buf);
6285 break;
6286 }
6287 }
Olivier Houchardc2aae742017-09-22 18:26:28 +02006288 }
6289#endif
Emeric Brun674b7432012-11-08 19:21:55 +01006290 /* If we use SSL_do_handshake to process a reneg initiated by
6291 * the remote peer, it sometimes returns SSL_ERROR_SSL.
6292 * Usually SSL_write and SSL_read are used and process implicitly
6293 * the reneg handshake.
6294 * Here we use SSL_peek as a workaround for reneg.
6295 */
Willy Tarreauc192b0a2020-01-23 09:11:58 +01006296 if (!(conn->flags & CO_FL_WAIT_L6_CONN) && SSL_renegotiate_pending(ctx->ssl)) {
Emeric Brun674b7432012-11-08 19:21:55 +01006297 char c;
6298
Olivier Houchard66ab4982019-02-26 18:37:15 +01006299 ret = SSL_peek(ctx->ssl, &c, 1);
Emeric Brun674b7432012-11-08 19:21:55 +01006300 if (ret <= 0) {
6301 /* handshake may have not been completed, let's find why */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006302 ret = SSL_get_error(ctx->ssl, ret);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006303
Emeric Brun674b7432012-11-08 19:21:55 +01006304 if (ret == SSL_ERROR_WANT_WRITE) {
6305 /* SSL handshake needs to write, L4 connection may not be ready */
Olivier Houchard03abf2d2019-05-28 10:12:02 +02006306 if (!(ctx->wait_event.events & SUB_RETRY_SEND))
Olivier Houchardea8dd942019-05-20 14:02:16 +02006307 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_SEND, &ctx->wait_event);
Emeric Brun674b7432012-11-08 19:21:55 +01006308 return 0;
6309 }
6310 else if (ret == SSL_ERROR_WANT_READ) {
6311 /* handshake may have been completed but we have
6312 * no more data to read.
6313 */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006314 if (!SSL_renegotiate_pending(ctx->ssl)) {
Emeric Brun674b7432012-11-08 19:21:55 +01006315 ret = 1;
6316 goto reneg_ok;
6317 }
6318 /* SSL handshake needs to read, L4 connection is ready */
Olivier Houchard03abf2d2019-05-28 10:12:02 +02006319 if (!(ctx->wait_event.events & SUB_RETRY_RECV))
Olivier Houchardea8dd942019-05-20 14:02:16 +02006320 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_RECV, &ctx->wait_event);
Emeric Brun674b7432012-11-08 19:21:55 +01006321 return 0;
6322 }
Willy Tarreau5db847a2019-05-09 14:13:35 +02006323#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006324 else if (ret == SSL_ERROR_WANT_ASYNC) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02006325 ssl_async_process_fds(ctx);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006326 return 0;
6327 }
6328#endif
Emeric Brun674b7432012-11-08 19:21:55 +01006329 else if (ret == SSL_ERROR_SYSCALL) {
6330 /* if errno is null, then connection was successfully established */
6331 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
6332 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Willy Tarreau20879a02012-12-03 16:32:10 +01006333 if (!conn->err_code) {
Lukas Tribus49799162019-07-08 14:29:15 +02006334#if defined(OPENSSL_IS_BORINGSSL) || defined(LIBRESSL_VERSION_NUMBER)
6335 /* do not handle empty handshakes in BoringSSL or LibreSSL */
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01006336 conn->err_code = CO_ER_SSL_HANDSHAKE;
6337#else
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006338 int empty_handshake;
Willy Tarreau5db847a2019-05-09 14:13:35 +02006339#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL)
Lukas Tribus49799162019-07-08 14:29:15 +02006340 /* use SSL_get_state() in OpenSSL >= 1.1.0; SSL_state() is broken */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006341 OSSL_HANDSHAKE_STATE state = SSL_get_state((SSL *)ctx->ssl);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006342 empty_handshake = state == TLS_ST_BEFORE;
6343#else
Lukas Tribus49799162019-07-08 14:29:15 +02006344 /* access packet_length directly in OpenSSL <= 1.0.2; SSL_state() is broken */
6345 empty_handshake = !ctx->ssl->packet_length;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006346#endif
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006347 if (empty_handshake) {
Emeric Brun29f037d2014-04-25 19:05:36 +02006348 if (!errno) {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006349 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emeric Brun29f037d2014-04-25 19:05:36 +02006350 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
6351 else
6352 conn->err_code = CO_ER_SSL_EMPTY;
6353 }
6354 else {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006355 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emeric Brun29f037d2014-04-25 19:05:36 +02006356 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
6357 else
6358 conn->err_code = CO_ER_SSL_ABORT;
6359 }
6360 }
6361 else {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006362 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emeric Brun29f037d2014-04-25 19:05:36 +02006363 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
Willy Tarreau20879a02012-12-03 16:32:10 +01006364 else
Emeric Brun29f037d2014-04-25 19:05:36 +02006365 conn->err_code = CO_ER_SSL_HANDSHAKE;
6366 }
Lukas Tribus49799162019-07-08 14:29:15 +02006367#endif /* BoringSSL or LibreSSL */
Willy Tarreau20879a02012-12-03 16:32:10 +01006368 }
Emeric Brun674b7432012-11-08 19:21:55 +01006369 goto out_error;
6370 }
6371 else {
6372 /* Fail on all other handshake errors */
6373 /* Note: OpenSSL may leave unread bytes in the socket's
6374 * buffer, causing an RST to be emitted upon close() on
6375 * TCP sockets. We first try to drain possibly pending
6376 * data to avoid this as much as possible.
6377 */
Willy Tarreaud85c4852015-03-13 00:40:28 +01006378 conn_sock_drain(conn);
Willy Tarreau20879a02012-12-03 16:32:10 +01006379 if (!conn->err_code)
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006380 conn->err_code = (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT) ?
Willy Tarreauf51c6982014-04-25 20:02:39 +02006381 CO_ER_SSL_KILLED_HB : CO_ER_SSL_HANDSHAKE;
Emeric Brun674b7432012-11-08 19:21:55 +01006382 goto out_error;
6383 }
6384 }
6385 /* read some data: consider handshake completed */
6386 goto reneg_ok;
6387 }
Olivier Houchard66ab4982019-02-26 18:37:15 +01006388 ret = SSL_do_handshake(ctx->ssl);
Olivier Houchardc2aae742017-09-22 18:26:28 +02006389check_error:
Emeric Brun46591952012-05-18 15:47:34 +02006390 if (ret != 1) {
6391 /* handshake did not complete, let's find why */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006392 ret = SSL_get_error(ctx->ssl, ret);
Emeric Brun46591952012-05-18 15:47:34 +02006393
6394 if (ret == SSL_ERROR_WANT_WRITE) {
6395 /* SSL handshake needs to write, L4 connection may not be ready */
Olivier Houchard03abf2d2019-05-28 10:12:02 +02006396 if (!(ctx->wait_event.events & SUB_RETRY_SEND))
Olivier Houchardea8dd942019-05-20 14:02:16 +02006397 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_SEND, &ctx->wait_event);
Emeric Brun46591952012-05-18 15:47:34 +02006398 return 0;
6399 }
6400 else if (ret == SSL_ERROR_WANT_READ) {
6401 /* SSL handshake needs to read, L4 connection is ready */
Olivier Houchardea8dd942019-05-20 14:02:16 +02006402 if (!(ctx->wait_event.events & SUB_RETRY_RECV))
Olivier Houchardea8dd942019-05-20 14:02:16 +02006403 ctx->xprt->subscribe(conn, ctx->xprt_ctx,
6404 SUB_RETRY_RECV, &ctx->wait_event);
Emeric Brun46591952012-05-18 15:47:34 +02006405 return 0;
6406 }
Willy Tarreau5db847a2019-05-09 14:13:35 +02006407#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006408 else if (ret == SSL_ERROR_WANT_ASYNC) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02006409 ssl_async_process_fds(ctx);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006410 return 0;
6411 }
6412#endif
Willy Tarreau89230192012-09-28 20:22:13 +02006413 else if (ret == SSL_ERROR_SYSCALL) {
6414 /* if errno is null, then connection was successfully established */
6415 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
6416 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01006417 if (!conn->err_code) {
Lukas Tribus49799162019-07-08 14:29:15 +02006418#if defined(OPENSSL_IS_BORINGSSL) || defined(LIBRESSL_VERSION_NUMBER)
6419 /* do not handle empty handshakes in BoringSSL or LibreSSL */
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01006420 conn->err_code = CO_ER_SSL_HANDSHAKE;
6421#else
6422 int empty_handshake;
Willy Tarreau5db847a2019-05-09 14:13:35 +02006423#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL)
Lukas Tribus49799162019-07-08 14:29:15 +02006424 /* use SSL_get_state() in OpenSSL >= 1.1.0; SSL_state() is broken */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006425 OSSL_HANDSHAKE_STATE state = SSL_get_state(ctx->ssl);
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01006426 empty_handshake = state == TLS_ST_BEFORE;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006427#else
Lukas Tribus49799162019-07-08 14:29:15 +02006428 /* access packet_length directly in OpenSSL <= 1.0.2; SSL_state() is broken */
6429 empty_handshake = !ctx->ssl->packet_length;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006430#endif
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01006431 if (empty_handshake) {
6432 if (!errno) {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006433 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01006434 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
6435 else
6436 conn->err_code = CO_ER_SSL_EMPTY;
6437 }
6438 else {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006439 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01006440 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
6441 else
6442 conn->err_code = CO_ER_SSL_ABORT;
6443 }
Emeric Brun29f037d2014-04-25 19:05:36 +02006444 }
6445 else {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006446 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emeric Brun29f037d2014-04-25 19:05:36 +02006447 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
6448 else
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01006449 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun29f037d2014-04-25 19:05:36 +02006450 }
Lukas Tribus49799162019-07-08 14:29:15 +02006451#endif /* BoringSSL or LibreSSL */
Emeric Brun29f037d2014-04-25 19:05:36 +02006452 }
Willy Tarreau89230192012-09-28 20:22:13 +02006453 goto out_error;
6454 }
Emeric Brun46591952012-05-18 15:47:34 +02006455 else {
6456 /* Fail on all other handshake errors */
Willy Tarreau566dc552012-10-19 20:52:18 +02006457 /* Note: OpenSSL may leave unread bytes in the socket's
6458 * buffer, causing an RST to be emitted upon close() on
6459 * TCP sockets. We first try to drain possibly pending
6460 * data to avoid this as much as possible.
6461 */
Willy Tarreaud85c4852015-03-13 00:40:28 +01006462 conn_sock_drain(conn);
Willy Tarreau20879a02012-12-03 16:32:10 +01006463 if (!conn->err_code)
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006464 conn->err_code = (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT) ?
Willy Tarreauf51c6982014-04-25 20:02:39 +02006465 CO_ER_SSL_KILLED_HB : CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02006466 goto out_error;
6467 }
6468 }
Willy Tarreau5db847a2019-05-09 14:13:35 +02006469#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Olivier Houchard522eea72017-11-03 16:27:47 +01006470 else {
6471 /*
6472 * If the server refused the early data, we have to send a
6473 * 425 to the client, as we no longer have the data to sent
6474 * them again.
6475 */
6476 if ((conn->flags & CO_FL_EARLY_DATA) && (objt_server(conn->target))) {
Olivier Houchard66ab4982019-02-26 18:37:15 +01006477 if (SSL_get_early_data_status(ctx->ssl) == SSL_EARLY_DATA_REJECTED) {
Olivier Houchard522eea72017-11-03 16:27:47 +01006478 conn->err_code = CO_ER_SSL_EARLY_FAILED;
6479 goto out_error;
6480 }
6481 }
6482 }
6483#endif
6484
Emeric Brun46591952012-05-18 15:47:34 +02006485
Emeric Brun674b7432012-11-08 19:21:55 +01006486reneg_ok:
Emeric Brunb5e42a82017-06-06 12:35:14 +00006487
Willy Tarreau5db847a2019-05-09 14:13:35 +02006488#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00006489 /* ASYNC engine API doesn't support moving read/write
6490 * buffers. So we disable ASYNC mode right after
6491 * the handshake to avoid buffer oveflows.
6492 */
6493 if (global_ssl.async)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006494 SSL_clear_mode(ctx->ssl, SSL_MODE_ASYNC);
Emeric Brunb5e42a82017-06-06 12:35:14 +00006495#endif
Emeric Brun46591952012-05-18 15:47:34 +02006496 /* Handshake succeeded */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006497 if (!SSL_session_reused(ctx->ssl)) {
Willy Tarreau0c9c2722014-05-28 12:28:58 +02006498 if (objt_server(conn->target)) {
6499 update_freq_ctr(&global.ssl_be_keys_per_sec, 1);
6500 if (global.ssl_be_keys_per_sec.curr_ctr > global.ssl_be_keys_max)
6501 global.ssl_be_keys_max = global.ssl_be_keys_per_sec.curr_ctr;
Emeric Brun46591952012-05-18 15:47:34 +02006502 }
Willy Tarreau0c9c2722014-05-28 12:28:58 +02006503 else {
6504 update_freq_ctr(&global.ssl_fe_keys_per_sec, 1);
6505 if (global.ssl_fe_keys_per_sec.curr_ctr > global.ssl_fe_keys_max)
6506 global.ssl_fe_keys_max = global.ssl_fe_keys_per_sec.curr_ctr;
6507 }
Emeric Brun46591952012-05-18 15:47:34 +02006508 }
6509
6510 /* The connection is now established at both layers, it's time to leave */
6511 conn->flags &= ~(flag | CO_FL_WAIT_L4_CONN | CO_FL_WAIT_L6_CONN);
6512 return 1;
6513
6514 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01006515 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02006516 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01006517 ERR_clear_error();
6518
Emeric Brun9fa89732012-10-04 17:09:56 +02006519 /* free resumed session if exists */
Willy Tarreau07d94e42018-09-20 10:57:52 +02006520 if (objt_server(conn->target) && __objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr) {
6521 free(__objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr);
6522 __objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr = NULL;
Emeric Brun9fa89732012-10-04 17:09:56 +02006523 }
6524
Emeric Brun46591952012-05-18 15:47:34 +02006525 /* Fail on all other handshake errors */
6526 conn->flags |= CO_FL_ERROR;
Willy Tarreau20879a02012-12-03 16:32:10 +01006527 if (!conn->err_code)
6528 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02006529 return 0;
6530}
6531
Willy Tarreauee1a6fc2020-01-17 07:52:13 +01006532/* Called from the upper layer, to subscribe <es> to events <event_type>. The
6533 * event subscriber <es> is not allowed to change from a previous call as long
6534 * as at least one event is still subscribed. The <event_type> must only be a
6535 * combination of SUB_RETRY_RECV and SUB_RETRY_SEND. It always returns 0,
6536 * unless the transport layer was already released.
6537 */
6538static int ssl_subscribe(struct connection *conn, void *xprt_ctx, int event_type, struct wait_event *es)
Olivier Houcharddf357842019-03-21 16:30:07 +01006539{
Olivier Houchardea8dd942019-05-20 14:02:16 +02006540 struct ssl_sock_ctx *ctx = xprt_ctx;
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006541
Olivier Houchard0ff28652019-06-24 18:57:39 +02006542 if (!ctx)
6543 return -1;
6544
Willy Tarreau113d52b2020-01-10 09:20:26 +01006545 BUG_ON(event_type & ~(SUB_RETRY_SEND|SUB_RETRY_RECV));
Willy Tarreauee1a6fc2020-01-17 07:52:13 +01006546 BUG_ON(ctx->subs && ctx->subs != es);
Olivier Houchardea8dd942019-05-20 14:02:16 +02006547
Willy Tarreauee1a6fc2020-01-17 07:52:13 +01006548 ctx->subs = es;
6549 es->events |= event_type;
Willy Tarreau113d52b2020-01-10 09:20:26 +01006550
6551 /* we may have to subscribe to lower layers for new events */
6552 event_type &= ~ctx->wait_event.events;
6553 if (event_type && !(conn->flags & CO_FL_SSL_WAIT_HS))
6554 ctx->xprt->subscribe(conn, ctx->xprt_ctx, event_type, &ctx->wait_event);
Olivier Houchardea8dd942019-05-20 14:02:16 +02006555 return 0;
Olivier Houcharddf357842019-03-21 16:30:07 +01006556}
6557
Willy Tarreauee1a6fc2020-01-17 07:52:13 +01006558/* Called from the upper layer, to unsubscribe <es> from events <event_type>.
6559 * The <es> pointer is not allowed to differ from the one passed to the
6560 * subscribe() call. It always returns zero.
6561 */
6562static int ssl_unsubscribe(struct connection *conn, void *xprt_ctx, int event_type, struct wait_event *es)
Olivier Houcharddf357842019-03-21 16:30:07 +01006563{
Olivier Houchardea8dd942019-05-20 14:02:16 +02006564 struct ssl_sock_ctx *ctx = xprt_ctx;
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006565
Willy Tarreau113d52b2020-01-10 09:20:26 +01006566 BUG_ON(event_type & ~(SUB_RETRY_SEND|SUB_RETRY_RECV));
Willy Tarreauee1a6fc2020-01-17 07:52:13 +01006567 BUG_ON(ctx->subs && ctx->subs != es);
Olivier Houchardea8dd942019-05-20 14:02:16 +02006568
Willy Tarreauee1a6fc2020-01-17 07:52:13 +01006569 es->events &= ~event_type;
6570 if (!es->events)
Willy Tarreau113d52b2020-01-10 09:20:26 +01006571 ctx->subs = NULL;
6572
6573 /* If we subscribed, and we're not doing the handshake,
6574 * then we subscribed because the upper layer asked for it,
6575 * as the upper layer is no longer interested, we can
6576 * unsubscribe too.
6577 */
6578 event_type &= ctx->wait_event.events;
6579 if (event_type && !(ctx->conn->flags & CO_FL_SSL_WAIT_HS))
6580 conn_unsubscribe(conn, ctx->xprt_ctx, event_type, &ctx->wait_event);
Olivier Houchardea8dd942019-05-20 14:02:16 +02006581
6582 return 0;
Olivier Houcharddf357842019-03-21 16:30:07 +01006583}
6584
Olivier Houchard2e055482019-05-27 19:50:12 +02006585/* Use the provided XPRT as an underlying XPRT, and provide the old one.
6586 * Returns 0 on success, and non-zero on failure.
6587 */
6588static 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)
6589{
6590 struct ssl_sock_ctx *ctx = xprt_ctx;
6591
6592 if (oldxprt_ops != NULL)
6593 *oldxprt_ops = ctx->xprt;
6594 if (oldxprt_ctx != NULL)
6595 *oldxprt_ctx = ctx->xprt_ctx;
6596 ctx->xprt = toadd_ops;
6597 ctx->xprt_ctx = toadd_ctx;
6598 return 0;
6599}
6600
Olivier Houchard5149b592019-05-23 17:47:36 +02006601/* Remove the specified xprt. If if it our underlying XPRT, remove it and
6602 * return 0, otherwise just call the remove_xprt method from the underlying
6603 * XPRT.
6604 */
6605static int ssl_remove_xprt(struct connection *conn, void *xprt_ctx, void *toremove_ctx, const struct xprt_ops *newops, void *newctx)
6606{
6607 struct ssl_sock_ctx *ctx = xprt_ctx;
6608
6609 if (ctx->xprt_ctx == toremove_ctx) {
6610 ctx->xprt_ctx = newctx;
6611 ctx->xprt = newops;
6612 return 0;
6613 }
6614 return (ctx->xprt->remove_xprt(conn, ctx->xprt_ctx, toremove_ctx, newops, newctx));
6615}
6616
Olivier Houchardea8dd942019-05-20 14:02:16 +02006617static struct task *ssl_sock_io_cb(struct task *t, void *context, unsigned short state)
6618{
6619 struct ssl_sock_ctx *ctx = context;
6620
6621 /* First if we're doing an handshake, try that */
6622 if (ctx->conn->flags & CO_FL_SSL_WAIT_HS)
6623 ssl_sock_handshake(ctx->conn, CO_FL_SSL_WAIT_HS);
6624 /* If we had an error, or the handshake is done and I/O is available,
6625 * let the upper layer know.
Olivier Houchard477902b2020-01-22 18:08:48 +01006626 * If no mux was set up yet, then call conn_create_mux()
Olivier Houchardea8dd942019-05-20 14:02:16 +02006627 * we can't be sure conn_fd_handler() will be called again.
6628 */
6629 if ((ctx->conn->flags & CO_FL_ERROR) ||
6630 !(ctx->conn->flags & CO_FL_SSL_WAIT_HS)) {
6631 int ret = 0;
6632 int woke = 0;
6633
6634 /* On error, wake any waiter */
Willy Tarreau113d52b2020-01-10 09:20:26 +01006635 if (ctx->subs) {
6636 tasklet_wakeup(ctx->subs->tasklet);
6637 ctx->subs->events = 0;
Olivier Houchardea8dd942019-05-20 14:02:16 +02006638 woke = 1;
Willy Tarreau113d52b2020-01-10 09:20:26 +01006639 ctx->subs = NULL;
Olivier Houchardea8dd942019-05-20 14:02:16 +02006640 }
Willy Tarreau113d52b2020-01-10 09:20:26 +01006641
Olivier Houchardea8dd942019-05-20 14:02:16 +02006642 /* If we're the first xprt for the connection, let the
Olivier Houchard477902b2020-01-22 18:08:48 +01006643 * upper layers know. If we have no mux, create it,
6644 * and once we have a mux, call its wake method if we didn't
6645 * woke a tasklet already.
Olivier Houchardea8dd942019-05-20 14:02:16 +02006646 */
6647 if (ctx->conn->xprt_ctx == ctx) {
Olivier Houchard477902b2020-01-22 18:08:48 +01006648 if (!ctx->conn->mux)
6649 ret = conn_create_mux(ctx->conn);
Olivier Houchardea8dd942019-05-20 14:02:16 +02006650 if (ret >= 0 && !woke && ctx->conn->mux && ctx->conn->mux->wake)
6651 ctx->conn->mux->wake(ctx->conn);
6652 return NULL;
6653 }
6654 }
Olivier Houchard54907bb2019-12-19 15:02:39 +01006655#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
6656 /* If we have early data and somebody wants to receive, let them */
Willy Tarreau113d52b2020-01-10 09:20:26 +01006657 else if (b_data(&ctx->early_buf) && ctx->subs &&
6658 ctx->subs->events & SUB_RETRY_RECV) {
6659 tasklet_wakeup(ctx->subs->tasklet);
6660 ctx->subs->events &= ~SUB_RETRY_RECV;
6661 if (!ctx->subs->events)
6662 ctx->subs = NULL;
Olivier Houchard54907bb2019-12-19 15:02:39 +01006663 }
6664#endif
Olivier Houchardea8dd942019-05-20 14:02:16 +02006665 return NULL;
6666}
6667
Emeric Brun46591952012-05-18 15:47:34 +02006668/* Receive up to <count> bytes from connection <conn>'s socket and store them
Willy Tarreauabf08d92014-01-14 11:31:27 +01006669 * into buffer <buf>. Only one call to recv() is performed, unless the
Emeric Brun46591952012-05-18 15:47:34 +02006670 * buffer wraps, in which case a second call may be performed. The connection's
6671 * flags are updated with whatever special event is detected (error, read0,
6672 * empty). The caller is responsible for taking care of those events and
6673 * avoiding the call if inappropriate. The function does not call the
6674 * connection's polling update function, so the caller is responsible for this.
6675 */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006676static 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 +02006677{
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006678 struct ssl_sock_ctx *ctx = xprt_ctx;
Willy Tarreaubfc4d772018-07-18 11:22:03 +02006679 ssize_t ret;
6680 size_t try, done = 0;
Emeric Brun46591952012-05-18 15:47:34 +02006681
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006682 if (!ctx)
Emeric Brun46591952012-05-18 15:47:34 +02006683 goto out_error;
6684
Olivier Houchard54907bb2019-12-19 15:02:39 +01006685#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
6686 if (b_data(&ctx->early_buf)) {
6687 try = b_contig_space(buf);
6688 if (try > b_data(&ctx->early_buf))
6689 try = b_data(&ctx->early_buf);
6690 memcpy(b_tail(buf), b_head(&ctx->early_buf), try);
6691 b_add(buf, try);
6692 b_del(&ctx->early_buf, try);
6693 if (b_data(&ctx->early_buf) == 0)
6694 b_free(&ctx->early_buf);
6695 return try;
6696 }
6697#endif
6698
Willy Tarreau911db9b2020-01-23 16:27:54 +01006699 if (conn->flags & (CO_FL_WAIT_XPRT | CO_FL_SSL_WAIT_HS))
Emeric Brun46591952012-05-18 15:47:34 +02006700 /* a handshake was requested */
6701 return 0;
6702
Emeric Brun46591952012-05-18 15:47:34 +02006703 /* read the largest possible block. For this, we perform only one call
6704 * to recv() unless the buffer wraps and we exactly fill the first hunk,
6705 * in which case we accept to do it once again. A new attempt is made on
6706 * EINTR too.
6707 */
Willy Tarreau00b0fb92014-01-17 11:09:40 +01006708 while (count > 0) {
Olivier Houchardc2aae742017-09-22 18:26:28 +02006709
Willy Tarreau591d4452018-06-15 17:21:00 +02006710 try = b_contig_space(buf);
6711 if (!try)
6712 break;
6713
Willy Tarreauabf08d92014-01-14 11:31:27 +01006714 if (try > count)
6715 try = count;
Willy Tarreau591d4452018-06-15 17:21:00 +02006716
Olivier Houchard66ab4982019-02-26 18:37:15 +01006717 ret = SSL_read(ctx->ssl, b_tail(buf), try);
Emmanuel Hocdetf967c312019-08-05 18:04:16 +02006718
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) {
Olivier Houchardacd14032018-06-28 18:17:23 +02006724 b_add(buf, ret);
Emeric Brun46591952012-05-18 15:47:34 +02006725 done += ret;
Emeric Brun46591952012-05-18 15:47:34 +02006726 count -= ret;
Emeric Brun46591952012-05-18 15:47:34 +02006727 }
Emeric Brun46591952012-05-18 15:47:34 +02006728 else {
Olivier Houchard66ab4982019-02-26 18:37:15 +01006729 ret = SSL_get_error(ctx->ssl, ret);
Emeric Brun46591952012-05-18 15:47:34 +02006730 if (ret == SSL_ERROR_WANT_WRITE) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01006731 /* handshake is running, and it needs to enable write */
Emeric Brun46591952012-05-18 15:47:34 +02006732 conn->flags |= CO_FL_SSL_WAIT_HS;
Olivier Houchardea8dd942019-05-20 14:02:16 +02006733 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_SEND, &ctx->wait_event);
Willy Tarreau5db847a2019-05-09 14:13:35 +02006734#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00006735 /* Async mode can be re-enabled, because we're leaving data state.*/
6736 if (global_ssl.async)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006737 SSL_set_mode(ctx->ssl, SSL_MODE_ASYNC);
Emeric Brunb5e42a82017-06-06 12:35:14 +00006738#endif
Emeric Brun46591952012-05-18 15:47:34 +02006739 break;
6740 }
6741 else if (ret == SSL_ERROR_WANT_READ) {
Olivier Houchard66ab4982019-02-26 18:37:15 +01006742 if (SSL_renegotiate_pending(ctx->ssl)) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02006743 ctx->xprt->subscribe(conn, ctx->xprt_ctx,
6744 SUB_RETRY_RECV,
6745 &ctx->wait_event);
Emeric Brun282a76a2012-11-08 18:02:56 +01006746 /* handshake is running, and it may need to re-enable read */
6747 conn->flags |= CO_FL_SSL_WAIT_HS;
Willy Tarreau5db847a2019-05-09 14:13:35 +02006748#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00006749 /* Async mode can be re-enabled, because we're leaving data state.*/
6750 if (global_ssl.async)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006751 SSL_set_mode(ctx->ssl, SSL_MODE_ASYNC);
Emeric Brunb5e42a82017-06-06 12:35:14 +00006752#endif
Emeric Brun282a76a2012-11-08 18:02:56 +01006753 break;
6754 }
Emeric Brun46591952012-05-18 15:47:34 +02006755 break;
Olivier Houchardc2aae742017-09-22 18:26:28 +02006756 } else if (ret == SSL_ERROR_ZERO_RETURN)
6757 goto read0;
Christopher Faulet4ac77a92018-02-19 14:25:15 +01006758 /* For SSL_ERROR_SYSCALL, make sure to clear the error
6759 * stack before shutting down the connection for
6760 * reading. */
Olivier Houchard7e2e5052018-02-13 15:17:23 +01006761 if (ret == SSL_ERROR_SYSCALL && (!errno || errno == EAGAIN))
6762 goto clear_ssl_error;
Emeric Brun46591952012-05-18 15:47:34 +02006763 /* otherwise it's a real error */
6764 goto out_error;
6765 }
6766 }
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02006767 leave:
Emeric Brun46591952012-05-18 15:47:34 +02006768 return done;
6769
Christopher Faulet4ac77a92018-02-19 14:25:15 +01006770 clear_ssl_error:
6771 /* Clear openssl global errors stack */
6772 ssl_sock_dump_errors(conn);
6773 ERR_clear_error();
Emeric Brun46591952012-05-18 15:47:34 +02006774 read0:
6775 conn_sock_read0(conn);
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02006776 goto leave;
Christopher Faulet4ac77a92018-02-19 14:25:15 +01006777
Emeric Brun46591952012-05-18 15:47:34 +02006778 out_error:
Olivier Houchard7e2e5052018-02-13 15:17:23 +01006779 conn->flags |= CO_FL_ERROR;
Emeric Brun644cde02012-12-14 11:21:13 +01006780 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02006781 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01006782 ERR_clear_error();
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02006783 goto leave;
Emeric Brun46591952012-05-18 15:47:34 +02006784}
6785
6786
Willy Tarreau787db9a2018-06-14 18:31:46 +02006787/* Send up to <count> pending bytes from buffer <buf> to connection <conn>'s
6788 * socket. <flags> may contain some CO_SFL_* flags to hint the system about
6789 * other pending data for example, but this flag is ignored at the moment.
Emeric Brun46591952012-05-18 15:47:34 +02006790 * Only one call to send() is performed, unless the buffer wraps, in which case
6791 * a second call may be performed. The connection's flags are updated with
6792 * whatever special event is detected (error, empty). The caller is responsible
6793 * for taking care of those events and avoiding the call if inappropriate. The
6794 * function does not call the connection's polling update function, so the caller
Willy Tarreau787db9a2018-06-14 18:31:46 +02006795 * is responsible for this. The buffer's output is not adjusted, it's up to the
6796 * caller to take care of this. It's up to the caller to update the buffer's
6797 * contents based on the return value.
Emeric Brun46591952012-05-18 15:47:34 +02006798 */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006799static 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 +02006800{
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006801 struct ssl_sock_ctx *ctx = xprt_ctx;
Willy Tarreau787db9a2018-06-14 18:31:46 +02006802 ssize_t ret;
6803 size_t try, done;
Emeric Brun46591952012-05-18 15:47:34 +02006804
6805 done = 0;
6806
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006807 if (!ctx)
Emeric Brun46591952012-05-18 15:47:34 +02006808 goto out_error;
6809
Willy Tarreau911db9b2020-01-23 16:27:54 +01006810 if (conn->flags & (CO_FL_WAIT_XPRT | CO_FL_SSL_WAIT_HS | CO_FL_EARLY_SSL_HS))
Emeric Brun46591952012-05-18 15:47:34 +02006811 /* a handshake was requested */
6812 return 0;
6813
6814 /* send the largest possible block. For this we perform only one call
6815 * to send() unless the buffer wraps and we exactly fill the first hunk,
6816 * in which case we accept to do it once again.
6817 */
Willy Tarreau787db9a2018-06-14 18:31:46 +02006818 while (count) {
Willy Tarreau5db847a2019-05-09 14:13:35 +02006819#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Olivier Houchardc2aae742017-09-22 18:26:28 +02006820 size_t written_data;
6821#endif
6822
Willy Tarreau787db9a2018-06-14 18:31:46 +02006823 try = b_contig_data(buf, done);
6824 if (try > count)
6825 try = count;
Willy Tarreaubfd59462013-02-21 07:46:09 +01006826
Willy Tarreau7bed9452014-02-02 02:00:24 +01006827 if (!(flags & CO_SFL_STREAMER) &&
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006828 !(ctx->xprt_st & SSL_SOCK_SEND_UNLIMITED) &&
Willy Tarreauef934602016-12-22 23:12:01 +01006829 global_ssl.max_record && try > global_ssl.max_record) {
6830 try = global_ssl.max_record;
Willy Tarreau518cedd2014-02-17 15:43:01 +01006831 }
6832 else {
6833 /* we need to keep the information about the fact that
6834 * we're not limiting the upcoming send(), because if it
6835 * fails, we'll have to retry with at least as many data.
6836 */
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006837 ctx->xprt_st |= SSL_SOCK_SEND_UNLIMITED;
Willy Tarreau518cedd2014-02-17 15:43:01 +01006838 }
Willy Tarreaubfd59462013-02-21 07:46:09 +01006839
Willy Tarreau5db847a2019-05-09 14:13:35 +02006840#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Olivier Houchard010941f2019-05-03 20:56:19 +02006841 if (!SSL_is_init_finished(ctx->ssl) && conn_is_back(conn)) {
Olivier Houchardc2aae742017-09-22 18:26:28 +02006842 unsigned int max_early;
6843
Olivier Houchard522eea72017-11-03 16:27:47 +01006844 if (objt_listener(conn->target))
Olivier Houchard66ab4982019-02-26 18:37:15 +01006845 max_early = SSL_get_max_early_data(ctx->ssl);
Olivier Houchard522eea72017-11-03 16:27:47 +01006846 else {
Olivier Houchard66ab4982019-02-26 18:37:15 +01006847 if (SSL_get0_session(ctx->ssl))
6848 max_early = SSL_SESSION_get_max_early_data(SSL_get0_session(ctx->ssl));
Olivier Houchard522eea72017-11-03 16:27:47 +01006849 else
6850 max_early = 0;
6851 }
6852
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006853 if (try + ctx->sent_early_data > max_early) {
6854 try -= (try + ctx->sent_early_data) - max_early;
Olivier Houchard522eea72017-11-03 16:27:47 +01006855 if (try <= 0) {
Olivier Houchard010941f2019-05-03 20:56:19 +02006856 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Olivier Houchard965e84e2019-06-15 20:59:30 +02006857 tasklet_wakeup(ctx->wait_event.tasklet);
Olivier Houchardc2aae742017-09-22 18:26:28 +02006858 break;
Olivier Houchard522eea72017-11-03 16:27:47 +01006859 }
Olivier Houchardc2aae742017-09-22 18:26:28 +02006860 }
Olivier Houchard66ab4982019-02-26 18:37:15 +01006861 ret = SSL_write_early_data(ctx->ssl, b_peek(buf, done), try, &written_data);
Olivier Houchardc2aae742017-09-22 18:26:28 +02006862 if (ret == 1) {
6863 ret = written_data;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006864 ctx->sent_early_data += ret;
Olivier Houchard965e84e2019-06-15 20:59:30 +02006865 if (objt_server(conn->target)) {
Olivier Houchard522eea72017-11-03 16:27:47 +01006866 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN | CO_FL_EARLY_DATA;
Olivier Houchard965e84e2019-06-15 20:59:30 +02006867 /* Initiate the handshake, now */
6868 tasklet_wakeup(ctx->wait_event.tasklet);
6869 }
Olivier Houchard522eea72017-11-03 16:27:47 +01006870
Olivier Houchardc2aae742017-09-22 18:26:28 +02006871 }
6872
6873 } else
6874#endif
Olivier Houchard66ab4982019-02-26 18:37:15 +01006875 ret = SSL_write(ctx->ssl, b_peek(buf, done), try);
Willy Tarreau518cedd2014-02-17 15:43:01 +01006876
Emeric Brune1f38db2012-09-03 20:36:47 +02006877 if (conn->flags & CO_FL_ERROR) {
6878 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01006879 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02006880 }
Emeric Brun46591952012-05-18 15:47:34 +02006881 if (ret > 0) {
Willy Tarreauc192b0a2020-01-23 09:11:58 +01006882 /* A send succeeded, so we can consider ourself connected */
6883 conn->flags &= ~CO_FL_WAIT_L4L6;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006884 ctx->xprt_st &= ~SSL_SOCK_SEND_UNLIMITED;
Willy Tarreau787db9a2018-06-14 18:31:46 +02006885 count -= ret;
Emeric Brun46591952012-05-18 15:47:34 +02006886 done += ret;
Emeric Brun46591952012-05-18 15:47:34 +02006887 }
6888 else {
Olivier Houchard66ab4982019-02-26 18:37:15 +01006889 ret = SSL_get_error(ctx->ssl, ret);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006890
Emeric Brun46591952012-05-18 15:47:34 +02006891 if (ret == SSL_ERROR_WANT_WRITE) {
Olivier Houchard66ab4982019-02-26 18:37:15 +01006892 if (SSL_renegotiate_pending(ctx->ssl)) {
Emeric Brun282a76a2012-11-08 18:02:56 +01006893 /* handshake is running, and it may need to re-enable write */
6894 conn->flags |= CO_FL_SSL_WAIT_HS;
Olivier Houchardea8dd942019-05-20 14:02:16 +02006895 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_SEND, &ctx->wait_event);
Willy Tarreau5db847a2019-05-09 14:13:35 +02006896#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00006897 /* Async mode can be re-enabled, because we're leaving data state.*/
6898 if (global_ssl.async)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006899 SSL_set_mode(ctx->ssl, SSL_MODE_ASYNC);
Emeric Brunb5e42a82017-06-06 12:35:14 +00006900#endif
Emeric Brun282a76a2012-11-08 18:02:56 +01006901 break;
6902 }
Olivier Houchardea8dd942019-05-20 14:02:16 +02006903
Emeric Brun46591952012-05-18 15:47:34 +02006904 break;
6905 }
6906 else if (ret == SSL_ERROR_WANT_READ) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01006907 /* handshake is running, and it needs to enable read */
Emeric Brun46591952012-05-18 15:47:34 +02006908 conn->flags |= CO_FL_SSL_WAIT_HS;
Olivier Houchardea8dd942019-05-20 14:02:16 +02006909 ctx->xprt->subscribe(conn, ctx->xprt_ctx,
6910 SUB_RETRY_RECV,
6911 &ctx->wait_event);
Willy Tarreau5db847a2019-05-09 14:13:35 +02006912#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00006913 /* Async mode can be re-enabled, because we're leaving data state.*/
6914 if (global_ssl.async)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006915 SSL_set_mode(ctx->ssl, SSL_MODE_ASYNC);
Emeric Brunb5e42a82017-06-06 12:35:14 +00006916#endif
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006917 break;
6918 }
Emeric Brun46591952012-05-18 15:47:34 +02006919 goto out_error;
6920 }
6921 }
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02006922 leave:
Emeric Brun46591952012-05-18 15:47:34 +02006923 return done;
6924
6925 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01006926 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02006927 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01006928 ERR_clear_error();
6929
Emeric Brun46591952012-05-18 15:47:34 +02006930 conn->flags |= CO_FL_ERROR;
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02006931 goto leave;
Emeric Brun46591952012-05-18 15:47:34 +02006932}
6933
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006934static void ssl_sock_close(struct connection *conn, void *xprt_ctx) {
Emeric Brun46591952012-05-18 15:47:34 +02006935
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006936 struct ssl_sock_ctx *ctx = xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006937
Olivier Houchardea8dd942019-05-20 14:02:16 +02006938
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006939 if (ctx) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02006940 if (ctx->wait_event.events != 0)
6941 ctx->xprt->unsubscribe(ctx->conn, ctx->xprt_ctx,
6942 ctx->wait_event.events,
6943 &ctx->wait_event);
Willy Tarreau113d52b2020-01-10 09:20:26 +01006944 if (ctx->subs) {
6945 ctx->subs->events = 0;
6946 tasklet_wakeup(ctx->subs->tasklet);
Olivier Houchardea8dd942019-05-20 14:02:16 +02006947 }
Willy Tarreau113d52b2020-01-10 09:20:26 +01006948
Olivier Houchard692c1d02019-05-23 18:41:47 +02006949 if (ctx->xprt->close)
6950 ctx->xprt->close(conn, ctx->xprt_ctx);
Willy Tarreau5db847a2019-05-09 14:13:35 +02006951#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brun3854e012017-05-17 20:42:48 +02006952 if (global_ssl.async) {
6953 OSSL_ASYNC_FD all_fd[32], afd;
6954 size_t num_all_fds = 0;
6955 int i;
6956
Olivier Houchard66ab4982019-02-26 18:37:15 +01006957 SSL_get_all_async_fds(ctx->ssl, NULL, &num_all_fds);
Emeric Brun3854e012017-05-17 20:42:48 +02006958 if (num_all_fds > 32) {
6959 send_log(NULL, LOG_EMERG, "haproxy: openssl returns too many async fds. It seems a bug. Process may crash\n");
6960 return;
6961 }
6962
Olivier Houchard66ab4982019-02-26 18:37:15 +01006963 SSL_get_all_async_fds(ctx->ssl, all_fd, &num_all_fds);
Emeric Brun3854e012017-05-17 20:42:48 +02006964
6965 /* If an async job is pending, we must try to
6966 to catch the end using polling before calling
6967 SSL_free */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006968 if (num_all_fds && SSL_waiting_for_async(ctx->ssl)) {
Emeric Brun3854e012017-05-17 20:42:48 +02006969 for (i=0 ; i < num_all_fds ; i++) {
6970 /* switch on an handler designed to
6971 * handle the SSL_free
6972 */
6973 afd = all_fd[i];
6974 fdtab[afd].iocb = ssl_async_fd_free;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006975 fdtab[afd].owner = ctx->ssl;
Emeric Brun3854e012017-05-17 20:42:48 +02006976 fd_want_recv(afd);
Emeric Brunce9e01c2017-05-31 10:02:53 +00006977 /* To ensure that the fd cache won't be used
6978 * and we'll catch a real RD event.
6979 */
6980 fd_cant_recv(afd);
Emeric Brun3854e012017-05-17 20:42:48 +02006981 }
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02006982 tasklet_free(ctx->wait_event.tasklet);
Olivier Houchard66ab4982019-02-26 18:37:15 +01006983 pool_free(ssl_sock_ctx_pool, ctx);
Olivier Houchard2be5a4c2019-03-08 18:54:43 +01006984 _HA_ATOMIC_ADD(&jobs, 1);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006985 return;
6986 }
Emeric Brun3854e012017-05-17 20:42:48 +02006987 /* Else we can remove the fds from the fdtab
6988 * and call SSL_free.
6989 * note: we do a fd_remove and not a delete
6990 * because the fd is owned by the engine.
6991 * the engine is responsible to close
6992 */
6993 for (i=0 ; i < num_all_fds ; i++)
6994 fd_remove(all_fd[i]);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006995 }
6996#endif
Olivier Houchard66ab4982019-02-26 18:37:15 +01006997 SSL_free(ctx->ssl);
Olivier Houchard54907bb2019-12-19 15:02:39 +01006998 b_free(&ctx->early_buf);
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02006999 tasklet_free(ctx->wait_event.tasklet);
Olivier Houchard66ab4982019-02-26 18:37:15 +01007000 pool_free(ssl_sock_ctx_pool, ctx);
Olivier Houchard2be5a4c2019-03-08 18:54:43 +01007001 _HA_ATOMIC_SUB(&sslconns, 1);
Emeric Brun46591952012-05-18 15:47:34 +02007002 }
Emeric Brun46591952012-05-18 15:47:34 +02007003}
7004
7005/* This function tries to perform a clean shutdown on an SSL connection, and in
7006 * any case, flags the connection as reusable if no handshake was in progress.
7007 */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01007008static void ssl_sock_shutw(struct connection *conn, void *xprt_ctx, int clean)
Emeric Brun46591952012-05-18 15:47:34 +02007009{
Olivier Houcharde179d0e2019-03-21 18:27:17 +01007010 struct ssl_sock_ctx *ctx = xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007011
Willy Tarreau911db9b2020-01-23 16:27:54 +01007012 if (conn->flags & (CO_FL_WAIT_XPRT | CO_FL_SSL_WAIT_HS))
Emeric Brun46591952012-05-18 15:47:34 +02007013 return;
Emmanuel Hocdet405ff312017-01-08 14:07:39 +01007014 if (!clean)
7015 /* don't sent notify on SSL_shutdown */
Olivier Houchard66ab4982019-02-26 18:37:15 +01007016 SSL_set_quiet_shutdown(ctx->ssl, 1);
Emeric Brun46591952012-05-18 15:47:34 +02007017 /* no handshake was in progress, try a clean ssl shutdown */
Olivier Houchard66ab4982019-02-26 18:37:15 +01007018 if (SSL_shutdown(ctx->ssl) <= 0) {
Emeric Brun644cde02012-12-14 11:21:13 +01007019 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02007020 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01007021 ERR_clear_error();
7022 }
Emeric Brun46591952012-05-18 15:47:34 +02007023}
7024
William Lallemandd4f946c2019-12-05 10:26:40 +01007025/* fill a buffer with the algorithm and size of a public key */
7026static int cert_get_pkey_algo(X509 *crt, struct buffer *out)
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01007027{
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01007028 int bits = 0;
7029 int sig = TLSEXT_signature_anonymous;
7030 int len = -1;
Emmanuel Hocdetc3775d22019-11-04 18:19:32 +01007031 EVP_PKEY *pkey;
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01007032
Emmanuel Hocdetc3775d22019-11-04 18:19:32 +01007033 pkey = X509_get_pubkey(crt);
7034 if (pkey) {
7035 bits = EVP_PKEY_bits(pkey);
7036 switch(EVP_PKEY_base_id(pkey)) {
7037 case EVP_PKEY_RSA:
7038 sig = TLSEXT_signature_rsa;
7039 break;
7040 case EVP_PKEY_EC:
7041 sig = TLSEXT_signature_ecdsa;
7042 break;
7043 case EVP_PKEY_DSA:
7044 sig = TLSEXT_signature_dsa;
7045 break;
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01007046 }
Emmanuel Hocdetc3775d22019-11-04 18:19:32 +01007047 EVP_PKEY_free(pkey);
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01007048 }
7049
7050 switch(sig) {
7051 case TLSEXT_signature_rsa:
7052 len = chunk_printf(out, "RSA%d", bits);
7053 break;
7054 case TLSEXT_signature_ecdsa:
7055 len = chunk_printf(out, "EC%d", bits);
7056 break;
7057 case TLSEXT_signature_dsa:
7058 len = chunk_printf(out, "DSA%d", bits);
7059 break;
7060 default:
7061 return 0;
7062 }
7063 if (len < 0)
7064 return 0;
7065 return 1;
7066}
7067
William Lallemandd4f946c2019-12-05 10:26:40 +01007068/* used for ppv2 pkey alog (can be used for logging) */
7069int ssl_sock_get_pkey_algo(struct connection *conn, struct buffer *out)
7070{
7071 struct ssl_sock_ctx *ctx;
7072 X509 *crt;
7073
7074 if (!ssl_sock_is_ssl(conn))
7075 return 0;
7076
7077 ctx = conn->xprt_ctx;
7078
7079 crt = SSL_get_certificate(ctx->ssl);
7080 if (!crt)
7081 return 0;
7082
7083 return cert_get_pkey_algo(crt, out);
7084}
7085
Emmanuel Hocdet283e0042017-11-02 14:05:23 +01007086/* used for ppv2 cert signature (can be used for logging) */
7087const char *ssl_sock_get_cert_sig(struct connection *conn)
7088{
Christopher Faulet82004142019-09-10 10:12:03 +02007089 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007090
Emmanuel Hocdet283e0042017-11-02 14:05:23 +01007091 __OPENSSL_110_CONST__ ASN1_OBJECT *algorithm;
7092 X509 *crt;
7093
7094 if (!ssl_sock_is_ssl(conn))
7095 return NULL;
Christopher Faulet82004142019-09-10 10:12:03 +02007096 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007097 crt = SSL_get_certificate(ctx->ssl);
Emmanuel Hocdet283e0042017-11-02 14:05:23 +01007098 if (!crt)
7099 return NULL;
7100 X509_ALGOR_get0(&algorithm, NULL, NULL, X509_get0_tbs_sigalg(crt));
7101 return OBJ_nid2sn(OBJ_obj2nid(algorithm));
7102}
7103
Emmanuel Hocdet253c3b72018-02-01 18:29:59 +01007104/* used for ppv2 authority */
7105const char *ssl_sock_get_sni(struct connection *conn)
7106{
7107#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Christopher Faulet82004142019-09-10 10:12:03 +02007108 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007109
Emmanuel Hocdet253c3b72018-02-01 18:29:59 +01007110 if (!ssl_sock_is_ssl(conn))
7111 return NULL;
Christopher Faulet82004142019-09-10 10:12:03 +02007112 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007113 return SSL_get_servername(ctx->ssl, TLSEXT_NAMETYPE_host_name);
Emmanuel Hocdet253c3b72018-02-01 18:29:59 +01007114#else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007115 return NULL;
Emmanuel Hocdet253c3b72018-02-01 18:29:59 +01007116#endif
7117}
7118
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02007119/* used for logging/ppv2, may be changed for a sample fetch later */
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02007120const char *ssl_sock_get_cipher_name(struct connection *conn)
7121{
Christopher Faulet82004142019-09-10 10:12:03 +02007122 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007123
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02007124 if (!ssl_sock_is_ssl(conn))
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02007125 return NULL;
Christopher Faulet82004142019-09-10 10:12:03 +02007126 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007127 return SSL_get_cipher_name(ctx->ssl);
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02007128}
7129
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02007130/* used for logging/ppv2, may be changed for a sample fetch later */
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02007131const char *ssl_sock_get_proto_version(struct connection *conn)
7132{
Christopher Faulet82004142019-09-10 10:12:03 +02007133 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007134
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02007135 if (!ssl_sock_is_ssl(conn))
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02007136 return NULL;
Christopher Faulet82004142019-09-10 10:12:03 +02007137 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007138 return SSL_get_version(ctx->ssl);
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02007139}
7140
Willy Tarreau8d598402012-10-22 17:58:39 +02007141/* Extract a serial from a cert, and copy it to a chunk.
7142 * Returns 1 if serial is found and copied, 0 if no serial found and
7143 * -1 if output is not large enough.
7144 */
7145static int
Willy Tarreau83061a82018-07-13 11:56:34 +02007146ssl_sock_get_serial(X509 *crt, struct buffer *out)
Willy Tarreau8d598402012-10-22 17:58:39 +02007147{
7148 ASN1_INTEGER *serial;
7149
7150 serial = X509_get_serialNumber(crt);
7151 if (!serial)
7152 return 0;
7153
7154 if (out->size < serial->length)
7155 return -1;
7156
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007157 memcpy(out->area, serial->data, serial->length);
7158 out->data = serial->length;
Willy Tarreau8d598402012-10-22 17:58:39 +02007159 return 1;
7160}
7161
Emeric Brun43e79582014-10-29 19:03:26 +01007162/* Extract a cert to der, and copy it to a chunk.
Joseph Herlant017b3da2018-11-15 09:07:59 -08007163 * Returns 1 if the cert is found and copied, 0 on der conversion failure
7164 * and -1 if the output is not large enough.
Emeric Brun43e79582014-10-29 19:03:26 +01007165 */
7166static int
Willy Tarreau83061a82018-07-13 11:56:34 +02007167ssl_sock_crt2der(X509 *crt, struct buffer *out)
Emeric Brun43e79582014-10-29 19:03:26 +01007168{
7169 int len;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007170 unsigned char *p = (unsigned char *) out->area;;
Emeric Brun43e79582014-10-29 19:03:26 +01007171
7172 len =i2d_X509(crt, NULL);
7173 if (len <= 0)
7174 return 1;
7175
7176 if (out->size < len)
7177 return -1;
7178
7179 i2d_X509(crt,&p);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007180 out->data = len;
Emeric Brun43e79582014-10-29 19:03:26 +01007181 return 1;
7182}
7183
Emeric Brunce5ad802012-10-22 14:11:22 +02007184
Willy Tarreau83061a82018-07-13 11:56:34 +02007185/* Copy Date in ASN1_UTCTIME format in struct buffer out.
Emeric Brunce5ad802012-10-22 14:11:22 +02007186 * Returns 1 if serial is found and copied, 0 if no valid time found
7187 * and -1 if output is not large enough.
7188 */
7189static int
Willy Tarreau83061a82018-07-13 11:56:34 +02007190ssl_sock_get_time(ASN1_TIME *tm, struct buffer *out)
Emeric Brunce5ad802012-10-22 14:11:22 +02007191{
7192 if (tm->type == V_ASN1_GENERALIZEDTIME) {
7193 ASN1_GENERALIZEDTIME *gentm = (ASN1_GENERALIZEDTIME *)tm;
7194
7195 if (gentm->length < 12)
7196 return 0;
7197 if (gentm->data[0] != 0x32 || gentm->data[1] != 0x30)
7198 return 0;
7199 if (out->size < gentm->length-2)
7200 return -1;
7201
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007202 memcpy(out->area, gentm->data+2, gentm->length-2);
7203 out->data = gentm->length-2;
Emeric Brunce5ad802012-10-22 14:11:22 +02007204 return 1;
7205 }
7206 else if (tm->type == V_ASN1_UTCTIME) {
7207 ASN1_UTCTIME *utctm = (ASN1_UTCTIME *)tm;
7208
7209 if (utctm->length < 10)
7210 return 0;
7211 if (utctm->data[0] >= 0x35)
7212 return 0;
7213 if (out->size < utctm->length)
7214 return -1;
7215
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007216 memcpy(out->area, utctm->data, utctm->length);
7217 out->data = utctm->length;
Emeric Brunce5ad802012-10-22 14:11:22 +02007218 return 1;
7219 }
7220
7221 return 0;
7222}
7223
Emeric Brun87855892012-10-17 17:39:35 +02007224/* Extract an entry from a X509_NAME and copy its value to an output chunk.
7225 * Returns 1 if entry found, 0 if entry not found, or -1 if output not large enough.
7226 */
7227static int
Willy Tarreau83061a82018-07-13 11:56:34 +02007228ssl_sock_get_dn_entry(X509_NAME *a, const struct buffer *entry, int pos,
7229 struct buffer *out)
Emeric Brun87855892012-10-17 17:39:35 +02007230{
7231 X509_NAME_ENTRY *ne;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007232 ASN1_OBJECT *obj;
7233 ASN1_STRING *data;
7234 const unsigned char *data_ptr;
7235 int data_len;
Emeric Brun87855892012-10-17 17:39:35 +02007236 int i, j, n;
7237 int cur = 0;
7238 const char *s;
7239 char tmp[128];
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007240 int name_count;
7241
7242 name_count = X509_NAME_entry_count(a);
Emeric Brun87855892012-10-17 17:39:35 +02007243
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007244 out->data = 0;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007245 for (i = 0; i < name_count; i++) {
Emeric Brun87855892012-10-17 17:39:35 +02007246 if (pos < 0)
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007247 j = (name_count-1) - i;
Emeric Brun87855892012-10-17 17:39:35 +02007248 else
7249 j = i;
7250
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007251 ne = X509_NAME_get_entry(a, j);
7252 obj = X509_NAME_ENTRY_get_object(ne);
7253 data = X509_NAME_ENTRY_get_data(ne);
7254 data_ptr = ASN1_STRING_get0_data(data);
7255 data_len = ASN1_STRING_length(data);
7256 n = OBJ_obj2nid(obj);
Emeric Brun87855892012-10-17 17:39:35 +02007257 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007258 i2t_ASN1_OBJECT(tmp, sizeof(tmp), obj);
Emeric Brun87855892012-10-17 17:39:35 +02007259 s = tmp;
7260 }
7261
7262 if (chunk_strcasecmp(entry, s) != 0)
7263 continue;
7264
7265 if (pos < 0)
7266 cur--;
7267 else
7268 cur++;
7269
7270 if (cur != pos)
7271 continue;
7272
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007273 if (data_len > out->size)
Emeric Brun87855892012-10-17 17:39:35 +02007274 return -1;
7275
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007276 memcpy(out->area, data_ptr, data_len);
7277 out->data = data_len;
Emeric Brun87855892012-10-17 17:39:35 +02007278 return 1;
7279 }
7280
7281 return 0;
7282
William Lallemandd4f946c2019-12-05 10:26:40 +01007283}
7284
7285/*
7286 * Extract and format the DNS SAN extensions and copy result into a chuink
7287 * Return 0;
7288 */
7289#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
7290static int ssl_sock_get_san_oneline(X509 *cert, struct buffer *out)
7291{
7292 int i;
7293 char *str;
7294 STACK_OF(GENERAL_NAME) *names = NULL;
7295
7296 names = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
7297 if (names) {
7298 for (i = 0; i < sk_GENERAL_NAME_num(names); i++) {
7299 GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i);
7300 if (i > 0)
7301 chunk_appendf(out, ", ");
7302 if (name->type == GEN_DNS) {
7303 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
7304 chunk_appendf(out, "DNS:%s", str);
7305 OPENSSL_free(str);
7306 }
7307 }
7308 }
7309 sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
7310 }
7311 return 0;
Emeric Brun87855892012-10-17 17:39:35 +02007312}
William Lallemandd4f946c2019-12-05 10:26:40 +01007313#endif
Emeric Brun87855892012-10-17 17:39:35 +02007314
Elliot Otchet71f82972020-01-15 08:12:14 -05007315/*
7316 * Extract the DN in the specified format from the X509_NAME and copy result to a chunk.
7317 * Currently supports rfc2253 for returning LDAP V3 DNs.
7318 * Returns 1 if dn entries exist, 0 if no dn entry was found.
7319 */
7320static int
7321ssl_sock_get_dn_formatted(X509_NAME *a, const struct buffer *format, struct buffer *out)
7322{
7323 BIO *bio = NULL;
7324 int ret = 0;
7325 int data_len = 0;
7326
7327 if (chunk_strcmp(format, "rfc2253") == 0) {
7328 bio = BIO_new(BIO_s_mem());
7329 if (bio == NULL)
7330 goto out;
7331
7332 if (X509_NAME_print_ex(bio, a, 0, XN_FLAG_RFC2253) < 0)
7333 goto out;
7334
7335 if ((data_len = BIO_read(bio, out->area, out->size)) <= 0)
7336 goto out;
7337
7338 out->data = data_len;
7339
7340 ret = 1;
7341 }
7342out:
7343 if (bio)
7344 BIO_free(bio);
7345 return ret;
7346}
7347
Emeric Brun87855892012-10-17 17:39:35 +02007348/* Extract and format full DN from a X509_NAME and copy result into a chunk
7349 * Returns 1 if dn entries exits, 0 if no dn entry found or -1 if output is not large enough.
7350 */
7351static int
Willy Tarreau83061a82018-07-13 11:56:34 +02007352ssl_sock_get_dn_oneline(X509_NAME *a, struct buffer *out)
Emeric Brun87855892012-10-17 17:39:35 +02007353{
7354 X509_NAME_ENTRY *ne;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007355 ASN1_OBJECT *obj;
7356 ASN1_STRING *data;
7357 const unsigned char *data_ptr;
7358 int data_len;
Emeric Brun87855892012-10-17 17:39:35 +02007359 int i, n, ln;
7360 int l = 0;
7361 const char *s;
7362 char *p;
7363 char tmp[128];
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007364 int name_count;
7365
7366
7367 name_count = X509_NAME_entry_count(a);
Emeric Brun87855892012-10-17 17:39:35 +02007368
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007369 out->data = 0;
7370 p = out->area;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007371 for (i = 0; i < name_count; i++) {
7372 ne = X509_NAME_get_entry(a, i);
7373 obj = X509_NAME_ENTRY_get_object(ne);
7374 data = X509_NAME_ENTRY_get_data(ne);
7375 data_ptr = ASN1_STRING_get0_data(data);
7376 data_len = ASN1_STRING_length(data);
7377 n = OBJ_obj2nid(obj);
Emeric Brun87855892012-10-17 17:39:35 +02007378 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007379 i2t_ASN1_OBJECT(tmp, sizeof(tmp), obj);
Emeric Brun87855892012-10-17 17:39:35 +02007380 s = tmp;
7381 }
7382 ln = strlen(s);
7383
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007384 l += 1 + ln + 1 + data_len;
Emeric Brun87855892012-10-17 17:39:35 +02007385 if (l > out->size)
7386 return -1;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007387 out->data = l;
Emeric Brun87855892012-10-17 17:39:35 +02007388
7389 *(p++)='/';
7390 memcpy(p, s, ln);
7391 p += ln;
7392 *(p++)='=';
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007393 memcpy(p, data_ptr, data_len);
7394 p += data_len;
Emeric Brun87855892012-10-17 17:39:35 +02007395 }
7396
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007397 if (!out->data)
Emeric Brun87855892012-10-17 17:39:35 +02007398 return 0;
7399
7400 return 1;
7401}
7402
Olivier Houchardab28a322018-12-21 19:45:40 +01007403void ssl_sock_set_alpn(struct connection *conn, const unsigned char *alpn, int len)
7404{
7405#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Christopher Faulet82004142019-09-10 10:12:03 +02007406 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007407
Olivier Houcharde488ea82019-06-28 14:10:33 +02007408 if (!ssl_sock_is_ssl(conn))
7409 return;
Christopher Faulet82004142019-09-10 10:12:03 +02007410 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007411 SSL_set_alpn_protos(ctx->ssl, alpn, len);
Olivier Houchardab28a322018-12-21 19:45:40 +01007412#endif
7413}
7414
Willy Tarreau119a4082016-12-22 21:58:38 +01007415/* Sets advertised SNI for outgoing connections. Please set <hostname> to NULL
7416 * to disable SNI.
7417 */
Willy Tarreau63076412015-07-10 11:33:32 +02007418void ssl_sock_set_servername(struct connection *conn, const char *hostname)
7419{
7420#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Christopher Faulet82004142019-09-10 10:12:03 +02007421 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007422
Willy Tarreau119a4082016-12-22 21:58:38 +01007423 char *prev_name;
7424
Willy Tarreau63076412015-07-10 11:33:32 +02007425 if (!ssl_sock_is_ssl(conn))
7426 return;
Christopher Faulet82004142019-09-10 10:12:03 +02007427 ctx = conn->xprt_ctx;
Willy Tarreau63076412015-07-10 11:33:32 +02007428
Willy Tarreau119a4082016-12-22 21:58:38 +01007429 /* if the SNI changes, we must destroy the reusable context so that a
7430 * new connection will present a new SNI. As an optimization we could
7431 * later imagine having a small cache of ssl_ctx to hold a few SNI per
7432 * server.
7433 */
Olivier Houchard66ab4982019-02-26 18:37:15 +01007434 prev_name = (char *)SSL_get_servername(ctx->ssl, TLSEXT_NAMETYPE_host_name);
Willy Tarreau119a4082016-12-22 21:58:38 +01007435 if ((!prev_name && hostname) ||
7436 (prev_name && (!hostname || strcmp(hostname, prev_name) != 0)))
Olivier Houchard66ab4982019-02-26 18:37:15 +01007437 SSL_set_session(ctx->ssl, NULL);
Willy Tarreau119a4082016-12-22 21:58:38 +01007438
Olivier Houchard66ab4982019-02-26 18:37:15 +01007439 SSL_set_tlsext_host_name(ctx->ssl, hostname);
Willy Tarreau63076412015-07-10 11:33:32 +02007440#endif
7441}
7442
Emeric Brun0abf8362014-06-24 18:26:41 +02007443/* Extract peer certificate's common name into the chunk dest
7444 * Returns
7445 * the len of the extracted common name
7446 * or 0 if no CN found in DN
7447 * or -1 on error case (i.e. no peer certificate)
7448 */
Willy Tarreau83061a82018-07-13 11:56:34 +02007449int ssl_sock_get_remote_common_name(struct connection *conn,
7450 struct buffer *dest)
David Safb76832014-05-08 23:42:08 -04007451{
Christopher Faulet82004142019-09-10 10:12:03 +02007452 struct ssl_sock_ctx *ctx;
David Safb76832014-05-08 23:42:08 -04007453 X509 *crt = NULL;
7454 X509_NAME *name;
David Safb76832014-05-08 23:42:08 -04007455 const char find_cn[] = "CN";
Willy Tarreau83061a82018-07-13 11:56:34 +02007456 const struct buffer find_cn_chunk = {
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007457 .area = (char *)&find_cn,
7458 .data = sizeof(find_cn)-1
David Safb76832014-05-08 23:42:08 -04007459 };
Emeric Brun0abf8362014-06-24 18:26:41 +02007460 int result = -1;
David Safb76832014-05-08 23:42:08 -04007461
7462 if (!ssl_sock_is_ssl(conn))
Emeric Brun0abf8362014-06-24 18:26:41 +02007463 goto out;
Christopher Faulet82004142019-09-10 10:12:03 +02007464 ctx = conn->xprt_ctx;
David Safb76832014-05-08 23:42:08 -04007465
7466 /* SSL_get_peer_certificate, it increase X509 * ref count */
Olivier Houchard66ab4982019-02-26 18:37:15 +01007467 crt = SSL_get_peer_certificate(ctx->ssl);
David Safb76832014-05-08 23:42:08 -04007468 if (!crt)
7469 goto out;
7470
7471 name = X509_get_subject_name(crt);
7472 if (!name)
7473 goto out;
David Safb76832014-05-08 23:42:08 -04007474
Emeric Brun0abf8362014-06-24 18:26:41 +02007475 result = ssl_sock_get_dn_entry(name, &find_cn_chunk, 1, dest);
7476out:
David Safb76832014-05-08 23:42:08 -04007477 if (crt)
7478 X509_free(crt);
7479
7480 return result;
7481}
7482
Dave McCowan328fb582014-07-30 10:39:13 -04007483/* returns 1 if client passed a certificate for this session, 0 if not */
7484int ssl_sock_get_cert_used_sess(struct connection *conn)
7485{
Christopher Faulet82004142019-09-10 10:12:03 +02007486 struct ssl_sock_ctx *ctx;
Dave McCowan328fb582014-07-30 10:39:13 -04007487 X509 *crt = NULL;
7488
7489 if (!ssl_sock_is_ssl(conn))
7490 return 0;
Christopher Faulet82004142019-09-10 10:12:03 +02007491 ctx = conn->xprt_ctx;
Dave McCowan328fb582014-07-30 10:39:13 -04007492
7493 /* SSL_get_peer_certificate, it increase X509 * ref count */
Olivier Houchard66ab4982019-02-26 18:37:15 +01007494 crt = SSL_get_peer_certificate(ctx->ssl);
Dave McCowan328fb582014-07-30 10:39:13 -04007495 if (!crt)
7496 return 0;
7497
7498 X509_free(crt);
7499 return 1;
7500}
7501
7502/* returns 1 if client passed a certificate for this connection, 0 if not */
7503int ssl_sock_get_cert_used_conn(struct connection *conn)
David Safb76832014-05-08 23:42:08 -04007504{
Christopher Faulet82004142019-09-10 10:12:03 +02007505 struct ssl_sock_ctx *ctx;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007506
David Safb76832014-05-08 23:42:08 -04007507 if (!ssl_sock_is_ssl(conn))
7508 return 0;
Christopher Faulet82004142019-09-10 10:12:03 +02007509 ctx = conn->xprt_ctx;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007510 return SSL_SOCK_ST_FL_VERIFY_DONE & ctx->xprt_st ? 1 : 0;
David Safb76832014-05-08 23:42:08 -04007511}
7512
7513/* returns result from SSL verify */
7514unsigned int ssl_sock_get_verify_result(struct connection *conn)
7515{
Christopher Faulet82004142019-09-10 10:12:03 +02007516 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007517
David Safb76832014-05-08 23:42:08 -04007518 if (!ssl_sock_is_ssl(conn))
7519 return (unsigned int)X509_V_ERR_APPLICATION_VERIFICATION;
Christopher Faulet82004142019-09-10 10:12:03 +02007520 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007521 return (unsigned int)SSL_get_verify_result(ctx->ssl);
David Safb76832014-05-08 23:42:08 -04007522}
7523
Willy Tarreau8743f7e2016-12-04 18:44:29 +01007524/* Returns the application layer protocol name in <str> and <len> when known.
7525 * Zero is returned if the protocol name was not found, otherwise non-zero is
7526 * returned. The string is allocated in the SSL context and doesn't have to be
7527 * freed by the caller. NPN is also checked if available since older versions
7528 * of openssl (1.0.1) which are more common in field only support this one.
7529 */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01007530static int ssl_sock_get_alpn(const struct connection *conn, void *xprt_ctx, const char **str, int *len)
Willy Tarreau8743f7e2016-12-04 18:44:29 +01007531{
Olivier Houchard66ab4982019-02-26 18:37:15 +01007532#if defined(TLSEXT_TYPE_application_layer_protocol_negotiation) || \
7533 defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Olivier Houcharde179d0e2019-03-21 18:27:17 +01007534 struct ssl_sock_ctx *ctx = xprt_ctx;
7535 if (!ctx)
Willy Tarreau8743f7e2016-12-04 18:44:29 +01007536 return 0;
7537
7538 *str = NULL;
7539
7540#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Olivier Houchard66ab4982019-02-26 18:37:15 +01007541 SSL_get0_alpn_selected(ctx->ssl, (const unsigned char **)str, (unsigned *)len);
Willy Tarreau8743f7e2016-12-04 18:44:29 +01007542 if (*str)
7543 return 1;
7544#endif
Bernard Spil13c53f82018-02-15 13:34:58 +01007545#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007546 SSL_get0_next_proto_negotiated(ctx->ssl, (const unsigned char **)str, (unsigned *)len);
Willy Tarreau8743f7e2016-12-04 18:44:29 +01007547 if (*str)
7548 return 1;
7549#endif
Olivier Houcharde179d0e2019-03-21 18:27:17 +01007550#endif
Willy Tarreau8743f7e2016-12-04 18:44:29 +01007551 return 0;
7552}
7553
Willy Tarreau7875d092012-09-10 08:20:03 +02007554/***** Below are some sample fetching functions for ACL/patterns *****/
7555
Olivier Houchardccaa7de2017-10-02 11:51:03 +02007556static int
7557smp_fetch_ssl_fc_has_early(const struct arg *args, struct sample *smp, const char *kw, void *private)
7558{
7559 struct connection *conn;
7560
7561 conn = objt_conn(smp->sess->origin);
7562 if (!conn || conn->xprt != &ssl_sock)
7563 return 0;
7564
7565 smp->flags = 0;
7566 smp->data.type = SMP_T_BOOL;
Emmanuel Hocdetc9858012019-08-07 14:44:49 +02007567#ifdef OPENSSL_IS_BORINGSSL
7568 {
7569 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
7570 smp->data.u.sint = (SSL_in_early_data(ctx->ssl) &&
7571 SSL_early_data_accepted(ctx->ssl));
7572 }
7573#else
Olivier Houchard25ae45a2017-11-29 19:51:19 +01007574 smp->data.u.sint = ((conn->flags & CO_FL_EARLY_DATA) &&
Olivier Houchard220a26c2020-01-23 14:57:36 +01007575 (conn->flags & (CO_FL_EARLY_SSL_HS | CO_FL_SSL_WAIT_HS))) ? 1 : 0;
Emmanuel Hocdetc9858012019-08-07 14:44:49 +02007576#endif
Olivier Houchardccaa7de2017-10-02 11:51:03 +02007577 return 1;
7578}
7579
Emeric Brune64aef12012-09-21 13:15:06 +02007580/* boolean, returns true if client cert was present */
7581static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007582smp_fetch_ssl_fc_has_crt(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brune64aef12012-09-21 13:15:06 +02007583{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007584 struct connection *conn;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007585 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007586
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007587 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007588 if (!conn || conn->xprt != &ssl_sock)
Emeric Brune64aef12012-09-21 13:15:06 +02007589 return 0;
7590
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007591 ctx = conn->xprt_ctx;
7592
Willy Tarreau911db9b2020-01-23 16:27:54 +01007593 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Brune64aef12012-09-21 13:15:06 +02007594 smp->flags |= SMP_F_MAY_CHANGE;
7595 return 0;
7596 }
7597
7598 smp->flags = 0;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007599 smp->data.type = SMP_T_BOOL;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007600 smp->data.u.sint = SSL_SOCK_ST_FL_VERIFY_DONE & ctx->xprt_st ? 1 : 0;
Emeric Brune64aef12012-09-21 13:15:06 +02007601
7602 return 1;
7603}
7604
Emeric Brun43e79582014-10-29 19:03:26 +01007605/* binary, returns a certificate in a binary chunk (der/raw).
7606 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7607 * should be use.
7608 */
7609static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007610smp_fetch_ssl_x_der(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun43e79582014-10-29 19:03:26 +01007611{
7612 int cert_peer = (kw[4] == 'c') ? 1 : 0;
7613 X509 *crt = NULL;
7614 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02007615 struct buffer *smp_trash;
Emeric Brun43e79582014-10-29 19:03:26 +01007616 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007617 struct ssl_sock_ctx *ctx;
Emeric Brun43e79582014-10-29 19:03:26 +01007618
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007619 conn = objt_conn(smp->sess->origin);
Emeric Brun43e79582014-10-29 19:03:26 +01007620 if (!conn || conn->xprt != &ssl_sock)
7621 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007622 ctx = conn->xprt_ctx;
Emeric Brun43e79582014-10-29 19:03:26 +01007623
Willy Tarreau911db9b2020-01-23 16:27:54 +01007624 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Brun43e79582014-10-29 19:03:26 +01007625 smp->flags |= SMP_F_MAY_CHANGE;
7626 return 0;
7627 }
7628
7629 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007630 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brun43e79582014-10-29 19:03:26 +01007631 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007632 crt = SSL_get_certificate(ctx->ssl);
Emeric Brun43e79582014-10-29 19:03:26 +01007633
7634 if (!crt)
7635 goto out;
7636
7637 smp_trash = get_trash_chunk();
7638 if (ssl_sock_crt2der(crt, smp_trash) <= 0)
7639 goto out;
7640
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007641 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007642 smp->data.type = SMP_T_BIN;
Emeric Brun43e79582014-10-29 19:03:26 +01007643 ret = 1;
7644out:
7645 /* SSL_get_peer_certificate, it increase X509 * ref count */
7646 if (cert_peer && crt)
7647 X509_free(crt);
7648 return ret;
7649}
7650
Emeric Brunba841a12014-04-30 17:05:08 +02007651/* binary, returns serial of certificate in a binary chunk.
7652 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7653 * should be use.
7654 */
Willy Tarreau8d598402012-10-22 17:58:39 +02007655static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007656smp_fetch_ssl_x_serial(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau8d598402012-10-22 17:58:39 +02007657{
Emeric Brunba841a12014-04-30 17:05:08 +02007658 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Willy Tarreau8d598402012-10-22 17:58:39 +02007659 X509 *crt = NULL;
7660 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02007661 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007662 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007663 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007664
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007665 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007666 if (!conn || conn->xprt != &ssl_sock)
Willy Tarreau8d598402012-10-22 17:58:39 +02007667 return 0;
7668
Olivier Houchard66ab4982019-02-26 18:37:15 +01007669 ctx = conn->xprt_ctx;
7670
Willy Tarreau911db9b2020-01-23 16:27:54 +01007671 if (conn->flags & CO_FL_WAIT_XPRT) {
Willy Tarreau8d598402012-10-22 17:58:39 +02007672 smp->flags |= SMP_F_MAY_CHANGE;
7673 return 0;
7674 }
7675
Emeric Brunba841a12014-04-30 17:05:08 +02007676 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007677 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007678 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007679 crt = SSL_get_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007680
Willy Tarreau8d598402012-10-22 17:58:39 +02007681 if (!crt)
7682 goto out;
7683
Willy Tarreau47ca5452012-12-23 20:22:19 +01007684 smp_trash = get_trash_chunk();
Willy Tarreau8d598402012-10-22 17:58:39 +02007685 if (ssl_sock_get_serial(crt, smp_trash) <= 0)
7686 goto out;
7687
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007688 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007689 smp->data.type = SMP_T_BIN;
Willy Tarreau8d598402012-10-22 17:58:39 +02007690 ret = 1;
7691out:
Emeric Brunba841a12014-04-30 17:05:08 +02007692 /* SSL_get_peer_certificate, it increase X509 * ref count */
7693 if (cert_peer && crt)
Willy Tarreau8d598402012-10-22 17:58:39 +02007694 X509_free(crt);
7695 return ret;
7696}
Emeric Brune64aef12012-09-21 13:15:06 +02007697
Emeric Brunba841a12014-04-30 17:05:08 +02007698/* binary, returns the client certificate's SHA-1 fingerprint (SHA-1 hash of DER-encoded certificate) in a binary chunk.
7699 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7700 * should be use.
7701 */
James Votha051b4a2013-05-14 20:37:59 +02007702static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007703smp_fetch_ssl_x_sha1(const struct arg *args, struct sample *smp, const char *kw, void *private)
James Votha051b4a2013-05-14 20:37:59 +02007704{
Emeric Brunba841a12014-04-30 17:05:08 +02007705 int cert_peer = (kw[4] == 'c') ? 1 : 0;
James Votha051b4a2013-05-14 20:37:59 +02007706 X509 *crt = NULL;
7707 const EVP_MD *digest;
7708 int ret = 0;
Willy Tarreau105599c2020-02-25 08:59:23 +01007709 unsigned int len = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02007710 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007711 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007712 struct ssl_sock_ctx *ctx;
James Votha051b4a2013-05-14 20:37:59 +02007713
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007714 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007715 if (!conn || conn->xprt != &ssl_sock)
7716 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007717 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007718
Willy Tarreau911db9b2020-01-23 16:27:54 +01007719 if (conn->flags & CO_FL_WAIT_XPRT) {
James Votha051b4a2013-05-14 20:37:59 +02007720 smp->flags |= SMP_F_MAY_CHANGE;
7721 return 0;
7722 }
7723
Emeric Brunba841a12014-04-30 17:05:08 +02007724 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007725 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007726 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007727 crt = SSL_get_certificate(ctx->ssl);
James Votha051b4a2013-05-14 20:37:59 +02007728 if (!crt)
7729 goto out;
7730
7731 smp_trash = get_trash_chunk();
7732 digest = EVP_sha1();
Willy Tarreau105599c2020-02-25 08:59:23 +01007733 X509_digest(crt, digest, (unsigned char *) smp_trash->area, &len);
7734 smp_trash->data = len;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007735 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007736 smp->data.type = SMP_T_BIN;
James Votha051b4a2013-05-14 20:37:59 +02007737 ret = 1;
7738out:
Emeric Brunba841a12014-04-30 17:05:08 +02007739 /* SSL_get_peer_certificate, it increase X509 * ref count */
7740 if (cert_peer && crt)
James Votha051b4a2013-05-14 20:37:59 +02007741 X509_free(crt);
7742 return ret;
7743}
7744
Emeric Brunba841a12014-04-30 17:05:08 +02007745/* string, returns certificate's notafter date in ASN1_UTCTIME format.
7746 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7747 * should be use.
7748 */
Emeric Brunce5ad802012-10-22 14:11:22 +02007749static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007750smp_fetch_ssl_x_notafter(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunce5ad802012-10-22 14:11:22 +02007751{
Emeric Brunba841a12014-04-30 17:05:08 +02007752 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brunce5ad802012-10-22 14:11:22 +02007753 X509 *crt = NULL;
7754 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02007755 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007756 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007757 struct ssl_sock_ctx *ctx;
Emeric Brunce5ad802012-10-22 14:11:22 +02007758
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007759 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007760 if (!conn || conn->xprt != &ssl_sock)
7761 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007762 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007763
Willy Tarreau911db9b2020-01-23 16:27:54 +01007764 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Brunce5ad802012-10-22 14:11:22 +02007765 smp->flags |= SMP_F_MAY_CHANGE;
7766 return 0;
7767 }
7768
Emeric Brunba841a12014-04-30 17:05:08 +02007769 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007770 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007771 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007772 crt = SSL_get_certificate(ctx->ssl);
Emeric Brunce5ad802012-10-22 14:11:22 +02007773 if (!crt)
7774 goto out;
7775
Willy Tarreau47ca5452012-12-23 20:22:19 +01007776 smp_trash = get_trash_chunk();
Rosen Penev68185952018-12-14 08:47:02 -08007777 if (ssl_sock_get_time(X509_getm_notAfter(crt), smp_trash) <= 0)
Emeric Brunce5ad802012-10-22 14:11:22 +02007778 goto out;
7779
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007780 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007781 smp->data.type = SMP_T_STR;
Emeric Brunce5ad802012-10-22 14:11:22 +02007782 ret = 1;
7783out:
Emeric Brunba841a12014-04-30 17:05:08 +02007784 /* SSL_get_peer_certificate, it increase X509 * ref count */
7785 if (cert_peer && crt)
Emeric Brunce5ad802012-10-22 14:11:22 +02007786 X509_free(crt);
7787 return ret;
7788}
7789
Emeric Brunba841a12014-04-30 17:05:08 +02007790/* string, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. of certificate's issuer
7791 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7792 * should be use.
7793 */
Emeric Brun87855892012-10-17 17:39:35 +02007794static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007795smp_fetch_ssl_x_i_dn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun87855892012-10-17 17:39:35 +02007796{
Emeric Brunba841a12014-04-30 17:05:08 +02007797 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun87855892012-10-17 17:39:35 +02007798 X509 *crt = NULL;
7799 X509_NAME *name;
7800 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02007801 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007802 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007803 struct ssl_sock_ctx *ctx;
Emeric Brun87855892012-10-17 17:39:35 +02007804
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007805 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007806 if (!conn || conn->xprt != &ssl_sock)
7807 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007808 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007809
Willy Tarreau911db9b2020-01-23 16:27:54 +01007810 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Brun87855892012-10-17 17:39:35 +02007811 smp->flags |= SMP_F_MAY_CHANGE;
7812 return 0;
7813 }
7814
Emeric Brunba841a12014-04-30 17:05:08 +02007815 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007816 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007817 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007818 crt = SSL_get_certificate(ctx->ssl);
Emeric Brun87855892012-10-17 17:39:35 +02007819 if (!crt)
7820 goto out;
7821
7822 name = X509_get_issuer_name(crt);
7823 if (!name)
7824 goto out;
7825
Willy Tarreau47ca5452012-12-23 20:22:19 +01007826 smp_trash = get_trash_chunk();
Elliot Otchet71f82972020-01-15 08:12:14 -05007827 if (args && args[0].type == ARGT_STR && args[0].data.str.data > 0) {
Emeric Brun87855892012-10-17 17:39:35 +02007828 int pos = 1;
7829
7830 if (args[1].type == ARGT_SINT)
7831 pos = args[1].data.sint;
Emeric Brun87855892012-10-17 17:39:35 +02007832
7833 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
7834 goto out;
7835 }
Elliot Otchet71f82972020-01-15 08:12:14 -05007836 else if (args && args[2].type == ARGT_STR && args[2].data.str.data > 0) {
7837 if (ssl_sock_get_dn_formatted(name, &args[2].data.str, smp_trash) <= 0)
7838 goto out;
7839 }
Emeric Brun87855892012-10-17 17:39:35 +02007840 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
7841 goto out;
7842
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007843 smp->data.type = SMP_T_STR;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007844 smp->data.u.str = *smp_trash;
Emeric Brun87855892012-10-17 17:39:35 +02007845 ret = 1;
7846out:
Emeric Brunba841a12014-04-30 17:05:08 +02007847 /* SSL_get_peer_certificate, it increase X509 * ref count */
7848 if (cert_peer && crt)
Emeric Brun87855892012-10-17 17:39:35 +02007849 X509_free(crt);
7850 return ret;
7851}
7852
Emeric Brunba841a12014-04-30 17:05:08 +02007853/* string, returns notbefore date in ASN1_UTCTIME format.
7854 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7855 * should be use.
7856 */
Emeric Brunce5ad802012-10-22 14:11:22 +02007857static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007858smp_fetch_ssl_x_notbefore(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunce5ad802012-10-22 14:11:22 +02007859{
Emeric Brunba841a12014-04-30 17:05:08 +02007860 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brunce5ad802012-10-22 14:11:22 +02007861 X509 *crt = NULL;
7862 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02007863 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007864 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007865 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007866
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007867 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007868 if (!conn || conn->xprt != &ssl_sock)
Emeric Brunce5ad802012-10-22 14:11:22 +02007869 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007870 ctx = conn->xprt_ctx;
Emeric Brunce5ad802012-10-22 14:11:22 +02007871
Willy Tarreau911db9b2020-01-23 16:27:54 +01007872 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Brunce5ad802012-10-22 14:11:22 +02007873 smp->flags |= SMP_F_MAY_CHANGE;
7874 return 0;
7875 }
7876
Emeric Brunba841a12014-04-30 17:05:08 +02007877 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007878 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007879 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007880 crt = SSL_get_certificate(ctx->ssl);
Emeric Brunce5ad802012-10-22 14:11:22 +02007881 if (!crt)
7882 goto out;
7883
Willy Tarreau47ca5452012-12-23 20:22:19 +01007884 smp_trash = get_trash_chunk();
Rosen Penev68185952018-12-14 08:47:02 -08007885 if (ssl_sock_get_time(X509_getm_notBefore(crt), smp_trash) <= 0)
Emeric Brunce5ad802012-10-22 14:11:22 +02007886 goto out;
7887
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007888 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007889 smp->data.type = SMP_T_STR;
Emeric Brunce5ad802012-10-22 14:11:22 +02007890 ret = 1;
7891out:
Emeric Brunba841a12014-04-30 17:05:08 +02007892 /* SSL_get_peer_certificate, it increase X509 * ref count */
7893 if (cert_peer && crt)
Emeric Brunce5ad802012-10-22 14:11:22 +02007894 X509_free(crt);
7895 return ret;
7896}
7897
Emeric Brunba841a12014-04-30 17:05:08 +02007898/* string, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. of certificate's subject
7899 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7900 * should be use.
7901 */
Emeric Brun87855892012-10-17 17:39:35 +02007902static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007903smp_fetch_ssl_x_s_dn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun87855892012-10-17 17:39:35 +02007904{
Emeric Brunba841a12014-04-30 17:05:08 +02007905 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun87855892012-10-17 17:39:35 +02007906 X509 *crt = NULL;
7907 X509_NAME *name;
7908 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02007909 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007910 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007911 struct ssl_sock_ctx *ctx;
Emeric Brun87855892012-10-17 17:39:35 +02007912
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007913 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007914 if (!conn || conn->xprt != &ssl_sock)
7915 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007916 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007917
Willy Tarreau911db9b2020-01-23 16:27:54 +01007918 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Brun87855892012-10-17 17:39:35 +02007919 smp->flags |= SMP_F_MAY_CHANGE;
7920 return 0;
7921 }
7922
Emeric Brunba841a12014-04-30 17:05:08 +02007923 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007924 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007925 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007926 crt = SSL_get_certificate(ctx->ssl);
Emeric Brun87855892012-10-17 17:39:35 +02007927 if (!crt)
7928 goto out;
7929
7930 name = X509_get_subject_name(crt);
7931 if (!name)
7932 goto out;
7933
Willy Tarreau47ca5452012-12-23 20:22:19 +01007934 smp_trash = get_trash_chunk();
Elliot Otchet71f82972020-01-15 08:12:14 -05007935 if (args && args[0].type == ARGT_STR && args[0].data.str.data > 0) {
Emeric Brun87855892012-10-17 17:39:35 +02007936 int pos = 1;
7937
7938 if (args[1].type == ARGT_SINT)
7939 pos = args[1].data.sint;
Emeric Brun87855892012-10-17 17:39:35 +02007940
7941 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
7942 goto out;
7943 }
Elliot Otchet71f82972020-01-15 08:12:14 -05007944 else if (args && args[2].type == ARGT_STR && args[2].data.str.data > 0) {
7945 if (ssl_sock_get_dn_formatted(name, &args[2].data.str, smp_trash) <= 0)
7946 goto out;
7947 }
Emeric Brun87855892012-10-17 17:39:35 +02007948 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
7949 goto out;
7950
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007951 smp->data.type = SMP_T_STR;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007952 smp->data.u.str = *smp_trash;
Emeric Brun87855892012-10-17 17:39:35 +02007953 ret = 1;
7954out:
Emeric Brunba841a12014-04-30 17:05:08 +02007955 /* SSL_get_peer_certificate, it increase X509 * ref count */
7956 if (cert_peer && crt)
Emeric Brun87855892012-10-17 17:39:35 +02007957 X509_free(crt);
7958 return ret;
7959}
Emeric Brun9143d372012-12-20 15:44:16 +01007960
7961/* integer, returns true if current session use a client certificate */
7962static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007963smp_fetch_ssl_c_used(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun9143d372012-12-20 15:44:16 +01007964{
7965 X509 *crt;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007966 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007967 struct ssl_sock_ctx *ctx;
Emeric Brun9143d372012-12-20 15:44:16 +01007968
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007969 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007970 if (!conn || conn->xprt != &ssl_sock)
7971 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007972 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007973
Willy Tarreau911db9b2020-01-23 16:27:54 +01007974 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Brun9143d372012-12-20 15:44:16 +01007975 smp->flags |= SMP_F_MAY_CHANGE;
7976 return 0;
7977 }
7978
7979 /* SSL_get_peer_certificate returns a ptr on allocated X509 struct */
Olivier Houchard66ab4982019-02-26 18:37:15 +01007980 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brun9143d372012-12-20 15:44:16 +01007981 if (crt) {
7982 X509_free(crt);
7983 }
7984
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007985 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007986 smp->data.u.sint = (crt != NULL);
Emeric Brun9143d372012-12-20 15:44:16 +01007987 return 1;
7988}
7989
Emeric Brunba841a12014-04-30 17:05:08 +02007990/* integer, returns the certificate version
7991 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7992 * should be use.
7993 */
Emeric Bruna7359fd2012-10-17 15:03:11 +02007994static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007995smp_fetch_ssl_x_version(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Bruna7359fd2012-10-17 15:03:11 +02007996{
Emeric Brunba841a12014-04-30 17:05:08 +02007997 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Bruna7359fd2012-10-17 15:03:11 +02007998 X509 *crt;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007999 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008000 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008001
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02008002 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008003 if (!conn || conn->xprt != &ssl_sock)
Emeric Bruna7359fd2012-10-17 15:03:11 +02008004 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008005 ctx = conn->xprt_ctx;
Emeric Bruna7359fd2012-10-17 15:03:11 +02008006
Willy Tarreau911db9b2020-01-23 16:27:54 +01008007 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Bruna7359fd2012-10-17 15:03:11 +02008008 smp->flags |= SMP_F_MAY_CHANGE;
8009 return 0;
8010 }
8011
Emeric Brunba841a12014-04-30 17:05:08 +02008012 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01008013 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02008014 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01008015 crt = SSL_get_certificate(ctx->ssl);
Emeric Bruna7359fd2012-10-17 15:03:11 +02008016 if (!crt)
8017 return 0;
8018
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02008019 smp->data.u.sint = (unsigned int)(1 + X509_get_version(crt));
Emeric Brunba841a12014-04-30 17:05:08 +02008020 /* SSL_get_peer_certificate increase X509 * ref count */
8021 if (cert_peer)
8022 X509_free(crt);
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008023 smp->data.type = SMP_T_SINT;
Emeric Bruna7359fd2012-10-17 15:03:11 +02008024
8025 return 1;
8026}
8027
Emeric Brunba841a12014-04-30 17:05:08 +02008028/* string, returns the certificate's signature algorithm.
8029 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
8030 * should be use.
8031 */
Emeric Brun7f56e742012-10-19 18:15:40 +02008032static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008033smp_fetch_ssl_x_sig_alg(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun7f56e742012-10-19 18:15:40 +02008034{
Emeric Brunba841a12014-04-30 17:05:08 +02008035 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun7f56e742012-10-19 18:15:40 +02008036 X509 *crt;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02008037 __OPENSSL_110_CONST__ ASN1_OBJECT *algorithm;
Emeric Brun7f56e742012-10-19 18:15:40 +02008038 int nid;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008039 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008040 struct ssl_sock_ctx *ctx;
Emeric Brun7f56e742012-10-19 18:15:40 +02008041
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02008042 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008043 if (!conn || conn->xprt != &ssl_sock)
8044 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008045 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008046
Willy Tarreau911db9b2020-01-23 16:27:54 +01008047 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Brun7f56e742012-10-19 18:15:40 +02008048 smp->flags |= SMP_F_MAY_CHANGE;
8049 return 0;
8050 }
8051
Emeric Brunba841a12014-04-30 17:05:08 +02008052 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01008053 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02008054 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01008055 crt = SSL_get_certificate(ctx->ssl);
Emeric Brun7f56e742012-10-19 18:15:40 +02008056 if (!crt)
8057 return 0;
8058
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02008059 X509_ALGOR_get0(&algorithm, NULL, NULL, X509_get0_tbs_sigalg(crt));
8060 nid = OBJ_obj2nid(algorithm);
Emeric Brun7f56e742012-10-19 18:15:40 +02008061
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008062 smp->data.u.str.area = (char *)OBJ_nid2sn(nid);
8063 if (!smp->data.u.str.area) {
Emeric Brunba841a12014-04-30 17:05:08 +02008064 /* SSL_get_peer_certificate increase X509 * ref count */
8065 if (cert_peer)
8066 X509_free(crt);
Emeric Brun7f56e742012-10-19 18:15:40 +02008067 return 0;
Emeric Brun9bf3ba22013-10-07 14:31:44 +02008068 }
Emeric Brun7f56e742012-10-19 18:15:40 +02008069
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008070 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008071 smp->flags |= SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008072 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brunba841a12014-04-30 17:05:08 +02008073 /* SSL_get_peer_certificate increase X509 * ref count */
8074 if (cert_peer)
8075 X509_free(crt);
Emeric Brun7f56e742012-10-19 18:15:40 +02008076
8077 return 1;
8078}
8079
Emeric Brunba841a12014-04-30 17:05:08 +02008080/* string, returns the certificate's key algorithm.
8081 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
8082 * should be use.
8083 */
Emeric Brun521a0112012-10-22 12:22:55 +02008084static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008085smp_fetch_ssl_x_key_alg(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun521a0112012-10-22 12:22:55 +02008086{
Emeric Brunba841a12014-04-30 17:05:08 +02008087 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun521a0112012-10-22 12:22:55 +02008088 X509 *crt;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02008089 ASN1_OBJECT *algorithm;
Emeric Brun521a0112012-10-22 12:22:55 +02008090 int nid;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008091 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008092 struct ssl_sock_ctx *ctx;
Emeric Brun521a0112012-10-22 12:22:55 +02008093
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02008094 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008095 if (!conn || conn->xprt != &ssl_sock)
8096 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008097 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008098
Willy Tarreau911db9b2020-01-23 16:27:54 +01008099 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Brun521a0112012-10-22 12:22:55 +02008100 smp->flags |= SMP_F_MAY_CHANGE;
8101 return 0;
8102 }
8103
Emeric Brunba841a12014-04-30 17:05:08 +02008104 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01008105 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02008106 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01008107 crt = SSL_get_certificate(ctx->ssl);
Emeric Brun521a0112012-10-22 12:22:55 +02008108 if (!crt)
8109 return 0;
8110
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02008111 X509_PUBKEY_get0_param(&algorithm, NULL, NULL, NULL, X509_get_X509_PUBKEY(crt));
8112 nid = OBJ_obj2nid(algorithm);
Emeric Brun521a0112012-10-22 12:22:55 +02008113
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008114 smp->data.u.str.area = (char *)OBJ_nid2sn(nid);
8115 if (!smp->data.u.str.area) {
Emeric Brunba841a12014-04-30 17:05:08 +02008116 /* SSL_get_peer_certificate increase X509 * ref count */
8117 if (cert_peer)
8118 X509_free(crt);
Emeric Brun521a0112012-10-22 12:22:55 +02008119 return 0;
Emeric Brun9bf3ba22013-10-07 14:31:44 +02008120 }
Emeric Brun521a0112012-10-22 12:22:55 +02008121
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008122 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008123 smp->flags |= SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008124 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brunba841a12014-04-30 17:05:08 +02008125 if (cert_peer)
8126 X509_free(crt);
Emeric Brun521a0112012-10-22 12:22:55 +02008127
8128 return 1;
8129}
8130
Emeric Brun645ae792014-04-30 14:21:06 +02008131/* boolean, returns true if front conn. transport layer is SSL.
8132 * This function is also usable on backend conn if the fetch keyword 5th
8133 * char is 'b'.
8134 */
Willy Tarreau7875d092012-09-10 08:20:03 +02008135static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008136smp_fetch_ssl_fc(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02008137{
Emeric Bruneb8def92018-02-19 15:59:48 +01008138 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
8139 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008140
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008141 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02008142 smp->data.u.sint = (conn && conn->xprt == &ssl_sock);
Willy Tarreau7875d092012-09-10 08:20:03 +02008143 return 1;
8144}
8145
Emeric Brun2525b6b2012-10-18 15:59:43 +02008146/* boolean, returns true if client present a SNI */
Willy Tarreau7875d092012-09-10 08:20:03 +02008147static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008148smp_fetch_ssl_fc_has_sni(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02008149{
8150#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02008151 struct connection *conn = objt_conn(smp->sess->origin);
Olivier Houchard66ab4982019-02-26 18:37:15 +01008152 struct ssl_sock_ctx *ctx = conn ? conn->xprt_ctx : NULL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008153
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008154 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02008155 smp->data.u.sint = (conn && conn->xprt == &ssl_sock) &&
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008156 conn->xprt_ctx &&
Olivier Houchard66ab4982019-02-26 18:37:15 +01008157 SSL_get_servername(ctx->ssl, TLSEXT_NAMETYPE_host_name) != NULL;
Willy Tarreau7875d092012-09-10 08:20:03 +02008158 return 1;
8159#else
8160 return 0;
8161#endif
8162}
8163
Emeric Brun74f7ffa2018-02-19 16:14:12 +01008164/* boolean, returns true if client session has been resumed.
8165 * This function is also usable on backend conn if the fetch keyword 5th
8166 * char is 'b'.
8167 */
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02008168static int
8169smp_fetch_ssl_fc_is_resumed(const struct arg *args, struct sample *smp, const char *kw, void *private)
8170{
Emeric Brun74f7ffa2018-02-19 16:14:12 +01008171 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
8172 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008173 struct ssl_sock_ctx *ctx = conn ? conn->xprt_ctx : NULL;
Emeric Brun74f7ffa2018-02-19 16:14:12 +01008174
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02008175
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008176 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02008177 smp->data.u.sint = (conn && conn->xprt == &ssl_sock) &&
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02008178 conn->xprt_ctx &&
Olivier Houchard66ab4982019-02-26 18:37:15 +01008179 SSL_session_reused(ctx->ssl);
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02008180 return 1;
8181}
8182
Emeric Brun645ae792014-04-30 14:21:06 +02008183/* string, returns the used cipher if front conn. transport layer is SSL.
8184 * This function is also usable on backend conn if the fetch keyword 5th
8185 * char is 'b'.
8186 */
Emeric Brun589fcad2012-10-16 14:13:26 +02008187static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008188smp_fetch_ssl_fc_cipher(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02008189{
Emeric Bruneb8def92018-02-19 15:59:48 +01008190 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
8191 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008192 struct ssl_sock_ctx *ctx;
Emeric Brun589fcad2012-10-16 14:13:26 +02008193
Willy Tarreaube508f12016-03-10 11:47:01 +01008194 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008195 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02008196 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008197 ctx = conn->xprt_ctx;
Emeric Brun589fcad2012-10-16 14:13:26 +02008198
Olivier Houchard66ab4982019-02-26 18:37:15 +01008199 smp->data.u.str.area = (char *)SSL_get_cipher_name(ctx->ssl);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008200 if (!smp->data.u.str.area)
Emeric Brun589fcad2012-10-16 14:13:26 +02008201 return 0;
8202
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008203 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008204 smp->flags |= SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008205 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brun589fcad2012-10-16 14:13:26 +02008206
8207 return 1;
8208}
8209
Emeric Brun645ae792014-04-30 14:21:06 +02008210/* integer, returns the algoritm's keysize if front conn. transport layer
8211 * is SSL.
8212 * This function is also usable on backend conn if the fetch keyword 5th
8213 * char is 'b'.
8214 */
Emeric Brun589fcad2012-10-16 14:13:26 +02008215static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008216smp_fetch_ssl_fc_alg_keysize(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02008217{
Emeric Bruneb8def92018-02-19 15:59:48 +01008218 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
8219 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008220 struct ssl_sock_ctx *ctx;
Willy Tarreaue237fe12016-03-10 17:05:28 +01008221 int sint;
Willy Tarreaube508f12016-03-10 11:47:01 +01008222
Emeric Brun589fcad2012-10-16 14:13:26 +02008223 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008224 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02008225 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008226 ctx = conn->xprt_ctx;
Emeric Brun589fcad2012-10-16 14:13:26 +02008227
Olivier Houchard66ab4982019-02-26 18:37:15 +01008228 if (!SSL_get_cipher_bits(ctx->ssl, &sint))
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008229 return 0;
8230
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02008231 smp->data.u.sint = sint;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008232 smp->data.type = SMP_T_SINT;
Emeric Brun589fcad2012-10-16 14:13:26 +02008233
8234 return 1;
8235}
8236
Emeric Brun645ae792014-04-30 14:21:06 +02008237/* integer, returns the used keysize if front conn. transport layer is SSL.
8238 * This function is also usable on backend conn if the fetch keyword 5th
8239 * char is 'b'.
8240 */
Emeric Brun589fcad2012-10-16 14:13:26 +02008241static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008242smp_fetch_ssl_fc_use_keysize(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02008243{
Emeric Bruneb8def92018-02-19 15:59:48 +01008244 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
8245 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008246 struct ssl_sock_ctx *ctx;
Willy Tarreaube508f12016-03-10 11:47:01 +01008247
Emeric Brun589fcad2012-10-16 14:13:26 +02008248 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008249 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8250 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008251 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008252
Olivier Houchard66ab4982019-02-26 18:37:15 +01008253 smp->data.u.sint = (unsigned int)SSL_get_cipher_bits(ctx->ssl, NULL);
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02008254 if (!smp->data.u.sint)
Emeric Brun589fcad2012-10-16 14:13:26 +02008255 return 0;
8256
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008257 smp->data.type = SMP_T_SINT;
Emeric Brun589fcad2012-10-16 14:13:26 +02008258
8259 return 1;
8260}
8261
Bernard Spil13c53f82018-02-15 13:34:58 +01008262#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Willy Tarreau7875d092012-09-10 08:20:03 +02008263static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008264smp_fetch_ssl_fc_npn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreaua33c6542012-10-15 13:19:06 +02008265{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008266 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008267 struct ssl_sock_ctx *ctx;
Willy Tarreau105599c2020-02-25 08:59:23 +01008268 unsigned int len = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008269
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008270 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008271 smp->data.type = SMP_T_STR;
Willy Tarreaua33c6542012-10-15 13:19:06 +02008272
Olivier Houchard6b77f492018-11-22 18:18:29 +01008273 conn = (kw[4] != 'b' ) ? objt_conn(smp->sess->origin) :
8274 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008275 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8276 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008277 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008278
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008279 smp->data.u.str.area = NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008280 SSL_get0_next_proto_negotiated(ctx->ssl,
Willy Tarreau105599c2020-02-25 08:59:23 +01008281 (const unsigned char **)&smp->data.u.str.area,
8282 &len);
Willy Tarreaua33c6542012-10-15 13:19:06 +02008283
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008284 if (!smp->data.u.str.area)
Willy Tarreaua33c6542012-10-15 13:19:06 +02008285 return 0;
8286
Willy Tarreau105599c2020-02-25 08:59:23 +01008287 smp->data.u.str.data = len;
Willy Tarreaua33c6542012-10-15 13:19:06 +02008288 return 1;
Willy Tarreaua33c6542012-10-15 13:19:06 +02008289}
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02008290#endif
Willy Tarreaua33c6542012-10-15 13:19:06 +02008291
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01008292#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02008293static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008294smp_fetch_ssl_fc_alpn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreauab861d32013-04-02 02:30:41 +02008295{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008296 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008297 struct ssl_sock_ctx *ctx;
Willy Tarreau105599c2020-02-25 08:59:23 +01008298 unsigned int len = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008299
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008300 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008301 smp->data.type = SMP_T_STR;
Willy Tarreauab861d32013-04-02 02:30:41 +02008302
Olivier Houchard6b77f492018-11-22 18:18:29 +01008303 conn = (kw[4] != 'b' ) ? objt_conn(smp->sess->origin) :
8304 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
8305
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008306 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Willy Tarreauab861d32013-04-02 02:30:41 +02008307 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008308 ctx = conn->xprt_ctx;
Willy Tarreauab861d32013-04-02 02:30:41 +02008309
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008310 smp->data.u.str.area = NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008311 SSL_get0_alpn_selected(ctx->ssl,
Willy Tarreau105599c2020-02-25 08:59:23 +01008312 (const unsigned char **)&smp->data.u.str.area,
8313 &len);
Willy Tarreauab861d32013-04-02 02:30:41 +02008314
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008315 if (!smp->data.u.str.area)
Willy Tarreauab861d32013-04-02 02:30:41 +02008316 return 0;
8317
Willy Tarreau105599c2020-02-25 08:59:23 +01008318 smp->data.u.str.data = len;
Willy Tarreauab861d32013-04-02 02:30:41 +02008319 return 1;
8320}
8321#endif
8322
Emeric Brun645ae792014-04-30 14:21:06 +02008323/* string, returns the used protocol if front conn. transport layer is SSL.
8324 * This function is also usable on backend conn if the fetch keyword 5th
8325 * char is 'b'.
8326 */
Willy Tarreaua33c6542012-10-15 13:19:06 +02008327static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008328smp_fetch_ssl_fc_protocol(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02008329{
Emeric Bruneb8def92018-02-19 15:59:48 +01008330 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
8331 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008332 struct ssl_sock_ctx *ctx;
Willy Tarreaube508f12016-03-10 11:47:01 +01008333
Emeric Brun589fcad2012-10-16 14:13:26 +02008334 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008335 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8336 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008337 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008338
Olivier Houchard66ab4982019-02-26 18:37:15 +01008339 smp->data.u.str.area = (char *)SSL_get_version(ctx->ssl);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008340 if (!smp->data.u.str.area)
Emeric Brun589fcad2012-10-16 14:13:26 +02008341 return 0;
8342
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008343 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008344 smp->flags = SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008345 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brun589fcad2012-10-16 14:13:26 +02008346
8347 return 1;
8348}
8349
Willy Tarreau87b09662015-04-03 00:22:06 +02008350/* binary, returns the SSL stream id if front conn. transport layer is SSL.
Emeric Brun645ae792014-04-30 14:21:06 +02008351 * This function is also usable on backend conn if the fetch keyword 5th
8352 * char is 'b'.
8353 */
Willy Tarreau9a1ab082019-05-09 13:26:41 +02008354#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
Emeric Brun589fcad2012-10-16 14:13:26 +02008355static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008356smp_fetch_ssl_fc_session_id(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunfe68f682012-10-16 14:59:28 +02008357{
Emeric Bruneb8def92018-02-19 15:59:48 +01008358 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
8359 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaue237fe12016-03-10 17:05:28 +01008360 SSL_SESSION *ssl_sess;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008361 struct ssl_sock_ctx *ctx;
Willy Tarreau105599c2020-02-25 08:59:23 +01008362 unsigned int len = 0;
Willy Tarreaube508f12016-03-10 11:47:01 +01008363
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008364 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008365 smp->data.type = SMP_T_BIN;
Emeric Brunfe68f682012-10-16 14:59:28 +02008366
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008367 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8368 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008369 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008370
Olivier Houchard66ab4982019-02-26 18:37:15 +01008371 ssl_sess = SSL_get_session(ctx->ssl);
Willy Tarreau192252e2015-04-04 01:47:55 +02008372 if (!ssl_sess)
Emeric Brunfe68f682012-10-16 14:59:28 +02008373 return 0;
8374
Willy Tarreau105599c2020-02-25 08:59:23 +01008375 smp->data.u.str.area = (char *)SSL_SESSION_get_id(ssl_sess, &len);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008376 if (!smp->data.u.str.area || !smp->data.u.str.data)
Emeric Brunfe68f682012-10-16 14:59:28 +02008377 return 0;
8378
Willy Tarreau105599c2020-02-25 08:59:23 +01008379 smp->data.u.str.data = len;
Emeric Brunfe68f682012-10-16 14:59:28 +02008380 return 1;
Emeric Brunfe68f682012-10-16 14:59:28 +02008381}
Patrick Hemmer41966772018-04-28 19:15:48 -04008382#endif
8383
Emeric Brunfe68f682012-10-16 14:59:28 +02008384
Emmanuel Hocdet839af572019-05-14 16:27:35 +02008385#if HA_OPENSSL_VERSION_NUMBER >= 0x10100000L
Patrick Hemmere0275472018-04-28 19:15:51 -04008386static int
Patrick Hemmer65674662019-06-04 08:13:03 -04008387smp_fetch_ssl_fc_random(const struct arg *args, struct sample *smp, const char *kw, void *private)
8388{
8389 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
8390 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
8391 struct buffer *data;
8392 struct ssl_sock_ctx *ctx;
8393
8394 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8395 return 0;
8396 ctx = conn->xprt_ctx;
8397
8398 data = get_trash_chunk();
8399 if (kw[7] == 'c')
8400 data->data = SSL_get_client_random(ctx->ssl,
8401 (unsigned char *) data->area,
8402 data->size);
8403 else
8404 data->data = SSL_get_server_random(ctx->ssl,
8405 (unsigned char *) data->area,
8406 data->size);
8407 if (!data->data)
8408 return 0;
8409
8410 smp->flags = 0;
8411 smp->data.type = SMP_T_BIN;
8412 smp->data.u.str = *data;
8413
8414 return 1;
8415}
8416
8417static int
Patrick Hemmere0275472018-04-28 19:15:51 -04008418smp_fetch_ssl_fc_session_key(const struct arg *args, struct sample *smp, const char *kw, void *private)
8419{
8420 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
8421 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
8422 SSL_SESSION *ssl_sess;
Willy Tarreau83061a82018-07-13 11:56:34 +02008423 struct buffer *data;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008424 struct ssl_sock_ctx *ctx;
Patrick Hemmere0275472018-04-28 19:15:51 -04008425
8426 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8427 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008428 ctx = conn->xprt_ctx;
Patrick Hemmere0275472018-04-28 19:15:51 -04008429
Olivier Houchard66ab4982019-02-26 18:37:15 +01008430 ssl_sess = SSL_get_session(ctx->ssl);
Patrick Hemmere0275472018-04-28 19:15:51 -04008431 if (!ssl_sess)
8432 return 0;
8433
8434 data = get_trash_chunk();
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008435 data->data = SSL_SESSION_get_master_key(ssl_sess,
8436 (unsigned char *) data->area,
8437 data->size);
8438 if (!data->data)
Patrick Hemmere0275472018-04-28 19:15:51 -04008439 return 0;
8440
8441 smp->flags = 0;
8442 smp->data.type = SMP_T_BIN;
8443 smp->data.u.str = *data;
8444
8445 return 1;
8446}
8447#endif
8448
Patrick Hemmer41966772018-04-28 19:15:48 -04008449#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emeric Brunfe68f682012-10-16 14:59:28 +02008450static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008451smp_fetch_ssl_fc_sni(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02008452{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008453 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008454 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008455
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008456 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008457 smp->data.type = SMP_T_STR;
Willy Tarreau7875d092012-09-10 08:20:03 +02008458
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02008459 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008460 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8461 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008462 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008463
Olivier Houchard66ab4982019-02-26 18:37:15 +01008464 smp->data.u.str.area = (char *)SSL_get_servername(ctx->ssl, TLSEXT_NAMETYPE_host_name);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008465 if (!smp->data.u.str.area)
Willy Tarreau3e394c92012-09-14 23:56:58 +02008466 return 0;
8467
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008468 smp->data.u.str.data = strlen(smp->data.u.str.area);
Willy Tarreau7875d092012-09-10 08:20:03 +02008469 return 1;
Willy Tarreau7875d092012-09-10 08:20:03 +02008470}
Patrick Hemmer41966772018-04-28 19:15:48 -04008471#endif
Willy Tarreau7875d092012-09-10 08:20:03 +02008472
David Sc1ad52e2014-04-08 18:48:47 -04008473static int
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008474smp_fetch_ssl_fc_cl_bin(const struct arg *args, struct sample *smp, const char *kw, void *private)
8475{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008476 struct connection *conn;
8477 struct ssl_capture *capture;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008478 struct ssl_sock_ctx *ctx;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008479
8480 conn = objt_conn(smp->sess->origin);
8481 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8482 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008483 ctx = conn->xprt_ctx;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008484
Olivier Houchard66ab4982019-02-26 18:37:15 +01008485 capture = SSL_get_ex_data(ctx->ssl, ssl_capture_ptr_index);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008486 if (!capture)
8487 return 0;
8488
8489 smp->flags = SMP_F_CONST;
8490 smp->data.type = SMP_T_BIN;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008491 smp->data.u.str.area = capture->ciphersuite;
8492 smp->data.u.str.data = capture->ciphersuite_len;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008493 return 1;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008494}
8495
8496static int
8497smp_fetch_ssl_fc_cl_hex(const struct arg *args, struct sample *smp, const char *kw, void *private)
8498{
Willy Tarreau83061a82018-07-13 11:56:34 +02008499 struct buffer *data;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008500
8501 if (!smp_fetch_ssl_fc_cl_bin(args, smp, kw, private))
8502 return 0;
8503
8504 data = get_trash_chunk();
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008505 dump_binary(data, smp->data.u.str.area, smp->data.u.str.data);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008506 smp->data.type = SMP_T_BIN;
8507 smp->data.u.str = *data;
8508 return 1;
8509}
8510
8511static int
8512smp_fetch_ssl_fc_cl_xxh64(const struct arg *args, struct sample *smp, const char *kw, void *private)
8513{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008514 struct connection *conn;
8515 struct ssl_capture *capture;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008516 struct ssl_sock_ctx *ctx;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008517
8518 conn = objt_conn(smp->sess->origin);
8519 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8520 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008521 ctx = conn->xprt_ctx;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008522
Olivier Houchard66ab4982019-02-26 18:37:15 +01008523 capture = SSL_get_ex_data(ctx->ssl, ssl_capture_ptr_index);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008524 if (!capture)
8525 return 0;
8526
8527 smp->data.type = SMP_T_SINT;
8528 smp->data.u.sint = capture->xxh64;
8529 return 1;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008530}
8531
8532static int
8533smp_fetch_ssl_fc_cl_str(const struct arg *args, struct sample *smp, const char *kw, void *private)
8534{
Willy Tarreau5db847a2019-05-09 14:13:35 +02008535#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL)
Willy Tarreau83061a82018-07-13 11:56:34 +02008536 struct buffer *data;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008537 int i;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008538
8539 if (!smp_fetch_ssl_fc_cl_bin(args, smp, kw, private))
8540 return 0;
8541
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008542 data = get_trash_chunk();
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008543 for (i = 0; i + 1 < smp->data.u.str.data; i += 2) {
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02008544 const char *str;
8545 const SSL_CIPHER *cipher;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008546 const unsigned char *bin = (const unsigned char *) smp->data.u.str.area + i;
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02008547 uint16_t id = (bin[0] << 8) | bin[1];
8548#if defined(OPENSSL_IS_BORINGSSL)
8549 cipher = SSL_get_cipher_by_value(id);
8550#else
Willy Tarreaub7290772018-10-15 11:01:59 +02008551 struct connection *conn = __objt_conn(smp->sess->origin);
Olivier Houchard66ab4982019-02-26 18:37:15 +01008552 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
8553 cipher = SSL_CIPHER_find(ctx->ssl, bin);
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02008554#endif
8555 str = SSL_CIPHER_get_name(cipher);
8556 if (!str || strcmp(str, "(NONE)") == 0)
8557 chunk_appendf(data, "%sUNKNOWN(%04x)", i == 0 ? "" : ",", id);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008558 else
8559 chunk_appendf(data, "%s%s", i == 0 ? "" : ",", str);
8560 }
8561 smp->data.type = SMP_T_STR;
8562 smp->data.u.str = *data;
8563 return 1;
8564#else
8565 return smp_fetch_ssl_fc_cl_xxh64(args, smp, kw, private);
8566#endif
8567}
8568
Willy Tarreau9a1ab082019-05-09 13:26:41 +02008569#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008570static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008571smp_fetch_ssl_fc_unique_id(const struct arg *args, struct sample *smp, const char *kw, void *private)
David Sc1ad52e2014-04-08 18:48:47 -04008572{
Emeric Bruneb8def92018-02-19 15:59:48 +01008573 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
8574 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
David Sc1ad52e2014-04-08 18:48:47 -04008575 int finished_len;
Willy Tarreau83061a82018-07-13 11:56:34 +02008576 struct buffer *finished_trash;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008577 struct ssl_sock_ctx *ctx;
David Sc1ad52e2014-04-08 18:48:47 -04008578
8579 smp->flags = 0;
David Sc1ad52e2014-04-08 18:48:47 -04008580 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8581 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008582 ctx = conn->xprt_ctx;
David Sc1ad52e2014-04-08 18:48:47 -04008583
Willy Tarreau911db9b2020-01-23 16:27:54 +01008584 if (conn->flags & CO_FL_WAIT_XPRT) {
David Sc1ad52e2014-04-08 18:48:47 -04008585 smp->flags |= SMP_F_MAY_CHANGE;
8586 return 0;
8587 }
8588
8589 finished_trash = get_trash_chunk();
Olivier Houchard66ab4982019-02-26 18:37:15 +01008590 if (!SSL_session_reused(ctx->ssl))
8591 finished_len = SSL_get_peer_finished(ctx->ssl,
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008592 finished_trash->area,
8593 finished_trash->size);
David Sc1ad52e2014-04-08 18:48:47 -04008594 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01008595 finished_len = SSL_get_finished(ctx->ssl,
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008596 finished_trash->area,
8597 finished_trash->size);
David Sc1ad52e2014-04-08 18:48:47 -04008598
8599 if (!finished_len)
8600 return 0;
8601
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008602 finished_trash->data = finished_len;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02008603 smp->data.u.str = *finished_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008604 smp->data.type = SMP_T_BIN;
David Sc1ad52e2014-04-08 18:48:47 -04008605
8606 return 1;
David Sc1ad52e2014-04-08 18:48:47 -04008607}
Patrick Hemmer41966772018-04-28 19:15:48 -04008608#endif
David Sc1ad52e2014-04-08 18:48:47 -04008609
Emeric Brun2525b6b2012-10-18 15:59:43 +02008610/* integer, returns the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02008611static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008612smp_fetch_ssl_c_ca_err(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunf282a812012-09-21 15:27:54 +02008613{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008614 struct connection *conn;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008615 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008616
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02008617 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008618 if (!conn || conn->xprt != &ssl_sock)
8619 return 0;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008620 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008621
Willy Tarreau911db9b2020-01-23 16:27:54 +01008622 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Brunf282a812012-09-21 15:27:54 +02008623 smp->flags = SMP_F_MAY_CHANGE;
8624 return 0;
8625 }
8626
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008627 smp->data.type = SMP_T_SINT;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008628 smp->data.u.sint = (unsigned long long int)SSL_SOCK_ST_TO_CA_ERROR(ctx->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02008629 smp->flags = 0;
8630
8631 return 1;
8632}
8633
Emeric Brun2525b6b2012-10-18 15:59:43 +02008634/* integer, returns the depth of the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02008635static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008636smp_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 +02008637{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008638 struct connection *conn;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008639 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008640
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02008641 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008642 if (!conn || conn->xprt != &ssl_sock)
Emeric Brunf282a812012-09-21 15:27:54 +02008643 return 0;
8644
Willy Tarreau911db9b2020-01-23 16:27:54 +01008645 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Brunf282a812012-09-21 15:27:54 +02008646 smp->flags = SMP_F_MAY_CHANGE;
8647 return 0;
8648 }
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008649 ctx = conn->xprt_ctx;
Emeric Brunf282a812012-09-21 15:27:54 +02008650
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008651 smp->data.type = SMP_T_SINT;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008652 smp->data.u.sint = (long long int)SSL_SOCK_ST_TO_CAEDEPTH(ctx->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02008653 smp->flags = 0;
8654
8655 return 1;
8656}
8657
Emeric Brun2525b6b2012-10-18 15:59:43 +02008658/* integer, returns the first verify error on client certificate */
Emeric Brunf282a812012-09-21 15:27:54 +02008659static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008660smp_fetch_ssl_c_err(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunf282a812012-09-21 15:27:54 +02008661{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008662 struct connection *conn;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008663 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008664
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02008665 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008666 if (!conn || conn->xprt != &ssl_sock)
8667 return 0;
8668
Willy Tarreau911db9b2020-01-23 16:27:54 +01008669 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Brunf282a812012-09-21 15:27:54 +02008670 smp->flags = SMP_F_MAY_CHANGE;
8671 return 0;
8672 }
8673
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008674 ctx = conn->xprt_ctx;
8675
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008676 smp->data.type = SMP_T_SINT;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008677 smp->data.u.sint = (long long int)SSL_SOCK_ST_TO_CRTERROR(ctx->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02008678 smp->flags = 0;
8679
8680 return 1;
8681}
8682
Emeric Brun2525b6b2012-10-18 15:59:43 +02008683/* integer, returns the verify result on client cert */
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02008684static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008685smp_fetch_ssl_c_verify(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02008686{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008687 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008688 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008689
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02008690 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008691 if (!conn || conn->xprt != &ssl_sock)
8692 return 0;
8693
Willy Tarreau911db9b2020-01-23 16:27:54 +01008694 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02008695 smp->flags = SMP_F_MAY_CHANGE;
8696 return 0;
8697 }
8698
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008699 if (!conn->xprt_ctx)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02008700 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008701 ctx = conn->xprt_ctx;
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02008702
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008703 smp->data.type = SMP_T_SINT;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008704 smp->data.u.sint = (long long int)SSL_get_verify_result(ctx->ssl);
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02008705 smp->flags = 0;
8706
8707 return 1;
8708}
8709
Emmanuel Hocdet842e94e2019-12-16 16:39:17 +01008710/* for ca-file and ca-verify-file */
8711static int ssl_bind_parse_ca_file_common(char **args, int cur_arg, char **ca_file_p, char **err)
Emeric Brund94b3fe2012-09-20 18:23:56 +02008712{
8713 if (!*args[cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01008714 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
Emeric Brund94b3fe2012-09-20 18:23:56 +02008715 return ERR_ALERT | ERR_FATAL;
8716 }
8717
Willy Tarreauef934602016-12-22 23:12:01 +01008718 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
Emmanuel Hocdet842e94e2019-12-16 16:39:17 +01008719 memprintf(ca_file_p, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02008720 else
Emmanuel Hocdet842e94e2019-12-16 16:39:17 +01008721 memprintf(ca_file_p, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02008722
Emmanuel Hocdet842e94e2019-12-16 16:39:17 +01008723 if (!ssl_store_load_locations_file(*ca_file_p)) {
8724 memprintf(err, "'%s' : unable to load %s", args[cur_arg], *ca_file_p);
Emmanuel Hocdetd4f9a602019-10-24 11:32:47 +02008725 return ERR_ALERT | ERR_FATAL;
8726 }
Emeric Brund94b3fe2012-09-20 18:23:56 +02008727 return 0;
8728}
Emmanuel Hocdet842e94e2019-12-16 16:39:17 +01008729
8730/* parse the "ca-file" bind keyword */
8731static int ssl_bind_parse_ca_file(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
8732{
8733 return ssl_bind_parse_ca_file_common(args, cur_arg, &conf->ca_file, err);
8734}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008735static int bind_parse_ca_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8736{
8737 return ssl_bind_parse_ca_file(args, cur_arg, px, &conf->ssl_conf, err);
8738}
Emeric Brund94b3fe2012-09-20 18:23:56 +02008739
Emmanuel Hocdet842e94e2019-12-16 16:39:17 +01008740/* parse the "ca-verify-file" bind keyword */
8741static int ssl_bind_parse_ca_verify_file(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
8742{
8743 return ssl_bind_parse_ca_file_common(args, cur_arg, &conf->ca_verify_file, err);
8744}
8745static int bind_parse_ca_verify_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8746{
8747 return ssl_bind_parse_ca_verify_file(args, cur_arg, px, &conf->ssl_conf, err);
8748}
8749
Christopher Faulet31af49d2015-06-09 17:29:50 +02008750/* parse the "ca-sign-file" bind keyword */
8751static int bind_parse_ca_sign_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8752{
8753 if (!*args[cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01008754 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
Christopher Faulet31af49d2015-06-09 17:29:50 +02008755 return ERR_ALERT | ERR_FATAL;
8756 }
8757
Willy Tarreauef934602016-12-22 23:12:01 +01008758 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
8759 memprintf(&conf->ca_sign_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Christopher Faulet31af49d2015-06-09 17:29:50 +02008760 else
8761 memprintf(&conf->ca_sign_file, "%s", args[cur_arg + 1]);
8762
8763 return 0;
8764}
8765
Bertrand Jacquinff13c062016-11-13 16:37:11 +00008766/* parse the "ca-sign-pass" bind keyword */
Christopher Faulet31af49d2015-06-09 17:29:50 +02008767static int bind_parse_ca_sign_pass(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8768{
8769 if (!*args[cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01008770 memprintf(err, "'%s' : missing CAkey password", args[cur_arg]);
Christopher Faulet31af49d2015-06-09 17:29:50 +02008771 return ERR_ALERT | ERR_FATAL;
8772 }
8773 memprintf(&conf->ca_sign_pass, "%s", args[cur_arg + 1]);
8774 return 0;
8775}
8776
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008777/* parse the "ciphers" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008778static 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 +02008779{
8780 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02008781 memprintf(err, "'%s' : missing cipher suite", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008782 return ERR_ALERT | ERR_FATAL;
8783 }
8784
Emeric Brun76d88952012-10-05 15:47:31 +02008785 free(conf->ciphers);
Willy Tarreau4348fad2012-09-20 16:48:07 +02008786 conf->ciphers = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008787 return 0;
8788}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008789static int bind_parse_ciphers(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8790{
8791 return ssl_bind_parse_ciphers(args, cur_arg, px, &conf->ssl_conf, err);
8792}
Dirkjan Bussink415150f2018-09-14 11:14:21 +02008793
Emmanuel Hocdet839af572019-05-14 16:27:35 +02008794#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02008795/* parse the "ciphersuites" bind keyword */
8796static int ssl_bind_parse_ciphersuites(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
8797{
8798 if (!*args[cur_arg + 1]) {
8799 memprintf(err, "'%s' : missing cipher suite", args[cur_arg]);
8800 return ERR_ALERT | ERR_FATAL;
8801 }
8802
8803 free(conf->ciphersuites);
8804 conf->ciphersuites = strdup(args[cur_arg + 1]);
8805 return 0;
8806}
8807static int bind_parse_ciphersuites(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8808{
8809 return ssl_bind_parse_ciphersuites(args, cur_arg, px, &conf->ssl_conf, err);
8810}
8811#endif
8812
Willy Tarreaubbc91962019-10-16 16:42:19 +02008813/* parse the "crt" bind keyword. Returns a set of ERR_* flags possibly with an error in <err>. */
Willy Tarreau4348fad2012-09-20 16:48:07 +02008814static 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 +02008815{
Willy Tarreau38011032013-08-13 16:59:39 +02008816 char path[MAXPATHLEN];
Willy Tarreaub75d6922014-04-14 18:05:41 +02008817
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008818 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02008819 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008820 return ERR_ALERT | ERR_FATAL;
8821 }
8822
Willy Tarreauef934602016-12-22 23:12:01 +01008823 if ((*args[cur_arg + 1] != '/' ) && global_ssl.crt_base) {
8824 if ((strlen(global_ssl.crt_base) + 1 + strlen(args[cur_arg + 1]) + 1) > MAXPATHLEN) {
Emeric Brunc8e8d122012-10-02 18:42:10 +02008825 memprintf(err, "'%s' : path too long", args[cur_arg]);
8826 return ERR_ALERT | ERR_FATAL;
8827 }
Willy Tarreauef934602016-12-22 23:12:01 +01008828 snprintf(path, sizeof(path), "%s/%s", global_ssl.crt_base, args[cur_arg + 1]);
Willy Tarreaubbc91962019-10-16 16:42:19 +02008829 return ssl_sock_load_cert(path, conf, err);
Emeric Brunc8e8d122012-10-02 18:42:10 +02008830 }
8831
Willy Tarreaubbc91962019-10-16 16:42:19 +02008832 return ssl_sock_load_cert(args[cur_arg + 1], conf, err);
Emeric Brund94b3fe2012-09-20 18:23:56 +02008833}
8834
Willy Tarreaubbc91962019-10-16 16:42:19 +02008835/* 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 +01008836static int bind_parse_crt_list(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8837{
Willy Tarreaubbc91962019-10-16 16:42:19 +02008838 int err_code;
8839
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01008840 if (!*args[cur_arg + 1]) {
8841 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
8842 return ERR_ALERT | ERR_FATAL;
8843 }
8844
Willy Tarreaubbc91962019-10-16 16:42:19 +02008845 err_code = ssl_sock_load_cert_list_file(args[cur_arg + 1], conf, px, err);
8846 if (err_code)
Willy Tarreauad1731d2013-04-02 17:35:58 +02008847 memprintf(err, "'%s' : %s", args[cur_arg], *err);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01008848
Willy Tarreaubbc91962019-10-16 16:42:19 +02008849 return err_code;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01008850}
8851
Emeric Brunfb510ea2012-10-05 12:00:26 +02008852/* parse the "crl-file" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008853static 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 +02008854{
Emeric Brun051cdab2012-10-02 19:25:50 +02008855#ifndef X509_V_FLAG_CRL_CHECK
Tim Duesterhus93128532019-11-23 23:45:10 +01008856 memprintf(err, "'%s' : library does not support CRL verify", args[cur_arg]);
Emeric Brun051cdab2012-10-02 19:25:50 +02008857 return ERR_ALERT | ERR_FATAL;
8858#else
Emeric Brund94b3fe2012-09-20 18:23:56 +02008859 if (!*args[cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01008860 memprintf(err, "'%s' : missing CRLfile path", args[cur_arg]);
Emeric Brund94b3fe2012-09-20 18:23:56 +02008861 return ERR_ALERT | ERR_FATAL;
8862 }
Emeric Brun2b58d042012-09-20 17:10:03 +02008863
Willy Tarreauef934602016-12-22 23:12:01 +01008864 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
8865 memprintf(&conf->crl_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02008866 else
8867 memprintf(&conf->crl_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02008868
Emmanuel Hocdetb270e812019-11-21 19:09:31 +01008869 if (!ssl_store_load_locations_file(conf->crl_file)) {
8870 memprintf(err, "'%s' : unable to load %s", args[cur_arg], conf->crl_file);
8871 return ERR_ALERT | ERR_FATAL;
8872 }
Emeric Brun2b58d042012-09-20 17:10:03 +02008873 return 0;
Emeric Brun051cdab2012-10-02 19:25:50 +02008874#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02008875}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008876static int bind_parse_crl_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8877{
8878 return ssl_bind_parse_crl_file(args, cur_arg, px, &conf->ssl_conf, err);
8879}
Emeric Brun2b58d042012-09-20 17:10:03 +02008880
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01008881/* parse the "curves" bind keyword keyword */
8882static int ssl_bind_parse_curves(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
8883{
Lukas Tribusd14b49c2019-11-24 18:20:40 +01008884#if ((HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL) || defined(LIBRESSL_VERSION_NUMBER))
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01008885 if (!*args[cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01008886 memprintf(err, "'%s' : missing curve suite", args[cur_arg]);
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01008887 return ERR_ALERT | ERR_FATAL;
8888 }
8889 conf->curves = strdup(args[cur_arg + 1]);
8890 return 0;
8891#else
Tim Duesterhus93128532019-11-23 23:45:10 +01008892 memprintf(err, "'%s' : library does not support curve suite", args[cur_arg]);
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01008893 return ERR_ALERT | ERR_FATAL;
8894#endif
8895}
8896static int bind_parse_curves(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8897{
8898 return ssl_bind_parse_curves(args, cur_arg, px, &conf->ssl_conf, err);
8899}
8900
Bertrand Jacquinff13c062016-11-13 16:37:11 +00008901/* parse the "ecdhe" bind keyword keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008902static 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 +02008903{
Willy Tarreau9a1ab082019-05-09 13:26:41 +02008904#if HA_OPENSSL_VERSION_NUMBER < 0x0090800fL
Tim Duesterhus93128532019-11-23 23:45:10 +01008905 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (too old)", args[cur_arg]);
Emeric Brun2b58d042012-09-20 17:10:03 +02008906 return ERR_ALERT | ERR_FATAL;
8907#elif defined(OPENSSL_NO_ECDH)
Tim Duesterhus93128532019-11-23 23:45:10 +01008908 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 +02008909 return ERR_ALERT | ERR_FATAL;
8910#else
8911 if (!*args[cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01008912 memprintf(err, "'%s' : missing named curve", args[cur_arg]);
Emeric Brun2b58d042012-09-20 17:10:03 +02008913 return ERR_ALERT | ERR_FATAL;
8914 }
8915
8916 conf->ecdhe = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008917
8918 return 0;
Emeric Brun2b58d042012-09-20 17:10:03 +02008919#endif
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008920}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008921static int bind_parse_ecdhe(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8922{
8923 return ssl_bind_parse_ecdhe(args, cur_arg, px, &conf->ssl_conf, err);
8924}
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008925
Bertrand Jacquinff13c062016-11-13 16:37:11 +00008926/* parse the "crt-ignore-err" and "ca-ignore-err" bind keywords */
Emeric Brun81c00f02012-09-21 14:31:21 +02008927static int bind_parse_ignore_err(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8928{
8929 int code;
8930 char *p = args[cur_arg + 1];
8931 unsigned long long *ignerr = &conf->crt_ignerr;
8932
8933 if (!*p) {
Tim Duesterhus93128532019-11-23 23:45:10 +01008934 memprintf(err, "'%s' : missing error IDs list", args[cur_arg]);
Emeric Brun81c00f02012-09-21 14:31:21 +02008935 return ERR_ALERT | ERR_FATAL;
8936 }
8937
8938 if (strcmp(args[cur_arg], "ca-ignore-err") == 0)
8939 ignerr = &conf->ca_ignerr;
8940
8941 if (strcmp(p, "all") == 0) {
8942 *ignerr = ~0ULL;
8943 return 0;
8944 }
8945
8946 while (p) {
8947 code = atoi(p);
8948 if ((code <= 0) || (code > 63)) {
Tim Duesterhus93128532019-11-23 23:45:10 +01008949 memprintf(err, "'%s' : ID '%d' out of range (1..63) in error IDs list '%s'",
8950 args[cur_arg], code, args[cur_arg + 1]);
Emeric Brun81c00f02012-09-21 14:31:21 +02008951 return ERR_ALERT | ERR_FATAL;
8952 }
8953 *ignerr |= 1ULL << code;
8954 p = strchr(p, ',');
8955 if (p)
8956 p++;
8957 }
8958
Emeric Brun2cb7ae52012-10-05 14:14:21 +02008959 return 0;
8960}
8961
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008962/* parse tls_method_options "no-xxx" and "force-xxx" */
8963static int parse_tls_method_options(char *arg, struct tls_version_filter *methods, char **err)
Emeric Brun2cb7ae52012-10-05 14:14:21 +02008964{
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008965 uint16_t v;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008966 char *p;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008967 p = strchr(arg, '-');
8968 if (!p)
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008969 goto fail;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008970 p++;
8971 if (!strcmp(p, "sslv3"))
8972 v = CONF_SSLV3;
8973 else if (!strcmp(p, "tlsv10"))
8974 v = CONF_TLSV10;
8975 else if (!strcmp(p, "tlsv11"))
8976 v = CONF_TLSV11;
8977 else if (!strcmp(p, "tlsv12"))
8978 v = CONF_TLSV12;
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +02008979 else if (!strcmp(p, "tlsv13"))
8980 v = CONF_TLSV13;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008981 else
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008982 goto fail;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008983 if (!strncmp(arg, "no-", 3))
8984 methods->flags |= methodVersions[v].flag;
8985 else if (!strncmp(arg, "force-", 6))
8986 methods->min = methods->max = v;
8987 else
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008988 goto fail;
Emeric Brun2d0c4822012-10-02 13:45:20 +02008989 return 0;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008990 fail:
Tim Duesterhus93128532019-11-23 23:45:10 +01008991 memprintf(err, "'%s' : option not implemented", arg);
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008992 return ERR_ALERT | ERR_FATAL;
Emeric Brun2d0c4822012-10-02 13:45:20 +02008993}
8994
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008995static 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 +02008996{
Emmanuel Hocdet43664762017-08-09 18:26:20 +02008997 return parse_tls_method_options(args[cur_arg], &conf->ssl_conf.ssl_methods, err);
Emeric Brun2cb7ae52012-10-05 14:14:21 +02008998}
8999
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02009000static 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 +02009001{
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02009002 return parse_tls_method_options(args[*cur_arg], &newsrv->ssl_ctx.methods, err);
9003}
9004
9005/* parse tls_method min/max: "ssl-min-ver" and "ssl-max-ver" */
9006static int parse_tls_method_minmax(char **args, int cur_arg, struct tls_version_filter *methods, char **err)
9007{
9008 uint16_t i, v = 0;
9009 char *argv = args[cur_arg + 1];
9010 if (!*argv) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009011 memprintf(err, "'%s' : missing the ssl/tls version", args[cur_arg]);
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02009012 return ERR_ALERT | ERR_FATAL;
9013 }
9014 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
9015 if (!strcmp(argv, methodVersions[i].name))
9016 v = i;
9017 if (!v) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009018 memprintf(err, "'%s' : unknown ssl/tls version", args[cur_arg + 1]);
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02009019 return ERR_ALERT | ERR_FATAL;
9020 }
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02009021 if (!strcmp("ssl-min-ver", args[cur_arg]))
9022 methods->min = v;
9023 else if (!strcmp("ssl-max-ver", args[cur_arg]))
9024 methods->max = v;
9025 else {
Tim Duesterhus93128532019-11-23 23:45:10 +01009026 memprintf(err, "'%s' : option not implemented", args[cur_arg]);
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02009027 return ERR_ALERT | ERR_FATAL;
9028 }
Emeric Brun2cb7ae52012-10-05 14:14:21 +02009029 return 0;
Emeric Brun2cb7ae52012-10-05 14:14:21 +02009030}
Emeric Brun2cb7ae52012-10-05 14:14:21 +02009031
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02009032static int ssl_bind_parse_tls_method_minmax(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
9033{
Willy Tarreau9a1ab082019-05-09 13:26:41 +02009034#if (HA_OPENSSL_VERSION_NUMBER < 0x10101000L) && !defined(OPENSSL_IS_BORINGSSL)
Christopher Faulet767a84b2017-11-24 16:50:31 +01009035 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 +02009036#endif
9037 return parse_tls_method_minmax(args, cur_arg, &conf->ssl_methods, err);
9038}
9039
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02009040static int bind_parse_tls_method_minmax(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
9041{
Emmanuel Hocdet43664762017-08-09 18:26:20 +02009042 return parse_tls_method_minmax(args, cur_arg, &conf->ssl_conf.ssl_methods, err);
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02009043}
9044
9045static int srv_parse_tls_method_minmax(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9046{
9047 return parse_tls_method_minmax(args, *cur_arg, &newsrv->ssl_ctx.methods, err);
9048}
9049
Emeric Brun2d0c4822012-10-02 13:45:20 +02009050/* parse the "no-tls-tickets" bind keyword */
Emmanuel Hocdet4608ed92017-01-20 13:06:27 +01009051static 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 +02009052{
Emeric Brun89675492012-10-05 13:48:26 +02009053 conf->ssl_options |= BC_SSL_O_NO_TLS_TICKETS;
Emeric Brun81c00f02012-09-21 14:31:21 +02009054 return 0;
9055}
Emeric Brun2d0c4822012-10-02 13:45:20 +02009056
Olivier Houchardc2aae742017-09-22 18:26:28 +02009057/* parse the "allow-0rtt" bind keyword */
9058static int ssl_bind_parse_allow_0rtt(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
9059{
9060 conf->early_data = 1;
9061 return 0;
9062}
9063
9064static int bind_parse_allow_0rtt(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
9065{
Olivier Houchard9679ac92017-10-27 14:58:08 +02009066 conf->ssl_conf.early_data = 1;
Olivier Houchardc2aae742017-09-22 18:26:28 +02009067 return 0;
9068}
9069
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02009070/* parse the "npn" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01009071static 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 +02009072{
Bernard Spil13c53f82018-02-15 13:34:58 +01009073#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02009074 char *p1, *p2;
9075
9076 if (!*args[cur_arg + 1]) {
9077 memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[cur_arg]);
9078 return ERR_ALERT | ERR_FATAL;
9079 }
9080
9081 free(conf->npn_str);
9082
Willy Tarreau3724da12016-02-12 17:11:12 +01009083 /* the NPN string is built as a suite of (<len> <name>)*,
9084 * so we reuse each comma to store the next <len> and need
9085 * one more for the end of the string.
9086 */
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02009087 conf->npn_len = strlen(args[cur_arg + 1]) + 1;
Willy Tarreau3724da12016-02-12 17:11:12 +01009088 conf->npn_str = calloc(1, conf->npn_len + 1);
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02009089 memcpy(conf->npn_str + 1, args[cur_arg + 1], conf->npn_len);
9090
9091 /* replace commas with the name length */
9092 p1 = conf->npn_str;
9093 p2 = p1 + 1;
9094 while (1) {
9095 p2 = memchr(p1 + 1, ',', conf->npn_str + conf->npn_len - (p1 + 1));
9096 if (!p2)
9097 p2 = p1 + 1 + strlen(p1 + 1);
9098
9099 if (p2 - (p1 + 1) > 255) {
9100 *p2 = '\0';
9101 memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
9102 return ERR_ALERT | ERR_FATAL;
9103 }
9104
9105 *p1 = p2 - (p1 + 1);
9106 p1 = p2;
9107
9108 if (!*p2)
9109 break;
9110
9111 *(p2++) = '\0';
9112 }
9113 return 0;
9114#else
Tim Duesterhus93128532019-11-23 23:45:10 +01009115 memprintf(err, "'%s' : library does not support TLS NPN extension", args[cur_arg]);
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02009116 return ERR_ALERT | ERR_FATAL;
9117#endif
9118}
9119
Emmanuel Hocdet98263292016-12-29 18:26:15 +01009120static int bind_parse_npn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
9121{
9122 return ssl_bind_parse_npn(args, cur_arg, px, &conf->ssl_conf, err);
9123}
9124
Willy Tarreauab861d32013-04-02 02:30:41 +02009125/* parse the "alpn" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01009126static 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 +02009127{
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01009128#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02009129 char *p1, *p2;
9130
9131 if (!*args[cur_arg + 1]) {
9132 memprintf(err, "'%s' : missing the comma-delimited ALPN protocol suite", args[cur_arg]);
9133 return ERR_ALERT | ERR_FATAL;
9134 }
9135
9136 free(conf->alpn_str);
9137
Marcoen Hirschbergbef60912016-02-12 17:05:24 +01009138 /* the ALPN string is built as a suite of (<len> <name>)*,
9139 * so we reuse each comma to store the next <len> and need
9140 * one more for the end of the string.
9141 */
Willy Tarreauab861d32013-04-02 02:30:41 +02009142 conf->alpn_len = strlen(args[cur_arg + 1]) + 1;
Marcoen Hirschbergbef60912016-02-12 17:05:24 +01009143 conf->alpn_str = calloc(1, conf->alpn_len + 1);
Willy Tarreauab861d32013-04-02 02:30:41 +02009144 memcpy(conf->alpn_str + 1, args[cur_arg + 1], conf->alpn_len);
9145
9146 /* replace commas with the name length */
9147 p1 = conf->alpn_str;
9148 p2 = p1 + 1;
9149 while (1) {
9150 p2 = memchr(p1 + 1, ',', conf->alpn_str + conf->alpn_len - (p1 + 1));
9151 if (!p2)
9152 p2 = p1 + 1 + strlen(p1 + 1);
9153
9154 if (p2 - (p1 + 1) > 255) {
9155 *p2 = '\0';
9156 memprintf(err, "'%s' : ALPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
9157 return ERR_ALERT | ERR_FATAL;
9158 }
9159
9160 *p1 = p2 - (p1 + 1);
9161 p1 = p2;
9162
9163 if (!*p2)
9164 break;
9165
9166 *(p2++) = '\0';
9167 }
9168 return 0;
9169#else
Tim Duesterhus93128532019-11-23 23:45:10 +01009170 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[cur_arg]);
Willy Tarreauab861d32013-04-02 02:30:41 +02009171 return ERR_ALERT | ERR_FATAL;
9172#endif
9173}
9174
Emmanuel Hocdet98263292016-12-29 18:26:15 +01009175static int bind_parse_alpn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
9176{
9177 return ssl_bind_parse_alpn(args, cur_arg, px, &conf->ssl_conf, err);
9178}
9179
Willy Tarreau79eeafa2012-09-14 07:53:05 +02009180/* parse the "ssl" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02009181static 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 +02009182{
Willy Tarreau71a8c7c2016-12-21 22:04:54 +01009183 conf->xprt = &ssl_sock;
Willy Tarreau4348fad2012-09-20 16:48:07 +02009184 conf->is_ssl = 1;
Emeric Brun76d88952012-10-05 15:47:31 +02009185
Emmanuel Hocdet98263292016-12-29 18:26:15 +01009186 if (global_ssl.listen_default_ciphers && !conf->ssl_conf.ciphers)
9187 conf->ssl_conf.ciphers = strdup(global_ssl.listen_default_ciphers);
Emmanuel Hocdet839af572019-05-14 16:27:35 +02009188#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009189 if (global_ssl.listen_default_ciphersuites && !conf->ssl_conf.ciphersuites)
9190 conf->ssl_conf.ciphersuites = strdup(global_ssl.listen_default_ciphersuites);
9191#endif
Emmanuel Hocdet4608ed92017-01-20 13:06:27 +01009192 conf->ssl_options |= global_ssl.listen_default_ssloptions;
Emmanuel Hocdet43664762017-08-09 18:26:20 +02009193 conf->ssl_conf.ssl_methods.flags |= global_ssl.listen_default_sslmethods.flags;
9194 if (!conf->ssl_conf.ssl_methods.min)
9195 conf->ssl_conf.ssl_methods.min = global_ssl.listen_default_sslmethods.min;
9196 if (!conf->ssl_conf.ssl_methods.max)
9197 conf->ssl_conf.ssl_methods.max = global_ssl.listen_default_sslmethods.max;
Emeric Brun76d88952012-10-05 15:47:31 +02009198
Willy Tarreau79eeafa2012-09-14 07:53:05 +02009199 return 0;
9200}
9201
Lukas Tribus53ae85c2017-05-04 15:45:40 +00009202/* parse the "prefer-client-ciphers" bind keyword */
9203static int bind_parse_pcc(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
9204{
9205 conf->ssl_options |= BC_SSL_O_PREF_CLIE_CIPH;
9206 return 0;
9207}
9208
Christopher Faulet31af49d2015-06-09 17:29:50 +02009209/* parse the "generate-certificates" bind keyword */
9210static int bind_parse_generate_certs(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
9211{
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01009212#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Christopher Faulet31af49d2015-06-09 17:29:50 +02009213 conf->generate_certs = 1;
9214#else
9215 memprintf(err, "%sthis version of openssl cannot generate SSL certificates.\n",
9216 err && *err ? *err : "");
9217#endif
9218 return 0;
9219}
9220
Emmanuel Hocdet65623372013-01-24 17:17:15 +01009221/* parse the "strict-sni" bind keyword */
9222static int bind_parse_strict_sni(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
9223{
9224 conf->strict_sni = 1;
9225 return 0;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009226}
9227
9228/* parse the "tls-ticket-keys" bind keyword */
9229static int bind_parse_tls_ticket_keys(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
9230{
9231#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
Christopher Faulete566f3d2019-10-21 09:55:49 +02009232 FILE *f = NULL;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009233 int i = 0;
9234 char thisline[LINESIZE];
Christopher Faulete566f3d2019-10-21 09:55:49 +02009235 struct tls_keys_ref *keys_ref = NULL;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009236
9237 if (!*args[cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009238 memprintf(err, "'%s' : missing TLS ticket keys file path", args[cur_arg]);
Christopher Faulete566f3d2019-10-21 09:55:49 +02009239 goto fail;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009240 }
9241
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02009242 keys_ref = tlskeys_ref_lookup(args[cur_arg + 1]);
Willy Tarreau17b4aa12018-07-17 10:05:32 +02009243 if (keys_ref) {
9244 keys_ref->refcount++;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02009245 conf->keys_ref = keys_ref;
9246 return 0;
9247 }
9248
Christopher Faulete566f3d2019-10-21 09:55:49 +02009249 keys_ref = calloc(1, sizeof(*keys_ref));
Emeric Brun09852f72019-01-10 10:51:13 +01009250 if (!keys_ref) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009251 memprintf(err, "'%s' : allocation error", args[cur_arg+1]);
Christopher Faulete566f3d2019-10-21 09:55:49 +02009252 goto fail;
Emeric Brun09852f72019-01-10 10:51:13 +01009253 }
9254
Emeric Brun9e754772019-01-10 17:51:55 +01009255 keys_ref->tlskeys = malloc(TLS_TICKETS_NO * sizeof(union tls_sess_key));
Emeric Brun09852f72019-01-10 10:51:13 +01009256 if (!keys_ref->tlskeys) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009257 memprintf(err, "'%s' : allocation error", args[cur_arg+1]);
Christopher Faulete566f3d2019-10-21 09:55:49 +02009258 goto fail;
Emeric Brun09852f72019-01-10 10:51:13 +01009259 }
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009260
9261 if ((f = fopen(args[cur_arg + 1], "r")) == NULL) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009262 memprintf(err, "'%s' : unable to load ssl tickets keys file", args[cur_arg+1]);
Christopher Faulete566f3d2019-10-21 09:55:49 +02009263 goto fail;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009264 }
9265
Nenad Merdanovic146defa2015-05-09 08:46:00 +02009266 keys_ref->filename = strdup(args[cur_arg + 1]);
Emeric Brun09852f72019-01-10 10:51:13 +01009267 if (!keys_ref->filename) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009268 memprintf(err, "'%s' : allocation error", args[cur_arg+1]);
Christopher Faulete566f3d2019-10-21 09:55:49 +02009269 goto fail;
Emeric Brun09852f72019-01-10 10:51:13 +01009270 }
Nenad Merdanovic146defa2015-05-09 08:46:00 +02009271
Emeric Brun9e754772019-01-10 17:51:55 +01009272 keys_ref->key_size_bits = 0;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009273 while (fgets(thisline, sizeof(thisline), f) != NULL) {
9274 int len = strlen(thisline);
Emeric Brun9e754772019-01-10 17:51:55 +01009275 int dec_size;
9276
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009277 /* Strip newline characters from the end */
9278 if(thisline[len - 1] == '\n')
9279 thisline[--len] = 0;
9280
9281 if(thisline[len - 1] == '\r')
9282 thisline[--len] = 0;
9283
Emeric Brun9e754772019-01-10 17:51:55 +01009284 dec_size = base64dec(thisline, len, (char *) (keys_ref->tlskeys + i % TLS_TICKETS_NO), sizeof(union tls_sess_key));
9285 if (dec_size < 0) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009286 memprintf(err, "'%s' : unable to decode base64 key on line %d", args[cur_arg+1], i + 1);
Christopher Faulete566f3d2019-10-21 09:55:49 +02009287 goto fail;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009288 }
Emeric Brun9e754772019-01-10 17:51:55 +01009289 else if (!keys_ref->key_size_bits && (dec_size == sizeof(struct tls_sess_key_128))) {
9290 keys_ref->key_size_bits = 128;
9291 }
9292 else if (!keys_ref->key_size_bits && (dec_size == sizeof(struct tls_sess_key_256))) {
9293 keys_ref->key_size_bits = 256;
9294 }
9295 else if (((dec_size != sizeof(struct tls_sess_key_128)) && (dec_size != sizeof(struct tls_sess_key_256)))
9296 || ((dec_size == sizeof(struct tls_sess_key_128) && (keys_ref->key_size_bits != 128)))
9297 || ((dec_size == sizeof(struct tls_sess_key_256) && (keys_ref->key_size_bits != 256)))) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009298 memprintf(err, "'%s' : wrong sized key on line %d", args[cur_arg+1], i + 1);
Christopher Faulete566f3d2019-10-21 09:55:49 +02009299 goto fail;
Emeric Brun9e754772019-01-10 17:51:55 +01009300 }
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009301 i++;
9302 }
9303
9304 if (i < TLS_TICKETS_NO) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009305 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 +02009306 goto fail;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009307 }
9308
9309 fclose(f);
9310
9311 /* Use penultimate key for encryption, handle when TLS_TICKETS_NO = 1 */
Nenad Merdanovic17891152016-03-25 22:16:57 +01009312 i -= 2;
9313 keys_ref->tls_ticket_enc_index = i < 0 ? 0 : i % TLS_TICKETS_NO;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02009314 keys_ref->unique_id = -1;
Willy Tarreau17b4aa12018-07-17 10:05:32 +02009315 keys_ref->refcount = 1;
Christopher Faulet16f45c82018-02-16 11:23:49 +01009316 HA_RWLOCK_INIT(&keys_ref->lock);
Nenad Merdanovic146defa2015-05-09 08:46:00 +02009317 conf->keys_ref = keys_ref;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009318
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02009319 LIST_ADD(&tlskeys_reference, &keys_ref->list);
9320
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009321 return 0;
Christopher Faulete566f3d2019-10-21 09:55:49 +02009322
9323 fail:
9324 if (f)
9325 fclose(f);
9326 if (keys_ref) {
9327 free(keys_ref->filename);
9328 free(keys_ref->tlskeys);
9329 free(keys_ref);
9330 }
9331 return ERR_ALERT | ERR_FATAL;
9332
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009333#else
Tim Duesterhus93128532019-11-23 23:45:10 +01009334 memprintf(err, "'%s' : TLS ticket callback extension not supported", args[cur_arg]);
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009335 return ERR_ALERT | ERR_FATAL;
9336#endif /* SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB */
Emmanuel Hocdet65623372013-01-24 17:17:15 +01009337}
9338
Emeric Brund94b3fe2012-09-20 18:23:56 +02009339/* parse the "verify" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01009340static 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 +02009341{
9342 if (!*args[cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009343 memprintf(err, "'%s' : missing verify method", args[cur_arg]);
Emeric Brund94b3fe2012-09-20 18:23:56 +02009344 return ERR_ALERT | ERR_FATAL;
9345 }
9346
9347 if (strcmp(args[cur_arg + 1], "none") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01009348 conf->verify = SSL_SOCK_VERIFY_NONE;
Emeric Brund94b3fe2012-09-20 18:23:56 +02009349 else if (strcmp(args[cur_arg + 1], "optional") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01009350 conf->verify = SSL_SOCK_VERIFY_OPTIONAL;
Emeric Brund94b3fe2012-09-20 18:23:56 +02009351 else if (strcmp(args[cur_arg + 1], "required") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01009352 conf->verify = SSL_SOCK_VERIFY_REQUIRED;
Emeric Brund94b3fe2012-09-20 18:23:56 +02009353 else {
Tim Duesterhus93128532019-11-23 23:45:10 +01009354 memprintf(err, "'%s' : unknown verify method '%s', only 'none', 'optional', and 'required' are supported\n",
9355 args[cur_arg], args[cur_arg + 1]);
Emeric Brund94b3fe2012-09-20 18:23:56 +02009356 return ERR_ALERT | ERR_FATAL;
9357 }
9358
9359 return 0;
9360}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01009361static int bind_parse_verify(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
9362{
9363 return ssl_bind_parse_verify(args, cur_arg, px, &conf->ssl_conf, err);
9364}
Emeric Brund94b3fe2012-09-20 18:23:56 +02009365
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02009366/* parse the "no-ca-names" bind keyword */
9367static int ssl_bind_parse_no_ca_names(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
9368{
9369 conf->no_ca_names = 1;
9370 return 0;
9371}
9372static int bind_parse_no_ca_names(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
9373{
9374 return ssl_bind_parse_no_ca_names(args, cur_arg, px, &conf->ssl_conf, err);
9375}
9376
Willy Tarreau92faadf2012-10-10 23:04:25 +02009377/************** "server" keywords ****************/
9378
Olivier Houchardc7566002018-11-20 23:33:50 +01009379/* parse the "npn" bind keyword */
9380static int srv_parse_npn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9381{
9382#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
9383 char *p1, *p2;
9384
9385 if (!*args[*cur_arg + 1]) {
9386 memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[*cur_arg]);
9387 return ERR_ALERT | ERR_FATAL;
9388 }
9389
9390 free(newsrv->ssl_ctx.npn_str);
9391
9392 /* the NPN string is built as a suite of (<len> <name>)*,
9393 * so we reuse each comma to store the next <len> and need
9394 * one more for the end of the string.
9395 */
9396 newsrv->ssl_ctx.npn_len = strlen(args[*cur_arg + 1]) + 1;
9397 newsrv->ssl_ctx.npn_str = calloc(1, newsrv->ssl_ctx.npn_len + 1);
9398 memcpy(newsrv->ssl_ctx.npn_str + 1, args[*cur_arg + 1],
9399 newsrv->ssl_ctx.npn_len);
9400
9401 /* replace commas with the name length */
9402 p1 = newsrv->ssl_ctx.npn_str;
9403 p2 = p1 + 1;
9404 while (1) {
9405 p2 = memchr(p1 + 1, ',', newsrv->ssl_ctx.npn_str +
9406 newsrv->ssl_ctx.npn_len - (p1 + 1));
9407 if (!p2)
9408 p2 = p1 + 1 + strlen(p1 + 1);
9409
9410 if (p2 - (p1 + 1) > 255) {
9411 *p2 = '\0';
9412 memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[*cur_arg], p1 + 1);
9413 return ERR_ALERT | ERR_FATAL;
9414 }
9415
9416 *p1 = p2 - (p1 + 1);
9417 p1 = p2;
9418
9419 if (!*p2)
9420 break;
9421
9422 *(p2++) = '\0';
9423 }
9424 return 0;
9425#else
Tim Duesterhus93128532019-11-23 23:45:10 +01009426 memprintf(err, "'%s' : library does not support TLS NPN extension", args[*cur_arg]);
Olivier Houchardc7566002018-11-20 23:33:50 +01009427 return ERR_ALERT | ERR_FATAL;
9428#endif
9429}
9430
Olivier Houchard92150142018-12-21 19:47:01 +01009431/* parse the "alpn" or the "check-alpn" server keyword */
Olivier Houchardc7566002018-11-20 23:33:50 +01009432static int srv_parse_alpn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9433{
9434#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
9435 char *p1, *p2;
Olivier Houchard92150142018-12-21 19:47:01 +01009436 char **alpn_str;
9437 int *alpn_len;
Olivier Houchardc7566002018-11-20 23:33:50 +01009438
Olivier Houchard92150142018-12-21 19:47:01 +01009439 if (*args[*cur_arg] == 'c') {
9440 alpn_str = &newsrv->check.alpn_str;
9441 alpn_len = &newsrv->check.alpn_len;
9442 } else {
9443 alpn_str = &newsrv->ssl_ctx.alpn_str;
9444 alpn_len = &newsrv->ssl_ctx.alpn_len;
9445
9446 }
Olivier Houchardc7566002018-11-20 23:33:50 +01009447 if (!*args[*cur_arg + 1]) {
9448 memprintf(err, "'%s' : missing the comma-delimited ALPN protocol suite", args[*cur_arg]);
9449 return ERR_ALERT | ERR_FATAL;
9450 }
9451
Olivier Houchard92150142018-12-21 19:47:01 +01009452 free(*alpn_str);
Olivier Houchardc7566002018-11-20 23:33:50 +01009453
9454 /* the ALPN string is built as a suite of (<len> <name>)*,
9455 * so we reuse each comma to store the next <len> and need
9456 * one more for the end of the string.
9457 */
Olivier Houchard92150142018-12-21 19:47:01 +01009458 *alpn_len = strlen(args[*cur_arg + 1]) + 1;
9459 *alpn_str = calloc(1, *alpn_len + 1);
9460 memcpy(*alpn_str + 1, args[*cur_arg + 1], *alpn_len);
Olivier Houchardc7566002018-11-20 23:33:50 +01009461
9462 /* replace commas with the name length */
Olivier Houchard92150142018-12-21 19:47:01 +01009463 p1 = *alpn_str;
Olivier Houchardc7566002018-11-20 23:33:50 +01009464 p2 = p1 + 1;
9465 while (1) {
Olivier Houchard92150142018-12-21 19:47:01 +01009466 p2 = memchr(p1 + 1, ',', *alpn_str + *alpn_len - (p1 + 1));
Olivier Houchardc7566002018-11-20 23:33:50 +01009467 if (!p2)
9468 p2 = p1 + 1 + strlen(p1 + 1);
9469
9470 if (p2 - (p1 + 1) > 255) {
9471 *p2 = '\0';
9472 memprintf(err, "'%s' : ALPN protocol name too long : '%s'", args[*cur_arg], p1 + 1);
9473 return ERR_ALERT | ERR_FATAL;
9474 }
9475
9476 *p1 = p2 - (p1 + 1);
9477 p1 = p2;
9478
9479 if (!*p2)
9480 break;
9481
9482 *(p2++) = '\0';
9483 }
9484 return 0;
9485#else
Tim Duesterhus93128532019-11-23 23:45:10 +01009486 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[*cur_arg]);
Olivier Houchardc7566002018-11-20 23:33:50 +01009487 return ERR_ALERT | ERR_FATAL;
9488#endif
9489}
9490
Emeric Brunef42d922012-10-11 16:11:36 +02009491/* parse the "ca-file" server keyword */
9492static int srv_parse_ca_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9493{
9494 if (!*args[*cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009495 memprintf(err, "'%s' : missing CAfile path", args[*cur_arg]);
Emeric Brunef42d922012-10-11 16:11:36 +02009496 return ERR_ALERT | ERR_FATAL;
9497 }
9498
Willy Tarreauef934602016-12-22 23:12:01 +01009499 if ((*args[*cur_arg + 1] != '/') && global_ssl.ca_base)
9500 memprintf(&newsrv->ssl_ctx.ca_file, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02009501 else
9502 memprintf(&newsrv->ssl_ctx.ca_file, "%s", args[*cur_arg + 1]);
9503
Emmanuel Hocdetd4f9a602019-10-24 11:32:47 +02009504 if (!ssl_store_load_locations_file(newsrv->ssl_ctx.ca_file)) {
9505 memprintf(err, "'%s' : unable to load %s", args[*cur_arg], newsrv->ssl_ctx.ca_file);
9506 return ERR_ALERT | ERR_FATAL;
9507 }
Emeric Brunef42d922012-10-11 16:11:36 +02009508 return 0;
9509}
9510
Olivier Houchard9130a962017-10-17 17:33:43 +02009511/* parse the "check-sni" server keyword */
9512static int srv_parse_check_sni(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9513{
9514 if (!*args[*cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009515 memprintf(err, "'%s' : missing SNI", args[*cur_arg]);
Olivier Houchard9130a962017-10-17 17:33:43 +02009516 return ERR_ALERT | ERR_FATAL;
9517 }
9518
9519 newsrv->check.sni = strdup(args[*cur_arg + 1]);
9520 if (!newsrv->check.sni) {
9521 memprintf(err, "'%s' : failed to allocate memory", args[*cur_arg]);
9522 return ERR_ALERT | ERR_FATAL;
9523 }
9524 return 0;
9525
9526}
9527
Willy Tarreau92faadf2012-10-10 23:04:25 +02009528/* parse the "check-ssl" server keyword */
9529static int srv_parse_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9530{
9531 newsrv->check.use_ssl = 1;
Willy Tarreauef934602016-12-22 23:12:01 +01009532 if (global_ssl.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
9533 newsrv->ssl_ctx.ciphers = strdup(global_ssl.connect_default_ciphers);
Emmanuel Hocdet839af572019-05-14 16:27:35 +02009534#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009535 if (global_ssl.connect_default_ciphersuites && !newsrv->ssl_ctx.ciphersuites)
9536 newsrv->ssl_ctx.ciphersuites = strdup(global_ssl.connect_default_ciphersuites);
9537#endif
Willy Tarreauef934602016-12-22 23:12:01 +01009538 newsrv->ssl_ctx.options |= global_ssl.connect_default_ssloptions;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02009539 newsrv->ssl_ctx.methods.flags |= global_ssl.connect_default_sslmethods.flags;
9540 if (!newsrv->ssl_ctx.methods.min)
9541 newsrv->ssl_ctx.methods.min = global_ssl.connect_default_sslmethods.min;
9542 if (!newsrv->ssl_ctx.methods.max)
9543 newsrv->ssl_ctx.methods.max = global_ssl.connect_default_sslmethods.max;
9544
Willy Tarreau92faadf2012-10-10 23:04:25 +02009545 return 0;
9546}
9547
9548/* parse the "ciphers" server keyword */
9549static int srv_parse_ciphers(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9550{
9551 if (!*args[*cur_arg + 1]) {
9552 memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
9553 return ERR_ALERT | ERR_FATAL;
9554 }
9555
9556 free(newsrv->ssl_ctx.ciphers);
9557 newsrv->ssl_ctx.ciphers = strdup(args[*cur_arg + 1]);
9558 return 0;
9559}
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009560
Emmanuel Hocdet839af572019-05-14 16:27:35 +02009561#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009562/* parse the "ciphersuites" server keyword */
9563static int srv_parse_ciphersuites(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9564{
9565 if (!*args[*cur_arg + 1]) {
9566 memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
9567 return ERR_ALERT | ERR_FATAL;
9568 }
9569
9570 free(newsrv->ssl_ctx.ciphersuites);
9571 newsrv->ssl_ctx.ciphersuites = strdup(args[*cur_arg + 1]);
9572 return 0;
9573}
9574#endif
Willy Tarreau92faadf2012-10-10 23:04:25 +02009575
Emeric Brunef42d922012-10-11 16:11:36 +02009576/* parse the "crl-file" server keyword */
9577static int srv_parse_crl_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9578{
9579#ifndef X509_V_FLAG_CRL_CHECK
Tim Duesterhus93128532019-11-23 23:45:10 +01009580 memprintf(err, "'%s' : library does not support CRL verify", args[*cur_arg]);
Emeric Brunef42d922012-10-11 16:11:36 +02009581 return ERR_ALERT | ERR_FATAL;
9582#else
9583 if (!*args[*cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009584 memprintf(err, "'%s' : missing CRLfile path", args[*cur_arg]);
Emeric Brunef42d922012-10-11 16:11:36 +02009585 return ERR_ALERT | ERR_FATAL;
9586 }
9587
Willy Tarreauef934602016-12-22 23:12:01 +01009588 if ((*args[*cur_arg + 1] != '/') && global_ssl.ca_base)
9589 memprintf(&newsrv->ssl_ctx.crl_file, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02009590 else
9591 memprintf(&newsrv->ssl_ctx.crl_file, "%s", args[*cur_arg + 1]);
9592
Emmanuel Hocdetb270e812019-11-21 19:09:31 +01009593 if (!ssl_store_load_locations_file(newsrv->ssl_ctx.crl_file)) {
9594 memprintf(err, "'%s' : unable to load %s", args[*cur_arg], newsrv->ssl_ctx.crl_file);
9595 return ERR_ALERT | ERR_FATAL;
9596 }
Emeric Brunef42d922012-10-11 16:11:36 +02009597 return 0;
9598#endif
9599}
9600
Emeric Bruna7aa3092012-10-26 12:58:00 +02009601/* parse the "crt" server keyword */
9602static int srv_parse_crt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9603{
9604 if (!*args[*cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009605 memprintf(err, "'%s' : missing certificate file path", args[*cur_arg]);
Emeric Bruna7aa3092012-10-26 12:58:00 +02009606 return ERR_ALERT | ERR_FATAL;
9607 }
9608
Willy Tarreauef934602016-12-22 23:12:01 +01009609 if ((*args[*cur_arg + 1] != '/') && global_ssl.crt_base)
Christopher Fauletff3a41e2017-11-23 09:13:32 +01009610 memprintf(&newsrv->ssl_ctx.client_crt, "%s/%s", global_ssl.crt_base, args[*cur_arg + 1]);
Emeric Bruna7aa3092012-10-26 12:58:00 +02009611 else
9612 memprintf(&newsrv->ssl_ctx.client_crt, "%s", args[*cur_arg + 1]);
9613
9614 return 0;
9615}
Emeric Brunef42d922012-10-11 16:11:36 +02009616
Frédéric Lécaille340ae602017-03-13 10:38:04 +01009617/* parse the "no-check-ssl" server keyword */
9618static int srv_parse_no_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9619{
9620 newsrv->check.use_ssl = 0;
9621 free(newsrv->ssl_ctx.ciphers);
9622 newsrv->ssl_ctx.ciphers = NULL;
9623 newsrv->ssl_ctx.options &= ~global_ssl.connect_default_ssloptions;
9624 return 0;
9625}
9626
Frédéric Lécaillee892c4c2017-03-13 12:08:01 +01009627/* parse the "no-send-proxy-v2-ssl" server keyword */
9628static int srv_parse_no_send_proxy_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9629{
9630 newsrv->pp_opts &= ~SRV_PP_V2;
9631 newsrv->pp_opts &= ~SRV_PP_V2_SSL;
9632 return 0;
9633}
9634
9635/* parse the "no-send-proxy-v2-ssl-cn" server keyword */
9636static int srv_parse_no_send_proxy_cn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9637{
9638 newsrv->pp_opts &= ~SRV_PP_V2;
9639 newsrv->pp_opts &= ~SRV_PP_V2_SSL;
9640 newsrv->pp_opts &= ~SRV_PP_V2_SSL_CN;
9641 return 0;
9642}
9643
Frédéric Lécaillee381d762017-03-13 11:54:17 +01009644/* parse the "no-ssl" server keyword */
9645static int srv_parse_no_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9646{
9647 newsrv->use_ssl = 0;
9648 free(newsrv->ssl_ctx.ciphers);
9649 newsrv->ssl_ctx.ciphers = NULL;
9650 return 0;
9651}
9652
Olivier Houchard522eea72017-11-03 16:27:47 +01009653/* parse the "allow-0rtt" server keyword */
9654static int srv_parse_allow_0rtt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9655{
9656 newsrv->ssl_ctx.options |= SRV_SSL_O_EARLY_DATA;
9657 return 0;
9658}
9659
Willy Tarreau2a3fb1c2015-02-05 16:47:07 +01009660/* parse the "no-ssl-reuse" server keyword */
9661static int srv_parse_no_ssl_reuse(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9662{
9663 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_REUSE;
9664 return 0;
9665}
9666
Emeric Brunf9c5c472012-10-11 15:28:34 +02009667/* parse the "no-tls-tickets" server keyword */
9668static int srv_parse_no_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9669{
9670 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLS_TICKETS;
9671 return 0;
9672}
David Safb76832014-05-08 23:42:08 -04009673/* parse the "send-proxy-v2-ssl" server keyword */
9674static int srv_parse_send_proxy_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9675{
9676 newsrv->pp_opts |= SRV_PP_V2;
9677 newsrv->pp_opts |= SRV_PP_V2_SSL;
9678 return 0;
9679}
9680
9681/* parse the "send-proxy-v2-ssl-cn" server keyword */
9682static int srv_parse_send_proxy_cn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9683{
9684 newsrv->pp_opts |= SRV_PP_V2;
9685 newsrv->pp_opts |= SRV_PP_V2_SSL;
9686 newsrv->pp_opts |= SRV_PP_V2_SSL_CN;
9687 return 0;
9688}
Emeric Brunf9c5c472012-10-11 15:28:34 +02009689
Willy Tarreau732eac42015-07-09 11:40:25 +02009690/* parse the "sni" server keyword */
9691static int srv_parse_sni(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9692{
9693#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
9694 memprintf(err, "'%s' : the current SSL library doesn't support the SNI TLS extension", args[*cur_arg]);
9695 return ERR_ALERT | ERR_FATAL;
9696#else
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01009697 char *arg;
Willy Tarreau732eac42015-07-09 11:40:25 +02009698
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01009699 arg = args[*cur_arg + 1];
9700 if (!*arg) {
Willy Tarreau732eac42015-07-09 11:40:25 +02009701 memprintf(err, "'%s' : missing sni expression", args[*cur_arg]);
9702 return ERR_ALERT | ERR_FATAL;
9703 }
9704
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01009705 free(newsrv->sni_expr);
9706 newsrv->sni_expr = strdup(arg);
Willy Tarreau732eac42015-07-09 11:40:25 +02009707
Willy Tarreau732eac42015-07-09 11:40:25 +02009708 return 0;
9709#endif
9710}
9711
Willy Tarreau92faadf2012-10-10 23:04:25 +02009712/* parse the "ssl" server keyword */
9713static int srv_parse_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9714{
9715 newsrv->use_ssl = 1;
Willy Tarreauef934602016-12-22 23:12:01 +01009716 if (global_ssl.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
9717 newsrv->ssl_ctx.ciphers = strdup(global_ssl.connect_default_ciphers);
Emmanuel Hocdet839af572019-05-14 16:27:35 +02009718#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009719 if (global_ssl.connect_default_ciphersuites && !newsrv->ssl_ctx.ciphersuites)
9720 newsrv->ssl_ctx.ciphersuites = strdup(global_ssl.connect_default_ciphersuites);
9721#endif
Willy Tarreau92faadf2012-10-10 23:04:25 +02009722 return 0;
9723}
9724
Frédéric Lécaille2cfcdbe2017-03-13 11:32:20 +01009725/* parse the "ssl-reuse" server keyword */
9726static int srv_parse_ssl_reuse(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9727{
9728 newsrv->ssl_ctx.options &= ~SRV_SSL_O_NO_REUSE;
9729 return 0;
9730}
9731
Frédéric Lécaille2cfcdbe2017-03-13 11:32:20 +01009732/* parse the "tls-tickets" server keyword */
9733static int srv_parse_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9734{
9735 newsrv->ssl_ctx.options &= ~SRV_SSL_O_NO_TLS_TICKETS;
9736 return 0;
9737}
9738
Emeric Brunef42d922012-10-11 16:11:36 +02009739/* parse the "verify" server keyword */
9740static int srv_parse_verify(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9741{
9742 if (!*args[*cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009743 memprintf(err, "'%s' : missing verify method", args[*cur_arg]);
Emeric Brunef42d922012-10-11 16:11:36 +02009744 return ERR_ALERT | ERR_FATAL;
9745 }
9746
9747 if (strcmp(args[*cur_arg + 1], "none") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01009748 newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_NONE;
Emeric Brunef42d922012-10-11 16:11:36 +02009749 else if (strcmp(args[*cur_arg + 1], "required") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01009750 newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_REQUIRED;
Emeric Brunef42d922012-10-11 16:11:36 +02009751 else {
Tim Duesterhus93128532019-11-23 23:45:10 +01009752 memprintf(err, "'%s' : unknown verify method '%s', only 'none' and 'required' are supported\n",
9753 args[*cur_arg], args[*cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02009754 return ERR_ALERT | ERR_FATAL;
9755 }
9756
Evan Broderbe554312013-06-27 00:05:25 -07009757 return 0;
9758}
9759
9760/* parse the "verifyhost" server keyword */
9761static int srv_parse_verifyhost(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9762{
9763 if (!*args[*cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009764 memprintf(err, "'%s' : missing hostname to verify against", args[*cur_arg]);
Evan Broderbe554312013-06-27 00:05:25 -07009765 return ERR_ALERT | ERR_FATAL;
9766 }
9767
Frédéric Lécaille273f3212017-03-13 15:52:01 +01009768 free(newsrv->ssl_ctx.verify_host);
Evan Broderbe554312013-06-27 00:05:25 -07009769 newsrv->ssl_ctx.verify_host = strdup(args[*cur_arg + 1]);
9770
Emeric Brunef42d922012-10-11 16:11:36 +02009771 return 0;
9772}
9773
Emeric Brun2c86cbf2014-10-30 15:56:50 +01009774/* parse the "ssl-default-bind-options" keyword in global section */
9775static int ssl_parse_default_bind_options(char **args, int section_type, struct proxy *curpx,
9776 struct proxy *defpx, const char *file, int line,
9777 char **err) {
9778 int i = 1;
9779
9780 if (*(args[i]) == 0) {
9781 memprintf(err, "global statement '%s' expects an option as an argument.", args[0]);
9782 return -1;
9783 }
9784 while (*(args[i])) {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02009785 if (!strcmp(args[i], "no-tls-tickets"))
Willy Tarreauef934602016-12-22 23:12:01 +01009786 global_ssl.listen_default_ssloptions |= BC_SSL_O_NO_TLS_TICKETS;
Lukas Tribus53ae85c2017-05-04 15:45:40 +00009787 else if (!strcmp(args[i], "prefer-client-ciphers"))
9788 global_ssl.listen_default_ssloptions |= BC_SSL_O_PREF_CLIE_CIPH;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02009789 else if (!strcmp(args[i], "ssl-min-ver") || !strcmp(args[i], "ssl-max-ver")) {
9790 if (!parse_tls_method_minmax(args, i, &global_ssl.listen_default_sslmethods, err))
9791 i++;
9792 else {
9793 memprintf(err, "%s on global statement '%s'.", *err, args[0]);
9794 return -1;
9795 }
9796 }
9797 else if (parse_tls_method_options(args[i], &global_ssl.listen_default_sslmethods, err)) {
Emeric Brun2c86cbf2014-10-30 15:56:50 +01009798 memprintf(err, "unknown option '%s' on global statement '%s'.", args[i], args[0]);
9799 return -1;
9800 }
9801 i++;
9802 }
9803 return 0;
9804}
9805
9806/* parse the "ssl-default-server-options" keyword in global section */
9807static int ssl_parse_default_server_options(char **args, int section_type, struct proxy *curpx,
9808 struct proxy *defpx, const char *file, int line,
9809 char **err) {
9810 int i = 1;
9811
9812 if (*(args[i]) == 0) {
9813 memprintf(err, "global statement '%s' expects an option as an argument.", args[0]);
9814 return -1;
9815 }
9816 while (*(args[i])) {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02009817 if (!strcmp(args[i], "no-tls-tickets"))
Willy Tarreauef934602016-12-22 23:12:01 +01009818 global_ssl.connect_default_ssloptions |= SRV_SSL_O_NO_TLS_TICKETS;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02009819 else if (!strcmp(args[i], "ssl-min-ver") || !strcmp(args[i], "ssl-max-ver")) {
9820 if (!parse_tls_method_minmax(args, i, &global_ssl.connect_default_sslmethods, err))
9821 i++;
9822 else {
9823 memprintf(err, "%s on global statement '%s'.", *err, args[0]);
9824 return -1;
9825 }
9826 }
9827 else if (parse_tls_method_options(args[i], &global_ssl.connect_default_sslmethods, err)) {
Emeric Brun2c86cbf2014-10-30 15:56:50 +01009828 memprintf(err, "unknown option '%s' on global statement '%s'.", args[i], args[0]);
9829 return -1;
9830 }
9831 i++;
9832 }
9833 return 0;
9834}
9835
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01009836/* parse the "ca-base" / "crt-base" keywords in global section.
9837 * Returns <0 on alert, >0 on warning, 0 on success.
9838 */
9839static int ssl_parse_global_ca_crt_base(char **args, int section_type, struct proxy *curpx,
9840 struct proxy *defpx, const char *file, int line,
9841 char **err)
9842{
9843 char **target;
9844
Willy Tarreauef934602016-12-22 23:12:01 +01009845 target = (args[0][1] == 'a') ? &global_ssl.ca_base : &global_ssl.crt_base;
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01009846
9847 if (too_many_args(1, args, err, NULL))
9848 return -1;
9849
9850 if (*target) {
9851 memprintf(err, "'%s' already specified.", args[0]);
9852 return -1;
9853 }
9854
9855 if (*(args[1]) == 0) {
9856 memprintf(err, "global statement '%s' expects a directory path as an argument.", args[0]);
9857 return -1;
9858 }
9859 *target = strdup(args[1]);
9860 return 0;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00009861}
9862
Emmanuel Hocdet70df7bf2019-01-04 11:08:20 +01009863/* "issuers-chain-path" load chain certificate in global */
9864static int ssl_load_global_issuer_from_BIO(BIO *in, char *fp, char **err)
9865{
9866 X509 *ca;
9867 X509_NAME *name = NULL;
9868 ASN1_OCTET_STRING *skid = NULL;
9869 STACK_OF(X509) *chain = NULL;
9870 struct issuer_chain *issuer;
9871 struct eb64_node *node;
9872 char *path;
9873 u64 key;
9874 int ret = 0;
9875
9876 while ((ca = PEM_read_bio_X509(in, NULL, NULL, NULL))) {
9877 if (chain == NULL) {
9878 chain = sk_X509_new_null();
9879 skid = X509_get_ext_d2i(ca, NID_subject_key_identifier, NULL, NULL);
9880 name = X509_get_subject_name(ca);
9881 }
9882 if (!sk_X509_push(chain, ca)) {
9883 X509_free(ca);
9884 goto end;
9885 }
9886 }
9887 if (!chain) {
9888 memprintf(err, "unable to load issuers-chain %s : pem certificate not found.\n", fp);
9889 goto end;
9890 }
9891 if (!skid) {
9892 memprintf(err, "unable to load issuers-chain %s : SubjectKeyIdentifier not found.\n", fp);
9893 goto end;
9894 }
9895 if (!name) {
9896 memprintf(err, "unable to load issuers-chain %s : SubjectName not found.\n", fp);
9897 goto end;
9898 }
9899 key = XXH64(ASN1_STRING_get0_data(skid), ASN1_STRING_length(skid), 0);
William Lallemande0f3fd52020-02-25 14:53:06 +01009900 for (node = eb64_lookup(&cert_issuer_tree, key); node; node = eb64_next(node)) {
Emmanuel Hocdet70df7bf2019-01-04 11:08:20 +01009901 issuer = container_of(node, typeof(*issuer), node);
9902 if (!X509_NAME_cmp(name, X509_get_subject_name(sk_X509_value(issuer->chain, 0)))) {
9903 memprintf(err, "duplicate issuers-chain %s: %s already in store\n", fp, issuer->path);
9904 goto end;
9905 }
9906 }
9907 issuer = calloc(1, sizeof *issuer);
9908 path = strdup(fp);
9909 if (!issuer || !path) {
9910 free(issuer);
9911 free(path);
9912 goto end;
9913 }
9914 issuer->node.key = key;
9915 issuer->path = path;
9916 issuer->chain = chain;
9917 chain = NULL;
William Lallemande0f3fd52020-02-25 14:53:06 +01009918 eb64_insert(&cert_issuer_tree, &issuer->node);
Emmanuel Hocdet70df7bf2019-01-04 11:08:20 +01009919 ret = 1;
9920 end:
9921 if (skid)
9922 ASN1_OCTET_STRING_free(skid);
9923 if (chain)
9924 sk_X509_pop_free(chain, X509_free);
9925 return ret;
9926}
9927
Emmanuel Hocdet75a7aa12020-02-18 15:19:24 +01009928static struct issuer_chain* ssl_get_issuer_chain(X509 *cert)
9929{
9930 AUTHORITY_KEYID *akid;
9931 struct issuer_chain *issuer = NULL;
9932
9933 akid = X509_get_ext_d2i(cert, NID_authority_key_identifier, NULL, NULL);
9934 if (akid) {
9935 struct eb64_node *node;
9936 u64 hk;
9937 hk = XXH64(ASN1_STRING_get0_data(akid->keyid), ASN1_STRING_length(akid->keyid), 0);
9938 for (node = eb64_lookup(&cert_issuer_tree, hk); node; node = eb64_next(node)) {
9939 struct issuer_chain *ti = container_of(node, typeof(*issuer), node);
9940 if (X509_check_issued(sk_X509_value(ti->chain, 0), cert) == X509_V_OK) {
9941 issuer = ti;
9942 break;
9943 }
9944 }
9945 AUTHORITY_KEYID_free(akid);
9946 }
9947 return issuer;
9948}
9949
Emmanuel Hocdet70df7bf2019-01-04 11:08:20 +01009950static void ssl_free_global_issuers(void)
9951{
9952 struct eb64_node *node, *back;
9953 struct issuer_chain *issuer;
9954
William Lallemande0f3fd52020-02-25 14:53:06 +01009955 node = eb64_first(&cert_issuer_tree);
Emmanuel Hocdet70df7bf2019-01-04 11:08:20 +01009956 while (node) {
9957 issuer = container_of(node, typeof(*issuer), node);
9958 back = eb64_next(node);
9959 eb64_delete(node);
9960 free(issuer->path);
9961 sk_X509_pop_free(issuer->chain, X509_free);
9962 free(issuer);
9963 node = back;
9964 }
9965}
9966
9967static int ssl_load_global_issuers_from_path(char **args, int section_type, struct proxy *curpx,
9968 struct proxy *defpx, const char *file, int line,
9969 char **err)
9970{
9971 char *path;
9972 struct dirent **de_list;
9973 int i, n;
9974 struct stat buf;
9975 char *end;
9976 char fp[MAXPATHLEN+1];
9977
9978 if (too_many_args(1, args, err, NULL))
9979 return -1;
9980
9981 path = args[1];
9982 if (*path == 0 || stat(path, &buf)) {
9983 memprintf(err, "%sglobal statement '%s' expects a directory path as an argument.\n",
9984 err && *err ? *err : "", args[0]);
9985 return -1;
9986 }
9987 if (S_ISDIR(buf.st_mode) == 0) {
9988 memprintf(err, "%sglobal statement '%s': %s is not a directory.\n",
9989 err && *err ? *err : "", args[0], path);
9990 return -1;
9991 }
9992
9993 /* strip trailing slashes, including first one */
9994 for (end = path + strlen(path) - 1; end >= path && *end == '/'; end--)
9995 *end = 0;
9996 /* path already parsed? */
9997 if (global_ssl.issuers_chain_path && strcmp(global_ssl.issuers_chain_path, path) == 0)
9998 return 0;
9999 /* overwrite old issuers_chain_path */
10000 free(global_ssl.issuers_chain_path);
10001 global_ssl.issuers_chain_path = strdup(path);
10002 ssl_free_global_issuers();
10003
10004 n = scandir(path, &de_list, 0, alphasort);
10005 if (n < 0) {
10006 memprintf(err, "%sglobal statement '%s': unable to scan directory '%s' : %s.\n",
10007 err && *err ? *err : "", args[0], path, strerror(errno));
10008 return -1;
10009 }
10010 for (i = 0; i < n; i++) {
10011 struct dirent *de = de_list[i];
10012 BIO *in = NULL;
10013 char *warn = NULL;
10014
10015 snprintf(fp, sizeof(fp), "%s/%s", path, de->d_name);
10016 free(de);
10017 if (stat(fp, &buf) != 0) {
10018 ha_warning("unable to stat certificate from file '%s' : %s.\n", fp, strerror(errno));
10019 goto next;
10020 }
10021 if (!S_ISREG(buf.st_mode))
10022 goto next;
10023
10024 in = BIO_new(BIO_s_file());
10025 if (in == NULL)
10026 goto next;
10027 if (BIO_read_filename(in, fp) <= 0)
10028 goto next;
10029 ssl_load_global_issuer_from_BIO(in, fp, &warn);
10030 if (warn) {
Tim Duesterhuse8aa5f22020-02-19 11:41:13 +010010031 ha_warning("%s", warn);
Emmanuel Hocdet70df7bf2019-01-04 11:08:20 +010010032 free(warn);
10033 warn = NULL;
10034 }
10035 next:
10036 if (in)
10037 BIO_free(in);
10038 }
10039 free(de_list);
10040
10041 return 0;
10042}
10043
Grant Zhangfa6c7ee2017-01-14 01:42:15 +000010044/* parse the "ssl-mode-async" keyword in global section.
10045 * Returns <0 on alert, >0 on warning, 0 on success.
10046 */
10047static int ssl_parse_global_ssl_async(char **args, int section_type, struct proxy *curpx,
10048 struct proxy *defpx, const char *file, int line,
10049 char **err)
10050{
Willy Tarreau5db847a2019-05-09 14:13:35 +020010051#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +000010052 global_ssl.async = 1;
Emeric Brunece0c332017-12-06 13:51:49 +010010053 global.ssl_used_async_engines = nb_engines;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +000010054 return 0;
10055#else
10056 memprintf(err, "'%s': openssl library does not support async mode", args[0]);
10057 return -1;
10058#endif
10059}
10060
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020010061#ifndef OPENSSL_NO_ENGINE
Grant Zhangfa6c7ee2017-01-14 01:42:15 +000010062static int ssl_check_async_engine_count(void) {
10063 int err_code = 0;
10064
Emeric Brun3854e012017-05-17 20:42:48 +020010065 if (global_ssl.async && (openssl_engines_initialized > 32)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +010010066 ha_alert("ssl-mode-async only supports a maximum of 32 engines.\n");
Grant Zhangfa6c7ee2017-01-14 01:42:15 +000010067 err_code = ERR_ABORT;
10068 }
10069 return err_code;
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +010010070}
10071
Grant Zhang872f9c22017-01-21 01:10:18 +000010072/* parse the "ssl-engine" keyword in global section.
10073 * Returns <0 on alert, >0 on warning, 0 on success.
10074 */
10075static int ssl_parse_global_ssl_engine(char **args, int section_type, struct proxy *curpx,
10076 struct proxy *defpx, const char *file, int line,
10077 char **err)
10078{
10079 char *algo;
10080 int ret = -1;
10081
10082 if (*(args[1]) == 0) {
10083 memprintf(err, "global statement '%s' expects a valid engine name as an argument.", args[0]);
10084 return ret;
10085 }
10086
10087 if (*(args[2]) == 0) {
10088 /* if no list of algorithms is given, it defaults to ALL */
10089 algo = strdup("ALL");
10090 goto add_engine;
10091 }
10092
10093 /* otherwise the expected format is ssl-engine <engine_name> algo <list of algo> */
10094 if (strcmp(args[2], "algo") != 0) {
10095 memprintf(err, "global statement '%s' expects to have algo keyword.", args[0]);
10096 return ret;
10097 }
10098
10099 if (*(args[3]) == 0) {
10100 memprintf(err, "global statement '%s' expects algorithm names as an argument.", args[0]);
10101 return ret;
10102 }
10103 algo = strdup(args[3]);
10104
10105add_engine:
10106 if (ssl_init_single_engine(args[1], algo)==0) {
10107 openssl_engines_initialized++;
10108 ret = 0;
10109 }
10110 free(algo);
10111 return ret;
10112}
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020010113#endif
Grant Zhang872f9c22017-01-21 01:10:18 +000010114
Willy Tarreauf22e9682016-12-21 23:23:19 +010010115/* parse the "ssl-default-bind-ciphers" / "ssl-default-server-ciphers" keywords
10116 * in global section. Returns <0 on alert, >0 on warning, 0 on success.
10117 */
10118static int ssl_parse_global_ciphers(char **args, int section_type, struct proxy *curpx,
10119 struct proxy *defpx, const char *file, int line,
10120 char **err)
10121{
10122 char **target;
10123
Willy Tarreauef934602016-12-22 23:12:01 +010010124 target = (args[0][12] == 'b') ? &global_ssl.listen_default_ciphers : &global_ssl.connect_default_ciphers;
Willy Tarreauf22e9682016-12-21 23:23:19 +010010125
10126 if (too_many_args(1, args, err, NULL))
10127 return -1;
10128
10129 if (*(args[1]) == 0) {
10130 memprintf(err, "global statement '%s' expects a cipher suite as an argument.", args[0]);
10131 return -1;
10132 }
10133
10134 free(*target);
10135 *target = strdup(args[1]);
10136 return 0;
10137}
Dirkjan Bussink415150f2018-09-14 11:14:21 +020010138
Emmanuel Hocdet839af572019-05-14 16:27:35 +020010139#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +020010140/* parse the "ssl-default-bind-ciphersuites" / "ssl-default-server-ciphersuites" keywords
10141 * in global section. Returns <0 on alert, >0 on warning, 0 on success.
10142 */
10143static int ssl_parse_global_ciphersuites(char **args, int section_type, struct proxy *curpx,
10144 struct proxy *defpx, const char *file, int line,
10145 char **err)
10146{
10147 char **target;
10148
10149 target = (args[0][12] == 'b') ? &global_ssl.listen_default_ciphersuites : &global_ssl.connect_default_ciphersuites;
10150
10151 if (too_many_args(1, args, err, NULL))
10152 return -1;
10153
10154 if (*(args[1]) == 0) {
10155 memprintf(err, "global statement '%s' expects a cipher suite as an argument.", args[0]);
10156 return -1;
10157 }
10158
10159 free(*target);
10160 *target = strdup(args[1]);
10161 return 0;
10162}
10163#endif
Willy Tarreauf22e9682016-12-21 23:23:19 +010010164
Willy Tarreau9ceda382016-12-21 23:13:03 +010010165/* parse various global tune.ssl settings consisting in positive integers.
10166 * Returns <0 on alert, >0 on warning, 0 on success.
10167 */
10168static int ssl_parse_global_int(char **args, int section_type, struct proxy *curpx,
10169 struct proxy *defpx, const char *file, int line,
10170 char **err)
10171{
10172 int *target;
10173
10174 if (strcmp(args[0], "tune.ssl.cachesize") == 0)
10175 target = &global.tune.sslcachesize;
10176 else if (strcmp(args[0], "tune.ssl.maxrecord") == 0)
Willy Tarreauef934602016-12-22 23:12:01 +010010177 target = (int *)&global_ssl.max_record;
Willy Tarreau9ceda382016-12-21 23:13:03 +010010178 else if (strcmp(args[0], "tune.ssl.ssl-ctx-cache-size") == 0)
Willy Tarreauef934602016-12-22 23:12:01 +010010179 target = &global_ssl.ctx_cache;
Willy Tarreau0bea58d2016-12-21 23:17:25 +010010180 else if (strcmp(args[0], "maxsslconn") == 0)
10181 target = &global.maxsslconn;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +010010182 else if (strcmp(args[0], "tune.ssl.capture-cipherlist-size") == 0)
10183 target = &global_ssl.capture_cipherlist;
Willy Tarreau9ceda382016-12-21 23:13:03 +010010184 else {
10185 memprintf(err, "'%s' keyword not unhandled (please report this bug).", args[0]);
10186 return -1;
10187 }
10188
10189 if (too_many_args(1, args, err, NULL))
10190 return -1;
10191
10192 if (*(args[1]) == 0) {
10193 memprintf(err, "'%s' expects an integer argument.", args[0]);
10194 return -1;
10195 }
10196
10197 *target = atoi(args[1]);
10198 if (*target < 0) {
10199 memprintf(err, "'%s' expects a positive numeric value.", args[0]);
10200 return -1;
10201 }
10202 return 0;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +010010203}
10204
10205static int ssl_parse_global_capture_cipherlist(char **args, int section_type, struct proxy *curpx,
10206 struct proxy *defpx, const char *file, int line,
10207 char **err)
10208{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +010010209 int ret;
10210
10211 ret = ssl_parse_global_int(args, section_type, curpx, defpx, file, line, err);
10212 if (ret != 0)
10213 return ret;
10214
Willy Tarreaubafbe012017-11-24 17:34:44 +010010215 if (pool_head_ssl_capture) {
Thierry FOURNIER5bf77322017-02-25 12:45:22 +010010216 memprintf(err, "'%s' is already configured.", args[0]);
10217 return -1;
10218 }
10219
Willy Tarreaubafbe012017-11-24 17:34:44 +010010220 pool_head_ssl_capture = create_pool("ssl-capture", sizeof(struct ssl_capture) + global_ssl.capture_cipherlist, MEM_F_SHARED);
10221 if (!pool_head_ssl_capture) {
Thierry FOURNIER5bf77322017-02-25 12:45:22 +010010222 memprintf(err, "Out of memory error.");
10223 return -1;
10224 }
10225 return 0;
Willy Tarreau9ceda382016-12-21 23:13:03 +010010226}
10227
10228/* parse "ssl.force-private-cache".
10229 * Returns <0 on alert, >0 on warning, 0 on success.
10230 */
10231static int ssl_parse_global_private_cache(char **args, int section_type, struct proxy *curpx,
10232 struct proxy *defpx, const char *file, int line,
10233 char **err)
10234{
10235 if (too_many_args(0, args, err, NULL))
10236 return -1;
10237
Willy Tarreauef934602016-12-22 23:12:01 +010010238 global_ssl.private_cache = 1;
Willy Tarreau9ceda382016-12-21 23:13:03 +010010239 return 0;
10240}
10241
10242/* parse "ssl.lifetime".
10243 * Returns <0 on alert, >0 on warning, 0 on success.
10244 */
10245static int ssl_parse_global_lifetime(char **args, int section_type, struct proxy *curpx,
10246 struct proxy *defpx, const char *file, int line,
10247 char **err)
10248{
10249 const char *res;
10250
10251 if (too_many_args(1, args, err, NULL))
10252 return -1;
10253
10254 if (*(args[1]) == 0) {
10255 memprintf(err, "'%s' expects ssl sessions <lifetime> in seconds as argument.", args[0]);
10256 return -1;
10257 }
10258
Willy Tarreauef934602016-12-22 23:12:01 +010010259 res = parse_time_err(args[1], &global_ssl.life_time, TIME_UNIT_S);
Willy Tarreau9faebe32019-06-07 19:00:37 +020010260 if (res == PARSE_TIME_OVER) {
10261 memprintf(err, "timer overflow in argument '%s' to <%s> (maximum value is 2147483647 s or ~68 years).",
10262 args[1], args[0]);
10263 return -1;
10264 }
10265 else if (res == PARSE_TIME_UNDER) {
10266 memprintf(err, "timer underflow in argument '%s' to <%s> (minimum non-null value is 1 s).",
10267 args[1], args[0]);
10268 return -1;
10269 }
10270 else if (res) {
Willy Tarreau9ceda382016-12-21 23:13:03 +010010271 memprintf(err, "unexpected character '%c' in argument to <%s>.", *res, args[0]);
10272 return -1;
10273 }
10274 return 0;
10275}
10276
10277#ifndef OPENSSL_NO_DH
Willy Tarreau14e36a12016-12-21 23:28:13 +010010278/* parse "ssl-dh-param-file".
10279 * Returns <0 on alert, >0 on warning, 0 on success.
10280 */
10281static int ssl_parse_global_dh_param_file(char **args, int section_type, struct proxy *curpx,
10282 struct proxy *defpx, const char *file, int line,
10283 char **err)
10284{
10285 if (too_many_args(1, args, err, NULL))
10286 return -1;
10287
10288 if (*(args[1]) == 0) {
10289 memprintf(err, "'%s' expects a file path as an argument.", args[0]);
10290 return -1;
10291 }
10292
10293 if (ssl_sock_load_global_dh_param_from_file(args[1])) {
10294 memprintf(err, "'%s': unable to load DH parameters from file <%s>.", args[0], args[1]);
10295 return -1;
10296 }
10297 return 0;
10298}
10299
Willy Tarreau9ceda382016-12-21 23:13:03 +010010300/* parse "ssl.default-dh-param".
10301 * Returns <0 on alert, >0 on warning, 0 on success.
10302 */
10303static int ssl_parse_global_default_dh(char **args, int section_type, struct proxy *curpx,
10304 struct proxy *defpx, const char *file, int line,
10305 char **err)
10306{
10307 if (too_many_args(1, args, err, NULL))
10308 return -1;
10309
10310 if (*(args[1]) == 0) {
10311 memprintf(err, "'%s' expects an integer argument.", args[0]);
10312 return -1;
10313 }
10314
Willy Tarreauef934602016-12-22 23:12:01 +010010315 global_ssl.default_dh_param = atoi(args[1]);
10316 if (global_ssl.default_dh_param < 1024) {
Willy Tarreau9ceda382016-12-21 23:13:03 +010010317 memprintf(err, "'%s' expects a value >= 1024.", args[0]);
10318 return -1;
10319 }
10320 return 0;
10321}
10322#endif
10323
William Lallemand3af48e72020-02-03 17:15:52 +010010324
10325/*
10326 * parse "ssl-load-extra-files".
10327 * multiple arguments are allowed: "bundle", "sctl", "ocsp", "issuer", "all", "none"
10328 */
10329static int ssl_parse_global_extra_files(char **args, int section_type, struct proxy *curpx,
10330 struct proxy *defpx, const char *file, int line,
10331 char **err)
10332{
10333 int i;
10334 int gf = SSL_GF_NONE;
10335
10336 if (*(args[1]) == 0)
10337 goto err_arg;
10338
10339 for (i = 1; *args[i]; i++) {
10340
10341 if (!strcmp("bundle", args[i])) {
10342 gf |= SSL_GF_BUNDLE;
10343
10344 } else if (!strcmp("sctl", args[i])) {
10345 gf |= SSL_GF_SCTL;
10346
10347 } else if (!strcmp("ocsp", args[i])){
10348 gf |= SSL_GF_OCSP;
10349
10350 } else if (!strcmp("issuer", args[i])){
10351 gf |= SSL_GF_OCSP_ISSUER;
10352
William Lallemand4c5adbf2020-02-24 14:23:22 +010010353 } else if (!strcmp("key", args[i])) {
10354 gf |= SSL_GF_KEY;
10355
William Lallemand3af48e72020-02-03 17:15:52 +010010356 } else if (!strcmp("none", args[i])) {
10357 if (gf != SSL_GF_NONE)
10358 goto err_alone;
10359 gf = SSL_GF_NONE;
10360 i++;
10361 break;
10362
10363 } else if (!strcmp("all", args[i])) {
10364 if (gf != SSL_GF_NONE)
10365 goto err_alone;
10366 gf = SSL_GF_ALL;
10367 i++;
10368 break;
10369 } else {
10370 goto err_arg;
10371 }
10372 }
10373 /* break from loop but there are still arguments */
10374 if (*args[i])
10375 goto err_alone;
10376
10377 global_ssl.extra_files = gf;
10378
10379 return 0;
10380
10381err_alone:
10382 memprintf(err, "'%s' 'none' and 'all' can be only used alone", args[0]);
10383 return -1;
10384
10385err_arg:
10386 memprintf(err, "'%s' expects one or multiple arguments (none, all, bundle, sctl, ocsp, issuer).", args[0]);
10387 return -1;
10388}
10389
Willy Tarreau9ceda382016-12-21 23:13:03 +010010390
William Lallemand32af2032016-10-29 18:09:35 +020010391/* This function is used with TLS ticket keys management. It permits to browse
10392 * each reference. The variable <getnext> must contain the current node,
10393 * <end> point to the root node.
10394 */
10395#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
10396static inline
10397struct tls_keys_ref *tlskeys_list_get_next(struct tls_keys_ref *getnext, struct list *end)
10398{
10399 struct tls_keys_ref *ref = getnext;
10400
10401 while (1) {
10402
10403 /* Get next list entry. */
10404 ref = LIST_NEXT(&ref->list, struct tls_keys_ref *, list);
10405
10406 /* If the entry is the last of the list, return NULL. */
10407 if (&ref->list == end)
10408 return NULL;
10409
10410 return ref;
10411 }
10412}
10413
10414static inline
10415struct tls_keys_ref *tlskeys_ref_lookup_ref(const char *reference)
10416{
10417 int id;
10418 char *error;
10419
10420 /* If the reference starts by a '#', this is numeric id. */
10421 if (reference[0] == '#') {
10422 /* Try to convert the numeric id. If the conversion fails, the lookup fails. */
10423 id = strtol(reference + 1, &error, 10);
10424 if (*error != '\0')
10425 return NULL;
10426
10427 /* Perform the unique id lookup. */
10428 return tlskeys_ref_lookupid(id);
10429 }
10430
10431 /* Perform the string lookup. */
10432 return tlskeys_ref_lookup(reference);
10433}
10434#endif
10435
10436
10437#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
10438
10439static int cli_io_handler_tlskeys_files(struct appctx *appctx);
10440
10441static inline int cli_io_handler_tlskeys_entries(struct appctx *appctx) {
10442 return cli_io_handler_tlskeys_files(appctx);
10443}
10444
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010445/* dumps all tls keys. Relies on cli.i0 (non-null = only list file names), cli.i1
10446 * (next index to be dumped), and cli.p0 (next key reference).
10447 */
William Lallemand32af2032016-10-29 18:09:35 +020010448static int cli_io_handler_tlskeys_files(struct appctx *appctx) {
10449
10450 struct stream_interface *si = appctx->owner;
10451
10452 switch (appctx->st2) {
10453 case STAT_ST_INIT:
10454 /* Display the column headers. If the message cannot be sent,
Joseph Herlant017b3da2018-11-15 09:07:59 -080010455 * quit the function with returning 0. The function is called
William Lallemand32af2032016-10-29 18:09:35 +020010456 * later and restart at the state "STAT_ST_INIT".
10457 */
10458 chunk_reset(&trash);
10459
10460 if (appctx->io_handler == cli_io_handler_tlskeys_entries)
10461 chunk_appendf(&trash, "# id secret\n");
10462 else
10463 chunk_appendf(&trash, "# id (file)\n");
10464
Willy Tarreau06d80a92017-10-19 14:32:15 +020010465 if (ci_putchk(si_ic(si), &trash) == -1) {
Willy Tarreaudb398432018-11-15 11:08:52 +010010466 si_rx_room_blk(si);
William Lallemand32af2032016-10-29 18:09:35 +020010467 return 0;
10468 }
10469
William Lallemand32af2032016-10-29 18:09:35 +020010470 /* Now, we start the browsing of the references lists.
10471 * Note that the following call to LIST_ELEM return bad pointer. The only
10472 * available field of this pointer is <list>. It is used with the function
10473 * tlskeys_list_get_next() for retruning the first available entry
10474 */
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010475 if (appctx->ctx.cli.p0 == NULL) {
10476 appctx->ctx.cli.p0 = LIST_ELEM(&tlskeys_reference, struct tls_keys_ref *, list);
10477 appctx->ctx.cli.p0 = tlskeys_list_get_next(appctx->ctx.cli.p0, &tlskeys_reference);
William Lallemand32af2032016-10-29 18:09:35 +020010478 }
10479
10480 appctx->st2 = STAT_ST_LIST;
10481 /* fall through */
10482
10483 case STAT_ST_LIST:
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010484 while (appctx->ctx.cli.p0) {
10485 struct tls_keys_ref *ref = appctx->ctx.cli.p0;
William Lallemand32af2032016-10-29 18:09:35 +020010486
10487 chunk_reset(&trash);
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010488 if (appctx->io_handler == cli_io_handler_tlskeys_entries && appctx->ctx.cli.i1 == 0)
William Lallemand32af2032016-10-29 18:09:35 +020010489 chunk_appendf(&trash, "# ");
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010490
10491 if (appctx->ctx.cli.i1 == 0)
10492 chunk_appendf(&trash, "%d (%s)\n", ref->unique_id, ref->filename);
10493
William Lallemand32af2032016-10-29 18:09:35 +020010494 if (appctx->io_handler == cli_io_handler_tlskeys_entries) {
Christopher Faulet16f45c82018-02-16 11:23:49 +010010495 int head;
10496
10497 HA_RWLOCK_RDLOCK(TLSKEYS_REF_LOCK, &ref->lock);
10498 head = ref->tls_ticket_enc_index;
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010499 while (appctx->ctx.cli.i1 < TLS_TICKETS_NO) {
Willy Tarreau83061a82018-07-13 11:56:34 +020010500 struct buffer *t2 = get_trash_chunk();
William Lallemand32af2032016-10-29 18:09:35 +020010501
10502 chunk_reset(t2);
10503 /* should never fail here because we dump only a key in the t2 buffer */
Emeric Brun9e754772019-01-10 17:51:55 +010010504 if (ref->key_size_bits == 128) {
10505 t2->data = a2base64((char *)(ref->tlskeys + (head + 2 + appctx->ctx.cli.i1) % TLS_TICKETS_NO),
10506 sizeof(struct tls_sess_key_128),
10507 t2->area, t2->size);
10508 chunk_appendf(&trash, "%d.%d %s\n", ref->unique_id, appctx->ctx.cli.i1,
10509 t2->area);
10510 }
10511 else if (ref->key_size_bits == 256) {
10512 t2->data = a2base64((char *)(ref->tlskeys + (head + 2 + appctx->ctx.cli.i1) % TLS_TICKETS_NO),
10513 sizeof(struct tls_sess_key_256),
10514 t2->area, t2->size);
10515 chunk_appendf(&trash, "%d.%d %s\n", ref->unique_id, appctx->ctx.cli.i1,
10516 t2->area);
10517 }
10518 else {
10519 /* This case should never happen */
10520 chunk_appendf(&trash, "%d.%d <unknown>\n", ref->unique_id, appctx->ctx.cli.i1);
10521 }
William Lallemand32af2032016-10-29 18:09:35 +020010522
Willy Tarreau06d80a92017-10-19 14:32:15 +020010523 if (ci_putchk(si_ic(si), &trash) == -1) {
William Lallemand32af2032016-10-29 18:09:35 +020010524 /* let's try again later from this stream. We add ourselves into
10525 * this stream's users so that it can remove us upon termination.
10526 */
Christopher Faulet16f45c82018-02-16 11:23:49 +010010527 HA_RWLOCK_RDUNLOCK(TLSKEYS_REF_LOCK, &ref->lock);
Willy Tarreaudb398432018-11-15 11:08:52 +010010528 si_rx_room_blk(si);
William Lallemand32af2032016-10-29 18:09:35 +020010529 return 0;
10530 }
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010531 appctx->ctx.cli.i1++;
William Lallemand32af2032016-10-29 18:09:35 +020010532 }
Christopher Faulet16f45c82018-02-16 11:23:49 +010010533 HA_RWLOCK_RDUNLOCK(TLSKEYS_REF_LOCK, &ref->lock);
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010534 appctx->ctx.cli.i1 = 0;
William Lallemand32af2032016-10-29 18:09:35 +020010535 }
Willy Tarreau06d80a92017-10-19 14:32:15 +020010536 if (ci_putchk(si_ic(si), &trash) == -1) {
William Lallemand32af2032016-10-29 18:09:35 +020010537 /* let's try again later from this stream. We add ourselves into
10538 * this stream's users so that it can remove us upon termination.
10539 */
Willy Tarreaudb398432018-11-15 11:08:52 +010010540 si_rx_room_blk(si);
William Lallemand32af2032016-10-29 18:09:35 +020010541 return 0;
10542 }
10543
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010544 if (appctx->ctx.cli.i0 == 0) /* don't display everything if not necessary */
William Lallemand32af2032016-10-29 18:09:35 +020010545 break;
10546
10547 /* get next list entry and check the end of the list */
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010548 appctx->ctx.cli.p0 = tlskeys_list_get_next(appctx->ctx.cli.p0, &tlskeys_reference);
William Lallemand32af2032016-10-29 18:09:35 +020010549 }
10550
10551 appctx->st2 = STAT_ST_FIN;
10552 /* fall through */
10553
10554 default:
10555 appctx->st2 = STAT_ST_FIN;
10556 return 1;
10557 }
10558 return 0;
10559}
10560
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010561/* sets cli.i0 to non-zero if only file lists should be dumped */
Aurélien Nephtaliabbf6072018-04-18 13:26:46 +020010562static int cli_parse_show_tlskeys(char **args, char *payload, struct appctx *appctx, void *private)
William Lallemand32af2032016-10-29 18:09:35 +020010563{
William Lallemand32af2032016-10-29 18:09:35 +020010564 /* no parameter, shows only file list */
10565 if (!*args[2]) {
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010566 appctx->ctx.cli.i0 = 1;
William Lallemand32af2032016-10-29 18:09:35 +020010567 appctx->io_handler = cli_io_handler_tlskeys_files;
Willy Tarreau3067bfa2016-12-05 14:50:15 +010010568 return 0;
William Lallemand32af2032016-10-29 18:09:35 +020010569 }
10570
10571 if (args[2][0] == '*') {
10572 /* list every TLS ticket keys */
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010573 appctx->ctx.cli.i0 = 1;
William Lallemand32af2032016-10-29 18:09:35 +020010574 } else {
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010575 appctx->ctx.cli.p0 = tlskeys_ref_lookup_ref(args[2]);
Willy Tarreau9d008692019-08-09 11:21:01 +020010576 if (!appctx->ctx.cli.p0)
10577 return cli_err(appctx, "'show tls-keys' unable to locate referenced filename\n");
William Lallemand32af2032016-10-29 18:09:35 +020010578 }
William Lallemand32af2032016-10-29 18:09:35 +020010579 appctx->io_handler = cli_io_handler_tlskeys_entries;
Willy Tarreau3067bfa2016-12-05 14:50:15 +010010580 return 0;
William Lallemand32af2032016-10-29 18:09:35 +020010581}
10582
Aurélien Nephtaliabbf6072018-04-18 13:26:46 +020010583static int cli_parse_set_tlskeys(char **args, char *payload, struct appctx *appctx, void *private)
William Lallemand32af2032016-10-29 18:09:35 +020010584{
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010585 struct tls_keys_ref *ref;
Willy Tarreau1c913e42018-08-22 05:26:57 +020010586 int ret;
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010587
William Lallemand32af2032016-10-29 18:09:35 +020010588 /* Expect two parameters: the filename and the new new TLS key in encoding */
Willy Tarreau9d008692019-08-09 11:21:01 +020010589 if (!*args[3] || !*args[4])
10590 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 +020010591
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010592 ref = tlskeys_ref_lookup_ref(args[3]);
Willy Tarreau9d008692019-08-09 11:21:01 +020010593 if (!ref)
10594 return cli_err(appctx, "'set ssl tls-key' unable to locate referenced filename\n");
William Lallemand32af2032016-10-29 18:09:35 +020010595
Willy Tarreau1c913e42018-08-22 05:26:57 +020010596 ret = base64dec(args[4], strlen(args[4]), trash.area, trash.size);
Willy Tarreau9d008692019-08-09 11:21:01 +020010597 if (ret < 0)
10598 return cli_err(appctx, "'set ssl tls-key' received invalid base64 encoded TLS key.\n");
Emeric Brun9e754772019-01-10 17:51:55 +010010599
Willy Tarreau1c913e42018-08-22 05:26:57 +020010600 trash.data = ret;
Willy Tarreau9d008692019-08-09 11:21:01 +020010601 if (ssl_sock_update_tlskey_ref(ref, &trash) < 0)
10602 return cli_err(appctx, "'set ssl tls-key' received a key of wrong size.\n");
William Lallemand32af2032016-10-29 18:09:35 +020010603
Willy Tarreau9d008692019-08-09 11:21:01 +020010604 return cli_msg(appctx, LOG_INFO, "TLS ticket key updated!\n");
William Lallemand32af2032016-10-29 18:09:35 +020010605}
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +010010606#endif
William Lallemand32af2032016-10-29 18:09:35 +020010607
William Lallemand44b35322019-10-17 16:28:40 +020010608
10609/* Type of SSL payloads that can be updated over the CLI */
10610
10611enum {
10612 CERT_TYPE_PEM = 0,
William Lallemand4c5adbf2020-02-24 14:23:22 +010010613 CERT_TYPE_KEY,
Emmanuel Hocdetf6ac4fa2019-10-30 17:41:27 +010010614#if ((defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP) || defined OPENSSL_IS_BORINGSSL)
William Lallemand44b35322019-10-17 16:28:40 +020010615 CERT_TYPE_OCSP,
Emmanuel Hocdetf6ac4fa2019-10-30 17:41:27 +010010616#endif
William Lallemand44b35322019-10-17 16:28:40 +020010617 CERT_TYPE_ISSUER,
Emmanuel Hocdetf6ac4fa2019-10-30 17:41:27 +010010618#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
William Lallemand44b35322019-10-17 16:28:40 +020010619 CERT_TYPE_SCTL,
Emmanuel Hocdetf6ac4fa2019-10-30 17:41:27 +010010620#endif
William Lallemand44b35322019-10-17 16:28:40 +020010621 CERT_TYPE_MAX,
10622};
10623
10624struct {
10625 const char *ext;
10626 int type;
10627 int (*load)(const char *path, char *payload, struct cert_key_and_chain *ckch, char **err);
10628 /* add a parsing callback */
William Lallemandf29cdef2019-10-23 15:00:52 +020010629} cert_exts[CERT_TYPE_MAX+1] = {
William Lallemand44b35322019-10-17 16:28:40 +020010630 [CERT_TYPE_PEM] = { "", CERT_TYPE_PEM, &ssl_sock_load_pem_into_ckch }, /* default mode, no extensions */
William Lallemand4c5adbf2020-02-24 14:23:22 +010010631 [CERT_TYPE_KEY] = { "key", CERT_TYPE_KEY, &ssl_sock_load_key_into_ckch },
William Lallemand541a5342019-10-23 14:11:54 +020010632#if ((defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP) || defined OPENSSL_IS_BORINGSSL)
William Lallemand44b35322019-10-17 16:28:40 +020010633 [CERT_TYPE_OCSP] = { "ocsp", CERT_TYPE_OCSP, &ssl_sock_load_ocsp_response_from_file },
William Lallemand541a5342019-10-23 14:11:54 +020010634#endif
10635#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
William Lallemand44b35322019-10-17 16:28:40 +020010636 [CERT_TYPE_SCTL] = { "sctl", CERT_TYPE_SCTL, &ssl_sock_load_sctl_from_file },
William Lallemand541a5342019-10-23 14:11:54 +020010637#endif
William Lallemand44b35322019-10-17 16:28:40 +020010638 [CERT_TYPE_ISSUER] = { "issuer", CERT_TYPE_ISSUER, &ssl_sock_load_issuer_file_into_ckch },
William Lallemandf29cdef2019-10-23 15:00:52 +020010639 [CERT_TYPE_MAX] = { NULL, CERT_TYPE_MAX, NULL },
William Lallemand44b35322019-10-17 16:28:40 +020010640};
10641
William Lallemand430413e2019-10-28 14:30:47 +010010642/* states of the CLI IO handler for 'set ssl cert' */
10643enum {
10644 SETCERT_ST_INIT = 0,
10645 SETCERT_ST_GEN,
10646 SETCERT_ST_INSERT,
10647 SETCERT_ST_FIN,
10648};
William Lallemand8f840d72019-10-23 10:53:05 +020010649
William Lallemandd4f946c2019-12-05 10:26:40 +010010650/* release function of the `show ssl cert' command */
10651static void cli_release_show_cert(struct appctx *appctx)
10652{
10653 HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
10654}
10655
10656/* IO handler of "show ssl cert <filename>" */
10657static int cli_io_handler_show_cert(struct appctx *appctx)
10658{
10659 struct buffer *trash = alloc_trash_chunk();
10660 struct ebmb_node *node;
10661 struct stream_interface *si = appctx->owner;
10662 struct ckch_store *ckchs;
William Lallemandd4f946c2019-12-05 10:26:40 +010010663
10664 if (trash == NULL)
10665 return 1;
10666
10667 if (!appctx->ctx.ssl.old_ckchs) {
10668 if (ckchs_transaction.old_ckchs) {
10669 ckchs = ckchs_transaction.old_ckchs;
10670 chunk_appendf(trash, "# transaction\n");
10671 if (!ckchs->multi) {
10672 chunk_appendf(trash, "*%s\n", ckchs->path);
William Lallemandba22e902019-12-18 20:36:01 +010010673#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
William Lallemandd4f946c2019-12-05 10:26:40 +010010674 } else {
William Lallemanda25a19f2020-01-29 00:04:24 +010010675 int n;
10676
William Lallemandd4f946c2019-12-05 10:26:40 +010010677 chunk_appendf(trash, "*%s:", ckchs->path);
10678 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
10679 if (ckchs->ckch[n].cert)
10680 chunk_appendf(trash, " %s.%s\n", ckchs->path, SSL_SOCK_KEYTYPE_NAMES[n]);
10681 }
10682 chunk_appendf(trash, "\n");
William Lallemandba22e902019-12-18 20:36:01 +010010683#endif
William Lallemandd4f946c2019-12-05 10:26:40 +010010684 }
10685 }
10686 }
10687
10688 if (!appctx->ctx.cli.p0) {
10689 chunk_appendf(trash, "# filename\n");
10690 node = ebmb_first(&ckchs_tree);
10691 } else {
10692 node = &((struct ckch_store *)appctx->ctx.cli.p0)->node;
10693 }
10694 while (node) {
10695 ckchs = ebmb_entry(node, struct ckch_store, node);
10696 if (!ckchs->multi) {
10697 chunk_appendf(trash, "%s\n", ckchs->path);
William Lallemandba22e902019-12-18 20:36:01 +010010698#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
William Lallemandd4f946c2019-12-05 10:26:40 +010010699 } else {
William Lallemanda25a19f2020-01-29 00:04:24 +010010700 int n;
10701
William Lallemandd4f946c2019-12-05 10:26:40 +010010702 chunk_appendf(trash, "%s:", ckchs->path);
10703 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
10704 if (ckchs->ckch[n].cert)
10705 chunk_appendf(trash, " %s.%s", ckchs->path, SSL_SOCK_KEYTYPE_NAMES[n]);
10706 }
10707 chunk_appendf(trash, "\n");
William Lallemandba22e902019-12-18 20:36:01 +010010708#endif
William Lallemandd4f946c2019-12-05 10:26:40 +010010709 }
10710
10711 node = ebmb_next(node);
10712 if (ci_putchk(si_ic(si), trash) == -1) {
10713 si_rx_room_blk(si);
10714 goto yield;
10715 }
10716 }
10717
10718 appctx->ctx.cli.p0 = NULL;
10719 free_trash_chunk(trash);
10720 return 1;
10721yield:
10722
10723 free_trash_chunk(trash);
10724 appctx->ctx.cli.p0 = ckchs;
10725 return 0; /* should come back */
10726}
10727
10728/* IO handler of the details "show ssl cert <filename>" */
10729static int cli_io_handler_show_cert_detail(struct appctx *appctx)
10730{
10731 struct stream_interface *si = appctx->owner;
10732 struct ckch_store *ckchs = appctx->ctx.cli.p0;
10733 struct buffer *out = alloc_trash_chunk();
10734 struct buffer *tmp = alloc_trash_chunk();
10735 X509_NAME *name = NULL;
Emmanuel Hocdetcf8cf6c2020-02-18 16:06:14 +010010736 STACK_OF(X509) *chain;
Willy Tarreau105599c2020-02-25 08:59:23 +010010737 unsigned int len = 0;
William Lallemandd4f946c2019-12-05 10:26:40 +010010738 int write = -1;
10739 BIO *bio = NULL;
William Lallemand35f4a9d2020-02-25 11:56:32 +010010740 int i;
William Lallemandd4f946c2019-12-05 10:26:40 +010010741
10742 if (!tmp || !out)
10743 goto end;
10744
10745 if (!ckchs->multi) {
10746 chunk_appendf(out, "Filename: ");
10747 if (ckchs == ckchs_transaction.new_ckchs)
10748 chunk_appendf(out, "*");
10749 chunk_appendf(out, "%s\n", ckchs->path);
Emmanuel Hocdetcf8cf6c2020-02-18 16:06:14 +010010750
10751 chain = ckchs->ckch->chain;
10752 if (chain == NULL) {
10753 struct issuer_chain *issuer;
10754 issuer = ssl_get_issuer_chain(ckchs->ckch->cert);
10755 if (issuer) {
10756 chain = issuer->chain;
10757 chunk_appendf(out, "Chain Filename: ");
10758 chunk_appendf(out, "%s\n", issuer->path);
10759 }
10760 }
William Lallemandd4f946c2019-12-05 10:26:40 +010010761 chunk_appendf(out, "Serial: ");
10762 if (ssl_sock_get_serial(ckchs->ckch->cert, tmp) == -1)
10763 goto end;
10764 dump_binary(out, tmp->area, tmp->data);
10765 chunk_appendf(out, "\n");
10766
10767 chunk_appendf(out, "notBefore: ");
10768 chunk_reset(tmp);
10769 if ((bio = BIO_new(BIO_s_mem())) == NULL)
10770 goto end;
10771 if (ASN1_TIME_print(bio, X509_getm_notBefore(ckchs->ckch->cert)) == 0)
10772 goto end;
10773 write = BIO_read(bio, tmp->area, tmp->size-1);
10774 tmp->area[write] = '\0';
10775 BIO_free(bio);
10776 chunk_appendf(out, "%s\n", tmp->area);
10777
10778 chunk_appendf(out, "notAfter: ");
10779 chunk_reset(tmp);
10780 if ((bio = BIO_new(BIO_s_mem())) == NULL)
10781 goto end;
10782 if (ASN1_TIME_print(bio, X509_getm_notAfter(ckchs->ckch->cert)) == 0)
10783 goto end;
10784 if ((write = BIO_read(bio, tmp->area, tmp->size-1)) <= 0)
10785 goto end;
10786 tmp->area[write] = '\0';
10787 BIO_free(bio);
10788 chunk_appendf(out, "%s\n", tmp->area);
10789
William Lallemandd4f946c2019-12-05 10:26:40 +010010790#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
10791 chunk_appendf(out, "Subject Alternative Name: ");
10792 if (ssl_sock_get_san_oneline(ckchs->ckch->cert, out) == -1)
10793 goto end;
10794 *(out->area + out->data) = '\0';
10795 chunk_appendf(out, "\n");
10796#endif
10797 chunk_reset(tmp);
10798 chunk_appendf(out, "Algorithm: ");
10799 if (cert_get_pkey_algo(ckchs->ckch->cert, tmp) == 0)
10800 goto end;
10801 chunk_appendf(out, "%s\n", tmp->area);
10802
10803 chunk_reset(tmp);
10804 chunk_appendf(out, "SHA1 FingerPrint: ");
Willy Tarreau105599c2020-02-25 08:59:23 +010010805 if (X509_digest(ckchs->ckch->cert, EVP_sha1(), (unsigned char *) tmp->area, &len) == 0)
William Lallemandd4f946c2019-12-05 10:26:40 +010010806 goto end;
Willy Tarreau105599c2020-02-25 08:59:23 +010010807 tmp->data = len;
William Lallemandd4f946c2019-12-05 10:26:40 +010010808 dump_binary(out, tmp->area, tmp->data);
10809 chunk_appendf(out, "\n");
William Lallemand35f4a9d2020-02-25 11:56:32 +010010810
William Lallemanda90e5932020-02-25 14:07:58 +010010811 chunk_appendf(out, "Subject: ");
10812 if ((name = X509_get_subject_name(ckchs->ckch->cert)) == NULL)
10813 goto end;
10814 if ((ssl_sock_get_dn_oneline(name, tmp)) == -1)
10815 goto end;
10816 *(tmp->area + tmp->data) = '\0';
10817 chunk_appendf(out, "%s\n", tmp->area);
10818
10819 chunk_appendf(out, "Issuer: ");
10820 if ((name = X509_get_issuer_name(ckchs->ckch->cert)) == NULL)
10821 goto end;
10822 if ((ssl_sock_get_dn_oneline(name, tmp)) == -1)
10823 goto end;
10824 *(tmp->area + tmp->data) = '\0';
10825 chunk_appendf(out, "%s\n", tmp->area);
10826
William Lallemand35f4a9d2020-02-25 11:56:32 +010010827 /* Displays subject of each certificate in the chain */
Emmanuel Hocdetcf8cf6c2020-02-18 16:06:14 +010010828 for (i = 0; i < sk_X509_num(chain); i++) {
10829 X509 *ca = sk_X509_value(chain, i);
William Lallemand35f4a9d2020-02-25 11:56:32 +010010830
William Lallemandbb7288a2020-02-25 14:04:33 +010010831 chunk_appendf(out, "Chain Subject: ");
William Lallemand35f4a9d2020-02-25 11:56:32 +010010832 if ((name = X509_get_subject_name(ca)) == NULL)
10833 goto end;
10834 if ((ssl_sock_get_dn_oneline(name, tmp)) == -1)
10835 goto end;
10836 *(tmp->area + tmp->data) = '\0';
10837 chunk_appendf(out, "%s\n", tmp->area);
10838
William Lallemandbb7288a2020-02-25 14:04:33 +010010839 chunk_appendf(out, "Chain Issuer: ");
10840 if ((name = X509_get_issuer_name(ca)) == NULL)
10841 goto end;
10842 if ((ssl_sock_get_dn_oneline(name, tmp)) == -1)
10843 goto end;
10844 *(tmp->area + tmp->data) = '\0';
10845 chunk_appendf(out, "%s\n", tmp->area);
William Lallemand35f4a9d2020-02-25 11:56:32 +010010846 }
William Lallemandd4f946c2019-12-05 10:26:40 +010010847 }
10848
10849 if (ci_putchk(si_ic(si), out) == -1) {
10850 si_rx_room_blk(si);
10851 goto yield;
10852 }
10853
10854end:
10855 free_trash_chunk(tmp);
10856 free_trash_chunk(out);
10857 return 1;
10858yield:
10859 free_trash_chunk(tmp);
10860 free_trash_chunk(out);
10861 return 0; /* should come back */
10862}
10863
10864/* parsing function for 'show ssl cert [certfile]' */
10865static int cli_parse_show_cert(char **args, char *payload, struct appctx *appctx, void *private)
10866{
10867 struct ckch_store *ckchs;
10868
10869 if (!cli_has_level(appctx, ACCESS_LVL_OPER))
10870 return cli_err(appctx, "Can't allocate memory!\n");
10871
10872 /* The operations on the CKCH architecture are locked so we can
10873 * manipulate ckch_store and ckch_inst */
10874 if (HA_SPIN_TRYLOCK(CKCH_LOCK, &ckch_lock))
10875 return cli_err(appctx, "Can't show!\nOperations on certificates are currently locked!\n");
10876
10877 /* check if there is a certificate to lookup */
10878 if (*args[3]) {
10879 if (*args[3] == '*') {
10880 if (!ckchs_transaction.new_ckchs)
10881 goto error;
10882
10883 ckchs = ckchs_transaction.new_ckchs;
10884
10885 if (strcmp(args[3] + 1, ckchs->path))
10886 goto error;
10887
10888 } else {
10889 if ((ckchs = ckchs_lookup(args[3])) == NULL)
10890 goto error;
10891
10892 }
10893
10894 if (ckchs->multi)
10895 goto error;
10896
10897 appctx->ctx.cli.p0 = ckchs;
10898 /* use the IO handler that shows details */
10899 appctx->io_handler = cli_io_handler_show_cert_detail;
10900 }
10901
10902 return 0;
10903
10904error:
10905 HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
10906 return cli_err(appctx, "Can't display the certificate: Not found or the certificate is a bundle!\n");
10907}
10908
William Lallemand430413e2019-10-28 14:30:47 +010010909/* release function of the `set ssl cert' command, free things and unlock the spinlock */
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010910static void cli_release_commit_cert(struct appctx *appctx)
William Lallemand8f840d72019-10-23 10:53:05 +020010911{
10912 struct ckch_store *new_ckchs;
10913 struct ckch_inst *ckchi, *ckchis;
William Lallemand8f840d72019-10-23 10:53:05 +020010914
William Lallemand430413e2019-10-28 14:30:47 +010010915 HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
William Lallemand8f840d72019-10-23 10:53:05 +020010916
William Lallemand430413e2019-10-28 14:30:47 +010010917 if (appctx->st2 != SETCERT_ST_FIN) {
William Lallemand8f840d72019-10-23 10:53:05 +020010918 /* 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 +010010919 new_ckchs = appctx->ctx.ssl.new_ckchs;
William Lallemand8f840d72019-10-23 10:53:05 +020010920
William Lallemandbeea2a42019-10-30 17:45:33 +010010921 if (!new_ckchs)
10922 return;
William Lallemand8f840d72019-10-23 10:53:05 +020010923
William Lallemandbeea2a42019-10-30 17:45:33 +010010924 /* if the allocation failed, we need to free everything from the temporary list */
10925 list_for_each_entry_safe(ckchi, ckchis, &new_ckchs->ckch_inst, by_ckchs) {
10926 struct sni_ctx *sc0, *sc0s;
William Lallemand8f840d72019-10-23 10:53:05 +020010927
William Lallemandbeea2a42019-10-30 17:45:33 +010010928 list_for_each_entry_safe(sc0, sc0s, &ckchi->sni_ctx, by_ckch_inst) {
10929 if (sc0->order == 0) /* we only free if it's the first inserted */
10930 SSL_CTX_free(sc0->ctx);
10931 LIST_DEL(&sc0->by_ckch_inst);
10932 free(sc0);
William Lallemand8f840d72019-10-23 10:53:05 +020010933 }
William Lallemandbeea2a42019-10-30 17:45:33 +010010934 LIST_DEL(&ckchi->by_ckchs);
10935 free(ckchi);
William Lallemand8f840d72019-10-23 10:53:05 +020010936 }
William Lallemandbeea2a42019-10-30 17:45:33 +010010937 ckchs_free(new_ckchs);
William Lallemand8f840d72019-10-23 10:53:05 +020010938 }
10939}
10940
10941
10942/*
10943 * This function tries to create the new ckch_inst and their SNIs
10944 */
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010945static int cli_io_handler_commit_cert(struct appctx *appctx)
William Lallemand8f840d72019-10-23 10:53:05 +020010946{
10947 struct stream_interface *si = appctx->owner;
10948 int y = 0;
10949 char *err = NULL;
10950 int errcode = 0;
10951 struct ckch_store *old_ckchs, *new_ckchs = NULL;
10952 struct ckch_inst *ckchi, *ckchis;
William Lallemand8f840d72019-10-23 10:53:05 +020010953 struct buffer *trash = alloc_trash_chunk();
William Lallemand8ef0c2a2019-11-21 16:30:34 +010010954 struct sni_ctx *sc0, *sc0s;
William Lallemand8f840d72019-10-23 10:53:05 +020010955
William Lallemand33cc76f2019-10-31 11:43:45 +010010956 if (trash == NULL)
10957 goto error;
10958
William Lallemand8f840d72019-10-23 10:53:05 +020010959 if (unlikely(si_ic(si)->flags & (CF_WRITE_ERROR|CF_SHUTW)))
10960 goto error;
10961
William Lallemand430413e2019-10-28 14:30:47 +010010962 while (1) {
10963 switch (appctx->st2) {
10964 case SETCERT_ST_INIT:
10965 /* This state just print the update message */
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010966 chunk_printf(trash, "Committing %s", ckchs_transaction.path);
William Lallemand430413e2019-10-28 14:30:47 +010010967 if (ci_putchk(si_ic(si), trash) == -1) {
10968 si_rx_room_blk(si);
William Lallemand8f840d72019-10-23 10:53:05 +020010969 goto yield;
William Lallemand430413e2019-10-28 14:30:47 +010010970 }
10971 appctx->st2 = SETCERT_ST_GEN;
10972 /* fallthrough */
10973 case SETCERT_ST_GEN:
10974 /*
10975 * This state generates the ckch instances with their
10976 * sni_ctxs and SSL_CTX.
10977 *
William Lallemand430413e2019-10-28 14:30:47 +010010978 * Since the SSL_CTX generation can be CPU consumer, we
10979 * yield every 10 instances.
10980 */
William Lallemand8f840d72019-10-23 10:53:05 +020010981
William Lallemandbeea2a42019-10-30 17:45:33 +010010982 old_ckchs = appctx->ctx.ssl.old_ckchs;
10983 new_ckchs = appctx->ctx.ssl.new_ckchs;
William Lallemand8f840d72019-10-23 10:53:05 +020010984
William Lallemandbeea2a42019-10-30 17:45:33 +010010985 if (!new_ckchs)
10986 continue;
William Lallemand8f840d72019-10-23 10:53:05 +020010987
William Lallemandbeea2a42019-10-30 17:45:33 +010010988 /* get the next ckchi to regenerate */
10989 ckchi = appctx->ctx.ssl.next_ckchi;
10990 /* we didn't start yet, set it to the first elem */
10991 if (ckchi == NULL)
10992 ckchi = LIST_ELEM(old_ckchs->ckch_inst.n, typeof(ckchi), by_ckchs);
William Lallemand8f840d72019-10-23 10:53:05 +020010993
William Lallemandbeea2a42019-10-30 17:45:33 +010010994 /* walk through the old ckch_inst and creates new ckch_inst using the updated ckchs */
10995 list_for_each_entry_from(ckchi, &old_ckchs->ckch_inst, by_ckchs) {
10996 struct ckch_inst *new_inst;
William Lallemand38df1c82019-12-04 15:39:35 +010010997 char **sni_filter = NULL;
10998 int fcount = 0;
William Lallemand8f840d72019-10-23 10:53:05 +020010999
William Lallemandbeea2a42019-10-30 17:45:33 +010011000 /* it takes a lot of CPU to creates SSL_CTXs, so we yield every 10 CKCH instances */
11001 if (y >= 10) {
11002 /* save the next ckchi to compute */
11003 appctx->ctx.ssl.next_ckchi = ckchi;
11004 goto yield;
11005 }
William Lallemand8f840d72019-10-23 10:53:05 +020011006
William Lallemand38df1c82019-12-04 15:39:35 +010011007 errcode |= ckch_inst_sni_ctx_to_sni_filters(ckchi, &sni_filter, &fcount, &err);
11008 if (errcode & ERR_CODE)
11009 goto error;
11010
William Lallemandbeea2a42019-10-30 17:45:33 +010011011 if (new_ckchs->multi)
William Lallemand38df1c82019-12-04 15:39:35 +010011012 errcode |= ckch_inst_new_load_multi_store(new_ckchs->path, new_ckchs, ckchi->bind_conf, ckchi->ssl_conf, sni_filter, fcount, &new_inst, &err);
William Lallemandbeea2a42019-10-30 17:45:33 +010011013 else
William Lallemand38df1c82019-12-04 15:39:35 +010011014 errcode |= ckch_inst_new_load_store(new_ckchs->path, new_ckchs, ckchi->bind_conf, ckchi->ssl_conf, sni_filter, fcount, &new_inst, &err);
11015
11016 free_sni_filters(sni_filter, fcount);
11017 sni_filter = NULL;
William Lallemand8f840d72019-10-23 10:53:05 +020011018
William Lallemandbeea2a42019-10-30 17:45:33 +010011019 if (errcode & ERR_CODE)
11020 goto error;
William Lallemand8f840d72019-10-23 10:53:05 +020011021
William Lallemand21724f02019-11-04 17:56:13 +010011022 /* if the previous ckchi was used as the default */
11023 if (ckchi->is_default)
11024 new_inst->is_default = 1;
11025
William Lallemand8ef0c2a2019-11-21 16:30:34 +010011026 /* we need to initialize the SSL_CTX generated */
William Lallemand696f3172020-02-07 20:45:24 +010011027 /* this iterate on the newly generated SNIs in the new instance to prepare their SSL_CTX */
11028 list_for_each_entry_safe(sc0, sc0s, &new_inst->sni_ctx, by_ckch_inst) {
William Lallemand8ef0c2a2019-11-21 16:30:34 +010011029 if (!sc0->order) { /* we initiliazed only the first SSL_CTX because it's the same in the other sni_ctx's */
11030 errcode |= ssl_sock_prepare_ctx(ckchi->bind_conf, ckchi->ssl_conf, sc0->ctx, &err);
11031 if (errcode & ERR_CODE)
11032 goto error;
11033 }
11034 }
11035
11036
William Lallemandbeea2a42019-10-30 17:45:33 +010011037 /* display one dot per new instance */
11038 chunk_appendf(trash, ".");
11039 /* link the new ckch_inst to the duplicate */
11040 LIST_ADDQ(&new_ckchs->ckch_inst, &new_inst->by_ckchs);
11041 y++;
11042 }
William Lallemand430413e2019-10-28 14:30:47 +010011043 appctx->st2 = SETCERT_ST_INSERT;
11044 /* fallthrough */
11045 case SETCERT_ST_INSERT:
11046 /* The generation is finished, we can insert everything */
William Lallemand8f840d72019-10-23 10:53:05 +020011047
William Lallemandbeea2a42019-10-30 17:45:33 +010011048 old_ckchs = appctx->ctx.ssl.old_ckchs;
11049 new_ckchs = appctx->ctx.ssl.new_ckchs;
William Lallemand8f840d72019-10-23 10:53:05 +020011050
William Lallemandbeea2a42019-10-30 17:45:33 +010011051 if (!new_ckchs)
11052 continue;
William Lallemand430413e2019-10-28 14:30:47 +010011053
William Lallemand21724f02019-11-04 17:56:13 +010011054 /* First, we insert every new SNIs in the trees, also replace the default_ctx */
William Lallemandbeea2a42019-10-30 17:45:33 +010011055 list_for_each_entry_safe(ckchi, ckchis, &new_ckchs->ckch_inst, by_ckchs) {
11056 HA_RWLOCK_WRLOCK(SNI_LOCK, &ckchi->bind_conf->sni_lock);
11057 ssl_sock_load_cert_sni(ckchi, ckchi->bind_conf);
11058 HA_RWLOCK_WRUNLOCK(SNI_LOCK, &ckchi->bind_conf->sni_lock);
11059 }
William Lallemand8f840d72019-10-23 10:53:05 +020011060
William Lallemandbeea2a42019-10-30 17:45:33 +010011061 /* delete the old sni_ctx, the old ckch_insts and the ckch_store */
11062 list_for_each_entry_safe(ckchi, ckchis, &old_ckchs->ckch_inst, by_ckchs) {
William Lallemand430413e2019-10-28 14:30:47 +010011063
William Lallemandbeea2a42019-10-30 17:45:33 +010011064 HA_RWLOCK_WRLOCK(SNI_LOCK, &ckchi->bind_conf->sni_lock);
11065 list_for_each_entry_safe(sc0, sc0s, &ckchi->sni_ctx, by_ckch_inst) {
11066 ebmb_delete(&sc0->name);
11067 LIST_DEL(&sc0->by_ckch_inst);
11068 free(sc0);
William Lallemand430413e2019-10-28 14:30:47 +010011069 }
William Lallemandbeea2a42019-10-30 17:45:33 +010011070 HA_RWLOCK_WRUNLOCK(SNI_LOCK, &ckchi->bind_conf->sni_lock);
11071 LIST_DEL(&ckchi->by_ckchs);
11072 free(ckchi);
11073 }
William Lallemand8f840d72019-10-23 10:53:05 +020011074
William Lallemandbeea2a42019-10-30 17:45:33 +010011075 /* Replace the old ckchs by the new one */
11076 ebmb_delete(&old_ckchs->node);
11077 ckchs_free(old_ckchs);
11078 ebst_insert(&ckchs_tree, &new_ckchs->node);
William Lallemand430413e2019-10-28 14:30:47 +010011079 appctx->st2 = SETCERT_ST_FIN;
11080 /* fallthrough */
11081 case SETCERT_ST_FIN:
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011082 /* we achieved the transaction, we can set everything to NULL */
11083 free(ckchs_transaction.path);
11084 ckchs_transaction.path = NULL;
11085 ckchs_transaction.new_ckchs = NULL;
11086 ckchs_transaction.old_ckchs = NULL;
William Lallemand430413e2019-10-28 14:30:47 +010011087 goto end;
11088 }
William Lallemand8f840d72019-10-23 10:53:05 +020011089 }
William Lallemand430413e2019-10-28 14:30:47 +010011090end:
William Lallemand8f840d72019-10-23 10:53:05 +020011091
William Lallemanded442432019-11-21 16:41:07 +010011092 chunk_appendf(trash, "\n");
11093 if (errcode & ERR_WARN)
Tim Duesterhusc0e820c2019-11-23 23:52:30 +010011094 chunk_appendf(trash, "%s", err);
William Lallemanded442432019-11-21 16:41:07 +010011095 chunk_appendf(trash, "Success!\n");
William Lallemand430413e2019-10-28 14:30:47 +010011096 if (ci_putchk(si_ic(si), trash) == -1)
11097 si_rx_room_blk(si);
11098 free_trash_chunk(trash);
11099 /* success: call the release function and don't come back */
11100 return 1;
William Lallemand8f840d72019-10-23 10:53:05 +020011101yield:
11102 /* store the state */
11103 if (ci_putchk(si_ic(si), trash) == -1)
11104 si_rx_room_blk(si);
11105 free_trash_chunk(trash);
11106 si_rx_endp_more(si); /* let's come back later */
William Lallemand8f840d72019-10-23 10:53:05 +020011107 return 0; /* should come back */
11108
11109error:
11110 /* spin unlock and free are done in the release function */
William Lallemand33cc76f2019-10-31 11:43:45 +010011111 if (trash) {
11112 chunk_appendf(trash, "\n%sFailed!\n", err);
11113 if (ci_putchk(si_ic(si), trash) == -1)
11114 si_rx_room_blk(si);
11115 free_trash_chunk(trash);
11116 }
William Lallemand430413e2019-10-28 14:30:47 +010011117 /* error: call the release function and don't come back */
11118 return 1;
William Lallemand8f840d72019-10-23 10:53:05 +020011119}
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011120
11121/*
11122 * Parsing function of 'commit ssl cert'
11123 */
11124static int cli_parse_commit_cert(char **args, char *payload, struct appctx *appctx, void *private)
11125{
11126 char *err = NULL;
11127
William Lallemand230662a2019-12-03 13:32:54 +010011128 if (!cli_has_level(appctx, ACCESS_LVL_ADMIN))
11129 return 1;
11130
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011131 if (!*args[3])
11132 return cli_err(appctx, "'commit ssl cert expects a filename\n");
11133
11134 /* The operations on the CKCH architecture are locked so we can
11135 * manipulate ckch_store and ckch_inst */
11136 if (HA_SPIN_TRYLOCK(CKCH_LOCK, &ckch_lock))
11137 return cli_err(appctx, "Can't commit the certificate!\nOperations on certificates are currently locked!\n");
11138
11139 if (!ckchs_transaction.path) {
11140 memprintf(&err, "No ongoing transaction! !\n");
11141 goto error;
11142 }
11143
11144 if (strcmp(ckchs_transaction.path, args[3]) != 0) {
11145 memprintf(&err, "The ongoing transaction is about '%s' but you are trying to set '%s'\n", ckchs_transaction.path, args[3]);
11146 goto error;
11147 }
11148
William Lallemand4c5adbf2020-02-24 14:23:22 +010011149#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
11150 if (ckchs_transaction.new_ckchs->multi) {
11151 int n;
11152
11153 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
11154 if (ckchs_transaction.new_ckchs->ckch[n].cert && !X509_check_private_key(ckchs_transaction.new_ckchs->ckch[n].cert, ckchs_transaction.new_ckchs->ckch[n].key)) {
11155 memprintf(&err, "inconsistencies between private key and certificate loaded '%s'.\n", ckchs_transaction.path);
11156 goto error;
11157 }
11158 }
11159 } else
11160#endif
11161 {
11162 if (!X509_check_private_key(ckchs_transaction.new_ckchs->ckch->cert, ckchs_transaction.new_ckchs->ckch->key)) {
11163 memprintf(&err, "inconsistencies between private key and certificate loaded '%s'.\n", ckchs_transaction.path);
11164 goto error;
11165 }
11166 }
11167
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011168 /* init the appctx structure */
11169 appctx->st2 = SETCERT_ST_INIT;
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011170 appctx->ctx.ssl.next_ckchi = NULL;
11171 appctx->ctx.ssl.new_ckchs = ckchs_transaction.new_ckchs;
11172 appctx->ctx.ssl.old_ckchs = ckchs_transaction.old_ckchs;
11173
11174 /* we don't unlock there, it will be unlock after the IO handler, in the release handler */
11175 return 0;
11176
11177error:
11178
11179 HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
11180 err = memprintf(&err, "%sCan't commit %s!\n", err ? err : "", args[3]);
11181
11182 return cli_dynerr(appctx, err);
11183}
11184
William Lallemand8f840d72019-10-23 10:53:05 +020011185/*
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011186 * Parsing function of `set ssl cert`, it updates or creates a temporary ckch.
William Lallemand8f840d72019-10-23 10:53:05 +020011187 */
William Lallemand150bfa82019-09-19 17:12:49 +020011188static int cli_parse_set_cert(char **args, char *payload, struct appctx *appctx, void *private)
11189{
William Lallemand0c3b7d92019-10-18 11:27:07 +020011190 struct ckch_store *new_ckchs = NULL;
William Lallemand8f840d72019-10-23 10:53:05 +020011191 struct ckch_store *old_ckchs = NULL;
William Lallemand150bfa82019-09-19 17:12:49 +020011192 char *err = NULL;
William Lallemand963b2e72019-10-14 11:38:36 +020011193 int i;
William Lallemand849eed62019-10-17 16:23:50 +020011194 int bundle = -1; /* TRUE if >= 0 (ckch index) */
Emeric Brunf69ed1d2019-10-17 11:56:56 +020011195 int errcode = 0;
William Lallemand44b35322019-10-17 16:28:40 +020011196 char *end;
11197 int type = CERT_TYPE_PEM;
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011198 struct cert_key_and_chain *ckch;
11199 struct buffer *buf;
William Lallemand8f840d72019-10-23 10:53:05 +020011200
William Lallemand230662a2019-12-03 13:32:54 +010011201 if (!cli_has_level(appctx, ACCESS_LVL_ADMIN))
11202 return 1;
11203
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011204 if ((buf = alloc_trash_chunk()) == NULL)
11205 return cli_err(appctx, "Can't allocate memory\n");
William Lallemand150bfa82019-09-19 17:12:49 +020011206
11207 if (!*args[3] || !payload)
11208 return cli_err(appctx, "'set ssl cert expects a filename and a certificat as a payload\n");
11209
11210 /* The operations on the CKCH architecture are locked so we can
11211 * manipulate ckch_store and ckch_inst */
11212 if (HA_SPIN_TRYLOCK(CKCH_LOCK, &ckch_lock))
11213 return cli_err(appctx, "Can't update the certificate!\nOperations on certificates are currently locked!\n");
11214
William Lallemand8f840d72019-10-23 10:53:05 +020011215 if (!chunk_strcpy(buf, args[3])) {
11216 memprintf(&err, "%sCan't allocate memory\n", err ? err : "");
11217 errcode |= ERR_ALERT | ERR_FATAL;
11218 goto end;
11219 }
11220
William Lallemand44b35322019-10-17 16:28:40 +020011221 /* check which type of file we want to update */
William Lallemandf29cdef2019-10-23 15:00:52 +020011222 for (i = 0; cert_exts[i].type < CERT_TYPE_MAX; i++) {
William Lallemand8f840d72019-10-23 10:53:05 +020011223 end = strrchr(buf->area, '.');
William Lallemand44b35322019-10-17 16:28:40 +020011224 if (end && *cert_exts[i].ext && (!strcmp(end + 1, cert_exts[i].ext))) {
11225 *end = '\0';
11226 type = cert_exts[i].type;
11227 break;
11228 }
11229 }
11230
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011231 appctx->ctx.ssl.old_ckchs = NULL;
11232 appctx->ctx.ssl.new_ckchs = NULL;
William Lallemand849eed62019-10-17 16:23:50 +020011233
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011234 /* if there is an ongoing transaction */
11235 if (ckchs_transaction.path) {
11236 /* 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 +020011237#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011238 if (ckchs_transaction.new_ckchs->multi) {
Emmanuel Hocdet40f2f1e2019-10-30 17:31:28 +010011239 char *end;
William Lallemand963b2e72019-10-14 11:38:36 +020011240 int j;
William Lallemand150bfa82019-09-19 17:12:49 +020011241
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011242 /* check if it was used in a bundle by removing the
William Lallemand963b2e72019-10-14 11:38:36 +020011243 * .dsa/.rsa/.ecdsa at the end of the filename */
William Lallemand8f840d72019-10-23 10:53:05 +020011244 end = strrchr(buf->area, '.');
Emmanuel Hocdet40f2f1e2019-10-30 17:31:28 +010011245 for (j = 0; end && j < SSL_SOCK_NUM_KEYTYPES; j++) {
William Lallemand963b2e72019-10-14 11:38:36 +020011246 if (!strcmp(end + 1, SSL_SOCK_KEYTYPE_NAMES[j])) {
11247 bundle = j; /* keep the type of certificate so we insert it at the right place */
11248 *end = '\0'; /* it's a bundle let's end the string*/
11249 break;
11250 }
William Lallemand150bfa82019-09-19 17:12:49 +020011251 }
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011252 if (bundle < 0) {
11253 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);
11254 errcode |= ERR_ALERT | ERR_FATAL;
11255 goto end;
11256 }
11257 }
11258#endif
11259
11260 /* if there is an ongoing transaction, check if this is the same file */
11261 if (strcmp(ckchs_transaction.path, buf->area) != 0) {
11262 memprintf(&err, "The ongoing transaction is about '%s' but you are trying to set '%s'\n", ckchs_transaction.path, buf->area);
11263 errcode |= ERR_ALERT | ERR_FATAL;
11264 goto end;
William Lallemand150bfa82019-09-19 17:12:49 +020011265 }
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011266
11267 appctx->ctx.ssl.old_ckchs = ckchs_transaction.new_ckchs;
11268
11269 } else {
11270 struct ckch_store *find_ckchs[2] = { NULL, NULL };
11271
11272 /* lookup for the certificate in the tree:
11273 * check if this is used as a bundle AND as a unique certificate */
11274 for (i = 0; i < 2; i++) {
11275
11276 if ((find_ckchs[i] = ckchs_lookup(buf->area)) != NULL) {
11277 /* only the bundle name is in the tree and you should
11278 * never update a bundle name, only a filename */
11279 if (bundle < 0 && find_ckchs[i]->multi) {
11280 /* we tried to look for a non-bundle and we found a bundle */
11281 memprintf(&err, "%s%s is a multi-cert bundle. Try updating %s.{dsa,rsa,ecdsa}\n",
11282 err ? err : "", args[3], args[3]);
11283 errcode |= ERR_ALERT | ERR_FATAL;
11284 goto end;
11285 }
William Lallemand3246d942019-11-04 14:02:11 +010011286 /* If we want a bundle but this is not a bundle
11287 * example: When you try to update <file>.rsa, but
11288 * <file> is a regular file */
11289 if (bundle >= 0 && find_ckchs[i]->multi == 0) {
11290 find_ckchs[i] = NULL;
11291 break;
11292 }
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011293 }
11294#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
11295 {
Emmanuel Hocdet40f2f1e2019-10-30 17:31:28 +010011296 char *end;
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011297 int j;
11298
11299 /* check if it was used in a bundle by removing the
11300 * .dsa/.rsa/.ecdsa at the end of the filename */
11301 end = strrchr(buf->area, '.');
Emmanuel Hocdet40f2f1e2019-10-30 17:31:28 +010011302 for (j = 0; end && j < SSL_SOCK_NUM_KEYTYPES; j++) {
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011303 if (!strcmp(end + 1, SSL_SOCK_KEYTYPE_NAMES[j])) {
11304 bundle = j; /* keep the type of certificate so we insert it at the right place */
11305 *end = '\0'; /* it's a bundle let's end the string*/
11306 break;
11307 }
11308 }
William Lallemand37031b82019-11-04 13:38:53 +010011309 if (bundle < 0) /* we didn't find a bundle extension */
11310 break;
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011311 }
William Lallemand963b2e72019-10-14 11:38:36 +020011312#else
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011313 /* bundles are not supported here, so we don't need to lookup again */
11314 break;
William Lallemand963b2e72019-10-14 11:38:36 +020011315#endif
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011316 }
11317
11318 if (find_ckchs[0] && find_ckchs[1]) {
11319 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",
11320 err ? err : "", find_ckchs[0]->path, find_ckchs[1]->path);
11321 errcode |= ERR_ALERT | ERR_FATAL;
11322 goto end;
11323 }
11324
11325 appctx->ctx.ssl.old_ckchs = find_ckchs[0] ? find_ckchs[0] : find_ckchs[1];
William Lallemand150bfa82019-09-19 17:12:49 +020011326 }
11327
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011328 if (!appctx->ctx.ssl.old_ckchs) {
11329 memprintf(&err, "%sCan't replace a certificate which is not referenced by the configuration!\n",
William Lallemand150bfa82019-09-19 17:12:49 +020011330 err ? err : "");
Emeric Brunf69ed1d2019-10-17 11:56:56 +020011331 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemand8f840d72019-10-23 10:53:05 +020011332 goto end;
William Lallemand150bfa82019-09-19 17:12:49 +020011333 }
11334
William Lallemand8a7fdf02019-11-04 10:59:32 +010011335 if (!appctx->ctx.ssl.path) {
11336 /* this is a new transaction, set the path of the transaction */
11337 appctx->ctx.ssl.path = strdup(appctx->ctx.ssl.old_ckchs->path);
11338 if (!appctx->ctx.ssl.path) {
11339 memprintf(&err, "%sCan't allocate memory\n", err ? err : "");
11340 errcode |= ERR_ALERT | ERR_FATAL;
11341 goto end;
11342 }
11343 }
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011344
11345 old_ckchs = appctx->ctx.ssl.old_ckchs;
11346
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011347 /* duplicate the ckch store */
11348 new_ckchs = ckchs_dup(old_ckchs);
11349 if (!new_ckchs) {
11350 memprintf(&err, "%sCannot allocate memory!\n",
11351 err ? err : "");
11352 errcode |= ERR_ALERT | ERR_FATAL;
11353 goto end;
11354 }
11355
11356 if (!new_ckchs->multi)
11357 ckch = new_ckchs->ckch;
11358 else
11359 ckch = &new_ckchs->ckch[bundle];
11360
11361 /* appply the change on the duplicate */
11362 if (cert_exts[type].load(buf->area, payload, ckch, &err) != 0) {
11363 memprintf(&err, "%sCan't load the payload\n", err ? err : "");
11364 errcode |= ERR_ALERT | ERR_FATAL;
11365 goto end;
11366 }
11367
11368 appctx->ctx.ssl.new_ckchs = new_ckchs;
11369
11370 /* we succeed, we can save the ckchs in the transaction */
11371
11372 /* if there wasn't a transaction, update the old ckchs */
William Dauchyc8bb1532019-11-24 15:04:20 +010011373 if (!ckchs_transaction.old_ckchs) {
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011374 ckchs_transaction.old_ckchs = appctx->ctx.ssl.old_ckchs;
11375 ckchs_transaction.path = appctx->ctx.ssl.path;
11376 err = memprintf(&err, "Transaction created for certificate %s!\n", ckchs_transaction.path);
11377 } else {
11378 err = memprintf(&err, "Transaction updated for certificate %s!\n", ckchs_transaction.path);
11379
11380 }
11381
11382 /* free the previous ckchs if there was a transaction */
11383 ckchs_free(ckchs_transaction.new_ckchs);
11384
11385 ckchs_transaction.new_ckchs = appctx->ctx.ssl.new_ckchs;
11386
11387
William Lallemand8f840d72019-10-23 10:53:05 +020011388 /* creates the SNI ctxs later in the IO handler */
William Lallemand150bfa82019-09-19 17:12:49 +020011389
William Lallemand8f840d72019-10-23 10:53:05 +020011390end:
11391 free_trash_chunk(buf);
William Lallemand150bfa82019-09-19 17:12:49 +020011392
Emeric Brunf69ed1d2019-10-17 11:56:56 +020011393 if (errcode & ERR_CODE) {
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011394
11395 ckchs_free(appctx->ctx.ssl.new_ckchs);
11396 appctx->ctx.ssl.new_ckchs = NULL;
11397
11398 appctx->ctx.ssl.old_ckchs = NULL;
11399
11400 free(appctx->ctx.ssl.path);
11401 appctx->ctx.ssl.path = NULL;
11402
11403 HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
William Lallemand44b35322019-10-17 16:28:40 +020011404 return cli_dynerr(appctx, memprintf(&err, "%sCan't update %s!\n", err ? err : "", args[3]));
William Lallemand430413e2019-10-28 14:30:47 +010011405 } else {
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011406
11407 HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
11408 return cli_dynmsg(appctx, LOG_NOTICE, err);
William Lallemand430413e2019-10-28 14:30:47 +010011409 }
William Lallemand8f840d72019-10-23 10:53:05 +020011410 /* TODO: handle the ERR_WARN which are not handled because of the io_handler */
William Lallemand150bfa82019-09-19 17:12:49 +020011411}
11412
William Lallemand0bc9c8a2019-11-19 15:51:51 +010011413/* parsing function of 'abort ssl cert' */
11414static int cli_parse_abort_cert(char **args, char *payload, struct appctx *appctx, void *private)
11415{
11416 char *err = NULL;
11417
William Lallemand230662a2019-12-03 13:32:54 +010011418 if (!cli_has_level(appctx, ACCESS_LVL_ADMIN))
11419 return 1;
11420
William Lallemand0bc9c8a2019-11-19 15:51:51 +010011421 if (!*args[3])
11422 return cli_err(appctx, "'abort ssl cert' expects a filename\n");
11423
11424 /* The operations on the CKCH architecture are locked so we can
11425 * manipulate ckch_store and ckch_inst */
11426 if (HA_SPIN_TRYLOCK(CKCH_LOCK, &ckch_lock))
11427 return cli_err(appctx, "Can't abort!\nOperations on certificates are currently locked!\n");
11428
11429 if (!ckchs_transaction.path) {
11430 memprintf(&err, "No ongoing transaction!\n");
11431 goto error;
11432 }
11433
11434 if (strcmp(ckchs_transaction.path, args[3]) != 0) {
11435 memprintf(&err, "The ongoing transaction is about '%s' but you are trying to abort a transaction for '%s'\n", ckchs_transaction.path, args[3]);
11436 goto error;
11437 }
11438
11439 /* Only free the ckchs there, because the SNI and instances were not generated yet */
11440 ckchs_free(ckchs_transaction.new_ckchs);
11441 ckchs_transaction.new_ckchs = NULL;
11442 ckchs_free(ckchs_transaction.old_ckchs);
11443 ckchs_transaction.old_ckchs = NULL;
11444 free(ckchs_transaction.path);
11445 ckchs_transaction.path = NULL;
11446
11447 HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
11448
11449 err = memprintf(&err, "Transaction aborted for certificate '%s'!\n", args[3]);
11450 return cli_dynmsg(appctx, LOG_NOTICE, err);
11451
11452error:
11453 HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
11454
11455 return cli_dynerr(appctx, err);
11456}
11457
Aurélien Nephtaliabbf6072018-04-18 13:26:46 +020011458static int cli_parse_set_ocspresponse(char **args, char *payload, struct appctx *appctx, void *private)
William Lallemand32af2032016-10-29 18:09:35 +020011459{
11460#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
11461 char *err = NULL;
Willy Tarreau1c913e42018-08-22 05:26:57 +020011462 int i, j, ret;
Aurélien Nephtali1e0867c2018-04-18 14:04:58 +020011463
11464 if (!payload)
11465 payload = args[3];
William Lallemand32af2032016-10-29 18:09:35 +020011466
11467 /* Expect one parameter: the new response in base64 encoding */
Willy Tarreau9d008692019-08-09 11:21:01 +020011468 if (!*payload)
11469 return cli_err(appctx, "'set ssl ocsp-response' expects response in base64 encoding.\n");
Aurélien Nephtali1e0867c2018-04-18 14:04:58 +020011470
11471 /* remove \r and \n from the payload */
11472 for (i = 0, j = 0; payload[i]; i++) {
11473 if (payload[i] == '\r' || payload[i] == '\n')
11474 continue;
11475 payload[j++] = payload[i];
11476 }
11477 payload[j] = 0;
William Lallemand32af2032016-10-29 18:09:35 +020011478
Willy Tarreau1c913e42018-08-22 05:26:57 +020011479 ret = base64dec(payload, j, trash.area, trash.size);
Willy Tarreau9d008692019-08-09 11:21:01 +020011480 if (ret < 0)
11481 return cli_err(appctx, "'set ssl ocsp-response' received invalid base64 encoded response.\n");
William Lallemand32af2032016-10-29 18:09:35 +020011482
Willy Tarreau1c913e42018-08-22 05:26:57 +020011483 trash.data = ret;
William Lallemand32af2032016-10-29 18:09:35 +020011484 if (ssl_sock_update_ocsp_response(&trash, &err)) {
Willy Tarreau9d008692019-08-09 11:21:01 +020011485 if (err)
11486 return cli_dynerr(appctx, memprintf(&err, "%s.\n", err));
11487 else
11488 return cli_err(appctx, "Failed to update OCSP response.\n");
William Lallemand32af2032016-10-29 18:09:35 +020011489 }
Willy Tarreau9d008692019-08-09 11:21:01 +020011490
11491 return cli_msg(appctx, LOG_INFO, "OCSP Response updated!\n");
William Lallemand32af2032016-10-29 18:09:35 +020011492#else
Willy Tarreau9d008692019-08-09 11:21:01 +020011493 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 +020011494#endif
11495
Nenad Merdanovicc31499d2019-03-23 11:00:32 +010011496}
11497
Willy Tarreau86a394e2019-05-09 14:15:32 +020011498#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000100fL)
Nenad Merdanovicc31499d2019-03-23 11:00:32 +010011499static inline int sample_conv_var2smp_str(const struct arg *arg, struct sample *smp)
11500{
11501 switch (arg->type) {
11502 case ARGT_STR:
11503 smp->data.type = SMP_T_STR;
11504 smp->data.u.str = arg->data.str;
11505 return 1;
11506 case ARGT_VAR:
11507 if (!vars_get_by_desc(&arg->data.var, smp))
11508 return 0;
11509 if (!sample_casts[smp->data.type][SMP_T_STR])
11510 return 0;
11511 if (!sample_casts[smp->data.type][SMP_T_STR](smp))
11512 return 0;
11513 return 1;
11514 default:
11515 return 0;
11516 }
11517}
11518
11519static int check_aes_gcm(struct arg *args, struct sample_conv *conv,
11520 const char *file, int line, char **err)
11521{
11522 switch(args[0].data.sint) {
11523 case 128:
11524 case 192:
11525 case 256:
11526 break;
11527 default:
11528 memprintf(err, "key size must be 128, 192 or 256 (bits).");
11529 return 0;
11530 }
11531 /* Try to decode a variable. */
11532 vars_check_arg(&args[1], NULL);
11533 vars_check_arg(&args[2], NULL);
11534 vars_check_arg(&args[3], NULL);
11535 return 1;
11536}
11537
11538/* Arguements: AES size in bits, nonce, key, tag. The last three arguments are base64 encoded */
11539static int sample_conv_aes_gcm_dec(const struct arg *arg_p, struct sample *smp, void *private)
11540{
11541 struct sample nonce, key, aead_tag;
11542 struct buffer *smp_trash, *smp_trash_alloc;
11543 EVP_CIPHER_CTX *ctx;
11544 int dec_size, ret;
11545
11546 smp_set_owner(&nonce, smp->px, smp->sess, smp->strm, smp->opt);
11547 if (!sample_conv_var2smp_str(&arg_p[1], &nonce))
11548 return 0;
11549
11550 smp_set_owner(&key, smp->px, smp->sess, smp->strm, smp->opt);
11551 if (!sample_conv_var2smp_str(&arg_p[2], &key))
11552 return 0;
11553
11554 smp_set_owner(&aead_tag, smp->px, smp->sess, smp->strm, smp->opt);
11555 if (!sample_conv_var2smp_str(&arg_p[3], &aead_tag))
11556 return 0;
11557
11558 smp_trash = get_trash_chunk();
11559 smp_trash_alloc = alloc_trash_chunk();
11560 if (!smp_trash_alloc)
11561 return 0;
11562
11563 ctx = EVP_CIPHER_CTX_new();
11564
11565 if (!ctx)
11566 goto err;
11567
11568 dec_size = base64dec(nonce.data.u.str.area, nonce.data.u.str.data, smp_trash->area, smp_trash->size);
11569 if (dec_size < 0)
11570 goto err;
11571 smp_trash->data = dec_size;
11572
11573 /* Set cipher type and mode */
11574 switch(arg_p[0].data.sint) {
11575 case 128:
11576 EVP_DecryptInit_ex(ctx, EVP_aes_128_gcm(), NULL, NULL, NULL);
11577 break;
11578 case 192:
11579 EVP_DecryptInit_ex(ctx, EVP_aes_192_gcm(), NULL, NULL, NULL);
11580 break;
11581 case 256:
11582 EVP_DecryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL);
11583 break;
11584 }
11585
11586 EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, smp_trash->data, NULL);
11587
11588 /* Initialise IV */
11589 if(!EVP_DecryptInit_ex(ctx, NULL, NULL, NULL, (unsigned char *) smp_trash->area))
11590 goto err;
11591
11592 dec_size = base64dec(key.data.u.str.area, key.data.u.str.data, smp_trash->area, smp_trash->size);
11593 if (dec_size < 0)
11594 goto err;
11595 smp_trash->data = dec_size;
11596
11597 /* Initialise key */
11598 if (!EVP_DecryptInit_ex(ctx, NULL, NULL, (unsigned char *) smp_trash->area, NULL))
11599 goto err;
11600
11601 if (!EVP_DecryptUpdate(ctx, (unsigned char *) smp_trash->area, (int *) &smp_trash->data,
11602 (unsigned char *) smp->data.u.str.area, (int) smp->data.u.str.data))
11603 goto err;
11604
11605 dec_size = base64dec(aead_tag.data.u.str.area, aead_tag.data.u.str.data, smp_trash_alloc->area, smp_trash_alloc->size);
11606 if (dec_size < 0)
11607 goto err;
11608 smp_trash_alloc->data = dec_size;
11609 dec_size = smp_trash->data;
11610
11611 EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, smp_trash_alloc->data, (void *) smp_trash_alloc->area);
11612 ret = EVP_DecryptFinal_ex(ctx, (unsigned char *) smp_trash->area + smp_trash->data, (int *) &smp_trash->data);
11613
11614 if (ret <= 0)
11615 goto err;
11616
11617 smp->data.u.str.data = dec_size + smp_trash->data;
11618 smp->data.u.str.area = smp_trash->area;
11619 smp->data.type = SMP_T_BIN;
11620 smp->flags &= ~SMP_F_CONST;
11621 free_trash_chunk(smp_trash_alloc);
11622 return 1;
11623
11624err:
11625 free_trash_chunk(smp_trash_alloc);
11626 return 0;
William Lallemand32af2032016-10-29 18:09:35 +020011627}
Nenad Merdanovicc31499d2019-03-23 11:00:32 +010011628# endif
William Lallemand32af2032016-10-29 18:09:35 +020011629
Elliot Otchet71f82972020-01-15 08:12:14 -050011630/* Argument validation functions */
11631
11632/* This function is used to validate the arguments passed to any "x_dn" ssl
11633 * keywords. These keywords support specifying a third parameter that must be
11634 * either empty or the value "rfc2253". Returns 0 on error, non-zero if OK.
11635 */
11636int val_dnfmt(struct arg *arg, char **err_msg)
11637{
11638 if (arg && arg[2].type == ARGT_STR && arg[2].data.str.data > 0 && (strcmp(arg[2].data.str.area, "rfc2253") != 0)) {
11639 memprintf(err_msg, "only rfc2253 or a blank value are currently supported as the format argument.");
11640 return 0;
11641 }
11642 return 1;
11643}
11644
William Lallemand32af2032016-10-29 18:09:35 +020011645/* register cli keywords */
11646static struct cli_kw_list cli_kws = {{ },{
11647#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
11648 { { "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 +020011649 { { "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 +020011650#endif
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +010011651 { { "set", "ssl", "ocsp-response", NULL }, NULL, cli_parse_set_ocspresponse, NULL },
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011652 { { "set", "ssl", "cert", NULL }, "set ssl cert <certfile> <payload> : replace a certificate file", cli_parse_set_cert, NULL, NULL },
11653 { { "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 +010011654 { { "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 +010011655 { { "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 +020011656 { { NULL }, NULL, NULL, NULL }
11657}};
11658
Willy Tarreau0108d902018-11-25 19:14:37 +010011659INITCALL1(STG_REGISTER, cli_register_kw, &cli_kws);
William Lallemand32af2032016-10-29 18:09:35 +020011660
Willy Tarreau7875d092012-09-10 08:20:03 +020011661/* Note: must not be declared <const> as its list will be overwritten.
11662 * Please take care of keeping this list alphabetically sorted.
11663 */
Willy Tarreaudc13c112013-06-21 23:16:39 +020011664static struct sample_fetch_kw_list sample_fetch_keywords = {ILH, {
Emeric Brun645ae792014-04-30 14:21:06 +020011665 { "ssl_bc", smp_fetch_ssl_fc, 0, NULL, SMP_T_BOOL, SMP_USE_L5SRV },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +020011666 { "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 +010011667#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Jérôme Magnine064a802018-12-03 22:21:04 +010011668 { "ssl_bc_alpn", smp_fetch_ssl_fc_alpn, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
Olivier Houchard6b77f492018-11-22 18:18:29 +010011669#endif
Emeric Brun645ae792014-04-30 14:21:06 +020011670 { "ssl_bc_cipher", smp_fetch_ssl_fc_cipher, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
Olivier Houchard6b77f492018-11-22 18:18:29 +010011671#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
11672 { "ssl_bc_npn", smp_fetch_ssl_fc_npn, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
11673#endif
Emeric Brun74f7ffa2018-02-19 16:14:12 +010011674 { "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 +020011675 { "ssl_bc_protocol", smp_fetch_ssl_fc_protocol, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
Emeric Brunb73a9b02014-04-30 18:49:19 +020011676 { "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 +020011677 { "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 +020011678#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
Emeric Brun645ae792014-04-30 14:21:06 +020011679 { "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 -040011680#endif
Emmanuel Hocdet839af572019-05-14 16:27:35 +020011681#if HA_OPENSSL_VERSION_NUMBER >= 0x10100000L
Patrick Hemmer65674662019-06-04 08:13:03 -040011682 { "ssl_bc_client_random", smp_fetch_ssl_fc_random, 0, NULL, SMP_T_BIN, SMP_USE_L5SRV },
11683 { "ssl_bc_server_random", smp_fetch_ssl_fc_random, 0, NULL, SMP_T_BIN, SMP_USE_L5SRV },
Patrick Hemmere0275472018-04-28 19:15:51 -040011684 { "ssl_bc_session_key", smp_fetch_ssl_fc_session_key, 0, NULL, SMP_T_BIN, SMP_USE_L5SRV },
11685#endif
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +020011686 { "ssl_c_ca_err", smp_fetch_ssl_c_ca_err, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
11687 { "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 +010011688 { "ssl_c_der", smp_fetch_ssl_x_der, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +020011689 { "ssl_c_err", smp_fetch_ssl_c_err, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Elliot Otchet71f82972020-01-15 08:12:14 -050011690 { "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 +020011691 { "ssl_c_key_alg", smp_fetch_ssl_x_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
11692 { "ssl_c_notafter", smp_fetch_ssl_x_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
11693 { "ssl_c_notbefore", smp_fetch_ssl_x_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
11694 { "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 -050011695 { "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 +020011696 { "ssl_c_serial", smp_fetch_ssl_x_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
11697 { "ssl_c_sha1", smp_fetch_ssl_x_sha1, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +010011698 { "ssl_c_used", smp_fetch_ssl_c_used, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +020011699 { "ssl_c_verify", smp_fetch_ssl_c_verify, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
11700 { "ssl_c_version", smp_fetch_ssl_x_version, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Emeric Brun43e79582014-10-29 19:03:26 +010011701 { "ssl_f_der", smp_fetch_ssl_x_der, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Elliot Otchet71f82972020-01-15 08:12:14 -050011702 { "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 +020011703 { "ssl_f_key_alg", smp_fetch_ssl_x_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
11704 { "ssl_f_notafter", smp_fetch_ssl_x_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
11705 { "ssl_f_notbefore", smp_fetch_ssl_x_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
11706 { "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 -050011707 { "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 +020011708 { "ssl_f_serial", smp_fetch_ssl_x_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Emeric Brun55f4fa82014-04-30 17:11:25 +020011709 { "ssl_f_sha1", smp_fetch_ssl_x_sha1, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +020011710 { "ssl_f_version", smp_fetch_ssl_x_version, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +010011711 { "ssl_fc", smp_fetch_ssl_fc, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +020011712 { "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 +010011713 { "ssl_fc_cipher", smp_fetch_ssl_fc_cipher, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +010011714 { "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 +020011715 { "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 +010011716 { "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 +020011717 { "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 +010011718#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +010011719 { "ssl_fc_npn", smp_fetch_ssl_fc_npn, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreaua33c6542012-10-15 13:19:06 +020011720#endif
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +010011721#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +010011722 { "ssl_fc_alpn", smp_fetch_ssl_fc_alpn, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreauab861d32013-04-02 02:30:41 +020011723#endif
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +010011724 { "ssl_fc_protocol", smp_fetch_ssl_fc_protocol, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreau9a1ab082019-05-09 13:26:41 +020011725#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
Emeric Brunb73a9b02014-04-30 18:49:19 +020011726 { "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 -040011727#endif
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +020011728 { "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 +020011729#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +010011730 { "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 -040011731#endif
Emmanuel Hocdet839af572019-05-14 16:27:35 +020011732#if HA_OPENSSL_VERSION_NUMBER >= 0x10100000L
Patrick Hemmer65674662019-06-04 08:13:03 -040011733 { "ssl_fc_client_random", smp_fetch_ssl_fc_random, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
11734 { "ssl_fc_server_random", smp_fetch_ssl_fc_random, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Patrick Hemmere0275472018-04-28 19:15:51 -040011735 { "ssl_fc_session_key", smp_fetch_ssl_fc_session_key, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
11736#endif
Patrick Hemmer41966772018-04-28 19:15:48 -040011737#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +010011738 { "ssl_fc_sni", smp_fetch_ssl_fc_sni, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Patrick Hemmer41966772018-04-28 19:15:48 -040011739#endif
Thierry FOURNIER5bf77322017-02-25 12:45:22 +010011740 { "ssl_fc_cipherlist_bin", smp_fetch_ssl_fc_cl_bin, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
11741 { "ssl_fc_cipherlist_hex", smp_fetch_ssl_fc_cl_hex, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
11742 { "ssl_fc_cipherlist_str", smp_fetch_ssl_fc_cl_str, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
11743 { "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 +020011744 { NULL, NULL, 0, 0, 0 },
11745}};
11746
Willy Tarreau0108d902018-11-25 19:14:37 +010011747INITCALL1(STG_REGISTER, sample_register_fetches, &sample_fetch_keywords);
11748
Willy Tarreau7875d092012-09-10 08:20:03 +020011749/* Note: must not be declared <const> as its list will be overwritten.
11750 * Please take care of keeping this list alphabetically sorted.
11751 */
Willy Tarreaudc13c112013-06-21 23:16:39 +020011752static struct acl_kw_list acl_kws = {ILH, {
Thierry FOURNIERc5a4e982014-03-05 16:07:08 +010011753 { "ssl_fc_sni_end", "ssl_fc_sni", PAT_MATCH_END },
11754 { "ssl_fc_sni_reg", "ssl_fc_sni", PAT_MATCH_REG },
Willy Tarreau8ed669b2013-01-11 15:49:37 +010011755 { /* END */ },
Willy Tarreau7875d092012-09-10 08:20:03 +020011756}};
11757
Willy Tarreau0108d902018-11-25 19:14:37 +010011758INITCALL1(STG_REGISTER, acl_register_keywords, &acl_kws);
11759
Willy Tarreau79eeafa2012-09-14 07:53:05 +020011760/* Note: must not be declared <const> as its list will be overwritten.
11761 * Please take care of keeping this list alphabetically sorted, doing so helps
11762 * all code contributors.
11763 * Optional keywords are also declared with a NULL ->parse() function so that
11764 * the config parser can report an appropriate error when a known keyword was
11765 * not enabled.
11766 */
Emmanuel Hocdet98263292016-12-29 18:26:15 +010011767static struct ssl_bind_kw ssl_bind_kws[] = {
Olivier Houchardc2aae742017-09-22 18:26:28 +020011768 { "allow-0rtt", ssl_bind_parse_allow_0rtt, 0 }, /* allow 0-RTT */
Emmanuel Hocdet98263292016-12-29 18:26:15 +010011769 { "alpn", ssl_bind_parse_alpn, 1 }, /* set ALPN supported protocols */
Emmanuel Hocdet842e94e2019-12-16 16:39:17 +010011770 { "ca-file", ssl_bind_parse_ca_file, 1 }, /* set CAfile to process ca-names and verify on client cert */
11771 { "ca-verify-file", ssl_bind_parse_ca_verify_file, 1 }, /* set CAverify file to process verify on client cert */
Emmanuel Hocdet98263292016-12-29 18:26:15 +010011772 { "ciphers", ssl_bind_parse_ciphers, 1 }, /* set SSL cipher suite */
Emmanuel Hocdet839af572019-05-14 16:27:35 +020011773#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +020011774 { "ciphersuites", ssl_bind_parse_ciphersuites, 1 }, /* set TLS 1.3 cipher suite */
11775#endif
Emmanuel Hocdet98263292016-12-29 18:26:15 +010011776 { "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 +010011777 { "curves", ssl_bind_parse_curves, 1 }, /* set SSL curve suite */
Emmanuel Hocdet98263292016-12-29 18:26:15 +010011778 { "ecdhe", ssl_bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +020011779 { "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 +010011780 { "npn", ssl_bind_parse_npn, 1 }, /* set NPN supported protocols */
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +020011781 { "ssl-min-ver", ssl_bind_parse_tls_method_minmax,1 }, /* minimum version */
11782 { "ssl-max-ver", ssl_bind_parse_tls_method_minmax,1 }, /* maximum version */
Emmanuel Hocdet98263292016-12-29 18:26:15 +010011783 { "verify", ssl_bind_parse_verify, 1 }, /* set SSL verify method */
11784 { NULL, NULL, 0 },
11785};
11786
Willy Tarreau0108d902018-11-25 19:14:37 +010011787/* no initcall for ssl_bind_kws, these ones are parsed in the parser loop */
11788
Willy Tarreau51fb7652012-09-18 18:24:39 +020011789static struct bind_kw_list bind_kws = { "SSL", { }, {
Olivier Houchardc2aae742017-09-22 18:26:28 +020011790 { "allow-0rtt", bind_parse_allow_0rtt, 0 }, /* Allow 0RTT */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +020011791 { "alpn", bind_parse_alpn, 1 }, /* set ALPN supported protocols */
Emmanuel Hocdet842e94e2019-12-16 16:39:17 +010011792 { "ca-file", bind_parse_ca_file, 1 }, /* set CAfile to process ca-names and verify on client cert */
11793 { "ca-verify-file", bind_parse_ca_verify_file, 1 }, /* set CAverify file to process verify on client cert */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +020011794 { "ca-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ignore on verify depth > 0 */
11795 { "ca-sign-file", bind_parse_ca_sign_file, 1 }, /* set CAFile used to generate and sign server certs */
11796 { "ca-sign-pass", bind_parse_ca_sign_pass, 1 }, /* set CAKey passphrase */
11797 { "ciphers", bind_parse_ciphers, 1 }, /* set SSL cipher suite */
Emmanuel Hocdet839af572019-05-14 16:27:35 +020011798#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +020011799 { "ciphersuites", bind_parse_ciphersuites, 1 }, /* set TLS 1.3 cipher suite */
11800#endif
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +020011801 { "crl-file", bind_parse_crl_file, 1 }, /* set certificat revocation list file use on client cert verify */
11802 { "crt", bind_parse_crt, 1 }, /* load SSL certificates from this location */
11803 { "crt-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ingore on verify depth == 0 */
11804 { "crt-list", bind_parse_crt_list, 1 }, /* load a list of crt from this location */
11805 { "curves", bind_parse_curves, 1 }, /* set SSL curve suite */
11806 { "ecdhe", bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
11807 { "force-sslv3", bind_parse_tls_method_options, 0 }, /* force SSLv3 */
11808 { "force-tlsv10", bind_parse_tls_method_options, 0 }, /* force TLSv10 */
11809 { "force-tlsv11", bind_parse_tls_method_options, 0 }, /* force TLSv11 */
11810 { "force-tlsv12", bind_parse_tls_method_options, 0 }, /* force TLSv12 */
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +020011811 { "force-tlsv13", bind_parse_tls_method_options, 0 }, /* force TLSv13 */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +020011812 { "generate-certificates", bind_parse_generate_certs, 0 }, /* enable the server certificates generation */
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +020011813 { "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 +020011814 { "no-sslv3", bind_parse_tls_method_options, 0 }, /* disable SSLv3 */
11815 { "no-tlsv10", bind_parse_tls_method_options, 0 }, /* disable TLSv10 */
11816 { "no-tlsv11", bind_parse_tls_method_options, 0 }, /* disable TLSv11 */
11817 { "no-tlsv12", bind_parse_tls_method_options, 0 }, /* disable TLSv12 */
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +020011818 { "no-tlsv13", bind_parse_tls_method_options, 0 }, /* disable TLSv13 */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +020011819 { "no-tls-tickets", bind_parse_no_tls_tickets, 0 }, /* disable session resumption tickets */
11820 { "ssl", bind_parse_ssl, 0 }, /* enable SSL processing */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +020011821 { "ssl-min-ver", bind_parse_tls_method_minmax, 1 }, /* minimum version */
11822 { "ssl-max-ver", bind_parse_tls_method_minmax, 1 }, /* maximum version */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +020011823 { "strict-sni", bind_parse_strict_sni, 0 }, /* refuse negotiation if sni doesn't match a certificate */
11824 { "tls-ticket-keys", bind_parse_tls_ticket_keys, 1 }, /* set file to load TLS ticket keys from */
11825 { "verify", bind_parse_verify, 1 }, /* set SSL verify method */
11826 { "npn", bind_parse_npn, 1 }, /* set NPN supported protocols */
11827 { "prefer-client-ciphers", bind_parse_pcc, 0 }, /* prefer client ciphers */
Willy Tarreau79eeafa2012-09-14 07:53:05 +020011828 { NULL, NULL, 0 },
11829}};
Emeric Brun46591952012-05-18 15:47:34 +020011830
Willy Tarreau0108d902018-11-25 19:14:37 +010011831INITCALL1(STG_REGISTER, bind_register_keywords, &bind_kws);
11832
Willy Tarreau92faadf2012-10-10 23:04:25 +020011833/* Note: must not be declared <const> as its list will be overwritten.
11834 * Please take care of keeping this list alphabetically sorted, doing so helps
11835 * all code contributors.
11836 * Optional keywords are also declared with a NULL ->parse() function so that
11837 * the config parser can report an appropriate error when a known keyword was
11838 * not enabled.
11839 */
11840static struct srv_kw_list srv_kws = { "SSL", { }, {
Olivier Houchard522eea72017-11-03 16:27:47 +010011841 { "allow-0rtt", srv_parse_allow_0rtt, 0, 1 }, /* Allow using early data on this server */
Olivier Houchardc7566002018-11-20 23:33:50 +010011842 { "alpn", srv_parse_alpn, 1, 1 }, /* Set ALPN supported protocols */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +020011843 { "ca-file", srv_parse_ca_file, 1, 1 }, /* set CAfile to process verify server cert */
Olivier Houchard92150142018-12-21 19:47:01 +010011844 { "check-alpn", srv_parse_alpn, 1, 1 }, /* Set ALPN used for checks */
Olivier Houchard9130a962017-10-17 17:33:43 +020011845 { "check-sni", srv_parse_check_sni, 1, 1 }, /* set SNI */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +020011846 { "check-ssl", srv_parse_check_ssl, 0, 1 }, /* enable SSL for health checks */
11847 { "ciphers", srv_parse_ciphers, 1, 1 }, /* select the cipher suite */
Emmanuel Hocdet839af572019-05-14 16:27:35 +020011848#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +020011849 { "ciphersuites", srv_parse_ciphersuites, 1, 1 }, /* select the cipher suite */
11850#endif
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +020011851 { "crl-file", srv_parse_crl_file, 1, 1 }, /* set certificate revocation list file use on server cert verify */
11852 { "crt", srv_parse_crt, 1, 1 }, /* set client certificate */
11853 { "force-sslv3", srv_parse_tls_method_options, 0, 1 }, /* force SSLv3 */
11854 { "force-tlsv10", srv_parse_tls_method_options, 0, 1 }, /* force TLSv10 */
11855 { "force-tlsv11", srv_parse_tls_method_options, 0, 1 }, /* force TLSv11 */
11856 { "force-tlsv12", srv_parse_tls_method_options, 0, 1 }, /* force TLSv12 */
11857 { "force-tlsv13", srv_parse_tls_method_options, 0, 1 }, /* force TLSv13 */
11858 { "no-check-ssl", srv_parse_no_check_ssl, 0, 1 }, /* disable SSL for health checks */
11859 { "no-send-proxy-v2-ssl", srv_parse_no_send_proxy_ssl, 0, 1 }, /* do not send PROXY protocol header v2 with SSL info */
11860 { "no-send-proxy-v2-ssl-cn", srv_parse_no_send_proxy_cn, 0, 1 }, /* do not send PROXY protocol header v2 with CN */
11861 { "no-ssl", srv_parse_no_ssl, 0, 1 }, /* disable SSL processing */
11862 { "no-ssl-reuse", srv_parse_no_ssl_reuse, 0, 1 }, /* disable session reuse */
11863 { "no-sslv3", srv_parse_tls_method_options, 0, 0 }, /* disable SSLv3 */
11864 { "no-tlsv10", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv10 */
11865 { "no-tlsv11", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv11 */
11866 { "no-tlsv12", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv12 */
11867 { "no-tlsv13", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv13 */
11868 { "no-tls-tickets", srv_parse_no_tls_tickets, 0, 1 }, /* disable session resumption tickets */
Olivier Houchardc7566002018-11-20 23:33:50 +010011869 { "npn", srv_parse_npn, 1, 1 }, /* Set NPN supported protocols */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +020011870 { "send-proxy-v2-ssl", srv_parse_send_proxy_ssl, 0, 1 }, /* send PROXY protocol header v2 with SSL info */
11871 { "send-proxy-v2-ssl-cn", srv_parse_send_proxy_cn, 0, 1 }, /* send PROXY protocol header v2 with CN */
11872 { "sni", srv_parse_sni, 1, 1 }, /* send SNI extension */
11873 { "ssl", srv_parse_ssl, 0, 1 }, /* enable SSL processing */
11874 { "ssl-min-ver", srv_parse_tls_method_minmax, 1, 1 }, /* minimum version */
11875 { "ssl-max-ver", srv_parse_tls_method_minmax, 1, 1 }, /* maximum version */
11876 { "ssl-reuse", srv_parse_ssl_reuse, 0, 1 }, /* enable session reuse */
11877 { "tls-tickets", srv_parse_tls_tickets, 0, 1 }, /* enable session resumption tickets */
11878 { "verify", srv_parse_verify, 1, 1 }, /* set SSL verify method */
11879 { "verifyhost", srv_parse_verifyhost, 1, 1 }, /* require that SSL cert verifies for hostname */
Willy Tarreau92faadf2012-10-10 23:04:25 +020011880 { NULL, NULL, 0, 0 },
11881}};
11882
Willy Tarreau0108d902018-11-25 19:14:37 +010011883INITCALL1(STG_REGISTER, srv_register_keywords, &srv_kws);
11884
Emeric Brun2c86cbf2014-10-30 15:56:50 +010011885static struct cfg_kw_list cfg_kws = {ILH, {
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +010011886 { CFG_GLOBAL, "ca-base", ssl_parse_global_ca_crt_base },
11887 { CFG_GLOBAL, "crt-base", ssl_parse_global_ca_crt_base },
Emmanuel Hocdet70df7bf2019-01-04 11:08:20 +010011888 { CFG_GLOBAL, "issuers-chain-path", ssl_load_global_issuers_from_path },
Willy Tarreau0bea58d2016-12-21 23:17:25 +010011889 { CFG_GLOBAL, "maxsslconn", ssl_parse_global_int },
Emeric Brun2c86cbf2014-10-30 15:56:50 +010011890 { CFG_GLOBAL, "ssl-default-bind-options", ssl_parse_default_bind_options },
11891 { CFG_GLOBAL, "ssl-default-server-options", ssl_parse_default_server_options },
Willy Tarreau14e36a12016-12-21 23:28:13 +010011892#ifndef OPENSSL_NO_DH
11893 { CFG_GLOBAL, "ssl-dh-param-file", ssl_parse_global_dh_param_file },
11894#endif
Grant Zhangfa6c7ee2017-01-14 01:42:15 +000011895 { CFG_GLOBAL, "ssl-mode-async", ssl_parse_global_ssl_async },
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020011896#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +000011897 { CFG_GLOBAL, "ssl-engine", ssl_parse_global_ssl_engine },
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020011898#endif
Willy Tarreau9ceda382016-12-21 23:13:03 +010011899 { CFG_GLOBAL, "tune.ssl.cachesize", ssl_parse_global_int },
11900#ifndef OPENSSL_NO_DH
11901 { CFG_GLOBAL, "tune.ssl.default-dh-param", ssl_parse_global_default_dh },
11902#endif
11903 { CFG_GLOBAL, "tune.ssl.force-private-cache", ssl_parse_global_private_cache },
11904 { CFG_GLOBAL, "tune.ssl.lifetime", ssl_parse_global_lifetime },
11905 { CFG_GLOBAL, "tune.ssl.maxrecord", ssl_parse_global_int },
11906 { CFG_GLOBAL, "tune.ssl.ssl-ctx-cache-size", ssl_parse_global_int },
Thierry FOURNIER5bf77322017-02-25 12:45:22 +010011907 { CFG_GLOBAL, "tune.ssl.capture-cipherlist-size", ssl_parse_global_capture_cipherlist },
Willy Tarreauf22e9682016-12-21 23:23:19 +010011908 { CFG_GLOBAL, "ssl-default-bind-ciphers", ssl_parse_global_ciphers },
11909 { CFG_GLOBAL, "ssl-default-server-ciphers", ssl_parse_global_ciphers },
Emmanuel Hocdet839af572019-05-14 16:27:35 +020011910#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +020011911 { CFG_GLOBAL, "ssl-default-bind-ciphersuites", ssl_parse_global_ciphersuites },
11912 { CFG_GLOBAL, "ssl-default-server-ciphersuites", ssl_parse_global_ciphersuites },
11913#endif
William Lallemand3af48e72020-02-03 17:15:52 +010011914 { CFG_GLOBAL, "ssl-load-extra-files", ssl_parse_global_extra_files },
Emeric Brun2c86cbf2014-10-30 15:56:50 +010011915 { 0, NULL, NULL },
11916}};
11917
Willy Tarreau0108d902018-11-25 19:14:37 +010011918INITCALL1(STG_REGISTER, cfg_register_keywords, &cfg_kws);
11919
Nenad Merdanovicc31499d2019-03-23 11:00:32 +010011920/* Note: must not be declared <const> as its list will be overwritten */
11921static struct sample_conv_kw_list conv_kws = {ILH, {
Willy Tarreau86a394e2019-05-09 14:15:32 +020011922#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000100fL)
Nenad Merdanovicc31499d2019-03-23 11:00:32 +010011923 { "aes_gcm_dec", sample_conv_aes_gcm_dec, ARG4(4,SINT,STR,STR,STR), check_aes_gcm, SMP_T_BIN, SMP_T_BIN },
11924#endif
11925 { NULL, NULL, 0, 0, 0 },
11926}};
11927
11928INITCALL1(STG_REGISTER, sample_register_convs, &conv_kws);
11929
Willy Tarreauf7bc57c2012-10-03 00:19:48 +020011930/* transport-layer operations for SSL sockets */
Willy Tarreaud9f5cca2016-12-22 21:08:52 +010011931static struct xprt_ops ssl_sock = {
Emeric Brun46591952012-05-18 15:47:34 +020011932 .snd_buf = ssl_sock_from_buf,
11933 .rcv_buf = ssl_sock_to_buf,
Olivier Houcharddf357842019-03-21 16:30:07 +010011934 .subscribe = ssl_subscribe,
11935 .unsubscribe = ssl_unsubscribe,
Olivier Houchard5149b592019-05-23 17:47:36 +020011936 .remove_xprt = ssl_remove_xprt,
Olivier Houchard2e055482019-05-27 19:50:12 +020011937 .add_xprt = ssl_add_xprt,
Emeric Brun46591952012-05-18 15:47:34 +020011938 .rcv_pipe = NULL,
11939 .snd_pipe = NULL,
11940 .shutr = NULL,
11941 .shutw = ssl_sock_shutw,
11942 .close = ssl_sock_close,
11943 .init = ssl_sock_init,
Willy Tarreau55d37912016-12-21 23:38:39 +010011944 .prepare_bind_conf = ssl_sock_prepare_bind_conf,
Willy Tarreau795cdab2016-12-22 17:30:54 +010011945 .destroy_bind_conf = ssl_sock_destroy_bind_conf,
Willy Tarreau17d45382016-12-22 21:16:08 +010011946 .prepare_srv = ssl_sock_prepare_srv_ctx,
11947 .destroy_srv = ssl_sock_free_srv_ctx,
Willy Tarreau8743f7e2016-12-04 18:44:29 +010011948 .get_alpn = ssl_sock_get_alpn,
Willy Tarreau8e0bb0a2016-11-24 16:58:12 +010011949 .name = "SSL",
Emeric Brun46591952012-05-18 15:47:34 +020011950};
11951
Olivier Houchardccaa7de2017-10-02 11:51:03 +020011952enum act_return ssl_action_wait_for_hs(struct act_rule *rule, struct proxy *px,
11953 struct session *sess, struct stream *s, int flags)
11954{
11955 struct connection *conn;
Olivier Houchard6fa63d92017-11-27 18:41:32 +010011956 struct conn_stream *cs;
Olivier Houchardccaa7de2017-10-02 11:51:03 +020011957
11958 conn = objt_conn(sess->origin);
Olivier Houchard6fa63d92017-11-27 18:41:32 +010011959 cs = objt_cs(s->si[0].end);
Olivier Houchardccaa7de2017-10-02 11:51:03 +020011960
Olivier Houchard6fa63d92017-11-27 18:41:32 +010011961 if (conn && cs) {
Olivier Houchardccaa7de2017-10-02 11:51:03 +020011962 if (conn->flags & (CO_FL_EARLY_SSL_HS | CO_FL_SSL_WAIT_HS)) {
Olivier Houchard6fa63d92017-11-27 18:41:32 +010011963 cs->flags |= CS_FL_WAIT_FOR_HS;
Olivier Houchardccaa7de2017-10-02 11:51:03 +020011964 s->req.flags |= CF_READ_NULL;
11965 return ACT_RET_YIELD;
11966 }
11967 }
11968 return (ACT_RET_CONT);
11969}
11970
11971static enum act_parse_ret ssl_parse_wait_for_hs(const char **args, int *orig_arg, struct proxy *px, struct act_rule *rule, char **err)
11972{
11973 rule->action_ptr = ssl_action_wait_for_hs;
11974
11975 return ACT_RET_PRS_OK;
11976}
11977
11978static struct action_kw_list http_req_actions = {ILH, {
11979 { "wait-for-handshake", ssl_parse_wait_for_hs },
11980 { /* END */ }
11981}};
11982
Willy Tarreau0108d902018-11-25 19:14:37 +010011983INITCALL1(STG_REGISTER, http_req_keywords_register, &http_req_actions);
11984
Willy Tarreau5db847a2019-05-09 14:13:35 +020011985#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +010011986
11987static void ssl_sock_sctl_free_func(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, long argl, void *argp)
11988{
11989 if (ptr) {
11990 chunk_destroy(ptr);
11991 free(ptr);
11992 }
11993}
11994
11995#endif
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +010011996static void ssl_sock_capture_free_func(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, long argl, void *argp)
11997{
Willy Tarreaubafbe012017-11-24 17:34:44 +010011998 pool_free(pool_head_ssl_capture, ptr);
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +010011999}
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +010012000
Emeric Brun46591952012-05-18 15:47:34 +020012001__attribute__((constructor))
Willy Tarreau92faadf2012-10-10 23:04:25 +020012002static void __ssl_sock_init(void)
12003{
Ilya Shipitsin0590f442019-05-25 19:30:50 +050012004#if (!defined(OPENSSL_NO_COMP) && !defined(SSL_OP_NO_COMPRESSION))
Emeric Brun46591952012-05-18 15:47:34 +020012005 STACK_OF(SSL_COMP)* cm;
Ilya Shipitsine242f3d2019-05-25 03:38:14 +050012006 int n;
Ilya Shipitsin0590f442019-05-25 19:30:50 +050012007#endif
Emeric Brun46591952012-05-18 15:47:34 +020012008
Willy Tarreauef934602016-12-22 23:12:01 +010012009 if (global_ssl.listen_default_ciphers)
12010 global_ssl.listen_default_ciphers = strdup(global_ssl.listen_default_ciphers);
12011 if (global_ssl.connect_default_ciphers)
12012 global_ssl.connect_default_ciphers = strdup(global_ssl.connect_default_ciphers);
Emmanuel Hocdet839af572019-05-14 16:27:35 +020012013#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +020012014 if (global_ssl.listen_default_ciphersuites)
12015 global_ssl.listen_default_ciphersuites = strdup(global_ssl.listen_default_ciphersuites);
12016 if (global_ssl.connect_default_ciphersuites)
12017 global_ssl.connect_default_ciphersuites = strdup(global_ssl.connect_default_ciphersuites);
12018#endif
Willy Tarreau610f04b2014-02-13 11:36:41 +010012019
Willy Tarreau13e14102016-12-22 20:25:26 +010012020 xprt_register(XPRT_SSL, &ssl_sock);
Willy Tarreau9a1ab082019-05-09 13:26:41 +020012021#if HA_OPENSSL_VERSION_NUMBER < 0x10100000L
Emeric Brun46591952012-05-18 15:47:34 +020012022 SSL_library_init();
Rosen Penev68185952018-12-14 08:47:02 -080012023#endif
Ilya Shipitsin0590f442019-05-25 19:30:50 +050012024#if (!defined(OPENSSL_NO_COMP) && !defined(SSL_OP_NO_COMPRESSION))
Emeric Brun46591952012-05-18 15:47:34 +020012025 cm = SSL_COMP_get_compression_methods();
Ilya Shipitsine242f3d2019-05-25 03:38:14 +050012026 n = sk_SSL_COMP_num(cm);
12027 while (n--) {
12028 (void) sk_SSL_COMP_pop(cm);
12029 }
Ilya Shipitsin0590f442019-05-25 19:30:50 +050012030#endif
Ilya Shipitsine242f3d2019-05-25 03:38:14 +050012031
Willy Tarreau5db847a2019-05-09 14:13:35 +020012032#if defined(USE_THREAD) && (HA_OPENSSL_VERSION_NUMBER < 0x10100000L)
Emeric Brun821bb9b2017-06-15 16:37:39 +020012033 ssl_locking_init();
12034#endif
Willy Tarreau5db847a2019-05-09 14:13:35 +020012035#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +010012036 sctl_ex_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, ssl_sock_sctl_free_func);
12037#endif
Thierry FOURNIER28962c92018-06-17 21:37:05 +020012038 ssl_app_data_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL);
Thierry FOURNIER16ff0502018-06-17 21:33:01 +020012039 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 +020012040#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +000012041 ENGINE_load_builtin_engines();
Grant Zhangfa6c7ee2017-01-14 01:42:15 +000012042 hap_register_post_check(ssl_check_async_engine_count);
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020012043#endif
Willy Tarreaud1c57502016-12-22 22:46:15 +010012044#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
12045 hap_register_post_check(tlskeys_finalize_config);
12046#endif
Willy Tarreau80713382018-11-26 10:19:54 +010012047
12048 global.ssl_session_max_cost = SSL_SESSION_MAX_COST;
12049 global.ssl_handshake_max_cost = SSL_HANDSHAKE_MAX_COST;
12050
Emmanuel Hocdet70df7bf2019-01-04 11:08:20 +010012051 hap_register_post_deinit(ssl_free_global_issuers);
12052
Willy Tarreau80713382018-11-26 10:19:54 +010012053#ifndef OPENSSL_NO_DH
12054 ssl_dh_ptr_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, NULL);
12055 hap_register_post_deinit(ssl_free_dh);
12056#endif
12057#ifndef OPENSSL_NO_ENGINE
12058 hap_register_post_deinit(ssl_free_engines);
12059#endif
12060 /* Load SSL string for the verbose & debug mode. */
12061 ERR_load_SSL_strings();
Olivier Houcharda8955d52019-04-07 22:00:38 +020012062 ha_meth = BIO_meth_new(0x666, "ha methods");
12063 BIO_meth_set_write(ha_meth, ha_ssl_write);
12064 BIO_meth_set_read(ha_meth, ha_ssl_read);
12065 BIO_meth_set_ctrl(ha_meth, ha_ssl_ctrl);
12066 BIO_meth_set_create(ha_meth, ha_ssl_new);
12067 BIO_meth_set_destroy(ha_meth, ha_ssl_free);
12068 BIO_meth_set_puts(ha_meth, ha_ssl_puts);
12069 BIO_meth_set_gets(ha_meth, ha_ssl_gets);
William Lallemand150bfa82019-09-19 17:12:49 +020012070
12071 HA_SPIN_INIT(&ckch_lock);
Willy Tarreau80713382018-11-26 10:19:54 +010012072}
Willy Tarreaud92aa5c2015-01-15 21:34:39 +010012073
Willy Tarreau80713382018-11-26 10:19:54 +010012074/* Compute and register the version string */
12075static void ssl_register_build_options()
12076{
12077 char *ptr = NULL;
12078 int i;
12079
Willy Tarreauc2c0b612016-12-21 19:23:20 +010012080 memprintf(&ptr, "Built with OpenSSL version : "
12081#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet50e25e12017-03-24 15:20:03 +010012082 "BoringSSL");
Willy Tarreauc2c0b612016-12-21 19:23:20 +010012083#else /* OPENSSL_IS_BORINGSSL */
12084 OPENSSL_VERSION_TEXT
12085 "\nRunning on OpenSSL version : %s%s",
Rosen Penev68185952018-12-14 08:47:02 -080012086 OpenSSL_version(OPENSSL_VERSION),
Willy Tarreau1d158ab2019-05-09 13:41:45 +020012087 ((OPENSSL_VERSION_NUMBER ^ OpenSSL_version_num()) >> 8) ? " (VERSIONS DIFFER!)" : "");
Willy Tarreauc2c0b612016-12-21 19:23:20 +010012088#endif
12089 memprintf(&ptr, "%s\nOpenSSL library supports TLS extensions : "
Willy Tarreau9a1ab082019-05-09 13:26:41 +020012090#if HA_OPENSSL_VERSION_NUMBER < 0x00907000L
Willy Tarreauc2c0b612016-12-21 19:23:20 +010012091 "no (library version too old)"
12092#elif defined(OPENSSL_NO_TLSEXT)
12093 "no (disabled via OPENSSL_NO_TLSEXT)"
12094#else
12095 "yes"
12096#endif
12097 "", ptr);
12098
12099 memprintf(&ptr, "%s\nOpenSSL library supports SNI : "
12100#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
12101 "yes"
12102#else
12103#ifdef OPENSSL_NO_TLSEXT
12104 "no (because of OPENSSL_NO_TLSEXT)"
12105#else
12106 "no (version might be too old, 0.9.8f min needed)"
12107#endif
12108#endif
12109 "", ptr);
12110
Emmanuel Hocdetf80bc242017-07-12 14:25:38 +020012111 memprintf(&ptr, "%s\nOpenSSL library supports :", ptr);
12112 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
12113 if (methodVersions[i].option)
12114 memprintf(&ptr, "%s %s", ptr, methodVersions[i].name);
Emmanuel Hocdet50e25e12017-03-24 15:20:03 +010012115
Willy Tarreauc2c0b612016-12-21 19:23:20 +010012116 hap_register_build_opts(ptr, 1);
Willy Tarreau80713382018-11-26 10:19:54 +010012117}
Willy Tarreauc2c0b612016-12-21 19:23:20 +010012118
Willy Tarreau80713382018-11-26 10:19:54 +010012119INITCALL0(STG_REGISTER, ssl_register_build_options);
Remi Gacogne4f902b82015-05-28 16:23:00 +020012120
Emeric Brun46591952012-05-18 15:47:34 +020012121
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020012122#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +000012123void ssl_free_engines(void) {
12124 struct ssl_engine_list *wl, *wlb;
12125 /* free up engine list */
12126 list_for_each_entry_safe(wl, wlb, &openssl_engines, list) {
12127 ENGINE_finish(wl->e);
12128 ENGINE_free(wl->e);
12129 LIST_DEL(&wl->list);
12130 free(wl);
12131 }
12132}
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020012133#endif
Christopher Faulet31af49d2015-06-09 17:29:50 +020012134
Remi Gacogned3a23c32015-05-28 16:39:47 +020012135#ifndef OPENSSL_NO_DH
Grant Zhang872f9c22017-01-21 01:10:18 +000012136void ssl_free_dh(void) {
12137 if (local_dh_1024) {
12138 DH_free(local_dh_1024);
12139 local_dh_1024 = NULL;
12140 }
12141 if (local_dh_2048) {
12142 DH_free(local_dh_2048);
12143 local_dh_2048 = NULL;
12144 }
12145 if (local_dh_4096) {
12146 DH_free(local_dh_4096);
12147 local_dh_4096 = NULL;
12148 }
Remi Gacogne47783ef2015-05-29 15:53:22 +020012149 if (global_dh) {
12150 DH_free(global_dh);
12151 global_dh = NULL;
12152 }
Grant Zhang872f9c22017-01-21 01:10:18 +000012153}
12154#endif
12155
12156__attribute__((destructor))
12157static void __ssl_sock_deinit(void)
12158{
12159#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Emeric Brun821bb9b2017-06-15 16:37:39 +020012160 if (ssl_ctx_lru_tree) {
12161 lru64_destroy(ssl_ctx_lru_tree);
Christopher Faulet2a944ee2017-11-07 10:42:54 +010012162 HA_RWLOCK_DESTROY(&ssl_ctx_lru_rwlock);
Emeric Brun821bb9b2017-06-15 16:37:39 +020012163 }
Remi Gacogned3a23c32015-05-28 16:39:47 +020012164#endif
12165
Willy Tarreau5db847a2019-05-09 14:13:35 +020012166#if (HA_OPENSSL_VERSION_NUMBER < 0x10100000L)
Remi Gacogned3a23c32015-05-28 16:39:47 +020012167 ERR_remove_state(0);
12168 ERR_free_strings();
12169
12170 EVP_cleanup();
Rosen Penev68185952018-12-14 08:47:02 -080012171#endif
Remi Gacogned3a23c32015-05-28 16:39:47 +020012172
Willy Tarreau5db847a2019-05-09 14:13:35 +020012173#if (HA_OPENSSL_VERSION_NUMBER >= 0x00907000L) && (HA_OPENSSL_VERSION_NUMBER < 0x10100000L)
Remi Gacogned3a23c32015-05-28 16:39:47 +020012174 CRYPTO_cleanup_all_ex_data();
12175#endif
Olivier Houcharda8955d52019-04-07 22:00:38 +020012176 BIO_meth_free(ha_meth);
Remi Gacogned3a23c32015-05-28 16:39:47 +020012177}
12178
12179
Emeric Brun46591952012-05-18 15:47:34 +020012180/*
12181 * Local variables:
12182 * c-indent-level: 8
12183 * c-basic-offset: 8
12184 * End:
12185 */