blob: 1a98e2ab82c91d7c610e7c01a2649510a6483ed0 [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 Lallemandcfca1422020-03-05 10:17:47 +01002952 sc->ckch_inst = ckch_inst;
William Lallemand1d29c742019-10-04 00:53:29 +02002953 LIST_ADDQ(&ckch_inst->sni_ctx, &sc->by_ckch_inst);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002954 }
2955 return order;
2956}
2957
William Lallemand6af03992019-07-23 15:00:54 +02002958/*
William Lallemand1d29c742019-10-04 00:53:29 +02002959 * Insert the sni_ctxs that are listed in the ckch_inst, in the bind_conf's sni_ctx tree
2960 * This function can't return an error.
2961 *
2962 * *CAUTION*: The caller must lock the sni tree if called in multithreading mode
2963 */
2964static void ssl_sock_load_cert_sni(struct ckch_inst *ckch_inst, struct bind_conf *bind_conf)
2965{
2966
2967 struct sni_ctx *sc0, *sc0b, *sc1;
2968 struct ebmb_node *node;
William Lallemand21724f02019-11-04 17:56:13 +01002969 int def = 0;
William Lallemand1d29c742019-10-04 00:53:29 +02002970
2971 list_for_each_entry_safe(sc0, sc0b, &ckch_inst->sni_ctx, by_ckch_inst) {
2972
2973 /* ignore if sc0 was already inserted in a tree */
2974 if (sc0->name.node.leaf_p)
2975 continue;
2976
2977 /* Check for duplicates. */
2978 if (sc0->wild)
2979 node = ebst_lookup(&bind_conf->sni_w_ctx, (char *)sc0->name.key);
2980 else
2981 node = ebst_lookup(&bind_conf->sni_ctx, (char *)sc0->name.key);
2982
2983 for (; node; node = ebmb_next_dup(node)) {
2984 sc1 = ebmb_entry(node, struct sni_ctx, name);
2985 if (sc1->ctx == sc0->ctx && sc1->conf == sc0->conf
2986 && sc1->neg == sc0->neg && sc1->wild == sc0->wild) {
2987 /* it's a duplicate, we should remove and free it */
2988 LIST_DEL(&sc0->by_ckch_inst);
2989 free(sc0);
2990 sc0 = NULL;
William Lallemande15029b2019-10-14 10:46:58 +02002991 break;
William Lallemand1d29c742019-10-04 00:53:29 +02002992 }
2993 }
2994
2995 /* if duplicate, ignore the insertion */
2996 if (!sc0)
2997 continue;
2998
2999 if (sc0->wild)
3000 ebst_insert(&bind_conf->sni_w_ctx, &sc0->name);
3001 else
3002 ebst_insert(&bind_conf->sni_ctx, &sc0->name);
William Lallemand21724f02019-11-04 17:56:13 +01003003
3004 /* replace the default_ctx if required with the first ctx */
3005 if (ckch_inst->is_default && !def) {
3006 /* we don't need to free the default_ctx because the refcount was not incremented */
3007 bind_conf->default_ctx = sc0->ctx;
3008 def = 1;
3009 }
William Lallemand1d29c742019-10-04 00:53:29 +02003010 }
3011}
3012
3013/*
William Lallemande3af8fb2019-10-08 11:36:53 +02003014 * tree used to store the ckchs ordered by filename/bundle name
William Lallemand6af03992019-07-23 15:00:54 +02003015 */
William Lallemande3af8fb2019-10-08 11:36:53 +02003016struct eb_root ckchs_tree = EB_ROOT_UNIQUE;
William Lallemand6af03992019-07-23 15:00:54 +02003017
William Lallemandfa892222019-07-23 16:06:08 +02003018
Emeric Brun7a883362019-10-17 13:27:40 +02003019/* Loads Diffie-Hellman parameter from a ckchs to an SSL_CTX.
3020 * If there is no DH paramater availaible in the ckchs, the global
3021 * DH parameter is loaded into the SSL_CTX and if there is no
3022 * DH parameter available in ckchs nor in global, the default
3023 * DH parameters are applied on the SSL_CTX.
3024 * Returns a bitfield containing the flags:
3025 * ERR_FATAL in any fatal error case
3026 * ERR_ALERT if a reason of the error is availabine in err
3027 * ERR_WARN if a warning is available into err
3028 * The value 0 means there is no error nor warning and
3029 * the operation succeed.
3030 */
William Lallemandfa892222019-07-23 16:06:08 +02003031#ifndef OPENSSL_NO_DH
Emeric Brun7a883362019-10-17 13:27:40 +02003032static int ssl_sock_load_dh_params(SSL_CTX *ctx, const struct cert_key_and_chain *ckch,
3033 const char *path, char **err)
William Lallemandfa892222019-07-23 16:06:08 +02003034{
Emeric Brun7a883362019-10-17 13:27:40 +02003035 int ret = 0;
William Lallemandfa892222019-07-23 16:06:08 +02003036 DH *dh = NULL;
3037
William Lallemanda8c73742019-07-31 18:31:34 +02003038 if (ckch && ckch->dh) {
William Lallemandfa892222019-07-23 16:06:08 +02003039 dh = ckch->dh;
Emeric Bruna9363eb2019-10-17 14:53:03 +02003040 if (!SSL_CTX_set_tmp_dh(ctx, dh)) {
3041 memprintf(err, "%sunable to load the DH parameter specified in '%s'",
3042 err && *err ? *err : "", path);
3043#if defined(SSL_CTX_set_dh_auto)
3044 SSL_CTX_set_dh_auto(ctx, 1);
3045 memprintf(err, "%s, SSL library will use an automatically generated DH parameter.\n",
3046 err && *err ? *err : "");
3047#else
3048 memprintf(err, "%s, DH ciphers won't be available.\n",
3049 err && *err ? *err : "");
3050#endif
3051 ret |= ERR_WARN;
3052 goto end;
3053 }
William Lallemandfa892222019-07-23 16:06:08 +02003054
3055 if (ssl_dh_ptr_index >= 0) {
3056 /* store a pointer to the DH params to avoid complaining about
3057 ssl-default-dh-param not being set for this SSL_CTX */
3058 SSL_CTX_set_ex_data(ctx, ssl_dh_ptr_index, dh);
3059 }
3060 }
3061 else if (global_dh) {
Emeric Bruna9363eb2019-10-17 14:53:03 +02003062 if (!SSL_CTX_set_tmp_dh(ctx, global_dh)) {
3063 memprintf(err, "%sunable to use the global DH parameter for certificate '%s'",
3064 err && *err ? *err : "", path);
3065#if defined(SSL_CTX_set_dh_auto)
3066 SSL_CTX_set_dh_auto(ctx, 1);
3067 memprintf(err, "%s, SSL library will use an automatically generated DH parameter.\n",
3068 err && *err ? *err : "");
3069#else
3070 memprintf(err, "%s, DH ciphers won't be available.\n",
3071 err && *err ? *err : "");
3072#endif
3073 ret |= ERR_WARN;
3074 goto end;
3075 }
William Lallemandfa892222019-07-23 16:06:08 +02003076 }
3077 else {
3078 /* Clear openssl global errors stack */
3079 ERR_clear_error();
3080
3081 if (global_ssl.default_dh_param <= 1024) {
3082 /* we are limited to DH parameter of 1024 bits anyway */
3083 if (local_dh_1024 == NULL)
3084 local_dh_1024 = ssl_get_dh_1024();
3085
Emeric Brun7a883362019-10-17 13:27:40 +02003086 if (local_dh_1024 == NULL) {
3087 memprintf(err, "%sunable to load default 1024 bits DH parameter for certificate '%s'.\n",
3088 err && *err ? *err : "", path);
3089 ret |= ERR_ALERT | ERR_FATAL;
William Lallemandfa892222019-07-23 16:06:08 +02003090 goto end;
Emeric Brun7a883362019-10-17 13:27:40 +02003091 }
William Lallemandfa892222019-07-23 16:06:08 +02003092
Emeric Bruna9363eb2019-10-17 14:53:03 +02003093 if (!SSL_CTX_set_tmp_dh(ctx, local_dh_1024)) {
3094 memprintf(err, "%sunable to load default 1024 bits DH parameter for certificate '%s'.\n",
3095 err && *err ? *err : "", path);
3096#if defined(SSL_CTX_set_dh_auto)
3097 SSL_CTX_set_dh_auto(ctx, 1);
3098 memprintf(err, "%s, SSL library will use an automatically generated DH parameter.\n",
3099 err && *err ? *err : "");
3100#else
3101 memprintf(err, "%s, DH ciphers won't be available.\n",
3102 err && *err ? *err : "");
3103#endif
3104 ret |= ERR_WARN;
3105 goto end;
3106 }
William Lallemandfa892222019-07-23 16:06:08 +02003107 }
3108 else {
3109 SSL_CTX_set_tmp_dh_callback(ctx, ssl_get_tmp_dh);
3110 }
William Lallemandfa892222019-07-23 16:06:08 +02003111 }
3112
3113end:
William Lallemand4dd145a2020-02-05 11:46:33 +01003114 ERR_clear_error();
William Lallemandfa892222019-07-23 16:06:08 +02003115 return ret;
3116}
3117#endif
yanbzhu08ce6ab2015-12-02 13:01:29 -05003118
yanbzhu488a4d22015-12-01 15:16:07 -05003119/* Frees the contents of a cert_key_and_chain
3120 */
3121static void ssl_sock_free_cert_key_and_chain_contents(struct cert_key_and_chain *ckch)
3122{
yanbzhu488a4d22015-12-01 15:16:07 -05003123 if (!ckch)
3124 return;
3125
3126 /* Free the certificate and set pointer to NULL */
3127 if (ckch->cert)
3128 X509_free(ckch->cert);
3129 ckch->cert = NULL;
3130
3131 /* Free the key and set pointer to NULL */
3132 if (ckch->key)
3133 EVP_PKEY_free(ckch->key);
3134 ckch->key = NULL;
3135
3136 /* Free each certificate in the chain */
Emmanuel Hocdet9246f8b2018-11-30 16:00:21 +01003137 if (ckch->chain)
3138 sk_X509_pop_free(ckch->chain, X509_free);
3139 ckch->chain = NULL;
yanbzhu488a4d22015-12-01 15:16:07 -05003140
William Lallemand455af502019-10-17 18:04:45 +02003141 if (ckch->dh)
3142 DH_free(ckch->dh);
3143 ckch->dh = NULL;
3144
3145 if (ckch->sctl) {
3146 free(ckch->sctl->area);
3147 ckch->sctl->area = NULL;
3148 free(ckch->sctl);
3149 ckch->sctl = NULL;
3150 }
3151
3152 if (ckch->ocsp_response) {
3153 free(ckch->ocsp_response->area);
3154 ckch->ocsp_response->area = NULL;
3155 free(ckch->ocsp_response);
3156 ckch->ocsp_response = NULL;
3157 }
William Lallemand5c3c96f2020-01-23 11:53:13 +01003158
3159 if (ckch->ocsp_issuer)
William Lallemanddad239d2020-01-23 11:59:02 +01003160 X509_free(ckch->ocsp_issuer);
William Lallemand5c3c96f2020-01-23 11:53:13 +01003161 ckch->ocsp_issuer = NULL;
yanbzhu488a4d22015-12-01 15:16:07 -05003162}
3163
William Lallemand8d0f8932019-10-17 18:03:58 +02003164/*
3165 *
3166 * This function copy a cert_key_and_chain in memory
3167 *
3168 * It's used to try to apply changes on a ckch before committing them, because
3169 * most of the time it's not possible to revert those changes
3170 *
3171 * Return a the dst or NULL
3172 */
3173static struct cert_key_and_chain *ssl_sock_copy_cert_key_and_chain(struct cert_key_and_chain *src,
3174 struct cert_key_and_chain *dst)
3175{
3176 if (src->cert) {
3177 dst->cert = src->cert;
3178 X509_up_ref(src->cert);
3179 }
3180
3181 if (src->key) {
3182 dst->key = src->key;
3183 EVP_PKEY_up_ref(src->key);
3184 }
3185
3186 if (src->chain) {
3187 dst->chain = X509_chain_up_ref(src->chain);
3188 }
3189
3190 if (src->dh) {
3191 DH_up_ref(src->dh);
3192 dst->dh = src->dh;
3193 }
3194
3195 if (src->sctl) {
3196 struct buffer *sctl;
3197
3198 sctl = calloc(1, sizeof(*sctl));
3199 if (!chunk_dup(sctl, src->sctl)) {
3200 free(sctl);
3201 sctl = NULL;
3202 goto error;
3203 }
3204 dst->sctl = sctl;
3205 }
3206
3207 if (src->ocsp_response) {
3208 struct buffer *ocsp_response;
3209
3210 ocsp_response = calloc(1, sizeof(*ocsp_response));
3211 if (!chunk_dup(ocsp_response, src->ocsp_response)) {
3212 free(ocsp_response);
3213 ocsp_response = NULL;
3214 goto error;
3215 }
3216 dst->ocsp_response = ocsp_response;
3217 }
3218
3219 if (src->ocsp_issuer) {
3220 X509_up_ref(src->ocsp_issuer);
3221 dst->ocsp_issuer = src->ocsp_issuer;
3222 }
3223
3224 return dst;
3225
3226error:
3227
3228 /* free everything */
3229 ssl_sock_free_cert_key_and_chain_contents(dst);
3230
3231 return NULL;
3232}
3233
3234
yanbzhu488a4d22015-12-01 15:16:07 -05003235/* checks if a key and cert exists in the ckch
3236 */
William Lallemand1633e392019-09-30 12:58:13 +02003237#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
yanbzhu488a4d22015-12-01 15:16:07 -05003238static int ssl_sock_is_ckch_valid(struct cert_key_and_chain *ckch)
3239{
3240 return (ckch->cert != NULL && ckch->key != NULL);
3241}
William Lallemand1633e392019-09-30 12:58:13 +02003242#endif
yanbzhu488a4d22015-12-01 15:16:07 -05003243
William Lallemandf9568fc2019-10-16 18:27:58 +02003244/*
3245 * return 0 on success or != 0 on failure
3246 */
3247static int ssl_sock_load_issuer_file_into_ckch(const char *path, char *buf, struct cert_key_and_chain *ckch, char **err)
3248{
3249 int ret = 1;
3250 BIO *in = NULL;
3251 X509 *issuer;
3252
3253 if (buf) {
3254 /* reading from a buffer */
3255 in = BIO_new_mem_buf(buf, -1);
3256 if (in == NULL) {
3257 memprintf(err, "%sCan't allocate memory\n", err && *err ? *err : "");
3258 goto end;
3259 }
3260
3261 } else {
3262 /* reading from a file */
3263 in = BIO_new(BIO_s_file());
3264 if (in == NULL)
3265 goto end;
3266
3267 if (BIO_read_filename(in, path) <= 0)
3268 goto end;
3269 }
3270
3271 issuer = PEM_read_bio_X509_AUX(in, NULL, NULL, NULL);
3272 if (!issuer) {
3273 memprintf(err, "%s'%s' cannot be read or parsed'.\n",
Tim Duesterhus93128532019-11-23 23:45:10 +01003274 err && *err ? *err : "", path);
William Lallemandf9568fc2019-10-16 18:27:58 +02003275 goto end;
3276 }
Emmanuel Hocdeteb73dc32020-01-16 14:45:00 +01003277 /* no error, fill ckch with new context, old context must be free */
3278 if (ckch->ocsp_issuer)
3279 X509_free(ckch->ocsp_issuer);
William Lallemandf9568fc2019-10-16 18:27:58 +02003280 ckch->ocsp_issuer = issuer;
Emmanuel Hocdeteb73dc32020-01-16 14:45:00 +01003281 ret = 0;
William Lallemandf9568fc2019-10-16 18:27:58 +02003282
3283end:
3284
3285 ERR_clear_error();
3286 if (in)
3287 BIO_free(in);
3288
3289 return ret;
3290}
3291
William Lallemand96a9c972019-10-17 11:56:17 +02003292
3293/*
3294 * Try to load a PEM file from a <path> or a buffer <buf>
William Lallemand4c5adbf2020-02-24 14:23:22 +01003295 * The PEM must contain at least a Certificate,
3296 * It could contain a DH, a certificate chain and a PrivateKey.
yanbzhu488a4d22015-12-01 15:16:07 -05003297 *
William Lallemand96a9c972019-10-17 11:56:17 +02003298 * If it failed you should not attempt to use the ckch but free it.
3299 *
3300 * Return 0 on success or != 0 on failure
yanbzhu488a4d22015-12-01 15:16:07 -05003301 */
William Lallemand96a9c972019-10-17 11:56:17 +02003302static 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 -05003303{
William Lallemandf11365b2019-09-19 14:25:58 +02003304 BIO *in = NULL;
yanbzhu488a4d22015-12-01 15:16:07 -05003305 int ret = 1;
Emmanuel Hocdet83cbd3c2019-10-25 11:55:03 +02003306 X509 *ca;
William Lallemand96a9c972019-10-17 11:56:17 +02003307 X509 *cert = NULL;
3308 EVP_PKEY *key = NULL;
Emmanuel Hocdet6b5b44e2019-12-20 17:47:12 +01003309 DH *dh = NULL;
3310 STACK_OF(X509) *chain = NULL;
William Lallemand96a9c972019-10-17 11:56:17 +02003311
3312 if (buf) {
3313 /* reading from a buffer */
3314 in = BIO_new_mem_buf(buf, -1);
3315 if (in == NULL) {
3316 memprintf(err, "%sCan't allocate memory\n", err && *err ? *err : "");
3317 goto end;
3318 }
yanbzhu488a4d22015-12-01 15:16:07 -05003319
William Lallemand96a9c972019-10-17 11:56:17 +02003320 } else {
3321 /* reading from a file */
William Lallemandf11365b2019-09-19 14:25:58 +02003322 in = BIO_new(BIO_s_file());
3323 if (in == NULL)
3324 goto end;
yanbzhu488a4d22015-12-01 15:16:07 -05003325
William Lallemandf11365b2019-09-19 14:25:58 +02003326 if (BIO_read_filename(in, path) <= 0)
3327 goto end;
William Lallemandf11365b2019-09-19 14:25:58 +02003328 }
yanbzhu488a4d22015-12-01 15:16:07 -05003329
yanbzhu488a4d22015-12-01 15:16:07 -05003330 /* Read Private Key */
William Lallemand96a9c972019-10-17 11:56:17 +02003331 key = PEM_read_bio_PrivateKey(in, NULL, NULL, NULL);
William Lallemand4c5adbf2020-02-24 14:23:22 +01003332 /* no need to check for errors here, because the private key could be loaded later */
yanbzhu488a4d22015-12-01 15:16:07 -05003333
Emmanuel Hocdet54227d82019-07-30 17:04:01 +02003334#ifndef OPENSSL_NO_DH
William Lallemandfa892222019-07-23 16:06:08 +02003335 /* Seek back to beginning of file */
3336 if (BIO_reset(in) == -1) {
3337 memprintf(err, "%san error occurred while reading the file '%s'.\n",
3338 err && *err ? *err : "", path);
3339 goto end;
3340 }
3341
William Lallemand96a9c972019-10-17 11:56:17 +02003342 dh = PEM_read_bio_DHparams(in, NULL, NULL, NULL);
3343 /* no need to return an error there, dh is not mandatory */
Emmanuel Hocdet54227d82019-07-30 17:04:01 +02003344#endif
William Lallemandfa892222019-07-23 16:06:08 +02003345
Willy Tarreaubb137a82016-04-06 19:02:38 +02003346 /* Seek back to beginning of file */
Thierry FOURNIER / OZON.IOd44ea3f2016-10-14 00:49:21 +02003347 if (BIO_reset(in) == -1) {
3348 memprintf(err, "%san error occurred while reading the file '%s'.\n",
3349 err && *err ? *err : "", path);
3350 goto end;
3351 }
Willy Tarreaubb137a82016-04-06 19:02:38 +02003352
3353 /* Read Certificate */
William Lallemand96a9c972019-10-17 11:56:17 +02003354 cert = PEM_read_bio_X509_AUX(in, NULL, NULL, NULL);
3355 if (cert == NULL) {
Willy Tarreaubb137a82016-04-06 19:02:38 +02003356 memprintf(err, "%sunable to load certificate from file '%s'.\n",
William Lallemand96a9c972019-10-17 11:56:17 +02003357 err && *err ? *err : "", path);
Willy Tarreaubb137a82016-04-06 19:02:38 +02003358 goto end;
3359 }
3360
William Lallemand96a9c972019-10-17 11:56:17 +02003361 /* Look for a Certificate Chain */
Emmanuel Hocdet6b5b44e2019-12-20 17:47:12 +01003362 while ((ca = PEM_read_bio_X509(in, NULL, NULL, NULL))) {
3363 if (chain == NULL)
3364 chain = sk_X509_new_null();
3365 if (!sk_X509_push(chain, ca)) {
William Lallemand96a9c972019-10-17 11:56:17 +02003366 X509_free(ca);
3367 goto end;
3368 }
3369 }
Emmanuel Hocdeted17f472019-10-24 18:28:33 +02003370
yanbzhu488a4d22015-12-01 15:16:07 -05003371 ret = ERR_get_error();
3372 if (ret && (ERR_GET_LIB(ret) != ERR_LIB_PEM && ERR_GET_REASON(ret) != PEM_R_NO_START_LINE)) {
3373 memprintf(err, "%sunable to load certificate chain from file '%s'.\n",
William Lallemand96a9c972019-10-17 11:56:17 +02003374 err && *err ? *err : "", path);
yanbzhu488a4d22015-12-01 15:16:07 -05003375 goto end;
William Lallemand246c0242019-10-11 08:59:13 +02003376 }
3377
William Lallemand75b15f72020-01-23 10:56:05 +01003378 /* once it loaded the PEM, it should remove everything else in the ckch */
3379 if (ckch->ocsp_response) {
3380 free(ckch->ocsp_response->area);
3381 ckch->ocsp_response->area = NULL;
3382 free(ckch->ocsp_response);
3383 ckch->ocsp_response = NULL;
3384 }
3385
3386 if (ckch->sctl) {
3387 free(ckch->sctl->area);
3388 ckch->sctl->area = NULL;
3389 free(ckch->sctl);
3390 ckch->sctl = NULL;
3391 }
3392
3393 if (ckch->ocsp_issuer) {
3394 X509_free(ckch->ocsp_issuer);
3395 ckch->ocsp_issuer = NULL;
3396 }
3397
Emmanuel Hocdet6b5b44e2019-12-20 17:47:12 +01003398 /* no error, fill ckch with new context, old context will be free at end: */
3399 SWAP(ckch->key, key);
3400 SWAP(ckch->dh, dh);
3401 SWAP(ckch->cert, cert);
3402 SWAP(ckch->chain, chain);
3403
William Lallemand246c0242019-10-11 08:59:13 +02003404 ret = 0;
3405
William Lallemand96a9c972019-10-17 11:56:17 +02003406end:
William Lallemand246c0242019-10-11 08:59:13 +02003407
3408 ERR_clear_error();
William Lallemand96a9c972019-10-17 11:56:17 +02003409 if (in)
William Lallemand246c0242019-10-11 08:59:13 +02003410 BIO_free(in);
Emmanuel Hocdet83cbd3c2019-10-25 11:55:03 +02003411 if (key)
3412 EVP_PKEY_free(key);
Emmanuel Hocdet6b5b44e2019-12-20 17:47:12 +01003413 if (dh)
3414 DH_free(dh);
Emmanuel Hocdet83cbd3c2019-10-25 11:55:03 +02003415 if (cert)
3416 X509_free(cert);
Emmanuel Hocdet6b5b44e2019-12-20 17:47:12 +01003417 if (chain)
3418 sk_X509_pop_free(chain, X509_free);
William Lallemanda17f4112019-10-10 15:16:44 +02003419
William Lallemand96a9c972019-10-17 11:56:17 +02003420 return ret;
3421}
3422
3423/*
William Lallemand4c5adbf2020-02-24 14:23:22 +01003424 * Try to load a private key file from a <path> or a buffer <buf>
3425 *
3426 * If it failed you should not attempt to use the ckch but free it.
3427 *
3428 * Return 0 on success or != 0 on failure
3429 */
3430static int ssl_sock_load_key_into_ckch(const char *path, char *buf, struct cert_key_and_chain *ckch , char **err)
3431{
3432 BIO *in = NULL;
3433 int ret = 1;
3434 EVP_PKEY *key = NULL;
3435
3436 if (buf) {
3437 /* reading from a buffer */
3438 in = BIO_new_mem_buf(buf, -1);
3439 if (in == NULL) {
3440 memprintf(err, "%sCan't allocate memory\n", err && *err ? *err : "");
3441 goto end;
3442 }
3443
3444 } else {
3445 /* reading from a file */
3446 in = BIO_new(BIO_s_file());
3447 if (in == NULL)
3448 goto end;
3449
3450 if (BIO_read_filename(in, path) <= 0)
3451 goto end;
3452 }
3453
3454 /* Read Private Key */
3455 key = PEM_read_bio_PrivateKey(in, NULL, NULL, NULL);
3456 if (key == NULL) {
3457 memprintf(err, "%sunable to load private key from file '%s'.\n",
3458 err && *err ? *err : "", path);
3459 goto end;
3460 }
3461
3462 ret = 0;
3463
3464 SWAP(ckch->key, key);
3465
3466end:
3467
3468 ERR_clear_error();
3469 if (in)
3470 BIO_free(in);
3471 if (key)
3472 EVP_PKEY_free(key);
3473
3474 return ret;
3475}
3476
3477/*
William Lallemand96a9c972019-10-17 11:56:17 +02003478 * Try to load in a ckch every files related to a ckch.
3479 * (PEM, sctl, ocsp, issuer etc.)
3480 *
3481 * This function is only used to load files during the configuration parsing,
3482 * it is not used with the CLI.
3483 *
3484 * This allows us to carry the contents of the file without having to read the
3485 * file multiple times. The caller must call
3486 * ssl_sock_free_cert_key_and_chain_contents.
3487 *
3488 * returns:
3489 * 0 on Success
3490 * 1 on SSL Failure
3491 */
3492static int ssl_sock_load_files_into_ckch(const char *path, struct cert_key_and_chain *ckch, char **err)
3493{
3494 int ret = 1;
3495
3496 /* try to load the PEM */
3497 if (ssl_sock_load_pem_into_ckch(path, NULL, ckch , err) != 0) {
3498 goto end;
3499 }
3500
William Lallemand4c5adbf2020-02-24 14:23:22 +01003501 /* try to load an external private key if it wasn't in the PEM */
3502 if ((ckch->key == NULL) && (global_ssl.extra_files & SSL_GF_KEY)) {
3503 char fp[MAXPATHLEN+1];
3504 struct stat st;
3505
3506 snprintf(fp, MAXPATHLEN+1, "%s.key", path);
3507 if (stat(fp, &st) == 0) {
3508 if (ssl_sock_load_key_into_ckch(fp, NULL, ckch, err)) {
3509 memprintf(err, "%s '%s' is present but cannot be read or parsed'.\n",
3510 err && *err ? *err : "", fp);
3511 goto end;
3512 }
3513 }
3514 }
3515
3516 if (ckch->key == NULL) {
3517 memprintf(err, "%sNo Private Key found in '%s' or '%s.key'.\n", err && *err ? *err : "", path, path);
3518 goto end;
3519 }
3520
3521 if (!X509_check_private_key(ckch->cert, ckch->key)) {
3522 memprintf(err, "%sinconsistencies between private key and certificate loaded '%s'.\n",
3523 err && *err ? *err : "", path);
3524 goto end;
3525 }
3526
William Lallemanda17f4112019-10-10 15:16:44 +02003527#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
3528 /* try to load the sctl file */
William Lallemand3af48e72020-02-03 17:15:52 +01003529 if (global_ssl.extra_files & SSL_GF_SCTL) {
William Lallemanda17f4112019-10-10 15:16:44 +02003530 char fp[MAXPATHLEN+1];
3531 struct stat st;
3532
3533 snprintf(fp, MAXPATHLEN+1, "%s.sctl", path);
3534 if (stat(fp, &st) == 0) {
William Lallemand0dfae6c2019-10-16 18:06:58 +02003535 if (ssl_sock_load_sctl_from_file(fp, NULL, ckch, err)) {
William Lallemanda17f4112019-10-10 15:16:44 +02003536 memprintf(err, "%s '%s.sctl' is present but cannot be read or parsed'.\n",
Tim Duesterhus93128532019-11-23 23:45:10 +01003537 err && *err ? *err : "", fp);
William Lallemanda17f4112019-10-10 15:16:44 +02003538 ret = 1;
3539 goto end;
3540 }
3541 }
3542 }
3543#endif
yanbzhu488a4d22015-12-01 15:16:07 -05003544
William Lallemand246c0242019-10-11 08:59:13 +02003545 /* try to load an ocsp response file */
William Lallemand3af48e72020-02-03 17:15:52 +01003546 if (global_ssl.extra_files & SSL_GF_OCSP) {
William Lallemand246c0242019-10-11 08:59:13 +02003547 char fp[MAXPATHLEN+1];
3548 struct stat st;
3549
3550 snprintf(fp, MAXPATHLEN+1, "%s.ocsp", path);
3551 if (stat(fp, &st) == 0) {
William Lallemand3b5f3602019-10-16 18:05:05 +02003552 if (ssl_sock_load_ocsp_response_from_file(fp, NULL, ckch, err)) {
William Lallemand246c0242019-10-11 08:59:13 +02003553 ret = 1;
3554 goto end;
3555 }
3556 }
3557 }
3558
Emmanuel Hocdeteaad5cc2019-10-25 12:19:00 +02003559#ifndef OPENSSL_IS_BORINGSSL /* Useless for BoringSSL */
William Lallemand3af48e72020-02-03 17:15:52 +01003560 if (ckch->ocsp_response && (global_ssl.extra_files & SSL_GF_OCSP_ISSUER)) {
William Lallemand246c0242019-10-11 08:59:13 +02003561 /* if no issuer was found, try to load an issuer from the .issuer */
Emmanuel Hocdet078156d2020-01-22 17:02:53 +01003562 if (!ckch->ocsp_issuer) {
William Lallemand246c0242019-10-11 08:59:13 +02003563 struct stat st;
3564 char fp[MAXPATHLEN+1];
3565
3566 snprintf(fp, MAXPATHLEN+1, "%s.issuer", path);
3567 if (stat(fp, &st) == 0) {
William Lallemandf9568fc2019-10-16 18:27:58 +02003568 if (ssl_sock_load_issuer_file_into_ckch(fp, NULL, ckch, err)) {
William Lallemand246c0242019-10-11 08:59:13 +02003569 ret = 1;
3570 goto end;
3571 }
3572
3573 if (X509_check_issued(ckch->ocsp_issuer, ckch->cert) != X509_V_OK) {
William Lallemand786188f2019-10-15 10:05:37 +02003574 memprintf(err, "%s '%s' is not an issuer'.\n",
Tim Duesterhus93128532019-11-23 23:45:10 +01003575 err && *err ? *err : "", fp);
William Lallemand246c0242019-10-11 08:59:13 +02003576 ret = 1;
3577 goto end;
3578 }
William Lallemand246c0242019-10-11 08:59:13 +02003579 }
3580 }
3581 }
Emmanuel Hocdeteaad5cc2019-10-25 12:19:00 +02003582#endif
William Lallemand246c0242019-10-11 08:59:13 +02003583
yanbzhu488a4d22015-12-01 15:16:07 -05003584 ret = 0;
3585
3586end:
3587
3588 ERR_clear_error();
yanbzhu488a4d22015-12-01 15:16:07 -05003589
3590 /* Something went wrong in one of the reads */
3591 if (ret != 0)
3592 ssl_sock_free_cert_key_and_chain_contents(ckch);
3593
3594 return ret;
3595}
3596
3597/* Loads the info in ckch into ctx
Emeric Bruna96b5822019-10-17 13:25:14 +02003598 * Returns a bitfield containing the flags:
3599 * ERR_FATAL in any fatal error case
3600 * ERR_ALERT if the reason of the error is available in err
3601 * ERR_WARN if a warning is available into err
3602 * The value 0 means there is no error nor warning and
3603 * the operation succeed.
yanbzhu488a4d22015-12-01 15:16:07 -05003604 */
3605static int ssl_sock_put_ckch_into_ctx(const char *path, const struct cert_key_and_chain *ckch, SSL_CTX *ctx, char **err)
3606{
Emeric Bruna96b5822019-10-17 13:25:14 +02003607 int errcode = 0;
Emmanuel Hocdetb90d2cb2020-02-18 15:27:32 +01003608 STACK_OF(X509) *find_chain = NULL;
Emeric Bruna96b5822019-10-17 13:25:14 +02003609
yanbzhu488a4d22015-12-01 15:16:07 -05003610 if (SSL_CTX_use_PrivateKey(ctx, ckch->key) <= 0) {
3611 memprintf(err, "%sunable to load SSL private key into SSL Context '%s'.\n",
3612 err && *err ? *err : "", path);
Emeric Bruna96b5822019-10-17 13:25:14 +02003613 errcode |= ERR_ALERT | ERR_FATAL;
3614 return errcode;
yanbzhu488a4d22015-12-01 15:16:07 -05003615 }
3616
3617 if (!SSL_CTX_use_certificate(ctx, ckch->cert)) {
3618 memprintf(err, "%sunable to load SSL certificate into SSL Context '%s'.\n",
3619 err && *err ? *err : "", path);
Emeric Bruna96b5822019-10-17 13:25:14 +02003620 errcode |= ERR_ALERT | ERR_FATAL;
3621 goto end;
yanbzhu488a4d22015-12-01 15:16:07 -05003622 }
3623
Emmanuel Hocdetb90d2cb2020-02-18 15:27:32 +01003624 if (ckch->chain) {
3625 find_chain = ckch->chain;
3626 } else {
3627 /* Find Certificate Chain in global */
3628 struct issuer_chain *issuer;
3629 issuer = ssl_get_issuer_chain(ckch->cert);
3630 if (issuer)
3631 find_chain = issuer->chain;
3632 }
William Lallemand85888572020-02-27 14:48:35 +01003633
3634 /* If we didn't find a chain we *MUST* use an empty X509 structure */
3635 if (find_chain == NULL)
3636 find_chain = sk_X509_new_null();
3637
yanbzhu488a4d22015-12-01 15:16:07 -05003638 /* Load all certs in the ckch into the ctx_chain for the ssl_ctx */
Emmanuel Hocdet1c65fdd2018-12-03 18:07:44 +01003639#ifdef SSL_CTX_set1_chain
Emmanuel Hocdetb90d2cb2020-02-18 15:27:32 +01003640 if (!SSL_CTX_set1_chain(ctx, find_chain)) {
Emmanuel Hocdet9246f8b2018-11-30 16:00:21 +01003641 memprintf(err, "%sunable to load chain certificate into SSL Context '%s'. Make sure you are linking against Openssl >= 1.0.2.\n",
3642 err && *err ? *err : "", path);
Emeric Bruna96b5822019-10-17 13:25:14 +02003643 errcode |= ERR_ALERT | ERR_FATAL;
3644 goto end;
yanbzhu488a4d22015-12-01 15:16:07 -05003645 }
Emmanuel Hocdet1c65fdd2018-12-03 18:07:44 +01003646#else
3647 { /* legacy compat (< openssl 1.0.2) */
3648 X509 *ca;
Emmanuel Hocdet140b64f2019-10-24 18:33:10 +02003649 STACK_OF(X509) *chain;
Emmanuel Hocdetb90d2cb2020-02-18 15:27:32 +01003650 chain = X509_chain_up_ref(find_chain);
Emmanuel Hocdet140b64f2019-10-24 18:33:10 +02003651 while ((ca = sk_X509_shift(chain)))
Emmanuel Hocdet1c65fdd2018-12-03 18:07:44 +01003652 if (!SSL_CTX_add_extra_chain_cert(ctx, ca)) {
3653 memprintf(err, "%sunable to load chain certificate into SSL Context '%s'.\n",
3654 err && *err ? *err : "", path);
3655 X509_free(ca);
Emmanuel Hocdet140b64f2019-10-24 18:33:10 +02003656 sk_X509_pop_free(chain, X509_free);
Emeric Bruna96b5822019-10-17 13:25:14 +02003657 errcode |= ERR_ALERT | ERR_FATAL;
3658 goto end;
Emmanuel Hocdet1c65fdd2018-12-03 18:07:44 +01003659 }
3660 }
3661#endif
yanbzhu488a4d22015-12-01 15:16:07 -05003662
William Lallemandfa892222019-07-23 16:06:08 +02003663#ifndef OPENSSL_NO_DH
3664 /* store a NULL pointer to indicate we have not yet loaded
3665 a custom DH param file */
3666 if (ssl_dh_ptr_index >= 0) {
3667 SSL_CTX_set_ex_data(ctx, ssl_dh_ptr_index, NULL);
3668 }
3669
Emeric Brun7a883362019-10-17 13:27:40 +02003670 errcode |= ssl_sock_load_dh_params(ctx, ckch, path, err);
3671 if (errcode & ERR_CODE) {
William Lallemandfa892222019-07-23 16:06:08 +02003672 memprintf(err, "%sunable to load DH parameters from file '%s'.\n",
3673 err && *err ? *err : "", path);
Emeric Bruna96b5822019-10-17 13:25:14 +02003674 goto end;
William Lallemandfa892222019-07-23 16:06:08 +02003675 }
3676#endif
3677
William Lallemanda17f4112019-10-10 15:16:44 +02003678#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
3679 if (sctl_ex_index >= 0 && ckch->sctl) {
3680 if (ssl_sock_load_sctl(ctx, ckch->sctl) < 0) {
3681 memprintf(err, "%s '%s.sctl' is present but cannot be read or parsed'.\n",
Tim Duesterhus93128532019-11-23 23:45:10 +01003682 err && *err ? *err : "", path);
Emeric Bruna96b5822019-10-17 13:25:14 +02003683 errcode |= ERR_ALERT | ERR_FATAL;
3684 goto end;
William Lallemanda17f4112019-10-10 15:16:44 +02003685 }
3686 }
3687#endif
3688
William Lallemand4a660132019-10-14 14:51:41 +02003689#if ((defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP) || defined OPENSSL_IS_BORINGSSL)
William Lallemand246c0242019-10-11 08:59:13 +02003690 /* Load OCSP Info into context */
3691 if (ckch->ocsp_response) {
Emmanuel Hocdet6f507c72020-02-18 15:56:39 +01003692 if (ssl_sock_load_ocsp(ctx, ckch, find_chain) < 0) {
Tim Duesterhus93128532019-11-23 23:45:10 +01003693 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",
3694 err && *err ? *err : "", path);
Emeric Bruna96b5822019-10-17 13:25:14 +02003695 errcode |= ERR_ALERT | ERR_FATAL;
3696 goto end;
William Lallemand246c0242019-10-11 08:59:13 +02003697 }
3698 }
William Lallemand246c0242019-10-11 08:59:13 +02003699#endif
3700
Emeric Bruna96b5822019-10-17 13:25:14 +02003701 end:
3702 return errcode;
yanbzhu488a4d22015-12-01 15:16:07 -05003703}
3704
William Lallemandc4ecddf2019-07-31 16:50:08 +02003705#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
yanbzhu08ce6ab2015-12-02 13:01:29 -05003706
William Lallemand28a8fce2019-10-04 17:36:55 +02003707static int ssl_sock_populate_sni_keytypes_hplr(const char *str, struct eb_root *sni_keytypes, int key_index)
yanbzhu08ce6ab2015-12-02 13:01:29 -05003708{
3709 struct sni_keytype *s_kt = NULL;
3710 struct ebmb_node *node;
3711 int i;
3712
3713 for (i = 0; i < trash.size; i++) {
3714 if (!str[i])
3715 break;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02003716 trash.area[i] = tolower(str[i]);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003717 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +02003718 trash.area[i] = 0;
3719 node = ebst_lookup(sni_keytypes, trash.area);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003720 if (!node) {
3721 /* CN not found in tree */
3722 s_kt = malloc(sizeof(struct sni_keytype) + i + 1);
3723 /* Using memcpy here instead of strncpy.
3724 * strncpy will cause sig_abrt errors under certain versions of gcc with -O2
3725 * See: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=60792
3726 */
William Lallemand28a8fce2019-10-04 17:36:55 +02003727 if (!s_kt)
3728 return -1;
3729
Willy Tarreau843b7cb2018-07-13 10:54:26 +02003730 memcpy(s_kt->name.key, trash.area, i+1);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003731 s_kt->keytypes = 0;
3732 ebst_insert(sni_keytypes, &s_kt->name);
3733 } else {
3734 /* CN found in tree */
3735 s_kt = container_of(node, struct sni_keytype, name);
3736 }
3737
3738 /* Mark that this CN has the keytype of key_index via keytypes mask */
3739 s_kt->keytypes |= 1<<key_index;
3740
William Lallemand28a8fce2019-10-04 17:36:55 +02003741 return 0;
3742
yanbzhu08ce6ab2015-12-02 13:01:29 -05003743}
3744
William Lallemandc4ecddf2019-07-31 16:50:08 +02003745#endif
William Lallemand8c1cdde2019-10-18 10:58:14 +02003746/*
3747 * Free a ckch_store and its ckch(s)
3748 * The linked ckch_inst are not free'd
3749 */
3750void ckchs_free(struct ckch_store *ckchs)
3751{
3752 if (!ckchs)
3753 return;
3754
3755#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
3756 if (ckchs->multi) {
3757 int n;
3758
3759 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++)
3760 ssl_sock_free_cert_key_and_chain_contents(&ckchs->ckch[n]);
3761 } else
3762#endif
3763 {
3764 ssl_sock_free_cert_key_and_chain_contents(ckchs->ckch);
3765 ckchs->ckch = NULL;
3766 }
3767
3768 free(ckchs);
3769}
3770
3771/* allocate and duplicate a ckch_store
3772 * Return a new ckch_store or NULL */
3773static struct ckch_store *ckchs_dup(const struct ckch_store *src)
3774{
3775 struct ckch_store *dst;
3776 int pathlen;
3777
3778 pathlen = strlen(src->path);
3779 dst = calloc(1, sizeof(*dst) + pathlen + 1);
3780 if (!dst)
3781 return NULL;
3782 /* copy previous key */
3783 memcpy(dst->path, src->path, pathlen + 1);
3784 dst->multi = src->multi;
3785 LIST_INIT(&dst->ckch_inst);
3786
3787 dst->ckch = calloc((src->multi ? SSL_SOCK_NUM_KEYTYPES : 1), sizeof(*dst->ckch));
3788 if (!dst->ckch)
3789 goto error;
3790
3791#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
3792 if (src->multi) {
3793 int n;
3794
3795 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
3796 if (&src->ckch[n]) {
3797 if (!ssl_sock_copy_cert_key_and_chain(&src->ckch[n], &dst->ckch[n]))
3798 goto error;
3799 }
3800 }
3801 } else
3802#endif
3803 {
3804 if (!ssl_sock_copy_cert_key_and_chain(src->ckch, dst->ckch))
3805 goto error;
3806 }
3807
3808 return dst;
3809
3810error:
3811 ckchs_free(dst);
3812
3813 return NULL;
3814}
William Lallemandc4ecddf2019-07-31 16:50:08 +02003815
William Lallemand36b84632019-07-18 19:28:17 +02003816/*
William Lallemande3af8fb2019-10-08 11:36:53 +02003817 * lookup a path into the ckchs tree.
William Lallemand6af03992019-07-23 15:00:54 +02003818 */
William Lallemande3af8fb2019-10-08 11:36:53 +02003819static inline struct ckch_store *ckchs_lookup(char *path)
William Lallemand6af03992019-07-23 15:00:54 +02003820{
3821 struct ebmb_node *eb;
3822
William Lallemande3af8fb2019-10-08 11:36:53 +02003823 eb = ebst_lookup(&ckchs_tree, path);
William Lallemand6af03992019-07-23 15:00:54 +02003824 if (!eb)
3825 return NULL;
3826
William Lallemande3af8fb2019-10-08 11:36:53 +02003827 return ebmb_entry(eb, struct ckch_store, node);
William Lallemand6af03992019-07-23 15:00:54 +02003828}
3829
3830/*
William Lallemande3af8fb2019-10-08 11:36:53 +02003831 * This function allocate a ckch_store and populate it with certificates from files.
William Lallemand36b84632019-07-18 19:28:17 +02003832 */
William Lallemande3af8fb2019-10-08 11:36:53 +02003833static struct ckch_store *ckchs_load_cert_file(char *path, int multi, char **err)
William Lallemand36b84632019-07-18 19:28:17 +02003834{
William Lallemande3af8fb2019-10-08 11:36:53 +02003835 struct ckch_store *ckchs;
William Lallemand36b84632019-07-18 19:28:17 +02003836
William Lallemande3af8fb2019-10-08 11:36:53 +02003837 ckchs = calloc(1, sizeof(*ckchs) + strlen(path) + 1);
3838 if (!ckchs) {
William Lallemand36b84632019-07-18 19:28:17 +02003839 memprintf(err, "%sunable to allocate memory.\n", err && *err ? *err : "");
3840 goto end;
3841 }
William Lallemande3af8fb2019-10-08 11:36:53 +02003842 ckchs->ckch = calloc(1, sizeof(*ckchs->ckch) * (multi ? SSL_SOCK_NUM_KEYTYPES : 1));
William Lallemand36b84632019-07-18 19:28:17 +02003843
William Lallemande3af8fb2019-10-08 11:36:53 +02003844 if (!ckchs->ckch) {
William Lallemand36b84632019-07-18 19:28:17 +02003845 memprintf(err, "%sunable to allocate memory.\n", err && *err ? *err : "");
3846 goto end;
3847 }
3848
William Lallemand9117de92019-10-04 00:29:42 +02003849 LIST_INIT(&ckchs->ckch_inst);
3850
William Lallemand36b84632019-07-18 19:28:17 +02003851 if (!multi) {
3852
William Lallemand96a9c972019-10-17 11:56:17 +02003853 if (ssl_sock_load_files_into_ckch(path, ckchs->ckch, err) == 1)
William Lallemand36b84632019-07-18 19:28:17 +02003854 goto end;
3855
William Lallemande3af8fb2019-10-08 11:36:53 +02003856 /* insert into the ckchs tree */
3857 memcpy(ckchs->path, path, strlen(path) + 1);
3858 ebst_insert(&ckchs_tree, &ckchs->node);
William Lallemand36b84632019-07-18 19:28:17 +02003859 } else {
3860 int found = 0;
William Lallemandc4ecddf2019-07-31 16:50:08 +02003861#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
3862 char fp[MAXPATHLEN+1] = {0};
3863 int n = 0;
William Lallemand36b84632019-07-18 19:28:17 +02003864
3865 /* Load all possible certs and keys */
3866 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
3867 struct stat buf;
3868 snprintf(fp, sizeof(fp), "%s.%s", path, SSL_SOCK_KEYTYPE_NAMES[n]);
3869 if (stat(fp, &buf) == 0) {
William Lallemand96a9c972019-10-17 11:56:17 +02003870 if (ssl_sock_load_files_into_ckch(fp, &ckchs->ckch[n], err) == 1)
William Lallemand36b84632019-07-18 19:28:17 +02003871 goto end;
3872 found = 1;
William Lallemande3af8fb2019-10-08 11:36:53 +02003873 ckchs->multi = 1;
William Lallemand36b84632019-07-18 19:28:17 +02003874 }
3875 }
William Lallemandc4ecddf2019-07-31 16:50:08 +02003876#endif
William Lallemand36b84632019-07-18 19:28:17 +02003877
3878 if (!found) {
William Lallemand6e5f2ce2019-08-01 14:43:20 +02003879 memprintf(err, "%sDidn't find any certificate for bundle '%s'.\n", err && *err ? *err : "", path);
William Lallemand36b84632019-07-18 19:28:17 +02003880 goto end;
3881 }
William Lallemande3af8fb2019-10-08 11:36:53 +02003882 /* insert into the ckchs tree */
3883 memcpy(ckchs->path, path, strlen(path) + 1);
3884 ebst_insert(&ckchs_tree, &ckchs->node);
William Lallemand36b84632019-07-18 19:28:17 +02003885 }
William Lallemande3af8fb2019-10-08 11:36:53 +02003886 return ckchs;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003887
William Lallemand36b84632019-07-18 19:28:17 +02003888end:
William Lallemande3af8fb2019-10-08 11:36:53 +02003889 if (ckchs) {
3890 free(ckchs->ckch);
3891 ebmb_delete(&ckchs->node);
William Lallemand6af03992019-07-23 15:00:54 +02003892 }
3893
William Lallemande3af8fb2019-10-08 11:36:53 +02003894 free(ckchs);
William Lallemand36b84632019-07-18 19:28:17 +02003895
3896 return NULL;
3897}
3898
William Lallemand38df1c82019-12-04 15:39:35 +01003899
3900/*
3901 * Free a sni filters array generated by ckch_inst_sni_ctx_to_sni_filters()
3902 */
3903static inline void free_sni_filters(char **sni_filter, int fcount)
3904{
3905 int i;
3906
3907 if (sni_filter) {
3908 for (i = 0; i < fcount; i++) {
3909 if (sni_filter[i]) {
3910 free(sni_filter[i]);
3911 sni_filter[i] = NULL;
3912 }
3913 }
3914 free(sni_filter);
3915 }
3916}
3917
3918/*
3919 * Fill <*sni_filter> with an allocated array of ptr to the existing filters,
3920 * The caller should free <*sni_filter>.
3921 * Fill <*fcount> with the number of filters
3922 * Return an ERR_* code.
3923 */
3924static int ckch_inst_sni_ctx_to_sni_filters(const struct ckch_inst *ckchi, char ***sni_filter, int *fcount, char **err)
3925{
3926 struct sni_ctx *sc0;
3927 int errcode = 0;
3928 int i = 0;
3929 char **tmp_filter;
3930 int tmp_fcount = 0;
3931
3932 list_for_each_entry(sc0, &ckchi->sni_ctx, by_ckch_inst) {
3933 tmp_fcount++;
3934 }
3935
3936 if (!tmp_fcount)
3937 goto end;
3938
3939 tmp_filter = malloc(sizeof(*tmp_filter) * tmp_fcount);
3940 if (!tmp_filter) {
3941 errcode |= ERR_FATAL|ERR_ALERT;
3942 goto error;
3943 }
3944
3945 list_for_each_entry(sc0, &ckchi->sni_ctx, by_ckch_inst) {
3946 size_t len = strlen((char *)sc0->name.key);
3947
3948 /* we need to alloc and copy to insert a '!' or/and a '*' */
3949 tmp_filter[i] = calloc(1, len + sc0->neg + sc0->wild + 1);
3950 if (!tmp_filter[i]) {
3951 errcode |= ERR_FATAL|ERR_ALERT;
3952 goto error;
3953 }
3954
3955 if (sc0->neg)
3956 *tmp_filter[i] = '!';
3957 if (sc0->wild)
3958 *(tmp_filter[i] + sc0->neg) = '*';
3959
3960 memcpy(tmp_filter[i] + sc0->neg + sc0->wild, (char *)sc0->name.key, len + 1);
3961 i++;
3962 }
William Lallemand38df1c82019-12-04 15:39:35 +01003963 *sni_filter = tmp_filter;
Willy Tarreaud04a2a62020-03-05 16:26:12 +01003964end:
William Lallemand38df1c82019-12-04 15:39:35 +01003965 *fcount = tmp_fcount;
3966
3967 return errcode;
3968error:
3969 memprintf(err, "%sUnable to generate filters!",
3970 err && *err ? *err : "");
3971 free_sni_filters(tmp_filter, tmp_fcount);
3972
3973 return errcode;
3974}
3975
3976
William Lallemandc4ecddf2019-07-31 16:50:08 +02003977#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
3978
William Lallemand36b84632019-07-18 19:28:17 +02003979/*
William Lallemande3af8fb2019-10-08 11:36:53 +02003980 * Take a ckch_store which contains a multi-certificate bundle.
William Lallemand36b84632019-07-18 19:28:17 +02003981 * Group these certificates into a set of SSL_CTX*
yanbzhu08ce6ab2015-12-02 13:01:29 -05003982 * based on shared and unique CN and SAN entries. Add these SSL_CTX* to the SNI tree.
3983 *
Joseph Herlant017b3da2018-11-15 09:07:59 -08003984 * This will allow the user to explicitly group multiple cert/keys for a single purpose
yanbzhu08ce6ab2015-12-02 13:01:29 -05003985 *
Emeric Brun054563d2019-10-17 13:16:58 +02003986 * Returns a bitfield containing the flags:
3987 * ERR_FATAL in any fatal error case
3988 * ERR_ALERT if the reason of the error is available in err
3989 * ERR_WARN if a warning is available into err
William Lallemand36b84632019-07-18 19:28:17 +02003990 *
yanbzhu08ce6ab2015-12-02 13:01:29 -05003991 */
Emeric Brun054563d2019-10-17 13:16:58 +02003992static int ckch_inst_new_load_multi_store(const char *path, struct ckch_store *ckchs,
3993 struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
3994 char **sni_filter, int fcount, struct ckch_inst **ckchi, char **err)
yanbzhu08ce6ab2015-12-02 13:01:29 -05003995{
William Lallemand36b84632019-07-18 19:28:17 +02003996 int i = 0, n = 0;
3997 struct cert_key_and_chain *certs_and_keys;
William Lallemand4b989f22019-10-04 18:36:55 +02003998 struct eb_root sni_keytypes_map = EB_ROOT;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003999 struct ebmb_node *node;
4000 struct ebmb_node *next;
4001 /* Array of SSL_CTX pointers corresponding to each possible combo
4002 * of keytypes
4003 */
4004 struct key_combo_ctx key_combos[SSL_SOCK_POSSIBLE_KT_COMBOS] = { {0} };
Emeric Brun054563d2019-10-17 13:16:58 +02004005 int errcode = 0;
yanbzhu08ce6ab2015-12-02 13:01:29 -05004006 X509_NAME *xname = NULL;
4007 char *str = NULL;
4008#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
4009 STACK_OF(GENERAL_NAME) *names = NULL;
4010#endif
William Lallemand614ca0d2019-10-07 13:52:11 +02004011 struct ckch_inst *ckch_inst;
yanbzhu08ce6ab2015-12-02 13:01:29 -05004012
Emeric Brun054563d2019-10-17 13:16:58 +02004013 *ckchi = NULL;
4014
William Lallemande3af8fb2019-10-08 11:36:53 +02004015 if (!ckchs || !ckchs->ckch || !ckchs->multi) {
William Lallemand36b84632019-07-18 19:28:17 +02004016 memprintf(err, "%sunable to load SSL certificate file '%s' file does not exist.\n",
4017 err && *err ? *err : "", path);
Emeric Brun054563d2019-10-17 13:16:58 +02004018 return ERR_ALERT | ERR_FATAL;
William Lallemand614ca0d2019-10-07 13:52:11 +02004019 }
4020
4021 ckch_inst = ckch_inst_new();
4022 if (!ckch_inst) {
4023 memprintf(err, "%sunable to allocate SSL context for cert '%s'.\n",
4024 err && *err ? *err : "", path);
Emeric Brun054563d2019-10-17 13:16:58 +02004025 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemand614ca0d2019-10-07 13:52:11 +02004026 goto end;
yanbzhu08ce6ab2015-12-02 13:01:29 -05004027 }
4028
William Lallemande3af8fb2019-10-08 11:36:53 +02004029 certs_and_keys = ckchs->ckch;
William Lallemand36b84632019-07-18 19:28:17 +02004030
yanbzhu08ce6ab2015-12-02 13:01:29 -05004031 /* Process each ckch and update keytypes for each CN/SAN
4032 * for example, if CN/SAN www.a.com is associated with
4033 * certs with keytype 0 and 2, then at the end of the loop,
4034 * www.a.com will have:
4035 * keyindex = 0 | 1 | 4 = 5
4036 */
4037 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
William Lallemand28a8fce2019-10-04 17:36:55 +02004038 int ret;
yanbzhu08ce6ab2015-12-02 13:01:29 -05004039
4040 if (!ssl_sock_is_ckch_valid(&certs_and_keys[n]))
4041 continue;
4042
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02004043 if (fcount) {
William Lallemand28a8fce2019-10-04 17:36:55 +02004044 for (i = 0; i < fcount; i++) {
4045 ret = ssl_sock_populate_sni_keytypes_hplr(sni_filter[i], &sni_keytypes_map, n);
4046 if (ret < 0) {
4047 memprintf(err, "%sunable to allocate SSL context.\n",
4048 err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02004049 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemand28a8fce2019-10-04 17:36:55 +02004050 goto end;
4051 }
4052 }
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02004053 } else {
4054 /* A lot of the following code is OpenSSL boilerplate for processing CN's and SAN's,
4055 * so the line that contains logic is marked via comments
4056 */
4057 xname = X509_get_subject_name(certs_and_keys[n].cert);
4058 i = -1;
4059 while ((i = X509_NAME_get_index_by_NID(xname, NID_commonName, i)) != -1) {
4060 X509_NAME_ENTRY *entry = X509_NAME_get_entry(xname, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02004061 ASN1_STRING *value;
4062 value = X509_NAME_ENTRY_get_data(entry);
4063 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02004064 /* Important line is here */
William Lallemand28a8fce2019-10-04 17:36:55 +02004065 ret = ssl_sock_populate_sni_keytypes_hplr(str, &sni_keytypes_map, n);
yanbzhu08ce6ab2015-12-02 13:01:29 -05004066
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02004067 OPENSSL_free(str);
4068 str = NULL;
William Lallemand28a8fce2019-10-04 17:36:55 +02004069 if (ret < 0) {
4070 memprintf(err, "%sunable to allocate SSL context.\n",
4071 err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02004072 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemand28a8fce2019-10-04 17:36:55 +02004073 goto end;
4074 }
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02004075 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05004076 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05004077
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02004078 /* Do the above logic for each SAN */
yanbzhu08ce6ab2015-12-02 13:01:29 -05004079#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02004080 names = X509_get_ext_d2i(certs_and_keys[n].cert, NID_subject_alt_name, NULL, NULL);
4081 if (names) {
4082 for (i = 0; i < sk_GENERAL_NAME_num(names); i++) {
4083 GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i);
yanbzhu08ce6ab2015-12-02 13:01:29 -05004084
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02004085 if (name->type == GEN_DNS) {
4086 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
4087 /* Important line is here */
William Lallemand28a8fce2019-10-04 17:36:55 +02004088 ret = ssl_sock_populate_sni_keytypes_hplr(str, &sni_keytypes_map, n);
yanbzhu08ce6ab2015-12-02 13:01:29 -05004089
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02004090 OPENSSL_free(str);
4091 str = NULL;
William Lallemand28a8fce2019-10-04 17:36:55 +02004092 if (ret < 0) {
4093 memprintf(err, "%sunable to allocate SSL context.\n",
4094 err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02004095 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemand28a8fce2019-10-04 17:36:55 +02004096 goto end;
4097 }
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02004098 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05004099 }
4100 }
4101 }
4102 }
4103#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
4104 }
4105
4106 /* If no files found, return error */
4107 if (eb_is_empty(&sni_keytypes_map)) {
4108 memprintf(err, "%sunable to load SSL certificate file '%s' file does not exist.\n",
4109 err && *err ? *err : "", path);
Emeric Brun054563d2019-10-17 13:16:58 +02004110 errcode |= ERR_ALERT | ERR_FATAL;
yanbzhu08ce6ab2015-12-02 13:01:29 -05004111 goto end;
4112 }
4113
4114 /* We now have a map of CN/SAN to keytypes that are loaded in
4115 * Iterate through the map to create the SSL_CTX's (if needed)
4116 * and add each CTX to the SNI tree
4117 *
4118 * Some math here:
Joseph Herlant017b3da2018-11-15 09:07:59 -08004119 * There are 2^n - 1 possible combinations, each unique
yanbzhu08ce6ab2015-12-02 13:01:29 -05004120 * combination is denoted by the key in the map. Each key
4121 * has a value between 1 and 2^n - 1. Conveniently, the array
4122 * of SSL_CTX* is sized 2^n. So, we can simply use the i'th
4123 * entry in the array to correspond to the unique combo (key)
4124 * associated with i. This unique key combo (i) will be associated
4125 * with combos[i-1]
4126 */
4127
4128 node = ebmb_first(&sni_keytypes_map);
4129 while (node) {
4130 SSL_CTX *cur_ctx;
Bertrand Jacquin33423092016-11-13 16:37:13 +00004131 char cur_file[MAXPATHLEN+1];
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02004132 const struct pkey_info kinfo = { .sig = TLSEXT_signature_anonymous, .bits = 0 };
yanbzhu08ce6ab2015-12-02 13:01:29 -05004133
4134 str = (char *)container_of(node, struct sni_keytype, name)->name.key;
4135 i = container_of(node, struct sni_keytype, name)->keytypes;
4136 cur_ctx = key_combos[i-1].ctx;
4137
4138 if (cur_ctx == NULL) {
4139 /* need to create SSL_CTX */
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004140 cur_ctx = SSL_CTX_new(SSLv23_server_method());
yanbzhu08ce6ab2015-12-02 13:01:29 -05004141 if (cur_ctx == NULL) {
4142 memprintf(err, "%sunable to allocate SSL context.\n",
4143 err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02004144 errcode |= ERR_ALERT | ERR_FATAL;
yanbzhu08ce6ab2015-12-02 13:01:29 -05004145 goto end;
4146 }
4147
yanbzhube2774d2015-12-10 15:07:30 -05004148 /* Load all required certs/keys/chains/OCSPs info into SSL_CTX */
yanbzhu08ce6ab2015-12-02 13:01:29 -05004149 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
4150 if (i & (1<<n)) {
4151 /* Key combo contains ckch[n] */
Bertrand Jacquin33423092016-11-13 16:37:13 +00004152 snprintf(cur_file, MAXPATHLEN+1, "%s.%s", path, SSL_SOCK_KEYTYPE_NAMES[n]);
Emeric Bruna96b5822019-10-17 13:25:14 +02004153 errcode |= ssl_sock_put_ckch_into_ctx(cur_file, &certs_and_keys[n], cur_ctx, err);
4154 if (errcode & ERR_CODE)
yanbzhu08ce6ab2015-12-02 13:01:29 -05004155 goto end;
yanbzhu08ce6ab2015-12-02 13:01:29 -05004156 }
4157 }
4158
yanbzhu08ce6ab2015-12-02 13:01:29 -05004159 /* Update key_combos */
4160 key_combos[i-1].ctx = cur_ctx;
4161 }
4162
4163 /* Update SNI Tree */
William Lallemand9117de92019-10-04 00:29:42 +02004164
William Lallemand1d29c742019-10-04 00:53:29 +02004165 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 +02004166 kinfo, str, key_combos[i-1].order);
4167 if (key_combos[i-1].order < 0) {
4168 memprintf(err, "%sunable to create a sni context.\n", err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02004169 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemandfe49bb32019-10-03 23:46:33 +02004170 goto end;
4171 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05004172 node = ebmb_next(node);
4173 }
4174
4175
4176 /* Mark a default context if none exists, using the ctx that has the most shared keys */
4177 if (!bind_conf->default_ctx) {
4178 for (i = SSL_SOCK_POSSIBLE_KT_COMBOS - 1; i >= 0; i--) {
4179 if (key_combos[i].ctx) {
4180 bind_conf->default_ctx = key_combos[i].ctx;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004181 bind_conf->default_ssl_conf = ssl_conf;
William Lallemand21724f02019-11-04 17:56:13 +01004182 ckch_inst->is_default = 1;
yanbzhu08ce6ab2015-12-02 13:01:29 -05004183 break;
4184 }
4185 }
4186 }
4187
William Lallemand614ca0d2019-10-07 13:52:11 +02004188 ckch_inst->bind_conf = bind_conf;
William Lallemand150bfa82019-09-19 17:12:49 +02004189 ckch_inst->ssl_conf = ssl_conf;
William Lallemandcfca1422020-03-05 10:17:47 +01004190 ckch_inst->ckch_store = ckchs;
William Lallemand67630162020-03-09 16:56:39 +01004191 ckch_inst->filters = !!fcount;
yanbzhu08ce6ab2015-12-02 13:01:29 -05004192end:
4193
4194 if (names)
4195 sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
4196
yanbzhu08ce6ab2015-12-02 13:01:29 -05004197 node = ebmb_first(&sni_keytypes_map);
4198 while (node) {
4199 next = ebmb_next(node);
4200 ebmb_delete(node);
William Lallemand8ed5b962019-10-04 17:24:39 +02004201 free(ebmb_entry(node, struct sni_keytype, name));
yanbzhu08ce6ab2015-12-02 13:01:29 -05004202 node = next;
4203 }
4204
Emeric Brun054563d2019-10-17 13:16:58 +02004205 if (errcode & ERR_CODE && ckch_inst) {
William Lallemand0c6d12f2019-10-04 18:38:51 +02004206 struct sni_ctx *sc0, *sc0b;
4207
4208 /* free the SSL_CTX in case of error */
4209 for (i = 0; i < SSL_SOCK_POSSIBLE_KT_COMBOS; i++) {
4210 if (key_combos[i].ctx)
4211 SSL_CTX_free(key_combos[i].ctx);
4212 }
4213
4214 /* free the sni_ctx in case of error */
4215 list_for_each_entry_safe(sc0, sc0b, &ckch_inst->sni_ctx, by_ckch_inst) {
4216
4217 ebmb_delete(&sc0->name);
4218 LIST_DEL(&sc0->by_ckch_inst);
4219 free(sc0);
4220 }
William Lallemand614ca0d2019-10-07 13:52:11 +02004221 free(ckch_inst);
4222 ckch_inst = NULL;
William Lallemand0c6d12f2019-10-04 18:38:51 +02004223 }
4224
Emeric Brun054563d2019-10-17 13:16:58 +02004225 *ckchi = ckch_inst;
4226 return errcode;
yanbzhu08ce6ab2015-12-02 13:01:29 -05004227}
4228#else
4229/* This is a dummy, that just logs an error and returns error */
Emeric Brun054563d2019-10-17 13:16:58 +02004230static int ckch_inst_new_load_multi_store(const char *path, struct ckch_store *ckchs,
4231 struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
4232 char **sni_filter, int fcount, struct ckch_inst **ckchi, char **err)
yanbzhu08ce6ab2015-12-02 13:01:29 -05004233{
4234 memprintf(err, "%sunable to stat SSL certificate from file '%s' : %s.\n",
4235 err && *err ? *err : "", path, strerror(errno));
Emeric Brun054563d2019-10-17 13:16:58 +02004236 return ERR_ALERT | ERR_FATAL;
yanbzhu08ce6ab2015-12-02 13:01:29 -05004237}
4238
Willy Tarreau9a1ab082019-05-09 13:26:41 +02004239#endif /* #if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL: Support for loading multiple certs into a single SSL_CTX */
yanbzhu488a4d22015-12-01 15:16:07 -05004240
William Lallemand614ca0d2019-10-07 13:52:11 +02004241/*
4242 * This function allocate a ckch_inst and create its snis
Emeric Brun054563d2019-10-17 13:16:58 +02004243 *
4244 * Returns a bitfield containing the flags:
4245 * ERR_FATAL in any fatal error case
4246 * ERR_ALERT if the reason of the error is available in err
4247 * ERR_WARN if a warning is available into err
William Lallemand614ca0d2019-10-07 13:52:11 +02004248 */
Emeric Brun054563d2019-10-17 13:16:58 +02004249static int ckch_inst_new_load_store(const char *path, struct ckch_store *ckchs, struct bind_conf *bind_conf,
4250 struct ssl_bind_conf *ssl_conf, char **sni_filter, int fcount, struct ckch_inst **ckchi, char **err)
Emeric Brunfc0421f2012-09-07 17:30:07 +02004251{
William Lallemandc9402072019-05-15 15:33:54 +02004252 SSL_CTX *ctx;
William Lallemandc9402072019-05-15 15:33:54 +02004253 int i;
Emeric Brunfc0421f2012-09-07 17:30:07 +02004254 int order = 0;
4255 X509_NAME *xname;
4256 char *str;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01004257 EVP_PKEY *pkey;
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02004258 struct pkey_info kinfo = { .sig = TLSEXT_signature_anonymous, .bits = 0 };
Emeric Brunfc0421f2012-09-07 17:30:07 +02004259#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
4260 STACK_OF(GENERAL_NAME) *names;
4261#endif
William Lallemand36b84632019-07-18 19:28:17 +02004262 struct cert_key_and_chain *ckch;
William Lallemand614ca0d2019-10-07 13:52:11 +02004263 struct ckch_inst *ckch_inst = NULL;
Emeric Brun054563d2019-10-17 13:16:58 +02004264 int errcode = 0;
4265
4266 *ckchi = NULL;
William Lallemanda59191b2019-05-15 16:08:56 +02004267
William Lallemande3af8fb2019-10-08 11:36:53 +02004268 if (!ckchs || !ckchs->ckch)
Emeric Brun054563d2019-10-17 13:16:58 +02004269 return ERR_FATAL;
Emeric Brunfc0421f2012-09-07 17:30:07 +02004270
William Lallemande3af8fb2019-10-08 11:36:53 +02004271 ckch = ckchs->ckch;
William Lallemand36b84632019-07-18 19:28:17 +02004272
William Lallemandc9402072019-05-15 15:33:54 +02004273 ctx = SSL_CTX_new(SSLv23_server_method());
4274 if (!ctx) {
4275 memprintf(err, "%sunable to allocate SSL context for cert '%s'.\n",
4276 err && *err ? *err : "", path);
Emeric Brun054563d2019-10-17 13:16:58 +02004277 errcode |= ERR_ALERT | ERR_FATAL;
4278 goto error;
William Lallemandc9402072019-05-15 15:33:54 +02004279 }
4280
Emeric Bruna96b5822019-10-17 13:25:14 +02004281 errcode |= ssl_sock_put_ckch_into_ctx(path, ckch, ctx, err);
4282 if (errcode & ERR_CODE)
William Lallemand614ca0d2019-10-07 13:52:11 +02004283 goto error;
William Lallemand614ca0d2019-10-07 13:52:11 +02004284
4285 ckch_inst = ckch_inst_new();
4286 if (!ckch_inst) {
4287 memprintf(err, "%sunable to allocate SSL context for cert '%s'.\n",
4288 err && *err ? *err : "", path);
Emeric Brun054563d2019-10-17 13:16:58 +02004289 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemandd9199372019-10-04 15:37:05 +02004290 goto error;
William Lallemandc9402072019-05-15 15:33:54 +02004291 }
4292
William Lallemand36b84632019-07-18 19:28:17 +02004293 pkey = X509_get_pubkey(ckch->cert);
Emmanuel Hocdet05942112017-02-20 16:11:50 +01004294 if (pkey) {
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02004295 kinfo.bits = EVP_PKEY_bits(pkey);
Emmanuel Hocdet05942112017-02-20 16:11:50 +01004296 switch(EVP_PKEY_base_id(pkey)) {
4297 case EVP_PKEY_RSA:
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02004298 kinfo.sig = TLSEXT_signature_rsa;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01004299 break;
4300 case EVP_PKEY_EC:
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02004301 kinfo.sig = TLSEXT_signature_ecdsa;
4302 break;
4303 case EVP_PKEY_DSA:
4304 kinfo.sig = TLSEXT_signature_dsa;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01004305 break;
4306 }
4307 EVP_PKEY_free(pkey);
4308 }
4309
Emeric Brun50bcecc2013-04-22 13:05:23 +02004310 if (fcount) {
William Lallemandfe49bb32019-10-03 23:46:33 +02004311 while (fcount--) {
William Lallemand1d29c742019-10-04 00:53:29 +02004312 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 +02004313 if (order < 0) {
4314 memprintf(err, "%sunable to create a sni context.\n", err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02004315 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemandd9199372019-10-04 15:37:05 +02004316 goto error;
William Lallemandfe49bb32019-10-03 23:46:33 +02004317 }
4318 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004319 }
4320 else {
Emeric Brunfc0421f2012-09-07 17:30:07 +02004321#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
William Lallemand36b84632019-07-18 19:28:17 +02004322 names = X509_get_ext_d2i(ckch->cert, NID_subject_alt_name, NULL, NULL);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004323 if (names) {
4324 for (i = 0; i < sk_GENERAL_NAME_num(names); i++) {
4325 GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i);
4326 if (name->type == GEN_DNS) {
4327 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
William Lallemand1d29c742019-10-04 00:53:29 +02004328 order = ckch_inst_add_cert_sni(ctx, ckch_inst, bind_conf, ssl_conf, kinfo, str, order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004329 OPENSSL_free(str);
William Lallemandfe49bb32019-10-03 23:46:33 +02004330 if (order < 0) {
4331 memprintf(err, "%sunable to create a sni context.\n", err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02004332 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemandd9199372019-10-04 15:37:05 +02004333 goto error;
William Lallemandfe49bb32019-10-03 23:46:33 +02004334 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004335 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004336 }
4337 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004338 sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004339 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004340#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
William Lallemand36b84632019-07-18 19:28:17 +02004341 xname = X509_get_subject_name(ckch->cert);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004342 i = -1;
4343 while ((i = X509_NAME_get_index_by_NID(xname, NID_commonName, i)) != -1) {
4344 X509_NAME_ENTRY *entry = X509_NAME_get_entry(xname, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02004345 ASN1_STRING *value;
4346
4347 value = X509_NAME_ENTRY_get_data(entry);
4348 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
William Lallemand1d29c742019-10-04 00:53:29 +02004349 order = ckch_inst_add_cert_sni(ctx, ckch_inst, bind_conf, ssl_conf, kinfo, str, order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004350 OPENSSL_free(str);
William Lallemandfe49bb32019-10-03 23:46:33 +02004351 if (order < 0) {
4352 memprintf(err, "%sunable to create a sni context.\n", err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02004353 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemandd9199372019-10-04 15:37:05 +02004354 goto error;
William Lallemandfe49bb32019-10-03 23:46:33 +02004355 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004356 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004357 }
4358 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004359 /* we must not free the SSL_CTX anymore below, since it's already in
4360 * the tree, so it will be discovered and cleaned in time.
4361 */
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02004362
Emeric Brunfc0421f2012-09-07 17:30:07 +02004363#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004364 if (bind_conf->default_ctx) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02004365 memprintf(err, "%sthis version of openssl cannot load multiple SSL certificates.\n",
4366 err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02004367 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemandd9199372019-10-04 15:37:05 +02004368 goto error;
Emeric Brunfc0421f2012-09-07 17:30:07 +02004369 }
4370#endif
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004371 if (!bind_conf->default_ctx) {
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004372 bind_conf->default_ctx = ctx;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004373 bind_conf->default_ssl_conf = ssl_conf;
William Lallemand21724f02019-11-04 17:56:13 +01004374 ckch_inst->is_default = 1;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004375 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004376
William Lallemand9117de92019-10-04 00:29:42 +02004377 /* everything succeed, the ckch instance can be used */
4378 ckch_inst->bind_conf = bind_conf;
William Lallemand150bfa82019-09-19 17:12:49 +02004379 ckch_inst->ssl_conf = ssl_conf;
William Lallemandcfca1422020-03-05 10:17:47 +01004380 ckch_inst->ckch_store = ckchs;
William Lallemand67630162020-03-09 16:56:39 +01004381 ckch_inst->filters = !!fcount;
William Lallemand9117de92019-10-04 00:29:42 +02004382
Emeric Brun054563d2019-10-17 13:16:58 +02004383 *ckchi = ckch_inst;
4384 return errcode;
William Lallemandd9199372019-10-04 15:37:05 +02004385
4386error:
4387 /* free the allocated sni_ctxs */
William Lallemand614ca0d2019-10-07 13:52:11 +02004388 if (ckch_inst) {
William Lallemandd9199372019-10-04 15:37:05 +02004389 struct sni_ctx *sc0, *sc0b;
4390
4391 list_for_each_entry_safe(sc0, sc0b, &ckch_inst->sni_ctx, by_ckch_inst) {
4392
4393 ebmb_delete(&sc0->name);
4394 LIST_DEL(&sc0->by_ckch_inst);
4395 free(sc0);
4396 }
William Lallemand614ca0d2019-10-07 13:52:11 +02004397 free(ckch_inst);
4398 ckch_inst = NULL;
William Lallemandd9199372019-10-04 15:37:05 +02004399 }
4400 /* We only created 1 SSL_CTX so we can free it there */
4401 SSL_CTX_free(ctx);
4402
Emeric Brun054563d2019-10-17 13:16:58 +02004403 return errcode;
Emeric Brunfc0421f2012-09-07 17:30:07 +02004404}
4405
Willy Tarreau8c5414a2019-10-16 17:06:25 +02004406/* Returns a set of ERR_* flags possibly with an error in <err>. */
William Lallemand614ca0d2019-10-07 13:52:11 +02004407static int ssl_sock_load_ckchs(const char *path, struct ckch_store *ckchs,
4408 struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
4409 char **sni_filter, int fcount, char **err)
4410{
4411 struct ckch_inst *ckch_inst = NULL;
Emeric Brun054563d2019-10-17 13:16:58 +02004412 int errcode = 0;
William Lallemand614ca0d2019-10-07 13:52:11 +02004413
4414 /* we found the ckchs in the tree, we can use it directly */
4415 if (ckchs->multi)
Emeric Brun054563d2019-10-17 13:16:58 +02004416 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 +02004417 else
Emeric Brun054563d2019-10-17 13:16:58 +02004418 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 +02004419
Emeric Brun054563d2019-10-17 13:16:58 +02004420 if (errcode & ERR_CODE)
4421 return errcode;
William Lallemand614ca0d2019-10-07 13:52:11 +02004422
4423 ssl_sock_load_cert_sni(ckch_inst, bind_conf);
4424
4425 /* succeed, add the instance to the ckch_store's list of instance */
4426 LIST_ADDQ(&ckchs->ckch_inst, &ckch_inst->by_ckchs);
Emeric Brun054563d2019-10-17 13:16:58 +02004427 return errcode;
William Lallemand614ca0d2019-10-07 13:52:11 +02004428}
4429
William Lallemand2d232c22020-03-06 22:12:35 +01004430/* Read a directory and open its certificates
4431 * Returns a set of ERR_* flags possibly with an error in <err>. */
4432static int ssl_sock_load_cert_dir(char *path, struct bind_conf *bind_conf, char **err)
Emeric Brunfc0421f2012-09-07 17:30:07 +02004433{
Cyril Bonté3180f7b2015-01-25 00:16:08 +01004434 struct dirent **de_list;
4435 int i, n;
Emeric Brunfc0421f2012-09-07 17:30:07 +02004436 struct stat buf;
Willy Tarreauee2663b2012-12-06 11:36:59 +01004437 char *end;
4438 char fp[MAXPATHLEN+1];
Emeric Brunfc0421f2012-09-07 17:30:07 +02004439 int cfgerr = 0;
William Lallemande3af8fb2019-10-08 11:36:53 +02004440 struct ckch_store *ckchs;
Willy Tarreau9a1ab082019-05-09 13:26:41 +02004441#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
yanbzhu63ea8462015-12-09 13:35:14 -05004442 int is_bundle;
4443 int j;
4444#endif
Willy Tarreaubbc91962019-10-16 16:42:19 +02004445
William Lallemand2d232c22020-03-06 22:12:35 +01004446 /* strip trailing slashes, including first one */
4447 for (end = path + strlen(path) - 1; end >= path && *end == '/'; end--)
4448 *end = 0;
Emeric Brunfc0421f2012-09-07 17:30:07 +02004449
William Lallemand2d232c22020-03-06 22:12:35 +01004450 n = scandir(path, &de_list, 0, alphasort);
4451 if (n < 0) {
4452 memprintf(err, "%sunable to scan directory '%s' : %s.\n",
4453 err && *err ? *err : "", path, strerror(errno));
4454 cfgerr |= ERR_ALERT | ERR_FATAL;
4455 }
4456 else {
4457 for (i = 0; i < n; i++) {
4458 struct dirent *de = de_list[i];
Emeric Brun2aab7222014-06-18 18:15:09 +02004459
William Lallemand2d232c22020-03-06 22:12:35 +01004460 end = strrchr(de->d_name, '.');
4461 if (end && (!strcmp(end, ".issuer") || !strcmp(end, ".ocsp") || !strcmp(end, ".sctl") || !strcmp(end, ".key")))
4462 goto ignore_entry;
Cyril Bonté3180f7b2015-01-25 00:16:08 +01004463
William Lallemand2d232c22020-03-06 22:12:35 +01004464 snprintf(fp, sizeof(fp), "%s/%s", path, de->d_name);
4465 if (stat(fp, &buf) != 0) {
4466 memprintf(err, "%sunable to stat SSL certificate from file '%s' : %s.\n",
4467 err && *err ? *err : "", fp, strerror(errno));
4468 cfgerr |= ERR_ALERT | ERR_FATAL;
4469 goto ignore_entry;
4470 }
4471 if (!S_ISREG(buf.st_mode))
4472 goto ignore_entry;
yanbzhu63ea8462015-12-09 13:35:14 -05004473
Willy Tarreau9a1ab082019-05-09 13:26:41 +02004474#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
William Lallemand2d232c22020-03-06 22:12:35 +01004475 is_bundle = 0;
4476 /* Check if current entry in directory is part of a multi-cert bundle */
yanbzhu63ea8462015-12-09 13:35:14 -05004477
William Lallemand2d232c22020-03-06 22:12:35 +01004478 if ((global_ssl.extra_files & SSL_GF_BUNDLE) && end) {
4479 for (j = 0; j < SSL_SOCK_NUM_KEYTYPES; j++) {
4480 if (!strcmp(end + 1, SSL_SOCK_KEYTYPE_NAMES[j])) {
4481 is_bundle = 1;
4482 break;
yanbzhu63ea8462015-12-09 13:35:14 -05004483 }
William Lallemand2d232c22020-03-06 22:12:35 +01004484 }
yanbzhu63ea8462015-12-09 13:35:14 -05004485
William Lallemand2d232c22020-03-06 22:12:35 +01004486 if (is_bundle) {
4487 int dp_len;
yanbzhu63ea8462015-12-09 13:35:14 -05004488
William Lallemand2d232c22020-03-06 22:12:35 +01004489 dp_len = end - de->d_name;
yanbzhu63ea8462015-12-09 13:35:14 -05004490
William Lallemand2d232c22020-03-06 22:12:35 +01004491 /* increment i and free de until we get to a non-bundle cert
4492 * Note here that we look at de_list[i + 1] before freeing de
4493 * this is important since ignore_entry will free de. This also
4494 * guarantees that de->d_name continues to hold the same prefix.
4495 */
4496 while (i + 1 < n && !strncmp(de_list[i + 1]->d_name, de->d_name, dp_len)) {
4497 free(de);
4498 i++;
4499 de = de_list[i];
yanbzhu63ea8462015-12-09 13:35:14 -05004500 }
William Lallemand2d232c22020-03-06 22:12:35 +01004501
4502 snprintf(fp, sizeof(fp), "%s/%.*s", path, dp_len, de->d_name);
4503 if ((ckchs = ckchs_lookup(fp)) == NULL)
4504 ckchs = ckchs_load_cert_file(fp, 1, err);
4505 if (!ckchs)
4506 cfgerr |= ERR_ALERT | ERR_FATAL;
4507 else
4508 cfgerr |= ssl_sock_load_ckchs(path, ckchs, bind_conf, NULL, NULL, 0, err);
4509 /* Successfully processed the bundle */
4510 goto ignore_entry;
yanbzhu63ea8462015-12-09 13:35:14 -05004511 }
William Lallemand2d232c22020-03-06 22:12:35 +01004512 }
yanbzhu63ea8462015-12-09 13:35:14 -05004513
4514#endif
William Lallemand2d232c22020-03-06 22:12:35 +01004515 if ((ckchs = ckchs_lookup(fp)) == NULL)
4516 ckchs = ckchs_load_cert_file(fp, 0, err);
4517 if (!ckchs)
4518 cfgerr |= ERR_ALERT | ERR_FATAL;
4519 else
4520 cfgerr |= ssl_sock_load_ckchs(path, ckchs, bind_conf, NULL, NULL, 0, err);
William Lallemand36b84632019-07-18 19:28:17 +02004521
yanbzhu08ce6ab2015-12-02 13:01:29 -05004522ignore_entry:
William Lallemand2d232c22020-03-06 22:12:35 +01004523 free(de);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004524 }
William Lallemand2d232c22020-03-06 22:12:35 +01004525 free(de_list);
4526 }
4527 return cfgerr;
4528}
yanbzhu08ce6ab2015-12-02 13:01:29 -05004529
William Lallemand2d232c22020-03-06 22:12:35 +01004530/* Returns a set of ERR_* flags possibly with an error in <err>. */
4531int ssl_sock_load_cert(char *path, struct bind_conf *bind_conf, char **err)
4532{
4533 struct stat buf;
4534 char fp[MAXPATHLEN+1];
4535 int cfgerr = 0;
4536 struct ckch_store *ckchs;
Willy Tarreaubbc91962019-10-16 16:42:19 +02004537
William Lallemand2d232c22020-03-06 22:12:35 +01004538 if ((ckchs = ckchs_lookup(path))) {
4539 /* we found the ckchs in the tree, we can use it directly */
4540 return ssl_sock_load_ckchs(path, ckchs, bind_conf, NULL, NULL, 0, err);
4541 }
4542 if (stat(path, &buf) == 0) {
4543 if (S_ISDIR(buf.st_mode) == 0) {
4544 ckchs = ckchs_load_cert_file(path, 0, err);
4545 if (!ckchs)
4546 return ERR_ALERT | ERR_FATAL;
4547
4548 return ssl_sock_load_ckchs(path, ckchs, bind_conf, NULL, NULL, 0, err);
4549 } else {
4550 return ssl_sock_load_cert_dir(path, bind_conf, err);
4551 }
4552 } else {
4553 /* stat failed, could be a bundle */
William Lallemand3af48e72020-02-03 17:15:52 +01004554 if (global_ssl.extra_files & SSL_GF_BUNDLE) {
4555 /* try to load a bundle if it is permitted */
4556 ckchs = ckchs_load_cert_file(path, 1, err);
4557 if (!ckchs)
4558 return ERR_ALERT | ERR_FATAL;
4559 cfgerr |= ssl_sock_load_ckchs(path, ckchs, bind_conf, NULL, NULL, 0, err);
4560 } else {
4561 memprintf(err, "%sunable to stat SSL certificate from file '%s' : %s.\n",
4562 err && *err ? *err : "", fp, strerror(errno));
4563 cfgerr |= ERR_ALERT | ERR_FATAL;
4564 }
4565 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05004566
Emeric Brunfc0421f2012-09-07 17:30:07 +02004567 return cfgerr;
4568}
4569
Thierry Fournier383085f2013-01-24 14:15:43 +01004570/* Make sure openssl opens /dev/urandom before the chroot. The work is only
4571 * done once. Zero is returned if the operation fails. No error is returned
4572 * if the random is said as not implemented, because we expect that openssl
4573 * will use another method once needed.
4574 */
4575static int ssl_initialize_random()
4576{
4577 unsigned char random;
4578 static int random_initialized = 0;
4579
4580 if (!random_initialized && RAND_bytes(&random, 1) != 0)
4581 random_initialized = 1;
4582
4583 return random_initialized;
4584}
4585
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004586/* release ssl bind conf */
4587void ssl_sock_free_ssl_conf(struct ssl_bind_conf *conf)
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004588{
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004589 if (conf) {
Bernard Spil13c53f82018-02-15 13:34:58 +01004590#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004591 free(conf->npn_str);
4592 conf->npn_str = NULL;
4593#endif
4594#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
4595 free(conf->alpn_str);
4596 conf->alpn_str = NULL;
4597#endif
4598 free(conf->ca_file);
4599 conf->ca_file = NULL;
Emmanuel Hocdet842e94e2019-12-16 16:39:17 +01004600 free(conf->ca_verify_file);
4601 conf->ca_verify_file = NULL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004602 free(conf->crl_file);
4603 conf->crl_file = NULL;
4604 free(conf->ciphers);
4605 conf->ciphers = NULL;
Emmanuel Hocdet839af572019-05-14 16:27:35 +02004606#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02004607 free(conf->ciphersuites);
4608 conf->ciphersuites = NULL;
4609#endif
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004610 free(conf->curves);
4611 conf->curves = NULL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004612 free(conf->ecdhe);
4613 conf->ecdhe = NULL;
4614 }
4615}
4616
Willy Tarreaubbc91962019-10-16 16:42:19 +02004617/* Returns a set of ERR_* flags possibly with an error in <err>. */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004618int ssl_sock_load_cert_list_file(char *file, struct bind_conf *bind_conf, struct proxy *curproxy, char **err)
4619{
4620 char thisline[CRT_LINESIZE];
4621 char path[MAXPATHLEN+1];
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004622 FILE *f;
yanbzhu1b04e5b2015-12-02 13:54:14 -05004623 struct stat buf;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004624 int linenum = 0;
4625 int cfgerr = 0;
William Lallemande3af8fb2019-10-08 11:36:53 +02004626 struct ckch_store *ckchs;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004627
Willy Tarreauad1731d2013-04-02 17:35:58 +02004628 if ((f = fopen(file, "r")) == NULL) {
4629 memprintf(err, "cannot open file '%s' : %s", file, strerror(errno));
Willy Tarreaubbc91962019-10-16 16:42:19 +02004630 return ERR_ALERT | ERR_FATAL;
Willy Tarreauad1731d2013-04-02 17:35:58 +02004631 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004632
4633 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004634 int arg, newarg, cur_arg, i, ssl_b = 0, ssl_e = 0;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004635 char *end;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004636 char *args[MAX_CRT_ARGS + 1];
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004637 char *line = thisline;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004638 char *crt_path;
4639 struct ssl_bind_conf *ssl_conf = NULL;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004640
4641 linenum++;
4642 end = line + strlen(line);
4643 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
4644 /* Check if we reached the limit and the last char is not \n.
4645 * Watch out for the last line without the terminating '\n'!
4646 */
Willy Tarreauad1731d2013-04-02 17:35:58 +02004647 memprintf(err, "line %d too long in file '%s', limit is %d characters",
4648 linenum, file, (int)sizeof(thisline)-1);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004649 cfgerr |= ERR_ALERT | ERR_FATAL;
Willy Tarreauad1731d2013-04-02 17:35:58 +02004650 break;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004651 }
4652
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004653 arg = 0;
Emeric Brun50bcecc2013-04-22 13:05:23 +02004654 newarg = 1;
4655 while (*line) {
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004656 if (*line == '#' || *line == '\n' || *line == '\r') {
4657 /* end of string, end of loop */
4658 *line = 0;
4659 break;
Willy Tarreauded15b72020-02-25 07:51:59 +01004660 } else if (isspace((unsigned char)*line)) {
Emeric Brun50bcecc2013-04-22 13:05:23 +02004661 newarg = 1;
4662 *line = 0;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004663 } else if (*line == '[') {
4664 if (ssl_b) {
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;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004667 break;
4668 }
4669 if (!arg) {
4670 memprintf(err, "file must start with a cert on 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_b = arg;
4675 newarg = 1;
4676 *line = 0;
4677 } else if (*line == ']') {
4678 if (ssl_e) {
4679 memprintf(err, "too many ']' on line %d in file '%s'.", linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004680 cfgerr |= ERR_ALERT | ERR_FATAL;
Emeric Brun50bcecc2013-04-22 13:05:23 +02004681 break;
4682 }
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004683 if (!ssl_b) {
4684 memprintf(err, "missing '[' in line %d in file '%s'.", linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004685 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004686 break;
4687 }
4688 ssl_e = arg;
4689 newarg = 1;
4690 *line = 0;
4691 } else if (newarg) {
4692 if (arg == MAX_CRT_ARGS) {
4693 memprintf(err, "too many args on line %d in file '%s'.", linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004694 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004695 break;
4696 }
Emeric Brun50bcecc2013-04-22 13:05:23 +02004697 newarg = 0;
4698 args[arg++] = line;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004699 }
Emeric Brun50bcecc2013-04-22 13:05:23 +02004700 line++;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004701 }
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02004702 if (cfgerr)
4703 break;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004704 args[arg++] = line;
Willy Tarreauad1731d2013-04-02 17:35:58 +02004705
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004706 /* empty line */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004707 if (!*args[0])
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004708 continue;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004709
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004710 crt_path = args[0];
4711 if (*crt_path != '/' && global_ssl.crt_base) {
4712 if ((strlen(global_ssl.crt_base) + 1 + strlen(crt_path)) > MAXPATHLEN) {
4713 memprintf(err, "'%s' : path too long on line %d in file '%s'",
4714 crt_path, linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004715 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004716 break;
4717 }
4718 snprintf(path, sizeof(path), "%s/%s", global_ssl.crt_base, crt_path);
4719 crt_path = path;
4720 }
4721
4722 ssl_conf = calloc(1, sizeof *ssl_conf);
4723 cur_arg = ssl_b ? ssl_b : 1;
4724 while (cur_arg < ssl_e) {
4725 newarg = 0;
4726 for (i = 0; ssl_bind_kws[i].kw != NULL; i++) {
4727 if (strcmp(ssl_bind_kws[i].kw, args[cur_arg]) == 0) {
4728 newarg = 1;
Willy Tarreaubbc91962019-10-16 16:42:19 +02004729 cfgerr |= ssl_bind_kws[i].parse(args, cur_arg, curproxy, ssl_conf, err);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004730 if (cur_arg + 1 + ssl_bind_kws[i].skip > ssl_e) {
4731 memprintf(err, "ssl args out of '[]' for %s on line %d in file '%s'",
4732 args[cur_arg], linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004733 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004734 }
4735 cur_arg += 1 + ssl_bind_kws[i].skip;
4736 break;
4737 }
4738 }
4739 if (!cfgerr && !newarg) {
4740 memprintf(err, "unknown ssl keyword %s on line %d in file '%s'.",
4741 args[cur_arg], linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004742 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004743 break;
4744 }
4745 }
Willy Tarreaubbc91962019-10-16 16:42:19 +02004746
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004747 if (cfgerr) {
4748 ssl_sock_free_ssl_conf(ssl_conf);
4749 free(ssl_conf);
4750 ssl_conf = NULL;
4751 break;
4752 }
4753
William Lallemande3af8fb2019-10-08 11:36:53 +02004754 if ((ckchs = ckchs_lookup(crt_path)) == NULL) {
William Lallemandeed4bf22019-10-10 11:38:13 +02004755 if (stat(crt_path, &buf) == 0)
William Lallemande3af8fb2019-10-08 11:36:53 +02004756 ckchs = ckchs_load_cert_file(crt_path, 0, err);
Emmanuel Hocdet1503e052019-07-31 18:30:33 +02004757 else
William Lallemande3af8fb2019-10-08 11:36:53 +02004758 ckchs = ckchs_load_cert_file(crt_path, 1, err);
yanbzhu1b04e5b2015-12-02 13:54:14 -05004759 }
4760
Willy Tarreau8c5414a2019-10-16 17:06:25 +02004761 if (!ckchs)
Willy Tarreaubbc91962019-10-16 16:42:19 +02004762 cfgerr |= ERR_ALERT | ERR_FATAL;
Willy Tarreau8c5414a2019-10-16 17:06:25 +02004763 else
4764 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 +02004765
Willy Tarreauad1731d2013-04-02 17:35:58 +02004766 if (cfgerr) {
4767 memprintf(err, "error processing line %d in file '%s' : %s", linenum, file, *err);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004768 break;
Willy Tarreauad1731d2013-04-02 17:35:58 +02004769 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004770 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004771 fclose(f);
4772 return cfgerr;
4773}
4774
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004775/* Create an initial CTX used to start the SSL connection before switchctx */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004776static int
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004777ssl_sock_initial_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02004778{
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004779 SSL_CTX *ctx = NULL;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004780 long options =
Emeric Brunfc0421f2012-09-07 17:30:07 +02004781 SSL_OP_ALL | /* all known workarounds for bugs */
4782 SSL_OP_NO_SSLv2 |
4783 SSL_OP_NO_COMPRESSION |
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02004784 SSL_OP_SINGLE_DH_USE |
Emeric Brun2b58d042012-09-20 17:10:03 +02004785 SSL_OP_SINGLE_ECDH_USE |
Emeric Brun3c4bc6e2012-10-04 18:44:19 +02004786 SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION |
Lukas Tribus926594f2018-05-18 17:55:57 +02004787 SSL_OP_PRIORITIZE_CHACHA |
Emeric Brun3c4bc6e2012-10-04 18:44:19 +02004788 SSL_OP_CIPHER_SERVER_PREFERENCE;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004789 long mode =
Emeric Brunfc0421f2012-09-07 17:30:07 +02004790 SSL_MODE_ENABLE_PARTIAL_WRITE |
4791 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
Willy Tarreau396a1862014-11-13 14:06:52 +01004792 SSL_MODE_RELEASE_BUFFERS |
4793 SSL_MODE_SMALL_BUFFERS;
Emmanuel Hocdet43664762017-08-09 18:26:20 +02004794 struct tls_version_filter *conf_ssl_methods = &bind_conf->ssl_conf.ssl_methods;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004795 int i, min, max, hole;
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004796 int flags = MC_SSL_O_ALL;
4797 int cfgerr = 0;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004798
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004799 ctx = SSL_CTX_new(SSLv23_server_method());
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004800 bind_conf->initial_ctx = ctx;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004801
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004802 if (conf_ssl_methods->flags && (conf_ssl_methods->min || conf_ssl_methods->max))
Christopher Faulet767a84b2017-11-24 16:50:31 +01004803 ha_warning("Proxy '%s': no-sslv3/no-tlsv1x are ignored for bind '%s' at [%s:%d]. "
4804 "Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
4805 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004806 else
4807 flags = conf_ssl_methods->flags;
4808
Emmanuel Hocdetbd695fe2017-05-15 15:53:41 +02004809 min = conf_ssl_methods->min;
4810 max = conf_ssl_methods->max;
4811 /* start with TLSv10 to remove SSLv3 per default */
4812 if (!min && (!max || max >= CONF_TLSV10))
4813 min = CONF_TLSV10;
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004814 /* Real min and max should be determinate with configuration and openssl's capabilities */
Emmanuel Hocdetbd695fe2017-05-15 15:53:41 +02004815 if (min)
4816 flags |= (methodVersions[min].flag - 1);
4817 if (max)
4818 flags |= ~((methodVersions[max].flag << 1) - 1);
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004819 /* find min, max and holes */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004820 min = max = CONF_TLSV_NONE;
4821 hole = 0;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004822 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004823 /* version is in openssl && version not disable in configuration */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004824 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004825 if (min) {
4826 if (hole) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004827 ha_warning("Proxy '%s': SSL/TLS versions range not contiguous for bind '%s' at [%s:%d]. "
4828 "Hole find for %s. Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
4829 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line,
4830 methodVersions[hole].name);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004831 hole = 0;
4832 }
4833 max = i;
4834 }
4835 else {
4836 min = max = i;
4837 }
4838 }
4839 else {
4840 if (min)
4841 hole = i;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004842 }
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004843 if (!min) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004844 ha_alert("Proxy '%s': all SSL/TLS versions are disabled for bind '%s' at [%s:%d].\n",
4845 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004846 cfgerr += 1;
4847 }
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02004848 /* save real min/max in bind_conf */
4849 conf_ssl_methods->min = min;
4850 conf_ssl_methods->max = max;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004851
Willy Tarreau9a1ab082019-05-09 13:26:41 +02004852#if (HA_OPENSSL_VERSION_NUMBER < 0x1010000fL)
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004853 /* Keep force-xxx implementation as it is in older haproxy. It's a
Joseph Herlant017b3da2018-11-15 09:07:59 -08004854 precautionary measure to avoid any surprise with older openssl version. */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004855 if (min == max)
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004856 methodVersions[min].ctx_set_version(ctx, SET_SERVER);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004857 else
4858 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
4859 if (flags & methodVersions[i].flag)
4860 options |= methodVersions[i].option;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004861#else /* openssl >= 1.1.0 */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004862 /* set the max_version is required to cap TLS version or activate new TLS (v1.3) */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004863 methodVersions[min].ctx_set_version(ctx, SET_MIN);
4864 methodVersions[max].ctx_set_version(ctx, SET_MAX);
Emeric Brunfa5c5c82017-04-28 16:19:51 +02004865#endif
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004866
4867 if (bind_conf->ssl_options & BC_SSL_O_NO_TLS_TICKETS)
4868 options |= SSL_OP_NO_TICKET;
4869 if (bind_conf->ssl_options & BC_SSL_O_PREF_CLIE_CIPH)
4870 options &= ~SSL_OP_CIPHER_SERVER_PREFERENCE;
Dirkjan Bussink526894f2019-01-21 09:35:03 -08004871
4872#ifdef SSL_OP_NO_RENEGOTIATION
4873 options |= SSL_OP_NO_RENEGOTIATION;
4874#endif
4875
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004876 SSL_CTX_set_options(ctx, options);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004877
Willy Tarreau5db847a2019-05-09 14:13:35 +02004878#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004879 if (global_ssl.async)
4880 mode |= SSL_MODE_ASYNC;
4881#endif
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004882 SSL_CTX_set_mode(ctx, mode);
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004883 if (global_ssl.life_time)
4884 SSL_CTX_set_timeout(ctx, global_ssl.life_time);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004885
4886#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
4887#ifdef OPENSSL_IS_BORINGSSL
4888 SSL_CTX_set_select_certificate_cb(ctx, ssl_sock_switchctx_cbk);
4889 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_err_cbk);
Ilya Shipitsine9ff8992020-01-19 12:20:14 +05004890#elif defined(SSL_OP_NO_ANTI_REPLAY)
Olivier Houchard545989f2019-12-17 15:39:54 +01004891 if (bind_conf->ssl_conf.early_data)
Olivier Houchard51088ce2019-01-02 18:46:41 +01004892 SSL_CTX_set_options(ctx, SSL_OP_NO_ANTI_REPLAY);
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02004893 SSL_CTX_set_client_hello_cb(ctx, ssl_sock_switchctx_cbk, NULL);
4894 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_err_cbk);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004895#else
4896 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_cbk);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004897#endif
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02004898 SSL_CTX_set_tlsext_servername_arg(ctx, bind_conf);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004899#endif
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004900 return cfgerr;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004901}
4902
William Lallemand4f45bb92017-10-30 20:08:51 +01004903
4904static inline void sh_ssl_sess_free_blocks(struct shared_block *first, struct shared_block *block)
4905{
4906 if (first == block) {
4907 struct sh_ssl_sess_hdr *sh_ssl_sess = (struct sh_ssl_sess_hdr *)first->data;
4908 if (first->len > 0)
4909 sh_ssl_sess_tree_delete(sh_ssl_sess);
4910 }
4911}
4912
4913/* return first block from sh_ssl_sess */
4914static inline struct shared_block *sh_ssl_sess_first_block(struct sh_ssl_sess_hdr *sh_ssl_sess)
4915{
4916 return (struct shared_block *)((unsigned char *)sh_ssl_sess - ((struct shared_block *)NULL)->data);
4917
4918}
4919
4920/* store a session into the cache
4921 * s_id : session id padded with zero to SSL_MAX_SSL_SESSION_ID_LENGTH
4922 * data: asn1 encoded session
4923 * data_len: asn1 encoded session length
4924 * Returns 1 id session was stored (else 0)
4925 */
4926static int sh_ssl_sess_store(unsigned char *s_id, unsigned char *data, int data_len)
4927{
4928 struct shared_block *first;
4929 struct sh_ssl_sess_hdr *sh_ssl_sess, *oldsh_ssl_sess;
4930
Frédéric Lécaille0bec8072018-10-22 17:55:57 +02004931 first = shctx_row_reserve_hot(ssl_shctx, NULL, data_len + sizeof(struct sh_ssl_sess_hdr));
William Lallemand4f45bb92017-10-30 20:08:51 +01004932 if (!first) {
4933 /* Could not retrieve enough free blocks to store that session */
4934 return 0;
4935 }
4936
4937 /* STORE the key in the first elem */
4938 sh_ssl_sess = (struct sh_ssl_sess_hdr *)first->data;
4939 memcpy(sh_ssl_sess->key_data, s_id, SSL_MAX_SSL_SESSION_ID_LENGTH);
4940 first->len = sizeof(struct sh_ssl_sess_hdr);
4941
4942 /* it returns the already existing node
4943 or current node if none, never returns null */
4944 oldsh_ssl_sess = sh_ssl_sess_tree_insert(sh_ssl_sess);
4945 if (oldsh_ssl_sess != sh_ssl_sess) {
4946 /* NOTE: Row couldn't be in use because we lock read & write function */
4947 /* release the reserved row */
4948 shctx_row_dec_hot(ssl_shctx, first);
4949 /* replace the previous session already in the tree */
4950 sh_ssl_sess = oldsh_ssl_sess;
4951 /* ignore the previous session data, only use the header */
4952 first = sh_ssl_sess_first_block(sh_ssl_sess);
4953 shctx_row_inc_hot(ssl_shctx, first);
4954 first->len = sizeof(struct sh_ssl_sess_hdr);
4955 }
4956
Frédéric Lécaille0bec8072018-10-22 17:55:57 +02004957 if (shctx_row_data_append(ssl_shctx, first, NULL, data, data_len) < 0) {
William Lallemand99b90af2018-01-03 19:15:51 +01004958 shctx_row_dec_hot(ssl_shctx, first);
William Lallemand4f45bb92017-10-30 20:08:51 +01004959 return 0;
William Lallemand99b90af2018-01-03 19:15:51 +01004960 }
4961
4962 shctx_row_dec_hot(ssl_shctx, first);
William Lallemand4f45bb92017-10-30 20:08:51 +01004963
4964 return 1;
4965}
William Lallemanded0b5ad2017-10-30 19:36:36 +01004966
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004967/* SSL callback used when a new session is created while connecting to a server */
4968static int ssl_sess_new_srv_cb(SSL *ssl, SSL_SESSION *sess)
4969{
Thierry FOURNIER28962c92018-06-17 21:37:05 +02004970 struct connection *conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Olivier Houcharde6060c52017-11-16 17:42:52 +01004971 struct server *s;
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004972
Willy Tarreau07d94e42018-09-20 10:57:52 +02004973 s = __objt_server(conn->target);
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004974
Olivier Houcharde6060c52017-11-16 17:42:52 +01004975 if (!(s->ssl_ctx.options & SRV_SSL_O_NO_REUSE)) {
4976 int len;
4977 unsigned char *ptr;
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004978
Olivier Houcharde6060c52017-11-16 17:42:52 +01004979 len = i2d_SSL_SESSION(sess, NULL);
4980 if (s->ssl_ctx.reused_sess[tid].ptr && s->ssl_ctx.reused_sess[tid].allocated_size >= len) {
4981 ptr = s->ssl_ctx.reused_sess[tid].ptr;
4982 } else {
4983 free(s->ssl_ctx.reused_sess[tid].ptr);
4984 ptr = s->ssl_ctx.reused_sess[tid].ptr = malloc(len);
4985 s->ssl_ctx.reused_sess[tid].allocated_size = len;
4986 }
4987 if (s->ssl_ctx.reused_sess[tid].ptr) {
4988 s->ssl_ctx.reused_sess[tid].size = i2d_SSL_SESSION(sess,
4989 &ptr);
4990 }
4991 } else {
4992 free(s->ssl_ctx.reused_sess[tid].ptr);
4993 s->ssl_ctx.reused_sess[tid].ptr = NULL;
4994 }
4995
4996 return 0;
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004997}
4998
Olivier Houcharde6060c52017-11-16 17:42:52 +01004999
William Lallemanded0b5ad2017-10-30 19:36:36 +01005000/* SSL callback used on new session creation */
William Lallemand4f45bb92017-10-30 20:08:51 +01005001int sh_ssl_sess_new_cb(SSL *ssl, SSL_SESSION *sess)
William Lallemanded0b5ad2017-10-30 19:36:36 +01005002{
5003 unsigned char encsess[SHSESS_MAX_DATA_LEN]; /* encoded session */
5004 unsigned char encid[SSL_MAX_SSL_SESSION_ID_LENGTH]; /* encoded id */
5005 unsigned char *p;
5006 int data_len;
Emeric Bruneb469652019-10-08 18:27:37 +02005007 unsigned int sid_length;
William Lallemanded0b5ad2017-10-30 19:36:36 +01005008 const unsigned char *sid_data;
William Lallemanded0b5ad2017-10-30 19:36:36 +01005009
5010 /* Session id is already stored in to key and session id is known
5011 * so we dont store it to keep size.
Emeric Bruneb469652019-10-08 18:27:37 +02005012 * note: SSL_SESSION_set1_id is using
5013 * a memcpy so we need to use a different pointer
5014 * than sid_data or sid_ctx_data to avoid valgrind
5015 * complaining.
William Lallemanded0b5ad2017-10-30 19:36:36 +01005016 */
5017
5018 sid_data = SSL_SESSION_get_id(sess, &sid_length);
Emeric Bruneb469652019-10-08 18:27:37 +02005019
5020 /* copy value in an other buffer */
5021 memcpy(encid, sid_data, sid_length);
5022
5023 /* pad with 0 */
5024 if (sid_length < SSL_MAX_SSL_SESSION_ID_LENGTH)
5025 memset(encid + sid_length, 0, SSL_MAX_SSL_SESSION_ID_LENGTH-sid_length);
5026
5027 /* force length to zero to avoid ASN1 encoding */
5028 SSL_SESSION_set1_id(sess, encid, 0);
5029
5030 /* force length to zero to avoid ASN1 encoding */
5031 SSL_SESSION_set1_id_context(sess, (const unsigned char *)SHCTX_APPNAME, 0);
William Lallemanded0b5ad2017-10-30 19:36:36 +01005032
5033 /* check if buffer is large enough for the ASN1 encoded session */
5034 data_len = i2d_SSL_SESSION(sess, NULL);
5035 if (data_len > SHSESS_MAX_DATA_LEN)
5036 goto err;
5037
5038 p = encsess;
5039
5040 /* process ASN1 session encoding before the lock */
5041 i2d_SSL_SESSION(sess, &p);
5042
William Lallemanded0b5ad2017-10-30 19:36:36 +01005043
William Lallemanda3c77cf2017-10-30 23:44:40 +01005044 shctx_lock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01005045 /* store to cache */
William Lallemand4f45bb92017-10-30 20:08:51 +01005046 sh_ssl_sess_store(encid, encsess, data_len);
William Lallemanda3c77cf2017-10-30 23:44:40 +01005047 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01005048err:
5049 /* reset original length values */
Emeric Bruneb469652019-10-08 18:27:37 +02005050 SSL_SESSION_set1_id(sess, encid, sid_length);
5051 SSL_SESSION_set1_id_context(sess, (const unsigned char *)SHCTX_APPNAME, strlen(SHCTX_APPNAME));
William Lallemanded0b5ad2017-10-30 19:36:36 +01005052
5053 return 0; /* do not increment session reference count */
5054}
5055
5056/* SSL callback used on lookup an existing session cause none found in internal cache */
William Lallemand4f45bb92017-10-30 20:08:51 +01005057SSL_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 +01005058{
William Lallemand4f45bb92017-10-30 20:08:51 +01005059 struct sh_ssl_sess_hdr *sh_ssl_sess;
William Lallemanded0b5ad2017-10-30 19:36:36 +01005060 unsigned char data[SHSESS_MAX_DATA_LEN], *p;
5061 unsigned char tmpkey[SSL_MAX_SSL_SESSION_ID_LENGTH];
William Lallemanded0b5ad2017-10-30 19:36:36 +01005062 SSL_SESSION *sess;
William Lallemand4f45bb92017-10-30 20:08:51 +01005063 struct shared_block *first;
William Lallemanded0b5ad2017-10-30 19:36:36 +01005064
5065 global.shctx_lookups++;
5066
5067 /* allow the session to be freed automatically by openssl */
5068 *do_copy = 0;
5069
5070 /* tree key is zeros padded sessionid */
5071 if (key_len < SSL_MAX_SSL_SESSION_ID_LENGTH) {
5072 memcpy(tmpkey, key, key_len);
5073 memset(tmpkey + key_len, 0, SSL_MAX_SSL_SESSION_ID_LENGTH - key_len);
5074 key = tmpkey;
5075 }
5076
5077 /* lock cache */
William Lallemanda3c77cf2017-10-30 23:44:40 +01005078 shctx_lock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01005079
5080 /* lookup for session */
William Lallemand4f45bb92017-10-30 20:08:51 +01005081 sh_ssl_sess = sh_ssl_sess_tree_lookup(key);
5082 if (!sh_ssl_sess) {
William Lallemanded0b5ad2017-10-30 19:36:36 +01005083 /* no session found: unlock cache and exit */
William Lallemanda3c77cf2017-10-30 23:44:40 +01005084 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01005085 global.shctx_misses++;
5086 return NULL;
5087 }
5088
William Lallemand4f45bb92017-10-30 20:08:51 +01005089 /* sh_ssl_sess (shared_block->data) is at the end of shared_block */
5090 first = sh_ssl_sess_first_block(sh_ssl_sess);
William Lallemanded0b5ad2017-10-30 19:36:36 +01005091
William Lallemand4f45bb92017-10-30 20:08:51 +01005092 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 +01005093
William Lallemanda3c77cf2017-10-30 23:44:40 +01005094 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01005095
5096 /* decode ASN1 session */
5097 p = data;
William Lallemand4f45bb92017-10-30 20:08:51 +01005098 sess = d2i_SSL_SESSION(NULL, (const unsigned char **)&p, first->len-sizeof(struct sh_ssl_sess_hdr));
William Lallemanded0b5ad2017-10-30 19:36:36 +01005099 /* Reset session id and session id contenxt */
5100 if (sess) {
5101 SSL_SESSION_set1_id(sess, key, key_len);
5102 SSL_SESSION_set1_id_context(sess, (const unsigned char *)SHCTX_APPNAME, strlen(SHCTX_APPNAME));
5103 }
5104
5105 return sess;
5106}
5107
William Lallemand4f45bb92017-10-30 20:08:51 +01005108
William Lallemanded0b5ad2017-10-30 19:36:36 +01005109/* SSL callback used to signal session is no more used in internal cache */
William Lallemand4f45bb92017-10-30 20:08:51 +01005110void sh_ssl_sess_remove_cb(SSL_CTX *ctx, SSL_SESSION *sess)
William Lallemanded0b5ad2017-10-30 19:36:36 +01005111{
William Lallemand4f45bb92017-10-30 20:08:51 +01005112 struct sh_ssl_sess_hdr *sh_ssl_sess;
William Lallemanded0b5ad2017-10-30 19:36:36 +01005113 unsigned char tmpkey[SSL_MAX_SSL_SESSION_ID_LENGTH];
5114 unsigned int sid_length;
5115 const unsigned char *sid_data;
5116 (void)ctx;
5117
5118 sid_data = SSL_SESSION_get_id(sess, &sid_length);
5119 /* tree key is zeros padded sessionid */
5120 if (sid_length < SSL_MAX_SSL_SESSION_ID_LENGTH) {
5121 memcpy(tmpkey, sid_data, sid_length);
5122 memset(tmpkey+sid_length, 0, SSL_MAX_SSL_SESSION_ID_LENGTH - sid_length);
5123 sid_data = tmpkey;
5124 }
5125
William Lallemanda3c77cf2017-10-30 23:44:40 +01005126 shctx_lock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01005127
5128 /* lookup for session */
William Lallemand4f45bb92017-10-30 20:08:51 +01005129 sh_ssl_sess = sh_ssl_sess_tree_lookup(sid_data);
5130 if (sh_ssl_sess) {
William Lallemanded0b5ad2017-10-30 19:36:36 +01005131 /* free session */
William Lallemand4f45bb92017-10-30 20:08:51 +01005132 sh_ssl_sess_tree_delete(sh_ssl_sess);
William Lallemanded0b5ad2017-10-30 19:36:36 +01005133 }
5134
5135 /* unlock cache */
William Lallemanda3c77cf2017-10-30 23:44:40 +01005136 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01005137}
5138
5139/* Set session cache mode to server and disable openssl internal cache.
5140 * Set shared cache callbacks on an ssl context.
5141 * Shared context MUST be firstly initialized */
William Lallemand4f45bb92017-10-30 20:08:51 +01005142void ssl_set_shctx(SSL_CTX *ctx)
William Lallemanded0b5ad2017-10-30 19:36:36 +01005143{
5144 SSL_CTX_set_session_id_context(ctx, (const unsigned char *)SHCTX_APPNAME, strlen(SHCTX_APPNAME));
5145
5146 if (!ssl_shctx) {
5147 SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF);
5148 return;
5149 }
5150
5151 SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_SERVER |
5152 SSL_SESS_CACHE_NO_INTERNAL |
5153 SSL_SESS_CACHE_NO_AUTO_CLEAR);
5154
5155 /* Set callbacks */
William Lallemand4f45bb92017-10-30 20:08:51 +01005156 SSL_CTX_sess_set_new_cb(ctx, sh_ssl_sess_new_cb);
5157 SSL_CTX_sess_set_get_cb(ctx, sh_ssl_sess_get_cb);
5158 SSL_CTX_sess_set_remove_cb(ctx, sh_ssl_sess_remove_cb);
William Lallemanded0b5ad2017-10-30 19:36:36 +01005159}
5160
William Lallemand8b453912019-11-21 15:48:10 +01005161/*
5162 * This function applies the SSL configuration on a SSL_CTX
5163 * It returns an error code and fills the <err> buffer
5164 */
5165int 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 +01005166{
5167 struct proxy *curproxy = bind_conf->frontend;
5168 int cfgerr = 0;
5169 int verify = SSL_VERIFY_NONE;
Willy Tarreau5d4cafb2018-01-04 18:55:19 +01005170 struct ssl_bind_conf __maybe_unused *ssl_conf_cur;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005171 const char *conf_ciphers;
Emmanuel Hocdet839af572019-05-14 16:27:35 +02005172#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02005173 const char *conf_ciphersuites;
5174#endif
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01005175 const char *conf_curves = NULL;
Emeric Brunfc0421f2012-09-07 17:30:07 +02005176
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02005177 if (ssl_conf) {
5178 struct tls_version_filter *conf_ssl_methods = &ssl_conf->ssl_methods;
5179 int i, min, max;
5180 int flags = MC_SSL_O_ALL;
5181
5182 /* Real min and max should be determinate with configuration and openssl's capabilities */
Emmanuel Hocdet43664762017-08-09 18:26:20 +02005183 min = conf_ssl_methods->min ? conf_ssl_methods->min : bind_conf->ssl_conf.ssl_methods.min;
5184 max = conf_ssl_methods->max ? conf_ssl_methods->max : bind_conf->ssl_conf.ssl_methods.max;
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02005185 if (min)
5186 flags |= (methodVersions[min].flag - 1);
5187 if (max)
5188 flags |= ~((methodVersions[max].flag << 1) - 1);
5189 min = max = CONF_TLSV_NONE;
5190 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
5191 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
5192 if (min)
5193 max = i;
5194 else
5195 min = max = i;
5196 }
5197 /* save real min/max */
5198 conf_ssl_methods->min = min;
5199 conf_ssl_methods->max = max;
5200 if (!min) {
Tim Duesterhus93128532019-11-23 23:45:10 +01005201 memprintf(err, "%sProxy '%s': all SSL/TLS versions are disabled for bind '%s' at [%s:%d].\n",
5202 err && *err ? *err : "", bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
William Lallemand8b453912019-11-21 15:48:10 +01005203 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02005204 }
5205 }
5206
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005207 switch ((ssl_conf && ssl_conf->verify) ? ssl_conf->verify : bind_conf->ssl_conf.verify) {
Emeric Brun850efd52014-01-29 12:24:34 +01005208 case SSL_SOCK_VERIFY_NONE:
5209 verify = SSL_VERIFY_NONE;
5210 break;
5211 case SSL_SOCK_VERIFY_OPTIONAL:
5212 verify = SSL_VERIFY_PEER;
5213 break;
5214 case SSL_SOCK_VERIFY_REQUIRED:
5215 verify = SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
5216 break;
5217 }
5218 SSL_CTX_set_verify(ctx, verify, ssl_sock_bind_verifycbk);
5219 if (verify & SSL_VERIFY_PEER) {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005220 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 +01005221 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 +01005222 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 +01005223 if (ca_file || ca_verify_file) {
Emmanuel Hocdetd4f9a602019-10-24 11:32:47 +02005224 /* set CAfile to verify */
Emmanuel Hocdet842e94e2019-12-16 16:39:17 +01005225 if (ca_file && !ssl_set_verify_locations_file(ctx, ca_file)) {
Emmanuel Hocdetd4f9a602019-10-24 11:32:47 +02005226 memprintf(err, "%sProxy '%s': unable to set CA file '%s' for bind '%s' at [%s:%d].\n",
Tim Duesterhus93128532019-11-23 23:45:10 +01005227 err && *err ? *err : "", curproxy->id, ca_file, bind_conf->arg, bind_conf->file, bind_conf->line);
William Lallemand8b453912019-11-21 15:48:10 +01005228 cfgerr |= ERR_ALERT | ERR_FATAL;
Emeric Brund94b3fe2012-09-20 18:23:56 +02005229 }
Emmanuel Hocdet842e94e2019-12-16 16:39:17 +01005230 if (ca_verify_file && !ssl_set_verify_locations_file(ctx, ca_verify_file)) {
5231 memprintf(err, "%sProxy '%s': unable to set CA-no-names file '%s' for bind '%s' at [%s:%d].\n",
5232 err && *err ? *err : "", curproxy->id, ca_verify_file, bind_conf->arg, bind_conf->file, bind_conf->line);
5233 cfgerr |= ERR_ALERT | ERR_FATAL;
5234 }
5235 if (ca_file && !((ssl_conf && ssl_conf->no_ca_names) || bind_conf->ssl_conf.no_ca_names)) {
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02005236 /* set CA names for client cert request, function returns void */
Emmanuel Hocdet129d3282019-10-24 18:08:51 +02005237 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 +02005238 }
Emeric Brund94b3fe2012-09-20 18:23:56 +02005239 }
Emeric Brun850efd52014-01-29 12:24:34 +01005240 else {
Tim Duesterhus93128532019-11-23 23:45:10 +01005241 memprintf(err, "%sProxy '%s': verify is enabled but no CA file specified for bind '%s' at [%s:%d].\n",
5242 err && *err ? *err : "", curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
William Lallemand8b453912019-11-21 15:48:10 +01005243 cfgerr |= ERR_ALERT | ERR_FATAL;
Emeric Brun850efd52014-01-29 12:24:34 +01005244 }
Emeric Brun051cdab2012-10-02 19:25:50 +02005245#ifdef X509_V_FLAG_CRL_CHECK
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005246 if (crl_file) {
Emeric Brund94b3fe2012-09-20 18:23:56 +02005247 X509_STORE *store = SSL_CTX_get_cert_store(ctx);
5248
Emmanuel Hocdetb270e812019-11-21 19:09:31 +01005249 if (!ssl_set_cert_crl_file(store, crl_file)) {
Tim Duesterhus93128532019-11-23 23:45:10 +01005250 memprintf(err, "%sProxy '%s': unable to configure CRL file '%s' for bind '%s' at [%s:%d].\n",
5251 err && *err ? *err : "", curproxy->id, crl_file, bind_conf->arg, bind_conf->file, bind_conf->line);
William Lallemand8b453912019-11-21 15:48:10 +01005252 cfgerr |= ERR_ALERT | ERR_FATAL;
Emeric Brund94b3fe2012-09-20 18:23:56 +02005253 }
Emeric Brun561e5742012-10-02 15:20:55 +02005254 else {
5255 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
5256 }
Emeric Brund94b3fe2012-09-20 18:23:56 +02005257 }
Emeric Brun051cdab2012-10-02 19:25:50 +02005258#endif
Emeric Brun644cde02012-12-14 11:21:13 +01005259 ERR_clear_error();
Emeric Brund94b3fe2012-09-20 18:23:56 +02005260 }
Nenad Merdanovic05552d42015-02-27 19:56:49 +01005261#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
Nenad Merdanovic146defa2015-05-09 08:46:00 +02005262 if(bind_conf->keys_ref) {
Nenad Merdanovic05552d42015-02-27 19:56:49 +01005263 if (!SSL_CTX_set_tlsext_ticket_key_cb(ctx, ssl_tlsext_ticket_key_cb)) {
Tim Duesterhus93128532019-11-23 23:45:10 +01005264 memprintf(err, "%sProxy '%s': unable to set callback for TLS ticket validation for bind '%s' at [%s:%d].\n",
5265 err && *err ? *err : "", curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
William Lallemand8b453912019-11-21 15:48:10 +01005266 cfgerr |= ERR_ALERT | ERR_FATAL;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01005267 }
5268 }
5269#endif
5270
William Lallemand4f45bb92017-10-30 20:08:51 +01005271 ssl_set_shctx(ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005272 conf_ciphers = (ssl_conf && ssl_conf->ciphers) ? ssl_conf->ciphers : bind_conf->ssl_conf.ciphers;
5273 if (conf_ciphers &&
5274 !SSL_CTX_set_cipher_list(ctx, conf_ciphers)) {
Tim Duesterhus93128532019-11-23 23:45:10 +01005275 memprintf(err, "%sProxy '%s': unable to set SSL cipher list to '%s' for bind '%s' at [%s:%d].\n",
5276 err && *err ? *err : "", curproxy->id, conf_ciphers, bind_conf->arg, bind_conf->file, bind_conf->line);
William Lallemand8b453912019-11-21 15:48:10 +01005277 cfgerr |= ERR_ALERT | ERR_FATAL;
Emeric Brunfc0421f2012-09-07 17:30:07 +02005278 }
5279
Emmanuel Hocdet839af572019-05-14 16:27:35 +02005280#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02005281 conf_ciphersuites = (ssl_conf && ssl_conf->ciphersuites) ? ssl_conf->ciphersuites : bind_conf->ssl_conf.ciphersuites;
5282 if (conf_ciphersuites &&
5283 !SSL_CTX_set_ciphersuites(ctx, conf_ciphersuites)) {
Tim Duesterhus93128532019-11-23 23:45:10 +01005284 memprintf(err, "%sProxy '%s': unable to set TLS 1.3 cipher suites to '%s' for bind '%s' at [%s:%d].\n",
5285 err && *err ? *err : "", curproxy->id, conf_ciphersuites, bind_conf->arg, bind_conf->file, bind_conf->line);
William Lallemand8b453912019-11-21 15:48:10 +01005286 cfgerr |= ERR_ALERT | ERR_FATAL;
Dirkjan Bussink415150f2018-09-14 11:14:21 +02005287 }
5288#endif
5289
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01005290#ifndef OPENSSL_NO_DH
Remi Gacogne47783ef2015-05-29 15:53:22 +02005291 /* If tune.ssl.default-dh-param has not been set,
5292 neither has ssl-default-dh-file and no static DH
5293 params were in the certificate file. */
Willy Tarreauef934602016-12-22 23:12:01 +01005294 if (global_ssl.default_dh_param == 0 &&
Remi Gacogne47783ef2015-05-29 15:53:22 +02005295 global_dh == NULL &&
Remi Gacogne4f902b82015-05-28 16:23:00 +02005296 (ssl_dh_ptr_index == -1 ||
5297 SSL_CTX_get_ex_data(ctx, ssl_dh_ptr_index) == NULL)) {
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01005298 STACK_OF(SSL_CIPHER) * ciphers = NULL;
5299 const SSL_CIPHER * cipher = NULL;
5300 char cipher_description[128];
5301 /* The description of ciphers using an Ephemeral Diffie Hellman key exchange
5302 contains " Kx=DH " or " Kx=DH(". Beware of " Kx=DH/",
5303 which is not ephemeral DH. */
5304 const char dhe_description[] = " Kx=DH ";
5305 const char dhe_export_description[] = " Kx=DH(";
5306 int idx = 0;
5307 int dhe_found = 0;
5308 SSL *ssl = NULL;
Lukas Tribus90132722014-08-18 00:56:33 +02005309
Remi Gacogne23d5d372014-10-10 17:04:26 +02005310 ssl = SSL_new(ctx);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02005311
Remi Gacogne23d5d372014-10-10 17:04:26 +02005312 if (ssl) {
5313 ciphers = SSL_get_ciphers(ssl);
5314
5315 if (ciphers) {
5316 for (idx = 0; idx < sk_SSL_CIPHER_num(ciphers); idx++) {
5317 cipher = sk_SSL_CIPHER_value(ciphers, idx);
5318 if (SSL_CIPHER_description(cipher, cipher_description, sizeof (cipher_description)) == cipher_description) {
5319 if (strstr(cipher_description, dhe_description) != NULL ||
5320 strstr(cipher_description, dhe_export_description) != NULL) {
5321 dhe_found = 1;
5322 break;
5323 }
Remi Gacognec1eab8c2014-06-12 18:20:11 +02005324 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02005325 }
5326 }
Remi Gacogne23d5d372014-10-10 17:04:26 +02005327 SSL_free(ssl);
5328 ssl = NULL;
Lukas Tribus90132722014-08-18 00:56:33 +02005329 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02005330
Lukas Tribus90132722014-08-18 00:56:33 +02005331 if (dhe_found) {
Tim Duesterhus93128532019-11-23 23:45:10 +01005332 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",
5333 err && *err ? *err : "");
William Lallemand8b453912019-11-21 15:48:10 +01005334 cfgerr |= ERR_WARN;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02005335 }
5336
Willy Tarreauef934602016-12-22 23:12:01 +01005337 global_ssl.default_dh_param = 1024;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02005338 }
Remi Gacogne8de54152014-07-15 11:36:40 +02005339
Willy Tarreauef934602016-12-22 23:12:01 +01005340 if (global_ssl.default_dh_param >= 1024) {
Remi Gacogne8de54152014-07-15 11:36:40 +02005341 if (local_dh_1024 == NULL) {
5342 local_dh_1024 = ssl_get_dh_1024();
5343 }
Willy Tarreauef934602016-12-22 23:12:01 +01005344 if (global_ssl.default_dh_param >= 2048) {
Remi Gacogne8de54152014-07-15 11:36:40 +02005345 if (local_dh_2048 == NULL) {
5346 local_dh_2048 = ssl_get_dh_2048();
5347 }
Willy Tarreauef934602016-12-22 23:12:01 +01005348 if (global_ssl.default_dh_param >= 4096) {
Remi Gacogne8de54152014-07-15 11:36:40 +02005349 if (local_dh_4096 == NULL) {
5350 local_dh_4096 = ssl_get_dh_4096();
5351 }
Remi Gacogne8de54152014-07-15 11:36:40 +02005352 }
5353 }
5354 }
5355#endif /* OPENSSL_NO_DH */
Remi Gacognef46cd6e2014-06-12 14:58:40 +02005356
Emeric Brunfc0421f2012-09-07 17:30:07 +02005357 SSL_CTX_set_info_callback(ctx, ssl_sock_infocbk);
Willy Tarreau9a1ab082019-05-09 13:26:41 +02005358#if HA_OPENSSL_VERSION_NUMBER >= 0x00907000L
Emeric Brun29f037d2014-04-25 19:05:36 +02005359 SSL_CTX_set_msg_callback(ctx, ssl_sock_msgcbk);
Willy Tarreau5cbe4ef2014-05-08 22:45:11 +02005360#endif
Emeric Brun29f037d2014-04-25 19:05:36 +02005361
Bernard Spil13c53f82018-02-15 13:34:58 +01005362#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005363 ssl_conf_cur = NULL;
5364 if (ssl_conf && ssl_conf->npn_str)
5365 ssl_conf_cur = ssl_conf;
5366 else if (bind_conf->ssl_conf.npn_str)
5367 ssl_conf_cur = &bind_conf->ssl_conf;
5368 if (ssl_conf_cur)
5369 SSL_CTX_set_next_protos_advertised_cb(ctx, ssl_sock_advertise_npn_protos, ssl_conf_cur);
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02005370#endif
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01005371#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005372 ssl_conf_cur = NULL;
5373 if (ssl_conf && ssl_conf->alpn_str)
5374 ssl_conf_cur = ssl_conf;
5375 else if (bind_conf->ssl_conf.alpn_str)
5376 ssl_conf_cur = &bind_conf->ssl_conf;
5377 if (ssl_conf_cur)
5378 SSL_CTX_set_alpn_select_cb(ctx, ssl_sock_advertise_alpn_protos, ssl_conf_cur);
Willy Tarreauab861d32013-04-02 02:30:41 +02005379#endif
Lukas Tribusd14b49c2019-11-24 18:20:40 +01005380#if ((HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL) || defined(LIBRESSL_VERSION_NUMBER))
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01005381 conf_curves = (ssl_conf && ssl_conf->curves) ? ssl_conf->curves : bind_conf->ssl_conf.curves;
5382 if (conf_curves) {
5383 if (!SSL_CTX_set1_curves_list(ctx, conf_curves)) {
Tim Duesterhus93128532019-11-23 23:45:10 +01005384 memprintf(err, "%sProxy '%s': unable to set SSL curves list to '%s' for bind '%s' at [%s:%d].\n",
5385 err && *err ? *err : "", curproxy->id, conf_curves, bind_conf->arg, bind_conf->file, bind_conf->line);
William Lallemand8b453912019-11-21 15:48:10 +01005386 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01005387 }
Emmanuel Hocdeta52bb152017-03-20 11:11:49 +01005388 (void)SSL_CTX_set_ecdh_auto(ctx, 1);
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01005389 }
5390#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02005391#if defined(SSL_CTX_set_tmp_ecdh) && !defined(OPENSSL_NO_ECDH)
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01005392 if (!conf_curves) {
Emeric Brun2b58d042012-09-20 17:10:03 +02005393 int i;
5394 EC_KEY *ecdh;
Willy Tarreau9a1ab082019-05-09 13:26:41 +02005395#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005396 const char *ecdhe = (ssl_conf && ssl_conf->ecdhe) ? ssl_conf->ecdhe :
Olivier Houchardc2aae742017-09-22 18:26:28 +02005397 (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe :
5398 NULL);
5399
5400 if (ecdhe == NULL) {
Eric Salama3c8bde82019-11-20 11:33:40 +01005401 (void)SSL_CTX_set_ecdh_auto(ctx, 1);
Olivier Houchardc2aae742017-09-22 18:26:28 +02005402 return cfgerr;
5403 }
5404#else
5405 const char *ecdhe = (ssl_conf && ssl_conf->ecdhe) ? ssl_conf->ecdhe :
5406 (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe :
5407 ECDHE_DEFAULT_CURVE);
5408#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02005409
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005410 i = OBJ_sn2nid(ecdhe);
Emeric Brun2b58d042012-09-20 17:10:03 +02005411 if (!i || ((ecdh = EC_KEY_new_by_curve_name(i)) == NULL)) {
Tim Duesterhus93128532019-11-23 23:45:10 +01005412 memprintf(err, "%sProxy '%s': unable to set elliptic named curve to '%s' for bind '%s' at [%s:%d].\n",
5413 err && *err ? *err : "", curproxy->id, ecdhe, bind_conf->arg, bind_conf->file, bind_conf->line);
William Lallemand8b453912019-11-21 15:48:10 +01005414 cfgerr |= ERR_ALERT | ERR_FATAL;
Emeric Brun2b58d042012-09-20 17:10:03 +02005415 }
5416 else {
5417 SSL_CTX_set_tmp_ecdh(ctx, ecdh);
5418 EC_KEY_free(ecdh);
5419 }
5420 }
5421#endif
5422
Emeric Brunfc0421f2012-09-07 17:30:07 +02005423 return cfgerr;
5424}
5425
Evan Broderbe554312013-06-27 00:05:25 -07005426static int ssl_sock_srv_hostcheck(const char *pattern, const char *hostname)
5427{
5428 const char *pattern_wildcard, *pattern_left_label_end, *hostname_left_label_end;
5429 size_t prefixlen, suffixlen;
5430
5431 /* Trivial case */
5432 if (strcmp(pattern, hostname) == 0)
5433 return 1;
5434
Evan Broderbe554312013-06-27 00:05:25 -07005435 /* The rest of this logic is based on RFC 6125, section 6.4.3
5436 * (http://tools.ietf.org/html/rfc6125#section-6.4.3) */
5437
Emeric Bruna848dae2013-10-08 11:27:28 +02005438 pattern_wildcard = NULL;
5439 pattern_left_label_end = pattern;
5440 while (*pattern_left_label_end != '.') {
5441 switch (*pattern_left_label_end) {
5442 case 0:
5443 /* End of label not found */
5444 return 0;
5445 case '*':
5446 /* If there is more than one wildcards */
5447 if (pattern_wildcard)
5448 return 0;
5449 pattern_wildcard = pattern_left_label_end;
5450 break;
5451 }
5452 pattern_left_label_end++;
5453 }
5454
5455 /* If it's not trivial and there is no wildcard, it can't
5456 * match */
5457 if (!pattern_wildcard)
Evan Broderbe554312013-06-27 00:05:25 -07005458 return 0;
5459
5460 /* Make sure all labels match except the leftmost */
5461 hostname_left_label_end = strchr(hostname, '.');
5462 if (!hostname_left_label_end
5463 || strcmp(pattern_left_label_end, hostname_left_label_end) != 0)
5464 return 0;
5465
5466 /* Make sure the leftmost label of the hostname is long enough
5467 * that the wildcard can match */
Emeric Brun369da852013-10-08 11:39:35 +02005468 if (hostname_left_label_end - hostname < (pattern_left_label_end - pattern) - 1)
Evan Broderbe554312013-06-27 00:05:25 -07005469 return 0;
5470
5471 /* Finally compare the string on either side of the
5472 * wildcard */
5473 prefixlen = pattern_wildcard - pattern;
5474 suffixlen = pattern_left_label_end - (pattern_wildcard + 1);
Emeric Bruna848dae2013-10-08 11:27:28 +02005475 if ((prefixlen && (memcmp(pattern, hostname, prefixlen) != 0))
5476 || (suffixlen && (memcmp(pattern_wildcard + 1, hostname_left_label_end - suffixlen, suffixlen) != 0)))
Evan Broderbe554312013-06-27 00:05:25 -07005477 return 0;
5478
5479 return 1;
5480}
5481
5482static int ssl_sock_srv_verifycbk(int ok, X509_STORE_CTX *ctx)
5483{
5484 SSL *ssl;
5485 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01005486 struct ssl_sock_ctx *ssl_ctx;
Willy Tarreau2ab88672017-07-05 18:23:03 +02005487 const char *servername;
Willy Tarreau71d058c2017-07-26 20:09:56 +02005488 const char *sni;
Evan Broderbe554312013-06-27 00:05:25 -07005489
5490 int depth;
5491 X509 *cert;
5492 STACK_OF(GENERAL_NAME) *alt_names;
5493 int i;
5494 X509_NAME *cert_subject;
5495 char *str;
5496
5497 if (ok == 0)
5498 return ok;
5499
5500 ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
Thierry FOURNIER28962c92018-06-17 21:37:05 +02005501 conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Olivier Houchard66ab4982019-02-26 18:37:15 +01005502 ssl_ctx = conn->xprt_ctx;
Evan Broderbe554312013-06-27 00:05:25 -07005503
Willy Tarreauad92a9a2017-07-28 11:38:41 +02005504 /* We're checking if the provided hostnames match the desired one. The
5505 * desired hostname comes from the SNI we presented if any, or if not
5506 * provided then it may have been explicitly stated using a "verifyhost"
5507 * directive. If neither is set, we don't care about the name so the
5508 * verification is OK.
Willy Tarreau2ab88672017-07-05 18:23:03 +02005509 */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005510 servername = SSL_get_servername(ssl_ctx->ssl, TLSEXT_NAMETYPE_host_name);
Willy Tarreau71d058c2017-07-26 20:09:56 +02005511 sni = servername;
Willy Tarreau2ab88672017-07-05 18:23:03 +02005512 if (!servername) {
Willy Tarreau07d94e42018-09-20 10:57:52 +02005513 servername = __objt_server(conn->target)->ssl_ctx.verify_host;
Willy Tarreau2ab88672017-07-05 18:23:03 +02005514 if (!servername)
5515 return ok;
5516 }
Evan Broderbe554312013-06-27 00:05:25 -07005517
5518 /* We only need to verify the CN on the actual server cert,
5519 * not the indirect CAs */
5520 depth = X509_STORE_CTX_get_error_depth(ctx);
5521 if (depth != 0)
5522 return ok;
5523
5524 /* At this point, the cert is *not* OK unless we can find a
5525 * hostname match */
5526 ok = 0;
5527
5528 cert = X509_STORE_CTX_get_current_cert(ctx);
5529 /* It seems like this might happen if verify peer isn't set */
5530 if (!cert)
5531 return ok;
5532
5533 alt_names = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
5534 if (alt_names) {
5535 for (i = 0; !ok && i < sk_GENERAL_NAME_num(alt_names); i++) {
5536 GENERAL_NAME *name = sk_GENERAL_NAME_value(alt_names, i);
5537 if (name->type == GEN_DNS) {
Willy Tarreau9a1ab082019-05-09 13:26:41 +02005538#if HA_OPENSSL_VERSION_NUMBER < 0x00907000L
Emeric Bruna33410c2013-09-17 15:47:48 +02005539 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.ia5) >= 0) {
5540#else
Evan Broderbe554312013-06-27 00:05:25 -07005541 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
Emeric Bruna33410c2013-09-17 15:47:48 +02005542#endif
Evan Broderbe554312013-06-27 00:05:25 -07005543 ok = ssl_sock_srv_hostcheck(str, servername);
5544 OPENSSL_free(str);
5545 }
5546 }
5547 }
Emeric Brun4ad50a42013-09-17 15:19:54 +02005548 sk_GENERAL_NAME_pop_free(alt_names, GENERAL_NAME_free);
Evan Broderbe554312013-06-27 00:05:25 -07005549 }
5550
5551 cert_subject = X509_get_subject_name(cert);
5552 i = -1;
5553 while (!ok && (i = X509_NAME_get_index_by_NID(cert_subject, NID_commonName, i)) != -1) {
5554 X509_NAME_ENTRY *entry = X509_NAME_get_entry(cert_subject, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005555 ASN1_STRING *value;
5556 value = X509_NAME_ENTRY_get_data(entry);
5557 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
Evan Broderbe554312013-06-27 00:05:25 -07005558 ok = ssl_sock_srv_hostcheck(str, servername);
5559 OPENSSL_free(str);
5560 }
5561 }
5562
Willy Tarreau71d058c2017-07-26 20:09:56 +02005563 /* report the mismatch and indicate if SNI was used or not */
5564 if (!ok && !conn->err_code)
5565 conn->err_code = sni ? CO_ER_SSL_MISMATCH_SNI : CO_ER_SSL_MISMATCH;
Evan Broderbe554312013-06-27 00:05:25 -07005566 return ok;
5567}
5568
Emeric Brun94324a42012-10-11 14:00:19 +02005569/* prepare ssl context from servers options. Returns an error count */
Willy Tarreau03209342016-12-22 17:08:28 +01005570int ssl_sock_prepare_srv_ctx(struct server *srv)
Emeric Brun94324a42012-10-11 14:00:19 +02005571{
Willy Tarreau03209342016-12-22 17:08:28 +01005572 struct proxy *curproxy = srv->proxy;
Emeric Brun94324a42012-10-11 14:00:19 +02005573 int cfgerr = 0;
Remi Gacogneaf5c3da2014-05-19 10:29:58 +02005574 long options =
Emeric Brun94324a42012-10-11 14:00:19 +02005575 SSL_OP_ALL | /* all known workarounds for bugs */
5576 SSL_OP_NO_SSLv2 |
5577 SSL_OP_NO_COMPRESSION;
Remi Gacogneaf5c3da2014-05-19 10:29:58 +02005578 long mode =
Emeric Brun94324a42012-10-11 14:00:19 +02005579 SSL_MODE_ENABLE_PARTIAL_WRITE |
5580 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
Willy Tarreau396a1862014-11-13 14:06:52 +01005581 SSL_MODE_RELEASE_BUFFERS |
5582 SSL_MODE_SMALL_BUFFERS;
Emeric Brun850efd52014-01-29 12:24:34 +01005583 int verify = SSL_VERIFY_NONE;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01005584 SSL_CTX *ctx = NULL;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005585 struct tls_version_filter *conf_ssl_methods = &srv->ssl_ctx.methods;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005586 int i, min, max, hole;
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005587 int flags = MC_SSL_O_ALL;
Emeric Brun94324a42012-10-11 14:00:19 +02005588
Thierry Fournier383085f2013-01-24 14:15:43 +01005589 /* Make sure openssl opens /dev/urandom before the chroot */
5590 if (!ssl_initialize_random()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005591 ha_alert("OpenSSL random data generator initialization failed.\n");
Thierry Fournier383085f2013-01-24 14:15:43 +01005592 cfgerr++;
5593 }
5594
Willy Tarreaufce03112015-01-15 21:32:40 +01005595 /* Automatic memory computations need to know we use SSL there */
5596 global.ssl_used_backend = 1;
5597
5598 /* Initiate SSL context for current server */
Emeric Brun821bb9b2017-06-15 16:37:39 +02005599 if (!srv->ssl_ctx.reused_sess) {
Olivier Houcharde6060c52017-11-16 17:42:52 +01005600 if ((srv->ssl_ctx.reused_sess = calloc(1, global.nbthread*sizeof(*srv->ssl_ctx.reused_sess))) == NULL) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005601 ha_alert("Proxy '%s', server '%s' [%s:%d] out of memory.\n",
5602 curproxy->id, srv->id,
5603 srv->conf.file, srv->conf.line);
Emeric Brun821bb9b2017-06-15 16:37:39 +02005604 cfgerr++;
5605 return cfgerr;
5606 }
5607 }
Emeric Brun94324a42012-10-11 14:00:19 +02005608 if (srv->use_ssl)
5609 srv->xprt = &ssl_sock;
5610 if (srv->check.use_ssl)
Cyril Bonté9ce13112014-11-15 22:41:27 +01005611 srv->check.xprt = &ssl_sock;
Emeric Brun94324a42012-10-11 14:00:19 +02005612
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005613 ctx = SSL_CTX_new(SSLv23_client_method());
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01005614 if (!ctx) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005615 ha_alert("config : %s '%s', server '%s': unable to allocate ssl context.\n",
5616 proxy_type_str(curproxy), curproxy->id,
5617 srv->id);
Emeric Brun94324a42012-10-11 14:00:19 +02005618 cfgerr++;
5619 return cfgerr;
5620 }
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005621
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005622 if (conf_ssl_methods->flags && (conf_ssl_methods->min || conf_ssl_methods->max))
Christopher Faulet767a84b2017-11-24 16:50:31 +01005623 ha_warning("config : %s '%s': no-sslv3/no-tlsv1x are ignored for server '%s'. "
5624 "Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
5625 proxy_type_str(curproxy), curproxy->id, srv->id);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005626 else
5627 flags = conf_ssl_methods->flags;
5628
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005629 /* Real min and max should be determinate with configuration and openssl's capabilities */
5630 if (conf_ssl_methods->min)
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005631 flags |= (methodVersions[conf_ssl_methods->min].flag - 1);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005632 if (conf_ssl_methods->max)
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005633 flags |= ~((methodVersions[conf_ssl_methods->max].flag << 1) - 1);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005634
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02005635 /* find min, max and holes */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005636 min = max = CONF_TLSV_NONE;
5637 hole = 0;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005638 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005639 /* version is in openssl && version not disable in configuration */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005640 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005641 if (min) {
5642 if (hole) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005643 ha_warning("config : %s '%s': SSL/TLS versions range not contiguous for server '%s'. "
5644 "Hole find for %s. Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
5645 proxy_type_str(curproxy), curproxy->id, srv->id,
5646 methodVersions[hole].name);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005647 hole = 0;
5648 }
5649 max = i;
5650 }
5651 else {
5652 min = max = i;
5653 }
5654 }
5655 else {
5656 if (min)
5657 hole = i;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005658 }
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005659 if (!min) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005660 ha_alert("config : %s '%s': all SSL/TLS versions are disabled for server '%s'.\n",
5661 proxy_type_str(curproxy), curproxy->id, srv->id);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005662 cfgerr += 1;
5663 }
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005664
Willy Tarreau9a1ab082019-05-09 13:26:41 +02005665#if (HA_OPENSSL_VERSION_NUMBER < 0x1010000fL)
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005666 /* Keep force-xxx implementation as it is in older haproxy. It's a
Joseph Herlant017b3da2018-11-15 09:07:59 -08005667 precautionary measure to avoid any surprise with older openssl version. */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005668 if (min == max)
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02005669 methodVersions[min].ctx_set_version(ctx, SET_CLIENT);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005670 else
5671 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
5672 if (flags & methodVersions[i].flag)
5673 options |= methodVersions[i].option;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005674#else /* openssl >= 1.1.0 */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005675 /* set the max_version is required to cap TLS version or activate new TLS (v1.3) */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02005676 methodVersions[min].ctx_set_version(ctx, SET_MIN);
5677 methodVersions[max].ctx_set_version(ctx, SET_MAX);
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005678#endif
5679
5680 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLS_TICKETS)
5681 options |= SSL_OP_NO_TICKET;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01005682 SSL_CTX_set_options(ctx, options);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005683
Willy Tarreau5db847a2019-05-09 14:13:35 +02005684#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005685 if (global_ssl.async)
5686 mode |= SSL_MODE_ASYNC;
5687#endif
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01005688 SSL_CTX_set_mode(ctx, mode);
5689 srv->ssl_ctx.ctx = ctx;
5690
Emeric Bruna7aa3092012-10-26 12:58:00 +02005691 if (srv->ssl_ctx.client_crt) {
5692 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 +01005693 ha_alert("config : %s '%s', server '%s': unable to load SSL private key from PEM file '%s'.\n",
5694 proxy_type_str(curproxy), curproxy->id,
5695 srv->id, srv->ssl_ctx.client_crt);
Emeric Bruna7aa3092012-10-26 12:58:00 +02005696 cfgerr++;
5697 }
5698 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 +01005699 ha_alert("config : %s '%s', server '%s': unable to load ssl certificate from PEM file '%s'.\n",
5700 proxy_type_str(curproxy), curproxy->id,
5701 srv->id, srv->ssl_ctx.client_crt);
Emeric Bruna7aa3092012-10-26 12:58:00 +02005702 cfgerr++;
5703 }
5704 else if (SSL_CTX_check_private_key(srv->ssl_ctx.ctx) <= 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005705 ha_alert("config : %s '%s', server '%s': inconsistencies between private key and certificate loaded from PEM file '%s'.\n",
5706 proxy_type_str(curproxy), curproxy->id,
5707 srv->id, srv->ssl_ctx.client_crt);
Emeric Bruna7aa3092012-10-26 12:58:00 +02005708 cfgerr++;
5709 }
5710 }
Emeric Brun94324a42012-10-11 14:00:19 +02005711
Emeric Brun850efd52014-01-29 12:24:34 +01005712 if (global.ssl_server_verify == SSL_SERVER_VERIFY_REQUIRED)
5713 verify = SSL_VERIFY_PEER;
Emeric Brun850efd52014-01-29 12:24:34 +01005714 switch (srv->ssl_ctx.verify) {
5715 case SSL_SOCK_VERIFY_NONE:
5716 verify = SSL_VERIFY_NONE;
5717 break;
5718 case SSL_SOCK_VERIFY_REQUIRED:
5719 verify = SSL_VERIFY_PEER;
5720 break;
5721 }
Evan Broderbe554312013-06-27 00:05:25 -07005722 SSL_CTX_set_verify(srv->ssl_ctx.ctx,
Emeric Brun850efd52014-01-29 12:24:34 +01005723 verify,
Willy Tarreau2ab88672017-07-05 18:23:03 +02005724 (srv->ssl_ctx.verify_host || (verify & SSL_VERIFY_PEER)) ? ssl_sock_srv_verifycbk : NULL);
Emeric Brun850efd52014-01-29 12:24:34 +01005725 if (verify & SSL_VERIFY_PEER) {
Emeric Brunef42d922012-10-11 16:11:36 +02005726 if (srv->ssl_ctx.ca_file) {
Emmanuel Hocdetd4f9a602019-10-24 11:32:47 +02005727 /* set CAfile to verify */
5728 if (!ssl_set_verify_locations_file(srv->ssl_ctx.ctx, srv->ssl_ctx.ca_file)) {
5729 ha_alert("Proxy '%s', server '%s' [%s:%d] unable to set CA file '%s'.\n",
Christopher Faulet767a84b2017-11-24 16:50:31 +01005730 curproxy->id, srv->id,
5731 srv->conf.file, srv->conf.line, srv->ssl_ctx.ca_file);
Emeric Brunef42d922012-10-11 16:11:36 +02005732 cfgerr++;
5733 }
5734 }
Emeric Brun850efd52014-01-29 12:24:34 +01005735 else {
5736 if (global.ssl_server_verify == SSL_SERVER_VERIFY_REQUIRED)
Christopher Faulet767a84b2017-11-24 16:50:31 +01005737 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",
5738 curproxy->id, srv->id,
5739 srv->conf.file, srv->conf.line);
Emeric Brun850efd52014-01-29 12:24:34 +01005740 else
Christopher Faulet767a84b2017-11-24 16:50:31 +01005741 ha_alert("Proxy '%s', server '%s' [%s:%d] verify is enabled but no CA file specified.\n",
5742 curproxy->id, srv->id,
5743 srv->conf.file, srv->conf.line);
Emeric Brun850efd52014-01-29 12:24:34 +01005744 cfgerr++;
5745 }
Emeric Brunef42d922012-10-11 16:11:36 +02005746#ifdef X509_V_FLAG_CRL_CHECK
5747 if (srv->ssl_ctx.crl_file) {
5748 X509_STORE *store = SSL_CTX_get_cert_store(srv->ssl_ctx.ctx);
5749
Emmanuel Hocdetb270e812019-11-21 19:09:31 +01005750 if (!ssl_set_cert_crl_file(store, srv->ssl_ctx.crl_file)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005751 ha_alert("Proxy '%s', server '%s' [%s:%d] unable to configure CRL file '%s'.\n",
5752 curproxy->id, srv->id,
5753 srv->conf.file, srv->conf.line, srv->ssl_ctx.crl_file);
Emeric Brunef42d922012-10-11 16:11:36 +02005754 cfgerr++;
5755 }
5756 else {
5757 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
5758 }
5759 }
5760#endif
5761 }
5762
Olivier Houchardbd84ac82017-11-03 13:43:35 +01005763 SSL_CTX_set_session_cache_mode(srv->ssl_ctx.ctx, SSL_SESS_CACHE_CLIENT |
5764 SSL_SESS_CACHE_NO_INTERNAL_STORE);
5765 SSL_CTX_sess_set_new_cb(srv->ssl_ctx.ctx, ssl_sess_new_srv_cb);
Emeric Brun94324a42012-10-11 14:00:19 +02005766 if (srv->ssl_ctx.ciphers &&
5767 !SSL_CTX_set_cipher_list(srv->ssl_ctx.ctx, srv->ssl_ctx.ciphers)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005768 ha_alert("Proxy '%s', server '%s' [%s:%d] : unable to set SSL cipher list to '%s'.\n",
5769 curproxy->id, srv->id,
5770 srv->conf.file, srv->conf.line, srv->ssl_ctx.ciphers);
Emeric Brun94324a42012-10-11 14:00:19 +02005771 cfgerr++;
5772 }
Dirkjan Bussink415150f2018-09-14 11:14:21 +02005773
Emmanuel Hocdet839af572019-05-14 16:27:35 +02005774#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02005775 if (srv->ssl_ctx.ciphersuites &&
Pierre Cheynierbc34cd12019-03-21 16:15:47 +00005776 !SSL_CTX_set_ciphersuites(srv->ssl_ctx.ctx, srv->ssl_ctx.ciphersuites)) {
Dirkjan Bussink415150f2018-09-14 11:14:21 +02005777 ha_alert("Proxy '%s', server '%s' [%s:%d] : unable to set TLS 1.3 cipher suites to '%s'.\n",
5778 curproxy->id, srv->id,
5779 srv->conf.file, srv->conf.line, srv->ssl_ctx.ciphersuites);
5780 cfgerr++;
5781 }
5782#endif
Olivier Houchardc7566002018-11-20 23:33:50 +01005783#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
5784 if (srv->ssl_ctx.npn_str)
5785 SSL_CTX_set_next_proto_select_cb(ctx, ssl_sock_srv_select_protos, srv);
5786#endif
5787#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
5788 if (srv->ssl_ctx.alpn_str)
5789 SSL_CTX_set_alpn_protos(ctx, (unsigned char *)srv->ssl_ctx.alpn_str, srv->ssl_ctx.alpn_len);
5790#endif
5791
Emeric Brun94324a42012-10-11 14:00:19 +02005792
5793 return cfgerr;
5794}
5795
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005796/* Walks down the two trees in bind_conf and prepares all certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +02005797 * be NULL, in which case nothing is done. Returns the number of errors
5798 * encountered.
5799 */
Willy Tarreau03209342016-12-22 17:08:28 +01005800int ssl_sock_prepare_all_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02005801{
5802 struct ebmb_node *node;
5803 struct sni_ctx *sni;
5804 int err = 0;
William Lallemand8b453912019-11-21 15:48:10 +01005805 int errcode = 0;
5806 char *errmsg = NULL;
Emeric Brunfc0421f2012-09-07 17:30:07 +02005807
Willy Tarreaufce03112015-01-15 21:32:40 +01005808 /* Automatic memory computations need to know we use SSL there */
5809 global.ssl_used_frontend = 1;
5810
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01005811 /* Make sure openssl opens /dev/urandom before the chroot */
5812 if (!ssl_initialize_random()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005813 ha_alert("OpenSSL random data generator initialization failed.\n");
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01005814 err++;
5815 }
5816 /* Create initial_ctx used to start the ssl connection before do switchctx */
5817 if (!bind_conf->initial_ctx) {
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005818 err += ssl_sock_initial_ctx(bind_conf);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01005819 /* It should not be necessary to call this function, but it's
5820 necessary first to check and move all initialisation related
5821 to initial_ctx in ssl_sock_initial_ctx. */
William Lallemand8b453912019-11-21 15:48:10 +01005822 errcode |= ssl_sock_prepare_ctx(bind_conf, NULL, bind_conf->initial_ctx, &errmsg);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01005823 }
Emeric Brun0bed9942014-10-30 19:25:24 +01005824 if (bind_conf->default_ctx)
William Lallemand8b453912019-11-21 15:48:10 +01005825 errcode |= ssl_sock_prepare_ctx(bind_conf, bind_conf->default_ssl_conf, bind_conf->default_ctx, &errmsg);
Emeric Brun0bed9942014-10-30 19:25:24 +01005826
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005827 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02005828 while (node) {
5829 sni = ebmb_entry(node, struct sni_ctx, name);
Emeric Brun0bed9942014-10-30 19:25:24 +01005830 if (!sni->order && sni->ctx != bind_conf->default_ctx)
5831 /* only initialize the CTX on its first occurrence and
5832 if it is not the default_ctx */
William Lallemand8b453912019-11-21 15:48:10 +01005833 errcode |= ssl_sock_prepare_ctx(bind_conf, sni->conf, sni->ctx, &errmsg);
Emeric Brunfc0421f2012-09-07 17:30:07 +02005834 node = ebmb_next(node);
5835 }
5836
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005837 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02005838 while (node) {
5839 sni = ebmb_entry(node, struct sni_ctx, name);
William Lallemand8b453912019-11-21 15:48:10 +01005840 if (!sni->order && sni->ctx != bind_conf->default_ctx) {
Emeric Brun0bed9942014-10-30 19:25:24 +01005841 /* only initialize the CTX on its first occurrence and
5842 if it is not the default_ctx */
William Lallemand8b453912019-11-21 15:48:10 +01005843 errcode |= ssl_sock_prepare_ctx(bind_conf, sni->conf, sni->ctx, &errmsg);
5844 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02005845 node = ebmb_next(node);
5846 }
William Lallemand8b453912019-11-21 15:48:10 +01005847
5848 if (errcode & ERR_WARN) {
Tim Duesterhusc0e820c2019-11-23 23:52:30 +01005849 ha_warning("%s", errmsg);
William Lallemand8b453912019-11-21 15:48:10 +01005850 } else if (errcode & ERR_CODE) {
Tim Duesterhusc0e820c2019-11-23 23:52:30 +01005851 ha_alert("%s", errmsg);
William Lallemand8b453912019-11-21 15:48:10 +01005852 err++;
5853 }
5854
5855 free(errmsg);
Emeric Brunfc0421f2012-09-07 17:30:07 +02005856 return err;
5857}
5858
Willy Tarreau55d37912016-12-21 23:38:39 +01005859/* Prepares all the contexts for a bind_conf and allocates the shared SSL
5860 * context if needed. Returns < 0 on error, 0 on success. The warnings and
5861 * alerts are directly emitted since the rest of the stack does it below.
5862 */
5863int ssl_sock_prepare_bind_conf(struct bind_conf *bind_conf)
5864{
5865 struct proxy *px = bind_conf->frontend;
5866 int alloc_ctx;
5867 int err;
5868
5869 if (!bind_conf->is_ssl) {
5870 if (bind_conf->default_ctx) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005871 ha_warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
5872 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreau55d37912016-12-21 23:38:39 +01005873 }
5874 return 0;
5875 }
5876 if (!bind_conf->default_ctx) {
Emmanuel Hocdetaa0d6372017-08-09 11:24:25 +02005877 if (bind_conf->strict_sni && !bind_conf->generate_certs) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005878 ha_warning("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d], ssl connections will fail (use 'crt').\n",
5879 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetaa0d6372017-08-09 11:24:25 +02005880 }
5881 else {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005882 ha_alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
5883 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetaa0d6372017-08-09 11:24:25 +02005884 return -1;
5885 }
Willy Tarreau55d37912016-12-21 23:38:39 +01005886 }
William Lallemandc61c0b32017-12-04 18:46:39 +01005887 if (!ssl_shctx && global.tune.sslcachesize) {
William Lallemandc3cd35f2017-11-28 11:04:43 +01005888 alloc_ctx = shctx_init(&ssl_shctx, global.tune.sslcachesize,
Frédéric Lécailleb7838af2018-10-22 16:21:39 +02005889 sizeof(struct sh_ssl_sess_hdr) + SHSESS_BLOCK_MIN_SIZE, -1,
William Lallemandc3cd35f2017-11-28 11:04:43 +01005890 sizeof(*sh_ssl_sess_tree),
5891 ((global.nbthread > 1) || (!global_ssl.private_cache && (global.nbproc > 1))) ? 1 : 0);
Frédéric Lécaille4c8aa112018-10-25 20:22:46 +02005892 if (alloc_ctx <= 0) {
William Lallemandc3cd35f2017-11-28 11:04:43 +01005893 if (alloc_ctx == SHCTX_E_INIT_LOCK)
5894 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");
5895 else
5896 ha_alert("Unable to allocate SSL session cache.\n");
5897 return -1;
5898 }
5899 /* free block callback */
5900 ssl_shctx->free_block = sh_ssl_sess_free_blocks;
5901 /* init the root tree within the extra space */
5902 sh_ssl_sess_tree = (void *)ssl_shctx + sizeof(struct shared_context);
5903 *sh_ssl_sess_tree = EB_ROOT_UNIQUE;
Willy Tarreau55d37912016-12-21 23:38:39 +01005904 }
Willy Tarreau55d37912016-12-21 23:38:39 +01005905 err = 0;
5906 /* initialize all certificate contexts */
5907 err += ssl_sock_prepare_all_ctx(bind_conf);
5908
5909 /* initialize CA variables if the certificates generation is enabled */
5910 err += ssl_sock_load_ca(bind_conf);
5911
5912 return -err;
5913}
Christopher Faulet77fe80c2015-07-29 13:02:40 +02005914
5915/* release ssl context allocated for servers. */
5916void ssl_sock_free_srv_ctx(struct server *srv)
5917{
Olivier Houchardc7566002018-11-20 23:33:50 +01005918#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
5919 if (srv->ssl_ctx.alpn_str)
5920 free(srv->ssl_ctx.alpn_str);
5921#endif
Lukas Tribusda95fd92018-11-25 13:21:27 +01005922#ifdef OPENSSL_NPN_NEGOTIATED
Olivier Houchardc7566002018-11-20 23:33:50 +01005923 if (srv->ssl_ctx.npn_str)
5924 free(srv->ssl_ctx.npn_str);
Lukas Tribus7706b852018-11-26 22:57:17 +01005925#endif
Christopher Faulet77fe80c2015-07-29 13:02:40 +02005926 if (srv->ssl_ctx.ctx)
5927 SSL_CTX_free(srv->ssl_ctx.ctx);
5928}
5929
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005930/* Walks down the two trees in bind_conf and frees all the certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +02005931 * be NULL, in which case nothing is done. The default_ctx is nullified too.
5932 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005933void ssl_sock_free_all_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02005934{
5935 struct ebmb_node *node, *back;
5936 struct sni_ctx *sni;
5937
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005938 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02005939 while (node) {
5940 sni = ebmb_entry(node, struct sni_ctx, name);
5941 back = ebmb_next(node);
5942 ebmb_delete(node);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005943 if (!sni->order) { /* only free the CTX on its first occurrence */
Emeric Brunfc0421f2012-09-07 17:30:07 +02005944 SSL_CTX_free(sni->ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005945 ssl_sock_free_ssl_conf(sni->conf);
5946 free(sni->conf);
5947 sni->conf = NULL;
5948 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02005949 free(sni);
5950 node = back;
5951 }
5952
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005953 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02005954 while (node) {
5955 sni = ebmb_entry(node, struct sni_ctx, name);
5956 back = ebmb_next(node);
5957 ebmb_delete(node);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005958 if (!sni->order) { /* only free the CTX on its first occurrence */
Emeric Brunfc0421f2012-09-07 17:30:07 +02005959 SSL_CTX_free(sni->ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005960 ssl_sock_free_ssl_conf(sni->conf);
5961 free(sni->conf);
5962 sni->conf = NULL;
5963 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02005964 free(sni);
5965 node = back;
5966 }
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01005967 SSL_CTX_free(bind_conf->initial_ctx);
5968 bind_conf->initial_ctx = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005969 bind_conf->default_ctx = NULL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005970 bind_conf->default_ssl_conf = NULL;
Emeric Brune1f38db2012-09-03 20:36:47 +02005971}
5972
Willy Tarreau795cdab2016-12-22 17:30:54 +01005973/* Destroys all the contexts for a bind_conf. This is used during deinit(). */
5974void ssl_sock_destroy_bind_conf(struct bind_conf *bind_conf)
5975{
5976 ssl_sock_free_ca(bind_conf);
5977 ssl_sock_free_all_ctx(bind_conf);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005978 ssl_sock_free_ssl_conf(&bind_conf->ssl_conf);
Willy Tarreau795cdab2016-12-22 17:30:54 +01005979 free(bind_conf->ca_sign_file);
5980 free(bind_conf->ca_sign_pass);
Willy Tarreau17b4aa12018-07-17 10:05:32 +02005981 if (bind_conf->keys_ref && !--bind_conf->keys_ref->refcount) {
Willy Tarreau795cdab2016-12-22 17:30:54 +01005982 free(bind_conf->keys_ref->filename);
5983 free(bind_conf->keys_ref->tlskeys);
5984 LIST_DEL(&bind_conf->keys_ref->list);
5985 free(bind_conf->keys_ref);
5986 }
5987 bind_conf->keys_ref = NULL;
Willy Tarreau795cdab2016-12-22 17:30:54 +01005988 bind_conf->ca_sign_pass = NULL;
5989 bind_conf->ca_sign_file = NULL;
Willy Tarreau795cdab2016-12-22 17:30:54 +01005990}
5991
Christopher Faulet31af49d2015-06-09 17:29:50 +02005992/* Load CA cert file and private key used to generate certificates */
5993int
Willy Tarreau03209342016-12-22 17:08:28 +01005994ssl_sock_load_ca(struct bind_conf *bind_conf)
Christopher Faulet31af49d2015-06-09 17:29:50 +02005995{
Willy Tarreau03209342016-12-22 17:08:28 +01005996 struct proxy *px = bind_conf->frontend;
Christopher Faulet31af49d2015-06-09 17:29:50 +02005997 FILE *fp;
5998 X509 *cacert = NULL;
5999 EVP_PKEY *capkey = NULL;
6000 int err = 0;
6001
Christopher Fauletf8bb0ce2017-09-15 09:52:49 +02006002 if (!bind_conf->generate_certs)
Christopher Faulet31af49d2015-06-09 17:29:50 +02006003 return err;
6004
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01006005#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Emeric Brun821bb9b2017-06-15 16:37:39 +02006006 if (global_ssl.ctx_cache) {
Willy Tarreauef934602016-12-22 23:12:01 +01006007 ssl_ctx_lru_tree = lru64_new(global_ssl.ctx_cache);
Emeric Brun821bb9b2017-06-15 16:37:39 +02006008 }
Christopher Fauletd2cab922015-07-28 16:03:47 +02006009 ssl_ctx_lru_seed = (unsigned int)time(NULL);
Emeric Brun821bb9b2017-06-15 16:37:39 +02006010 ssl_ctx_serial = now_ms;
Willy Tarreaua84c2672015-10-09 12:10:13 +02006011#endif
Christopher Fauletd2cab922015-07-28 16:03:47 +02006012
Christopher Faulet31af49d2015-06-09 17:29:50 +02006013 if (!bind_conf->ca_sign_file) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01006014 ha_alert("Proxy '%s': cannot enable certificate generation, "
6015 "no CA certificate File configured at [%s:%d].\n",
6016 px->id, bind_conf->file, bind_conf->line);
Christopher Faulet31af49d2015-06-09 17:29:50 +02006017 goto load_error;
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02006018 }
Christopher Faulet31af49d2015-06-09 17:29:50 +02006019
6020 /* read in the CA certificate */
6021 if (!(fp = fopen(bind_conf->ca_sign_file, "r"))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01006022 ha_alert("Proxy '%s': Failed to read CA certificate file '%s' at [%s:%d].\n",
6023 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Faulet31af49d2015-06-09 17:29:50 +02006024 goto load_error;
6025 }
6026 if (!(cacert = PEM_read_X509(fp, NULL, NULL, NULL))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01006027 ha_alert("Proxy '%s': Failed to read CA certificate file '%s' at [%s:%d].\n",
6028 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02006029 goto read_error;
Christopher Faulet31af49d2015-06-09 17:29:50 +02006030 }
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02006031 rewind(fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02006032 if (!(capkey = PEM_read_PrivateKey(fp, NULL, NULL, bind_conf->ca_sign_pass))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01006033 ha_alert("Proxy '%s': Failed to read CA private key file '%s' at [%s:%d].\n",
6034 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02006035 goto read_error;
Christopher Faulet31af49d2015-06-09 17:29:50 +02006036 }
Christopher Faulet31af49d2015-06-09 17:29:50 +02006037
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02006038 fclose (fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02006039 bind_conf->ca_sign_cert = cacert;
6040 bind_conf->ca_sign_pkey = capkey;
6041 return err;
6042
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02006043 read_error:
6044 fclose (fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02006045 if (capkey) EVP_PKEY_free(capkey);
6046 if (cacert) X509_free(cacert);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02006047 load_error:
6048 bind_conf->generate_certs = 0;
6049 err++;
Christopher Faulet31af49d2015-06-09 17:29:50 +02006050 return err;
6051}
6052
6053/* Release CA cert and private key used to generate certificated */
6054void
6055ssl_sock_free_ca(struct bind_conf *bind_conf)
6056{
Christopher Faulet31af49d2015-06-09 17:29:50 +02006057 if (bind_conf->ca_sign_pkey)
6058 EVP_PKEY_free(bind_conf->ca_sign_pkey);
6059 if (bind_conf->ca_sign_cert)
6060 X509_free(bind_conf->ca_sign_cert);
Willy Tarreau94ff03a2016-12-22 17:57:46 +01006061 bind_conf->ca_sign_pkey = NULL;
6062 bind_conf->ca_sign_cert = NULL;
Christopher Faulet31af49d2015-06-09 17:29:50 +02006063}
6064
Emeric Brun46591952012-05-18 15:47:34 +02006065/*
6066 * This function is called if SSL * context is not yet allocated. The function
6067 * is designed to be called before any other data-layer operation and sets the
6068 * handshake flag on the connection. It is safe to call it multiple times.
6069 * It returns 0 on success and -1 in error case.
6070 */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006071static int ssl_sock_init(struct connection *conn, void **xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02006072{
Olivier Houchard66ab4982019-02-26 18:37:15 +01006073 struct ssl_sock_ctx *ctx;
Emeric Brun46591952012-05-18 15:47:34 +02006074 /* already initialized */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006075 if (*xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02006076 return 0;
6077
Willy Tarreau3c728722014-01-23 13:50:42 +01006078 if (!conn_ctrl_ready(conn))
Willy Tarreauf79c8172013-10-21 16:30:56 +02006079 return 0;
6080
Olivier Houchard66ab4982019-02-26 18:37:15 +01006081 ctx = pool_alloc(ssl_sock_ctx_pool);
6082 if (!ctx) {
6083 conn->err_code = CO_ER_SSL_NO_MEM;
6084 return -1;
6085 }
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02006086 ctx->wait_event.tasklet = tasklet_new();
6087 if (!ctx->wait_event.tasklet) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02006088 conn->err_code = CO_ER_SSL_NO_MEM;
6089 pool_free(ssl_sock_ctx_pool, ctx);
6090 return -1;
6091 }
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02006092 ctx->wait_event.tasklet->process = ssl_sock_io_cb;
6093 ctx->wait_event.tasklet->context = ctx;
Olivier Houchardea8dd942019-05-20 14:02:16 +02006094 ctx->wait_event.events = 0;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006095 ctx->sent_early_data = 0;
Olivier Houchard54907bb2019-12-19 15:02:39 +01006096 ctx->early_buf = BUF_NULL;
Olivier Houcharda8955d52019-04-07 22:00:38 +02006097 ctx->conn = conn;
Willy Tarreau113d52b2020-01-10 09:20:26 +01006098 ctx->subs = NULL;
Emeric Brun5762a0d2019-09-06 15:36:02 +02006099 ctx->xprt_st = 0;
6100 ctx->xprt_ctx = NULL;
Olivier Houcharda8955d52019-04-07 22:00:38 +02006101
6102 /* Only work with sockets for now, this should be adapted when we'll
6103 * add QUIC support.
6104 */
6105 ctx->xprt = xprt_get(XPRT_RAW);
Olivier Houchard19afb272019-05-23 18:24:07 +02006106 if (ctx->xprt->init) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02006107 if (ctx->xprt->init(conn, &ctx->xprt_ctx) != 0)
6108 goto err;
Olivier Houchard19afb272019-05-23 18:24:07 +02006109 }
Olivier Houchard66ab4982019-02-26 18:37:15 +01006110
Willy Tarreau20879a02012-12-03 16:32:10 +01006111 if (global.maxsslconn && sslconns >= global.maxsslconn) {
6112 conn->err_code = CO_ER_SSL_TOO_MANY;
Olivier Houchardea8dd942019-05-20 14:02:16 +02006113 goto err;
Willy Tarreau20879a02012-12-03 16:32:10 +01006114 }
Willy Tarreau403edff2012-09-06 11:58:37 +02006115
Emeric Brun46591952012-05-18 15:47:34 +02006116 /* If it is in client mode initiate SSL session
6117 in connect state otherwise accept state */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01006118 if (objt_server(conn->target)) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01006119 int may_retry = 1;
6120
6121 retry_connect:
Emeric Brun46591952012-05-18 15:47:34 +02006122 /* Alloc a new SSL session ctx */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006123 ctx->ssl = SSL_new(__objt_server(conn->target)->ssl_ctx.ctx);
6124 if (!ctx->ssl) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01006125 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01006126 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01006127 goto retry_connect;
6128 }
Willy Tarreau20879a02012-12-03 16:32:10 +01006129 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006130 goto err;
Willy Tarreau20879a02012-12-03 16:32:10 +01006131 }
Olivier Houcharda8955d52019-04-07 22:00:38 +02006132 ctx->bio = BIO_new(ha_meth);
6133 if (!ctx->bio) {
Olivier Houchardefe5e8e2020-01-24 15:17:38 +01006134 SSL_free(ctx->ssl);
6135 ctx->ssl = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01006136 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01006137 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01006138 goto retry_connect;
6139 }
Emeric Brun55476152014-11-12 17:35:37 +01006140 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006141 goto err;
Emeric Brun55476152014-11-12 17:35:37 +01006142 }
Olivier Houcharda8955d52019-04-07 22:00:38 +02006143 BIO_set_data(ctx->bio, ctx);
Olivier Houcharda8955d52019-04-07 22:00:38 +02006144 SSL_set_bio(ctx->ssl, ctx->bio, ctx->bio);
Emeric Brun46591952012-05-18 15:47:34 +02006145
Evan Broderbe554312013-06-27 00:05:25 -07006146 /* set connection pointer */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006147 if (!SSL_set_ex_data(ctx->ssl, ssl_app_data_index, conn)) {
6148 SSL_free(ctx->ssl);
6149 ctx->ssl = NULL;
Emeric Brun55476152014-11-12 17:35:37 +01006150 conn->xprt_ctx = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01006151 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01006152 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01006153 goto retry_connect;
6154 }
Emeric Brun55476152014-11-12 17:35:37 +01006155 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006156 goto err;
Emeric Brun55476152014-11-12 17:35:37 +01006157 }
6158
Olivier Houchard66ab4982019-02-26 18:37:15 +01006159 SSL_set_connect_state(ctx->ssl);
Willy Tarreau07d94e42018-09-20 10:57:52 +02006160 if (__objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr) {
6161 const unsigned char *ptr = __objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr;
6162 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 +01006163 if (sess && !SSL_set_session(ctx->ssl, sess)) {
Olivier Houcharde6060c52017-11-16 17:42:52 +01006164 SSL_SESSION_free(sess);
Willy Tarreau07d94e42018-09-20 10:57:52 +02006165 free(__objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr);
6166 __objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr = NULL;
Olivier Houcharde6060c52017-11-16 17:42:52 +01006167 } else if (sess) {
6168 SSL_SESSION_free(sess);
Emeric Brun55476152014-11-12 17:35:37 +01006169 }
6170 }
Evan Broderbe554312013-06-27 00:05:25 -07006171
Emeric Brun46591952012-05-18 15:47:34 +02006172 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +02006173 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Willy Tarreau403edff2012-09-06 11:58:37 +02006174
Olivier Houchard2be5a4c2019-03-08 18:54:43 +01006175 _HA_ATOMIC_ADD(&sslconns, 1);
6176 _HA_ATOMIC_ADD(&totalsslconns, 1);
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006177 *xprt_ctx = ctx;
Olivier Houchardea8dd942019-05-20 14:02:16 +02006178 /* Start the handshake */
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02006179 tasklet_wakeup(ctx->wait_event.tasklet);
Emeric Brun46591952012-05-18 15:47:34 +02006180 return 0;
6181 }
Willy Tarreau3fdb3662012-11-12 00:42:33 +01006182 else if (objt_listener(conn->target)) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01006183 int may_retry = 1;
6184
6185 retry_accept:
Emeric Brun46591952012-05-18 15:47:34 +02006186 /* Alloc a new SSL session ctx */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006187 ctx->ssl = SSL_new(__objt_listener(conn->target)->bind_conf->initial_ctx);
6188 if (!ctx->ssl) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01006189 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01006190 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01006191 goto retry_accept;
6192 }
Willy Tarreau20879a02012-12-03 16:32:10 +01006193 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006194 goto err;
Willy Tarreau20879a02012-12-03 16:32:10 +01006195 }
Olivier Houcharda8955d52019-04-07 22:00:38 +02006196 ctx->bio = BIO_new(ha_meth);
6197 if (!ctx->bio) {
Olivier Houchardefe5e8e2020-01-24 15:17:38 +01006198 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 }
Olivier Houcharda8955d52019-04-07 22:00:38 +02006207 BIO_set_data(ctx->bio, ctx);
Olivier Houcharda8955d52019-04-07 22:00:38 +02006208 SSL_set_bio(ctx->ssl, ctx->bio, ctx->bio);
Emeric Brun46591952012-05-18 15:47:34 +02006209
Emeric Brune1f38db2012-09-03 20:36:47 +02006210 /* set connection pointer */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006211 if (!SSL_set_ex_data(ctx->ssl, ssl_app_data_index, conn)) {
6212 SSL_free(ctx->ssl);
6213 ctx->ssl = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01006214 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01006215 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01006216 goto retry_accept;
6217 }
Emeric Brun55476152014-11-12 17:35:37 +01006218 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006219 goto err;
Emeric Brun55476152014-11-12 17:35:37 +01006220 }
6221
Frédéric Lécaille3139c1b2020-01-24 14:56:18 +01006222#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
6223 if (__objt_listener(conn->target)->bind_conf->ssl_conf.early_data) {
6224 b_alloc(&ctx->early_buf);
6225 SSL_set_max_early_data(ctx->ssl,
6226 /* Only allow early data if we managed to allocate
6227 * a buffer.
6228 */
6229 (!b_is_null(&ctx->early_buf)) ?
6230 global.tune.bufsize - global.tune.maxrewrite : 0);
6231 }
6232#endif
6233
Olivier Houchard66ab4982019-02-26 18:37:15 +01006234 SSL_set_accept_state(ctx->ssl);
Emeric Brune1f38db2012-09-03 20:36:47 +02006235
Emeric Brun46591952012-05-18 15:47:34 +02006236 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +02006237 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Emmanuel Hocdetf967c312019-08-05 18:04:16 +02006238#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Olivier Houchardc2aae742017-09-22 18:26:28 +02006239 conn->flags |= CO_FL_EARLY_SSL_HS;
6240#endif
Willy Tarreau403edff2012-09-06 11:58:37 +02006241
Olivier Houchard2be5a4c2019-03-08 18:54:43 +01006242 _HA_ATOMIC_ADD(&sslconns, 1);
6243 _HA_ATOMIC_ADD(&totalsslconns, 1);
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006244 *xprt_ctx = ctx;
Olivier Houchardea8dd942019-05-20 14:02:16 +02006245 /* Start the handshake */
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02006246 tasklet_wakeup(ctx->wait_event.tasklet);
Emeric Brun46591952012-05-18 15:47:34 +02006247 return 0;
6248 }
6249 /* don't know how to handle such a target */
Willy Tarreau20879a02012-12-03 16:32:10 +01006250 conn->err_code = CO_ER_SSL_NO_TARGET;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006251err:
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02006252 if (ctx && ctx->wait_event.tasklet)
6253 tasklet_free(ctx->wait_event.tasklet);
Olivier Houchard66ab4982019-02-26 18:37:15 +01006254 pool_free(ssl_sock_ctx_pool, ctx);
Emeric Brun46591952012-05-18 15:47:34 +02006255 return -1;
6256}
6257
6258
6259/* This is the callback which is used when an SSL handshake is pending. It
6260 * updates the FD status if it wants some polling before being called again.
6261 * It returns 0 if it fails in a fatal way or needs to poll to go further,
6262 * otherwise it returns non-zero and removes itself from the connection's
6263 * flags (the bit is provided in <flag> by the caller).
6264 */
Olivier Houchard000694c2019-05-23 14:45:12 +02006265static int ssl_sock_handshake(struct connection *conn, unsigned int flag)
Emeric Brun46591952012-05-18 15:47:34 +02006266{
Olivier Houchard66ab4982019-02-26 18:37:15 +01006267 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
Emeric Brun46591952012-05-18 15:47:34 +02006268 int ret;
6269
Willy Tarreau3c728722014-01-23 13:50:42 +01006270 if (!conn_ctrl_ready(conn))
Willy Tarreauf79c8172013-10-21 16:30:56 +02006271 return 0;
6272
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02006273 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02006274 goto out_error;
6275
Willy Tarreau5db847a2019-05-09 14:13:35 +02006276#if HA_OPENSSL_VERSION_NUMBER >= 0x10101000L
Olivier Houchardc2aae742017-09-22 18:26:28 +02006277 /*
6278 * Check if we have early data. If we do, we have to read them
6279 * before SSL_do_handshake() is called, And there's no way to
6280 * detect early data, except to try to read them
6281 */
6282 if (conn->flags & CO_FL_EARLY_SSL_HS) {
Olivier Houchard54907bb2019-12-19 15:02:39 +01006283 size_t read_data = 0;
Olivier Houchardc2aae742017-09-22 18:26:28 +02006284
Olivier Houchard54907bb2019-12-19 15:02:39 +01006285 while (1) {
6286 ret = SSL_read_early_data(ctx->ssl,
6287 b_tail(&ctx->early_buf), b_room(&ctx->early_buf),
6288 &read_data);
6289 if (ret == SSL_READ_EARLY_DATA_ERROR)
6290 goto check_error;
6291 if (read_data > 0) {
6292 conn->flags |= CO_FL_EARLY_DATA;
6293 b_add(&ctx->early_buf, read_data);
6294 }
6295 if (ret == SSL_READ_EARLY_DATA_FINISH) {
6296 conn->flags &= ~CO_FL_EARLY_SSL_HS;
6297 if (!b_data(&ctx->early_buf))
6298 b_free(&ctx->early_buf);
6299 break;
6300 }
6301 }
Olivier Houchardc2aae742017-09-22 18:26:28 +02006302 }
6303#endif
Emeric Brun674b7432012-11-08 19:21:55 +01006304 /* If we use SSL_do_handshake to process a reneg initiated by
6305 * the remote peer, it sometimes returns SSL_ERROR_SSL.
6306 * Usually SSL_write and SSL_read are used and process implicitly
6307 * the reneg handshake.
6308 * Here we use SSL_peek as a workaround for reneg.
6309 */
Willy Tarreauc192b0a2020-01-23 09:11:58 +01006310 if (!(conn->flags & CO_FL_WAIT_L6_CONN) && SSL_renegotiate_pending(ctx->ssl)) {
Emeric Brun674b7432012-11-08 19:21:55 +01006311 char c;
6312
Olivier Houchard66ab4982019-02-26 18:37:15 +01006313 ret = SSL_peek(ctx->ssl, &c, 1);
Emeric Brun674b7432012-11-08 19:21:55 +01006314 if (ret <= 0) {
6315 /* handshake may have not been completed, let's find why */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006316 ret = SSL_get_error(ctx->ssl, ret);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006317
Emeric Brun674b7432012-11-08 19:21:55 +01006318 if (ret == SSL_ERROR_WANT_WRITE) {
6319 /* SSL handshake needs to write, L4 connection may not be ready */
Olivier Houchard03abf2d2019-05-28 10:12:02 +02006320 if (!(ctx->wait_event.events & SUB_RETRY_SEND))
Olivier Houchardea8dd942019-05-20 14:02:16 +02006321 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_SEND, &ctx->wait_event);
Emeric Brun674b7432012-11-08 19:21:55 +01006322 return 0;
6323 }
6324 else if (ret == SSL_ERROR_WANT_READ) {
6325 /* handshake may have been completed but we have
6326 * no more data to read.
6327 */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006328 if (!SSL_renegotiate_pending(ctx->ssl)) {
Emeric Brun674b7432012-11-08 19:21:55 +01006329 ret = 1;
6330 goto reneg_ok;
6331 }
6332 /* SSL handshake needs to read, L4 connection is ready */
Olivier Houchard03abf2d2019-05-28 10:12:02 +02006333 if (!(ctx->wait_event.events & SUB_RETRY_RECV))
Olivier Houchardea8dd942019-05-20 14:02:16 +02006334 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_RECV, &ctx->wait_event);
Emeric Brun674b7432012-11-08 19:21:55 +01006335 return 0;
6336 }
Willy Tarreau5db847a2019-05-09 14:13:35 +02006337#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006338 else if (ret == SSL_ERROR_WANT_ASYNC) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02006339 ssl_async_process_fds(ctx);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006340 return 0;
6341 }
6342#endif
Emeric Brun674b7432012-11-08 19:21:55 +01006343 else if (ret == SSL_ERROR_SYSCALL) {
6344 /* if errno is null, then connection was successfully established */
6345 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
6346 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Willy Tarreau20879a02012-12-03 16:32:10 +01006347 if (!conn->err_code) {
Lukas Tribus49799162019-07-08 14:29:15 +02006348#if defined(OPENSSL_IS_BORINGSSL) || defined(LIBRESSL_VERSION_NUMBER)
6349 /* do not handle empty handshakes in BoringSSL or LibreSSL */
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01006350 conn->err_code = CO_ER_SSL_HANDSHAKE;
6351#else
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006352 int empty_handshake;
Willy Tarreau5db847a2019-05-09 14:13:35 +02006353#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL)
Lukas Tribus49799162019-07-08 14:29:15 +02006354 /* use SSL_get_state() in OpenSSL >= 1.1.0; SSL_state() is broken */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006355 OSSL_HANDSHAKE_STATE state = SSL_get_state((SSL *)ctx->ssl);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006356 empty_handshake = state == TLS_ST_BEFORE;
6357#else
Lukas Tribus49799162019-07-08 14:29:15 +02006358 /* access packet_length directly in OpenSSL <= 1.0.2; SSL_state() is broken */
6359 empty_handshake = !ctx->ssl->packet_length;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006360#endif
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006361 if (empty_handshake) {
Emeric Brun29f037d2014-04-25 19:05:36 +02006362 if (!errno) {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006363 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emeric Brun29f037d2014-04-25 19:05:36 +02006364 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
6365 else
6366 conn->err_code = CO_ER_SSL_EMPTY;
6367 }
6368 else {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006369 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emeric Brun29f037d2014-04-25 19:05:36 +02006370 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
6371 else
6372 conn->err_code = CO_ER_SSL_ABORT;
6373 }
6374 }
6375 else {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006376 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emeric Brun29f037d2014-04-25 19:05:36 +02006377 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
Willy Tarreau20879a02012-12-03 16:32:10 +01006378 else
Emeric Brun29f037d2014-04-25 19:05:36 +02006379 conn->err_code = CO_ER_SSL_HANDSHAKE;
6380 }
Lukas Tribus49799162019-07-08 14:29:15 +02006381#endif /* BoringSSL or LibreSSL */
Willy Tarreau20879a02012-12-03 16:32:10 +01006382 }
Emeric Brun674b7432012-11-08 19:21:55 +01006383 goto out_error;
6384 }
6385 else {
6386 /* Fail on all other handshake errors */
6387 /* Note: OpenSSL may leave unread bytes in the socket's
6388 * buffer, causing an RST to be emitted upon close() on
6389 * TCP sockets. We first try to drain possibly pending
6390 * data to avoid this as much as possible.
6391 */
Willy Tarreaud85c4852015-03-13 00:40:28 +01006392 conn_sock_drain(conn);
Willy Tarreau20879a02012-12-03 16:32:10 +01006393 if (!conn->err_code)
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006394 conn->err_code = (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT) ?
Willy Tarreauf51c6982014-04-25 20:02:39 +02006395 CO_ER_SSL_KILLED_HB : CO_ER_SSL_HANDSHAKE;
Emeric Brun674b7432012-11-08 19:21:55 +01006396 goto out_error;
6397 }
6398 }
6399 /* read some data: consider handshake completed */
6400 goto reneg_ok;
6401 }
Olivier Houchard66ab4982019-02-26 18:37:15 +01006402 ret = SSL_do_handshake(ctx->ssl);
Olivier Houchardc2aae742017-09-22 18:26:28 +02006403check_error:
Emeric Brun46591952012-05-18 15:47:34 +02006404 if (ret != 1) {
6405 /* handshake did not complete, let's find why */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006406 ret = SSL_get_error(ctx->ssl, ret);
Emeric Brun46591952012-05-18 15:47:34 +02006407
6408 if (ret == SSL_ERROR_WANT_WRITE) {
6409 /* SSL handshake needs to write, L4 connection may not be ready */
Olivier Houchard03abf2d2019-05-28 10:12:02 +02006410 if (!(ctx->wait_event.events & SUB_RETRY_SEND))
Olivier Houchardea8dd942019-05-20 14:02:16 +02006411 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_SEND, &ctx->wait_event);
Emeric Brun46591952012-05-18 15:47:34 +02006412 return 0;
6413 }
6414 else if (ret == SSL_ERROR_WANT_READ) {
6415 /* SSL handshake needs to read, L4 connection is ready */
Olivier Houchardea8dd942019-05-20 14:02:16 +02006416 if (!(ctx->wait_event.events & SUB_RETRY_RECV))
Olivier Houchardea8dd942019-05-20 14:02:16 +02006417 ctx->xprt->subscribe(conn, ctx->xprt_ctx,
6418 SUB_RETRY_RECV, &ctx->wait_event);
Emeric Brun46591952012-05-18 15:47:34 +02006419 return 0;
6420 }
Willy Tarreau5db847a2019-05-09 14:13:35 +02006421#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006422 else if (ret == SSL_ERROR_WANT_ASYNC) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02006423 ssl_async_process_fds(ctx);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006424 return 0;
6425 }
6426#endif
Willy Tarreau89230192012-09-28 20:22:13 +02006427 else if (ret == SSL_ERROR_SYSCALL) {
6428 /* if errno is null, then connection was successfully established */
6429 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
6430 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01006431 if (!conn->err_code) {
Lukas Tribus49799162019-07-08 14:29:15 +02006432#if defined(OPENSSL_IS_BORINGSSL) || defined(LIBRESSL_VERSION_NUMBER)
6433 /* do not handle empty handshakes in BoringSSL or LibreSSL */
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01006434 conn->err_code = CO_ER_SSL_HANDSHAKE;
6435#else
6436 int empty_handshake;
Willy Tarreau5db847a2019-05-09 14:13:35 +02006437#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL)
Lukas Tribus49799162019-07-08 14:29:15 +02006438 /* use SSL_get_state() in OpenSSL >= 1.1.0; SSL_state() is broken */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006439 OSSL_HANDSHAKE_STATE state = SSL_get_state(ctx->ssl);
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01006440 empty_handshake = state == TLS_ST_BEFORE;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006441#else
Lukas Tribus49799162019-07-08 14:29:15 +02006442 /* access packet_length directly in OpenSSL <= 1.0.2; SSL_state() is broken */
6443 empty_handshake = !ctx->ssl->packet_length;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006444#endif
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01006445 if (empty_handshake) {
6446 if (!errno) {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006447 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01006448 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
6449 else
6450 conn->err_code = CO_ER_SSL_EMPTY;
6451 }
6452 else {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006453 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01006454 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
6455 else
6456 conn->err_code = CO_ER_SSL_ABORT;
6457 }
Emeric Brun29f037d2014-04-25 19:05:36 +02006458 }
6459 else {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006460 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emeric Brun29f037d2014-04-25 19:05:36 +02006461 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
6462 else
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01006463 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun29f037d2014-04-25 19:05:36 +02006464 }
Lukas Tribus49799162019-07-08 14:29:15 +02006465#endif /* BoringSSL or LibreSSL */
Emeric Brun29f037d2014-04-25 19:05:36 +02006466 }
Willy Tarreau89230192012-09-28 20:22:13 +02006467 goto out_error;
6468 }
Emeric Brun46591952012-05-18 15:47:34 +02006469 else {
6470 /* Fail on all other handshake errors */
Willy Tarreau566dc552012-10-19 20:52:18 +02006471 /* Note: OpenSSL may leave unread bytes in the socket's
6472 * buffer, causing an RST to be emitted upon close() on
6473 * TCP sockets. We first try to drain possibly pending
6474 * data to avoid this as much as possible.
6475 */
Willy Tarreaud85c4852015-03-13 00:40:28 +01006476 conn_sock_drain(conn);
Willy Tarreau20879a02012-12-03 16:32:10 +01006477 if (!conn->err_code)
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006478 conn->err_code = (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT) ?
Willy Tarreauf51c6982014-04-25 20:02:39 +02006479 CO_ER_SSL_KILLED_HB : CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02006480 goto out_error;
6481 }
6482 }
Willy Tarreau5db847a2019-05-09 14:13:35 +02006483#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Olivier Houchard522eea72017-11-03 16:27:47 +01006484 else {
6485 /*
6486 * If the server refused the early data, we have to send a
6487 * 425 to the client, as we no longer have the data to sent
6488 * them again.
6489 */
6490 if ((conn->flags & CO_FL_EARLY_DATA) && (objt_server(conn->target))) {
Olivier Houchard66ab4982019-02-26 18:37:15 +01006491 if (SSL_get_early_data_status(ctx->ssl) == SSL_EARLY_DATA_REJECTED) {
Olivier Houchard522eea72017-11-03 16:27:47 +01006492 conn->err_code = CO_ER_SSL_EARLY_FAILED;
6493 goto out_error;
6494 }
6495 }
6496 }
6497#endif
6498
Emeric Brun46591952012-05-18 15:47:34 +02006499
Emeric Brun674b7432012-11-08 19:21:55 +01006500reneg_ok:
Emeric Brunb5e42a82017-06-06 12:35:14 +00006501
Willy Tarreau5db847a2019-05-09 14:13:35 +02006502#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00006503 /* ASYNC engine API doesn't support moving read/write
6504 * buffers. So we disable ASYNC mode right after
6505 * the handshake to avoid buffer oveflows.
6506 */
6507 if (global_ssl.async)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006508 SSL_clear_mode(ctx->ssl, SSL_MODE_ASYNC);
Emeric Brunb5e42a82017-06-06 12:35:14 +00006509#endif
Emeric Brun46591952012-05-18 15:47:34 +02006510 /* Handshake succeeded */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006511 if (!SSL_session_reused(ctx->ssl)) {
Willy Tarreau0c9c2722014-05-28 12:28:58 +02006512 if (objt_server(conn->target)) {
6513 update_freq_ctr(&global.ssl_be_keys_per_sec, 1);
6514 if (global.ssl_be_keys_per_sec.curr_ctr > global.ssl_be_keys_max)
6515 global.ssl_be_keys_max = global.ssl_be_keys_per_sec.curr_ctr;
Emeric Brun46591952012-05-18 15:47:34 +02006516 }
Willy Tarreau0c9c2722014-05-28 12:28:58 +02006517 else {
6518 update_freq_ctr(&global.ssl_fe_keys_per_sec, 1);
6519 if (global.ssl_fe_keys_per_sec.curr_ctr > global.ssl_fe_keys_max)
6520 global.ssl_fe_keys_max = global.ssl_fe_keys_per_sec.curr_ctr;
6521 }
Emeric Brun46591952012-05-18 15:47:34 +02006522 }
6523
6524 /* The connection is now established at both layers, it's time to leave */
6525 conn->flags &= ~(flag | CO_FL_WAIT_L4_CONN | CO_FL_WAIT_L6_CONN);
6526 return 1;
6527
6528 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01006529 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02006530 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01006531 ERR_clear_error();
6532
Emeric Brun9fa89732012-10-04 17:09:56 +02006533 /* free resumed session if exists */
Willy Tarreau07d94e42018-09-20 10:57:52 +02006534 if (objt_server(conn->target) && __objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr) {
6535 free(__objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr);
6536 __objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr = NULL;
Emeric Brun9fa89732012-10-04 17:09:56 +02006537 }
6538
Emeric Brun46591952012-05-18 15:47:34 +02006539 /* Fail on all other handshake errors */
6540 conn->flags |= CO_FL_ERROR;
Willy Tarreau20879a02012-12-03 16:32:10 +01006541 if (!conn->err_code)
6542 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02006543 return 0;
6544}
6545
Willy Tarreauee1a6fc2020-01-17 07:52:13 +01006546/* Called from the upper layer, to subscribe <es> to events <event_type>. The
6547 * event subscriber <es> is not allowed to change from a previous call as long
6548 * as at least one event is still subscribed. The <event_type> must only be a
6549 * combination of SUB_RETRY_RECV and SUB_RETRY_SEND. It always returns 0,
6550 * unless the transport layer was already released.
6551 */
6552static int ssl_subscribe(struct connection *conn, void *xprt_ctx, int event_type, struct wait_event *es)
Olivier Houcharddf357842019-03-21 16:30:07 +01006553{
Olivier Houchardea8dd942019-05-20 14:02:16 +02006554 struct ssl_sock_ctx *ctx = xprt_ctx;
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006555
Olivier Houchard0ff28652019-06-24 18:57:39 +02006556 if (!ctx)
6557 return -1;
6558
Willy Tarreau113d52b2020-01-10 09:20:26 +01006559 BUG_ON(event_type & ~(SUB_RETRY_SEND|SUB_RETRY_RECV));
Willy Tarreauee1a6fc2020-01-17 07:52:13 +01006560 BUG_ON(ctx->subs && ctx->subs != es);
Olivier Houchardea8dd942019-05-20 14:02:16 +02006561
Willy Tarreauee1a6fc2020-01-17 07:52:13 +01006562 ctx->subs = es;
6563 es->events |= event_type;
Willy Tarreau113d52b2020-01-10 09:20:26 +01006564
6565 /* we may have to subscribe to lower layers for new events */
6566 event_type &= ~ctx->wait_event.events;
6567 if (event_type && !(conn->flags & CO_FL_SSL_WAIT_HS))
6568 ctx->xprt->subscribe(conn, ctx->xprt_ctx, event_type, &ctx->wait_event);
Olivier Houchardea8dd942019-05-20 14:02:16 +02006569 return 0;
Olivier Houcharddf357842019-03-21 16:30:07 +01006570}
6571
Willy Tarreauee1a6fc2020-01-17 07:52:13 +01006572/* Called from the upper layer, to unsubscribe <es> from events <event_type>.
6573 * The <es> pointer is not allowed to differ from the one passed to the
6574 * subscribe() call. It always returns zero.
6575 */
6576static int ssl_unsubscribe(struct connection *conn, void *xprt_ctx, int event_type, struct wait_event *es)
Olivier Houcharddf357842019-03-21 16:30:07 +01006577{
Olivier Houchardea8dd942019-05-20 14:02:16 +02006578 struct ssl_sock_ctx *ctx = xprt_ctx;
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006579
Willy Tarreau113d52b2020-01-10 09:20:26 +01006580 BUG_ON(event_type & ~(SUB_RETRY_SEND|SUB_RETRY_RECV));
Willy Tarreauee1a6fc2020-01-17 07:52:13 +01006581 BUG_ON(ctx->subs && ctx->subs != es);
Olivier Houchardea8dd942019-05-20 14:02:16 +02006582
Willy Tarreauee1a6fc2020-01-17 07:52:13 +01006583 es->events &= ~event_type;
6584 if (!es->events)
Willy Tarreau113d52b2020-01-10 09:20:26 +01006585 ctx->subs = NULL;
6586
6587 /* If we subscribed, and we're not doing the handshake,
6588 * then we subscribed because the upper layer asked for it,
6589 * as the upper layer is no longer interested, we can
6590 * unsubscribe too.
6591 */
6592 event_type &= ctx->wait_event.events;
6593 if (event_type && !(ctx->conn->flags & CO_FL_SSL_WAIT_HS))
6594 conn_unsubscribe(conn, ctx->xprt_ctx, event_type, &ctx->wait_event);
Olivier Houchardea8dd942019-05-20 14:02:16 +02006595
6596 return 0;
Olivier Houcharddf357842019-03-21 16:30:07 +01006597}
6598
Olivier Houchard2e055482019-05-27 19:50:12 +02006599/* Use the provided XPRT as an underlying XPRT, and provide the old one.
6600 * Returns 0 on success, and non-zero on failure.
6601 */
6602static 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)
6603{
6604 struct ssl_sock_ctx *ctx = xprt_ctx;
6605
6606 if (oldxprt_ops != NULL)
6607 *oldxprt_ops = ctx->xprt;
6608 if (oldxprt_ctx != NULL)
6609 *oldxprt_ctx = ctx->xprt_ctx;
6610 ctx->xprt = toadd_ops;
6611 ctx->xprt_ctx = toadd_ctx;
6612 return 0;
6613}
6614
Olivier Houchard5149b592019-05-23 17:47:36 +02006615/* Remove the specified xprt. If if it our underlying XPRT, remove it and
6616 * return 0, otherwise just call the remove_xprt method from the underlying
6617 * XPRT.
6618 */
6619static int ssl_remove_xprt(struct connection *conn, void *xprt_ctx, void *toremove_ctx, const struct xprt_ops *newops, void *newctx)
6620{
6621 struct ssl_sock_ctx *ctx = xprt_ctx;
6622
6623 if (ctx->xprt_ctx == toremove_ctx) {
6624 ctx->xprt_ctx = newctx;
6625 ctx->xprt = newops;
6626 return 0;
6627 }
6628 return (ctx->xprt->remove_xprt(conn, ctx->xprt_ctx, toremove_ctx, newops, newctx));
6629}
6630
Olivier Houchardea8dd942019-05-20 14:02:16 +02006631static struct task *ssl_sock_io_cb(struct task *t, void *context, unsigned short state)
6632{
6633 struct ssl_sock_ctx *ctx = context;
6634
6635 /* First if we're doing an handshake, try that */
6636 if (ctx->conn->flags & CO_FL_SSL_WAIT_HS)
6637 ssl_sock_handshake(ctx->conn, CO_FL_SSL_WAIT_HS);
6638 /* If we had an error, or the handshake is done and I/O is available,
6639 * let the upper layer know.
Olivier Houchard477902b2020-01-22 18:08:48 +01006640 * If no mux was set up yet, then call conn_create_mux()
Olivier Houchardea8dd942019-05-20 14:02:16 +02006641 * we can't be sure conn_fd_handler() will be called again.
6642 */
6643 if ((ctx->conn->flags & CO_FL_ERROR) ||
6644 !(ctx->conn->flags & CO_FL_SSL_WAIT_HS)) {
6645 int ret = 0;
6646 int woke = 0;
6647
6648 /* On error, wake any waiter */
Willy Tarreau113d52b2020-01-10 09:20:26 +01006649 if (ctx->subs) {
6650 tasklet_wakeup(ctx->subs->tasklet);
6651 ctx->subs->events = 0;
Olivier Houchardea8dd942019-05-20 14:02:16 +02006652 woke = 1;
Willy Tarreau113d52b2020-01-10 09:20:26 +01006653 ctx->subs = NULL;
Olivier Houchardea8dd942019-05-20 14:02:16 +02006654 }
Willy Tarreau113d52b2020-01-10 09:20:26 +01006655
Olivier Houchardea8dd942019-05-20 14:02:16 +02006656 /* If we're the first xprt for the connection, let the
Olivier Houchard477902b2020-01-22 18:08:48 +01006657 * upper layers know. If we have no mux, create it,
6658 * and once we have a mux, call its wake method if we didn't
6659 * woke a tasklet already.
Olivier Houchardea8dd942019-05-20 14:02:16 +02006660 */
6661 if (ctx->conn->xprt_ctx == ctx) {
Olivier Houchard477902b2020-01-22 18:08:48 +01006662 if (!ctx->conn->mux)
6663 ret = conn_create_mux(ctx->conn);
Olivier Houchardea8dd942019-05-20 14:02:16 +02006664 if (ret >= 0 && !woke && ctx->conn->mux && ctx->conn->mux->wake)
6665 ctx->conn->mux->wake(ctx->conn);
6666 return NULL;
6667 }
6668 }
Olivier Houchard54907bb2019-12-19 15:02:39 +01006669#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
6670 /* If we have early data and somebody wants to receive, let them */
Willy Tarreau113d52b2020-01-10 09:20:26 +01006671 else if (b_data(&ctx->early_buf) && ctx->subs &&
6672 ctx->subs->events & SUB_RETRY_RECV) {
6673 tasklet_wakeup(ctx->subs->tasklet);
6674 ctx->subs->events &= ~SUB_RETRY_RECV;
6675 if (!ctx->subs->events)
6676 ctx->subs = NULL;
Olivier Houchard54907bb2019-12-19 15:02:39 +01006677 }
6678#endif
Olivier Houchardea8dd942019-05-20 14:02:16 +02006679 return NULL;
6680}
6681
Emeric Brun46591952012-05-18 15:47:34 +02006682/* Receive up to <count> bytes from connection <conn>'s socket and store them
Willy Tarreauabf08d92014-01-14 11:31:27 +01006683 * into buffer <buf>. Only one call to recv() is performed, unless the
Emeric Brun46591952012-05-18 15:47:34 +02006684 * buffer wraps, in which case a second call may be performed. The connection's
6685 * flags are updated with whatever special event is detected (error, read0,
6686 * empty). The caller is responsible for taking care of those events and
6687 * avoiding the call if inappropriate. The function does not call the
6688 * connection's polling update function, so the caller is responsible for this.
6689 */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006690static 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 +02006691{
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006692 struct ssl_sock_ctx *ctx = xprt_ctx;
Willy Tarreaubfc4d772018-07-18 11:22:03 +02006693 ssize_t ret;
6694 size_t try, done = 0;
Emeric Brun46591952012-05-18 15:47:34 +02006695
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006696 if (!ctx)
Emeric Brun46591952012-05-18 15:47:34 +02006697 goto out_error;
6698
Olivier Houchard54907bb2019-12-19 15:02:39 +01006699#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
6700 if (b_data(&ctx->early_buf)) {
6701 try = b_contig_space(buf);
6702 if (try > b_data(&ctx->early_buf))
6703 try = b_data(&ctx->early_buf);
6704 memcpy(b_tail(buf), b_head(&ctx->early_buf), try);
6705 b_add(buf, try);
6706 b_del(&ctx->early_buf, try);
6707 if (b_data(&ctx->early_buf) == 0)
6708 b_free(&ctx->early_buf);
6709 return try;
6710 }
6711#endif
6712
Willy Tarreau911db9b2020-01-23 16:27:54 +01006713 if (conn->flags & (CO_FL_WAIT_XPRT | CO_FL_SSL_WAIT_HS))
Emeric Brun46591952012-05-18 15:47:34 +02006714 /* a handshake was requested */
6715 return 0;
6716
Emeric Brun46591952012-05-18 15:47:34 +02006717 /* read the largest possible block. For this, we perform only one call
6718 * to recv() unless the buffer wraps and we exactly fill the first hunk,
6719 * in which case we accept to do it once again. A new attempt is made on
6720 * EINTR too.
6721 */
Willy Tarreau00b0fb92014-01-17 11:09:40 +01006722 while (count > 0) {
Olivier Houchardc2aae742017-09-22 18:26:28 +02006723
Willy Tarreau591d4452018-06-15 17:21:00 +02006724 try = b_contig_space(buf);
6725 if (!try)
6726 break;
6727
Willy Tarreauabf08d92014-01-14 11:31:27 +01006728 if (try > count)
6729 try = count;
Willy Tarreau591d4452018-06-15 17:21:00 +02006730
Olivier Houchard66ab4982019-02-26 18:37:15 +01006731 ret = SSL_read(ctx->ssl, b_tail(buf), try);
Emmanuel Hocdetf967c312019-08-05 18:04:16 +02006732
Emeric Brune1f38db2012-09-03 20:36:47 +02006733 if (conn->flags & CO_FL_ERROR) {
6734 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01006735 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02006736 }
Emeric Brun46591952012-05-18 15:47:34 +02006737 if (ret > 0) {
Olivier Houchardacd14032018-06-28 18:17:23 +02006738 b_add(buf, ret);
Emeric Brun46591952012-05-18 15:47:34 +02006739 done += ret;
Emeric Brun46591952012-05-18 15:47:34 +02006740 count -= ret;
Emeric Brun46591952012-05-18 15:47:34 +02006741 }
Emeric Brun46591952012-05-18 15:47:34 +02006742 else {
Olivier Houchard66ab4982019-02-26 18:37:15 +01006743 ret = SSL_get_error(ctx->ssl, ret);
Emeric Brun46591952012-05-18 15:47:34 +02006744 if (ret == SSL_ERROR_WANT_WRITE) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01006745 /* handshake is running, and it needs to enable write */
Emeric Brun46591952012-05-18 15:47:34 +02006746 conn->flags |= CO_FL_SSL_WAIT_HS;
Olivier Houchardea8dd942019-05-20 14:02:16 +02006747 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_SEND, &ctx->wait_event);
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 Brun46591952012-05-18 15:47:34 +02006753 break;
6754 }
6755 else if (ret == SSL_ERROR_WANT_READ) {
Olivier Houchard66ab4982019-02-26 18:37:15 +01006756 if (SSL_renegotiate_pending(ctx->ssl)) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02006757 ctx->xprt->subscribe(conn, ctx->xprt_ctx,
6758 SUB_RETRY_RECV,
6759 &ctx->wait_event);
Emeric Brun282a76a2012-11-08 18:02:56 +01006760 /* handshake is running, and it may need to re-enable read */
6761 conn->flags |= CO_FL_SSL_WAIT_HS;
Willy Tarreau5db847a2019-05-09 14:13:35 +02006762#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00006763 /* Async mode can be re-enabled, because we're leaving data state.*/
6764 if (global_ssl.async)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006765 SSL_set_mode(ctx->ssl, SSL_MODE_ASYNC);
Emeric Brunb5e42a82017-06-06 12:35:14 +00006766#endif
Emeric Brun282a76a2012-11-08 18:02:56 +01006767 break;
6768 }
Emeric Brun46591952012-05-18 15:47:34 +02006769 break;
Olivier Houchardc2aae742017-09-22 18:26:28 +02006770 } else if (ret == SSL_ERROR_ZERO_RETURN)
6771 goto read0;
Christopher Faulet4ac77a92018-02-19 14:25:15 +01006772 /* For SSL_ERROR_SYSCALL, make sure to clear the error
6773 * stack before shutting down the connection for
6774 * reading. */
Olivier Houchard7e2e5052018-02-13 15:17:23 +01006775 if (ret == SSL_ERROR_SYSCALL && (!errno || errno == EAGAIN))
6776 goto clear_ssl_error;
Emeric Brun46591952012-05-18 15:47:34 +02006777 /* otherwise it's a real error */
6778 goto out_error;
6779 }
6780 }
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02006781 leave:
Emeric Brun46591952012-05-18 15:47:34 +02006782 return done;
6783
Christopher Faulet4ac77a92018-02-19 14:25:15 +01006784 clear_ssl_error:
6785 /* Clear openssl global errors stack */
6786 ssl_sock_dump_errors(conn);
6787 ERR_clear_error();
Emeric Brun46591952012-05-18 15:47:34 +02006788 read0:
6789 conn_sock_read0(conn);
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02006790 goto leave;
Christopher Faulet4ac77a92018-02-19 14:25:15 +01006791
Emeric Brun46591952012-05-18 15:47:34 +02006792 out_error:
Olivier Houchard7e2e5052018-02-13 15:17:23 +01006793 conn->flags |= CO_FL_ERROR;
Emeric Brun644cde02012-12-14 11:21:13 +01006794 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02006795 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01006796 ERR_clear_error();
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02006797 goto leave;
Emeric Brun46591952012-05-18 15:47:34 +02006798}
6799
6800
Willy Tarreau787db9a2018-06-14 18:31:46 +02006801/* Send up to <count> pending bytes from buffer <buf> to connection <conn>'s
6802 * socket. <flags> may contain some CO_SFL_* flags to hint the system about
6803 * other pending data for example, but this flag is ignored at the moment.
Emeric Brun46591952012-05-18 15:47:34 +02006804 * Only one call to send() is performed, unless the buffer wraps, in which case
6805 * a second call may be performed. The connection's flags are updated with
6806 * whatever special event is detected (error, empty). The caller is responsible
6807 * for taking care of those events and avoiding the call if inappropriate. The
6808 * function does not call the connection's polling update function, so the caller
Willy Tarreau787db9a2018-06-14 18:31:46 +02006809 * is responsible for this. The buffer's output is not adjusted, it's up to the
6810 * caller to take care of this. It's up to the caller to update the buffer's
6811 * contents based on the return value.
Emeric Brun46591952012-05-18 15:47:34 +02006812 */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006813static 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 +02006814{
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006815 struct ssl_sock_ctx *ctx = xprt_ctx;
Willy Tarreau787db9a2018-06-14 18:31:46 +02006816 ssize_t ret;
6817 size_t try, done;
Emeric Brun46591952012-05-18 15:47:34 +02006818
6819 done = 0;
6820
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006821 if (!ctx)
Emeric Brun46591952012-05-18 15:47:34 +02006822 goto out_error;
6823
Willy Tarreau911db9b2020-01-23 16:27:54 +01006824 if (conn->flags & (CO_FL_WAIT_XPRT | CO_FL_SSL_WAIT_HS | CO_FL_EARLY_SSL_HS))
Emeric Brun46591952012-05-18 15:47:34 +02006825 /* a handshake was requested */
6826 return 0;
6827
6828 /* send the largest possible block. For this we perform only one call
6829 * to send() unless the buffer wraps and we exactly fill the first hunk,
6830 * in which case we accept to do it once again.
6831 */
Willy Tarreau787db9a2018-06-14 18:31:46 +02006832 while (count) {
Willy Tarreau5db847a2019-05-09 14:13:35 +02006833#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Olivier Houchardc2aae742017-09-22 18:26:28 +02006834 size_t written_data;
6835#endif
6836
Willy Tarreau787db9a2018-06-14 18:31:46 +02006837 try = b_contig_data(buf, done);
6838 if (try > count)
6839 try = count;
Willy Tarreaubfd59462013-02-21 07:46:09 +01006840
Willy Tarreau7bed9452014-02-02 02:00:24 +01006841 if (!(flags & CO_SFL_STREAMER) &&
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006842 !(ctx->xprt_st & SSL_SOCK_SEND_UNLIMITED) &&
Willy Tarreauef934602016-12-22 23:12:01 +01006843 global_ssl.max_record && try > global_ssl.max_record) {
6844 try = global_ssl.max_record;
Willy Tarreau518cedd2014-02-17 15:43:01 +01006845 }
6846 else {
6847 /* we need to keep the information about the fact that
6848 * we're not limiting the upcoming send(), because if it
6849 * fails, we'll have to retry with at least as many data.
6850 */
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006851 ctx->xprt_st |= SSL_SOCK_SEND_UNLIMITED;
Willy Tarreau518cedd2014-02-17 15:43:01 +01006852 }
Willy Tarreaubfd59462013-02-21 07:46:09 +01006853
Willy Tarreau5db847a2019-05-09 14:13:35 +02006854#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Olivier Houchard010941f2019-05-03 20:56:19 +02006855 if (!SSL_is_init_finished(ctx->ssl) && conn_is_back(conn)) {
Olivier Houchardc2aae742017-09-22 18:26:28 +02006856 unsigned int max_early;
6857
Olivier Houchard522eea72017-11-03 16:27:47 +01006858 if (objt_listener(conn->target))
Olivier Houchard66ab4982019-02-26 18:37:15 +01006859 max_early = SSL_get_max_early_data(ctx->ssl);
Olivier Houchard522eea72017-11-03 16:27:47 +01006860 else {
Olivier Houchard66ab4982019-02-26 18:37:15 +01006861 if (SSL_get0_session(ctx->ssl))
6862 max_early = SSL_SESSION_get_max_early_data(SSL_get0_session(ctx->ssl));
Olivier Houchard522eea72017-11-03 16:27:47 +01006863 else
6864 max_early = 0;
6865 }
6866
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006867 if (try + ctx->sent_early_data > max_early) {
6868 try -= (try + ctx->sent_early_data) - max_early;
Olivier Houchard522eea72017-11-03 16:27:47 +01006869 if (try <= 0) {
Olivier Houchard010941f2019-05-03 20:56:19 +02006870 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Olivier Houchard965e84e2019-06-15 20:59:30 +02006871 tasklet_wakeup(ctx->wait_event.tasklet);
Olivier Houchardc2aae742017-09-22 18:26:28 +02006872 break;
Olivier Houchard522eea72017-11-03 16:27:47 +01006873 }
Olivier Houchardc2aae742017-09-22 18:26:28 +02006874 }
Olivier Houchard66ab4982019-02-26 18:37:15 +01006875 ret = SSL_write_early_data(ctx->ssl, b_peek(buf, done), try, &written_data);
Olivier Houchardc2aae742017-09-22 18:26:28 +02006876 if (ret == 1) {
6877 ret = written_data;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006878 ctx->sent_early_data += ret;
Olivier Houchard965e84e2019-06-15 20:59:30 +02006879 if (objt_server(conn->target)) {
Olivier Houchard522eea72017-11-03 16:27:47 +01006880 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN | CO_FL_EARLY_DATA;
Olivier Houchard965e84e2019-06-15 20:59:30 +02006881 /* Initiate the handshake, now */
6882 tasklet_wakeup(ctx->wait_event.tasklet);
6883 }
Olivier Houchard522eea72017-11-03 16:27:47 +01006884
Olivier Houchardc2aae742017-09-22 18:26:28 +02006885 }
6886
6887 } else
6888#endif
Olivier Houchard66ab4982019-02-26 18:37:15 +01006889 ret = SSL_write(ctx->ssl, b_peek(buf, done), try);
Willy Tarreau518cedd2014-02-17 15:43:01 +01006890
Emeric Brune1f38db2012-09-03 20:36:47 +02006891 if (conn->flags & CO_FL_ERROR) {
6892 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01006893 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02006894 }
Emeric Brun46591952012-05-18 15:47:34 +02006895 if (ret > 0) {
Willy Tarreauc192b0a2020-01-23 09:11:58 +01006896 /* A send succeeded, so we can consider ourself connected */
6897 conn->flags &= ~CO_FL_WAIT_L4L6;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006898 ctx->xprt_st &= ~SSL_SOCK_SEND_UNLIMITED;
Willy Tarreau787db9a2018-06-14 18:31:46 +02006899 count -= ret;
Emeric Brun46591952012-05-18 15:47:34 +02006900 done += ret;
Emeric Brun46591952012-05-18 15:47:34 +02006901 }
6902 else {
Olivier Houchard66ab4982019-02-26 18:37:15 +01006903 ret = SSL_get_error(ctx->ssl, ret);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006904
Emeric Brun46591952012-05-18 15:47:34 +02006905 if (ret == SSL_ERROR_WANT_WRITE) {
Olivier Houchard66ab4982019-02-26 18:37:15 +01006906 if (SSL_renegotiate_pending(ctx->ssl)) {
Emeric Brun282a76a2012-11-08 18:02:56 +01006907 /* handshake is running, and it may need to re-enable write */
6908 conn->flags |= CO_FL_SSL_WAIT_HS;
Olivier Houchardea8dd942019-05-20 14:02:16 +02006909 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_SEND, &ctx->wait_event);
Willy Tarreau5db847a2019-05-09 14:13:35 +02006910#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00006911 /* Async mode can be re-enabled, because we're leaving data state.*/
6912 if (global_ssl.async)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006913 SSL_set_mode(ctx->ssl, SSL_MODE_ASYNC);
Emeric Brunb5e42a82017-06-06 12:35:14 +00006914#endif
Emeric Brun282a76a2012-11-08 18:02:56 +01006915 break;
6916 }
Olivier Houchardea8dd942019-05-20 14:02:16 +02006917
Emeric Brun46591952012-05-18 15:47:34 +02006918 break;
6919 }
6920 else if (ret == SSL_ERROR_WANT_READ) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01006921 /* handshake is running, and it needs to enable read */
Emeric Brun46591952012-05-18 15:47:34 +02006922 conn->flags |= CO_FL_SSL_WAIT_HS;
Olivier Houchardea8dd942019-05-20 14:02:16 +02006923 ctx->xprt->subscribe(conn, ctx->xprt_ctx,
6924 SUB_RETRY_RECV,
6925 &ctx->wait_event);
Willy Tarreau5db847a2019-05-09 14:13:35 +02006926#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00006927 /* Async mode can be re-enabled, because we're leaving data state.*/
6928 if (global_ssl.async)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006929 SSL_set_mode(ctx->ssl, SSL_MODE_ASYNC);
Emeric Brunb5e42a82017-06-06 12:35:14 +00006930#endif
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006931 break;
6932 }
Emeric Brun46591952012-05-18 15:47:34 +02006933 goto out_error;
6934 }
6935 }
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02006936 leave:
Emeric Brun46591952012-05-18 15:47:34 +02006937 return done;
6938
6939 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01006940 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02006941 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01006942 ERR_clear_error();
6943
Emeric Brun46591952012-05-18 15:47:34 +02006944 conn->flags |= CO_FL_ERROR;
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02006945 goto leave;
Emeric Brun46591952012-05-18 15:47:34 +02006946}
6947
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006948static void ssl_sock_close(struct connection *conn, void *xprt_ctx) {
Emeric Brun46591952012-05-18 15:47:34 +02006949
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006950 struct ssl_sock_ctx *ctx = xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006951
Olivier Houchardea8dd942019-05-20 14:02:16 +02006952
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006953 if (ctx) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02006954 if (ctx->wait_event.events != 0)
6955 ctx->xprt->unsubscribe(ctx->conn, ctx->xprt_ctx,
6956 ctx->wait_event.events,
6957 &ctx->wait_event);
Willy Tarreau113d52b2020-01-10 09:20:26 +01006958 if (ctx->subs) {
6959 ctx->subs->events = 0;
6960 tasklet_wakeup(ctx->subs->tasklet);
Olivier Houchardea8dd942019-05-20 14:02:16 +02006961 }
Willy Tarreau113d52b2020-01-10 09:20:26 +01006962
Olivier Houchard692c1d02019-05-23 18:41:47 +02006963 if (ctx->xprt->close)
6964 ctx->xprt->close(conn, ctx->xprt_ctx);
Willy Tarreau5db847a2019-05-09 14:13:35 +02006965#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brun3854e012017-05-17 20:42:48 +02006966 if (global_ssl.async) {
6967 OSSL_ASYNC_FD all_fd[32], afd;
6968 size_t num_all_fds = 0;
6969 int i;
6970
Olivier Houchard66ab4982019-02-26 18:37:15 +01006971 SSL_get_all_async_fds(ctx->ssl, NULL, &num_all_fds);
Emeric Brun3854e012017-05-17 20:42:48 +02006972 if (num_all_fds > 32) {
6973 send_log(NULL, LOG_EMERG, "haproxy: openssl returns too many async fds. It seems a bug. Process may crash\n");
6974 return;
6975 }
6976
Olivier Houchard66ab4982019-02-26 18:37:15 +01006977 SSL_get_all_async_fds(ctx->ssl, all_fd, &num_all_fds);
Emeric Brun3854e012017-05-17 20:42:48 +02006978
6979 /* If an async job is pending, we must try to
6980 to catch the end using polling before calling
6981 SSL_free */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006982 if (num_all_fds && SSL_waiting_for_async(ctx->ssl)) {
Emeric Brun3854e012017-05-17 20:42:48 +02006983 for (i=0 ; i < num_all_fds ; i++) {
6984 /* switch on an handler designed to
6985 * handle the SSL_free
6986 */
6987 afd = all_fd[i];
6988 fdtab[afd].iocb = ssl_async_fd_free;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006989 fdtab[afd].owner = ctx->ssl;
Emeric Brun3854e012017-05-17 20:42:48 +02006990 fd_want_recv(afd);
Emeric Brunce9e01c2017-05-31 10:02:53 +00006991 /* To ensure that the fd cache won't be used
6992 * and we'll catch a real RD event.
6993 */
6994 fd_cant_recv(afd);
Emeric Brun3854e012017-05-17 20:42:48 +02006995 }
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02006996 tasklet_free(ctx->wait_event.tasklet);
Olivier Houchard66ab4982019-02-26 18:37:15 +01006997 pool_free(ssl_sock_ctx_pool, ctx);
Olivier Houchard2be5a4c2019-03-08 18:54:43 +01006998 _HA_ATOMIC_ADD(&jobs, 1);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006999 return;
7000 }
Emeric Brun3854e012017-05-17 20:42:48 +02007001 /* Else we can remove the fds from the fdtab
7002 * and call SSL_free.
7003 * note: we do a fd_remove and not a delete
7004 * because the fd is owned by the engine.
7005 * the engine is responsible to close
7006 */
7007 for (i=0 ; i < num_all_fds ; i++)
7008 fd_remove(all_fd[i]);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00007009 }
7010#endif
Olivier Houchard66ab4982019-02-26 18:37:15 +01007011 SSL_free(ctx->ssl);
Olivier Houchard54907bb2019-12-19 15:02:39 +01007012 b_free(&ctx->early_buf);
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02007013 tasklet_free(ctx->wait_event.tasklet);
Olivier Houchard66ab4982019-02-26 18:37:15 +01007014 pool_free(ssl_sock_ctx_pool, ctx);
Olivier Houchard2be5a4c2019-03-08 18:54:43 +01007015 _HA_ATOMIC_SUB(&sslconns, 1);
Emeric Brun46591952012-05-18 15:47:34 +02007016 }
Emeric Brun46591952012-05-18 15:47:34 +02007017}
7018
7019/* This function tries to perform a clean shutdown on an SSL connection, and in
7020 * any case, flags the connection as reusable if no handshake was in progress.
7021 */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01007022static void ssl_sock_shutw(struct connection *conn, void *xprt_ctx, int clean)
Emeric Brun46591952012-05-18 15:47:34 +02007023{
Olivier Houcharde179d0e2019-03-21 18:27:17 +01007024 struct ssl_sock_ctx *ctx = xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007025
Willy Tarreau911db9b2020-01-23 16:27:54 +01007026 if (conn->flags & (CO_FL_WAIT_XPRT | CO_FL_SSL_WAIT_HS))
Emeric Brun46591952012-05-18 15:47:34 +02007027 return;
Emmanuel Hocdet405ff312017-01-08 14:07:39 +01007028 if (!clean)
7029 /* don't sent notify on SSL_shutdown */
Olivier Houchard66ab4982019-02-26 18:37:15 +01007030 SSL_set_quiet_shutdown(ctx->ssl, 1);
Emeric Brun46591952012-05-18 15:47:34 +02007031 /* no handshake was in progress, try a clean ssl shutdown */
Olivier Houchard66ab4982019-02-26 18:37:15 +01007032 if (SSL_shutdown(ctx->ssl) <= 0) {
Emeric Brun644cde02012-12-14 11:21:13 +01007033 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02007034 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01007035 ERR_clear_error();
7036 }
Emeric Brun46591952012-05-18 15:47:34 +02007037}
7038
William Lallemandd4f946c2019-12-05 10:26:40 +01007039/* fill a buffer with the algorithm and size of a public key */
7040static int cert_get_pkey_algo(X509 *crt, struct buffer *out)
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01007041{
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01007042 int bits = 0;
7043 int sig = TLSEXT_signature_anonymous;
7044 int len = -1;
Emmanuel Hocdetc3775d22019-11-04 18:19:32 +01007045 EVP_PKEY *pkey;
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01007046
Emmanuel Hocdetc3775d22019-11-04 18:19:32 +01007047 pkey = X509_get_pubkey(crt);
7048 if (pkey) {
7049 bits = EVP_PKEY_bits(pkey);
7050 switch(EVP_PKEY_base_id(pkey)) {
7051 case EVP_PKEY_RSA:
7052 sig = TLSEXT_signature_rsa;
7053 break;
7054 case EVP_PKEY_EC:
7055 sig = TLSEXT_signature_ecdsa;
7056 break;
7057 case EVP_PKEY_DSA:
7058 sig = TLSEXT_signature_dsa;
7059 break;
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01007060 }
Emmanuel Hocdetc3775d22019-11-04 18:19:32 +01007061 EVP_PKEY_free(pkey);
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01007062 }
7063
7064 switch(sig) {
7065 case TLSEXT_signature_rsa:
7066 len = chunk_printf(out, "RSA%d", bits);
7067 break;
7068 case TLSEXT_signature_ecdsa:
7069 len = chunk_printf(out, "EC%d", bits);
7070 break;
7071 case TLSEXT_signature_dsa:
7072 len = chunk_printf(out, "DSA%d", bits);
7073 break;
7074 default:
7075 return 0;
7076 }
7077 if (len < 0)
7078 return 0;
7079 return 1;
7080}
7081
William Lallemandd4f946c2019-12-05 10:26:40 +01007082/* used for ppv2 pkey alog (can be used for logging) */
7083int ssl_sock_get_pkey_algo(struct connection *conn, struct buffer *out)
7084{
7085 struct ssl_sock_ctx *ctx;
7086 X509 *crt;
7087
7088 if (!ssl_sock_is_ssl(conn))
7089 return 0;
7090
7091 ctx = conn->xprt_ctx;
7092
7093 crt = SSL_get_certificate(ctx->ssl);
7094 if (!crt)
7095 return 0;
7096
7097 return cert_get_pkey_algo(crt, out);
7098}
7099
Emmanuel Hocdet283e0042017-11-02 14:05:23 +01007100/* used for ppv2 cert signature (can be used for logging) */
7101const char *ssl_sock_get_cert_sig(struct connection *conn)
7102{
Christopher Faulet82004142019-09-10 10:12:03 +02007103 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007104
Emmanuel Hocdet283e0042017-11-02 14:05:23 +01007105 __OPENSSL_110_CONST__ ASN1_OBJECT *algorithm;
7106 X509 *crt;
7107
7108 if (!ssl_sock_is_ssl(conn))
7109 return NULL;
Christopher Faulet82004142019-09-10 10:12:03 +02007110 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007111 crt = SSL_get_certificate(ctx->ssl);
Emmanuel Hocdet283e0042017-11-02 14:05:23 +01007112 if (!crt)
7113 return NULL;
7114 X509_ALGOR_get0(&algorithm, NULL, NULL, X509_get0_tbs_sigalg(crt));
7115 return OBJ_nid2sn(OBJ_obj2nid(algorithm));
7116}
7117
Emmanuel Hocdet253c3b72018-02-01 18:29:59 +01007118/* used for ppv2 authority */
7119const char *ssl_sock_get_sni(struct connection *conn)
7120{
7121#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Christopher Faulet82004142019-09-10 10:12:03 +02007122 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007123
Emmanuel Hocdet253c3b72018-02-01 18:29:59 +01007124 if (!ssl_sock_is_ssl(conn))
7125 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_servername(ctx->ssl, TLSEXT_NAMETYPE_host_name);
Emmanuel Hocdet253c3b72018-02-01 18:29:59 +01007128#else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007129 return NULL;
Emmanuel Hocdet253c3b72018-02-01 18:29:59 +01007130#endif
7131}
7132
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02007133/* used for logging/ppv2, may be changed for a sample fetch later */
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02007134const char *ssl_sock_get_cipher_name(struct connection *conn)
7135{
Christopher Faulet82004142019-09-10 10:12:03 +02007136 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007137
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02007138 if (!ssl_sock_is_ssl(conn))
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02007139 return NULL;
Christopher Faulet82004142019-09-10 10:12:03 +02007140 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007141 return SSL_get_cipher_name(ctx->ssl);
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02007142}
7143
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02007144/* used for logging/ppv2, may be changed for a sample fetch later */
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02007145const char *ssl_sock_get_proto_version(struct connection *conn)
7146{
Christopher Faulet82004142019-09-10 10:12:03 +02007147 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007148
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02007149 if (!ssl_sock_is_ssl(conn))
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02007150 return NULL;
Christopher Faulet82004142019-09-10 10:12:03 +02007151 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007152 return SSL_get_version(ctx->ssl);
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02007153}
7154
Willy Tarreau8d598402012-10-22 17:58:39 +02007155/* Extract a serial from a cert, and copy it to a chunk.
7156 * Returns 1 if serial is found and copied, 0 if no serial found and
7157 * -1 if output is not large enough.
7158 */
7159static int
Willy Tarreau83061a82018-07-13 11:56:34 +02007160ssl_sock_get_serial(X509 *crt, struct buffer *out)
Willy Tarreau8d598402012-10-22 17:58:39 +02007161{
7162 ASN1_INTEGER *serial;
7163
7164 serial = X509_get_serialNumber(crt);
7165 if (!serial)
7166 return 0;
7167
7168 if (out->size < serial->length)
7169 return -1;
7170
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007171 memcpy(out->area, serial->data, serial->length);
7172 out->data = serial->length;
Willy Tarreau8d598402012-10-22 17:58:39 +02007173 return 1;
7174}
7175
Emeric Brun43e79582014-10-29 19:03:26 +01007176/* Extract a cert to der, and copy it to a chunk.
Joseph Herlant017b3da2018-11-15 09:07:59 -08007177 * Returns 1 if the cert is found and copied, 0 on der conversion failure
7178 * and -1 if the output is not large enough.
Emeric Brun43e79582014-10-29 19:03:26 +01007179 */
7180static int
Willy Tarreau83061a82018-07-13 11:56:34 +02007181ssl_sock_crt2der(X509 *crt, struct buffer *out)
Emeric Brun43e79582014-10-29 19:03:26 +01007182{
7183 int len;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007184 unsigned char *p = (unsigned char *) out->area;;
Emeric Brun43e79582014-10-29 19:03:26 +01007185
7186 len =i2d_X509(crt, NULL);
7187 if (len <= 0)
7188 return 1;
7189
7190 if (out->size < len)
7191 return -1;
7192
7193 i2d_X509(crt,&p);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007194 out->data = len;
Emeric Brun43e79582014-10-29 19:03:26 +01007195 return 1;
7196}
7197
Emeric Brunce5ad802012-10-22 14:11:22 +02007198
Willy Tarreau83061a82018-07-13 11:56:34 +02007199/* Copy Date in ASN1_UTCTIME format in struct buffer out.
Emeric Brunce5ad802012-10-22 14:11:22 +02007200 * Returns 1 if serial is found and copied, 0 if no valid time found
7201 * and -1 if output is not large enough.
7202 */
7203static int
Willy Tarreau83061a82018-07-13 11:56:34 +02007204ssl_sock_get_time(ASN1_TIME *tm, struct buffer *out)
Emeric Brunce5ad802012-10-22 14:11:22 +02007205{
7206 if (tm->type == V_ASN1_GENERALIZEDTIME) {
7207 ASN1_GENERALIZEDTIME *gentm = (ASN1_GENERALIZEDTIME *)tm;
7208
7209 if (gentm->length < 12)
7210 return 0;
7211 if (gentm->data[0] != 0x32 || gentm->data[1] != 0x30)
7212 return 0;
7213 if (out->size < gentm->length-2)
7214 return -1;
7215
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007216 memcpy(out->area, gentm->data+2, gentm->length-2);
7217 out->data = gentm->length-2;
Emeric Brunce5ad802012-10-22 14:11:22 +02007218 return 1;
7219 }
7220 else if (tm->type == V_ASN1_UTCTIME) {
7221 ASN1_UTCTIME *utctm = (ASN1_UTCTIME *)tm;
7222
7223 if (utctm->length < 10)
7224 return 0;
7225 if (utctm->data[0] >= 0x35)
7226 return 0;
7227 if (out->size < utctm->length)
7228 return -1;
7229
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007230 memcpy(out->area, utctm->data, utctm->length);
7231 out->data = utctm->length;
Emeric Brunce5ad802012-10-22 14:11:22 +02007232 return 1;
7233 }
7234
7235 return 0;
7236}
7237
Emeric Brun87855892012-10-17 17:39:35 +02007238/* Extract an entry from a X509_NAME and copy its value to an output chunk.
7239 * Returns 1 if entry found, 0 if entry not found, or -1 if output not large enough.
7240 */
7241static int
Willy Tarreau83061a82018-07-13 11:56:34 +02007242ssl_sock_get_dn_entry(X509_NAME *a, const struct buffer *entry, int pos,
7243 struct buffer *out)
Emeric Brun87855892012-10-17 17:39:35 +02007244{
7245 X509_NAME_ENTRY *ne;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007246 ASN1_OBJECT *obj;
7247 ASN1_STRING *data;
7248 const unsigned char *data_ptr;
7249 int data_len;
Emeric Brun87855892012-10-17 17:39:35 +02007250 int i, j, n;
7251 int cur = 0;
7252 const char *s;
7253 char tmp[128];
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007254 int name_count;
7255
7256 name_count = X509_NAME_entry_count(a);
Emeric Brun87855892012-10-17 17:39:35 +02007257
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007258 out->data = 0;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007259 for (i = 0; i < name_count; i++) {
Emeric Brun87855892012-10-17 17:39:35 +02007260 if (pos < 0)
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007261 j = (name_count-1) - i;
Emeric Brun87855892012-10-17 17:39:35 +02007262 else
7263 j = i;
7264
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007265 ne = X509_NAME_get_entry(a, j);
7266 obj = X509_NAME_ENTRY_get_object(ne);
7267 data = X509_NAME_ENTRY_get_data(ne);
7268 data_ptr = ASN1_STRING_get0_data(data);
7269 data_len = ASN1_STRING_length(data);
7270 n = OBJ_obj2nid(obj);
Emeric Brun87855892012-10-17 17:39:35 +02007271 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007272 i2t_ASN1_OBJECT(tmp, sizeof(tmp), obj);
Emeric Brun87855892012-10-17 17:39:35 +02007273 s = tmp;
7274 }
7275
7276 if (chunk_strcasecmp(entry, s) != 0)
7277 continue;
7278
7279 if (pos < 0)
7280 cur--;
7281 else
7282 cur++;
7283
7284 if (cur != pos)
7285 continue;
7286
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007287 if (data_len > out->size)
Emeric Brun87855892012-10-17 17:39:35 +02007288 return -1;
7289
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007290 memcpy(out->area, data_ptr, data_len);
7291 out->data = data_len;
Emeric Brun87855892012-10-17 17:39:35 +02007292 return 1;
7293 }
7294
7295 return 0;
7296
William Lallemandd4f946c2019-12-05 10:26:40 +01007297}
7298
7299/*
7300 * Extract and format the DNS SAN extensions and copy result into a chuink
7301 * Return 0;
7302 */
7303#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
7304static int ssl_sock_get_san_oneline(X509 *cert, struct buffer *out)
7305{
7306 int i;
7307 char *str;
7308 STACK_OF(GENERAL_NAME) *names = NULL;
7309
7310 names = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
7311 if (names) {
7312 for (i = 0; i < sk_GENERAL_NAME_num(names); i++) {
7313 GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i);
7314 if (i > 0)
7315 chunk_appendf(out, ", ");
7316 if (name->type == GEN_DNS) {
7317 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
7318 chunk_appendf(out, "DNS:%s", str);
7319 OPENSSL_free(str);
7320 }
7321 }
7322 }
7323 sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
7324 }
7325 return 0;
Emeric Brun87855892012-10-17 17:39:35 +02007326}
William Lallemandd4f946c2019-12-05 10:26:40 +01007327#endif
Emeric Brun87855892012-10-17 17:39:35 +02007328
Elliot Otchet71f82972020-01-15 08:12:14 -05007329/*
7330 * Extract the DN in the specified format from the X509_NAME and copy result to a chunk.
7331 * Currently supports rfc2253 for returning LDAP V3 DNs.
7332 * Returns 1 if dn entries exist, 0 if no dn entry was found.
7333 */
7334static int
7335ssl_sock_get_dn_formatted(X509_NAME *a, const struct buffer *format, struct buffer *out)
7336{
7337 BIO *bio = NULL;
7338 int ret = 0;
7339 int data_len = 0;
7340
7341 if (chunk_strcmp(format, "rfc2253") == 0) {
7342 bio = BIO_new(BIO_s_mem());
7343 if (bio == NULL)
7344 goto out;
7345
7346 if (X509_NAME_print_ex(bio, a, 0, XN_FLAG_RFC2253) < 0)
7347 goto out;
7348
7349 if ((data_len = BIO_read(bio, out->area, out->size)) <= 0)
7350 goto out;
7351
7352 out->data = data_len;
7353
7354 ret = 1;
7355 }
7356out:
7357 if (bio)
7358 BIO_free(bio);
7359 return ret;
7360}
7361
Emeric Brun87855892012-10-17 17:39:35 +02007362/* Extract and format full DN from a X509_NAME and copy result into a chunk
7363 * Returns 1 if dn entries exits, 0 if no dn entry found or -1 if output is not large enough.
7364 */
7365static int
Willy Tarreau83061a82018-07-13 11:56:34 +02007366ssl_sock_get_dn_oneline(X509_NAME *a, struct buffer *out)
Emeric Brun87855892012-10-17 17:39:35 +02007367{
7368 X509_NAME_ENTRY *ne;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007369 ASN1_OBJECT *obj;
7370 ASN1_STRING *data;
7371 const unsigned char *data_ptr;
7372 int data_len;
Emeric Brun87855892012-10-17 17:39:35 +02007373 int i, n, ln;
7374 int l = 0;
7375 const char *s;
7376 char *p;
7377 char tmp[128];
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007378 int name_count;
7379
7380
7381 name_count = X509_NAME_entry_count(a);
Emeric Brun87855892012-10-17 17:39:35 +02007382
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007383 out->data = 0;
7384 p = out->area;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007385 for (i = 0; i < name_count; i++) {
7386 ne = X509_NAME_get_entry(a, i);
7387 obj = X509_NAME_ENTRY_get_object(ne);
7388 data = X509_NAME_ENTRY_get_data(ne);
7389 data_ptr = ASN1_STRING_get0_data(data);
7390 data_len = ASN1_STRING_length(data);
7391 n = OBJ_obj2nid(obj);
Emeric Brun87855892012-10-17 17:39:35 +02007392 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007393 i2t_ASN1_OBJECT(tmp, sizeof(tmp), obj);
Emeric Brun87855892012-10-17 17:39:35 +02007394 s = tmp;
7395 }
7396 ln = strlen(s);
7397
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007398 l += 1 + ln + 1 + data_len;
Emeric Brun87855892012-10-17 17:39:35 +02007399 if (l > out->size)
7400 return -1;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007401 out->data = l;
Emeric Brun87855892012-10-17 17:39:35 +02007402
7403 *(p++)='/';
7404 memcpy(p, s, ln);
7405 p += ln;
7406 *(p++)='=';
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007407 memcpy(p, data_ptr, data_len);
7408 p += data_len;
Emeric Brun87855892012-10-17 17:39:35 +02007409 }
7410
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007411 if (!out->data)
Emeric Brun87855892012-10-17 17:39:35 +02007412 return 0;
7413
7414 return 1;
7415}
7416
Olivier Houchardab28a322018-12-21 19:45:40 +01007417void ssl_sock_set_alpn(struct connection *conn, const unsigned char *alpn, int len)
7418{
7419#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Christopher Faulet82004142019-09-10 10:12:03 +02007420 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007421
Olivier Houcharde488ea82019-06-28 14:10:33 +02007422 if (!ssl_sock_is_ssl(conn))
7423 return;
Christopher Faulet82004142019-09-10 10:12:03 +02007424 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007425 SSL_set_alpn_protos(ctx->ssl, alpn, len);
Olivier Houchardab28a322018-12-21 19:45:40 +01007426#endif
7427}
7428
Willy Tarreau119a4082016-12-22 21:58:38 +01007429/* Sets advertised SNI for outgoing connections. Please set <hostname> to NULL
7430 * to disable SNI.
7431 */
Willy Tarreau63076412015-07-10 11:33:32 +02007432void ssl_sock_set_servername(struct connection *conn, const char *hostname)
7433{
7434#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Christopher Faulet82004142019-09-10 10:12:03 +02007435 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007436
Willy Tarreau119a4082016-12-22 21:58:38 +01007437 char *prev_name;
7438
Willy Tarreau63076412015-07-10 11:33:32 +02007439 if (!ssl_sock_is_ssl(conn))
7440 return;
Christopher Faulet82004142019-09-10 10:12:03 +02007441 ctx = conn->xprt_ctx;
Willy Tarreau63076412015-07-10 11:33:32 +02007442
Willy Tarreau119a4082016-12-22 21:58:38 +01007443 /* if the SNI changes, we must destroy the reusable context so that a
7444 * new connection will present a new SNI. As an optimization we could
7445 * later imagine having a small cache of ssl_ctx to hold a few SNI per
7446 * server.
7447 */
Olivier Houchard66ab4982019-02-26 18:37:15 +01007448 prev_name = (char *)SSL_get_servername(ctx->ssl, TLSEXT_NAMETYPE_host_name);
Willy Tarreau119a4082016-12-22 21:58:38 +01007449 if ((!prev_name && hostname) ||
7450 (prev_name && (!hostname || strcmp(hostname, prev_name) != 0)))
Olivier Houchard66ab4982019-02-26 18:37:15 +01007451 SSL_set_session(ctx->ssl, NULL);
Willy Tarreau119a4082016-12-22 21:58:38 +01007452
Olivier Houchard66ab4982019-02-26 18:37:15 +01007453 SSL_set_tlsext_host_name(ctx->ssl, hostname);
Willy Tarreau63076412015-07-10 11:33:32 +02007454#endif
7455}
7456
Emeric Brun0abf8362014-06-24 18:26:41 +02007457/* Extract peer certificate's common name into the chunk dest
7458 * Returns
7459 * the len of the extracted common name
7460 * or 0 if no CN found in DN
7461 * or -1 on error case (i.e. no peer certificate)
7462 */
Willy Tarreau83061a82018-07-13 11:56:34 +02007463int ssl_sock_get_remote_common_name(struct connection *conn,
7464 struct buffer *dest)
David Safb76832014-05-08 23:42:08 -04007465{
Christopher Faulet82004142019-09-10 10:12:03 +02007466 struct ssl_sock_ctx *ctx;
David Safb76832014-05-08 23:42:08 -04007467 X509 *crt = NULL;
7468 X509_NAME *name;
David Safb76832014-05-08 23:42:08 -04007469 const char find_cn[] = "CN";
Willy Tarreau83061a82018-07-13 11:56:34 +02007470 const struct buffer find_cn_chunk = {
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007471 .area = (char *)&find_cn,
7472 .data = sizeof(find_cn)-1
David Safb76832014-05-08 23:42:08 -04007473 };
Emeric Brun0abf8362014-06-24 18:26:41 +02007474 int result = -1;
David Safb76832014-05-08 23:42:08 -04007475
7476 if (!ssl_sock_is_ssl(conn))
Emeric Brun0abf8362014-06-24 18:26:41 +02007477 goto out;
Christopher Faulet82004142019-09-10 10:12:03 +02007478 ctx = conn->xprt_ctx;
David Safb76832014-05-08 23:42:08 -04007479
7480 /* SSL_get_peer_certificate, it increase X509 * ref count */
Olivier Houchard66ab4982019-02-26 18:37:15 +01007481 crt = SSL_get_peer_certificate(ctx->ssl);
David Safb76832014-05-08 23:42:08 -04007482 if (!crt)
7483 goto out;
7484
7485 name = X509_get_subject_name(crt);
7486 if (!name)
7487 goto out;
David Safb76832014-05-08 23:42:08 -04007488
Emeric Brun0abf8362014-06-24 18:26:41 +02007489 result = ssl_sock_get_dn_entry(name, &find_cn_chunk, 1, dest);
7490out:
David Safb76832014-05-08 23:42:08 -04007491 if (crt)
7492 X509_free(crt);
7493
7494 return result;
7495}
7496
Dave McCowan328fb582014-07-30 10:39:13 -04007497/* returns 1 if client passed a certificate for this session, 0 if not */
7498int ssl_sock_get_cert_used_sess(struct connection *conn)
7499{
Christopher Faulet82004142019-09-10 10:12:03 +02007500 struct ssl_sock_ctx *ctx;
Dave McCowan328fb582014-07-30 10:39:13 -04007501 X509 *crt = NULL;
7502
7503 if (!ssl_sock_is_ssl(conn))
7504 return 0;
Christopher Faulet82004142019-09-10 10:12:03 +02007505 ctx = conn->xprt_ctx;
Dave McCowan328fb582014-07-30 10:39:13 -04007506
7507 /* SSL_get_peer_certificate, it increase X509 * ref count */
Olivier Houchard66ab4982019-02-26 18:37:15 +01007508 crt = SSL_get_peer_certificate(ctx->ssl);
Dave McCowan328fb582014-07-30 10:39:13 -04007509 if (!crt)
7510 return 0;
7511
7512 X509_free(crt);
7513 return 1;
7514}
7515
7516/* returns 1 if client passed a certificate for this connection, 0 if not */
7517int ssl_sock_get_cert_used_conn(struct connection *conn)
David Safb76832014-05-08 23:42:08 -04007518{
Christopher Faulet82004142019-09-10 10:12:03 +02007519 struct ssl_sock_ctx *ctx;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007520
David Safb76832014-05-08 23:42:08 -04007521 if (!ssl_sock_is_ssl(conn))
7522 return 0;
Christopher Faulet82004142019-09-10 10:12:03 +02007523 ctx = conn->xprt_ctx;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007524 return SSL_SOCK_ST_FL_VERIFY_DONE & ctx->xprt_st ? 1 : 0;
David Safb76832014-05-08 23:42:08 -04007525}
7526
7527/* returns result from SSL verify */
7528unsigned int ssl_sock_get_verify_result(struct connection *conn)
7529{
Christopher Faulet82004142019-09-10 10:12:03 +02007530 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007531
David Safb76832014-05-08 23:42:08 -04007532 if (!ssl_sock_is_ssl(conn))
7533 return (unsigned int)X509_V_ERR_APPLICATION_VERIFICATION;
Christopher Faulet82004142019-09-10 10:12:03 +02007534 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007535 return (unsigned int)SSL_get_verify_result(ctx->ssl);
David Safb76832014-05-08 23:42:08 -04007536}
7537
Willy Tarreau8743f7e2016-12-04 18:44:29 +01007538/* Returns the application layer protocol name in <str> and <len> when known.
7539 * Zero is returned if the protocol name was not found, otherwise non-zero is
7540 * returned. The string is allocated in the SSL context and doesn't have to be
7541 * freed by the caller. NPN is also checked if available since older versions
7542 * of openssl (1.0.1) which are more common in field only support this one.
7543 */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01007544static int ssl_sock_get_alpn(const struct connection *conn, void *xprt_ctx, const char **str, int *len)
Willy Tarreau8743f7e2016-12-04 18:44:29 +01007545{
Olivier Houchard66ab4982019-02-26 18:37:15 +01007546#if defined(TLSEXT_TYPE_application_layer_protocol_negotiation) || \
7547 defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Olivier Houcharde179d0e2019-03-21 18:27:17 +01007548 struct ssl_sock_ctx *ctx = xprt_ctx;
7549 if (!ctx)
Willy Tarreau8743f7e2016-12-04 18:44:29 +01007550 return 0;
7551
7552 *str = NULL;
7553
7554#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Olivier Houchard66ab4982019-02-26 18:37:15 +01007555 SSL_get0_alpn_selected(ctx->ssl, (const unsigned char **)str, (unsigned *)len);
Willy Tarreau8743f7e2016-12-04 18:44:29 +01007556 if (*str)
7557 return 1;
7558#endif
Bernard Spil13c53f82018-02-15 13:34:58 +01007559#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007560 SSL_get0_next_proto_negotiated(ctx->ssl, (const unsigned char **)str, (unsigned *)len);
Willy Tarreau8743f7e2016-12-04 18:44:29 +01007561 if (*str)
7562 return 1;
7563#endif
Olivier Houcharde179d0e2019-03-21 18:27:17 +01007564#endif
Willy Tarreau8743f7e2016-12-04 18:44:29 +01007565 return 0;
7566}
7567
Willy Tarreau7875d092012-09-10 08:20:03 +02007568/***** Below are some sample fetching functions for ACL/patterns *****/
7569
Olivier Houchardccaa7de2017-10-02 11:51:03 +02007570static int
7571smp_fetch_ssl_fc_has_early(const struct arg *args, struct sample *smp, const char *kw, void *private)
7572{
7573 struct connection *conn;
7574
7575 conn = objt_conn(smp->sess->origin);
7576 if (!conn || conn->xprt != &ssl_sock)
7577 return 0;
7578
7579 smp->flags = 0;
7580 smp->data.type = SMP_T_BOOL;
Emmanuel Hocdetc9858012019-08-07 14:44:49 +02007581#ifdef OPENSSL_IS_BORINGSSL
7582 {
7583 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
7584 smp->data.u.sint = (SSL_in_early_data(ctx->ssl) &&
7585 SSL_early_data_accepted(ctx->ssl));
7586 }
7587#else
Olivier Houchard25ae45a2017-11-29 19:51:19 +01007588 smp->data.u.sint = ((conn->flags & CO_FL_EARLY_DATA) &&
Olivier Houchard220a26c2020-01-23 14:57:36 +01007589 (conn->flags & (CO_FL_EARLY_SSL_HS | CO_FL_SSL_WAIT_HS))) ? 1 : 0;
Emmanuel Hocdetc9858012019-08-07 14:44:49 +02007590#endif
Olivier Houchardccaa7de2017-10-02 11:51:03 +02007591 return 1;
7592}
7593
Emeric Brune64aef12012-09-21 13:15:06 +02007594/* boolean, returns true if client cert was present */
7595static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007596smp_fetch_ssl_fc_has_crt(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brune64aef12012-09-21 13:15:06 +02007597{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007598 struct connection *conn;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007599 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007600
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007601 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007602 if (!conn || conn->xprt != &ssl_sock)
Emeric Brune64aef12012-09-21 13:15:06 +02007603 return 0;
7604
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007605 ctx = conn->xprt_ctx;
7606
Willy Tarreau911db9b2020-01-23 16:27:54 +01007607 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Brune64aef12012-09-21 13:15:06 +02007608 smp->flags |= SMP_F_MAY_CHANGE;
7609 return 0;
7610 }
7611
7612 smp->flags = 0;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007613 smp->data.type = SMP_T_BOOL;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007614 smp->data.u.sint = SSL_SOCK_ST_FL_VERIFY_DONE & ctx->xprt_st ? 1 : 0;
Emeric Brune64aef12012-09-21 13:15:06 +02007615
7616 return 1;
7617}
7618
Emeric Brun43e79582014-10-29 19:03:26 +01007619/* binary, returns a certificate in a binary chunk (der/raw).
7620 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7621 * should be use.
7622 */
7623static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007624smp_fetch_ssl_x_der(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun43e79582014-10-29 19:03:26 +01007625{
7626 int cert_peer = (kw[4] == 'c') ? 1 : 0;
7627 X509 *crt = NULL;
7628 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02007629 struct buffer *smp_trash;
Emeric Brun43e79582014-10-29 19:03:26 +01007630 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007631 struct ssl_sock_ctx *ctx;
Emeric Brun43e79582014-10-29 19:03:26 +01007632
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007633 conn = objt_conn(smp->sess->origin);
Emeric Brun43e79582014-10-29 19:03:26 +01007634 if (!conn || conn->xprt != &ssl_sock)
7635 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007636 ctx = conn->xprt_ctx;
Emeric Brun43e79582014-10-29 19:03:26 +01007637
Willy Tarreau911db9b2020-01-23 16:27:54 +01007638 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Brun43e79582014-10-29 19:03:26 +01007639 smp->flags |= SMP_F_MAY_CHANGE;
7640 return 0;
7641 }
7642
7643 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007644 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brun43e79582014-10-29 19:03:26 +01007645 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007646 crt = SSL_get_certificate(ctx->ssl);
Emeric Brun43e79582014-10-29 19:03:26 +01007647
7648 if (!crt)
7649 goto out;
7650
7651 smp_trash = get_trash_chunk();
7652 if (ssl_sock_crt2der(crt, smp_trash) <= 0)
7653 goto out;
7654
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007655 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007656 smp->data.type = SMP_T_BIN;
Emeric Brun43e79582014-10-29 19:03:26 +01007657 ret = 1;
7658out:
7659 /* SSL_get_peer_certificate, it increase X509 * ref count */
7660 if (cert_peer && crt)
7661 X509_free(crt);
7662 return ret;
7663}
7664
Emeric Brunba841a12014-04-30 17:05:08 +02007665/* binary, returns serial of certificate in a binary chunk.
7666 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7667 * should be use.
7668 */
Willy Tarreau8d598402012-10-22 17:58:39 +02007669static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007670smp_fetch_ssl_x_serial(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau8d598402012-10-22 17:58:39 +02007671{
Emeric Brunba841a12014-04-30 17:05:08 +02007672 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Willy Tarreau8d598402012-10-22 17:58:39 +02007673 X509 *crt = NULL;
7674 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02007675 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007676 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007677 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007678
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007679 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007680 if (!conn || conn->xprt != &ssl_sock)
Willy Tarreau8d598402012-10-22 17:58:39 +02007681 return 0;
7682
Olivier Houchard66ab4982019-02-26 18:37:15 +01007683 ctx = conn->xprt_ctx;
7684
Willy Tarreau911db9b2020-01-23 16:27:54 +01007685 if (conn->flags & CO_FL_WAIT_XPRT) {
Willy Tarreau8d598402012-10-22 17:58:39 +02007686 smp->flags |= SMP_F_MAY_CHANGE;
7687 return 0;
7688 }
7689
Emeric Brunba841a12014-04-30 17:05:08 +02007690 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007691 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007692 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007693 crt = SSL_get_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007694
Willy Tarreau8d598402012-10-22 17:58:39 +02007695 if (!crt)
7696 goto out;
7697
Willy Tarreau47ca5452012-12-23 20:22:19 +01007698 smp_trash = get_trash_chunk();
Willy Tarreau8d598402012-10-22 17:58:39 +02007699 if (ssl_sock_get_serial(crt, smp_trash) <= 0)
7700 goto out;
7701
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007702 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007703 smp->data.type = SMP_T_BIN;
Willy Tarreau8d598402012-10-22 17:58:39 +02007704 ret = 1;
7705out:
Emeric Brunba841a12014-04-30 17:05:08 +02007706 /* SSL_get_peer_certificate, it increase X509 * ref count */
7707 if (cert_peer && crt)
Willy Tarreau8d598402012-10-22 17:58:39 +02007708 X509_free(crt);
7709 return ret;
7710}
Emeric Brune64aef12012-09-21 13:15:06 +02007711
Emeric Brunba841a12014-04-30 17:05:08 +02007712/* binary, returns the client certificate's SHA-1 fingerprint (SHA-1 hash of DER-encoded certificate) in a binary chunk.
7713 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7714 * should be use.
7715 */
James Votha051b4a2013-05-14 20:37:59 +02007716static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007717smp_fetch_ssl_x_sha1(const struct arg *args, struct sample *smp, const char *kw, void *private)
James Votha051b4a2013-05-14 20:37:59 +02007718{
Emeric Brunba841a12014-04-30 17:05:08 +02007719 int cert_peer = (kw[4] == 'c') ? 1 : 0;
James Votha051b4a2013-05-14 20:37:59 +02007720 X509 *crt = NULL;
7721 const EVP_MD *digest;
7722 int ret = 0;
Willy Tarreau105599c2020-02-25 08:59:23 +01007723 unsigned int len = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02007724 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007725 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007726 struct ssl_sock_ctx *ctx;
James Votha051b4a2013-05-14 20:37:59 +02007727
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007728 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007729 if (!conn || conn->xprt != &ssl_sock)
7730 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007731 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007732
Willy Tarreau911db9b2020-01-23 16:27:54 +01007733 if (conn->flags & CO_FL_WAIT_XPRT) {
James Votha051b4a2013-05-14 20:37:59 +02007734 smp->flags |= SMP_F_MAY_CHANGE;
7735 return 0;
7736 }
7737
Emeric Brunba841a12014-04-30 17:05:08 +02007738 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007739 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007740 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007741 crt = SSL_get_certificate(ctx->ssl);
James Votha051b4a2013-05-14 20:37:59 +02007742 if (!crt)
7743 goto out;
7744
7745 smp_trash = get_trash_chunk();
7746 digest = EVP_sha1();
Willy Tarreau105599c2020-02-25 08:59:23 +01007747 X509_digest(crt, digest, (unsigned char *) smp_trash->area, &len);
7748 smp_trash->data = len;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007749 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007750 smp->data.type = SMP_T_BIN;
James Votha051b4a2013-05-14 20:37:59 +02007751 ret = 1;
7752out:
Emeric Brunba841a12014-04-30 17:05:08 +02007753 /* SSL_get_peer_certificate, it increase X509 * ref count */
7754 if (cert_peer && crt)
James Votha051b4a2013-05-14 20:37:59 +02007755 X509_free(crt);
7756 return ret;
7757}
7758
Emeric Brunba841a12014-04-30 17:05:08 +02007759/* string, returns certificate's notafter date in ASN1_UTCTIME format.
7760 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7761 * should be use.
7762 */
Emeric Brunce5ad802012-10-22 14:11:22 +02007763static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007764smp_fetch_ssl_x_notafter(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunce5ad802012-10-22 14:11:22 +02007765{
Emeric Brunba841a12014-04-30 17:05:08 +02007766 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brunce5ad802012-10-22 14:11:22 +02007767 X509 *crt = NULL;
7768 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02007769 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007770 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007771 struct ssl_sock_ctx *ctx;
Emeric Brunce5ad802012-10-22 14:11:22 +02007772
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007773 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007774 if (!conn || conn->xprt != &ssl_sock)
7775 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007776 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007777
Willy Tarreau911db9b2020-01-23 16:27:54 +01007778 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Brunce5ad802012-10-22 14:11:22 +02007779 smp->flags |= SMP_F_MAY_CHANGE;
7780 return 0;
7781 }
7782
Emeric Brunba841a12014-04-30 17:05:08 +02007783 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007784 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007785 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007786 crt = SSL_get_certificate(ctx->ssl);
Emeric Brunce5ad802012-10-22 14:11:22 +02007787 if (!crt)
7788 goto out;
7789
Willy Tarreau47ca5452012-12-23 20:22:19 +01007790 smp_trash = get_trash_chunk();
Rosen Penev68185952018-12-14 08:47:02 -08007791 if (ssl_sock_get_time(X509_getm_notAfter(crt), smp_trash) <= 0)
Emeric Brunce5ad802012-10-22 14:11:22 +02007792 goto out;
7793
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007794 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007795 smp->data.type = SMP_T_STR;
Emeric Brunce5ad802012-10-22 14:11:22 +02007796 ret = 1;
7797out:
Emeric Brunba841a12014-04-30 17:05:08 +02007798 /* SSL_get_peer_certificate, it increase X509 * ref count */
7799 if (cert_peer && crt)
Emeric Brunce5ad802012-10-22 14:11:22 +02007800 X509_free(crt);
7801 return ret;
7802}
7803
Emeric Brunba841a12014-04-30 17:05:08 +02007804/* string, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. of certificate's issuer
7805 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7806 * should be use.
7807 */
Emeric Brun87855892012-10-17 17:39:35 +02007808static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007809smp_fetch_ssl_x_i_dn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun87855892012-10-17 17:39:35 +02007810{
Emeric Brunba841a12014-04-30 17:05:08 +02007811 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun87855892012-10-17 17:39:35 +02007812 X509 *crt = NULL;
7813 X509_NAME *name;
7814 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02007815 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007816 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007817 struct ssl_sock_ctx *ctx;
Emeric Brun87855892012-10-17 17:39:35 +02007818
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007819 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007820 if (!conn || conn->xprt != &ssl_sock)
7821 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007822 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007823
Willy Tarreau911db9b2020-01-23 16:27:54 +01007824 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Brun87855892012-10-17 17:39:35 +02007825 smp->flags |= SMP_F_MAY_CHANGE;
7826 return 0;
7827 }
7828
Emeric Brunba841a12014-04-30 17:05:08 +02007829 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007830 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007831 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007832 crt = SSL_get_certificate(ctx->ssl);
Emeric Brun87855892012-10-17 17:39:35 +02007833 if (!crt)
7834 goto out;
7835
7836 name = X509_get_issuer_name(crt);
7837 if (!name)
7838 goto out;
7839
Willy Tarreau47ca5452012-12-23 20:22:19 +01007840 smp_trash = get_trash_chunk();
Elliot Otchet71f82972020-01-15 08:12:14 -05007841 if (args && args[0].type == ARGT_STR && args[0].data.str.data > 0) {
Emeric Brun87855892012-10-17 17:39:35 +02007842 int pos = 1;
7843
7844 if (args[1].type == ARGT_SINT)
7845 pos = args[1].data.sint;
Emeric Brun87855892012-10-17 17:39:35 +02007846
7847 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
7848 goto out;
7849 }
Elliot Otchet71f82972020-01-15 08:12:14 -05007850 else if (args && args[2].type == ARGT_STR && args[2].data.str.data > 0) {
7851 if (ssl_sock_get_dn_formatted(name, &args[2].data.str, smp_trash) <= 0)
7852 goto out;
7853 }
Emeric Brun87855892012-10-17 17:39:35 +02007854 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
7855 goto out;
7856
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007857 smp->data.type = SMP_T_STR;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007858 smp->data.u.str = *smp_trash;
Emeric Brun87855892012-10-17 17:39:35 +02007859 ret = 1;
7860out:
Emeric Brunba841a12014-04-30 17:05:08 +02007861 /* SSL_get_peer_certificate, it increase X509 * ref count */
7862 if (cert_peer && crt)
Emeric Brun87855892012-10-17 17:39:35 +02007863 X509_free(crt);
7864 return ret;
7865}
7866
Emeric Brunba841a12014-04-30 17:05:08 +02007867/* string, returns notbefore date in ASN1_UTCTIME format.
7868 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7869 * should be use.
7870 */
Emeric Brunce5ad802012-10-22 14:11:22 +02007871static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007872smp_fetch_ssl_x_notbefore(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunce5ad802012-10-22 14:11:22 +02007873{
Emeric Brunba841a12014-04-30 17:05:08 +02007874 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brunce5ad802012-10-22 14:11:22 +02007875 X509 *crt = NULL;
7876 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02007877 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007878 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007879 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007880
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007881 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007882 if (!conn || conn->xprt != &ssl_sock)
Emeric Brunce5ad802012-10-22 14:11:22 +02007883 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007884 ctx = conn->xprt_ctx;
Emeric Brunce5ad802012-10-22 14:11:22 +02007885
Willy Tarreau911db9b2020-01-23 16:27:54 +01007886 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Brunce5ad802012-10-22 14:11:22 +02007887 smp->flags |= SMP_F_MAY_CHANGE;
7888 return 0;
7889 }
7890
Emeric Brunba841a12014-04-30 17:05:08 +02007891 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007892 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007893 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007894 crt = SSL_get_certificate(ctx->ssl);
Emeric Brunce5ad802012-10-22 14:11:22 +02007895 if (!crt)
7896 goto out;
7897
Willy Tarreau47ca5452012-12-23 20:22:19 +01007898 smp_trash = get_trash_chunk();
Rosen Penev68185952018-12-14 08:47:02 -08007899 if (ssl_sock_get_time(X509_getm_notBefore(crt), smp_trash) <= 0)
Emeric Brunce5ad802012-10-22 14:11:22 +02007900 goto out;
7901
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007902 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007903 smp->data.type = SMP_T_STR;
Emeric Brunce5ad802012-10-22 14:11:22 +02007904 ret = 1;
7905out:
Emeric Brunba841a12014-04-30 17:05:08 +02007906 /* SSL_get_peer_certificate, it increase X509 * ref count */
7907 if (cert_peer && crt)
Emeric Brunce5ad802012-10-22 14:11:22 +02007908 X509_free(crt);
7909 return ret;
7910}
7911
Emeric Brunba841a12014-04-30 17:05:08 +02007912/* string, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. of certificate's subject
7913 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7914 * should be use.
7915 */
Emeric Brun87855892012-10-17 17:39:35 +02007916static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007917smp_fetch_ssl_x_s_dn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun87855892012-10-17 17:39:35 +02007918{
Emeric Brunba841a12014-04-30 17:05:08 +02007919 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun87855892012-10-17 17:39:35 +02007920 X509 *crt = NULL;
7921 X509_NAME *name;
7922 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02007923 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007924 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007925 struct ssl_sock_ctx *ctx;
Emeric Brun87855892012-10-17 17:39:35 +02007926
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007927 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007928 if (!conn || conn->xprt != &ssl_sock)
7929 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007930 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007931
Willy Tarreau911db9b2020-01-23 16:27:54 +01007932 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Brun87855892012-10-17 17:39:35 +02007933 smp->flags |= SMP_F_MAY_CHANGE;
7934 return 0;
7935 }
7936
Emeric Brunba841a12014-04-30 17:05:08 +02007937 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007938 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007939 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007940 crt = SSL_get_certificate(ctx->ssl);
Emeric Brun87855892012-10-17 17:39:35 +02007941 if (!crt)
7942 goto out;
7943
7944 name = X509_get_subject_name(crt);
7945 if (!name)
7946 goto out;
7947
Willy Tarreau47ca5452012-12-23 20:22:19 +01007948 smp_trash = get_trash_chunk();
Elliot Otchet71f82972020-01-15 08:12:14 -05007949 if (args && args[0].type == ARGT_STR && args[0].data.str.data > 0) {
Emeric Brun87855892012-10-17 17:39:35 +02007950 int pos = 1;
7951
7952 if (args[1].type == ARGT_SINT)
7953 pos = args[1].data.sint;
Emeric Brun87855892012-10-17 17:39:35 +02007954
7955 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
7956 goto out;
7957 }
Elliot Otchet71f82972020-01-15 08:12:14 -05007958 else if (args && args[2].type == ARGT_STR && args[2].data.str.data > 0) {
7959 if (ssl_sock_get_dn_formatted(name, &args[2].data.str, smp_trash) <= 0)
7960 goto out;
7961 }
Emeric Brun87855892012-10-17 17:39:35 +02007962 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
7963 goto out;
7964
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007965 smp->data.type = SMP_T_STR;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007966 smp->data.u.str = *smp_trash;
Emeric Brun87855892012-10-17 17:39:35 +02007967 ret = 1;
7968out:
Emeric Brunba841a12014-04-30 17:05:08 +02007969 /* SSL_get_peer_certificate, it increase X509 * ref count */
7970 if (cert_peer && crt)
Emeric Brun87855892012-10-17 17:39:35 +02007971 X509_free(crt);
7972 return ret;
7973}
Emeric Brun9143d372012-12-20 15:44:16 +01007974
7975/* integer, returns true if current session use a client certificate */
7976static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007977smp_fetch_ssl_c_used(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun9143d372012-12-20 15:44:16 +01007978{
7979 X509 *crt;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007980 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007981 struct ssl_sock_ctx *ctx;
Emeric Brun9143d372012-12-20 15:44:16 +01007982
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007983 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007984 if (!conn || conn->xprt != &ssl_sock)
7985 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007986 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007987
Willy Tarreau911db9b2020-01-23 16:27:54 +01007988 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Brun9143d372012-12-20 15:44:16 +01007989 smp->flags |= SMP_F_MAY_CHANGE;
7990 return 0;
7991 }
7992
7993 /* SSL_get_peer_certificate returns a ptr on allocated X509 struct */
Olivier Houchard66ab4982019-02-26 18:37:15 +01007994 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brun9143d372012-12-20 15:44:16 +01007995 if (crt) {
7996 X509_free(crt);
7997 }
7998
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007999 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02008000 smp->data.u.sint = (crt != NULL);
Emeric Brun9143d372012-12-20 15:44:16 +01008001 return 1;
8002}
8003
Emeric Brunba841a12014-04-30 17:05:08 +02008004/* integer, returns the certificate version
8005 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
8006 * should be use.
8007 */
Emeric Bruna7359fd2012-10-17 15:03:11 +02008008static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008009smp_fetch_ssl_x_version(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Bruna7359fd2012-10-17 15:03:11 +02008010{
Emeric Brunba841a12014-04-30 17:05:08 +02008011 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Bruna7359fd2012-10-17 15:03:11 +02008012 X509 *crt;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008013 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008014 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008015
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02008016 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008017 if (!conn || conn->xprt != &ssl_sock)
Emeric Bruna7359fd2012-10-17 15:03:11 +02008018 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008019 ctx = conn->xprt_ctx;
Emeric Bruna7359fd2012-10-17 15:03:11 +02008020
Willy Tarreau911db9b2020-01-23 16:27:54 +01008021 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Bruna7359fd2012-10-17 15:03:11 +02008022 smp->flags |= SMP_F_MAY_CHANGE;
8023 return 0;
8024 }
8025
Emeric Brunba841a12014-04-30 17:05:08 +02008026 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01008027 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02008028 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01008029 crt = SSL_get_certificate(ctx->ssl);
Emeric Bruna7359fd2012-10-17 15:03:11 +02008030 if (!crt)
8031 return 0;
8032
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02008033 smp->data.u.sint = (unsigned int)(1 + X509_get_version(crt));
Emeric Brunba841a12014-04-30 17:05:08 +02008034 /* SSL_get_peer_certificate increase X509 * ref count */
8035 if (cert_peer)
8036 X509_free(crt);
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008037 smp->data.type = SMP_T_SINT;
Emeric Bruna7359fd2012-10-17 15:03:11 +02008038
8039 return 1;
8040}
8041
Emeric Brunba841a12014-04-30 17:05:08 +02008042/* string, returns the certificate's signature algorithm.
8043 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
8044 * should be use.
8045 */
Emeric Brun7f56e742012-10-19 18:15:40 +02008046static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008047smp_fetch_ssl_x_sig_alg(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun7f56e742012-10-19 18:15:40 +02008048{
Emeric Brunba841a12014-04-30 17:05:08 +02008049 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun7f56e742012-10-19 18:15:40 +02008050 X509 *crt;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02008051 __OPENSSL_110_CONST__ ASN1_OBJECT *algorithm;
Emeric Brun7f56e742012-10-19 18:15:40 +02008052 int nid;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008053 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008054 struct ssl_sock_ctx *ctx;
Emeric Brun7f56e742012-10-19 18:15:40 +02008055
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02008056 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008057 if (!conn || conn->xprt != &ssl_sock)
8058 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008059 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008060
Willy Tarreau911db9b2020-01-23 16:27:54 +01008061 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Brun7f56e742012-10-19 18:15:40 +02008062 smp->flags |= SMP_F_MAY_CHANGE;
8063 return 0;
8064 }
8065
Emeric Brunba841a12014-04-30 17:05:08 +02008066 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01008067 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02008068 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01008069 crt = SSL_get_certificate(ctx->ssl);
Emeric Brun7f56e742012-10-19 18:15:40 +02008070 if (!crt)
8071 return 0;
8072
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02008073 X509_ALGOR_get0(&algorithm, NULL, NULL, X509_get0_tbs_sigalg(crt));
8074 nid = OBJ_obj2nid(algorithm);
Emeric Brun7f56e742012-10-19 18:15:40 +02008075
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008076 smp->data.u.str.area = (char *)OBJ_nid2sn(nid);
8077 if (!smp->data.u.str.area) {
Emeric Brunba841a12014-04-30 17:05:08 +02008078 /* SSL_get_peer_certificate increase X509 * ref count */
8079 if (cert_peer)
8080 X509_free(crt);
Emeric Brun7f56e742012-10-19 18:15:40 +02008081 return 0;
Emeric Brun9bf3ba22013-10-07 14:31:44 +02008082 }
Emeric Brun7f56e742012-10-19 18:15:40 +02008083
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008084 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008085 smp->flags |= SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008086 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brunba841a12014-04-30 17:05:08 +02008087 /* SSL_get_peer_certificate increase X509 * ref count */
8088 if (cert_peer)
8089 X509_free(crt);
Emeric Brun7f56e742012-10-19 18:15:40 +02008090
8091 return 1;
8092}
8093
Emeric Brunba841a12014-04-30 17:05:08 +02008094/* string, returns the certificate's key algorithm.
8095 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
8096 * should be use.
8097 */
Emeric Brun521a0112012-10-22 12:22:55 +02008098static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008099smp_fetch_ssl_x_key_alg(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun521a0112012-10-22 12:22:55 +02008100{
Emeric Brunba841a12014-04-30 17:05:08 +02008101 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun521a0112012-10-22 12:22:55 +02008102 X509 *crt;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02008103 ASN1_OBJECT *algorithm;
Emeric Brun521a0112012-10-22 12:22:55 +02008104 int nid;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008105 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008106 struct ssl_sock_ctx *ctx;
Emeric Brun521a0112012-10-22 12:22:55 +02008107
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02008108 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008109 if (!conn || conn->xprt != &ssl_sock)
8110 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008111 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008112
Willy Tarreau911db9b2020-01-23 16:27:54 +01008113 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Brun521a0112012-10-22 12:22:55 +02008114 smp->flags |= SMP_F_MAY_CHANGE;
8115 return 0;
8116 }
8117
Emeric Brunba841a12014-04-30 17:05:08 +02008118 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01008119 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02008120 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01008121 crt = SSL_get_certificate(ctx->ssl);
Emeric Brun521a0112012-10-22 12:22:55 +02008122 if (!crt)
8123 return 0;
8124
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02008125 X509_PUBKEY_get0_param(&algorithm, NULL, NULL, NULL, X509_get_X509_PUBKEY(crt));
8126 nid = OBJ_obj2nid(algorithm);
Emeric Brun521a0112012-10-22 12:22:55 +02008127
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008128 smp->data.u.str.area = (char *)OBJ_nid2sn(nid);
8129 if (!smp->data.u.str.area) {
Emeric Brunba841a12014-04-30 17:05:08 +02008130 /* SSL_get_peer_certificate increase X509 * ref count */
8131 if (cert_peer)
8132 X509_free(crt);
Emeric Brun521a0112012-10-22 12:22:55 +02008133 return 0;
Emeric Brun9bf3ba22013-10-07 14:31:44 +02008134 }
Emeric Brun521a0112012-10-22 12:22:55 +02008135
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008136 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008137 smp->flags |= SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008138 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brunba841a12014-04-30 17:05:08 +02008139 if (cert_peer)
8140 X509_free(crt);
Emeric Brun521a0112012-10-22 12:22:55 +02008141
8142 return 1;
8143}
8144
Emeric Brun645ae792014-04-30 14:21:06 +02008145/* boolean, returns true if front conn. transport layer is SSL.
8146 * This function is also usable on backend conn if the fetch keyword 5th
8147 * char is 'b'.
8148 */
Willy Tarreau7875d092012-09-10 08:20:03 +02008149static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008150smp_fetch_ssl_fc(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02008151{
Emeric Bruneb8def92018-02-19 15:59:48 +01008152 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
8153 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008154
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008155 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02008156 smp->data.u.sint = (conn && conn->xprt == &ssl_sock);
Willy Tarreau7875d092012-09-10 08:20:03 +02008157 return 1;
8158}
8159
Emeric Brun2525b6b2012-10-18 15:59:43 +02008160/* boolean, returns true if client present a SNI */
Willy Tarreau7875d092012-09-10 08:20:03 +02008161static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008162smp_fetch_ssl_fc_has_sni(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02008163{
8164#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02008165 struct connection *conn = objt_conn(smp->sess->origin);
Olivier Houchard66ab4982019-02-26 18:37:15 +01008166 struct ssl_sock_ctx *ctx = conn ? conn->xprt_ctx : NULL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008167
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008168 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02008169 smp->data.u.sint = (conn && conn->xprt == &ssl_sock) &&
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008170 conn->xprt_ctx &&
Olivier Houchard66ab4982019-02-26 18:37:15 +01008171 SSL_get_servername(ctx->ssl, TLSEXT_NAMETYPE_host_name) != NULL;
Willy Tarreau7875d092012-09-10 08:20:03 +02008172 return 1;
8173#else
8174 return 0;
8175#endif
8176}
8177
Emeric Brun74f7ffa2018-02-19 16:14:12 +01008178/* boolean, returns true if client session has been resumed.
8179 * This function is also usable on backend conn if the fetch keyword 5th
8180 * char is 'b'.
8181 */
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02008182static int
8183smp_fetch_ssl_fc_is_resumed(const struct arg *args, struct sample *smp, const char *kw, void *private)
8184{
Emeric Brun74f7ffa2018-02-19 16:14:12 +01008185 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
8186 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008187 struct ssl_sock_ctx *ctx = conn ? conn->xprt_ctx : NULL;
Emeric Brun74f7ffa2018-02-19 16:14:12 +01008188
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02008189
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008190 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02008191 smp->data.u.sint = (conn && conn->xprt == &ssl_sock) &&
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02008192 conn->xprt_ctx &&
Olivier Houchard66ab4982019-02-26 18:37:15 +01008193 SSL_session_reused(ctx->ssl);
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02008194 return 1;
8195}
8196
Emeric Brun645ae792014-04-30 14:21:06 +02008197/* string, returns the used cipher if front conn. transport layer is SSL.
8198 * This function is also usable on backend conn if the fetch keyword 5th
8199 * char is 'b'.
8200 */
Emeric Brun589fcad2012-10-16 14:13:26 +02008201static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008202smp_fetch_ssl_fc_cipher(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02008203{
Emeric Bruneb8def92018-02-19 15:59:48 +01008204 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
8205 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008206 struct ssl_sock_ctx *ctx;
Emeric Brun589fcad2012-10-16 14:13:26 +02008207
Willy Tarreaube508f12016-03-10 11:47:01 +01008208 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008209 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02008210 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008211 ctx = conn->xprt_ctx;
Emeric Brun589fcad2012-10-16 14:13:26 +02008212
Olivier Houchard66ab4982019-02-26 18:37:15 +01008213 smp->data.u.str.area = (char *)SSL_get_cipher_name(ctx->ssl);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008214 if (!smp->data.u.str.area)
Emeric Brun589fcad2012-10-16 14:13:26 +02008215 return 0;
8216
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008217 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008218 smp->flags |= SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008219 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brun589fcad2012-10-16 14:13:26 +02008220
8221 return 1;
8222}
8223
Emeric Brun645ae792014-04-30 14:21:06 +02008224/* integer, returns the algoritm's keysize if front conn. transport layer
8225 * is SSL.
8226 * This function is also usable on backend conn if the fetch keyword 5th
8227 * char is 'b'.
8228 */
Emeric Brun589fcad2012-10-16 14:13:26 +02008229static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008230smp_fetch_ssl_fc_alg_keysize(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02008231{
Emeric Bruneb8def92018-02-19 15:59:48 +01008232 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
8233 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008234 struct ssl_sock_ctx *ctx;
Willy Tarreaue237fe12016-03-10 17:05:28 +01008235 int sint;
Willy Tarreaube508f12016-03-10 11:47:01 +01008236
Emeric Brun589fcad2012-10-16 14:13:26 +02008237 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008238 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02008239 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008240 ctx = conn->xprt_ctx;
Emeric Brun589fcad2012-10-16 14:13:26 +02008241
Olivier Houchard66ab4982019-02-26 18:37:15 +01008242 if (!SSL_get_cipher_bits(ctx->ssl, &sint))
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008243 return 0;
8244
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02008245 smp->data.u.sint = sint;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008246 smp->data.type = SMP_T_SINT;
Emeric Brun589fcad2012-10-16 14:13:26 +02008247
8248 return 1;
8249}
8250
Emeric Brun645ae792014-04-30 14:21:06 +02008251/* integer, returns the used keysize if front conn. transport layer is SSL.
8252 * This function is also usable on backend conn if the fetch keyword 5th
8253 * char is 'b'.
8254 */
Emeric Brun589fcad2012-10-16 14:13:26 +02008255static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008256smp_fetch_ssl_fc_use_keysize(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02008257{
Emeric Bruneb8def92018-02-19 15:59:48 +01008258 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
8259 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008260 struct ssl_sock_ctx *ctx;
Willy Tarreaube508f12016-03-10 11:47:01 +01008261
Emeric Brun589fcad2012-10-16 14:13:26 +02008262 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008263 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8264 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008265 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008266
Olivier Houchard66ab4982019-02-26 18:37:15 +01008267 smp->data.u.sint = (unsigned int)SSL_get_cipher_bits(ctx->ssl, NULL);
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02008268 if (!smp->data.u.sint)
Emeric Brun589fcad2012-10-16 14:13:26 +02008269 return 0;
8270
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008271 smp->data.type = SMP_T_SINT;
Emeric Brun589fcad2012-10-16 14:13:26 +02008272
8273 return 1;
8274}
8275
Bernard Spil13c53f82018-02-15 13:34:58 +01008276#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Willy Tarreau7875d092012-09-10 08:20:03 +02008277static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008278smp_fetch_ssl_fc_npn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreaua33c6542012-10-15 13:19:06 +02008279{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008280 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008281 struct ssl_sock_ctx *ctx;
Willy Tarreau105599c2020-02-25 08:59:23 +01008282 unsigned int len = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008283
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008284 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008285 smp->data.type = SMP_T_STR;
Willy Tarreaua33c6542012-10-15 13:19:06 +02008286
Olivier Houchard6b77f492018-11-22 18:18:29 +01008287 conn = (kw[4] != 'b' ) ? objt_conn(smp->sess->origin) :
8288 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008289 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8290 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008291 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008292
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008293 smp->data.u.str.area = NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008294 SSL_get0_next_proto_negotiated(ctx->ssl,
Willy Tarreau105599c2020-02-25 08:59:23 +01008295 (const unsigned char **)&smp->data.u.str.area,
8296 &len);
Willy Tarreaua33c6542012-10-15 13:19:06 +02008297
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008298 if (!smp->data.u.str.area)
Willy Tarreaua33c6542012-10-15 13:19:06 +02008299 return 0;
8300
Willy Tarreau105599c2020-02-25 08:59:23 +01008301 smp->data.u.str.data = len;
Willy Tarreaua33c6542012-10-15 13:19:06 +02008302 return 1;
Willy Tarreaua33c6542012-10-15 13:19:06 +02008303}
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02008304#endif
Willy Tarreaua33c6542012-10-15 13:19:06 +02008305
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01008306#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02008307static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008308smp_fetch_ssl_fc_alpn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreauab861d32013-04-02 02:30:41 +02008309{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008310 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008311 struct ssl_sock_ctx *ctx;
Willy Tarreau105599c2020-02-25 08:59:23 +01008312 unsigned int len = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008313
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008314 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008315 smp->data.type = SMP_T_STR;
Willy Tarreauab861d32013-04-02 02:30:41 +02008316
Olivier Houchard6b77f492018-11-22 18:18:29 +01008317 conn = (kw[4] != 'b' ) ? objt_conn(smp->sess->origin) :
8318 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
8319
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008320 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Willy Tarreauab861d32013-04-02 02:30:41 +02008321 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008322 ctx = conn->xprt_ctx;
Willy Tarreauab861d32013-04-02 02:30:41 +02008323
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008324 smp->data.u.str.area = NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008325 SSL_get0_alpn_selected(ctx->ssl,
Willy Tarreau105599c2020-02-25 08:59:23 +01008326 (const unsigned char **)&smp->data.u.str.area,
8327 &len);
Willy Tarreauab861d32013-04-02 02:30:41 +02008328
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008329 if (!smp->data.u.str.area)
Willy Tarreauab861d32013-04-02 02:30:41 +02008330 return 0;
8331
Willy Tarreau105599c2020-02-25 08:59:23 +01008332 smp->data.u.str.data = len;
Willy Tarreauab861d32013-04-02 02:30:41 +02008333 return 1;
8334}
8335#endif
8336
Emeric Brun645ae792014-04-30 14:21:06 +02008337/* string, returns the used protocol if front conn. transport layer is SSL.
8338 * This function is also usable on backend conn if the fetch keyword 5th
8339 * char is 'b'.
8340 */
Willy Tarreaua33c6542012-10-15 13:19:06 +02008341static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008342smp_fetch_ssl_fc_protocol(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02008343{
Emeric Bruneb8def92018-02-19 15:59:48 +01008344 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
8345 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008346 struct ssl_sock_ctx *ctx;
Willy Tarreaube508f12016-03-10 11:47:01 +01008347
Emeric Brun589fcad2012-10-16 14:13:26 +02008348 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008349 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8350 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008351 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008352
Olivier Houchard66ab4982019-02-26 18:37:15 +01008353 smp->data.u.str.area = (char *)SSL_get_version(ctx->ssl);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008354 if (!smp->data.u.str.area)
Emeric Brun589fcad2012-10-16 14:13:26 +02008355 return 0;
8356
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008357 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008358 smp->flags = SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008359 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brun589fcad2012-10-16 14:13:26 +02008360
8361 return 1;
8362}
8363
Willy Tarreau87b09662015-04-03 00:22:06 +02008364/* binary, returns the SSL stream id if front conn. transport layer is SSL.
Emeric Brun645ae792014-04-30 14:21:06 +02008365 * This function is also usable on backend conn if the fetch keyword 5th
8366 * char is 'b'.
8367 */
Willy Tarreau9a1ab082019-05-09 13:26:41 +02008368#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
Emeric Brun589fcad2012-10-16 14:13:26 +02008369static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008370smp_fetch_ssl_fc_session_id(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunfe68f682012-10-16 14:59:28 +02008371{
Emeric Bruneb8def92018-02-19 15:59:48 +01008372 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
8373 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaue237fe12016-03-10 17:05:28 +01008374 SSL_SESSION *ssl_sess;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008375 struct ssl_sock_ctx *ctx;
Willy Tarreau105599c2020-02-25 08:59:23 +01008376 unsigned int len = 0;
Willy Tarreaube508f12016-03-10 11:47:01 +01008377
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008378 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008379 smp->data.type = SMP_T_BIN;
Emeric Brunfe68f682012-10-16 14:59:28 +02008380
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008381 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8382 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008383 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008384
Olivier Houchard66ab4982019-02-26 18:37:15 +01008385 ssl_sess = SSL_get_session(ctx->ssl);
Willy Tarreau192252e2015-04-04 01:47:55 +02008386 if (!ssl_sess)
Emeric Brunfe68f682012-10-16 14:59:28 +02008387 return 0;
8388
Willy Tarreau105599c2020-02-25 08:59:23 +01008389 smp->data.u.str.area = (char *)SSL_SESSION_get_id(ssl_sess, &len);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008390 if (!smp->data.u.str.area || !smp->data.u.str.data)
Emeric Brunfe68f682012-10-16 14:59:28 +02008391 return 0;
8392
Willy Tarreau105599c2020-02-25 08:59:23 +01008393 smp->data.u.str.data = len;
Emeric Brunfe68f682012-10-16 14:59:28 +02008394 return 1;
Emeric Brunfe68f682012-10-16 14:59:28 +02008395}
Patrick Hemmer41966772018-04-28 19:15:48 -04008396#endif
8397
Emeric Brunfe68f682012-10-16 14:59:28 +02008398
Emmanuel Hocdet839af572019-05-14 16:27:35 +02008399#if HA_OPENSSL_VERSION_NUMBER >= 0x10100000L
Patrick Hemmere0275472018-04-28 19:15:51 -04008400static int
Patrick Hemmer65674662019-06-04 08:13:03 -04008401smp_fetch_ssl_fc_random(const struct arg *args, struct sample *smp, const char *kw, void *private)
8402{
8403 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
8404 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
8405 struct buffer *data;
8406 struct ssl_sock_ctx *ctx;
8407
8408 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8409 return 0;
8410 ctx = conn->xprt_ctx;
8411
8412 data = get_trash_chunk();
8413 if (kw[7] == 'c')
8414 data->data = SSL_get_client_random(ctx->ssl,
8415 (unsigned char *) data->area,
8416 data->size);
8417 else
8418 data->data = SSL_get_server_random(ctx->ssl,
8419 (unsigned char *) data->area,
8420 data->size);
8421 if (!data->data)
8422 return 0;
8423
8424 smp->flags = 0;
8425 smp->data.type = SMP_T_BIN;
8426 smp->data.u.str = *data;
8427
8428 return 1;
8429}
8430
8431static int
Patrick Hemmere0275472018-04-28 19:15:51 -04008432smp_fetch_ssl_fc_session_key(const struct arg *args, struct sample *smp, const char *kw, void *private)
8433{
8434 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
8435 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
8436 SSL_SESSION *ssl_sess;
Willy Tarreau83061a82018-07-13 11:56:34 +02008437 struct buffer *data;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008438 struct ssl_sock_ctx *ctx;
Patrick Hemmere0275472018-04-28 19:15:51 -04008439
8440 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8441 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008442 ctx = conn->xprt_ctx;
Patrick Hemmere0275472018-04-28 19:15:51 -04008443
Olivier Houchard66ab4982019-02-26 18:37:15 +01008444 ssl_sess = SSL_get_session(ctx->ssl);
Patrick Hemmere0275472018-04-28 19:15:51 -04008445 if (!ssl_sess)
8446 return 0;
8447
8448 data = get_trash_chunk();
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008449 data->data = SSL_SESSION_get_master_key(ssl_sess,
8450 (unsigned char *) data->area,
8451 data->size);
8452 if (!data->data)
Patrick Hemmere0275472018-04-28 19:15:51 -04008453 return 0;
8454
8455 smp->flags = 0;
8456 smp->data.type = SMP_T_BIN;
8457 smp->data.u.str = *data;
8458
8459 return 1;
8460}
8461#endif
8462
Patrick Hemmer41966772018-04-28 19:15:48 -04008463#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emeric Brunfe68f682012-10-16 14:59:28 +02008464static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008465smp_fetch_ssl_fc_sni(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02008466{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008467 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008468 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008469
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008470 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008471 smp->data.type = SMP_T_STR;
Willy Tarreau7875d092012-09-10 08:20:03 +02008472
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02008473 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008474 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8475 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008476 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008477
Olivier Houchard66ab4982019-02-26 18:37:15 +01008478 smp->data.u.str.area = (char *)SSL_get_servername(ctx->ssl, TLSEXT_NAMETYPE_host_name);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008479 if (!smp->data.u.str.area)
Willy Tarreau3e394c92012-09-14 23:56:58 +02008480 return 0;
8481
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008482 smp->data.u.str.data = strlen(smp->data.u.str.area);
Willy Tarreau7875d092012-09-10 08:20:03 +02008483 return 1;
Willy Tarreau7875d092012-09-10 08:20:03 +02008484}
Patrick Hemmer41966772018-04-28 19:15:48 -04008485#endif
Willy Tarreau7875d092012-09-10 08:20:03 +02008486
David Sc1ad52e2014-04-08 18:48:47 -04008487static int
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008488smp_fetch_ssl_fc_cl_bin(const struct arg *args, struct sample *smp, const char *kw, void *private)
8489{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008490 struct connection *conn;
8491 struct ssl_capture *capture;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008492 struct ssl_sock_ctx *ctx;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008493
8494 conn = objt_conn(smp->sess->origin);
8495 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8496 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008497 ctx = conn->xprt_ctx;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008498
Olivier Houchard66ab4982019-02-26 18:37:15 +01008499 capture = SSL_get_ex_data(ctx->ssl, ssl_capture_ptr_index);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008500 if (!capture)
8501 return 0;
8502
8503 smp->flags = SMP_F_CONST;
8504 smp->data.type = SMP_T_BIN;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008505 smp->data.u.str.area = capture->ciphersuite;
8506 smp->data.u.str.data = capture->ciphersuite_len;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008507 return 1;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008508}
8509
8510static int
8511smp_fetch_ssl_fc_cl_hex(const struct arg *args, struct sample *smp, const char *kw, void *private)
8512{
Willy Tarreau83061a82018-07-13 11:56:34 +02008513 struct buffer *data;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008514
8515 if (!smp_fetch_ssl_fc_cl_bin(args, smp, kw, private))
8516 return 0;
8517
8518 data = get_trash_chunk();
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008519 dump_binary(data, smp->data.u.str.area, smp->data.u.str.data);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008520 smp->data.type = SMP_T_BIN;
8521 smp->data.u.str = *data;
8522 return 1;
8523}
8524
8525static int
8526smp_fetch_ssl_fc_cl_xxh64(const struct arg *args, struct sample *smp, const char *kw, void *private)
8527{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008528 struct connection *conn;
8529 struct ssl_capture *capture;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008530 struct ssl_sock_ctx *ctx;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008531
8532 conn = objt_conn(smp->sess->origin);
8533 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8534 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008535 ctx = conn->xprt_ctx;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008536
Olivier Houchard66ab4982019-02-26 18:37:15 +01008537 capture = SSL_get_ex_data(ctx->ssl, ssl_capture_ptr_index);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008538 if (!capture)
8539 return 0;
8540
8541 smp->data.type = SMP_T_SINT;
8542 smp->data.u.sint = capture->xxh64;
8543 return 1;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008544}
8545
8546static int
8547smp_fetch_ssl_fc_cl_str(const struct arg *args, struct sample *smp, const char *kw, void *private)
8548{
Willy Tarreau5db847a2019-05-09 14:13:35 +02008549#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL)
Willy Tarreau83061a82018-07-13 11:56:34 +02008550 struct buffer *data;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008551 int i;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008552
8553 if (!smp_fetch_ssl_fc_cl_bin(args, smp, kw, private))
8554 return 0;
8555
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008556 data = get_trash_chunk();
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008557 for (i = 0; i + 1 < smp->data.u.str.data; i += 2) {
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02008558 const char *str;
8559 const SSL_CIPHER *cipher;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008560 const unsigned char *bin = (const unsigned char *) smp->data.u.str.area + i;
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02008561 uint16_t id = (bin[0] << 8) | bin[1];
8562#if defined(OPENSSL_IS_BORINGSSL)
8563 cipher = SSL_get_cipher_by_value(id);
8564#else
Willy Tarreaub7290772018-10-15 11:01:59 +02008565 struct connection *conn = __objt_conn(smp->sess->origin);
Olivier Houchard66ab4982019-02-26 18:37:15 +01008566 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
8567 cipher = SSL_CIPHER_find(ctx->ssl, bin);
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02008568#endif
8569 str = SSL_CIPHER_get_name(cipher);
8570 if (!str || strcmp(str, "(NONE)") == 0)
8571 chunk_appendf(data, "%sUNKNOWN(%04x)", i == 0 ? "" : ",", id);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008572 else
8573 chunk_appendf(data, "%s%s", i == 0 ? "" : ",", str);
8574 }
8575 smp->data.type = SMP_T_STR;
8576 smp->data.u.str = *data;
8577 return 1;
8578#else
8579 return smp_fetch_ssl_fc_cl_xxh64(args, smp, kw, private);
8580#endif
8581}
8582
Willy Tarreau9a1ab082019-05-09 13:26:41 +02008583#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008584static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008585smp_fetch_ssl_fc_unique_id(const struct arg *args, struct sample *smp, const char *kw, void *private)
David Sc1ad52e2014-04-08 18:48:47 -04008586{
Emeric Bruneb8def92018-02-19 15:59:48 +01008587 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
8588 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
David Sc1ad52e2014-04-08 18:48:47 -04008589 int finished_len;
Willy Tarreau83061a82018-07-13 11:56:34 +02008590 struct buffer *finished_trash;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008591 struct ssl_sock_ctx *ctx;
David Sc1ad52e2014-04-08 18:48:47 -04008592
8593 smp->flags = 0;
David Sc1ad52e2014-04-08 18:48:47 -04008594 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8595 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008596 ctx = conn->xprt_ctx;
David Sc1ad52e2014-04-08 18:48:47 -04008597
Willy Tarreau911db9b2020-01-23 16:27:54 +01008598 if (conn->flags & CO_FL_WAIT_XPRT) {
David Sc1ad52e2014-04-08 18:48:47 -04008599 smp->flags |= SMP_F_MAY_CHANGE;
8600 return 0;
8601 }
8602
8603 finished_trash = get_trash_chunk();
Olivier Houchard66ab4982019-02-26 18:37:15 +01008604 if (!SSL_session_reused(ctx->ssl))
8605 finished_len = SSL_get_peer_finished(ctx->ssl,
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008606 finished_trash->area,
8607 finished_trash->size);
David Sc1ad52e2014-04-08 18:48:47 -04008608 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01008609 finished_len = SSL_get_finished(ctx->ssl,
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008610 finished_trash->area,
8611 finished_trash->size);
David Sc1ad52e2014-04-08 18:48:47 -04008612
8613 if (!finished_len)
8614 return 0;
8615
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008616 finished_trash->data = finished_len;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02008617 smp->data.u.str = *finished_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008618 smp->data.type = SMP_T_BIN;
David Sc1ad52e2014-04-08 18:48:47 -04008619
8620 return 1;
David Sc1ad52e2014-04-08 18:48:47 -04008621}
Patrick Hemmer41966772018-04-28 19:15:48 -04008622#endif
David Sc1ad52e2014-04-08 18:48:47 -04008623
Emeric Brun2525b6b2012-10-18 15:59:43 +02008624/* integer, returns the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02008625static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008626smp_fetch_ssl_c_ca_err(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunf282a812012-09-21 15:27:54 +02008627{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008628 struct connection *conn;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008629 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008630
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02008631 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008632 if (!conn || conn->xprt != &ssl_sock)
8633 return 0;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008634 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008635
Willy Tarreau911db9b2020-01-23 16:27:54 +01008636 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Brunf282a812012-09-21 15:27:54 +02008637 smp->flags = SMP_F_MAY_CHANGE;
8638 return 0;
8639 }
8640
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008641 smp->data.type = SMP_T_SINT;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008642 smp->data.u.sint = (unsigned long long int)SSL_SOCK_ST_TO_CA_ERROR(ctx->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02008643 smp->flags = 0;
8644
8645 return 1;
8646}
8647
Emeric Brun2525b6b2012-10-18 15:59:43 +02008648/* integer, returns the depth of the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02008649static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008650smp_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 +02008651{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008652 struct connection *conn;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008653 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008654
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02008655 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008656 if (!conn || conn->xprt != &ssl_sock)
Emeric Brunf282a812012-09-21 15:27:54 +02008657 return 0;
8658
Willy Tarreau911db9b2020-01-23 16:27:54 +01008659 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Brunf282a812012-09-21 15:27:54 +02008660 smp->flags = SMP_F_MAY_CHANGE;
8661 return 0;
8662 }
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008663 ctx = conn->xprt_ctx;
Emeric Brunf282a812012-09-21 15:27:54 +02008664
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008665 smp->data.type = SMP_T_SINT;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008666 smp->data.u.sint = (long long int)SSL_SOCK_ST_TO_CAEDEPTH(ctx->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02008667 smp->flags = 0;
8668
8669 return 1;
8670}
8671
Emeric Brun2525b6b2012-10-18 15:59:43 +02008672/* integer, returns the first verify error on client certificate */
Emeric Brunf282a812012-09-21 15:27:54 +02008673static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008674smp_fetch_ssl_c_err(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunf282a812012-09-21 15:27:54 +02008675{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008676 struct connection *conn;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008677 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008678
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02008679 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008680 if (!conn || conn->xprt != &ssl_sock)
8681 return 0;
8682
Willy Tarreau911db9b2020-01-23 16:27:54 +01008683 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Brunf282a812012-09-21 15:27:54 +02008684 smp->flags = SMP_F_MAY_CHANGE;
8685 return 0;
8686 }
8687
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008688 ctx = conn->xprt_ctx;
8689
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008690 smp->data.type = SMP_T_SINT;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008691 smp->data.u.sint = (long long int)SSL_SOCK_ST_TO_CRTERROR(ctx->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02008692 smp->flags = 0;
8693
8694 return 1;
8695}
8696
Emeric Brun2525b6b2012-10-18 15:59:43 +02008697/* integer, returns the verify result on client cert */
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02008698static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008699smp_fetch_ssl_c_verify(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02008700{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008701 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008702 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008703
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02008704 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008705 if (!conn || conn->xprt != &ssl_sock)
8706 return 0;
8707
Willy Tarreau911db9b2020-01-23 16:27:54 +01008708 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02008709 smp->flags = SMP_F_MAY_CHANGE;
8710 return 0;
8711 }
8712
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008713 if (!conn->xprt_ctx)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02008714 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008715 ctx = conn->xprt_ctx;
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02008716
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008717 smp->data.type = SMP_T_SINT;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008718 smp->data.u.sint = (long long int)SSL_get_verify_result(ctx->ssl);
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02008719 smp->flags = 0;
8720
8721 return 1;
8722}
8723
Emmanuel Hocdet842e94e2019-12-16 16:39:17 +01008724/* for ca-file and ca-verify-file */
8725static 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 +02008726{
8727 if (!*args[cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01008728 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
Emeric Brund94b3fe2012-09-20 18:23:56 +02008729 return ERR_ALERT | ERR_FATAL;
8730 }
8731
Willy Tarreauef934602016-12-22 23:12:01 +01008732 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
Emmanuel Hocdet842e94e2019-12-16 16:39:17 +01008733 memprintf(ca_file_p, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02008734 else
Emmanuel Hocdet842e94e2019-12-16 16:39:17 +01008735 memprintf(ca_file_p, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02008736
Emmanuel Hocdet842e94e2019-12-16 16:39:17 +01008737 if (!ssl_store_load_locations_file(*ca_file_p)) {
8738 memprintf(err, "'%s' : unable to load %s", args[cur_arg], *ca_file_p);
Emmanuel Hocdetd4f9a602019-10-24 11:32:47 +02008739 return ERR_ALERT | ERR_FATAL;
8740 }
Emeric Brund94b3fe2012-09-20 18:23:56 +02008741 return 0;
8742}
Emmanuel Hocdet842e94e2019-12-16 16:39:17 +01008743
8744/* parse the "ca-file" bind keyword */
8745static int ssl_bind_parse_ca_file(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
8746{
8747 return ssl_bind_parse_ca_file_common(args, cur_arg, &conf->ca_file, err);
8748}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008749static int bind_parse_ca_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8750{
8751 return ssl_bind_parse_ca_file(args, cur_arg, px, &conf->ssl_conf, err);
8752}
Emeric Brund94b3fe2012-09-20 18:23:56 +02008753
Emmanuel Hocdet842e94e2019-12-16 16:39:17 +01008754/* parse the "ca-verify-file" bind keyword */
8755static int ssl_bind_parse_ca_verify_file(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
8756{
8757 return ssl_bind_parse_ca_file_common(args, cur_arg, &conf->ca_verify_file, err);
8758}
8759static int bind_parse_ca_verify_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8760{
8761 return ssl_bind_parse_ca_verify_file(args, cur_arg, px, &conf->ssl_conf, err);
8762}
8763
Christopher Faulet31af49d2015-06-09 17:29:50 +02008764/* parse the "ca-sign-file" bind keyword */
8765static int bind_parse_ca_sign_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8766{
8767 if (!*args[cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01008768 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
Christopher Faulet31af49d2015-06-09 17:29:50 +02008769 return ERR_ALERT | ERR_FATAL;
8770 }
8771
Willy Tarreauef934602016-12-22 23:12:01 +01008772 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
8773 memprintf(&conf->ca_sign_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Christopher Faulet31af49d2015-06-09 17:29:50 +02008774 else
8775 memprintf(&conf->ca_sign_file, "%s", args[cur_arg + 1]);
8776
8777 return 0;
8778}
8779
Bertrand Jacquinff13c062016-11-13 16:37:11 +00008780/* parse the "ca-sign-pass" bind keyword */
Christopher Faulet31af49d2015-06-09 17:29:50 +02008781static int bind_parse_ca_sign_pass(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8782{
8783 if (!*args[cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01008784 memprintf(err, "'%s' : missing CAkey password", args[cur_arg]);
Christopher Faulet31af49d2015-06-09 17:29:50 +02008785 return ERR_ALERT | ERR_FATAL;
8786 }
8787 memprintf(&conf->ca_sign_pass, "%s", args[cur_arg + 1]);
8788 return 0;
8789}
8790
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008791/* parse the "ciphers" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008792static 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 +02008793{
8794 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02008795 memprintf(err, "'%s' : missing cipher suite", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008796 return ERR_ALERT | ERR_FATAL;
8797 }
8798
Emeric Brun76d88952012-10-05 15:47:31 +02008799 free(conf->ciphers);
Willy Tarreau4348fad2012-09-20 16:48:07 +02008800 conf->ciphers = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008801 return 0;
8802}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008803static int bind_parse_ciphers(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8804{
8805 return ssl_bind_parse_ciphers(args, cur_arg, px, &conf->ssl_conf, err);
8806}
Dirkjan Bussink415150f2018-09-14 11:14:21 +02008807
Emmanuel Hocdet839af572019-05-14 16:27:35 +02008808#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02008809/* parse the "ciphersuites" bind keyword */
8810static int ssl_bind_parse_ciphersuites(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
8811{
8812 if (!*args[cur_arg + 1]) {
8813 memprintf(err, "'%s' : missing cipher suite", args[cur_arg]);
8814 return ERR_ALERT | ERR_FATAL;
8815 }
8816
8817 free(conf->ciphersuites);
8818 conf->ciphersuites = strdup(args[cur_arg + 1]);
8819 return 0;
8820}
8821static int bind_parse_ciphersuites(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8822{
8823 return ssl_bind_parse_ciphersuites(args, cur_arg, px, &conf->ssl_conf, err);
8824}
8825#endif
8826
Willy Tarreaubbc91962019-10-16 16:42:19 +02008827/* parse the "crt" bind keyword. Returns a set of ERR_* flags possibly with an error in <err>. */
Willy Tarreau4348fad2012-09-20 16:48:07 +02008828static 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 +02008829{
Willy Tarreau38011032013-08-13 16:59:39 +02008830 char path[MAXPATHLEN];
Willy Tarreaub75d6922014-04-14 18:05:41 +02008831
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008832 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02008833 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008834 return ERR_ALERT | ERR_FATAL;
8835 }
8836
Willy Tarreauef934602016-12-22 23:12:01 +01008837 if ((*args[cur_arg + 1] != '/' ) && global_ssl.crt_base) {
8838 if ((strlen(global_ssl.crt_base) + 1 + strlen(args[cur_arg + 1]) + 1) > MAXPATHLEN) {
Emeric Brunc8e8d122012-10-02 18:42:10 +02008839 memprintf(err, "'%s' : path too long", args[cur_arg]);
8840 return ERR_ALERT | ERR_FATAL;
8841 }
Willy Tarreauef934602016-12-22 23:12:01 +01008842 snprintf(path, sizeof(path), "%s/%s", global_ssl.crt_base, args[cur_arg + 1]);
Willy Tarreaubbc91962019-10-16 16:42:19 +02008843 return ssl_sock_load_cert(path, conf, err);
Emeric Brunc8e8d122012-10-02 18:42:10 +02008844 }
8845
Willy Tarreaubbc91962019-10-16 16:42:19 +02008846 return ssl_sock_load_cert(args[cur_arg + 1], conf, err);
Emeric Brund94b3fe2012-09-20 18:23:56 +02008847}
8848
Willy Tarreaubbc91962019-10-16 16:42:19 +02008849/* 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 +01008850static int bind_parse_crt_list(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8851{
Willy Tarreaubbc91962019-10-16 16:42:19 +02008852 int err_code;
8853
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01008854 if (!*args[cur_arg + 1]) {
8855 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
8856 return ERR_ALERT | ERR_FATAL;
8857 }
8858
Willy Tarreaubbc91962019-10-16 16:42:19 +02008859 err_code = ssl_sock_load_cert_list_file(args[cur_arg + 1], conf, px, err);
8860 if (err_code)
Willy Tarreauad1731d2013-04-02 17:35:58 +02008861 memprintf(err, "'%s' : %s", args[cur_arg], *err);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01008862
Willy Tarreaubbc91962019-10-16 16:42:19 +02008863 return err_code;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01008864}
8865
Emeric Brunfb510ea2012-10-05 12:00:26 +02008866/* parse the "crl-file" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008867static 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 +02008868{
Emeric Brun051cdab2012-10-02 19:25:50 +02008869#ifndef X509_V_FLAG_CRL_CHECK
Tim Duesterhus93128532019-11-23 23:45:10 +01008870 memprintf(err, "'%s' : library does not support CRL verify", args[cur_arg]);
Emeric Brun051cdab2012-10-02 19:25:50 +02008871 return ERR_ALERT | ERR_FATAL;
8872#else
Emeric Brund94b3fe2012-09-20 18:23:56 +02008873 if (!*args[cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01008874 memprintf(err, "'%s' : missing CRLfile path", args[cur_arg]);
Emeric Brund94b3fe2012-09-20 18:23:56 +02008875 return ERR_ALERT | ERR_FATAL;
8876 }
Emeric Brun2b58d042012-09-20 17:10:03 +02008877
Willy Tarreauef934602016-12-22 23:12:01 +01008878 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
8879 memprintf(&conf->crl_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02008880 else
8881 memprintf(&conf->crl_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02008882
Emmanuel Hocdetb270e812019-11-21 19:09:31 +01008883 if (!ssl_store_load_locations_file(conf->crl_file)) {
8884 memprintf(err, "'%s' : unable to load %s", args[cur_arg], conf->crl_file);
8885 return ERR_ALERT | ERR_FATAL;
8886 }
Emeric Brun2b58d042012-09-20 17:10:03 +02008887 return 0;
Emeric Brun051cdab2012-10-02 19:25:50 +02008888#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02008889}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008890static int bind_parse_crl_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8891{
8892 return ssl_bind_parse_crl_file(args, cur_arg, px, &conf->ssl_conf, err);
8893}
Emeric Brun2b58d042012-09-20 17:10:03 +02008894
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01008895/* parse the "curves" bind keyword keyword */
8896static int ssl_bind_parse_curves(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
8897{
Lukas Tribusd14b49c2019-11-24 18:20:40 +01008898#if ((HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL) || defined(LIBRESSL_VERSION_NUMBER))
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01008899 if (!*args[cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01008900 memprintf(err, "'%s' : missing curve suite", args[cur_arg]);
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01008901 return ERR_ALERT | ERR_FATAL;
8902 }
8903 conf->curves = strdup(args[cur_arg + 1]);
8904 return 0;
8905#else
Tim Duesterhus93128532019-11-23 23:45:10 +01008906 memprintf(err, "'%s' : library does not support curve suite", args[cur_arg]);
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01008907 return ERR_ALERT | ERR_FATAL;
8908#endif
8909}
8910static int bind_parse_curves(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8911{
8912 return ssl_bind_parse_curves(args, cur_arg, px, &conf->ssl_conf, err);
8913}
8914
Bertrand Jacquinff13c062016-11-13 16:37:11 +00008915/* parse the "ecdhe" bind keyword keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008916static 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 +02008917{
Willy Tarreau9a1ab082019-05-09 13:26:41 +02008918#if HA_OPENSSL_VERSION_NUMBER < 0x0090800fL
Tim Duesterhus93128532019-11-23 23:45:10 +01008919 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (too old)", args[cur_arg]);
Emeric Brun2b58d042012-09-20 17:10:03 +02008920 return ERR_ALERT | ERR_FATAL;
8921#elif defined(OPENSSL_NO_ECDH)
Tim Duesterhus93128532019-11-23 23:45:10 +01008922 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 +02008923 return ERR_ALERT | ERR_FATAL;
8924#else
8925 if (!*args[cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01008926 memprintf(err, "'%s' : missing named curve", args[cur_arg]);
Emeric Brun2b58d042012-09-20 17:10:03 +02008927 return ERR_ALERT | ERR_FATAL;
8928 }
8929
8930 conf->ecdhe = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008931
8932 return 0;
Emeric Brun2b58d042012-09-20 17:10:03 +02008933#endif
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008934}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008935static int bind_parse_ecdhe(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8936{
8937 return ssl_bind_parse_ecdhe(args, cur_arg, px, &conf->ssl_conf, err);
8938}
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008939
Bertrand Jacquinff13c062016-11-13 16:37:11 +00008940/* parse the "crt-ignore-err" and "ca-ignore-err" bind keywords */
Emeric Brun81c00f02012-09-21 14:31:21 +02008941static int bind_parse_ignore_err(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8942{
8943 int code;
8944 char *p = args[cur_arg + 1];
8945 unsigned long long *ignerr = &conf->crt_ignerr;
8946
8947 if (!*p) {
Tim Duesterhus93128532019-11-23 23:45:10 +01008948 memprintf(err, "'%s' : missing error IDs list", args[cur_arg]);
Emeric Brun81c00f02012-09-21 14:31:21 +02008949 return ERR_ALERT | ERR_FATAL;
8950 }
8951
8952 if (strcmp(args[cur_arg], "ca-ignore-err") == 0)
8953 ignerr = &conf->ca_ignerr;
8954
8955 if (strcmp(p, "all") == 0) {
8956 *ignerr = ~0ULL;
8957 return 0;
8958 }
8959
8960 while (p) {
8961 code = atoi(p);
8962 if ((code <= 0) || (code > 63)) {
Tim Duesterhus93128532019-11-23 23:45:10 +01008963 memprintf(err, "'%s' : ID '%d' out of range (1..63) in error IDs list '%s'",
8964 args[cur_arg], code, args[cur_arg + 1]);
Emeric Brun81c00f02012-09-21 14:31:21 +02008965 return ERR_ALERT | ERR_FATAL;
8966 }
8967 *ignerr |= 1ULL << code;
8968 p = strchr(p, ',');
8969 if (p)
8970 p++;
8971 }
8972
Emeric Brun2cb7ae52012-10-05 14:14:21 +02008973 return 0;
8974}
8975
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008976/* parse tls_method_options "no-xxx" and "force-xxx" */
8977static int parse_tls_method_options(char *arg, struct tls_version_filter *methods, char **err)
Emeric Brun2cb7ae52012-10-05 14:14:21 +02008978{
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008979 uint16_t v;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008980 char *p;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008981 p = strchr(arg, '-');
8982 if (!p)
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008983 goto fail;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008984 p++;
8985 if (!strcmp(p, "sslv3"))
8986 v = CONF_SSLV3;
8987 else if (!strcmp(p, "tlsv10"))
8988 v = CONF_TLSV10;
8989 else if (!strcmp(p, "tlsv11"))
8990 v = CONF_TLSV11;
8991 else if (!strcmp(p, "tlsv12"))
8992 v = CONF_TLSV12;
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +02008993 else if (!strcmp(p, "tlsv13"))
8994 v = CONF_TLSV13;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008995 else
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008996 goto fail;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008997 if (!strncmp(arg, "no-", 3))
8998 methods->flags |= methodVersions[v].flag;
8999 else if (!strncmp(arg, "force-", 6))
9000 methods->min = methods->max = v;
9001 else
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02009002 goto fail;
Emeric Brun2d0c4822012-10-02 13:45:20 +02009003 return 0;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02009004 fail:
Tim Duesterhus93128532019-11-23 23:45:10 +01009005 memprintf(err, "'%s' : option not implemented", arg);
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02009006 return ERR_ALERT | ERR_FATAL;
Emeric Brun2d0c4822012-10-02 13:45:20 +02009007}
9008
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02009009static 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 +02009010{
Emmanuel Hocdet43664762017-08-09 18:26:20 +02009011 return parse_tls_method_options(args[cur_arg], &conf->ssl_conf.ssl_methods, err);
Emeric Brun2cb7ae52012-10-05 14:14:21 +02009012}
9013
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02009014static 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 +02009015{
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02009016 return parse_tls_method_options(args[*cur_arg], &newsrv->ssl_ctx.methods, err);
9017}
9018
9019/* parse tls_method min/max: "ssl-min-ver" and "ssl-max-ver" */
9020static int parse_tls_method_minmax(char **args, int cur_arg, struct tls_version_filter *methods, char **err)
9021{
9022 uint16_t i, v = 0;
9023 char *argv = args[cur_arg + 1];
9024 if (!*argv) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009025 memprintf(err, "'%s' : missing the ssl/tls version", args[cur_arg]);
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02009026 return ERR_ALERT | ERR_FATAL;
9027 }
9028 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
9029 if (!strcmp(argv, methodVersions[i].name))
9030 v = i;
9031 if (!v) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009032 memprintf(err, "'%s' : unknown ssl/tls version", args[cur_arg + 1]);
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02009033 return ERR_ALERT | ERR_FATAL;
9034 }
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02009035 if (!strcmp("ssl-min-ver", args[cur_arg]))
9036 methods->min = v;
9037 else if (!strcmp("ssl-max-ver", args[cur_arg]))
9038 methods->max = v;
9039 else {
Tim Duesterhus93128532019-11-23 23:45:10 +01009040 memprintf(err, "'%s' : option not implemented", args[cur_arg]);
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02009041 return ERR_ALERT | ERR_FATAL;
9042 }
Emeric Brun2cb7ae52012-10-05 14:14:21 +02009043 return 0;
Emeric Brun2cb7ae52012-10-05 14:14:21 +02009044}
Emeric Brun2cb7ae52012-10-05 14:14:21 +02009045
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02009046static int ssl_bind_parse_tls_method_minmax(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
9047{
Willy Tarreau9a1ab082019-05-09 13:26:41 +02009048#if (HA_OPENSSL_VERSION_NUMBER < 0x10101000L) && !defined(OPENSSL_IS_BORINGSSL)
Christopher Faulet767a84b2017-11-24 16:50:31 +01009049 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 +02009050#endif
9051 return parse_tls_method_minmax(args, cur_arg, &conf->ssl_methods, err);
9052}
9053
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02009054static int bind_parse_tls_method_minmax(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
9055{
Emmanuel Hocdet43664762017-08-09 18:26:20 +02009056 return parse_tls_method_minmax(args, cur_arg, &conf->ssl_conf.ssl_methods, err);
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02009057}
9058
9059static int srv_parse_tls_method_minmax(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9060{
9061 return parse_tls_method_minmax(args, *cur_arg, &newsrv->ssl_ctx.methods, err);
9062}
9063
Emeric Brun2d0c4822012-10-02 13:45:20 +02009064/* parse the "no-tls-tickets" bind keyword */
Emmanuel Hocdet4608ed92017-01-20 13:06:27 +01009065static 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 +02009066{
Emeric Brun89675492012-10-05 13:48:26 +02009067 conf->ssl_options |= BC_SSL_O_NO_TLS_TICKETS;
Emeric Brun81c00f02012-09-21 14:31:21 +02009068 return 0;
9069}
Emeric Brun2d0c4822012-10-02 13:45:20 +02009070
Olivier Houchardc2aae742017-09-22 18:26:28 +02009071/* parse the "allow-0rtt" bind keyword */
9072static int ssl_bind_parse_allow_0rtt(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
9073{
9074 conf->early_data = 1;
9075 return 0;
9076}
9077
9078static int bind_parse_allow_0rtt(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
9079{
Olivier Houchard9679ac92017-10-27 14:58:08 +02009080 conf->ssl_conf.early_data = 1;
Olivier Houchardc2aae742017-09-22 18:26:28 +02009081 return 0;
9082}
9083
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02009084/* parse the "npn" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01009085static 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 +02009086{
Bernard Spil13c53f82018-02-15 13:34:58 +01009087#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02009088 char *p1, *p2;
9089
9090 if (!*args[cur_arg + 1]) {
9091 memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[cur_arg]);
9092 return ERR_ALERT | ERR_FATAL;
9093 }
9094
9095 free(conf->npn_str);
9096
Willy Tarreau3724da12016-02-12 17:11:12 +01009097 /* the NPN string is built as a suite of (<len> <name>)*,
9098 * so we reuse each comma to store the next <len> and need
9099 * one more for the end of the string.
9100 */
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02009101 conf->npn_len = strlen(args[cur_arg + 1]) + 1;
Willy Tarreau3724da12016-02-12 17:11:12 +01009102 conf->npn_str = calloc(1, conf->npn_len + 1);
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02009103 memcpy(conf->npn_str + 1, args[cur_arg + 1], conf->npn_len);
9104
9105 /* replace commas with the name length */
9106 p1 = conf->npn_str;
9107 p2 = p1 + 1;
9108 while (1) {
9109 p2 = memchr(p1 + 1, ',', conf->npn_str + conf->npn_len - (p1 + 1));
9110 if (!p2)
9111 p2 = p1 + 1 + strlen(p1 + 1);
9112
9113 if (p2 - (p1 + 1) > 255) {
9114 *p2 = '\0';
9115 memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
9116 return ERR_ALERT | ERR_FATAL;
9117 }
9118
9119 *p1 = p2 - (p1 + 1);
9120 p1 = p2;
9121
9122 if (!*p2)
9123 break;
9124
9125 *(p2++) = '\0';
9126 }
9127 return 0;
9128#else
Tim Duesterhus93128532019-11-23 23:45:10 +01009129 memprintf(err, "'%s' : library does not support TLS NPN extension", args[cur_arg]);
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02009130 return ERR_ALERT | ERR_FATAL;
9131#endif
9132}
9133
Emmanuel Hocdet98263292016-12-29 18:26:15 +01009134static int bind_parse_npn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
9135{
9136 return ssl_bind_parse_npn(args, cur_arg, px, &conf->ssl_conf, err);
9137}
9138
Willy Tarreauab861d32013-04-02 02:30:41 +02009139/* parse the "alpn" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01009140static 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 +02009141{
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01009142#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02009143 char *p1, *p2;
9144
9145 if (!*args[cur_arg + 1]) {
9146 memprintf(err, "'%s' : missing the comma-delimited ALPN protocol suite", args[cur_arg]);
9147 return ERR_ALERT | ERR_FATAL;
9148 }
9149
9150 free(conf->alpn_str);
9151
Marcoen Hirschbergbef60912016-02-12 17:05:24 +01009152 /* the ALPN string is built as a suite of (<len> <name>)*,
9153 * so we reuse each comma to store the next <len> and need
9154 * one more for the end of the string.
9155 */
Willy Tarreauab861d32013-04-02 02:30:41 +02009156 conf->alpn_len = strlen(args[cur_arg + 1]) + 1;
Marcoen Hirschbergbef60912016-02-12 17:05:24 +01009157 conf->alpn_str = calloc(1, conf->alpn_len + 1);
Willy Tarreauab861d32013-04-02 02:30:41 +02009158 memcpy(conf->alpn_str + 1, args[cur_arg + 1], conf->alpn_len);
9159
9160 /* replace commas with the name length */
9161 p1 = conf->alpn_str;
9162 p2 = p1 + 1;
9163 while (1) {
9164 p2 = memchr(p1 + 1, ',', conf->alpn_str + conf->alpn_len - (p1 + 1));
9165 if (!p2)
9166 p2 = p1 + 1 + strlen(p1 + 1);
9167
9168 if (p2 - (p1 + 1) > 255) {
9169 *p2 = '\0';
9170 memprintf(err, "'%s' : ALPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
9171 return ERR_ALERT | ERR_FATAL;
9172 }
9173
9174 *p1 = p2 - (p1 + 1);
9175 p1 = p2;
9176
9177 if (!*p2)
9178 break;
9179
9180 *(p2++) = '\0';
9181 }
9182 return 0;
9183#else
Tim Duesterhus93128532019-11-23 23:45:10 +01009184 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[cur_arg]);
Willy Tarreauab861d32013-04-02 02:30:41 +02009185 return ERR_ALERT | ERR_FATAL;
9186#endif
9187}
9188
Emmanuel Hocdet98263292016-12-29 18:26:15 +01009189static int bind_parse_alpn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
9190{
9191 return ssl_bind_parse_alpn(args, cur_arg, px, &conf->ssl_conf, err);
9192}
9193
Willy Tarreau79eeafa2012-09-14 07:53:05 +02009194/* parse the "ssl" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02009195static 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 +02009196{
Willy Tarreau71a8c7c2016-12-21 22:04:54 +01009197 conf->xprt = &ssl_sock;
Willy Tarreau4348fad2012-09-20 16:48:07 +02009198 conf->is_ssl = 1;
Emeric Brun76d88952012-10-05 15:47:31 +02009199
Emmanuel Hocdet98263292016-12-29 18:26:15 +01009200 if (global_ssl.listen_default_ciphers && !conf->ssl_conf.ciphers)
9201 conf->ssl_conf.ciphers = strdup(global_ssl.listen_default_ciphers);
Emmanuel Hocdet839af572019-05-14 16:27:35 +02009202#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009203 if (global_ssl.listen_default_ciphersuites && !conf->ssl_conf.ciphersuites)
9204 conf->ssl_conf.ciphersuites = strdup(global_ssl.listen_default_ciphersuites);
9205#endif
Emmanuel Hocdet4608ed92017-01-20 13:06:27 +01009206 conf->ssl_options |= global_ssl.listen_default_ssloptions;
Emmanuel Hocdet43664762017-08-09 18:26:20 +02009207 conf->ssl_conf.ssl_methods.flags |= global_ssl.listen_default_sslmethods.flags;
9208 if (!conf->ssl_conf.ssl_methods.min)
9209 conf->ssl_conf.ssl_methods.min = global_ssl.listen_default_sslmethods.min;
9210 if (!conf->ssl_conf.ssl_methods.max)
9211 conf->ssl_conf.ssl_methods.max = global_ssl.listen_default_sslmethods.max;
Emeric Brun76d88952012-10-05 15:47:31 +02009212
Willy Tarreau79eeafa2012-09-14 07:53:05 +02009213 return 0;
9214}
9215
Lukas Tribus53ae85c2017-05-04 15:45:40 +00009216/* parse the "prefer-client-ciphers" bind keyword */
9217static int bind_parse_pcc(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
9218{
9219 conf->ssl_options |= BC_SSL_O_PREF_CLIE_CIPH;
9220 return 0;
9221}
9222
Christopher Faulet31af49d2015-06-09 17:29:50 +02009223/* parse the "generate-certificates" bind keyword */
9224static int bind_parse_generate_certs(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
9225{
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01009226#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Christopher Faulet31af49d2015-06-09 17:29:50 +02009227 conf->generate_certs = 1;
9228#else
9229 memprintf(err, "%sthis version of openssl cannot generate SSL certificates.\n",
9230 err && *err ? *err : "");
9231#endif
9232 return 0;
9233}
9234
Emmanuel Hocdet65623372013-01-24 17:17:15 +01009235/* parse the "strict-sni" bind keyword */
9236static int bind_parse_strict_sni(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
9237{
9238 conf->strict_sni = 1;
9239 return 0;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009240}
9241
9242/* parse the "tls-ticket-keys" bind keyword */
9243static int bind_parse_tls_ticket_keys(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
9244{
9245#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
Christopher Faulete566f3d2019-10-21 09:55:49 +02009246 FILE *f = NULL;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009247 int i = 0;
9248 char thisline[LINESIZE];
Christopher Faulete566f3d2019-10-21 09:55:49 +02009249 struct tls_keys_ref *keys_ref = NULL;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009250
9251 if (!*args[cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009252 memprintf(err, "'%s' : missing TLS ticket keys file path", args[cur_arg]);
Christopher Faulete566f3d2019-10-21 09:55:49 +02009253 goto fail;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009254 }
9255
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02009256 keys_ref = tlskeys_ref_lookup(args[cur_arg + 1]);
Willy Tarreau17b4aa12018-07-17 10:05:32 +02009257 if (keys_ref) {
9258 keys_ref->refcount++;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02009259 conf->keys_ref = keys_ref;
9260 return 0;
9261 }
9262
Christopher Faulete566f3d2019-10-21 09:55:49 +02009263 keys_ref = calloc(1, sizeof(*keys_ref));
Emeric Brun09852f72019-01-10 10:51:13 +01009264 if (!keys_ref) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009265 memprintf(err, "'%s' : allocation error", args[cur_arg+1]);
Christopher Faulete566f3d2019-10-21 09:55:49 +02009266 goto fail;
Emeric Brun09852f72019-01-10 10:51:13 +01009267 }
9268
Emeric Brun9e754772019-01-10 17:51:55 +01009269 keys_ref->tlskeys = malloc(TLS_TICKETS_NO * sizeof(union tls_sess_key));
Emeric Brun09852f72019-01-10 10:51:13 +01009270 if (!keys_ref->tlskeys) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009271 memprintf(err, "'%s' : allocation error", args[cur_arg+1]);
Christopher Faulete566f3d2019-10-21 09:55:49 +02009272 goto fail;
Emeric Brun09852f72019-01-10 10:51:13 +01009273 }
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009274
9275 if ((f = fopen(args[cur_arg + 1], "r")) == NULL) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009276 memprintf(err, "'%s' : unable to load ssl tickets keys file", args[cur_arg+1]);
Christopher Faulete566f3d2019-10-21 09:55:49 +02009277 goto fail;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009278 }
9279
Nenad Merdanovic146defa2015-05-09 08:46:00 +02009280 keys_ref->filename = strdup(args[cur_arg + 1]);
Emeric Brun09852f72019-01-10 10:51:13 +01009281 if (!keys_ref->filename) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009282 memprintf(err, "'%s' : allocation error", args[cur_arg+1]);
Christopher Faulete566f3d2019-10-21 09:55:49 +02009283 goto fail;
Emeric Brun09852f72019-01-10 10:51:13 +01009284 }
Nenad Merdanovic146defa2015-05-09 08:46:00 +02009285
Emeric Brun9e754772019-01-10 17:51:55 +01009286 keys_ref->key_size_bits = 0;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009287 while (fgets(thisline, sizeof(thisline), f) != NULL) {
9288 int len = strlen(thisline);
Emeric Brun9e754772019-01-10 17:51:55 +01009289 int dec_size;
9290
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009291 /* Strip newline characters from the end */
9292 if(thisline[len - 1] == '\n')
9293 thisline[--len] = 0;
9294
9295 if(thisline[len - 1] == '\r')
9296 thisline[--len] = 0;
9297
Emeric Brun9e754772019-01-10 17:51:55 +01009298 dec_size = base64dec(thisline, len, (char *) (keys_ref->tlskeys + i % TLS_TICKETS_NO), sizeof(union tls_sess_key));
9299 if (dec_size < 0) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009300 memprintf(err, "'%s' : unable to decode base64 key on line %d", args[cur_arg+1], i + 1);
Christopher Faulete566f3d2019-10-21 09:55:49 +02009301 goto fail;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009302 }
Emeric Brun9e754772019-01-10 17:51:55 +01009303 else if (!keys_ref->key_size_bits && (dec_size == sizeof(struct tls_sess_key_128))) {
9304 keys_ref->key_size_bits = 128;
9305 }
9306 else if (!keys_ref->key_size_bits && (dec_size == sizeof(struct tls_sess_key_256))) {
9307 keys_ref->key_size_bits = 256;
9308 }
9309 else if (((dec_size != sizeof(struct tls_sess_key_128)) && (dec_size != sizeof(struct tls_sess_key_256)))
9310 || ((dec_size == sizeof(struct tls_sess_key_128) && (keys_ref->key_size_bits != 128)))
9311 || ((dec_size == sizeof(struct tls_sess_key_256) && (keys_ref->key_size_bits != 256)))) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009312 memprintf(err, "'%s' : wrong sized key on line %d", args[cur_arg+1], i + 1);
Christopher Faulete566f3d2019-10-21 09:55:49 +02009313 goto fail;
Emeric Brun9e754772019-01-10 17:51:55 +01009314 }
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009315 i++;
9316 }
9317
9318 if (i < TLS_TICKETS_NO) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009319 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 +02009320 goto fail;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009321 }
9322
9323 fclose(f);
9324
9325 /* Use penultimate key for encryption, handle when TLS_TICKETS_NO = 1 */
Nenad Merdanovic17891152016-03-25 22:16:57 +01009326 i -= 2;
9327 keys_ref->tls_ticket_enc_index = i < 0 ? 0 : i % TLS_TICKETS_NO;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02009328 keys_ref->unique_id = -1;
Willy Tarreau17b4aa12018-07-17 10:05:32 +02009329 keys_ref->refcount = 1;
Christopher Faulet16f45c82018-02-16 11:23:49 +01009330 HA_RWLOCK_INIT(&keys_ref->lock);
Nenad Merdanovic146defa2015-05-09 08:46:00 +02009331 conf->keys_ref = keys_ref;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009332
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02009333 LIST_ADD(&tlskeys_reference, &keys_ref->list);
9334
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009335 return 0;
Christopher Faulete566f3d2019-10-21 09:55:49 +02009336
9337 fail:
9338 if (f)
9339 fclose(f);
9340 if (keys_ref) {
9341 free(keys_ref->filename);
9342 free(keys_ref->tlskeys);
9343 free(keys_ref);
9344 }
9345 return ERR_ALERT | ERR_FATAL;
9346
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009347#else
Tim Duesterhus93128532019-11-23 23:45:10 +01009348 memprintf(err, "'%s' : TLS ticket callback extension not supported", args[cur_arg]);
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009349 return ERR_ALERT | ERR_FATAL;
9350#endif /* SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB */
Emmanuel Hocdet65623372013-01-24 17:17:15 +01009351}
9352
Emeric Brund94b3fe2012-09-20 18:23:56 +02009353/* parse the "verify" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01009354static 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 +02009355{
9356 if (!*args[cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009357 memprintf(err, "'%s' : missing verify method", args[cur_arg]);
Emeric Brund94b3fe2012-09-20 18:23:56 +02009358 return ERR_ALERT | ERR_FATAL;
9359 }
9360
9361 if (strcmp(args[cur_arg + 1], "none") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01009362 conf->verify = SSL_SOCK_VERIFY_NONE;
Emeric Brund94b3fe2012-09-20 18:23:56 +02009363 else if (strcmp(args[cur_arg + 1], "optional") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01009364 conf->verify = SSL_SOCK_VERIFY_OPTIONAL;
Emeric Brund94b3fe2012-09-20 18:23:56 +02009365 else if (strcmp(args[cur_arg + 1], "required") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01009366 conf->verify = SSL_SOCK_VERIFY_REQUIRED;
Emeric Brund94b3fe2012-09-20 18:23:56 +02009367 else {
Tim Duesterhus93128532019-11-23 23:45:10 +01009368 memprintf(err, "'%s' : unknown verify method '%s', only 'none', 'optional', and 'required' are supported\n",
9369 args[cur_arg], args[cur_arg + 1]);
Emeric Brund94b3fe2012-09-20 18:23:56 +02009370 return ERR_ALERT | ERR_FATAL;
9371 }
9372
9373 return 0;
9374}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01009375static int bind_parse_verify(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
9376{
9377 return ssl_bind_parse_verify(args, cur_arg, px, &conf->ssl_conf, err);
9378}
Emeric Brund94b3fe2012-09-20 18:23:56 +02009379
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02009380/* parse the "no-ca-names" bind keyword */
9381static int ssl_bind_parse_no_ca_names(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
9382{
9383 conf->no_ca_names = 1;
9384 return 0;
9385}
9386static int bind_parse_no_ca_names(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
9387{
9388 return ssl_bind_parse_no_ca_names(args, cur_arg, px, &conf->ssl_conf, err);
9389}
9390
Willy Tarreau92faadf2012-10-10 23:04:25 +02009391/************** "server" keywords ****************/
9392
Olivier Houchardc7566002018-11-20 23:33:50 +01009393/* parse the "npn" bind keyword */
9394static int srv_parse_npn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9395{
9396#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
9397 char *p1, *p2;
9398
9399 if (!*args[*cur_arg + 1]) {
9400 memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[*cur_arg]);
9401 return ERR_ALERT | ERR_FATAL;
9402 }
9403
9404 free(newsrv->ssl_ctx.npn_str);
9405
9406 /* the NPN string is built as a suite of (<len> <name>)*,
9407 * so we reuse each comma to store the next <len> and need
9408 * one more for the end of the string.
9409 */
9410 newsrv->ssl_ctx.npn_len = strlen(args[*cur_arg + 1]) + 1;
9411 newsrv->ssl_ctx.npn_str = calloc(1, newsrv->ssl_ctx.npn_len + 1);
9412 memcpy(newsrv->ssl_ctx.npn_str + 1, args[*cur_arg + 1],
9413 newsrv->ssl_ctx.npn_len);
9414
9415 /* replace commas with the name length */
9416 p1 = newsrv->ssl_ctx.npn_str;
9417 p2 = p1 + 1;
9418 while (1) {
9419 p2 = memchr(p1 + 1, ',', newsrv->ssl_ctx.npn_str +
9420 newsrv->ssl_ctx.npn_len - (p1 + 1));
9421 if (!p2)
9422 p2 = p1 + 1 + strlen(p1 + 1);
9423
9424 if (p2 - (p1 + 1) > 255) {
9425 *p2 = '\0';
9426 memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[*cur_arg], p1 + 1);
9427 return ERR_ALERT | ERR_FATAL;
9428 }
9429
9430 *p1 = p2 - (p1 + 1);
9431 p1 = p2;
9432
9433 if (!*p2)
9434 break;
9435
9436 *(p2++) = '\0';
9437 }
9438 return 0;
9439#else
Tim Duesterhus93128532019-11-23 23:45:10 +01009440 memprintf(err, "'%s' : library does not support TLS NPN extension", args[*cur_arg]);
Olivier Houchardc7566002018-11-20 23:33:50 +01009441 return ERR_ALERT | ERR_FATAL;
9442#endif
9443}
9444
Olivier Houchard92150142018-12-21 19:47:01 +01009445/* parse the "alpn" or the "check-alpn" server keyword */
Olivier Houchardc7566002018-11-20 23:33:50 +01009446static int srv_parse_alpn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9447{
9448#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
9449 char *p1, *p2;
Olivier Houchard92150142018-12-21 19:47:01 +01009450 char **alpn_str;
9451 int *alpn_len;
Olivier Houchardc7566002018-11-20 23:33:50 +01009452
Olivier Houchard92150142018-12-21 19:47:01 +01009453 if (*args[*cur_arg] == 'c') {
9454 alpn_str = &newsrv->check.alpn_str;
9455 alpn_len = &newsrv->check.alpn_len;
9456 } else {
9457 alpn_str = &newsrv->ssl_ctx.alpn_str;
9458 alpn_len = &newsrv->ssl_ctx.alpn_len;
9459
9460 }
Olivier Houchardc7566002018-11-20 23:33:50 +01009461 if (!*args[*cur_arg + 1]) {
9462 memprintf(err, "'%s' : missing the comma-delimited ALPN protocol suite", args[*cur_arg]);
9463 return ERR_ALERT | ERR_FATAL;
9464 }
9465
Olivier Houchard92150142018-12-21 19:47:01 +01009466 free(*alpn_str);
Olivier Houchardc7566002018-11-20 23:33:50 +01009467
9468 /* the ALPN string is built as a suite of (<len> <name>)*,
9469 * so we reuse each comma to store the next <len> and need
9470 * one more for the end of the string.
9471 */
Olivier Houchard92150142018-12-21 19:47:01 +01009472 *alpn_len = strlen(args[*cur_arg + 1]) + 1;
9473 *alpn_str = calloc(1, *alpn_len + 1);
9474 memcpy(*alpn_str + 1, args[*cur_arg + 1], *alpn_len);
Olivier Houchardc7566002018-11-20 23:33:50 +01009475
9476 /* replace commas with the name length */
Olivier Houchard92150142018-12-21 19:47:01 +01009477 p1 = *alpn_str;
Olivier Houchardc7566002018-11-20 23:33:50 +01009478 p2 = p1 + 1;
9479 while (1) {
Olivier Houchard92150142018-12-21 19:47:01 +01009480 p2 = memchr(p1 + 1, ',', *alpn_str + *alpn_len - (p1 + 1));
Olivier Houchardc7566002018-11-20 23:33:50 +01009481 if (!p2)
9482 p2 = p1 + 1 + strlen(p1 + 1);
9483
9484 if (p2 - (p1 + 1) > 255) {
9485 *p2 = '\0';
9486 memprintf(err, "'%s' : ALPN protocol name too long : '%s'", args[*cur_arg], p1 + 1);
9487 return ERR_ALERT | ERR_FATAL;
9488 }
9489
9490 *p1 = p2 - (p1 + 1);
9491 p1 = p2;
9492
9493 if (!*p2)
9494 break;
9495
9496 *(p2++) = '\0';
9497 }
9498 return 0;
9499#else
Tim Duesterhus93128532019-11-23 23:45:10 +01009500 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[*cur_arg]);
Olivier Houchardc7566002018-11-20 23:33:50 +01009501 return ERR_ALERT | ERR_FATAL;
9502#endif
9503}
9504
Emeric Brunef42d922012-10-11 16:11:36 +02009505/* parse the "ca-file" server keyword */
9506static int srv_parse_ca_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9507{
9508 if (!*args[*cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009509 memprintf(err, "'%s' : missing CAfile path", args[*cur_arg]);
Emeric Brunef42d922012-10-11 16:11:36 +02009510 return ERR_ALERT | ERR_FATAL;
9511 }
9512
Willy Tarreauef934602016-12-22 23:12:01 +01009513 if ((*args[*cur_arg + 1] != '/') && global_ssl.ca_base)
9514 memprintf(&newsrv->ssl_ctx.ca_file, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02009515 else
9516 memprintf(&newsrv->ssl_ctx.ca_file, "%s", args[*cur_arg + 1]);
9517
Emmanuel Hocdetd4f9a602019-10-24 11:32:47 +02009518 if (!ssl_store_load_locations_file(newsrv->ssl_ctx.ca_file)) {
9519 memprintf(err, "'%s' : unable to load %s", args[*cur_arg], newsrv->ssl_ctx.ca_file);
9520 return ERR_ALERT | ERR_FATAL;
9521 }
Emeric Brunef42d922012-10-11 16:11:36 +02009522 return 0;
9523}
9524
Olivier Houchard9130a962017-10-17 17:33:43 +02009525/* parse the "check-sni" server keyword */
9526static int srv_parse_check_sni(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9527{
9528 if (!*args[*cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009529 memprintf(err, "'%s' : missing SNI", args[*cur_arg]);
Olivier Houchard9130a962017-10-17 17:33:43 +02009530 return ERR_ALERT | ERR_FATAL;
9531 }
9532
9533 newsrv->check.sni = strdup(args[*cur_arg + 1]);
9534 if (!newsrv->check.sni) {
9535 memprintf(err, "'%s' : failed to allocate memory", args[*cur_arg]);
9536 return ERR_ALERT | ERR_FATAL;
9537 }
9538 return 0;
9539
9540}
9541
Willy Tarreau92faadf2012-10-10 23:04:25 +02009542/* parse the "check-ssl" server keyword */
9543static int srv_parse_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9544{
9545 newsrv->check.use_ssl = 1;
Willy Tarreauef934602016-12-22 23:12:01 +01009546 if (global_ssl.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
9547 newsrv->ssl_ctx.ciphers = strdup(global_ssl.connect_default_ciphers);
Emmanuel Hocdet839af572019-05-14 16:27:35 +02009548#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009549 if (global_ssl.connect_default_ciphersuites && !newsrv->ssl_ctx.ciphersuites)
9550 newsrv->ssl_ctx.ciphersuites = strdup(global_ssl.connect_default_ciphersuites);
9551#endif
Willy Tarreauef934602016-12-22 23:12:01 +01009552 newsrv->ssl_ctx.options |= global_ssl.connect_default_ssloptions;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02009553 newsrv->ssl_ctx.methods.flags |= global_ssl.connect_default_sslmethods.flags;
9554 if (!newsrv->ssl_ctx.methods.min)
9555 newsrv->ssl_ctx.methods.min = global_ssl.connect_default_sslmethods.min;
9556 if (!newsrv->ssl_ctx.methods.max)
9557 newsrv->ssl_ctx.methods.max = global_ssl.connect_default_sslmethods.max;
9558
Willy Tarreau92faadf2012-10-10 23:04:25 +02009559 return 0;
9560}
9561
9562/* parse the "ciphers" server keyword */
9563static int srv_parse_ciphers(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.ciphers);
9571 newsrv->ssl_ctx.ciphers = strdup(args[*cur_arg + 1]);
9572 return 0;
9573}
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009574
Emmanuel Hocdet839af572019-05-14 16:27:35 +02009575#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009576/* parse the "ciphersuites" server keyword */
9577static int srv_parse_ciphersuites(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9578{
9579 if (!*args[*cur_arg + 1]) {
9580 memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
9581 return ERR_ALERT | ERR_FATAL;
9582 }
9583
9584 free(newsrv->ssl_ctx.ciphersuites);
9585 newsrv->ssl_ctx.ciphersuites = strdup(args[*cur_arg + 1]);
9586 return 0;
9587}
9588#endif
Willy Tarreau92faadf2012-10-10 23:04:25 +02009589
Emeric Brunef42d922012-10-11 16:11:36 +02009590/* parse the "crl-file" server keyword */
9591static int srv_parse_crl_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9592{
9593#ifndef X509_V_FLAG_CRL_CHECK
Tim Duesterhus93128532019-11-23 23:45:10 +01009594 memprintf(err, "'%s' : library does not support CRL verify", args[*cur_arg]);
Emeric Brunef42d922012-10-11 16:11:36 +02009595 return ERR_ALERT | ERR_FATAL;
9596#else
9597 if (!*args[*cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009598 memprintf(err, "'%s' : missing CRLfile path", args[*cur_arg]);
Emeric Brunef42d922012-10-11 16:11:36 +02009599 return ERR_ALERT | ERR_FATAL;
9600 }
9601
Willy Tarreauef934602016-12-22 23:12:01 +01009602 if ((*args[*cur_arg + 1] != '/') && global_ssl.ca_base)
9603 memprintf(&newsrv->ssl_ctx.crl_file, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02009604 else
9605 memprintf(&newsrv->ssl_ctx.crl_file, "%s", args[*cur_arg + 1]);
9606
Emmanuel Hocdetb270e812019-11-21 19:09:31 +01009607 if (!ssl_store_load_locations_file(newsrv->ssl_ctx.crl_file)) {
9608 memprintf(err, "'%s' : unable to load %s", args[*cur_arg], newsrv->ssl_ctx.crl_file);
9609 return ERR_ALERT | ERR_FATAL;
9610 }
Emeric Brunef42d922012-10-11 16:11:36 +02009611 return 0;
9612#endif
9613}
9614
Emeric Bruna7aa3092012-10-26 12:58:00 +02009615/* parse the "crt" server keyword */
9616static int srv_parse_crt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9617{
9618 if (!*args[*cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009619 memprintf(err, "'%s' : missing certificate file path", args[*cur_arg]);
Emeric Bruna7aa3092012-10-26 12:58:00 +02009620 return ERR_ALERT | ERR_FATAL;
9621 }
9622
Willy Tarreauef934602016-12-22 23:12:01 +01009623 if ((*args[*cur_arg + 1] != '/') && global_ssl.crt_base)
Christopher Fauletff3a41e2017-11-23 09:13:32 +01009624 memprintf(&newsrv->ssl_ctx.client_crt, "%s/%s", global_ssl.crt_base, args[*cur_arg + 1]);
Emeric Bruna7aa3092012-10-26 12:58:00 +02009625 else
9626 memprintf(&newsrv->ssl_ctx.client_crt, "%s", args[*cur_arg + 1]);
9627
9628 return 0;
9629}
Emeric Brunef42d922012-10-11 16:11:36 +02009630
Frédéric Lécaille340ae602017-03-13 10:38:04 +01009631/* parse the "no-check-ssl" server keyword */
9632static int srv_parse_no_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9633{
9634 newsrv->check.use_ssl = 0;
9635 free(newsrv->ssl_ctx.ciphers);
9636 newsrv->ssl_ctx.ciphers = NULL;
9637 newsrv->ssl_ctx.options &= ~global_ssl.connect_default_ssloptions;
9638 return 0;
9639}
9640
Frédéric Lécaillee892c4c2017-03-13 12:08:01 +01009641/* parse the "no-send-proxy-v2-ssl" server keyword */
9642static int srv_parse_no_send_proxy_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9643{
9644 newsrv->pp_opts &= ~SRV_PP_V2;
9645 newsrv->pp_opts &= ~SRV_PP_V2_SSL;
9646 return 0;
9647}
9648
9649/* parse the "no-send-proxy-v2-ssl-cn" server keyword */
9650static int srv_parse_no_send_proxy_cn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9651{
9652 newsrv->pp_opts &= ~SRV_PP_V2;
9653 newsrv->pp_opts &= ~SRV_PP_V2_SSL;
9654 newsrv->pp_opts &= ~SRV_PP_V2_SSL_CN;
9655 return 0;
9656}
9657
Frédéric Lécaillee381d762017-03-13 11:54:17 +01009658/* parse the "no-ssl" server keyword */
9659static int srv_parse_no_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9660{
9661 newsrv->use_ssl = 0;
9662 free(newsrv->ssl_ctx.ciphers);
9663 newsrv->ssl_ctx.ciphers = NULL;
9664 return 0;
9665}
9666
Olivier Houchard522eea72017-11-03 16:27:47 +01009667/* parse the "allow-0rtt" server keyword */
9668static int srv_parse_allow_0rtt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9669{
9670 newsrv->ssl_ctx.options |= SRV_SSL_O_EARLY_DATA;
9671 return 0;
9672}
9673
Willy Tarreau2a3fb1c2015-02-05 16:47:07 +01009674/* parse the "no-ssl-reuse" server keyword */
9675static int srv_parse_no_ssl_reuse(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9676{
9677 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_REUSE;
9678 return 0;
9679}
9680
Emeric Brunf9c5c472012-10-11 15:28:34 +02009681/* parse the "no-tls-tickets" server keyword */
9682static int srv_parse_no_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9683{
9684 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLS_TICKETS;
9685 return 0;
9686}
David Safb76832014-05-08 23:42:08 -04009687/* parse the "send-proxy-v2-ssl" server keyword */
9688static int srv_parse_send_proxy_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9689{
9690 newsrv->pp_opts |= SRV_PP_V2;
9691 newsrv->pp_opts |= SRV_PP_V2_SSL;
9692 return 0;
9693}
9694
9695/* parse the "send-proxy-v2-ssl-cn" server keyword */
9696static int srv_parse_send_proxy_cn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9697{
9698 newsrv->pp_opts |= SRV_PP_V2;
9699 newsrv->pp_opts |= SRV_PP_V2_SSL;
9700 newsrv->pp_opts |= SRV_PP_V2_SSL_CN;
9701 return 0;
9702}
Emeric Brunf9c5c472012-10-11 15:28:34 +02009703
Willy Tarreau732eac42015-07-09 11:40:25 +02009704/* parse the "sni" server keyword */
9705static int srv_parse_sni(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9706{
9707#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
9708 memprintf(err, "'%s' : the current SSL library doesn't support the SNI TLS extension", args[*cur_arg]);
9709 return ERR_ALERT | ERR_FATAL;
9710#else
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01009711 char *arg;
Willy Tarreau732eac42015-07-09 11:40:25 +02009712
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01009713 arg = args[*cur_arg + 1];
9714 if (!*arg) {
Willy Tarreau732eac42015-07-09 11:40:25 +02009715 memprintf(err, "'%s' : missing sni expression", args[*cur_arg]);
9716 return ERR_ALERT | ERR_FATAL;
9717 }
9718
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01009719 free(newsrv->sni_expr);
9720 newsrv->sni_expr = strdup(arg);
Willy Tarreau732eac42015-07-09 11:40:25 +02009721
Willy Tarreau732eac42015-07-09 11:40:25 +02009722 return 0;
9723#endif
9724}
9725
Willy Tarreau92faadf2012-10-10 23:04:25 +02009726/* parse the "ssl" server keyword */
9727static int srv_parse_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9728{
9729 newsrv->use_ssl = 1;
Willy Tarreauef934602016-12-22 23:12:01 +01009730 if (global_ssl.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
9731 newsrv->ssl_ctx.ciphers = strdup(global_ssl.connect_default_ciphers);
Emmanuel Hocdet839af572019-05-14 16:27:35 +02009732#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009733 if (global_ssl.connect_default_ciphersuites && !newsrv->ssl_ctx.ciphersuites)
9734 newsrv->ssl_ctx.ciphersuites = strdup(global_ssl.connect_default_ciphersuites);
9735#endif
Willy Tarreau92faadf2012-10-10 23:04:25 +02009736 return 0;
9737}
9738
Frédéric Lécaille2cfcdbe2017-03-13 11:32:20 +01009739/* parse the "ssl-reuse" server keyword */
9740static int srv_parse_ssl_reuse(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9741{
9742 newsrv->ssl_ctx.options &= ~SRV_SSL_O_NO_REUSE;
9743 return 0;
9744}
9745
Frédéric Lécaille2cfcdbe2017-03-13 11:32:20 +01009746/* parse the "tls-tickets" server keyword */
9747static int srv_parse_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9748{
9749 newsrv->ssl_ctx.options &= ~SRV_SSL_O_NO_TLS_TICKETS;
9750 return 0;
9751}
9752
Emeric Brunef42d922012-10-11 16:11:36 +02009753/* parse the "verify" server keyword */
9754static int srv_parse_verify(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9755{
9756 if (!*args[*cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009757 memprintf(err, "'%s' : missing verify method", args[*cur_arg]);
Emeric Brunef42d922012-10-11 16:11:36 +02009758 return ERR_ALERT | ERR_FATAL;
9759 }
9760
9761 if (strcmp(args[*cur_arg + 1], "none") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01009762 newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_NONE;
Emeric Brunef42d922012-10-11 16:11:36 +02009763 else if (strcmp(args[*cur_arg + 1], "required") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01009764 newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_REQUIRED;
Emeric Brunef42d922012-10-11 16:11:36 +02009765 else {
Tim Duesterhus93128532019-11-23 23:45:10 +01009766 memprintf(err, "'%s' : unknown verify method '%s', only 'none' and 'required' are supported\n",
9767 args[*cur_arg], args[*cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02009768 return ERR_ALERT | ERR_FATAL;
9769 }
9770
Evan Broderbe554312013-06-27 00:05:25 -07009771 return 0;
9772}
9773
9774/* parse the "verifyhost" server keyword */
9775static int srv_parse_verifyhost(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9776{
9777 if (!*args[*cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009778 memprintf(err, "'%s' : missing hostname to verify against", args[*cur_arg]);
Evan Broderbe554312013-06-27 00:05:25 -07009779 return ERR_ALERT | ERR_FATAL;
9780 }
9781
Frédéric Lécaille273f3212017-03-13 15:52:01 +01009782 free(newsrv->ssl_ctx.verify_host);
Evan Broderbe554312013-06-27 00:05:25 -07009783 newsrv->ssl_ctx.verify_host = strdup(args[*cur_arg + 1]);
9784
Emeric Brunef42d922012-10-11 16:11:36 +02009785 return 0;
9786}
9787
Emeric Brun2c86cbf2014-10-30 15:56:50 +01009788/* parse the "ssl-default-bind-options" keyword in global section */
9789static int ssl_parse_default_bind_options(char **args, int section_type, struct proxy *curpx,
9790 struct proxy *defpx, const char *file, int line,
9791 char **err) {
9792 int i = 1;
9793
9794 if (*(args[i]) == 0) {
9795 memprintf(err, "global statement '%s' expects an option as an argument.", args[0]);
9796 return -1;
9797 }
9798 while (*(args[i])) {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02009799 if (!strcmp(args[i], "no-tls-tickets"))
Willy Tarreauef934602016-12-22 23:12:01 +01009800 global_ssl.listen_default_ssloptions |= BC_SSL_O_NO_TLS_TICKETS;
Lukas Tribus53ae85c2017-05-04 15:45:40 +00009801 else if (!strcmp(args[i], "prefer-client-ciphers"))
9802 global_ssl.listen_default_ssloptions |= BC_SSL_O_PREF_CLIE_CIPH;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02009803 else if (!strcmp(args[i], "ssl-min-ver") || !strcmp(args[i], "ssl-max-ver")) {
9804 if (!parse_tls_method_minmax(args, i, &global_ssl.listen_default_sslmethods, err))
9805 i++;
9806 else {
9807 memprintf(err, "%s on global statement '%s'.", *err, args[0]);
9808 return -1;
9809 }
9810 }
9811 else if (parse_tls_method_options(args[i], &global_ssl.listen_default_sslmethods, err)) {
Emeric Brun2c86cbf2014-10-30 15:56:50 +01009812 memprintf(err, "unknown option '%s' on global statement '%s'.", args[i], args[0]);
9813 return -1;
9814 }
9815 i++;
9816 }
9817 return 0;
9818}
9819
9820/* parse the "ssl-default-server-options" keyword in global section */
9821static int ssl_parse_default_server_options(char **args, int section_type, struct proxy *curpx,
9822 struct proxy *defpx, const char *file, int line,
9823 char **err) {
9824 int i = 1;
9825
9826 if (*(args[i]) == 0) {
9827 memprintf(err, "global statement '%s' expects an option as an argument.", args[0]);
9828 return -1;
9829 }
9830 while (*(args[i])) {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02009831 if (!strcmp(args[i], "no-tls-tickets"))
Willy Tarreauef934602016-12-22 23:12:01 +01009832 global_ssl.connect_default_ssloptions |= SRV_SSL_O_NO_TLS_TICKETS;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02009833 else if (!strcmp(args[i], "ssl-min-ver") || !strcmp(args[i], "ssl-max-ver")) {
9834 if (!parse_tls_method_minmax(args, i, &global_ssl.connect_default_sslmethods, err))
9835 i++;
9836 else {
9837 memprintf(err, "%s on global statement '%s'.", *err, args[0]);
9838 return -1;
9839 }
9840 }
9841 else if (parse_tls_method_options(args[i], &global_ssl.connect_default_sslmethods, err)) {
Emeric Brun2c86cbf2014-10-30 15:56:50 +01009842 memprintf(err, "unknown option '%s' on global statement '%s'.", args[i], args[0]);
9843 return -1;
9844 }
9845 i++;
9846 }
9847 return 0;
9848}
9849
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01009850/* parse the "ca-base" / "crt-base" keywords in global section.
9851 * Returns <0 on alert, >0 on warning, 0 on success.
9852 */
9853static int ssl_parse_global_ca_crt_base(char **args, int section_type, struct proxy *curpx,
9854 struct proxy *defpx, const char *file, int line,
9855 char **err)
9856{
9857 char **target;
9858
Willy Tarreauef934602016-12-22 23:12:01 +01009859 target = (args[0][1] == 'a') ? &global_ssl.ca_base : &global_ssl.crt_base;
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01009860
9861 if (too_many_args(1, args, err, NULL))
9862 return -1;
9863
9864 if (*target) {
9865 memprintf(err, "'%s' already specified.", args[0]);
9866 return -1;
9867 }
9868
9869 if (*(args[1]) == 0) {
9870 memprintf(err, "global statement '%s' expects a directory path as an argument.", args[0]);
9871 return -1;
9872 }
9873 *target = strdup(args[1]);
9874 return 0;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00009875}
9876
Emmanuel Hocdet70df7bf2019-01-04 11:08:20 +01009877/* "issuers-chain-path" load chain certificate in global */
9878static int ssl_load_global_issuer_from_BIO(BIO *in, char *fp, char **err)
9879{
9880 X509 *ca;
9881 X509_NAME *name = NULL;
9882 ASN1_OCTET_STRING *skid = NULL;
9883 STACK_OF(X509) *chain = NULL;
9884 struct issuer_chain *issuer;
9885 struct eb64_node *node;
9886 char *path;
9887 u64 key;
9888 int ret = 0;
9889
9890 while ((ca = PEM_read_bio_X509(in, NULL, NULL, NULL))) {
9891 if (chain == NULL) {
9892 chain = sk_X509_new_null();
9893 skid = X509_get_ext_d2i(ca, NID_subject_key_identifier, NULL, NULL);
9894 name = X509_get_subject_name(ca);
9895 }
9896 if (!sk_X509_push(chain, ca)) {
9897 X509_free(ca);
9898 goto end;
9899 }
9900 }
9901 if (!chain) {
9902 memprintf(err, "unable to load issuers-chain %s : pem certificate not found.\n", fp);
9903 goto end;
9904 }
9905 if (!skid) {
9906 memprintf(err, "unable to load issuers-chain %s : SubjectKeyIdentifier not found.\n", fp);
9907 goto end;
9908 }
9909 if (!name) {
9910 memprintf(err, "unable to load issuers-chain %s : SubjectName not found.\n", fp);
9911 goto end;
9912 }
9913 key = XXH64(ASN1_STRING_get0_data(skid), ASN1_STRING_length(skid), 0);
William Lallemande0f3fd52020-02-25 14:53:06 +01009914 for (node = eb64_lookup(&cert_issuer_tree, key); node; node = eb64_next(node)) {
Emmanuel Hocdet70df7bf2019-01-04 11:08:20 +01009915 issuer = container_of(node, typeof(*issuer), node);
9916 if (!X509_NAME_cmp(name, X509_get_subject_name(sk_X509_value(issuer->chain, 0)))) {
9917 memprintf(err, "duplicate issuers-chain %s: %s already in store\n", fp, issuer->path);
9918 goto end;
9919 }
9920 }
9921 issuer = calloc(1, sizeof *issuer);
9922 path = strdup(fp);
9923 if (!issuer || !path) {
9924 free(issuer);
9925 free(path);
9926 goto end;
9927 }
9928 issuer->node.key = key;
9929 issuer->path = path;
9930 issuer->chain = chain;
9931 chain = NULL;
William Lallemande0f3fd52020-02-25 14:53:06 +01009932 eb64_insert(&cert_issuer_tree, &issuer->node);
Emmanuel Hocdet70df7bf2019-01-04 11:08:20 +01009933 ret = 1;
9934 end:
9935 if (skid)
9936 ASN1_OCTET_STRING_free(skid);
9937 if (chain)
9938 sk_X509_pop_free(chain, X509_free);
9939 return ret;
9940}
9941
Emmanuel Hocdet75a7aa12020-02-18 15:19:24 +01009942static struct issuer_chain* ssl_get_issuer_chain(X509 *cert)
9943{
9944 AUTHORITY_KEYID *akid;
9945 struct issuer_chain *issuer = NULL;
9946
9947 akid = X509_get_ext_d2i(cert, NID_authority_key_identifier, NULL, NULL);
9948 if (akid) {
9949 struct eb64_node *node;
9950 u64 hk;
9951 hk = XXH64(ASN1_STRING_get0_data(akid->keyid), ASN1_STRING_length(akid->keyid), 0);
9952 for (node = eb64_lookup(&cert_issuer_tree, hk); node; node = eb64_next(node)) {
9953 struct issuer_chain *ti = container_of(node, typeof(*issuer), node);
9954 if (X509_check_issued(sk_X509_value(ti->chain, 0), cert) == X509_V_OK) {
9955 issuer = ti;
9956 break;
9957 }
9958 }
9959 AUTHORITY_KEYID_free(akid);
9960 }
9961 return issuer;
9962}
9963
Emmanuel Hocdet70df7bf2019-01-04 11:08:20 +01009964static void ssl_free_global_issuers(void)
9965{
9966 struct eb64_node *node, *back;
9967 struct issuer_chain *issuer;
9968
William Lallemande0f3fd52020-02-25 14:53:06 +01009969 node = eb64_first(&cert_issuer_tree);
Emmanuel Hocdet70df7bf2019-01-04 11:08:20 +01009970 while (node) {
9971 issuer = container_of(node, typeof(*issuer), node);
9972 back = eb64_next(node);
9973 eb64_delete(node);
9974 free(issuer->path);
9975 sk_X509_pop_free(issuer->chain, X509_free);
9976 free(issuer);
9977 node = back;
9978 }
9979}
9980
9981static int ssl_load_global_issuers_from_path(char **args, int section_type, struct proxy *curpx,
9982 struct proxy *defpx, const char *file, int line,
9983 char **err)
9984{
9985 char *path;
9986 struct dirent **de_list;
9987 int i, n;
9988 struct stat buf;
9989 char *end;
9990 char fp[MAXPATHLEN+1];
9991
9992 if (too_many_args(1, args, err, NULL))
9993 return -1;
9994
9995 path = args[1];
9996 if (*path == 0 || stat(path, &buf)) {
9997 memprintf(err, "%sglobal statement '%s' expects a directory path as an argument.\n",
9998 err && *err ? *err : "", args[0]);
9999 return -1;
10000 }
10001 if (S_ISDIR(buf.st_mode) == 0) {
10002 memprintf(err, "%sglobal statement '%s': %s is not a directory.\n",
10003 err && *err ? *err : "", args[0], path);
10004 return -1;
10005 }
10006
10007 /* strip trailing slashes, including first one */
10008 for (end = path + strlen(path) - 1; end >= path && *end == '/'; end--)
10009 *end = 0;
10010 /* path already parsed? */
10011 if (global_ssl.issuers_chain_path && strcmp(global_ssl.issuers_chain_path, path) == 0)
10012 return 0;
10013 /* overwrite old issuers_chain_path */
10014 free(global_ssl.issuers_chain_path);
10015 global_ssl.issuers_chain_path = strdup(path);
10016 ssl_free_global_issuers();
10017
10018 n = scandir(path, &de_list, 0, alphasort);
10019 if (n < 0) {
10020 memprintf(err, "%sglobal statement '%s': unable to scan directory '%s' : %s.\n",
10021 err && *err ? *err : "", args[0], path, strerror(errno));
10022 return -1;
10023 }
10024 for (i = 0; i < n; i++) {
10025 struct dirent *de = de_list[i];
10026 BIO *in = NULL;
10027 char *warn = NULL;
10028
10029 snprintf(fp, sizeof(fp), "%s/%s", path, de->d_name);
10030 free(de);
10031 if (stat(fp, &buf) != 0) {
10032 ha_warning("unable to stat certificate from file '%s' : %s.\n", fp, strerror(errno));
10033 goto next;
10034 }
10035 if (!S_ISREG(buf.st_mode))
10036 goto next;
10037
10038 in = BIO_new(BIO_s_file());
10039 if (in == NULL)
10040 goto next;
10041 if (BIO_read_filename(in, fp) <= 0)
10042 goto next;
10043 ssl_load_global_issuer_from_BIO(in, fp, &warn);
10044 if (warn) {
Tim Duesterhuse8aa5f22020-02-19 11:41:13 +010010045 ha_warning("%s", warn);
Emmanuel Hocdet70df7bf2019-01-04 11:08:20 +010010046 free(warn);
10047 warn = NULL;
10048 }
10049 next:
10050 if (in)
10051 BIO_free(in);
10052 }
10053 free(de_list);
10054
10055 return 0;
10056}
10057
Grant Zhangfa6c7ee2017-01-14 01:42:15 +000010058/* parse the "ssl-mode-async" keyword in global section.
10059 * Returns <0 on alert, >0 on warning, 0 on success.
10060 */
10061static int ssl_parse_global_ssl_async(char **args, int section_type, struct proxy *curpx,
10062 struct proxy *defpx, const char *file, int line,
10063 char **err)
10064{
Willy Tarreau5db847a2019-05-09 14:13:35 +020010065#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +000010066 global_ssl.async = 1;
Emeric Brunece0c332017-12-06 13:51:49 +010010067 global.ssl_used_async_engines = nb_engines;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +000010068 return 0;
10069#else
10070 memprintf(err, "'%s': openssl library does not support async mode", args[0]);
10071 return -1;
10072#endif
10073}
10074
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020010075#ifndef OPENSSL_NO_ENGINE
Grant Zhangfa6c7ee2017-01-14 01:42:15 +000010076static int ssl_check_async_engine_count(void) {
10077 int err_code = 0;
10078
Emeric Brun3854e012017-05-17 20:42:48 +020010079 if (global_ssl.async && (openssl_engines_initialized > 32)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +010010080 ha_alert("ssl-mode-async only supports a maximum of 32 engines.\n");
Grant Zhangfa6c7ee2017-01-14 01:42:15 +000010081 err_code = ERR_ABORT;
10082 }
10083 return err_code;
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +010010084}
10085
Grant Zhang872f9c22017-01-21 01:10:18 +000010086/* parse the "ssl-engine" keyword in global section.
10087 * Returns <0 on alert, >0 on warning, 0 on success.
10088 */
10089static int ssl_parse_global_ssl_engine(char **args, int section_type, struct proxy *curpx,
10090 struct proxy *defpx, const char *file, int line,
10091 char **err)
10092{
10093 char *algo;
10094 int ret = -1;
10095
10096 if (*(args[1]) == 0) {
10097 memprintf(err, "global statement '%s' expects a valid engine name as an argument.", args[0]);
10098 return ret;
10099 }
10100
10101 if (*(args[2]) == 0) {
10102 /* if no list of algorithms is given, it defaults to ALL */
10103 algo = strdup("ALL");
10104 goto add_engine;
10105 }
10106
10107 /* otherwise the expected format is ssl-engine <engine_name> algo <list of algo> */
10108 if (strcmp(args[2], "algo") != 0) {
10109 memprintf(err, "global statement '%s' expects to have algo keyword.", args[0]);
10110 return ret;
10111 }
10112
10113 if (*(args[3]) == 0) {
10114 memprintf(err, "global statement '%s' expects algorithm names as an argument.", args[0]);
10115 return ret;
10116 }
10117 algo = strdup(args[3]);
10118
10119add_engine:
10120 if (ssl_init_single_engine(args[1], algo)==0) {
10121 openssl_engines_initialized++;
10122 ret = 0;
10123 }
10124 free(algo);
10125 return ret;
10126}
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020010127#endif
Grant Zhang872f9c22017-01-21 01:10:18 +000010128
Willy Tarreauf22e9682016-12-21 23:23:19 +010010129/* parse the "ssl-default-bind-ciphers" / "ssl-default-server-ciphers" keywords
10130 * in global section. Returns <0 on alert, >0 on warning, 0 on success.
10131 */
10132static int ssl_parse_global_ciphers(char **args, int section_type, struct proxy *curpx,
10133 struct proxy *defpx, const char *file, int line,
10134 char **err)
10135{
10136 char **target;
10137
Willy Tarreauef934602016-12-22 23:12:01 +010010138 target = (args[0][12] == 'b') ? &global_ssl.listen_default_ciphers : &global_ssl.connect_default_ciphers;
Willy Tarreauf22e9682016-12-21 23:23:19 +010010139
10140 if (too_many_args(1, args, err, NULL))
10141 return -1;
10142
10143 if (*(args[1]) == 0) {
10144 memprintf(err, "global statement '%s' expects a cipher suite as an argument.", args[0]);
10145 return -1;
10146 }
10147
10148 free(*target);
10149 *target = strdup(args[1]);
10150 return 0;
10151}
Dirkjan Bussink415150f2018-09-14 11:14:21 +020010152
Emmanuel Hocdet839af572019-05-14 16:27:35 +020010153#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +020010154/* parse the "ssl-default-bind-ciphersuites" / "ssl-default-server-ciphersuites" keywords
10155 * in global section. Returns <0 on alert, >0 on warning, 0 on success.
10156 */
10157static int ssl_parse_global_ciphersuites(char **args, int section_type, struct proxy *curpx,
10158 struct proxy *defpx, const char *file, int line,
10159 char **err)
10160{
10161 char **target;
10162
10163 target = (args[0][12] == 'b') ? &global_ssl.listen_default_ciphersuites : &global_ssl.connect_default_ciphersuites;
10164
10165 if (too_many_args(1, args, err, NULL))
10166 return -1;
10167
10168 if (*(args[1]) == 0) {
10169 memprintf(err, "global statement '%s' expects a cipher suite as an argument.", args[0]);
10170 return -1;
10171 }
10172
10173 free(*target);
10174 *target = strdup(args[1]);
10175 return 0;
10176}
10177#endif
Willy Tarreauf22e9682016-12-21 23:23:19 +010010178
Willy Tarreau9ceda382016-12-21 23:13:03 +010010179/* parse various global tune.ssl settings consisting in positive integers.
10180 * Returns <0 on alert, >0 on warning, 0 on success.
10181 */
10182static int ssl_parse_global_int(char **args, int section_type, struct proxy *curpx,
10183 struct proxy *defpx, const char *file, int line,
10184 char **err)
10185{
10186 int *target;
10187
10188 if (strcmp(args[0], "tune.ssl.cachesize") == 0)
10189 target = &global.tune.sslcachesize;
10190 else if (strcmp(args[0], "tune.ssl.maxrecord") == 0)
Willy Tarreauef934602016-12-22 23:12:01 +010010191 target = (int *)&global_ssl.max_record;
Willy Tarreau9ceda382016-12-21 23:13:03 +010010192 else if (strcmp(args[0], "tune.ssl.ssl-ctx-cache-size") == 0)
Willy Tarreauef934602016-12-22 23:12:01 +010010193 target = &global_ssl.ctx_cache;
Willy Tarreau0bea58d2016-12-21 23:17:25 +010010194 else if (strcmp(args[0], "maxsslconn") == 0)
10195 target = &global.maxsslconn;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +010010196 else if (strcmp(args[0], "tune.ssl.capture-cipherlist-size") == 0)
10197 target = &global_ssl.capture_cipherlist;
Willy Tarreau9ceda382016-12-21 23:13:03 +010010198 else {
10199 memprintf(err, "'%s' keyword not unhandled (please report this bug).", args[0]);
10200 return -1;
10201 }
10202
10203 if (too_many_args(1, args, err, NULL))
10204 return -1;
10205
10206 if (*(args[1]) == 0) {
10207 memprintf(err, "'%s' expects an integer argument.", args[0]);
10208 return -1;
10209 }
10210
10211 *target = atoi(args[1]);
10212 if (*target < 0) {
10213 memprintf(err, "'%s' expects a positive numeric value.", args[0]);
10214 return -1;
10215 }
10216 return 0;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +010010217}
10218
10219static int ssl_parse_global_capture_cipherlist(char **args, int section_type, struct proxy *curpx,
10220 struct proxy *defpx, const char *file, int line,
10221 char **err)
10222{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +010010223 int ret;
10224
10225 ret = ssl_parse_global_int(args, section_type, curpx, defpx, file, line, err);
10226 if (ret != 0)
10227 return ret;
10228
Willy Tarreaubafbe012017-11-24 17:34:44 +010010229 if (pool_head_ssl_capture) {
Thierry FOURNIER5bf77322017-02-25 12:45:22 +010010230 memprintf(err, "'%s' is already configured.", args[0]);
10231 return -1;
10232 }
10233
Willy Tarreaubafbe012017-11-24 17:34:44 +010010234 pool_head_ssl_capture = create_pool("ssl-capture", sizeof(struct ssl_capture) + global_ssl.capture_cipherlist, MEM_F_SHARED);
10235 if (!pool_head_ssl_capture) {
Thierry FOURNIER5bf77322017-02-25 12:45:22 +010010236 memprintf(err, "Out of memory error.");
10237 return -1;
10238 }
10239 return 0;
Willy Tarreau9ceda382016-12-21 23:13:03 +010010240}
10241
10242/* parse "ssl.force-private-cache".
10243 * Returns <0 on alert, >0 on warning, 0 on success.
10244 */
10245static int ssl_parse_global_private_cache(char **args, int section_type, struct proxy *curpx,
10246 struct proxy *defpx, const char *file, int line,
10247 char **err)
10248{
10249 if (too_many_args(0, args, err, NULL))
10250 return -1;
10251
Willy Tarreauef934602016-12-22 23:12:01 +010010252 global_ssl.private_cache = 1;
Willy Tarreau9ceda382016-12-21 23:13:03 +010010253 return 0;
10254}
10255
10256/* parse "ssl.lifetime".
10257 * Returns <0 on alert, >0 on warning, 0 on success.
10258 */
10259static int ssl_parse_global_lifetime(char **args, int section_type, struct proxy *curpx,
10260 struct proxy *defpx, const char *file, int line,
10261 char **err)
10262{
10263 const char *res;
10264
10265 if (too_many_args(1, args, err, NULL))
10266 return -1;
10267
10268 if (*(args[1]) == 0) {
10269 memprintf(err, "'%s' expects ssl sessions <lifetime> in seconds as argument.", args[0]);
10270 return -1;
10271 }
10272
Willy Tarreauef934602016-12-22 23:12:01 +010010273 res = parse_time_err(args[1], &global_ssl.life_time, TIME_UNIT_S);
Willy Tarreau9faebe32019-06-07 19:00:37 +020010274 if (res == PARSE_TIME_OVER) {
10275 memprintf(err, "timer overflow in argument '%s' to <%s> (maximum value is 2147483647 s or ~68 years).",
10276 args[1], args[0]);
10277 return -1;
10278 }
10279 else if (res == PARSE_TIME_UNDER) {
10280 memprintf(err, "timer underflow in argument '%s' to <%s> (minimum non-null value is 1 s).",
10281 args[1], args[0]);
10282 return -1;
10283 }
10284 else if (res) {
Willy Tarreau9ceda382016-12-21 23:13:03 +010010285 memprintf(err, "unexpected character '%c' in argument to <%s>.", *res, args[0]);
10286 return -1;
10287 }
10288 return 0;
10289}
10290
10291#ifndef OPENSSL_NO_DH
Willy Tarreau14e36a12016-12-21 23:28:13 +010010292/* parse "ssl-dh-param-file".
10293 * Returns <0 on alert, >0 on warning, 0 on success.
10294 */
10295static int ssl_parse_global_dh_param_file(char **args, int section_type, struct proxy *curpx,
10296 struct proxy *defpx, const char *file, int line,
10297 char **err)
10298{
10299 if (too_many_args(1, args, err, NULL))
10300 return -1;
10301
10302 if (*(args[1]) == 0) {
10303 memprintf(err, "'%s' expects a file path as an argument.", args[0]);
10304 return -1;
10305 }
10306
10307 if (ssl_sock_load_global_dh_param_from_file(args[1])) {
10308 memprintf(err, "'%s': unable to load DH parameters from file <%s>.", args[0], args[1]);
10309 return -1;
10310 }
10311 return 0;
10312}
10313
Willy Tarreau9ceda382016-12-21 23:13:03 +010010314/* parse "ssl.default-dh-param".
10315 * Returns <0 on alert, >0 on warning, 0 on success.
10316 */
10317static int ssl_parse_global_default_dh(char **args, int section_type, struct proxy *curpx,
10318 struct proxy *defpx, const char *file, int line,
10319 char **err)
10320{
10321 if (too_many_args(1, args, err, NULL))
10322 return -1;
10323
10324 if (*(args[1]) == 0) {
10325 memprintf(err, "'%s' expects an integer argument.", args[0]);
10326 return -1;
10327 }
10328
Willy Tarreauef934602016-12-22 23:12:01 +010010329 global_ssl.default_dh_param = atoi(args[1]);
10330 if (global_ssl.default_dh_param < 1024) {
Willy Tarreau9ceda382016-12-21 23:13:03 +010010331 memprintf(err, "'%s' expects a value >= 1024.", args[0]);
10332 return -1;
10333 }
10334 return 0;
10335}
10336#endif
10337
William Lallemand3af48e72020-02-03 17:15:52 +010010338
10339/*
10340 * parse "ssl-load-extra-files".
10341 * multiple arguments are allowed: "bundle", "sctl", "ocsp", "issuer", "all", "none"
10342 */
10343static int ssl_parse_global_extra_files(char **args, int section_type, struct proxy *curpx,
10344 struct proxy *defpx, const char *file, int line,
10345 char **err)
10346{
10347 int i;
10348 int gf = SSL_GF_NONE;
10349
10350 if (*(args[1]) == 0)
10351 goto err_arg;
10352
10353 for (i = 1; *args[i]; i++) {
10354
10355 if (!strcmp("bundle", args[i])) {
10356 gf |= SSL_GF_BUNDLE;
10357
10358 } else if (!strcmp("sctl", args[i])) {
10359 gf |= SSL_GF_SCTL;
10360
10361 } else if (!strcmp("ocsp", args[i])){
10362 gf |= SSL_GF_OCSP;
10363
10364 } else if (!strcmp("issuer", args[i])){
10365 gf |= SSL_GF_OCSP_ISSUER;
10366
William Lallemand4c5adbf2020-02-24 14:23:22 +010010367 } else if (!strcmp("key", args[i])) {
10368 gf |= SSL_GF_KEY;
10369
William Lallemand3af48e72020-02-03 17:15:52 +010010370 } else if (!strcmp("none", args[i])) {
10371 if (gf != SSL_GF_NONE)
10372 goto err_alone;
10373 gf = SSL_GF_NONE;
10374 i++;
10375 break;
10376
10377 } else if (!strcmp("all", args[i])) {
10378 if (gf != SSL_GF_NONE)
10379 goto err_alone;
10380 gf = SSL_GF_ALL;
10381 i++;
10382 break;
10383 } else {
10384 goto err_arg;
10385 }
10386 }
10387 /* break from loop but there are still arguments */
10388 if (*args[i])
10389 goto err_alone;
10390
10391 global_ssl.extra_files = gf;
10392
10393 return 0;
10394
10395err_alone:
10396 memprintf(err, "'%s' 'none' and 'all' can be only used alone", args[0]);
10397 return -1;
10398
10399err_arg:
10400 memprintf(err, "'%s' expects one or multiple arguments (none, all, bundle, sctl, ocsp, issuer).", args[0]);
10401 return -1;
10402}
10403
Willy Tarreau9ceda382016-12-21 23:13:03 +010010404
William Lallemand32af2032016-10-29 18:09:35 +020010405/* This function is used with TLS ticket keys management. It permits to browse
10406 * each reference. The variable <getnext> must contain the current node,
10407 * <end> point to the root node.
10408 */
10409#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
10410static inline
10411struct tls_keys_ref *tlskeys_list_get_next(struct tls_keys_ref *getnext, struct list *end)
10412{
10413 struct tls_keys_ref *ref = getnext;
10414
10415 while (1) {
10416
10417 /* Get next list entry. */
10418 ref = LIST_NEXT(&ref->list, struct tls_keys_ref *, list);
10419
10420 /* If the entry is the last of the list, return NULL. */
10421 if (&ref->list == end)
10422 return NULL;
10423
10424 return ref;
10425 }
10426}
10427
10428static inline
10429struct tls_keys_ref *tlskeys_ref_lookup_ref(const char *reference)
10430{
10431 int id;
10432 char *error;
10433
10434 /* If the reference starts by a '#', this is numeric id. */
10435 if (reference[0] == '#') {
10436 /* Try to convert the numeric id. If the conversion fails, the lookup fails. */
10437 id = strtol(reference + 1, &error, 10);
10438 if (*error != '\0')
10439 return NULL;
10440
10441 /* Perform the unique id lookup. */
10442 return tlskeys_ref_lookupid(id);
10443 }
10444
10445 /* Perform the string lookup. */
10446 return tlskeys_ref_lookup(reference);
10447}
10448#endif
10449
10450
10451#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
10452
10453static int cli_io_handler_tlskeys_files(struct appctx *appctx);
10454
10455static inline int cli_io_handler_tlskeys_entries(struct appctx *appctx) {
10456 return cli_io_handler_tlskeys_files(appctx);
10457}
10458
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010459/* dumps all tls keys. Relies on cli.i0 (non-null = only list file names), cli.i1
10460 * (next index to be dumped), and cli.p0 (next key reference).
10461 */
William Lallemand32af2032016-10-29 18:09:35 +020010462static int cli_io_handler_tlskeys_files(struct appctx *appctx) {
10463
10464 struct stream_interface *si = appctx->owner;
10465
10466 switch (appctx->st2) {
10467 case STAT_ST_INIT:
10468 /* Display the column headers. If the message cannot be sent,
Joseph Herlant017b3da2018-11-15 09:07:59 -080010469 * quit the function with returning 0. The function is called
William Lallemand32af2032016-10-29 18:09:35 +020010470 * later and restart at the state "STAT_ST_INIT".
10471 */
10472 chunk_reset(&trash);
10473
10474 if (appctx->io_handler == cli_io_handler_tlskeys_entries)
10475 chunk_appendf(&trash, "# id secret\n");
10476 else
10477 chunk_appendf(&trash, "# id (file)\n");
10478
Willy Tarreau06d80a92017-10-19 14:32:15 +020010479 if (ci_putchk(si_ic(si), &trash) == -1) {
Willy Tarreaudb398432018-11-15 11:08:52 +010010480 si_rx_room_blk(si);
William Lallemand32af2032016-10-29 18:09:35 +020010481 return 0;
10482 }
10483
William Lallemand32af2032016-10-29 18:09:35 +020010484 /* Now, we start the browsing of the references lists.
10485 * Note that the following call to LIST_ELEM return bad pointer. The only
10486 * available field of this pointer is <list>. It is used with the function
10487 * tlskeys_list_get_next() for retruning the first available entry
10488 */
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010489 if (appctx->ctx.cli.p0 == NULL) {
10490 appctx->ctx.cli.p0 = LIST_ELEM(&tlskeys_reference, struct tls_keys_ref *, list);
10491 appctx->ctx.cli.p0 = tlskeys_list_get_next(appctx->ctx.cli.p0, &tlskeys_reference);
William Lallemand32af2032016-10-29 18:09:35 +020010492 }
10493
10494 appctx->st2 = STAT_ST_LIST;
10495 /* fall through */
10496
10497 case STAT_ST_LIST:
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010498 while (appctx->ctx.cli.p0) {
10499 struct tls_keys_ref *ref = appctx->ctx.cli.p0;
William Lallemand32af2032016-10-29 18:09:35 +020010500
10501 chunk_reset(&trash);
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010502 if (appctx->io_handler == cli_io_handler_tlskeys_entries && appctx->ctx.cli.i1 == 0)
William Lallemand32af2032016-10-29 18:09:35 +020010503 chunk_appendf(&trash, "# ");
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010504
10505 if (appctx->ctx.cli.i1 == 0)
10506 chunk_appendf(&trash, "%d (%s)\n", ref->unique_id, ref->filename);
10507
William Lallemand32af2032016-10-29 18:09:35 +020010508 if (appctx->io_handler == cli_io_handler_tlskeys_entries) {
Christopher Faulet16f45c82018-02-16 11:23:49 +010010509 int head;
10510
10511 HA_RWLOCK_RDLOCK(TLSKEYS_REF_LOCK, &ref->lock);
10512 head = ref->tls_ticket_enc_index;
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010513 while (appctx->ctx.cli.i1 < TLS_TICKETS_NO) {
Willy Tarreau83061a82018-07-13 11:56:34 +020010514 struct buffer *t2 = get_trash_chunk();
William Lallemand32af2032016-10-29 18:09:35 +020010515
10516 chunk_reset(t2);
10517 /* should never fail here because we dump only a key in the t2 buffer */
Emeric Brun9e754772019-01-10 17:51:55 +010010518 if (ref->key_size_bits == 128) {
10519 t2->data = a2base64((char *)(ref->tlskeys + (head + 2 + appctx->ctx.cli.i1) % TLS_TICKETS_NO),
10520 sizeof(struct tls_sess_key_128),
10521 t2->area, t2->size);
10522 chunk_appendf(&trash, "%d.%d %s\n", ref->unique_id, appctx->ctx.cli.i1,
10523 t2->area);
10524 }
10525 else if (ref->key_size_bits == 256) {
10526 t2->data = a2base64((char *)(ref->tlskeys + (head + 2 + appctx->ctx.cli.i1) % TLS_TICKETS_NO),
10527 sizeof(struct tls_sess_key_256),
10528 t2->area, t2->size);
10529 chunk_appendf(&trash, "%d.%d %s\n", ref->unique_id, appctx->ctx.cli.i1,
10530 t2->area);
10531 }
10532 else {
10533 /* This case should never happen */
10534 chunk_appendf(&trash, "%d.%d <unknown>\n", ref->unique_id, appctx->ctx.cli.i1);
10535 }
William Lallemand32af2032016-10-29 18:09:35 +020010536
Willy Tarreau06d80a92017-10-19 14:32:15 +020010537 if (ci_putchk(si_ic(si), &trash) == -1) {
William Lallemand32af2032016-10-29 18:09:35 +020010538 /* let's try again later from this stream. We add ourselves into
10539 * this stream's users so that it can remove us upon termination.
10540 */
Christopher Faulet16f45c82018-02-16 11:23:49 +010010541 HA_RWLOCK_RDUNLOCK(TLSKEYS_REF_LOCK, &ref->lock);
Willy Tarreaudb398432018-11-15 11:08:52 +010010542 si_rx_room_blk(si);
William Lallemand32af2032016-10-29 18:09:35 +020010543 return 0;
10544 }
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010545 appctx->ctx.cli.i1++;
William Lallemand32af2032016-10-29 18:09:35 +020010546 }
Christopher Faulet16f45c82018-02-16 11:23:49 +010010547 HA_RWLOCK_RDUNLOCK(TLSKEYS_REF_LOCK, &ref->lock);
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010548 appctx->ctx.cli.i1 = 0;
William Lallemand32af2032016-10-29 18:09:35 +020010549 }
Willy Tarreau06d80a92017-10-19 14:32:15 +020010550 if (ci_putchk(si_ic(si), &trash) == -1) {
William Lallemand32af2032016-10-29 18:09:35 +020010551 /* let's try again later from this stream. We add ourselves into
10552 * this stream's users so that it can remove us upon termination.
10553 */
Willy Tarreaudb398432018-11-15 11:08:52 +010010554 si_rx_room_blk(si);
William Lallemand32af2032016-10-29 18:09:35 +020010555 return 0;
10556 }
10557
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010558 if (appctx->ctx.cli.i0 == 0) /* don't display everything if not necessary */
William Lallemand32af2032016-10-29 18:09:35 +020010559 break;
10560
10561 /* get next list entry and check the end of the list */
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010562 appctx->ctx.cli.p0 = tlskeys_list_get_next(appctx->ctx.cli.p0, &tlskeys_reference);
William Lallemand32af2032016-10-29 18:09:35 +020010563 }
10564
10565 appctx->st2 = STAT_ST_FIN;
10566 /* fall through */
10567
10568 default:
10569 appctx->st2 = STAT_ST_FIN;
10570 return 1;
10571 }
10572 return 0;
10573}
10574
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010575/* sets cli.i0 to non-zero if only file lists should be dumped */
Aurélien Nephtaliabbf6072018-04-18 13:26:46 +020010576static int cli_parse_show_tlskeys(char **args, char *payload, struct appctx *appctx, void *private)
William Lallemand32af2032016-10-29 18:09:35 +020010577{
William Lallemand32af2032016-10-29 18:09:35 +020010578 /* no parameter, shows only file list */
10579 if (!*args[2]) {
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010580 appctx->ctx.cli.i0 = 1;
William Lallemand32af2032016-10-29 18:09:35 +020010581 appctx->io_handler = cli_io_handler_tlskeys_files;
Willy Tarreau3067bfa2016-12-05 14:50:15 +010010582 return 0;
William Lallemand32af2032016-10-29 18:09:35 +020010583 }
10584
10585 if (args[2][0] == '*') {
10586 /* list every TLS ticket keys */
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010587 appctx->ctx.cli.i0 = 1;
William Lallemand32af2032016-10-29 18:09:35 +020010588 } else {
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010589 appctx->ctx.cli.p0 = tlskeys_ref_lookup_ref(args[2]);
Willy Tarreau9d008692019-08-09 11:21:01 +020010590 if (!appctx->ctx.cli.p0)
10591 return cli_err(appctx, "'show tls-keys' unable to locate referenced filename\n");
William Lallemand32af2032016-10-29 18:09:35 +020010592 }
William Lallemand32af2032016-10-29 18:09:35 +020010593 appctx->io_handler = cli_io_handler_tlskeys_entries;
Willy Tarreau3067bfa2016-12-05 14:50:15 +010010594 return 0;
William Lallemand32af2032016-10-29 18:09:35 +020010595}
10596
Aurélien Nephtaliabbf6072018-04-18 13:26:46 +020010597static int cli_parse_set_tlskeys(char **args, char *payload, struct appctx *appctx, void *private)
William Lallemand32af2032016-10-29 18:09:35 +020010598{
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010599 struct tls_keys_ref *ref;
Willy Tarreau1c913e42018-08-22 05:26:57 +020010600 int ret;
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010601
William Lallemand32af2032016-10-29 18:09:35 +020010602 /* Expect two parameters: the filename and the new new TLS key in encoding */
Willy Tarreau9d008692019-08-09 11:21:01 +020010603 if (!*args[3] || !*args[4])
10604 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 +020010605
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010606 ref = tlskeys_ref_lookup_ref(args[3]);
Willy Tarreau9d008692019-08-09 11:21:01 +020010607 if (!ref)
10608 return cli_err(appctx, "'set ssl tls-key' unable to locate referenced filename\n");
William Lallemand32af2032016-10-29 18:09:35 +020010609
Willy Tarreau1c913e42018-08-22 05:26:57 +020010610 ret = base64dec(args[4], strlen(args[4]), trash.area, trash.size);
Willy Tarreau9d008692019-08-09 11:21:01 +020010611 if (ret < 0)
10612 return cli_err(appctx, "'set ssl tls-key' received invalid base64 encoded TLS key.\n");
Emeric Brun9e754772019-01-10 17:51:55 +010010613
Willy Tarreau1c913e42018-08-22 05:26:57 +020010614 trash.data = ret;
Willy Tarreau9d008692019-08-09 11:21:01 +020010615 if (ssl_sock_update_tlskey_ref(ref, &trash) < 0)
10616 return cli_err(appctx, "'set ssl tls-key' received a key of wrong size.\n");
William Lallemand32af2032016-10-29 18:09:35 +020010617
Willy Tarreau9d008692019-08-09 11:21:01 +020010618 return cli_msg(appctx, LOG_INFO, "TLS ticket key updated!\n");
William Lallemand32af2032016-10-29 18:09:35 +020010619}
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +010010620#endif
William Lallemand32af2032016-10-29 18:09:35 +020010621
William Lallemand44b35322019-10-17 16:28:40 +020010622
10623/* Type of SSL payloads that can be updated over the CLI */
10624
10625enum {
10626 CERT_TYPE_PEM = 0,
William Lallemand4c5adbf2020-02-24 14:23:22 +010010627 CERT_TYPE_KEY,
Emmanuel Hocdetf6ac4fa2019-10-30 17:41:27 +010010628#if ((defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP) || defined OPENSSL_IS_BORINGSSL)
William Lallemand44b35322019-10-17 16:28:40 +020010629 CERT_TYPE_OCSP,
Emmanuel Hocdetf6ac4fa2019-10-30 17:41:27 +010010630#endif
William Lallemand44b35322019-10-17 16:28:40 +020010631 CERT_TYPE_ISSUER,
Emmanuel Hocdetf6ac4fa2019-10-30 17:41:27 +010010632#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
William Lallemand44b35322019-10-17 16:28:40 +020010633 CERT_TYPE_SCTL,
Emmanuel Hocdetf6ac4fa2019-10-30 17:41:27 +010010634#endif
William Lallemand44b35322019-10-17 16:28:40 +020010635 CERT_TYPE_MAX,
10636};
10637
10638struct {
10639 const char *ext;
10640 int type;
10641 int (*load)(const char *path, char *payload, struct cert_key_and_chain *ckch, char **err);
10642 /* add a parsing callback */
William Lallemandf29cdef2019-10-23 15:00:52 +020010643} cert_exts[CERT_TYPE_MAX+1] = {
William Lallemand44b35322019-10-17 16:28:40 +020010644 [CERT_TYPE_PEM] = { "", CERT_TYPE_PEM, &ssl_sock_load_pem_into_ckch }, /* default mode, no extensions */
William Lallemand4c5adbf2020-02-24 14:23:22 +010010645 [CERT_TYPE_KEY] = { "key", CERT_TYPE_KEY, &ssl_sock_load_key_into_ckch },
William Lallemand541a5342019-10-23 14:11:54 +020010646#if ((defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP) || defined OPENSSL_IS_BORINGSSL)
William Lallemand44b35322019-10-17 16:28:40 +020010647 [CERT_TYPE_OCSP] = { "ocsp", CERT_TYPE_OCSP, &ssl_sock_load_ocsp_response_from_file },
William Lallemand541a5342019-10-23 14:11:54 +020010648#endif
10649#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
William Lallemand44b35322019-10-17 16:28:40 +020010650 [CERT_TYPE_SCTL] = { "sctl", CERT_TYPE_SCTL, &ssl_sock_load_sctl_from_file },
William Lallemand541a5342019-10-23 14:11:54 +020010651#endif
William Lallemand44b35322019-10-17 16:28:40 +020010652 [CERT_TYPE_ISSUER] = { "issuer", CERT_TYPE_ISSUER, &ssl_sock_load_issuer_file_into_ckch },
William Lallemandf29cdef2019-10-23 15:00:52 +020010653 [CERT_TYPE_MAX] = { NULL, CERT_TYPE_MAX, NULL },
William Lallemand44b35322019-10-17 16:28:40 +020010654};
10655
William Lallemand430413e2019-10-28 14:30:47 +010010656/* states of the CLI IO handler for 'set ssl cert' */
10657enum {
10658 SETCERT_ST_INIT = 0,
10659 SETCERT_ST_GEN,
10660 SETCERT_ST_INSERT,
10661 SETCERT_ST_FIN,
10662};
William Lallemand8f840d72019-10-23 10:53:05 +020010663
William Lallemandd4f946c2019-12-05 10:26:40 +010010664/* release function of the `show ssl cert' command */
10665static void cli_release_show_cert(struct appctx *appctx)
10666{
10667 HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
10668}
10669
10670/* IO handler of "show ssl cert <filename>" */
10671static int cli_io_handler_show_cert(struct appctx *appctx)
10672{
10673 struct buffer *trash = alloc_trash_chunk();
10674 struct ebmb_node *node;
10675 struct stream_interface *si = appctx->owner;
10676 struct ckch_store *ckchs;
William Lallemandd4f946c2019-12-05 10:26:40 +010010677
10678 if (trash == NULL)
10679 return 1;
10680
10681 if (!appctx->ctx.ssl.old_ckchs) {
10682 if (ckchs_transaction.old_ckchs) {
10683 ckchs = ckchs_transaction.old_ckchs;
10684 chunk_appendf(trash, "# transaction\n");
10685 if (!ckchs->multi) {
10686 chunk_appendf(trash, "*%s\n", ckchs->path);
William Lallemandba22e902019-12-18 20:36:01 +010010687#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
William Lallemandd4f946c2019-12-05 10:26:40 +010010688 } else {
William Lallemanda25a19f2020-01-29 00:04:24 +010010689 int n;
10690
William Lallemandd4f946c2019-12-05 10:26:40 +010010691 chunk_appendf(trash, "*%s:", ckchs->path);
10692 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
10693 if (ckchs->ckch[n].cert)
10694 chunk_appendf(trash, " %s.%s\n", ckchs->path, SSL_SOCK_KEYTYPE_NAMES[n]);
10695 }
10696 chunk_appendf(trash, "\n");
William Lallemandba22e902019-12-18 20:36:01 +010010697#endif
William Lallemandd4f946c2019-12-05 10:26:40 +010010698 }
10699 }
10700 }
10701
10702 if (!appctx->ctx.cli.p0) {
10703 chunk_appendf(trash, "# filename\n");
10704 node = ebmb_first(&ckchs_tree);
10705 } else {
10706 node = &((struct ckch_store *)appctx->ctx.cli.p0)->node;
10707 }
10708 while (node) {
10709 ckchs = ebmb_entry(node, struct ckch_store, node);
10710 if (!ckchs->multi) {
10711 chunk_appendf(trash, "%s\n", ckchs->path);
William Lallemandba22e902019-12-18 20:36:01 +010010712#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
William Lallemandd4f946c2019-12-05 10:26:40 +010010713 } else {
William Lallemanda25a19f2020-01-29 00:04:24 +010010714 int n;
10715
William Lallemandd4f946c2019-12-05 10:26:40 +010010716 chunk_appendf(trash, "%s:", ckchs->path);
10717 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
10718 if (ckchs->ckch[n].cert)
10719 chunk_appendf(trash, " %s.%s", ckchs->path, SSL_SOCK_KEYTYPE_NAMES[n]);
10720 }
10721 chunk_appendf(trash, "\n");
William Lallemandba22e902019-12-18 20:36:01 +010010722#endif
William Lallemandd4f946c2019-12-05 10:26:40 +010010723 }
10724
10725 node = ebmb_next(node);
10726 if (ci_putchk(si_ic(si), trash) == -1) {
10727 si_rx_room_blk(si);
10728 goto yield;
10729 }
10730 }
10731
10732 appctx->ctx.cli.p0 = NULL;
10733 free_trash_chunk(trash);
10734 return 1;
10735yield:
10736
10737 free_trash_chunk(trash);
10738 appctx->ctx.cli.p0 = ckchs;
10739 return 0; /* should come back */
10740}
10741
10742/* IO handler of the details "show ssl cert <filename>" */
10743static int cli_io_handler_show_cert_detail(struct appctx *appctx)
10744{
10745 struct stream_interface *si = appctx->owner;
10746 struct ckch_store *ckchs = appctx->ctx.cli.p0;
10747 struct buffer *out = alloc_trash_chunk();
10748 struct buffer *tmp = alloc_trash_chunk();
10749 X509_NAME *name = NULL;
Emmanuel Hocdetcf8cf6c2020-02-18 16:06:14 +010010750 STACK_OF(X509) *chain;
Willy Tarreau105599c2020-02-25 08:59:23 +010010751 unsigned int len = 0;
William Lallemandd4f946c2019-12-05 10:26:40 +010010752 int write = -1;
10753 BIO *bio = NULL;
William Lallemand35f4a9d2020-02-25 11:56:32 +010010754 int i;
William Lallemandd4f946c2019-12-05 10:26:40 +010010755
10756 if (!tmp || !out)
10757 goto end;
10758
10759 if (!ckchs->multi) {
10760 chunk_appendf(out, "Filename: ");
10761 if (ckchs == ckchs_transaction.new_ckchs)
10762 chunk_appendf(out, "*");
10763 chunk_appendf(out, "%s\n", ckchs->path);
Emmanuel Hocdetcf8cf6c2020-02-18 16:06:14 +010010764
10765 chain = ckchs->ckch->chain;
10766 if (chain == NULL) {
10767 struct issuer_chain *issuer;
10768 issuer = ssl_get_issuer_chain(ckchs->ckch->cert);
10769 if (issuer) {
10770 chain = issuer->chain;
10771 chunk_appendf(out, "Chain Filename: ");
10772 chunk_appendf(out, "%s\n", issuer->path);
10773 }
10774 }
William Lallemandd4f946c2019-12-05 10:26:40 +010010775 chunk_appendf(out, "Serial: ");
10776 if (ssl_sock_get_serial(ckchs->ckch->cert, tmp) == -1)
10777 goto end;
10778 dump_binary(out, tmp->area, tmp->data);
10779 chunk_appendf(out, "\n");
10780
10781 chunk_appendf(out, "notBefore: ");
10782 chunk_reset(tmp);
10783 if ((bio = BIO_new(BIO_s_mem())) == NULL)
10784 goto end;
10785 if (ASN1_TIME_print(bio, X509_getm_notBefore(ckchs->ckch->cert)) == 0)
10786 goto end;
10787 write = BIO_read(bio, tmp->area, tmp->size-1);
10788 tmp->area[write] = '\0';
10789 BIO_free(bio);
10790 chunk_appendf(out, "%s\n", tmp->area);
10791
10792 chunk_appendf(out, "notAfter: ");
10793 chunk_reset(tmp);
10794 if ((bio = BIO_new(BIO_s_mem())) == NULL)
10795 goto end;
10796 if (ASN1_TIME_print(bio, X509_getm_notAfter(ckchs->ckch->cert)) == 0)
10797 goto end;
10798 if ((write = BIO_read(bio, tmp->area, tmp->size-1)) <= 0)
10799 goto end;
10800 tmp->area[write] = '\0';
10801 BIO_free(bio);
10802 chunk_appendf(out, "%s\n", tmp->area);
10803
William Lallemandd4f946c2019-12-05 10:26:40 +010010804#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
10805 chunk_appendf(out, "Subject Alternative Name: ");
10806 if (ssl_sock_get_san_oneline(ckchs->ckch->cert, out) == -1)
10807 goto end;
10808 *(out->area + out->data) = '\0';
10809 chunk_appendf(out, "\n");
10810#endif
10811 chunk_reset(tmp);
10812 chunk_appendf(out, "Algorithm: ");
10813 if (cert_get_pkey_algo(ckchs->ckch->cert, tmp) == 0)
10814 goto end;
10815 chunk_appendf(out, "%s\n", tmp->area);
10816
10817 chunk_reset(tmp);
10818 chunk_appendf(out, "SHA1 FingerPrint: ");
Willy Tarreau105599c2020-02-25 08:59:23 +010010819 if (X509_digest(ckchs->ckch->cert, EVP_sha1(), (unsigned char *) tmp->area, &len) == 0)
William Lallemandd4f946c2019-12-05 10:26:40 +010010820 goto end;
Willy Tarreau105599c2020-02-25 08:59:23 +010010821 tmp->data = len;
William Lallemandd4f946c2019-12-05 10:26:40 +010010822 dump_binary(out, tmp->area, tmp->data);
10823 chunk_appendf(out, "\n");
William Lallemand35f4a9d2020-02-25 11:56:32 +010010824
William Lallemanda90e5932020-02-25 14:07:58 +010010825 chunk_appendf(out, "Subject: ");
10826 if ((name = X509_get_subject_name(ckchs->ckch->cert)) == NULL)
10827 goto end;
10828 if ((ssl_sock_get_dn_oneline(name, tmp)) == -1)
10829 goto end;
10830 *(tmp->area + tmp->data) = '\0';
10831 chunk_appendf(out, "%s\n", tmp->area);
10832
10833 chunk_appendf(out, "Issuer: ");
10834 if ((name = X509_get_issuer_name(ckchs->ckch->cert)) == NULL)
10835 goto end;
10836 if ((ssl_sock_get_dn_oneline(name, tmp)) == -1)
10837 goto end;
10838 *(tmp->area + tmp->data) = '\0';
10839 chunk_appendf(out, "%s\n", tmp->area);
10840
William Lallemand35f4a9d2020-02-25 11:56:32 +010010841 /* Displays subject of each certificate in the chain */
Emmanuel Hocdetcf8cf6c2020-02-18 16:06:14 +010010842 for (i = 0; i < sk_X509_num(chain); i++) {
10843 X509 *ca = sk_X509_value(chain, i);
William Lallemand35f4a9d2020-02-25 11:56:32 +010010844
William Lallemandbb7288a2020-02-25 14:04:33 +010010845 chunk_appendf(out, "Chain Subject: ");
William Lallemand35f4a9d2020-02-25 11:56:32 +010010846 if ((name = X509_get_subject_name(ca)) == NULL)
10847 goto end;
10848 if ((ssl_sock_get_dn_oneline(name, tmp)) == -1)
10849 goto end;
10850 *(tmp->area + tmp->data) = '\0';
10851 chunk_appendf(out, "%s\n", tmp->area);
10852
William Lallemandbb7288a2020-02-25 14:04:33 +010010853 chunk_appendf(out, "Chain Issuer: ");
10854 if ((name = X509_get_issuer_name(ca)) == NULL)
10855 goto end;
10856 if ((ssl_sock_get_dn_oneline(name, tmp)) == -1)
10857 goto end;
10858 *(tmp->area + tmp->data) = '\0';
10859 chunk_appendf(out, "%s\n", tmp->area);
William Lallemand35f4a9d2020-02-25 11:56:32 +010010860 }
William Lallemandd4f946c2019-12-05 10:26:40 +010010861 }
10862
10863 if (ci_putchk(si_ic(si), out) == -1) {
10864 si_rx_room_blk(si);
10865 goto yield;
10866 }
10867
10868end:
10869 free_trash_chunk(tmp);
10870 free_trash_chunk(out);
10871 return 1;
10872yield:
10873 free_trash_chunk(tmp);
10874 free_trash_chunk(out);
10875 return 0; /* should come back */
10876}
10877
10878/* parsing function for 'show ssl cert [certfile]' */
10879static int cli_parse_show_cert(char **args, char *payload, struct appctx *appctx, void *private)
10880{
10881 struct ckch_store *ckchs;
10882
10883 if (!cli_has_level(appctx, ACCESS_LVL_OPER))
10884 return cli_err(appctx, "Can't allocate memory!\n");
10885
10886 /* The operations on the CKCH architecture are locked so we can
10887 * manipulate ckch_store and ckch_inst */
10888 if (HA_SPIN_TRYLOCK(CKCH_LOCK, &ckch_lock))
10889 return cli_err(appctx, "Can't show!\nOperations on certificates are currently locked!\n");
10890
10891 /* check if there is a certificate to lookup */
10892 if (*args[3]) {
10893 if (*args[3] == '*') {
10894 if (!ckchs_transaction.new_ckchs)
10895 goto error;
10896
10897 ckchs = ckchs_transaction.new_ckchs;
10898
10899 if (strcmp(args[3] + 1, ckchs->path))
10900 goto error;
10901
10902 } else {
10903 if ((ckchs = ckchs_lookup(args[3])) == NULL)
10904 goto error;
10905
10906 }
10907
10908 if (ckchs->multi)
10909 goto error;
10910
10911 appctx->ctx.cli.p0 = ckchs;
10912 /* use the IO handler that shows details */
10913 appctx->io_handler = cli_io_handler_show_cert_detail;
10914 }
10915
10916 return 0;
10917
10918error:
10919 HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
10920 return cli_err(appctx, "Can't display the certificate: Not found or the certificate is a bundle!\n");
10921}
10922
William Lallemand430413e2019-10-28 14:30:47 +010010923/* release function of the `set ssl cert' command, free things and unlock the spinlock */
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010924static void cli_release_commit_cert(struct appctx *appctx)
William Lallemand8f840d72019-10-23 10:53:05 +020010925{
10926 struct ckch_store *new_ckchs;
10927 struct ckch_inst *ckchi, *ckchis;
William Lallemand8f840d72019-10-23 10:53:05 +020010928
William Lallemand430413e2019-10-28 14:30:47 +010010929 HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
William Lallemand8f840d72019-10-23 10:53:05 +020010930
William Lallemand430413e2019-10-28 14:30:47 +010010931 if (appctx->st2 != SETCERT_ST_FIN) {
William Lallemand8f840d72019-10-23 10:53:05 +020010932 /* 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 +010010933 new_ckchs = appctx->ctx.ssl.new_ckchs;
William Lallemand8f840d72019-10-23 10:53:05 +020010934
William Lallemandbeea2a42019-10-30 17:45:33 +010010935 if (!new_ckchs)
10936 return;
William Lallemand8f840d72019-10-23 10:53:05 +020010937
William Lallemandbeea2a42019-10-30 17:45:33 +010010938 /* if the allocation failed, we need to free everything from the temporary list */
10939 list_for_each_entry_safe(ckchi, ckchis, &new_ckchs->ckch_inst, by_ckchs) {
10940 struct sni_ctx *sc0, *sc0s;
William Lallemand8f840d72019-10-23 10:53:05 +020010941
William Lallemandbeea2a42019-10-30 17:45:33 +010010942 list_for_each_entry_safe(sc0, sc0s, &ckchi->sni_ctx, by_ckch_inst) {
10943 if (sc0->order == 0) /* we only free if it's the first inserted */
10944 SSL_CTX_free(sc0->ctx);
10945 LIST_DEL(&sc0->by_ckch_inst);
10946 free(sc0);
William Lallemand8f840d72019-10-23 10:53:05 +020010947 }
William Lallemandbeea2a42019-10-30 17:45:33 +010010948 LIST_DEL(&ckchi->by_ckchs);
10949 free(ckchi);
William Lallemand8f840d72019-10-23 10:53:05 +020010950 }
William Lallemandbeea2a42019-10-30 17:45:33 +010010951 ckchs_free(new_ckchs);
William Lallemand8f840d72019-10-23 10:53:05 +020010952 }
10953}
10954
10955
10956/*
10957 * This function tries to create the new ckch_inst and their SNIs
10958 */
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010959static int cli_io_handler_commit_cert(struct appctx *appctx)
William Lallemand8f840d72019-10-23 10:53:05 +020010960{
10961 struct stream_interface *si = appctx->owner;
10962 int y = 0;
10963 char *err = NULL;
10964 int errcode = 0;
10965 struct ckch_store *old_ckchs, *new_ckchs = NULL;
10966 struct ckch_inst *ckchi, *ckchis;
William Lallemand8f840d72019-10-23 10:53:05 +020010967 struct buffer *trash = alloc_trash_chunk();
William Lallemand8ef0c2a2019-11-21 16:30:34 +010010968 struct sni_ctx *sc0, *sc0s;
William Lallemand8f840d72019-10-23 10:53:05 +020010969
William Lallemand33cc76f2019-10-31 11:43:45 +010010970 if (trash == NULL)
10971 goto error;
10972
William Lallemand8f840d72019-10-23 10:53:05 +020010973 if (unlikely(si_ic(si)->flags & (CF_WRITE_ERROR|CF_SHUTW)))
10974 goto error;
10975
William Lallemand430413e2019-10-28 14:30:47 +010010976 while (1) {
10977 switch (appctx->st2) {
10978 case SETCERT_ST_INIT:
10979 /* This state just print the update message */
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010980 chunk_printf(trash, "Committing %s", ckchs_transaction.path);
William Lallemand430413e2019-10-28 14:30:47 +010010981 if (ci_putchk(si_ic(si), trash) == -1) {
10982 si_rx_room_blk(si);
William Lallemand8f840d72019-10-23 10:53:05 +020010983 goto yield;
William Lallemand430413e2019-10-28 14:30:47 +010010984 }
10985 appctx->st2 = SETCERT_ST_GEN;
10986 /* fallthrough */
10987 case SETCERT_ST_GEN:
10988 /*
10989 * This state generates the ckch instances with their
10990 * sni_ctxs and SSL_CTX.
10991 *
William Lallemand430413e2019-10-28 14:30:47 +010010992 * Since the SSL_CTX generation can be CPU consumer, we
10993 * yield every 10 instances.
10994 */
William Lallemand8f840d72019-10-23 10:53:05 +020010995
William Lallemandbeea2a42019-10-30 17:45:33 +010010996 old_ckchs = appctx->ctx.ssl.old_ckchs;
10997 new_ckchs = appctx->ctx.ssl.new_ckchs;
William Lallemand8f840d72019-10-23 10:53:05 +020010998
William Lallemandbeea2a42019-10-30 17:45:33 +010010999 if (!new_ckchs)
11000 continue;
William Lallemand8f840d72019-10-23 10:53:05 +020011001
William Lallemandbeea2a42019-10-30 17:45:33 +010011002 /* get the next ckchi to regenerate */
11003 ckchi = appctx->ctx.ssl.next_ckchi;
11004 /* we didn't start yet, set it to the first elem */
11005 if (ckchi == NULL)
11006 ckchi = LIST_ELEM(old_ckchs->ckch_inst.n, typeof(ckchi), by_ckchs);
William Lallemand8f840d72019-10-23 10:53:05 +020011007
William Lallemandbeea2a42019-10-30 17:45:33 +010011008 /* walk through the old ckch_inst and creates new ckch_inst using the updated ckchs */
11009 list_for_each_entry_from(ckchi, &old_ckchs->ckch_inst, by_ckchs) {
11010 struct ckch_inst *new_inst;
William Lallemand38df1c82019-12-04 15:39:35 +010011011 char **sni_filter = NULL;
11012 int fcount = 0;
William Lallemand8f840d72019-10-23 10:53:05 +020011013
William Lallemandbeea2a42019-10-30 17:45:33 +010011014 /* it takes a lot of CPU to creates SSL_CTXs, so we yield every 10 CKCH instances */
11015 if (y >= 10) {
11016 /* save the next ckchi to compute */
11017 appctx->ctx.ssl.next_ckchi = ckchi;
11018 goto yield;
11019 }
William Lallemand67630162020-03-09 16:56:39 +010011020 if (ckchi->filters) {
11021 errcode |= ckch_inst_sni_ctx_to_sni_filters(ckchi, &sni_filter, &fcount, &err);
11022 if (errcode & ERR_CODE)
11023 goto error;
11024 }
William Lallemand38df1c82019-12-04 15:39:35 +010011025
William Lallemandbeea2a42019-10-30 17:45:33 +010011026 if (new_ckchs->multi)
William Lallemand38df1c82019-12-04 15:39:35 +010011027 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 +010011028 else
William Lallemand38df1c82019-12-04 15:39:35 +010011029 errcode |= ckch_inst_new_load_store(new_ckchs->path, new_ckchs, ckchi->bind_conf, ckchi->ssl_conf, sni_filter, fcount, &new_inst, &err);
11030
11031 free_sni_filters(sni_filter, fcount);
11032 sni_filter = NULL;
William Lallemand8f840d72019-10-23 10:53:05 +020011033
William Lallemandbeea2a42019-10-30 17:45:33 +010011034 if (errcode & ERR_CODE)
11035 goto error;
William Lallemand8f840d72019-10-23 10:53:05 +020011036
William Lallemand21724f02019-11-04 17:56:13 +010011037 /* if the previous ckchi was used as the default */
11038 if (ckchi->is_default)
11039 new_inst->is_default = 1;
11040
William Lallemand8ef0c2a2019-11-21 16:30:34 +010011041 /* we need to initialize the SSL_CTX generated */
William Lallemand696f3172020-02-07 20:45:24 +010011042 /* this iterate on the newly generated SNIs in the new instance to prepare their SSL_CTX */
11043 list_for_each_entry_safe(sc0, sc0s, &new_inst->sni_ctx, by_ckch_inst) {
William Lallemand8ef0c2a2019-11-21 16:30:34 +010011044 if (!sc0->order) { /* we initiliazed only the first SSL_CTX because it's the same in the other sni_ctx's */
11045 errcode |= ssl_sock_prepare_ctx(ckchi->bind_conf, ckchi->ssl_conf, sc0->ctx, &err);
11046 if (errcode & ERR_CODE)
11047 goto error;
11048 }
11049 }
11050
11051
William Lallemandbeea2a42019-10-30 17:45:33 +010011052 /* display one dot per new instance */
11053 chunk_appendf(trash, ".");
11054 /* link the new ckch_inst to the duplicate */
11055 LIST_ADDQ(&new_ckchs->ckch_inst, &new_inst->by_ckchs);
11056 y++;
11057 }
William Lallemand430413e2019-10-28 14:30:47 +010011058 appctx->st2 = SETCERT_ST_INSERT;
11059 /* fallthrough */
11060 case SETCERT_ST_INSERT:
11061 /* The generation is finished, we can insert everything */
William Lallemand8f840d72019-10-23 10:53:05 +020011062
William Lallemandbeea2a42019-10-30 17:45:33 +010011063 old_ckchs = appctx->ctx.ssl.old_ckchs;
11064 new_ckchs = appctx->ctx.ssl.new_ckchs;
William Lallemand8f840d72019-10-23 10:53:05 +020011065
William Lallemandbeea2a42019-10-30 17:45:33 +010011066 if (!new_ckchs)
11067 continue;
William Lallemand430413e2019-10-28 14:30:47 +010011068
William Lallemand21724f02019-11-04 17:56:13 +010011069 /* First, we insert every new SNIs in the trees, also replace the default_ctx */
William Lallemandbeea2a42019-10-30 17:45:33 +010011070 list_for_each_entry_safe(ckchi, ckchis, &new_ckchs->ckch_inst, by_ckchs) {
11071 HA_RWLOCK_WRLOCK(SNI_LOCK, &ckchi->bind_conf->sni_lock);
11072 ssl_sock_load_cert_sni(ckchi, ckchi->bind_conf);
11073 HA_RWLOCK_WRUNLOCK(SNI_LOCK, &ckchi->bind_conf->sni_lock);
11074 }
William Lallemand8f840d72019-10-23 10:53:05 +020011075
William Lallemandbeea2a42019-10-30 17:45:33 +010011076 /* delete the old sni_ctx, the old ckch_insts and the ckch_store */
11077 list_for_each_entry_safe(ckchi, ckchis, &old_ckchs->ckch_inst, by_ckchs) {
William Lallemand430413e2019-10-28 14:30:47 +010011078
William Lallemandbeea2a42019-10-30 17:45:33 +010011079 HA_RWLOCK_WRLOCK(SNI_LOCK, &ckchi->bind_conf->sni_lock);
11080 list_for_each_entry_safe(sc0, sc0s, &ckchi->sni_ctx, by_ckch_inst) {
11081 ebmb_delete(&sc0->name);
11082 LIST_DEL(&sc0->by_ckch_inst);
11083 free(sc0);
William Lallemand430413e2019-10-28 14:30:47 +010011084 }
William Lallemandbeea2a42019-10-30 17:45:33 +010011085 HA_RWLOCK_WRUNLOCK(SNI_LOCK, &ckchi->bind_conf->sni_lock);
11086 LIST_DEL(&ckchi->by_ckchs);
11087 free(ckchi);
11088 }
William Lallemand8f840d72019-10-23 10:53:05 +020011089
William Lallemandbeea2a42019-10-30 17:45:33 +010011090 /* Replace the old ckchs by the new one */
11091 ebmb_delete(&old_ckchs->node);
11092 ckchs_free(old_ckchs);
11093 ebst_insert(&ckchs_tree, &new_ckchs->node);
William Lallemand430413e2019-10-28 14:30:47 +010011094 appctx->st2 = SETCERT_ST_FIN;
11095 /* fallthrough */
11096 case SETCERT_ST_FIN:
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011097 /* we achieved the transaction, we can set everything to NULL */
11098 free(ckchs_transaction.path);
11099 ckchs_transaction.path = NULL;
11100 ckchs_transaction.new_ckchs = NULL;
11101 ckchs_transaction.old_ckchs = NULL;
William Lallemand430413e2019-10-28 14:30:47 +010011102 goto end;
11103 }
William Lallemand8f840d72019-10-23 10:53:05 +020011104 }
William Lallemand430413e2019-10-28 14:30:47 +010011105end:
William Lallemand8f840d72019-10-23 10:53:05 +020011106
William Lallemanded442432019-11-21 16:41:07 +010011107 chunk_appendf(trash, "\n");
11108 if (errcode & ERR_WARN)
Tim Duesterhusc0e820c2019-11-23 23:52:30 +010011109 chunk_appendf(trash, "%s", err);
William Lallemanded442432019-11-21 16:41:07 +010011110 chunk_appendf(trash, "Success!\n");
William Lallemand430413e2019-10-28 14:30:47 +010011111 if (ci_putchk(si_ic(si), trash) == -1)
11112 si_rx_room_blk(si);
11113 free_trash_chunk(trash);
11114 /* success: call the release function and don't come back */
11115 return 1;
William Lallemand8f840d72019-10-23 10:53:05 +020011116yield:
11117 /* store the state */
11118 if (ci_putchk(si_ic(si), trash) == -1)
11119 si_rx_room_blk(si);
11120 free_trash_chunk(trash);
11121 si_rx_endp_more(si); /* let's come back later */
William Lallemand8f840d72019-10-23 10:53:05 +020011122 return 0; /* should come back */
11123
11124error:
11125 /* spin unlock and free are done in the release function */
William Lallemand33cc76f2019-10-31 11:43:45 +010011126 if (trash) {
11127 chunk_appendf(trash, "\n%sFailed!\n", err);
11128 if (ci_putchk(si_ic(si), trash) == -1)
11129 si_rx_room_blk(si);
11130 free_trash_chunk(trash);
11131 }
William Lallemand430413e2019-10-28 14:30:47 +010011132 /* error: call the release function and don't come back */
11133 return 1;
William Lallemand8f840d72019-10-23 10:53:05 +020011134}
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011135
11136/*
11137 * Parsing function of 'commit ssl cert'
11138 */
11139static int cli_parse_commit_cert(char **args, char *payload, struct appctx *appctx, void *private)
11140{
11141 char *err = NULL;
11142
William Lallemand230662a2019-12-03 13:32:54 +010011143 if (!cli_has_level(appctx, ACCESS_LVL_ADMIN))
11144 return 1;
11145
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011146 if (!*args[3])
11147 return cli_err(appctx, "'commit ssl cert expects a filename\n");
11148
11149 /* The operations on the CKCH architecture are locked so we can
11150 * manipulate ckch_store and ckch_inst */
11151 if (HA_SPIN_TRYLOCK(CKCH_LOCK, &ckch_lock))
11152 return cli_err(appctx, "Can't commit the certificate!\nOperations on certificates are currently locked!\n");
11153
11154 if (!ckchs_transaction.path) {
11155 memprintf(&err, "No ongoing transaction! !\n");
11156 goto error;
11157 }
11158
11159 if (strcmp(ckchs_transaction.path, args[3]) != 0) {
11160 memprintf(&err, "The ongoing transaction is about '%s' but you are trying to set '%s'\n", ckchs_transaction.path, args[3]);
11161 goto error;
11162 }
11163
William Lallemand4c5adbf2020-02-24 14:23:22 +010011164#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
11165 if (ckchs_transaction.new_ckchs->multi) {
11166 int n;
11167
11168 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
11169 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)) {
11170 memprintf(&err, "inconsistencies between private key and certificate loaded '%s'.\n", ckchs_transaction.path);
11171 goto error;
11172 }
11173 }
11174 } else
11175#endif
11176 {
11177 if (!X509_check_private_key(ckchs_transaction.new_ckchs->ckch->cert, ckchs_transaction.new_ckchs->ckch->key)) {
11178 memprintf(&err, "inconsistencies between private key and certificate loaded '%s'.\n", ckchs_transaction.path);
11179 goto error;
11180 }
11181 }
11182
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011183 /* init the appctx structure */
11184 appctx->st2 = SETCERT_ST_INIT;
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011185 appctx->ctx.ssl.next_ckchi = NULL;
11186 appctx->ctx.ssl.new_ckchs = ckchs_transaction.new_ckchs;
11187 appctx->ctx.ssl.old_ckchs = ckchs_transaction.old_ckchs;
11188
11189 /* we don't unlock there, it will be unlock after the IO handler, in the release handler */
11190 return 0;
11191
11192error:
11193
11194 HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
11195 err = memprintf(&err, "%sCan't commit %s!\n", err ? err : "", args[3]);
11196
11197 return cli_dynerr(appctx, err);
11198}
11199
William Lallemand8f840d72019-10-23 10:53:05 +020011200/*
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011201 * Parsing function of `set ssl cert`, it updates or creates a temporary ckch.
William Lallemand8f840d72019-10-23 10:53:05 +020011202 */
William Lallemand150bfa82019-09-19 17:12:49 +020011203static int cli_parse_set_cert(char **args, char *payload, struct appctx *appctx, void *private)
11204{
William Lallemand0c3b7d92019-10-18 11:27:07 +020011205 struct ckch_store *new_ckchs = NULL;
William Lallemand8f840d72019-10-23 10:53:05 +020011206 struct ckch_store *old_ckchs = NULL;
William Lallemand150bfa82019-09-19 17:12:49 +020011207 char *err = NULL;
William Lallemand963b2e72019-10-14 11:38:36 +020011208 int i;
William Lallemand849eed62019-10-17 16:23:50 +020011209 int bundle = -1; /* TRUE if >= 0 (ckch index) */
Emeric Brunf69ed1d2019-10-17 11:56:56 +020011210 int errcode = 0;
William Lallemand44b35322019-10-17 16:28:40 +020011211 char *end;
11212 int type = CERT_TYPE_PEM;
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011213 struct cert_key_and_chain *ckch;
11214 struct buffer *buf;
William Lallemand8f840d72019-10-23 10:53:05 +020011215
William Lallemand230662a2019-12-03 13:32:54 +010011216 if (!cli_has_level(appctx, ACCESS_LVL_ADMIN))
11217 return 1;
11218
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011219 if ((buf = alloc_trash_chunk()) == NULL)
11220 return cli_err(appctx, "Can't allocate memory\n");
William Lallemand150bfa82019-09-19 17:12:49 +020011221
11222 if (!*args[3] || !payload)
11223 return cli_err(appctx, "'set ssl cert expects a filename and a certificat as a payload\n");
11224
11225 /* The operations on the CKCH architecture are locked so we can
11226 * manipulate ckch_store and ckch_inst */
11227 if (HA_SPIN_TRYLOCK(CKCH_LOCK, &ckch_lock))
11228 return cli_err(appctx, "Can't update the certificate!\nOperations on certificates are currently locked!\n");
11229
William Lallemand8f840d72019-10-23 10:53:05 +020011230 if (!chunk_strcpy(buf, args[3])) {
11231 memprintf(&err, "%sCan't allocate memory\n", err ? err : "");
11232 errcode |= ERR_ALERT | ERR_FATAL;
11233 goto end;
11234 }
11235
William Lallemand44b35322019-10-17 16:28:40 +020011236 /* check which type of file we want to update */
William Lallemandf29cdef2019-10-23 15:00:52 +020011237 for (i = 0; cert_exts[i].type < CERT_TYPE_MAX; i++) {
William Lallemand8f840d72019-10-23 10:53:05 +020011238 end = strrchr(buf->area, '.');
William Lallemand44b35322019-10-17 16:28:40 +020011239 if (end && *cert_exts[i].ext && (!strcmp(end + 1, cert_exts[i].ext))) {
11240 *end = '\0';
11241 type = cert_exts[i].type;
11242 break;
11243 }
11244 }
11245
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011246 appctx->ctx.ssl.old_ckchs = NULL;
11247 appctx->ctx.ssl.new_ckchs = NULL;
William Lallemand849eed62019-10-17 16:23:50 +020011248
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011249 /* if there is an ongoing transaction */
11250 if (ckchs_transaction.path) {
11251 /* 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 +020011252#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011253 if (ckchs_transaction.new_ckchs->multi) {
Emmanuel Hocdet40f2f1e2019-10-30 17:31:28 +010011254 char *end;
William Lallemand963b2e72019-10-14 11:38:36 +020011255 int j;
William Lallemand150bfa82019-09-19 17:12:49 +020011256
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011257 /* check if it was used in a bundle by removing the
William Lallemand963b2e72019-10-14 11:38:36 +020011258 * .dsa/.rsa/.ecdsa at the end of the filename */
William Lallemand8f840d72019-10-23 10:53:05 +020011259 end = strrchr(buf->area, '.');
Emmanuel Hocdet40f2f1e2019-10-30 17:31:28 +010011260 for (j = 0; end && j < SSL_SOCK_NUM_KEYTYPES; j++) {
William Lallemand963b2e72019-10-14 11:38:36 +020011261 if (!strcmp(end + 1, SSL_SOCK_KEYTYPE_NAMES[j])) {
11262 bundle = j; /* keep the type of certificate so we insert it at the right place */
11263 *end = '\0'; /* it's a bundle let's end the string*/
11264 break;
11265 }
William Lallemand150bfa82019-09-19 17:12:49 +020011266 }
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011267 if (bundle < 0) {
11268 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);
11269 errcode |= ERR_ALERT | ERR_FATAL;
11270 goto end;
11271 }
11272 }
11273#endif
11274
11275 /* if there is an ongoing transaction, check if this is the same file */
11276 if (strcmp(ckchs_transaction.path, buf->area) != 0) {
11277 memprintf(&err, "The ongoing transaction is about '%s' but you are trying to set '%s'\n", ckchs_transaction.path, buf->area);
11278 errcode |= ERR_ALERT | ERR_FATAL;
11279 goto end;
William Lallemand150bfa82019-09-19 17:12:49 +020011280 }
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011281
11282 appctx->ctx.ssl.old_ckchs = ckchs_transaction.new_ckchs;
11283
11284 } else {
11285 struct ckch_store *find_ckchs[2] = { NULL, NULL };
11286
11287 /* lookup for the certificate in the tree:
11288 * check if this is used as a bundle AND as a unique certificate */
11289 for (i = 0; i < 2; i++) {
11290
11291 if ((find_ckchs[i] = ckchs_lookup(buf->area)) != NULL) {
11292 /* only the bundle name is in the tree and you should
11293 * never update a bundle name, only a filename */
11294 if (bundle < 0 && find_ckchs[i]->multi) {
11295 /* we tried to look for a non-bundle and we found a bundle */
11296 memprintf(&err, "%s%s is a multi-cert bundle. Try updating %s.{dsa,rsa,ecdsa}\n",
11297 err ? err : "", args[3], args[3]);
11298 errcode |= ERR_ALERT | ERR_FATAL;
11299 goto end;
11300 }
William Lallemand3246d942019-11-04 14:02:11 +010011301 /* If we want a bundle but this is not a bundle
11302 * example: When you try to update <file>.rsa, but
11303 * <file> is a regular file */
11304 if (bundle >= 0 && find_ckchs[i]->multi == 0) {
11305 find_ckchs[i] = NULL;
11306 break;
11307 }
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011308 }
11309#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
11310 {
Emmanuel Hocdet40f2f1e2019-10-30 17:31:28 +010011311 char *end;
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011312 int j;
11313
11314 /* check if it was used in a bundle by removing the
11315 * .dsa/.rsa/.ecdsa at the end of the filename */
11316 end = strrchr(buf->area, '.');
Emmanuel Hocdet40f2f1e2019-10-30 17:31:28 +010011317 for (j = 0; end && j < SSL_SOCK_NUM_KEYTYPES; j++) {
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011318 if (!strcmp(end + 1, SSL_SOCK_KEYTYPE_NAMES[j])) {
11319 bundle = j; /* keep the type of certificate so we insert it at the right place */
11320 *end = '\0'; /* it's a bundle let's end the string*/
11321 break;
11322 }
11323 }
William Lallemand37031b82019-11-04 13:38:53 +010011324 if (bundle < 0) /* we didn't find a bundle extension */
11325 break;
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011326 }
William Lallemand963b2e72019-10-14 11:38:36 +020011327#else
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011328 /* bundles are not supported here, so we don't need to lookup again */
11329 break;
William Lallemand963b2e72019-10-14 11:38:36 +020011330#endif
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011331 }
11332
11333 if (find_ckchs[0] && find_ckchs[1]) {
11334 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",
11335 err ? err : "", find_ckchs[0]->path, find_ckchs[1]->path);
11336 errcode |= ERR_ALERT | ERR_FATAL;
11337 goto end;
11338 }
11339
11340 appctx->ctx.ssl.old_ckchs = find_ckchs[0] ? find_ckchs[0] : find_ckchs[1];
William Lallemand150bfa82019-09-19 17:12:49 +020011341 }
11342
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011343 if (!appctx->ctx.ssl.old_ckchs) {
11344 memprintf(&err, "%sCan't replace a certificate which is not referenced by the configuration!\n",
William Lallemand150bfa82019-09-19 17:12:49 +020011345 err ? err : "");
Emeric Brunf69ed1d2019-10-17 11:56:56 +020011346 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemand8f840d72019-10-23 10:53:05 +020011347 goto end;
William Lallemand150bfa82019-09-19 17:12:49 +020011348 }
11349
William Lallemand8a7fdf02019-11-04 10:59:32 +010011350 if (!appctx->ctx.ssl.path) {
11351 /* this is a new transaction, set the path of the transaction */
11352 appctx->ctx.ssl.path = strdup(appctx->ctx.ssl.old_ckchs->path);
11353 if (!appctx->ctx.ssl.path) {
11354 memprintf(&err, "%sCan't allocate memory\n", err ? err : "");
11355 errcode |= ERR_ALERT | ERR_FATAL;
11356 goto end;
11357 }
11358 }
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011359
11360 old_ckchs = appctx->ctx.ssl.old_ckchs;
11361
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011362 /* duplicate the ckch store */
11363 new_ckchs = ckchs_dup(old_ckchs);
11364 if (!new_ckchs) {
11365 memprintf(&err, "%sCannot allocate memory!\n",
11366 err ? err : "");
11367 errcode |= ERR_ALERT | ERR_FATAL;
11368 goto end;
11369 }
11370
11371 if (!new_ckchs->multi)
11372 ckch = new_ckchs->ckch;
11373 else
11374 ckch = &new_ckchs->ckch[bundle];
11375
11376 /* appply the change on the duplicate */
11377 if (cert_exts[type].load(buf->area, payload, ckch, &err) != 0) {
11378 memprintf(&err, "%sCan't load the payload\n", err ? err : "");
11379 errcode |= ERR_ALERT | ERR_FATAL;
11380 goto end;
11381 }
11382
11383 appctx->ctx.ssl.new_ckchs = new_ckchs;
11384
11385 /* we succeed, we can save the ckchs in the transaction */
11386
11387 /* if there wasn't a transaction, update the old ckchs */
William Dauchyc8bb1532019-11-24 15:04:20 +010011388 if (!ckchs_transaction.old_ckchs) {
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011389 ckchs_transaction.old_ckchs = appctx->ctx.ssl.old_ckchs;
11390 ckchs_transaction.path = appctx->ctx.ssl.path;
11391 err = memprintf(&err, "Transaction created for certificate %s!\n", ckchs_transaction.path);
11392 } else {
11393 err = memprintf(&err, "Transaction updated for certificate %s!\n", ckchs_transaction.path);
11394
11395 }
11396
11397 /* free the previous ckchs if there was a transaction */
11398 ckchs_free(ckchs_transaction.new_ckchs);
11399
11400 ckchs_transaction.new_ckchs = appctx->ctx.ssl.new_ckchs;
11401
11402
William Lallemand8f840d72019-10-23 10:53:05 +020011403 /* creates the SNI ctxs later in the IO handler */
William Lallemand150bfa82019-09-19 17:12:49 +020011404
William Lallemand8f840d72019-10-23 10:53:05 +020011405end:
11406 free_trash_chunk(buf);
William Lallemand150bfa82019-09-19 17:12:49 +020011407
Emeric Brunf69ed1d2019-10-17 11:56:56 +020011408 if (errcode & ERR_CODE) {
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011409
11410 ckchs_free(appctx->ctx.ssl.new_ckchs);
11411 appctx->ctx.ssl.new_ckchs = NULL;
11412
11413 appctx->ctx.ssl.old_ckchs = NULL;
11414
11415 free(appctx->ctx.ssl.path);
11416 appctx->ctx.ssl.path = NULL;
11417
11418 HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
William Lallemand44b35322019-10-17 16:28:40 +020011419 return cli_dynerr(appctx, memprintf(&err, "%sCan't update %s!\n", err ? err : "", args[3]));
William Lallemand430413e2019-10-28 14:30:47 +010011420 } else {
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011421
11422 HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
11423 return cli_dynmsg(appctx, LOG_NOTICE, err);
William Lallemand430413e2019-10-28 14:30:47 +010011424 }
William Lallemand8f840d72019-10-23 10:53:05 +020011425 /* TODO: handle the ERR_WARN which are not handled because of the io_handler */
William Lallemand150bfa82019-09-19 17:12:49 +020011426}
11427
William Lallemand0bc9c8a2019-11-19 15:51:51 +010011428/* parsing function of 'abort ssl cert' */
11429static int cli_parse_abort_cert(char **args, char *payload, struct appctx *appctx, void *private)
11430{
11431 char *err = NULL;
11432
William Lallemand230662a2019-12-03 13:32:54 +010011433 if (!cli_has_level(appctx, ACCESS_LVL_ADMIN))
11434 return 1;
11435
William Lallemand0bc9c8a2019-11-19 15:51:51 +010011436 if (!*args[3])
11437 return cli_err(appctx, "'abort ssl cert' expects a filename\n");
11438
11439 /* The operations on the CKCH architecture are locked so we can
11440 * manipulate ckch_store and ckch_inst */
11441 if (HA_SPIN_TRYLOCK(CKCH_LOCK, &ckch_lock))
11442 return cli_err(appctx, "Can't abort!\nOperations on certificates are currently locked!\n");
11443
11444 if (!ckchs_transaction.path) {
11445 memprintf(&err, "No ongoing transaction!\n");
11446 goto error;
11447 }
11448
11449 if (strcmp(ckchs_transaction.path, args[3]) != 0) {
11450 memprintf(&err, "The ongoing transaction is about '%s' but you are trying to abort a transaction for '%s'\n", ckchs_transaction.path, args[3]);
11451 goto error;
11452 }
11453
11454 /* Only free the ckchs there, because the SNI and instances were not generated yet */
11455 ckchs_free(ckchs_transaction.new_ckchs);
11456 ckchs_transaction.new_ckchs = NULL;
11457 ckchs_free(ckchs_transaction.old_ckchs);
11458 ckchs_transaction.old_ckchs = NULL;
11459 free(ckchs_transaction.path);
11460 ckchs_transaction.path = NULL;
11461
11462 HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
11463
11464 err = memprintf(&err, "Transaction aborted for certificate '%s'!\n", args[3]);
11465 return cli_dynmsg(appctx, LOG_NOTICE, err);
11466
11467error:
11468 HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
11469
11470 return cli_dynerr(appctx, err);
11471}
11472
Aurélien Nephtaliabbf6072018-04-18 13:26:46 +020011473static int cli_parse_set_ocspresponse(char **args, char *payload, struct appctx *appctx, void *private)
William Lallemand32af2032016-10-29 18:09:35 +020011474{
11475#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
11476 char *err = NULL;
Willy Tarreau1c913e42018-08-22 05:26:57 +020011477 int i, j, ret;
Aurélien Nephtali1e0867c2018-04-18 14:04:58 +020011478
11479 if (!payload)
11480 payload = args[3];
William Lallemand32af2032016-10-29 18:09:35 +020011481
11482 /* Expect one parameter: the new response in base64 encoding */
Willy Tarreau9d008692019-08-09 11:21:01 +020011483 if (!*payload)
11484 return cli_err(appctx, "'set ssl ocsp-response' expects response in base64 encoding.\n");
Aurélien Nephtali1e0867c2018-04-18 14:04:58 +020011485
11486 /* remove \r and \n from the payload */
11487 for (i = 0, j = 0; payload[i]; i++) {
11488 if (payload[i] == '\r' || payload[i] == '\n')
11489 continue;
11490 payload[j++] = payload[i];
11491 }
11492 payload[j] = 0;
William Lallemand32af2032016-10-29 18:09:35 +020011493
Willy Tarreau1c913e42018-08-22 05:26:57 +020011494 ret = base64dec(payload, j, trash.area, trash.size);
Willy Tarreau9d008692019-08-09 11:21:01 +020011495 if (ret < 0)
11496 return cli_err(appctx, "'set ssl ocsp-response' received invalid base64 encoded response.\n");
William Lallemand32af2032016-10-29 18:09:35 +020011497
Willy Tarreau1c913e42018-08-22 05:26:57 +020011498 trash.data = ret;
William Lallemand32af2032016-10-29 18:09:35 +020011499 if (ssl_sock_update_ocsp_response(&trash, &err)) {
Willy Tarreau9d008692019-08-09 11:21:01 +020011500 if (err)
11501 return cli_dynerr(appctx, memprintf(&err, "%s.\n", err));
11502 else
11503 return cli_err(appctx, "Failed to update OCSP response.\n");
William Lallemand32af2032016-10-29 18:09:35 +020011504 }
Willy Tarreau9d008692019-08-09 11:21:01 +020011505
11506 return cli_msg(appctx, LOG_INFO, "OCSP Response updated!\n");
William Lallemand32af2032016-10-29 18:09:35 +020011507#else
Willy Tarreau9d008692019-08-09 11:21:01 +020011508 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 +020011509#endif
11510
Nenad Merdanovicc31499d2019-03-23 11:00:32 +010011511}
11512
Willy Tarreau86a394e2019-05-09 14:15:32 +020011513#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000100fL)
Nenad Merdanovicc31499d2019-03-23 11:00:32 +010011514static inline int sample_conv_var2smp_str(const struct arg *arg, struct sample *smp)
11515{
11516 switch (arg->type) {
11517 case ARGT_STR:
11518 smp->data.type = SMP_T_STR;
11519 smp->data.u.str = arg->data.str;
11520 return 1;
11521 case ARGT_VAR:
11522 if (!vars_get_by_desc(&arg->data.var, smp))
11523 return 0;
11524 if (!sample_casts[smp->data.type][SMP_T_STR])
11525 return 0;
11526 if (!sample_casts[smp->data.type][SMP_T_STR](smp))
11527 return 0;
11528 return 1;
11529 default:
11530 return 0;
11531 }
11532}
11533
11534static int check_aes_gcm(struct arg *args, struct sample_conv *conv,
11535 const char *file, int line, char **err)
11536{
11537 switch(args[0].data.sint) {
11538 case 128:
11539 case 192:
11540 case 256:
11541 break;
11542 default:
11543 memprintf(err, "key size must be 128, 192 or 256 (bits).");
11544 return 0;
11545 }
11546 /* Try to decode a variable. */
11547 vars_check_arg(&args[1], NULL);
11548 vars_check_arg(&args[2], NULL);
11549 vars_check_arg(&args[3], NULL);
11550 return 1;
11551}
11552
11553/* Arguements: AES size in bits, nonce, key, tag. The last three arguments are base64 encoded */
11554static int sample_conv_aes_gcm_dec(const struct arg *arg_p, struct sample *smp, void *private)
11555{
11556 struct sample nonce, key, aead_tag;
11557 struct buffer *smp_trash, *smp_trash_alloc;
11558 EVP_CIPHER_CTX *ctx;
11559 int dec_size, ret;
11560
11561 smp_set_owner(&nonce, smp->px, smp->sess, smp->strm, smp->opt);
11562 if (!sample_conv_var2smp_str(&arg_p[1], &nonce))
11563 return 0;
11564
11565 smp_set_owner(&key, smp->px, smp->sess, smp->strm, smp->opt);
11566 if (!sample_conv_var2smp_str(&arg_p[2], &key))
11567 return 0;
11568
11569 smp_set_owner(&aead_tag, smp->px, smp->sess, smp->strm, smp->opt);
11570 if (!sample_conv_var2smp_str(&arg_p[3], &aead_tag))
11571 return 0;
11572
11573 smp_trash = get_trash_chunk();
11574 smp_trash_alloc = alloc_trash_chunk();
11575 if (!smp_trash_alloc)
11576 return 0;
11577
11578 ctx = EVP_CIPHER_CTX_new();
11579
11580 if (!ctx)
11581 goto err;
11582
11583 dec_size = base64dec(nonce.data.u.str.area, nonce.data.u.str.data, smp_trash->area, smp_trash->size);
11584 if (dec_size < 0)
11585 goto err;
11586 smp_trash->data = dec_size;
11587
11588 /* Set cipher type and mode */
11589 switch(arg_p[0].data.sint) {
11590 case 128:
11591 EVP_DecryptInit_ex(ctx, EVP_aes_128_gcm(), NULL, NULL, NULL);
11592 break;
11593 case 192:
11594 EVP_DecryptInit_ex(ctx, EVP_aes_192_gcm(), NULL, NULL, NULL);
11595 break;
11596 case 256:
11597 EVP_DecryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL);
11598 break;
11599 }
11600
11601 EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, smp_trash->data, NULL);
11602
11603 /* Initialise IV */
11604 if(!EVP_DecryptInit_ex(ctx, NULL, NULL, NULL, (unsigned char *) smp_trash->area))
11605 goto err;
11606
11607 dec_size = base64dec(key.data.u.str.area, key.data.u.str.data, smp_trash->area, smp_trash->size);
11608 if (dec_size < 0)
11609 goto err;
11610 smp_trash->data = dec_size;
11611
11612 /* Initialise key */
11613 if (!EVP_DecryptInit_ex(ctx, NULL, NULL, (unsigned char *) smp_trash->area, NULL))
11614 goto err;
11615
11616 if (!EVP_DecryptUpdate(ctx, (unsigned char *) smp_trash->area, (int *) &smp_trash->data,
11617 (unsigned char *) smp->data.u.str.area, (int) smp->data.u.str.data))
11618 goto err;
11619
11620 dec_size = base64dec(aead_tag.data.u.str.area, aead_tag.data.u.str.data, smp_trash_alloc->area, smp_trash_alloc->size);
11621 if (dec_size < 0)
11622 goto err;
11623 smp_trash_alloc->data = dec_size;
11624 dec_size = smp_trash->data;
11625
11626 EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, smp_trash_alloc->data, (void *) smp_trash_alloc->area);
11627 ret = EVP_DecryptFinal_ex(ctx, (unsigned char *) smp_trash->area + smp_trash->data, (int *) &smp_trash->data);
11628
11629 if (ret <= 0)
11630 goto err;
11631
11632 smp->data.u.str.data = dec_size + smp_trash->data;
11633 smp->data.u.str.area = smp_trash->area;
11634 smp->data.type = SMP_T_BIN;
11635 smp->flags &= ~SMP_F_CONST;
11636 free_trash_chunk(smp_trash_alloc);
11637 return 1;
11638
11639err:
11640 free_trash_chunk(smp_trash_alloc);
11641 return 0;
William Lallemand32af2032016-10-29 18:09:35 +020011642}
Nenad Merdanovicc31499d2019-03-23 11:00:32 +010011643# endif
William Lallemand32af2032016-10-29 18:09:35 +020011644
Elliot Otchet71f82972020-01-15 08:12:14 -050011645/* Argument validation functions */
11646
11647/* This function is used to validate the arguments passed to any "x_dn" ssl
11648 * keywords. These keywords support specifying a third parameter that must be
11649 * either empty or the value "rfc2253". Returns 0 on error, non-zero if OK.
11650 */
11651int val_dnfmt(struct arg *arg, char **err_msg)
11652{
11653 if (arg && arg[2].type == ARGT_STR && arg[2].data.str.data > 0 && (strcmp(arg[2].data.str.area, "rfc2253") != 0)) {
11654 memprintf(err_msg, "only rfc2253 or a blank value are currently supported as the format argument.");
11655 return 0;
11656 }
11657 return 1;
11658}
11659
William Lallemand32af2032016-10-29 18:09:35 +020011660/* register cli keywords */
11661static struct cli_kw_list cli_kws = {{ },{
11662#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
11663 { { "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 +020011664 { { "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 +020011665#endif
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +010011666 { { "set", "ssl", "ocsp-response", NULL }, NULL, cli_parse_set_ocspresponse, NULL },
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011667 { { "set", "ssl", "cert", NULL }, "set ssl cert <certfile> <payload> : replace a certificate file", cli_parse_set_cert, NULL, NULL },
11668 { { "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 +010011669 { { "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 +010011670 { { "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 +020011671 { { NULL }, NULL, NULL, NULL }
11672}};
11673
Willy Tarreau0108d902018-11-25 19:14:37 +010011674INITCALL1(STG_REGISTER, cli_register_kw, &cli_kws);
William Lallemand32af2032016-10-29 18:09:35 +020011675
Willy Tarreau7875d092012-09-10 08:20:03 +020011676/* Note: must not be declared <const> as its list will be overwritten.
11677 * Please take care of keeping this list alphabetically sorted.
11678 */
Willy Tarreaudc13c112013-06-21 23:16:39 +020011679static struct sample_fetch_kw_list sample_fetch_keywords = {ILH, {
Emeric Brun645ae792014-04-30 14:21:06 +020011680 { "ssl_bc", smp_fetch_ssl_fc, 0, NULL, SMP_T_BOOL, SMP_USE_L5SRV },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +020011681 { "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 +010011682#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Jérôme Magnine064a802018-12-03 22:21:04 +010011683 { "ssl_bc_alpn", smp_fetch_ssl_fc_alpn, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
Olivier Houchard6b77f492018-11-22 18:18:29 +010011684#endif
Emeric Brun645ae792014-04-30 14:21:06 +020011685 { "ssl_bc_cipher", smp_fetch_ssl_fc_cipher, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
Olivier Houchard6b77f492018-11-22 18:18:29 +010011686#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
11687 { "ssl_bc_npn", smp_fetch_ssl_fc_npn, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
11688#endif
Emeric Brun74f7ffa2018-02-19 16:14:12 +010011689 { "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 +020011690 { "ssl_bc_protocol", smp_fetch_ssl_fc_protocol, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
Emeric Brunb73a9b02014-04-30 18:49:19 +020011691 { "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 +020011692 { "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 +020011693#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
Emeric Brun645ae792014-04-30 14:21:06 +020011694 { "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 -040011695#endif
Emmanuel Hocdet839af572019-05-14 16:27:35 +020011696#if HA_OPENSSL_VERSION_NUMBER >= 0x10100000L
Patrick Hemmer65674662019-06-04 08:13:03 -040011697 { "ssl_bc_client_random", smp_fetch_ssl_fc_random, 0, NULL, SMP_T_BIN, SMP_USE_L5SRV },
11698 { "ssl_bc_server_random", smp_fetch_ssl_fc_random, 0, NULL, SMP_T_BIN, SMP_USE_L5SRV },
Patrick Hemmere0275472018-04-28 19:15:51 -040011699 { "ssl_bc_session_key", smp_fetch_ssl_fc_session_key, 0, NULL, SMP_T_BIN, SMP_USE_L5SRV },
11700#endif
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +020011701 { "ssl_c_ca_err", smp_fetch_ssl_c_ca_err, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
11702 { "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 +010011703 { "ssl_c_der", smp_fetch_ssl_x_der, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +020011704 { "ssl_c_err", smp_fetch_ssl_c_err, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Elliot Otchet71f82972020-01-15 08:12:14 -050011705 { "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 +020011706 { "ssl_c_key_alg", smp_fetch_ssl_x_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
11707 { "ssl_c_notafter", smp_fetch_ssl_x_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
11708 { "ssl_c_notbefore", smp_fetch_ssl_x_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
11709 { "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 -050011710 { "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 +020011711 { "ssl_c_serial", smp_fetch_ssl_x_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
11712 { "ssl_c_sha1", smp_fetch_ssl_x_sha1, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +010011713 { "ssl_c_used", smp_fetch_ssl_c_used, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +020011714 { "ssl_c_verify", smp_fetch_ssl_c_verify, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
11715 { "ssl_c_version", smp_fetch_ssl_x_version, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Emeric Brun43e79582014-10-29 19:03:26 +010011716 { "ssl_f_der", smp_fetch_ssl_x_der, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Elliot Otchet71f82972020-01-15 08:12:14 -050011717 { "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 +020011718 { "ssl_f_key_alg", smp_fetch_ssl_x_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
11719 { "ssl_f_notafter", smp_fetch_ssl_x_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
11720 { "ssl_f_notbefore", smp_fetch_ssl_x_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
11721 { "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 -050011722 { "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 +020011723 { "ssl_f_serial", smp_fetch_ssl_x_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Emeric Brun55f4fa82014-04-30 17:11:25 +020011724 { "ssl_f_sha1", smp_fetch_ssl_x_sha1, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +020011725 { "ssl_f_version", smp_fetch_ssl_x_version, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +010011726 { "ssl_fc", smp_fetch_ssl_fc, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +020011727 { "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 +010011728 { "ssl_fc_cipher", smp_fetch_ssl_fc_cipher, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +010011729 { "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 +020011730 { "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 +010011731 { "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 +020011732 { "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 +010011733#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +010011734 { "ssl_fc_npn", smp_fetch_ssl_fc_npn, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreaua33c6542012-10-15 13:19:06 +020011735#endif
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +010011736#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +010011737 { "ssl_fc_alpn", smp_fetch_ssl_fc_alpn, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreauab861d32013-04-02 02:30:41 +020011738#endif
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +010011739 { "ssl_fc_protocol", smp_fetch_ssl_fc_protocol, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreau9a1ab082019-05-09 13:26:41 +020011740#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
Emeric Brunb73a9b02014-04-30 18:49:19 +020011741 { "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 -040011742#endif
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +020011743 { "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 +020011744#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +010011745 { "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 -040011746#endif
Emmanuel Hocdet839af572019-05-14 16:27:35 +020011747#if HA_OPENSSL_VERSION_NUMBER >= 0x10100000L
Patrick Hemmer65674662019-06-04 08:13:03 -040011748 { "ssl_fc_client_random", smp_fetch_ssl_fc_random, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
11749 { "ssl_fc_server_random", smp_fetch_ssl_fc_random, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Patrick Hemmere0275472018-04-28 19:15:51 -040011750 { "ssl_fc_session_key", smp_fetch_ssl_fc_session_key, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
11751#endif
Patrick Hemmer41966772018-04-28 19:15:48 -040011752#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +010011753 { "ssl_fc_sni", smp_fetch_ssl_fc_sni, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Patrick Hemmer41966772018-04-28 19:15:48 -040011754#endif
Thierry FOURNIER5bf77322017-02-25 12:45:22 +010011755 { "ssl_fc_cipherlist_bin", smp_fetch_ssl_fc_cl_bin, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
11756 { "ssl_fc_cipherlist_hex", smp_fetch_ssl_fc_cl_hex, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
11757 { "ssl_fc_cipherlist_str", smp_fetch_ssl_fc_cl_str, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
11758 { "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 +020011759 { NULL, NULL, 0, 0, 0 },
11760}};
11761
Willy Tarreau0108d902018-11-25 19:14:37 +010011762INITCALL1(STG_REGISTER, sample_register_fetches, &sample_fetch_keywords);
11763
Willy Tarreau7875d092012-09-10 08:20:03 +020011764/* Note: must not be declared <const> as its list will be overwritten.
11765 * Please take care of keeping this list alphabetically sorted.
11766 */
Willy Tarreaudc13c112013-06-21 23:16:39 +020011767static struct acl_kw_list acl_kws = {ILH, {
Thierry FOURNIERc5a4e982014-03-05 16:07:08 +010011768 { "ssl_fc_sni_end", "ssl_fc_sni", PAT_MATCH_END },
11769 { "ssl_fc_sni_reg", "ssl_fc_sni", PAT_MATCH_REG },
Willy Tarreau8ed669b2013-01-11 15:49:37 +010011770 { /* END */ },
Willy Tarreau7875d092012-09-10 08:20:03 +020011771}};
11772
Willy Tarreau0108d902018-11-25 19:14:37 +010011773INITCALL1(STG_REGISTER, acl_register_keywords, &acl_kws);
11774
Willy Tarreau79eeafa2012-09-14 07:53:05 +020011775/* Note: must not be declared <const> as its list will be overwritten.
11776 * Please take care of keeping this list alphabetically sorted, doing so helps
11777 * all code contributors.
11778 * Optional keywords are also declared with a NULL ->parse() function so that
11779 * the config parser can report an appropriate error when a known keyword was
11780 * not enabled.
11781 */
Emmanuel Hocdet98263292016-12-29 18:26:15 +010011782static struct ssl_bind_kw ssl_bind_kws[] = {
Olivier Houchardc2aae742017-09-22 18:26:28 +020011783 { "allow-0rtt", ssl_bind_parse_allow_0rtt, 0 }, /* allow 0-RTT */
Emmanuel Hocdet98263292016-12-29 18:26:15 +010011784 { "alpn", ssl_bind_parse_alpn, 1 }, /* set ALPN supported protocols */
Emmanuel Hocdet842e94e2019-12-16 16:39:17 +010011785 { "ca-file", ssl_bind_parse_ca_file, 1 }, /* set CAfile to process ca-names and verify on client cert */
11786 { "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 +010011787 { "ciphers", ssl_bind_parse_ciphers, 1 }, /* set SSL cipher suite */
Emmanuel Hocdet839af572019-05-14 16:27:35 +020011788#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +020011789 { "ciphersuites", ssl_bind_parse_ciphersuites, 1 }, /* set TLS 1.3 cipher suite */
11790#endif
Emmanuel Hocdet98263292016-12-29 18:26:15 +010011791 { "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 +010011792 { "curves", ssl_bind_parse_curves, 1 }, /* set SSL curve suite */
Emmanuel Hocdet98263292016-12-29 18:26:15 +010011793 { "ecdhe", ssl_bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +020011794 { "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 +010011795 { "npn", ssl_bind_parse_npn, 1 }, /* set NPN supported protocols */
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +020011796 { "ssl-min-ver", ssl_bind_parse_tls_method_minmax,1 }, /* minimum version */
11797 { "ssl-max-ver", ssl_bind_parse_tls_method_minmax,1 }, /* maximum version */
Emmanuel Hocdet98263292016-12-29 18:26:15 +010011798 { "verify", ssl_bind_parse_verify, 1 }, /* set SSL verify method */
11799 { NULL, NULL, 0 },
11800};
11801
Willy Tarreau0108d902018-11-25 19:14:37 +010011802/* no initcall for ssl_bind_kws, these ones are parsed in the parser loop */
11803
Willy Tarreau51fb7652012-09-18 18:24:39 +020011804static struct bind_kw_list bind_kws = { "SSL", { }, {
Olivier Houchardc2aae742017-09-22 18:26:28 +020011805 { "allow-0rtt", bind_parse_allow_0rtt, 0 }, /* Allow 0RTT */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +020011806 { "alpn", bind_parse_alpn, 1 }, /* set ALPN supported protocols */
Emmanuel Hocdet842e94e2019-12-16 16:39:17 +010011807 { "ca-file", bind_parse_ca_file, 1 }, /* set CAfile to process ca-names and verify on client cert */
11808 { "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 +020011809 { "ca-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ignore on verify depth > 0 */
11810 { "ca-sign-file", bind_parse_ca_sign_file, 1 }, /* set CAFile used to generate and sign server certs */
11811 { "ca-sign-pass", bind_parse_ca_sign_pass, 1 }, /* set CAKey passphrase */
11812 { "ciphers", bind_parse_ciphers, 1 }, /* set SSL cipher suite */
Emmanuel Hocdet839af572019-05-14 16:27:35 +020011813#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +020011814 { "ciphersuites", bind_parse_ciphersuites, 1 }, /* set TLS 1.3 cipher suite */
11815#endif
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +020011816 { "crl-file", bind_parse_crl_file, 1 }, /* set certificat revocation list file use on client cert verify */
11817 { "crt", bind_parse_crt, 1 }, /* load SSL certificates from this location */
11818 { "crt-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ingore on verify depth == 0 */
11819 { "crt-list", bind_parse_crt_list, 1 }, /* load a list of crt from this location */
11820 { "curves", bind_parse_curves, 1 }, /* set SSL curve suite */
11821 { "ecdhe", bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
11822 { "force-sslv3", bind_parse_tls_method_options, 0 }, /* force SSLv3 */
11823 { "force-tlsv10", bind_parse_tls_method_options, 0 }, /* force TLSv10 */
11824 { "force-tlsv11", bind_parse_tls_method_options, 0 }, /* force TLSv11 */
11825 { "force-tlsv12", bind_parse_tls_method_options, 0 }, /* force TLSv12 */
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +020011826 { "force-tlsv13", bind_parse_tls_method_options, 0 }, /* force TLSv13 */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +020011827 { "generate-certificates", bind_parse_generate_certs, 0 }, /* enable the server certificates generation */
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +020011828 { "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 +020011829 { "no-sslv3", bind_parse_tls_method_options, 0 }, /* disable SSLv3 */
11830 { "no-tlsv10", bind_parse_tls_method_options, 0 }, /* disable TLSv10 */
11831 { "no-tlsv11", bind_parse_tls_method_options, 0 }, /* disable TLSv11 */
11832 { "no-tlsv12", bind_parse_tls_method_options, 0 }, /* disable TLSv12 */
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +020011833 { "no-tlsv13", bind_parse_tls_method_options, 0 }, /* disable TLSv13 */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +020011834 { "no-tls-tickets", bind_parse_no_tls_tickets, 0 }, /* disable session resumption tickets */
11835 { "ssl", bind_parse_ssl, 0 }, /* enable SSL processing */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +020011836 { "ssl-min-ver", bind_parse_tls_method_minmax, 1 }, /* minimum version */
11837 { "ssl-max-ver", bind_parse_tls_method_minmax, 1 }, /* maximum version */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +020011838 { "strict-sni", bind_parse_strict_sni, 0 }, /* refuse negotiation if sni doesn't match a certificate */
11839 { "tls-ticket-keys", bind_parse_tls_ticket_keys, 1 }, /* set file to load TLS ticket keys from */
11840 { "verify", bind_parse_verify, 1 }, /* set SSL verify method */
11841 { "npn", bind_parse_npn, 1 }, /* set NPN supported protocols */
11842 { "prefer-client-ciphers", bind_parse_pcc, 0 }, /* prefer client ciphers */
Willy Tarreau79eeafa2012-09-14 07:53:05 +020011843 { NULL, NULL, 0 },
11844}};
Emeric Brun46591952012-05-18 15:47:34 +020011845
Willy Tarreau0108d902018-11-25 19:14:37 +010011846INITCALL1(STG_REGISTER, bind_register_keywords, &bind_kws);
11847
Willy Tarreau92faadf2012-10-10 23:04:25 +020011848/* Note: must not be declared <const> as its list will be overwritten.
11849 * Please take care of keeping this list alphabetically sorted, doing so helps
11850 * all code contributors.
11851 * Optional keywords are also declared with a NULL ->parse() function so that
11852 * the config parser can report an appropriate error when a known keyword was
11853 * not enabled.
11854 */
11855static struct srv_kw_list srv_kws = { "SSL", { }, {
Olivier Houchard522eea72017-11-03 16:27:47 +010011856 { "allow-0rtt", srv_parse_allow_0rtt, 0, 1 }, /* Allow using early data on this server */
Olivier Houchardc7566002018-11-20 23:33:50 +010011857 { "alpn", srv_parse_alpn, 1, 1 }, /* Set ALPN supported protocols */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +020011858 { "ca-file", srv_parse_ca_file, 1, 1 }, /* set CAfile to process verify server cert */
Olivier Houchard92150142018-12-21 19:47:01 +010011859 { "check-alpn", srv_parse_alpn, 1, 1 }, /* Set ALPN used for checks */
Olivier Houchard9130a962017-10-17 17:33:43 +020011860 { "check-sni", srv_parse_check_sni, 1, 1 }, /* set SNI */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +020011861 { "check-ssl", srv_parse_check_ssl, 0, 1 }, /* enable SSL for health checks */
11862 { "ciphers", srv_parse_ciphers, 1, 1 }, /* select the cipher suite */
Emmanuel Hocdet839af572019-05-14 16:27:35 +020011863#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +020011864 { "ciphersuites", srv_parse_ciphersuites, 1, 1 }, /* select the cipher suite */
11865#endif
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +020011866 { "crl-file", srv_parse_crl_file, 1, 1 }, /* set certificate revocation list file use on server cert verify */
11867 { "crt", srv_parse_crt, 1, 1 }, /* set client certificate */
11868 { "force-sslv3", srv_parse_tls_method_options, 0, 1 }, /* force SSLv3 */
11869 { "force-tlsv10", srv_parse_tls_method_options, 0, 1 }, /* force TLSv10 */
11870 { "force-tlsv11", srv_parse_tls_method_options, 0, 1 }, /* force TLSv11 */
11871 { "force-tlsv12", srv_parse_tls_method_options, 0, 1 }, /* force TLSv12 */
11872 { "force-tlsv13", srv_parse_tls_method_options, 0, 1 }, /* force TLSv13 */
11873 { "no-check-ssl", srv_parse_no_check_ssl, 0, 1 }, /* disable SSL for health checks */
11874 { "no-send-proxy-v2-ssl", srv_parse_no_send_proxy_ssl, 0, 1 }, /* do not send PROXY protocol header v2 with SSL info */
11875 { "no-send-proxy-v2-ssl-cn", srv_parse_no_send_proxy_cn, 0, 1 }, /* do not send PROXY protocol header v2 with CN */
11876 { "no-ssl", srv_parse_no_ssl, 0, 1 }, /* disable SSL processing */
11877 { "no-ssl-reuse", srv_parse_no_ssl_reuse, 0, 1 }, /* disable session reuse */
11878 { "no-sslv3", srv_parse_tls_method_options, 0, 0 }, /* disable SSLv3 */
11879 { "no-tlsv10", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv10 */
11880 { "no-tlsv11", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv11 */
11881 { "no-tlsv12", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv12 */
11882 { "no-tlsv13", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv13 */
11883 { "no-tls-tickets", srv_parse_no_tls_tickets, 0, 1 }, /* disable session resumption tickets */
Olivier Houchardc7566002018-11-20 23:33:50 +010011884 { "npn", srv_parse_npn, 1, 1 }, /* Set NPN supported protocols */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +020011885 { "send-proxy-v2-ssl", srv_parse_send_proxy_ssl, 0, 1 }, /* send PROXY protocol header v2 with SSL info */
11886 { "send-proxy-v2-ssl-cn", srv_parse_send_proxy_cn, 0, 1 }, /* send PROXY protocol header v2 with CN */
11887 { "sni", srv_parse_sni, 1, 1 }, /* send SNI extension */
11888 { "ssl", srv_parse_ssl, 0, 1 }, /* enable SSL processing */
11889 { "ssl-min-ver", srv_parse_tls_method_minmax, 1, 1 }, /* minimum version */
11890 { "ssl-max-ver", srv_parse_tls_method_minmax, 1, 1 }, /* maximum version */
11891 { "ssl-reuse", srv_parse_ssl_reuse, 0, 1 }, /* enable session reuse */
11892 { "tls-tickets", srv_parse_tls_tickets, 0, 1 }, /* enable session resumption tickets */
11893 { "verify", srv_parse_verify, 1, 1 }, /* set SSL verify method */
11894 { "verifyhost", srv_parse_verifyhost, 1, 1 }, /* require that SSL cert verifies for hostname */
Willy Tarreau92faadf2012-10-10 23:04:25 +020011895 { NULL, NULL, 0, 0 },
11896}};
11897
Willy Tarreau0108d902018-11-25 19:14:37 +010011898INITCALL1(STG_REGISTER, srv_register_keywords, &srv_kws);
11899
Emeric Brun2c86cbf2014-10-30 15:56:50 +010011900static struct cfg_kw_list cfg_kws = {ILH, {
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +010011901 { CFG_GLOBAL, "ca-base", ssl_parse_global_ca_crt_base },
11902 { CFG_GLOBAL, "crt-base", ssl_parse_global_ca_crt_base },
Emmanuel Hocdet70df7bf2019-01-04 11:08:20 +010011903 { CFG_GLOBAL, "issuers-chain-path", ssl_load_global_issuers_from_path },
Willy Tarreau0bea58d2016-12-21 23:17:25 +010011904 { CFG_GLOBAL, "maxsslconn", ssl_parse_global_int },
Emeric Brun2c86cbf2014-10-30 15:56:50 +010011905 { CFG_GLOBAL, "ssl-default-bind-options", ssl_parse_default_bind_options },
11906 { CFG_GLOBAL, "ssl-default-server-options", ssl_parse_default_server_options },
Willy Tarreau14e36a12016-12-21 23:28:13 +010011907#ifndef OPENSSL_NO_DH
11908 { CFG_GLOBAL, "ssl-dh-param-file", ssl_parse_global_dh_param_file },
11909#endif
Grant Zhangfa6c7ee2017-01-14 01:42:15 +000011910 { CFG_GLOBAL, "ssl-mode-async", ssl_parse_global_ssl_async },
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020011911#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +000011912 { CFG_GLOBAL, "ssl-engine", ssl_parse_global_ssl_engine },
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020011913#endif
Willy Tarreau9ceda382016-12-21 23:13:03 +010011914 { CFG_GLOBAL, "tune.ssl.cachesize", ssl_parse_global_int },
11915#ifndef OPENSSL_NO_DH
11916 { CFG_GLOBAL, "tune.ssl.default-dh-param", ssl_parse_global_default_dh },
11917#endif
11918 { CFG_GLOBAL, "tune.ssl.force-private-cache", ssl_parse_global_private_cache },
11919 { CFG_GLOBAL, "tune.ssl.lifetime", ssl_parse_global_lifetime },
11920 { CFG_GLOBAL, "tune.ssl.maxrecord", ssl_parse_global_int },
11921 { CFG_GLOBAL, "tune.ssl.ssl-ctx-cache-size", ssl_parse_global_int },
Thierry FOURNIER5bf77322017-02-25 12:45:22 +010011922 { CFG_GLOBAL, "tune.ssl.capture-cipherlist-size", ssl_parse_global_capture_cipherlist },
Willy Tarreauf22e9682016-12-21 23:23:19 +010011923 { CFG_GLOBAL, "ssl-default-bind-ciphers", ssl_parse_global_ciphers },
11924 { CFG_GLOBAL, "ssl-default-server-ciphers", ssl_parse_global_ciphers },
Emmanuel Hocdet839af572019-05-14 16:27:35 +020011925#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +020011926 { CFG_GLOBAL, "ssl-default-bind-ciphersuites", ssl_parse_global_ciphersuites },
11927 { CFG_GLOBAL, "ssl-default-server-ciphersuites", ssl_parse_global_ciphersuites },
11928#endif
William Lallemand3af48e72020-02-03 17:15:52 +010011929 { CFG_GLOBAL, "ssl-load-extra-files", ssl_parse_global_extra_files },
Emeric Brun2c86cbf2014-10-30 15:56:50 +010011930 { 0, NULL, NULL },
11931}};
11932
Willy Tarreau0108d902018-11-25 19:14:37 +010011933INITCALL1(STG_REGISTER, cfg_register_keywords, &cfg_kws);
11934
Nenad Merdanovicc31499d2019-03-23 11:00:32 +010011935/* Note: must not be declared <const> as its list will be overwritten */
11936static struct sample_conv_kw_list conv_kws = {ILH, {
Willy Tarreau86a394e2019-05-09 14:15:32 +020011937#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000100fL)
Nenad Merdanovicc31499d2019-03-23 11:00:32 +010011938 { "aes_gcm_dec", sample_conv_aes_gcm_dec, ARG4(4,SINT,STR,STR,STR), check_aes_gcm, SMP_T_BIN, SMP_T_BIN },
11939#endif
11940 { NULL, NULL, 0, 0, 0 },
11941}};
11942
11943INITCALL1(STG_REGISTER, sample_register_convs, &conv_kws);
11944
Willy Tarreauf7bc57c2012-10-03 00:19:48 +020011945/* transport-layer operations for SSL sockets */
Willy Tarreaud9f5cca2016-12-22 21:08:52 +010011946static struct xprt_ops ssl_sock = {
Emeric Brun46591952012-05-18 15:47:34 +020011947 .snd_buf = ssl_sock_from_buf,
11948 .rcv_buf = ssl_sock_to_buf,
Olivier Houcharddf357842019-03-21 16:30:07 +010011949 .subscribe = ssl_subscribe,
11950 .unsubscribe = ssl_unsubscribe,
Olivier Houchard5149b592019-05-23 17:47:36 +020011951 .remove_xprt = ssl_remove_xprt,
Olivier Houchard2e055482019-05-27 19:50:12 +020011952 .add_xprt = ssl_add_xprt,
Emeric Brun46591952012-05-18 15:47:34 +020011953 .rcv_pipe = NULL,
11954 .snd_pipe = NULL,
11955 .shutr = NULL,
11956 .shutw = ssl_sock_shutw,
11957 .close = ssl_sock_close,
11958 .init = ssl_sock_init,
Willy Tarreau55d37912016-12-21 23:38:39 +010011959 .prepare_bind_conf = ssl_sock_prepare_bind_conf,
Willy Tarreau795cdab2016-12-22 17:30:54 +010011960 .destroy_bind_conf = ssl_sock_destroy_bind_conf,
Willy Tarreau17d45382016-12-22 21:16:08 +010011961 .prepare_srv = ssl_sock_prepare_srv_ctx,
11962 .destroy_srv = ssl_sock_free_srv_ctx,
Willy Tarreau8743f7e2016-12-04 18:44:29 +010011963 .get_alpn = ssl_sock_get_alpn,
Willy Tarreau8e0bb0a2016-11-24 16:58:12 +010011964 .name = "SSL",
Emeric Brun46591952012-05-18 15:47:34 +020011965};
11966
Olivier Houchardccaa7de2017-10-02 11:51:03 +020011967enum act_return ssl_action_wait_for_hs(struct act_rule *rule, struct proxy *px,
11968 struct session *sess, struct stream *s, int flags)
11969{
11970 struct connection *conn;
Olivier Houchard6fa63d92017-11-27 18:41:32 +010011971 struct conn_stream *cs;
Olivier Houchardccaa7de2017-10-02 11:51:03 +020011972
11973 conn = objt_conn(sess->origin);
Olivier Houchard6fa63d92017-11-27 18:41:32 +010011974 cs = objt_cs(s->si[0].end);
Olivier Houchardccaa7de2017-10-02 11:51:03 +020011975
Olivier Houchard6fa63d92017-11-27 18:41:32 +010011976 if (conn && cs) {
Olivier Houchardccaa7de2017-10-02 11:51:03 +020011977 if (conn->flags & (CO_FL_EARLY_SSL_HS | CO_FL_SSL_WAIT_HS)) {
Olivier Houchard6fa63d92017-11-27 18:41:32 +010011978 cs->flags |= CS_FL_WAIT_FOR_HS;
Olivier Houchardccaa7de2017-10-02 11:51:03 +020011979 s->req.flags |= CF_READ_NULL;
11980 return ACT_RET_YIELD;
11981 }
11982 }
11983 return (ACT_RET_CONT);
11984}
11985
11986static enum act_parse_ret ssl_parse_wait_for_hs(const char **args, int *orig_arg, struct proxy *px, struct act_rule *rule, char **err)
11987{
11988 rule->action_ptr = ssl_action_wait_for_hs;
11989
11990 return ACT_RET_PRS_OK;
11991}
11992
11993static struct action_kw_list http_req_actions = {ILH, {
11994 { "wait-for-handshake", ssl_parse_wait_for_hs },
11995 { /* END */ }
11996}};
11997
Willy Tarreau0108d902018-11-25 19:14:37 +010011998INITCALL1(STG_REGISTER, http_req_keywords_register, &http_req_actions);
11999
Willy Tarreau5db847a2019-05-09 14:13:35 +020012000#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +010012001
12002static void ssl_sock_sctl_free_func(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, long argl, void *argp)
12003{
12004 if (ptr) {
12005 chunk_destroy(ptr);
12006 free(ptr);
12007 }
12008}
12009
12010#endif
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +010012011static void ssl_sock_capture_free_func(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, long argl, void *argp)
12012{
Willy Tarreaubafbe012017-11-24 17:34:44 +010012013 pool_free(pool_head_ssl_capture, ptr);
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +010012014}
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +010012015
Emeric Brun46591952012-05-18 15:47:34 +020012016__attribute__((constructor))
Willy Tarreau92faadf2012-10-10 23:04:25 +020012017static void __ssl_sock_init(void)
12018{
Ilya Shipitsin0590f442019-05-25 19:30:50 +050012019#if (!defined(OPENSSL_NO_COMP) && !defined(SSL_OP_NO_COMPRESSION))
Emeric Brun46591952012-05-18 15:47:34 +020012020 STACK_OF(SSL_COMP)* cm;
Ilya Shipitsine242f3d2019-05-25 03:38:14 +050012021 int n;
Ilya Shipitsin0590f442019-05-25 19:30:50 +050012022#endif
Emeric Brun46591952012-05-18 15:47:34 +020012023
Willy Tarreauef934602016-12-22 23:12:01 +010012024 if (global_ssl.listen_default_ciphers)
12025 global_ssl.listen_default_ciphers = strdup(global_ssl.listen_default_ciphers);
12026 if (global_ssl.connect_default_ciphers)
12027 global_ssl.connect_default_ciphers = strdup(global_ssl.connect_default_ciphers);
Emmanuel Hocdet839af572019-05-14 16:27:35 +020012028#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +020012029 if (global_ssl.listen_default_ciphersuites)
12030 global_ssl.listen_default_ciphersuites = strdup(global_ssl.listen_default_ciphersuites);
12031 if (global_ssl.connect_default_ciphersuites)
12032 global_ssl.connect_default_ciphersuites = strdup(global_ssl.connect_default_ciphersuites);
12033#endif
Willy Tarreau610f04b2014-02-13 11:36:41 +010012034
Willy Tarreau13e14102016-12-22 20:25:26 +010012035 xprt_register(XPRT_SSL, &ssl_sock);
Willy Tarreau9a1ab082019-05-09 13:26:41 +020012036#if HA_OPENSSL_VERSION_NUMBER < 0x10100000L
Emeric Brun46591952012-05-18 15:47:34 +020012037 SSL_library_init();
Rosen Penev68185952018-12-14 08:47:02 -080012038#endif
Ilya Shipitsin0590f442019-05-25 19:30:50 +050012039#if (!defined(OPENSSL_NO_COMP) && !defined(SSL_OP_NO_COMPRESSION))
Emeric Brun46591952012-05-18 15:47:34 +020012040 cm = SSL_COMP_get_compression_methods();
Ilya Shipitsine242f3d2019-05-25 03:38:14 +050012041 n = sk_SSL_COMP_num(cm);
12042 while (n--) {
12043 (void) sk_SSL_COMP_pop(cm);
12044 }
Ilya Shipitsin0590f442019-05-25 19:30:50 +050012045#endif
Ilya Shipitsine242f3d2019-05-25 03:38:14 +050012046
Willy Tarreau5db847a2019-05-09 14:13:35 +020012047#if defined(USE_THREAD) && (HA_OPENSSL_VERSION_NUMBER < 0x10100000L)
Emeric Brun821bb9b2017-06-15 16:37:39 +020012048 ssl_locking_init();
12049#endif
Willy Tarreau5db847a2019-05-09 14:13:35 +020012050#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +010012051 sctl_ex_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, ssl_sock_sctl_free_func);
12052#endif
Thierry FOURNIER28962c92018-06-17 21:37:05 +020012053 ssl_app_data_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL);
Thierry FOURNIER16ff0502018-06-17 21:33:01 +020012054 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 +020012055#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +000012056 ENGINE_load_builtin_engines();
Grant Zhangfa6c7ee2017-01-14 01:42:15 +000012057 hap_register_post_check(ssl_check_async_engine_count);
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020012058#endif
Willy Tarreaud1c57502016-12-22 22:46:15 +010012059#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
12060 hap_register_post_check(tlskeys_finalize_config);
12061#endif
Willy Tarreau80713382018-11-26 10:19:54 +010012062
12063 global.ssl_session_max_cost = SSL_SESSION_MAX_COST;
12064 global.ssl_handshake_max_cost = SSL_HANDSHAKE_MAX_COST;
12065
Emmanuel Hocdet70df7bf2019-01-04 11:08:20 +010012066 hap_register_post_deinit(ssl_free_global_issuers);
12067
Willy Tarreau80713382018-11-26 10:19:54 +010012068#ifndef OPENSSL_NO_DH
12069 ssl_dh_ptr_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, NULL);
12070 hap_register_post_deinit(ssl_free_dh);
12071#endif
12072#ifndef OPENSSL_NO_ENGINE
12073 hap_register_post_deinit(ssl_free_engines);
12074#endif
12075 /* Load SSL string for the verbose & debug mode. */
12076 ERR_load_SSL_strings();
Olivier Houcharda8955d52019-04-07 22:00:38 +020012077 ha_meth = BIO_meth_new(0x666, "ha methods");
12078 BIO_meth_set_write(ha_meth, ha_ssl_write);
12079 BIO_meth_set_read(ha_meth, ha_ssl_read);
12080 BIO_meth_set_ctrl(ha_meth, ha_ssl_ctrl);
12081 BIO_meth_set_create(ha_meth, ha_ssl_new);
12082 BIO_meth_set_destroy(ha_meth, ha_ssl_free);
12083 BIO_meth_set_puts(ha_meth, ha_ssl_puts);
12084 BIO_meth_set_gets(ha_meth, ha_ssl_gets);
William Lallemand150bfa82019-09-19 17:12:49 +020012085
12086 HA_SPIN_INIT(&ckch_lock);
Willy Tarreau80713382018-11-26 10:19:54 +010012087}
Willy Tarreaud92aa5c2015-01-15 21:34:39 +010012088
Willy Tarreau80713382018-11-26 10:19:54 +010012089/* Compute and register the version string */
12090static void ssl_register_build_options()
12091{
12092 char *ptr = NULL;
12093 int i;
12094
Willy Tarreauc2c0b612016-12-21 19:23:20 +010012095 memprintf(&ptr, "Built with OpenSSL version : "
12096#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet50e25e12017-03-24 15:20:03 +010012097 "BoringSSL");
Willy Tarreauc2c0b612016-12-21 19:23:20 +010012098#else /* OPENSSL_IS_BORINGSSL */
12099 OPENSSL_VERSION_TEXT
12100 "\nRunning on OpenSSL version : %s%s",
Rosen Penev68185952018-12-14 08:47:02 -080012101 OpenSSL_version(OPENSSL_VERSION),
Willy Tarreau1d158ab2019-05-09 13:41:45 +020012102 ((OPENSSL_VERSION_NUMBER ^ OpenSSL_version_num()) >> 8) ? " (VERSIONS DIFFER!)" : "");
Willy Tarreauc2c0b612016-12-21 19:23:20 +010012103#endif
12104 memprintf(&ptr, "%s\nOpenSSL library supports TLS extensions : "
Willy Tarreau9a1ab082019-05-09 13:26:41 +020012105#if HA_OPENSSL_VERSION_NUMBER < 0x00907000L
Willy Tarreauc2c0b612016-12-21 19:23:20 +010012106 "no (library version too old)"
12107#elif defined(OPENSSL_NO_TLSEXT)
12108 "no (disabled via OPENSSL_NO_TLSEXT)"
12109#else
12110 "yes"
12111#endif
12112 "", ptr);
12113
12114 memprintf(&ptr, "%s\nOpenSSL library supports SNI : "
12115#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
12116 "yes"
12117#else
12118#ifdef OPENSSL_NO_TLSEXT
12119 "no (because of OPENSSL_NO_TLSEXT)"
12120#else
12121 "no (version might be too old, 0.9.8f min needed)"
12122#endif
12123#endif
12124 "", ptr);
12125
Emmanuel Hocdetf80bc242017-07-12 14:25:38 +020012126 memprintf(&ptr, "%s\nOpenSSL library supports :", ptr);
12127 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
12128 if (methodVersions[i].option)
12129 memprintf(&ptr, "%s %s", ptr, methodVersions[i].name);
Emmanuel Hocdet50e25e12017-03-24 15:20:03 +010012130
Willy Tarreauc2c0b612016-12-21 19:23:20 +010012131 hap_register_build_opts(ptr, 1);
Willy Tarreau80713382018-11-26 10:19:54 +010012132}
Willy Tarreauc2c0b612016-12-21 19:23:20 +010012133
Willy Tarreau80713382018-11-26 10:19:54 +010012134INITCALL0(STG_REGISTER, ssl_register_build_options);
Remi Gacogne4f902b82015-05-28 16:23:00 +020012135
Emeric Brun46591952012-05-18 15:47:34 +020012136
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020012137#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +000012138void ssl_free_engines(void) {
12139 struct ssl_engine_list *wl, *wlb;
12140 /* free up engine list */
12141 list_for_each_entry_safe(wl, wlb, &openssl_engines, list) {
12142 ENGINE_finish(wl->e);
12143 ENGINE_free(wl->e);
12144 LIST_DEL(&wl->list);
12145 free(wl);
12146 }
12147}
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020012148#endif
Christopher Faulet31af49d2015-06-09 17:29:50 +020012149
Remi Gacogned3a23c32015-05-28 16:39:47 +020012150#ifndef OPENSSL_NO_DH
Grant Zhang872f9c22017-01-21 01:10:18 +000012151void ssl_free_dh(void) {
12152 if (local_dh_1024) {
12153 DH_free(local_dh_1024);
12154 local_dh_1024 = NULL;
12155 }
12156 if (local_dh_2048) {
12157 DH_free(local_dh_2048);
12158 local_dh_2048 = NULL;
12159 }
12160 if (local_dh_4096) {
12161 DH_free(local_dh_4096);
12162 local_dh_4096 = NULL;
12163 }
Remi Gacogne47783ef2015-05-29 15:53:22 +020012164 if (global_dh) {
12165 DH_free(global_dh);
12166 global_dh = NULL;
12167 }
Grant Zhang872f9c22017-01-21 01:10:18 +000012168}
12169#endif
12170
12171__attribute__((destructor))
12172static void __ssl_sock_deinit(void)
12173{
12174#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Emeric Brun821bb9b2017-06-15 16:37:39 +020012175 if (ssl_ctx_lru_tree) {
12176 lru64_destroy(ssl_ctx_lru_tree);
Christopher Faulet2a944ee2017-11-07 10:42:54 +010012177 HA_RWLOCK_DESTROY(&ssl_ctx_lru_rwlock);
Emeric Brun821bb9b2017-06-15 16:37:39 +020012178 }
Remi Gacogned3a23c32015-05-28 16:39:47 +020012179#endif
12180
Willy Tarreau5db847a2019-05-09 14:13:35 +020012181#if (HA_OPENSSL_VERSION_NUMBER < 0x10100000L)
Remi Gacogned3a23c32015-05-28 16:39:47 +020012182 ERR_remove_state(0);
12183 ERR_free_strings();
12184
12185 EVP_cleanup();
Rosen Penev68185952018-12-14 08:47:02 -080012186#endif
Remi Gacogned3a23c32015-05-28 16:39:47 +020012187
Willy Tarreau5db847a2019-05-09 14:13:35 +020012188#if (HA_OPENSSL_VERSION_NUMBER >= 0x00907000L) && (HA_OPENSSL_VERSION_NUMBER < 0x10100000L)
Remi Gacogned3a23c32015-05-28 16:39:47 +020012189 CRYPTO_cleanup_all_ex_data();
12190#endif
Olivier Houcharda8955d52019-04-07 22:00:38 +020012191 BIO_meth_free(ha_meth);
Remi Gacogned3a23c32015-05-28 16:39:47 +020012192}
12193
12194
Emeric Brun46591952012-05-18 15:47:34 +020012195/*
12196 * Local variables:
12197 * c-indent-level: 8
12198 * c-basic-offset: 8
12199 * End:
12200 */