blob: df15b77c192873f58adff6b20cdb79fe0543b27f [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 }
3963end:
3964 *sni_filter = tmp_filter;
3965 *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;
yanbzhu08ce6ab2015-12-02 13:01:29 -05004191end:
4192
4193 if (names)
4194 sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
4195
yanbzhu08ce6ab2015-12-02 13:01:29 -05004196 node = ebmb_first(&sni_keytypes_map);
4197 while (node) {
4198 next = ebmb_next(node);
4199 ebmb_delete(node);
William Lallemand8ed5b962019-10-04 17:24:39 +02004200 free(ebmb_entry(node, struct sni_keytype, name));
yanbzhu08ce6ab2015-12-02 13:01:29 -05004201 node = next;
4202 }
4203
Emeric Brun054563d2019-10-17 13:16:58 +02004204 if (errcode & ERR_CODE && ckch_inst) {
William Lallemand0c6d12f2019-10-04 18:38:51 +02004205 struct sni_ctx *sc0, *sc0b;
4206
4207 /* free the SSL_CTX in case of error */
4208 for (i = 0; i < SSL_SOCK_POSSIBLE_KT_COMBOS; i++) {
4209 if (key_combos[i].ctx)
4210 SSL_CTX_free(key_combos[i].ctx);
4211 }
4212
4213 /* free the sni_ctx in case of error */
4214 list_for_each_entry_safe(sc0, sc0b, &ckch_inst->sni_ctx, by_ckch_inst) {
4215
4216 ebmb_delete(&sc0->name);
4217 LIST_DEL(&sc0->by_ckch_inst);
4218 free(sc0);
4219 }
William Lallemand614ca0d2019-10-07 13:52:11 +02004220 free(ckch_inst);
4221 ckch_inst = NULL;
William Lallemand0c6d12f2019-10-04 18:38:51 +02004222 }
4223
Emeric Brun054563d2019-10-17 13:16:58 +02004224 *ckchi = ckch_inst;
4225 return errcode;
yanbzhu08ce6ab2015-12-02 13:01:29 -05004226}
4227#else
4228/* This is a dummy, that just logs an error and returns error */
Emeric Brun054563d2019-10-17 13:16:58 +02004229static int ckch_inst_new_load_multi_store(const char *path, struct ckch_store *ckchs,
4230 struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
4231 char **sni_filter, int fcount, struct ckch_inst **ckchi, char **err)
yanbzhu08ce6ab2015-12-02 13:01:29 -05004232{
4233 memprintf(err, "%sunable to stat SSL certificate from file '%s' : %s.\n",
4234 err && *err ? *err : "", path, strerror(errno));
Emeric Brun054563d2019-10-17 13:16:58 +02004235 return ERR_ALERT | ERR_FATAL;
yanbzhu08ce6ab2015-12-02 13:01:29 -05004236}
4237
Willy Tarreau9a1ab082019-05-09 13:26:41 +02004238#endif /* #if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL: Support for loading multiple certs into a single SSL_CTX */
yanbzhu488a4d22015-12-01 15:16:07 -05004239
William Lallemand614ca0d2019-10-07 13:52:11 +02004240/*
4241 * This function allocate a ckch_inst and create its snis
Emeric Brun054563d2019-10-17 13:16:58 +02004242 *
4243 * Returns a bitfield containing the flags:
4244 * ERR_FATAL in any fatal error case
4245 * ERR_ALERT if the reason of the error is available in err
4246 * ERR_WARN if a warning is available into err
William Lallemand614ca0d2019-10-07 13:52:11 +02004247 */
Emeric Brun054563d2019-10-17 13:16:58 +02004248static int ckch_inst_new_load_store(const char *path, struct ckch_store *ckchs, struct bind_conf *bind_conf,
4249 struct ssl_bind_conf *ssl_conf, char **sni_filter, int fcount, struct ckch_inst **ckchi, char **err)
Emeric Brunfc0421f2012-09-07 17:30:07 +02004250{
William Lallemandc9402072019-05-15 15:33:54 +02004251 SSL_CTX *ctx;
William Lallemandc9402072019-05-15 15:33:54 +02004252 int i;
Emeric Brunfc0421f2012-09-07 17:30:07 +02004253 int order = 0;
4254 X509_NAME *xname;
4255 char *str;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01004256 EVP_PKEY *pkey;
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02004257 struct pkey_info kinfo = { .sig = TLSEXT_signature_anonymous, .bits = 0 };
Emeric Brunfc0421f2012-09-07 17:30:07 +02004258#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
4259 STACK_OF(GENERAL_NAME) *names;
4260#endif
William Lallemand36b84632019-07-18 19:28:17 +02004261 struct cert_key_and_chain *ckch;
William Lallemand614ca0d2019-10-07 13:52:11 +02004262 struct ckch_inst *ckch_inst = NULL;
Emeric Brun054563d2019-10-17 13:16:58 +02004263 int errcode = 0;
4264
4265 *ckchi = NULL;
William Lallemanda59191b2019-05-15 16:08:56 +02004266
William Lallemande3af8fb2019-10-08 11:36:53 +02004267 if (!ckchs || !ckchs->ckch)
Emeric Brun054563d2019-10-17 13:16:58 +02004268 return ERR_FATAL;
Emeric Brunfc0421f2012-09-07 17:30:07 +02004269
William Lallemande3af8fb2019-10-08 11:36:53 +02004270 ckch = ckchs->ckch;
William Lallemand36b84632019-07-18 19:28:17 +02004271
William Lallemandc9402072019-05-15 15:33:54 +02004272 ctx = SSL_CTX_new(SSLv23_server_method());
4273 if (!ctx) {
4274 memprintf(err, "%sunable to allocate SSL context for cert '%s'.\n",
4275 err && *err ? *err : "", path);
Emeric Brun054563d2019-10-17 13:16:58 +02004276 errcode |= ERR_ALERT | ERR_FATAL;
4277 goto error;
William Lallemandc9402072019-05-15 15:33:54 +02004278 }
4279
Emeric Bruna96b5822019-10-17 13:25:14 +02004280 errcode |= ssl_sock_put_ckch_into_ctx(path, ckch, ctx, err);
4281 if (errcode & ERR_CODE)
William Lallemand614ca0d2019-10-07 13:52:11 +02004282 goto error;
William Lallemand614ca0d2019-10-07 13:52:11 +02004283
4284 ckch_inst = ckch_inst_new();
4285 if (!ckch_inst) {
4286 memprintf(err, "%sunable to allocate SSL context for cert '%s'.\n",
4287 err && *err ? *err : "", path);
Emeric Brun054563d2019-10-17 13:16:58 +02004288 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemandd9199372019-10-04 15:37:05 +02004289 goto error;
William Lallemandc9402072019-05-15 15:33:54 +02004290 }
4291
William Lallemand36b84632019-07-18 19:28:17 +02004292 pkey = X509_get_pubkey(ckch->cert);
Emmanuel Hocdet05942112017-02-20 16:11:50 +01004293 if (pkey) {
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02004294 kinfo.bits = EVP_PKEY_bits(pkey);
Emmanuel Hocdet05942112017-02-20 16:11:50 +01004295 switch(EVP_PKEY_base_id(pkey)) {
4296 case EVP_PKEY_RSA:
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02004297 kinfo.sig = TLSEXT_signature_rsa;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01004298 break;
4299 case EVP_PKEY_EC:
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02004300 kinfo.sig = TLSEXT_signature_ecdsa;
4301 break;
4302 case EVP_PKEY_DSA:
4303 kinfo.sig = TLSEXT_signature_dsa;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01004304 break;
4305 }
4306 EVP_PKEY_free(pkey);
4307 }
4308
Emeric Brun50bcecc2013-04-22 13:05:23 +02004309 if (fcount) {
William Lallemandfe49bb32019-10-03 23:46:33 +02004310 while (fcount--) {
William Lallemand1d29c742019-10-04 00:53:29 +02004311 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 +02004312 if (order < 0) {
4313 memprintf(err, "%sunable to create a sni context.\n", err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02004314 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemandd9199372019-10-04 15:37:05 +02004315 goto error;
William Lallemandfe49bb32019-10-03 23:46:33 +02004316 }
4317 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004318 }
4319 else {
Emeric Brunfc0421f2012-09-07 17:30:07 +02004320#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
William Lallemand36b84632019-07-18 19:28:17 +02004321 names = X509_get_ext_d2i(ckch->cert, NID_subject_alt_name, NULL, NULL);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004322 if (names) {
4323 for (i = 0; i < sk_GENERAL_NAME_num(names); i++) {
4324 GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i);
4325 if (name->type == GEN_DNS) {
4326 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
William Lallemand1d29c742019-10-04 00:53:29 +02004327 order = ckch_inst_add_cert_sni(ctx, ckch_inst, bind_conf, ssl_conf, kinfo, str, order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004328 OPENSSL_free(str);
William Lallemandfe49bb32019-10-03 23:46:33 +02004329 if (order < 0) {
4330 memprintf(err, "%sunable to create a sni context.\n", err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02004331 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemandd9199372019-10-04 15:37:05 +02004332 goto error;
William Lallemandfe49bb32019-10-03 23:46:33 +02004333 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004334 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004335 }
4336 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004337 sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004338 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004339#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
William Lallemand36b84632019-07-18 19:28:17 +02004340 xname = X509_get_subject_name(ckch->cert);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004341 i = -1;
4342 while ((i = X509_NAME_get_index_by_NID(xname, NID_commonName, i)) != -1) {
4343 X509_NAME_ENTRY *entry = X509_NAME_get_entry(xname, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02004344 ASN1_STRING *value;
4345
4346 value = X509_NAME_ENTRY_get_data(entry);
4347 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
William Lallemand1d29c742019-10-04 00:53:29 +02004348 order = ckch_inst_add_cert_sni(ctx, ckch_inst, bind_conf, ssl_conf, kinfo, str, order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004349 OPENSSL_free(str);
William Lallemandfe49bb32019-10-03 23:46:33 +02004350 if (order < 0) {
4351 memprintf(err, "%sunable to create a sni context.\n", err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02004352 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemandd9199372019-10-04 15:37:05 +02004353 goto error;
William Lallemandfe49bb32019-10-03 23:46:33 +02004354 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004355 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004356 }
4357 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004358 /* we must not free the SSL_CTX anymore below, since it's already in
4359 * the tree, so it will be discovered and cleaned in time.
4360 */
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02004361
Emeric Brunfc0421f2012-09-07 17:30:07 +02004362#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004363 if (bind_conf->default_ctx) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02004364 memprintf(err, "%sthis version of openssl cannot load multiple SSL certificates.\n",
4365 err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02004366 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemandd9199372019-10-04 15:37:05 +02004367 goto error;
Emeric Brunfc0421f2012-09-07 17:30:07 +02004368 }
4369#endif
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004370 if (!bind_conf->default_ctx) {
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004371 bind_conf->default_ctx = ctx;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004372 bind_conf->default_ssl_conf = ssl_conf;
William Lallemand21724f02019-11-04 17:56:13 +01004373 ckch_inst->is_default = 1;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004374 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004375
William Lallemand9117de92019-10-04 00:29:42 +02004376 /* everything succeed, the ckch instance can be used */
4377 ckch_inst->bind_conf = bind_conf;
William Lallemand150bfa82019-09-19 17:12:49 +02004378 ckch_inst->ssl_conf = ssl_conf;
William Lallemandcfca1422020-03-05 10:17:47 +01004379 ckch_inst->ckch_store = ckchs;
William Lallemand9117de92019-10-04 00:29:42 +02004380
Emeric Brun054563d2019-10-17 13:16:58 +02004381 *ckchi = ckch_inst;
4382 return errcode;
William Lallemandd9199372019-10-04 15:37:05 +02004383
4384error:
4385 /* free the allocated sni_ctxs */
William Lallemand614ca0d2019-10-07 13:52:11 +02004386 if (ckch_inst) {
William Lallemandd9199372019-10-04 15:37:05 +02004387 struct sni_ctx *sc0, *sc0b;
4388
4389 list_for_each_entry_safe(sc0, sc0b, &ckch_inst->sni_ctx, by_ckch_inst) {
4390
4391 ebmb_delete(&sc0->name);
4392 LIST_DEL(&sc0->by_ckch_inst);
4393 free(sc0);
4394 }
William Lallemand614ca0d2019-10-07 13:52:11 +02004395 free(ckch_inst);
4396 ckch_inst = NULL;
William Lallemandd9199372019-10-04 15:37:05 +02004397 }
4398 /* We only created 1 SSL_CTX so we can free it there */
4399 SSL_CTX_free(ctx);
4400
Emeric Brun054563d2019-10-17 13:16:58 +02004401 return errcode;
Emeric Brunfc0421f2012-09-07 17:30:07 +02004402}
4403
Willy Tarreau8c5414a2019-10-16 17:06:25 +02004404/* Returns a set of ERR_* flags possibly with an error in <err>. */
William Lallemand614ca0d2019-10-07 13:52:11 +02004405static int ssl_sock_load_ckchs(const char *path, struct ckch_store *ckchs,
4406 struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
4407 char **sni_filter, int fcount, char **err)
4408{
4409 struct ckch_inst *ckch_inst = NULL;
Emeric Brun054563d2019-10-17 13:16:58 +02004410 int errcode = 0;
William Lallemand614ca0d2019-10-07 13:52:11 +02004411
4412 /* we found the ckchs in the tree, we can use it directly */
4413 if (ckchs->multi)
Emeric Brun054563d2019-10-17 13:16:58 +02004414 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 +02004415 else
Emeric Brun054563d2019-10-17 13:16:58 +02004416 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 +02004417
Emeric Brun054563d2019-10-17 13:16:58 +02004418 if (errcode & ERR_CODE)
4419 return errcode;
William Lallemand614ca0d2019-10-07 13:52:11 +02004420
4421 ssl_sock_load_cert_sni(ckch_inst, bind_conf);
4422
4423 /* succeed, add the instance to the ckch_store's list of instance */
4424 LIST_ADDQ(&ckchs->ckch_inst, &ckch_inst->by_ckchs);
Emeric Brun054563d2019-10-17 13:16:58 +02004425 return errcode;
William Lallemand614ca0d2019-10-07 13:52:11 +02004426}
4427
4428
Willy Tarreaubbc91962019-10-16 16:42:19 +02004429/* Returns a set of ERR_* flags possibly with an error in <err>. */
Willy Tarreau03209342016-12-22 17:08:28 +01004430int ssl_sock_load_cert(char *path, struct bind_conf *bind_conf, char **err)
Emeric Brunfc0421f2012-09-07 17:30:07 +02004431{
Cyril Bonté3180f7b2015-01-25 00:16:08 +01004432 struct dirent **de_list;
4433 int i, n;
Emeric Brunfc0421f2012-09-07 17:30:07 +02004434 struct stat buf;
Willy Tarreauee2663b2012-12-06 11:36:59 +01004435 char *end;
4436 char fp[MAXPATHLEN+1];
Emeric Brunfc0421f2012-09-07 17:30:07 +02004437 int cfgerr = 0;
William Lallemande3af8fb2019-10-08 11:36:53 +02004438 struct ckch_store *ckchs;
Willy Tarreau9a1ab082019-05-09 13:26:41 +02004439#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
yanbzhu63ea8462015-12-09 13:35:14 -05004440 int is_bundle;
4441 int j;
4442#endif
William Lallemande3af8fb2019-10-08 11:36:53 +02004443 if ((ckchs = ckchs_lookup(path))) {
William Lallemande3af8fb2019-10-08 11:36:53 +02004444 /* we found the ckchs in the tree, we can use it directly */
Willy Tarreau8c5414a2019-10-16 17:06:25 +02004445 return ssl_sock_load_ckchs(path, ckchs, bind_conf, NULL, NULL, 0, err);
William Lallemand6af03992019-07-23 15:00:54 +02004446 }
4447
yanbzhu08ce6ab2015-12-02 13:01:29 -05004448 if (stat(path, &buf) == 0) {
William Dauchy9a8ef7f2020-01-13 17:52:49 +01004449 if (S_ISDIR(buf.st_mode) == 0) {
William Lallemande3af8fb2019-10-08 11:36:53 +02004450 ckchs = ckchs_load_cert_file(path, 0, err);
4451 if (!ckchs)
Willy Tarreaubbc91962019-10-16 16:42:19 +02004452 return ERR_ALERT | ERR_FATAL;
4453
Willy Tarreau8c5414a2019-10-16 17:06:25 +02004454 return ssl_sock_load_ckchs(path, ckchs, bind_conf, NULL, NULL, 0, err);
William Lallemand36b84632019-07-18 19:28:17 +02004455 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004456
yanbzhu08ce6ab2015-12-02 13:01:29 -05004457 /* strip trailing slashes, including first one */
4458 for (end = path + strlen(path) - 1; end >= path && *end == '/'; end--)
4459 *end = 0;
Emeric Brunfc0421f2012-09-07 17:30:07 +02004460
yanbzhu08ce6ab2015-12-02 13:01:29 -05004461 n = scandir(path, &de_list, 0, alphasort);
4462 if (n < 0) {
4463 memprintf(err, "%sunable to scan directory '%s' : %s.\n",
4464 err && *err ? *err : "", path, strerror(errno));
Willy Tarreaubbc91962019-10-16 16:42:19 +02004465 cfgerr |= ERR_ALERT | ERR_FATAL;
yanbzhu08ce6ab2015-12-02 13:01:29 -05004466 }
4467 else {
4468 for (i = 0; i < n; i++) {
4469 struct dirent *de = de_list[i];
Emeric Brun2aab7222014-06-18 18:15:09 +02004470
yanbzhu08ce6ab2015-12-02 13:01:29 -05004471 end = strrchr(de->d_name, '.');
William Lallemand3f25ae32020-02-24 16:30:12 +01004472 if (end && (!strcmp(end, ".issuer") || !strcmp(end, ".ocsp") || !strcmp(end, ".sctl") || !strcmp(end, ".key")))
yanbzhu08ce6ab2015-12-02 13:01:29 -05004473 goto ignore_entry;
Cyril Bonté3180f7b2015-01-25 00:16:08 +01004474
yanbzhu08ce6ab2015-12-02 13:01:29 -05004475 snprintf(fp, sizeof(fp), "%s/%s", path, de->d_name);
4476 if (stat(fp, &buf) != 0) {
4477 memprintf(err, "%sunable to stat SSL certificate from file '%s' : %s.\n",
4478 err && *err ? *err : "", fp, strerror(errno));
Willy Tarreaubbc91962019-10-16 16:42:19 +02004479 cfgerr |= ERR_ALERT | ERR_FATAL;
yanbzhu08ce6ab2015-12-02 13:01:29 -05004480 goto ignore_entry;
4481 }
4482 if (!S_ISREG(buf.st_mode))
4483 goto ignore_entry;
yanbzhu63ea8462015-12-09 13:35:14 -05004484
Willy Tarreau9a1ab082019-05-09 13:26:41 +02004485#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
yanbzhu63ea8462015-12-09 13:35:14 -05004486 is_bundle = 0;
4487 /* Check if current entry in directory is part of a multi-cert bundle */
4488
William Lallemand3af48e72020-02-03 17:15:52 +01004489 if ((global_ssl.extra_files & SSL_GF_BUNDLE) && end) {
yanbzhu63ea8462015-12-09 13:35:14 -05004490 for (j = 0; j < SSL_SOCK_NUM_KEYTYPES; j++) {
4491 if (!strcmp(end + 1, SSL_SOCK_KEYTYPE_NAMES[j])) {
4492 is_bundle = 1;
4493 break;
4494 }
4495 }
4496
4497 if (is_bundle) {
yanbzhu63ea8462015-12-09 13:35:14 -05004498 int dp_len;
4499
4500 dp_len = end - de->d_name;
yanbzhu63ea8462015-12-09 13:35:14 -05004501
4502 /* increment i and free de until we get to a non-bundle cert
4503 * Note here that we look at de_list[i + 1] before freeing de
Willy Tarreau05800522019-10-29 10:48:50 +01004504 * this is important since ignore_entry will free de. This also
4505 * guarantees that de->d_name continues to hold the same prefix.
yanbzhu63ea8462015-12-09 13:35:14 -05004506 */
Willy Tarreau05800522019-10-29 10:48:50 +01004507 while (i + 1 < n && !strncmp(de_list[i + 1]->d_name, de->d_name, dp_len)) {
yanbzhu63ea8462015-12-09 13:35:14 -05004508 free(de);
4509 i++;
4510 de = de_list[i];
4511 }
4512
Willy Tarreau05800522019-10-29 10:48:50 +01004513 snprintf(fp, sizeof(fp), "%s/%.*s", path, dp_len, de->d_name);
William Lallemande3af8fb2019-10-08 11:36:53 +02004514 if ((ckchs = ckchs_lookup(fp)) == NULL)
4515 ckchs = ckchs_load_cert_file(fp, 1, err);
4516 if (!ckchs)
Willy Tarreaubbc91962019-10-16 16:42:19 +02004517 cfgerr |= ERR_ALERT | ERR_FATAL;
Willy Tarreau8c5414a2019-10-16 17:06:25 +02004518 else
4519 cfgerr |= ssl_sock_load_ckchs(path, ckchs, bind_conf, NULL, NULL, 0, err);
yanbzhu63ea8462015-12-09 13:35:14 -05004520 /* Successfully processed the bundle */
4521 goto ignore_entry;
4522 }
4523 }
4524
4525#endif
William Lallemande3af8fb2019-10-08 11:36:53 +02004526 if ((ckchs = ckchs_lookup(fp)) == NULL)
4527 ckchs = ckchs_load_cert_file(fp, 0, err);
4528 if (!ckchs)
Willy Tarreaubbc91962019-10-16 16:42:19 +02004529 cfgerr |= ERR_ALERT | ERR_FATAL;
William Lallemand614ca0d2019-10-07 13:52:11 +02004530 else
Willy Tarreau8c5414a2019-10-16 17:06:25 +02004531 cfgerr |= ssl_sock_load_ckchs(path, ckchs, bind_conf, NULL, NULL, 0, err);
William Lallemand36b84632019-07-18 19:28:17 +02004532
yanbzhu08ce6ab2015-12-02 13:01:29 -05004533ignore_entry:
4534 free(de);
Cyril Bonté3180f7b2015-01-25 00:16:08 +01004535 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05004536 free(de_list);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004537 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05004538 return cfgerr;
yanbzhu08ce6ab2015-12-02 13:01:29 -05004539
William Lallemand3af48e72020-02-03 17:15:52 +01004540 } else {
4541 /* stat failed */
Willy Tarreaubbc91962019-10-16 16:42:19 +02004542
William Lallemand3af48e72020-02-03 17:15:52 +01004543 if (global_ssl.extra_files & SSL_GF_BUNDLE) {
4544 /* try to load a bundle if it is permitted */
4545 ckchs = ckchs_load_cert_file(path, 1, err);
4546 if (!ckchs)
4547 return ERR_ALERT | ERR_FATAL;
4548 cfgerr |= ssl_sock_load_ckchs(path, ckchs, bind_conf, NULL, NULL, 0, err);
4549 } else {
4550 memprintf(err, "%sunable to stat SSL certificate from file '%s' : %s.\n",
4551 err && *err ? *err : "", fp, strerror(errno));
4552 cfgerr |= ERR_ALERT | ERR_FATAL;
4553 }
4554 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05004555
Emeric Brunfc0421f2012-09-07 17:30:07 +02004556 return cfgerr;
4557}
4558
Thierry Fournier383085f2013-01-24 14:15:43 +01004559/* Make sure openssl opens /dev/urandom before the chroot. The work is only
4560 * done once. Zero is returned if the operation fails. No error is returned
4561 * if the random is said as not implemented, because we expect that openssl
4562 * will use another method once needed.
4563 */
4564static int ssl_initialize_random()
4565{
4566 unsigned char random;
4567 static int random_initialized = 0;
4568
4569 if (!random_initialized && RAND_bytes(&random, 1) != 0)
4570 random_initialized = 1;
4571
4572 return random_initialized;
4573}
4574
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004575/* release ssl bind conf */
4576void ssl_sock_free_ssl_conf(struct ssl_bind_conf *conf)
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004577{
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004578 if (conf) {
Bernard Spil13c53f82018-02-15 13:34:58 +01004579#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004580 free(conf->npn_str);
4581 conf->npn_str = NULL;
4582#endif
4583#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
4584 free(conf->alpn_str);
4585 conf->alpn_str = NULL;
4586#endif
4587 free(conf->ca_file);
4588 conf->ca_file = NULL;
Emmanuel Hocdet842e94e2019-12-16 16:39:17 +01004589 free(conf->ca_verify_file);
4590 conf->ca_verify_file = NULL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004591 free(conf->crl_file);
4592 conf->crl_file = NULL;
4593 free(conf->ciphers);
4594 conf->ciphers = NULL;
Emmanuel Hocdet839af572019-05-14 16:27:35 +02004595#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02004596 free(conf->ciphersuites);
4597 conf->ciphersuites = NULL;
4598#endif
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004599 free(conf->curves);
4600 conf->curves = NULL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004601 free(conf->ecdhe);
4602 conf->ecdhe = NULL;
4603 }
4604}
4605
Willy Tarreaubbc91962019-10-16 16:42:19 +02004606/* Returns a set of ERR_* flags possibly with an error in <err>. */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004607int ssl_sock_load_cert_list_file(char *file, struct bind_conf *bind_conf, struct proxy *curproxy, char **err)
4608{
4609 char thisline[CRT_LINESIZE];
4610 char path[MAXPATHLEN+1];
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004611 FILE *f;
yanbzhu1b04e5b2015-12-02 13:54:14 -05004612 struct stat buf;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004613 int linenum = 0;
4614 int cfgerr = 0;
William Lallemande3af8fb2019-10-08 11:36:53 +02004615 struct ckch_store *ckchs;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004616
Willy Tarreauad1731d2013-04-02 17:35:58 +02004617 if ((f = fopen(file, "r")) == NULL) {
4618 memprintf(err, "cannot open file '%s' : %s", file, strerror(errno));
Willy Tarreaubbc91962019-10-16 16:42:19 +02004619 return ERR_ALERT | ERR_FATAL;
Willy Tarreauad1731d2013-04-02 17:35:58 +02004620 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004621
4622 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004623 int arg, newarg, cur_arg, i, ssl_b = 0, ssl_e = 0;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004624 char *end;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004625 char *args[MAX_CRT_ARGS + 1];
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004626 char *line = thisline;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004627 char *crt_path;
4628 struct ssl_bind_conf *ssl_conf = NULL;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004629
4630 linenum++;
4631 end = line + strlen(line);
4632 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
4633 /* Check if we reached the limit and the last char is not \n.
4634 * Watch out for the last line without the terminating '\n'!
4635 */
Willy Tarreauad1731d2013-04-02 17:35:58 +02004636 memprintf(err, "line %d too long in file '%s', limit is %d characters",
4637 linenum, file, (int)sizeof(thisline)-1);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004638 cfgerr |= ERR_ALERT | ERR_FATAL;
Willy Tarreauad1731d2013-04-02 17:35:58 +02004639 break;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004640 }
4641
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004642 arg = 0;
Emeric Brun50bcecc2013-04-22 13:05:23 +02004643 newarg = 1;
4644 while (*line) {
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004645 if (*line == '#' || *line == '\n' || *line == '\r') {
4646 /* end of string, end of loop */
4647 *line = 0;
4648 break;
Willy Tarreauded15b72020-02-25 07:51:59 +01004649 } else if (isspace((unsigned char)*line)) {
Emeric Brun50bcecc2013-04-22 13:05:23 +02004650 newarg = 1;
4651 *line = 0;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004652 } else if (*line == '[') {
4653 if (ssl_b) {
4654 memprintf(err, "too many '[' on line %d in file '%s'.", linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004655 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004656 break;
4657 }
4658 if (!arg) {
4659 memprintf(err, "file must start with a cert on line %d in file '%s'", linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004660 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004661 break;
4662 }
4663 ssl_b = arg;
4664 newarg = 1;
4665 *line = 0;
4666 } else if (*line == ']') {
4667 if (ssl_e) {
4668 memprintf(err, "too many ']' on line %d in file '%s'.", linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004669 cfgerr |= ERR_ALERT | ERR_FATAL;
Emeric Brun50bcecc2013-04-22 13:05:23 +02004670 break;
4671 }
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004672 if (!ssl_b) {
4673 memprintf(err, "missing '[' in line %d in file '%s'.", linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004674 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004675 break;
4676 }
4677 ssl_e = arg;
4678 newarg = 1;
4679 *line = 0;
4680 } else if (newarg) {
4681 if (arg == MAX_CRT_ARGS) {
4682 memprintf(err, "too many args on line %d in file '%s'.", linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004683 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004684 break;
4685 }
Emeric Brun50bcecc2013-04-22 13:05:23 +02004686 newarg = 0;
4687 args[arg++] = line;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004688 }
Emeric Brun50bcecc2013-04-22 13:05:23 +02004689 line++;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004690 }
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02004691 if (cfgerr)
4692 break;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004693 args[arg++] = line;
Willy Tarreauad1731d2013-04-02 17:35:58 +02004694
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004695 /* empty line */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004696 if (!*args[0])
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004697 continue;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004698
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004699 crt_path = args[0];
4700 if (*crt_path != '/' && global_ssl.crt_base) {
4701 if ((strlen(global_ssl.crt_base) + 1 + strlen(crt_path)) > MAXPATHLEN) {
4702 memprintf(err, "'%s' : path too long on line %d in file '%s'",
4703 crt_path, linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004704 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004705 break;
4706 }
4707 snprintf(path, sizeof(path), "%s/%s", global_ssl.crt_base, crt_path);
4708 crt_path = path;
4709 }
4710
4711 ssl_conf = calloc(1, sizeof *ssl_conf);
4712 cur_arg = ssl_b ? ssl_b : 1;
4713 while (cur_arg < ssl_e) {
4714 newarg = 0;
4715 for (i = 0; ssl_bind_kws[i].kw != NULL; i++) {
4716 if (strcmp(ssl_bind_kws[i].kw, args[cur_arg]) == 0) {
4717 newarg = 1;
Willy Tarreaubbc91962019-10-16 16:42:19 +02004718 cfgerr |= ssl_bind_kws[i].parse(args, cur_arg, curproxy, ssl_conf, err);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004719 if (cur_arg + 1 + ssl_bind_kws[i].skip > ssl_e) {
4720 memprintf(err, "ssl args out of '[]' for %s on line %d in file '%s'",
4721 args[cur_arg], linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004722 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004723 }
4724 cur_arg += 1 + ssl_bind_kws[i].skip;
4725 break;
4726 }
4727 }
4728 if (!cfgerr && !newarg) {
4729 memprintf(err, "unknown ssl keyword %s on line %d in file '%s'.",
4730 args[cur_arg], linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004731 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004732 break;
4733 }
4734 }
Willy Tarreaubbc91962019-10-16 16:42:19 +02004735
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004736 if (cfgerr) {
4737 ssl_sock_free_ssl_conf(ssl_conf);
4738 free(ssl_conf);
4739 ssl_conf = NULL;
4740 break;
4741 }
4742
William Lallemande3af8fb2019-10-08 11:36:53 +02004743 if ((ckchs = ckchs_lookup(crt_path)) == NULL) {
William Lallemandeed4bf22019-10-10 11:38:13 +02004744 if (stat(crt_path, &buf) == 0)
William Lallemande3af8fb2019-10-08 11:36:53 +02004745 ckchs = ckchs_load_cert_file(crt_path, 0, err);
Emmanuel Hocdet1503e052019-07-31 18:30:33 +02004746 else
William Lallemande3af8fb2019-10-08 11:36:53 +02004747 ckchs = ckchs_load_cert_file(crt_path, 1, err);
yanbzhu1b04e5b2015-12-02 13:54:14 -05004748 }
4749
Willy Tarreau8c5414a2019-10-16 17:06:25 +02004750 if (!ckchs)
Willy Tarreaubbc91962019-10-16 16:42:19 +02004751 cfgerr |= ERR_ALERT | ERR_FATAL;
Willy Tarreau8c5414a2019-10-16 17:06:25 +02004752 else
4753 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 +02004754
Willy Tarreauad1731d2013-04-02 17:35:58 +02004755 if (cfgerr) {
4756 memprintf(err, "error processing line %d in file '%s' : %s", linenum, file, *err);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004757 break;
Willy Tarreauad1731d2013-04-02 17:35:58 +02004758 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004759 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004760 fclose(f);
4761 return cfgerr;
4762}
4763
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004764/* Create an initial CTX used to start the SSL connection before switchctx */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004765static int
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004766ssl_sock_initial_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02004767{
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004768 SSL_CTX *ctx = NULL;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004769 long options =
Emeric Brunfc0421f2012-09-07 17:30:07 +02004770 SSL_OP_ALL | /* all known workarounds for bugs */
4771 SSL_OP_NO_SSLv2 |
4772 SSL_OP_NO_COMPRESSION |
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02004773 SSL_OP_SINGLE_DH_USE |
Emeric Brun2b58d042012-09-20 17:10:03 +02004774 SSL_OP_SINGLE_ECDH_USE |
Emeric Brun3c4bc6e2012-10-04 18:44:19 +02004775 SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION |
Lukas Tribus926594f2018-05-18 17:55:57 +02004776 SSL_OP_PRIORITIZE_CHACHA |
Emeric Brun3c4bc6e2012-10-04 18:44:19 +02004777 SSL_OP_CIPHER_SERVER_PREFERENCE;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004778 long mode =
Emeric Brunfc0421f2012-09-07 17:30:07 +02004779 SSL_MODE_ENABLE_PARTIAL_WRITE |
4780 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
Willy Tarreau396a1862014-11-13 14:06:52 +01004781 SSL_MODE_RELEASE_BUFFERS |
4782 SSL_MODE_SMALL_BUFFERS;
Emmanuel Hocdet43664762017-08-09 18:26:20 +02004783 struct tls_version_filter *conf_ssl_methods = &bind_conf->ssl_conf.ssl_methods;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004784 int i, min, max, hole;
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004785 int flags = MC_SSL_O_ALL;
4786 int cfgerr = 0;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004787
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004788 ctx = SSL_CTX_new(SSLv23_server_method());
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004789 bind_conf->initial_ctx = ctx;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004790
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004791 if (conf_ssl_methods->flags && (conf_ssl_methods->min || conf_ssl_methods->max))
Christopher Faulet767a84b2017-11-24 16:50:31 +01004792 ha_warning("Proxy '%s': no-sslv3/no-tlsv1x are ignored for bind '%s' at [%s:%d]. "
4793 "Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
4794 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004795 else
4796 flags = conf_ssl_methods->flags;
4797
Emmanuel Hocdetbd695fe2017-05-15 15:53:41 +02004798 min = conf_ssl_methods->min;
4799 max = conf_ssl_methods->max;
4800 /* start with TLSv10 to remove SSLv3 per default */
4801 if (!min && (!max || max >= CONF_TLSV10))
4802 min = CONF_TLSV10;
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004803 /* Real min and max should be determinate with configuration and openssl's capabilities */
Emmanuel Hocdetbd695fe2017-05-15 15:53:41 +02004804 if (min)
4805 flags |= (methodVersions[min].flag - 1);
4806 if (max)
4807 flags |= ~((methodVersions[max].flag << 1) - 1);
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004808 /* find min, max and holes */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004809 min = max = CONF_TLSV_NONE;
4810 hole = 0;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004811 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004812 /* version is in openssl && version not disable in configuration */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004813 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004814 if (min) {
4815 if (hole) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004816 ha_warning("Proxy '%s': SSL/TLS versions range not contiguous for bind '%s' at [%s:%d]. "
4817 "Hole find for %s. Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
4818 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line,
4819 methodVersions[hole].name);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004820 hole = 0;
4821 }
4822 max = i;
4823 }
4824 else {
4825 min = max = i;
4826 }
4827 }
4828 else {
4829 if (min)
4830 hole = i;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004831 }
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004832 if (!min) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004833 ha_alert("Proxy '%s': all SSL/TLS versions are disabled for bind '%s' at [%s:%d].\n",
4834 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004835 cfgerr += 1;
4836 }
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02004837 /* save real min/max in bind_conf */
4838 conf_ssl_methods->min = min;
4839 conf_ssl_methods->max = max;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004840
Willy Tarreau9a1ab082019-05-09 13:26:41 +02004841#if (HA_OPENSSL_VERSION_NUMBER < 0x1010000fL)
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004842 /* Keep force-xxx implementation as it is in older haproxy. It's a
Joseph Herlant017b3da2018-11-15 09:07:59 -08004843 precautionary measure to avoid any surprise with older openssl version. */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004844 if (min == max)
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004845 methodVersions[min].ctx_set_version(ctx, SET_SERVER);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004846 else
4847 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
4848 if (flags & methodVersions[i].flag)
4849 options |= methodVersions[i].option;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004850#else /* openssl >= 1.1.0 */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004851 /* set the max_version is required to cap TLS version or activate new TLS (v1.3) */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004852 methodVersions[min].ctx_set_version(ctx, SET_MIN);
4853 methodVersions[max].ctx_set_version(ctx, SET_MAX);
Emeric Brunfa5c5c82017-04-28 16:19:51 +02004854#endif
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004855
4856 if (bind_conf->ssl_options & BC_SSL_O_NO_TLS_TICKETS)
4857 options |= SSL_OP_NO_TICKET;
4858 if (bind_conf->ssl_options & BC_SSL_O_PREF_CLIE_CIPH)
4859 options &= ~SSL_OP_CIPHER_SERVER_PREFERENCE;
Dirkjan Bussink526894f2019-01-21 09:35:03 -08004860
4861#ifdef SSL_OP_NO_RENEGOTIATION
4862 options |= SSL_OP_NO_RENEGOTIATION;
4863#endif
4864
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004865 SSL_CTX_set_options(ctx, options);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004866
Willy Tarreau5db847a2019-05-09 14:13:35 +02004867#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004868 if (global_ssl.async)
4869 mode |= SSL_MODE_ASYNC;
4870#endif
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004871 SSL_CTX_set_mode(ctx, mode);
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004872 if (global_ssl.life_time)
4873 SSL_CTX_set_timeout(ctx, global_ssl.life_time);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004874
4875#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
4876#ifdef OPENSSL_IS_BORINGSSL
4877 SSL_CTX_set_select_certificate_cb(ctx, ssl_sock_switchctx_cbk);
4878 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_err_cbk);
Ilya Shipitsine9ff8992020-01-19 12:20:14 +05004879#elif defined(SSL_OP_NO_ANTI_REPLAY)
Olivier Houchard545989f2019-12-17 15:39:54 +01004880 if (bind_conf->ssl_conf.early_data)
Olivier Houchard51088ce2019-01-02 18:46:41 +01004881 SSL_CTX_set_options(ctx, SSL_OP_NO_ANTI_REPLAY);
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02004882 SSL_CTX_set_client_hello_cb(ctx, ssl_sock_switchctx_cbk, NULL);
4883 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_err_cbk);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004884#else
4885 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_cbk);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004886#endif
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02004887 SSL_CTX_set_tlsext_servername_arg(ctx, bind_conf);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004888#endif
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004889 return cfgerr;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004890}
4891
William Lallemand4f45bb92017-10-30 20:08:51 +01004892
4893static inline void sh_ssl_sess_free_blocks(struct shared_block *first, struct shared_block *block)
4894{
4895 if (first == block) {
4896 struct sh_ssl_sess_hdr *sh_ssl_sess = (struct sh_ssl_sess_hdr *)first->data;
4897 if (first->len > 0)
4898 sh_ssl_sess_tree_delete(sh_ssl_sess);
4899 }
4900}
4901
4902/* return first block from sh_ssl_sess */
4903static inline struct shared_block *sh_ssl_sess_first_block(struct sh_ssl_sess_hdr *sh_ssl_sess)
4904{
4905 return (struct shared_block *)((unsigned char *)sh_ssl_sess - ((struct shared_block *)NULL)->data);
4906
4907}
4908
4909/* store a session into the cache
4910 * s_id : session id padded with zero to SSL_MAX_SSL_SESSION_ID_LENGTH
4911 * data: asn1 encoded session
4912 * data_len: asn1 encoded session length
4913 * Returns 1 id session was stored (else 0)
4914 */
4915static int sh_ssl_sess_store(unsigned char *s_id, unsigned char *data, int data_len)
4916{
4917 struct shared_block *first;
4918 struct sh_ssl_sess_hdr *sh_ssl_sess, *oldsh_ssl_sess;
4919
Frédéric Lécaille0bec8072018-10-22 17:55:57 +02004920 first = shctx_row_reserve_hot(ssl_shctx, NULL, data_len + sizeof(struct sh_ssl_sess_hdr));
William Lallemand4f45bb92017-10-30 20:08:51 +01004921 if (!first) {
4922 /* Could not retrieve enough free blocks to store that session */
4923 return 0;
4924 }
4925
4926 /* STORE the key in the first elem */
4927 sh_ssl_sess = (struct sh_ssl_sess_hdr *)first->data;
4928 memcpy(sh_ssl_sess->key_data, s_id, SSL_MAX_SSL_SESSION_ID_LENGTH);
4929 first->len = sizeof(struct sh_ssl_sess_hdr);
4930
4931 /* it returns the already existing node
4932 or current node if none, never returns null */
4933 oldsh_ssl_sess = sh_ssl_sess_tree_insert(sh_ssl_sess);
4934 if (oldsh_ssl_sess != sh_ssl_sess) {
4935 /* NOTE: Row couldn't be in use because we lock read & write function */
4936 /* release the reserved row */
4937 shctx_row_dec_hot(ssl_shctx, first);
4938 /* replace the previous session already in the tree */
4939 sh_ssl_sess = oldsh_ssl_sess;
4940 /* ignore the previous session data, only use the header */
4941 first = sh_ssl_sess_first_block(sh_ssl_sess);
4942 shctx_row_inc_hot(ssl_shctx, first);
4943 first->len = sizeof(struct sh_ssl_sess_hdr);
4944 }
4945
Frédéric Lécaille0bec8072018-10-22 17:55:57 +02004946 if (shctx_row_data_append(ssl_shctx, first, NULL, data, data_len) < 0) {
William Lallemand99b90af2018-01-03 19:15:51 +01004947 shctx_row_dec_hot(ssl_shctx, first);
William Lallemand4f45bb92017-10-30 20:08:51 +01004948 return 0;
William Lallemand99b90af2018-01-03 19:15:51 +01004949 }
4950
4951 shctx_row_dec_hot(ssl_shctx, first);
William Lallemand4f45bb92017-10-30 20:08:51 +01004952
4953 return 1;
4954}
William Lallemanded0b5ad2017-10-30 19:36:36 +01004955
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004956/* SSL callback used when a new session is created while connecting to a server */
4957static int ssl_sess_new_srv_cb(SSL *ssl, SSL_SESSION *sess)
4958{
Thierry FOURNIER28962c92018-06-17 21:37:05 +02004959 struct connection *conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Olivier Houcharde6060c52017-11-16 17:42:52 +01004960 struct server *s;
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004961
Willy Tarreau07d94e42018-09-20 10:57:52 +02004962 s = __objt_server(conn->target);
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004963
Olivier Houcharde6060c52017-11-16 17:42:52 +01004964 if (!(s->ssl_ctx.options & SRV_SSL_O_NO_REUSE)) {
4965 int len;
4966 unsigned char *ptr;
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004967
Olivier Houcharde6060c52017-11-16 17:42:52 +01004968 len = i2d_SSL_SESSION(sess, NULL);
4969 if (s->ssl_ctx.reused_sess[tid].ptr && s->ssl_ctx.reused_sess[tid].allocated_size >= len) {
4970 ptr = s->ssl_ctx.reused_sess[tid].ptr;
4971 } else {
4972 free(s->ssl_ctx.reused_sess[tid].ptr);
4973 ptr = s->ssl_ctx.reused_sess[tid].ptr = malloc(len);
4974 s->ssl_ctx.reused_sess[tid].allocated_size = len;
4975 }
4976 if (s->ssl_ctx.reused_sess[tid].ptr) {
4977 s->ssl_ctx.reused_sess[tid].size = i2d_SSL_SESSION(sess,
4978 &ptr);
4979 }
4980 } else {
4981 free(s->ssl_ctx.reused_sess[tid].ptr);
4982 s->ssl_ctx.reused_sess[tid].ptr = NULL;
4983 }
4984
4985 return 0;
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004986}
4987
Olivier Houcharde6060c52017-11-16 17:42:52 +01004988
William Lallemanded0b5ad2017-10-30 19:36:36 +01004989/* SSL callback used on new session creation */
William Lallemand4f45bb92017-10-30 20:08:51 +01004990int sh_ssl_sess_new_cb(SSL *ssl, SSL_SESSION *sess)
William Lallemanded0b5ad2017-10-30 19:36:36 +01004991{
4992 unsigned char encsess[SHSESS_MAX_DATA_LEN]; /* encoded session */
4993 unsigned char encid[SSL_MAX_SSL_SESSION_ID_LENGTH]; /* encoded id */
4994 unsigned char *p;
4995 int data_len;
Emeric Bruneb469652019-10-08 18:27:37 +02004996 unsigned int sid_length;
William Lallemanded0b5ad2017-10-30 19:36:36 +01004997 const unsigned char *sid_data;
William Lallemanded0b5ad2017-10-30 19:36:36 +01004998
4999 /* Session id is already stored in to key and session id is known
5000 * so we dont store it to keep size.
Emeric Bruneb469652019-10-08 18:27:37 +02005001 * note: SSL_SESSION_set1_id is using
5002 * a memcpy so we need to use a different pointer
5003 * than sid_data or sid_ctx_data to avoid valgrind
5004 * complaining.
William Lallemanded0b5ad2017-10-30 19:36:36 +01005005 */
5006
5007 sid_data = SSL_SESSION_get_id(sess, &sid_length);
Emeric Bruneb469652019-10-08 18:27:37 +02005008
5009 /* copy value in an other buffer */
5010 memcpy(encid, sid_data, sid_length);
5011
5012 /* pad with 0 */
5013 if (sid_length < SSL_MAX_SSL_SESSION_ID_LENGTH)
5014 memset(encid + sid_length, 0, SSL_MAX_SSL_SESSION_ID_LENGTH-sid_length);
5015
5016 /* force length to zero to avoid ASN1 encoding */
5017 SSL_SESSION_set1_id(sess, encid, 0);
5018
5019 /* force length to zero to avoid ASN1 encoding */
5020 SSL_SESSION_set1_id_context(sess, (const unsigned char *)SHCTX_APPNAME, 0);
William Lallemanded0b5ad2017-10-30 19:36:36 +01005021
5022 /* check if buffer is large enough for the ASN1 encoded session */
5023 data_len = i2d_SSL_SESSION(sess, NULL);
5024 if (data_len > SHSESS_MAX_DATA_LEN)
5025 goto err;
5026
5027 p = encsess;
5028
5029 /* process ASN1 session encoding before the lock */
5030 i2d_SSL_SESSION(sess, &p);
5031
William Lallemanded0b5ad2017-10-30 19:36:36 +01005032
William Lallemanda3c77cf2017-10-30 23:44:40 +01005033 shctx_lock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01005034 /* store to cache */
William Lallemand4f45bb92017-10-30 20:08:51 +01005035 sh_ssl_sess_store(encid, encsess, data_len);
William Lallemanda3c77cf2017-10-30 23:44:40 +01005036 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01005037err:
5038 /* reset original length values */
Emeric Bruneb469652019-10-08 18:27:37 +02005039 SSL_SESSION_set1_id(sess, encid, sid_length);
5040 SSL_SESSION_set1_id_context(sess, (const unsigned char *)SHCTX_APPNAME, strlen(SHCTX_APPNAME));
William Lallemanded0b5ad2017-10-30 19:36:36 +01005041
5042 return 0; /* do not increment session reference count */
5043}
5044
5045/* SSL callback used on lookup an existing session cause none found in internal cache */
William Lallemand4f45bb92017-10-30 20:08:51 +01005046SSL_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 +01005047{
William Lallemand4f45bb92017-10-30 20:08:51 +01005048 struct sh_ssl_sess_hdr *sh_ssl_sess;
William Lallemanded0b5ad2017-10-30 19:36:36 +01005049 unsigned char data[SHSESS_MAX_DATA_LEN], *p;
5050 unsigned char tmpkey[SSL_MAX_SSL_SESSION_ID_LENGTH];
William Lallemanded0b5ad2017-10-30 19:36:36 +01005051 SSL_SESSION *sess;
William Lallemand4f45bb92017-10-30 20:08:51 +01005052 struct shared_block *first;
William Lallemanded0b5ad2017-10-30 19:36:36 +01005053
5054 global.shctx_lookups++;
5055
5056 /* allow the session to be freed automatically by openssl */
5057 *do_copy = 0;
5058
5059 /* tree key is zeros padded sessionid */
5060 if (key_len < SSL_MAX_SSL_SESSION_ID_LENGTH) {
5061 memcpy(tmpkey, key, key_len);
5062 memset(tmpkey + key_len, 0, SSL_MAX_SSL_SESSION_ID_LENGTH - key_len);
5063 key = tmpkey;
5064 }
5065
5066 /* lock cache */
William Lallemanda3c77cf2017-10-30 23:44:40 +01005067 shctx_lock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01005068
5069 /* lookup for session */
William Lallemand4f45bb92017-10-30 20:08:51 +01005070 sh_ssl_sess = sh_ssl_sess_tree_lookup(key);
5071 if (!sh_ssl_sess) {
William Lallemanded0b5ad2017-10-30 19:36:36 +01005072 /* no session found: unlock cache and exit */
William Lallemanda3c77cf2017-10-30 23:44:40 +01005073 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01005074 global.shctx_misses++;
5075 return NULL;
5076 }
5077
William Lallemand4f45bb92017-10-30 20:08:51 +01005078 /* sh_ssl_sess (shared_block->data) is at the end of shared_block */
5079 first = sh_ssl_sess_first_block(sh_ssl_sess);
William Lallemanded0b5ad2017-10-30 19:36:36 +01005080
William Lallemand4f45bb92017-10-30 20:08:51 +01005081 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 +01005082
William Lallemanda3c77cf2017-10-30 23:44:40 +01005083 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01005084
5085 /* decode ASN1 session */
5086 p = data;
William Lallemand4f45bb92017-10-30 20:08:51 +01005087 sess = d2i_SSL_SESSION(NULL, (const unsigned char **)&p, first->len-sizeof(struct sh_ssl_sess_hdr));
William Lallemanded0b5ad2017-10-30 19:36:36 +01005088 /* Reset session id and session id contenxt */
5089 if (sess) {
5090 SSL_SESSION_set1_id(sess, key, key_len);
5091 SSL_SESSION_set1_id_context(sess, (const unsigned char *)SHCTX_APPNAME, strlen(SHCTX_APPNAME));
5092 }
5093
5094 return sess;
5095}
5096
William Lallemand4f45bb92017-10-30 20:08:51 +01005097
William Lallemanded0b5ad2017-10-30 19:36:36 +01005098/* SSL callback used to signal session is no more used in internal cache */
William Lallemand4f45bb92017-10-30 20:08:51 +01005099void sh_ssl_sess_remove_cb(SSL_CTX *ctx, SSL_SESSION *sess)
William Lallemanded0b5ad2017-10-30 19:36:36 +01005100{
William Lallemand4f45bb92017-10-30 20:08:51 +01005101 struct sh_ssl_sess_hdr *sh_ssl_sess;
William Lallemanded0b5ad2017-10-30 19:36:36 +01005102 unsigned char tmpkey[SSL_MAX_SSL_SESSION_ID_LENGTH];
5103 unsigned int sid_length;
5104 const unsigned char *sid_data;
5105 (void)ctx;
5106
5107 sid_data = SSL_SESSION_get_id(sess, &sid_length);
5108 /* tree key is zeros padded sessionid */
5109 if (sid_length < SSL_MAX_SSL_SESSION_ID_LENGTH) {
5110 memcpy(tmpkey, sid_data, sid_length);
5111 memset(tmpkey+sid_length, 0, SSL_MAX_SSL_SESSION_ID_LENGTH - sid_length);
5112 sid_data = tmpkey;
5113 }
5114
William Lallemanda3c77cf2017-10-30 23:44:40 +01005115 shctx_lock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01005116
5117 /* lookup for session */
William Lallemand4f45bb92017-10-30 20:08:51 +01005118 sh_ssl_sess = sh_ssl_sess_tree_lookup(sid_data);
5119 if (sh_ssl_sess) {
William Lallemanded0b5ad2017-10-30 19:36:36 +01005120 /* free session */
William Lallemand4f45bb92017-10-30 20:08:51 +01005121 sh_ssl_sess_tree_delete(sh_ssl_sess);
William Lallemanded0b5ad2017-10-30 19:36:36 +01005122 }
5123
5124 /* unlock cache */
William Lallemanda3c77cf2017-10-30 23:44:40 +01005125 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01005126}
5127
5128/* Set session cache mode to server and disable openssl internal cache.
5129 * Set shared cache callbacks on an ssl context.
5130 * Shared context MUST be firstly initialized */
William Lallemand4f45bb92017-10-30 20:08:51 +01005131void ssl_set_shctx(SSL_CTX *ctx)
William Lallemanded0b5ad2017-10-30 19:36:36 +01005132{
5133 SSL_CTX_set_session_id_context(ctx, (const unsigned char *)SHCTX_APPNAME, strlen(SHCTX_APPNAME));
5134
5135 if (!ssl_shctx) {
5136 SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF);
5137 return;
5138 }
5139
5140 SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_SERVER |
5141 SSL_SESS_CACHE_NO_INTERNAL |
5142 SSL_SESS_CACHE_NO_AUTO_CLEAR);
5143
5144 /* Set callbacks */
William Lallemand4f45bb92017-10-30 20:08:51 +01005145 SSL_CTX_sess_set_new_cb(ctx, sh_ssl_sess_new_cb);
5146 SSL_CTX_sess_set_get_cb(ctx, sh_ssl_sess_get_cb);
5147 SSL_CTX_sess_set_remove_cb(ctx, sh_ssl_sess_remove_cb);
William Lallemanded0b5ad2017-10-30 19:36:36 +01005148}
5149
William Lallemand8b453912019-11-21 15:48:10 +01005150/*
5151 * This function applies the SSL configuration on a SSL_CTX
5152 * It returns an error code and fills the <err> buffer
5153 */
5154int 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 +01005155{
5156 struct proxy *curproxy = bind_conf->frontend;
5157 int cfgerr = 0;
5158 int verify = SSL_VERIFY_NONE;
Willy Tarreau5d4cafb2018-01-04 18:55:19 +01005159 struct ssl_bind_conf __maybe_unused *ssl_conf_cur;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005160 const char *conf_ciphers;
Emmanuel Hocdet839af572019-05-14 16:27:35 +02005161#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02005162 const char *conf_ciphersuites;
5163#endif
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01005164 const char *conf_curves = NULL;
Emeric Brunfc0421f2012-09-07 17:30:07 +02005165
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02005166 if (ssl_conf) {
5167 struct tls_version_filter *conf_ssl_methods = &ssl_conf->ssl_methods;
5168 int i, min, max;
5169 int flags = MC_SSL_O_ALL;
5170
5171 /* Real min and max should be determinate with configuration and openssl's capabilities */
Emmanuel Hocdet43664762017-08-09 18:26:20 +02005172 min = conf_ssl_methods->min ? conf_ssl_methods->min : bind_conf->ssl_conf.ssl_methods.min;
5173 max = conf_ssl_methods->max ? conf_ssl_methods->max : bind_conf->ssl_conf.ssl_methods.max;
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02005174 if (min)
5175 flags |= (methodVersions[min].flag - 1);
5176 if (max)
5177 flags |= ~((methodVersions[max].flag << 1) - 1);
5178 min = max = CONF_TLSV_NONE;
5179 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
5180 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
5181 if (min)
5182 max = i;
5183 else
5184 min = max = i;
5185 }
5186 /* save real min/max */
5187 conf_ssl_methods->min = min;
5188 conf_ssl_methods->max = max;
5189 if (!min) {
Tim Duesterhus93128532019-11-23 23:45:10 +01005190 memprintf(err, "%sProxy '%s': all SSL/TLS versions are disabled for bind '%s' at [%s:%d].\n",
5191 err && *err ? *err : "", bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
William Lallemand8b453912019-11-21 15:48:10 +01005192 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02005193 }
5194 }
5195
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005196 switch ((ssl_conf && ssl_conf->verify) ? ssl_conf->verify : bind_conf->ssl_conf.verify) {
Emeric Brun850efd52014-01-29 12:24:34 +01005197 case SSL_SOCK_VERIFY_NONE:
5198 verify = SSL_VERIFY_NONE;
5199 break;
5200 case SSL_SOCK_VERIFY_OPTIONAL:
5201 verify = SSL_VERIFY_PEER;
5202 break;
5203 case SSL_SOCK_VERIFY_REQUIRED:
5204 verify = SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
5205 break;
5206 }
5207 SSL_CTX_set_verify(ctx, verify, ssl_sock_bind_verifycbk);
5208 if (verify & SSL_VERIFY_PEER) {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005209 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 +01005210 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 +01005211 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 +01005212 if (ca_file || ca_verify_file) {
Emmanuel Hocdetd4f9a602019-10-24 11:32:47 +02005213 /* set CAfile to verify */
Emmanuel Hocdet842e94e2019-12-16 16:39:17 +01005214 if (ca_file && !ssl_set_verify_locations_file(ctx, ca_file)) {
Emmanuel Hocdetd4f9a602019-10-24 11:32:47 +02005215 memprintf(err, "%sProxy '%s': unable to set CA file '%s' for bind '%s' at [%s:%d].\n",
Tim Duesterhus93128532019-11-23 23:45:10 +01005216 err && *err ? *err : "", curproxy->id, ca_file, bind_conf->arg, bind_conf->file, bind_conf->line);
William Lallemand8b453912019-11-21 15:48:10 +01005217 cfgerr |= ERR_ALERT | ERR_FATAL;
Emeric Brund94b3fe2012-09-20 18:23:56 +02005218 }
Emmanuel Hocdet842e94e2019-12-16 16:39:17 +01005219 if (ca_verify_file && !ssl_set_verify_locations_file(ctx, ca_verify_file)) {
5220 memprintf(err, "%sProxy '%s': unable to set CA-no-names file '%s' for bind '%s' at [%s:%d].\n",
5221 err && *err ? *err : "", curproxy->id, ca_verify_file, bind_conf->arg, bind_conf->file, bind_conf->line);
5222 cfgerr |= ERR_ALERT | ERR_FATAL;
5223 }
5224 if (ca_file && !((ssl_conf && ssl_conf->no_ca_names) || bind_conf->ssl_conf.no_ca_names)) {
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02005225 /* set CA names for client cert request, function returns void */
Emmanuel Hocdet129d3282019-10-24 18:08:51 +02005226 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 +02005227 }
Emeric Brund94b3fe2012-09-20 18:23:56 +02005228 }
Emeric Brun850efd52014-01-29 12:24:34 +01005229 else {
Tim Duesterhus93128532019-11-23 23:45:10 +01005230 memprintf(err, "%sProxy '%s': verify is enabled but no CA file specified for bind '%s' at [%s:%d].\n",
5231 err && *err ? *err : "", curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
William Lallemand8b453912019-11-21 15:48:10 +01005232 cfgerr |= ERR_ALERT | ERR_FATAL;
Emeric Brun850efd52014-01-29 12:24:34 +01005233 }
Emeric Brun051cdab2012-10-02 19:25:50 +02005234#ifdef X509_V_FLAG_CRL_CHECK
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005235 if (crl_file) {
Emeric Brund94b3fe2012-09-20 18:23:56 +02005236 X509_STORE *store = SSL_CTX_get_cert_store(ctx);
5237
Emmanuel Hocdetb270e812019-11-21 19:09:31 +01005238 if (!ssl_set_cert_crl_file(store, crl_file)) {
Tim Duesterhus93128532019-11-23 23:45:10 +01005239 memprintf(err, "%sProxy '%s': unable to configure CRL file '%s' for bind '%s' at [%s:%d].\n",
5240 err && *err ? *err : "", curproxy->id, crl_file, bind_conf->arg, bind_conf->file, bind_conf->line);
William Lallemand8b453912019-11-21 15:48:10 +01005241 cfgerr |= ERR_ALERT | ERR_FATAL;
Emeric Brund94b3fe2012-09-20 18:23:56 +02005242 }
Emeric Brun561e5742012-10-02 15:20:55 +02005243 else {
5244 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
5245 }
Emeric Brund94b3fe2012-09-20 18:23:56 +02005246 }
Emeric Brun051cdab2012-10-02 19:25:50 +02005247#endif
Emeric Brun644cde02012-12-14 11:21:13 +01005248 ERR_clear_error();
Emeric Brund94b3fe2012-09-20 18:23:56 +02005249 }
Nenad Merdanovic05552d42015-02-27 19:56:49 +01005250#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
Nenad Merdanovic146defa2015-05-09 08:46:00 +02005251 if(bind_conf->keys_ref) {
Nenad Merdanovic05552d42015-02-27 19:56:49 +01005252 if (!SSL_CTX_set_tlsext_ticket_key_cb(ctx, ssl_tlsext_ticket_key_cb)) {
Tim Duesterhus93128532019-11-23 23:45:10 +01005253 memprintf(err, "%sProxy '%s': unable to set callback for TLS ticket validation for bind '%s' at [%s:%d].\n",
5254 err && *err ? *err : "", curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
William Lallemand8b453912019-11-21 15:48:10 +01005255 cfgerr |= ERR_ALERT | ERR_FATAL;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01005256 }
5257 }
5258#endif
5259
William Lallemand4f45bb92017-10-30 20:08:51 +01005260 ssl_set_shctx(ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005261 conf_ciphers = (ssl_conf && ssl_conf->ciphers) ? ssl_conf->ciphers : bind_conf->ssl_conf.ciphers;
5262 if (conf_ciphers &&
5263 !SSL_CTX_set_cipher_list(ctx, conf_ciphers)) {
Tim Duesterhus93128532019-11-23 23:45:10 +01005264 memprintf(err, "%sProxy '%s': unable to set SSL cipher list to '%s' for bind '%s' at [%s:%d].\n",
5265 err && *err ? *err : "", curproxy->id, conf_ciphers, bind_conf->arg, bind_conf->file, bind_conf->line);
William Lallemand8b453912019-11-21 15:48:10 +01005266 cfgerr |= ERR_ALERT | ERR_FATAL;
Emeric Brunfc0421f2012-09-07 17:30:07 +02005267 }
5268
Emmanuel Hocdet839af572019-05-14 16:27:35 +02005269#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02005270 conf_ciphersuites = (ssl_conf && ssl_conf->ciphersuites) ? ssl_conf->ciphersuites : bind_conf->ssl_conf.ciphersuites;
5271 if (conf_ciphersuites &&
5272 !SSL_CTX_set_ciphersuites(ctx, conf_ciphersuites)) {
Tim Duesterhus93128532019-11-23 23:45:10 +01005273 memprintf(err, "%sProxy '%s': unable to set TLS 1.3 cipher suites to '%s' for bind '%s' at [%s:%d].\n",
5274 err && *err ? *err : "", curproxy->id, conf_ciphersuites, bind_conf->arg, bind_conf->file, bind_conf->line);
William Lallemand8b453912019-11-21 15:48:10 +01005275 cfgerr |= ERR_ALERT | ERR_FATAL;
Dirkjan Bussink415150f2018-09-14 11:14:21 +02005276 }
5277#endif
5278
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01005279#ifndef OPENSSL_NO_DH
Remi Gacogne47783ef2015-05-29 15:53:22 +02005280 /* If tune.ssl.default-dh-param has not been set,
5281 neither has ssl-default-dh-file and no static DH
5282 params were in the certificate file. */
Willy Tarreauef934602016-12-22 23:12:01 +01005283 if (global_ssl.default_dh_param == 0 &&
Remi Gacogne47783ef2015-05-29 15:53:22 +02005284 global_dh == NULL &&
Remi Gacogne4f902b82015-05-28 16:23:00 +02005285 (ssl_dh_ptr_index == -1 ||
5286 SSL_CTX_get_ex_data(ctx, ssl_dh_ptr_index) == NULL)) {
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01005287 STACK_OF(SSL_CIPHER) * ciphers = NULL;
5288 const SSL_CIPHER * cipher = NULL;
5289 char cipher_description[128];
5290 /* The description of ciphers using an Ephemeral Diffie Hellman key exchange
5291 contains " Kx=DH " or " Kx=DH(". Beware of " Kx=DH/",
5292 which is not ephemeral DH. */
5293 const char dhe_description[] = " Kx=DH ";
5294 const char dhe_export_description[] = " Kx=DH(";
5295 int idx = 0;
5296 int dhe_found = 0;
5297 SSL *ssl = NULL;
Lukas Tribus90132722014-08-18 00:56:33 +02005298
Remi Gacogne23d5d372014-10-10 17:04:26 +02005299 ssl = SSL_new(ctx);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02005300
Remi Gacogne23d5d372014-10-10 17:04:26 +02005301 if (ssl) {
5302 ciphers = SSL_get_ciphers(ssl);
5303
5304 if (ciphers) {
5305 for (idx = 0; idx < sk_SSL_CIPHER_num(ciphers); idx++) {
5306 cipher = sk_SSL_CIPHER_value(ciphers, idx);
5307 if (SSL_CIPHER_description(cipher, cipher_description, sizeof (cipher_description)) == cipher_description) {
5308 if (strstr(cipher_description, dhe_description) != NULL ||
5309 strstr(cipher_description, dhe_export_description) != NULL) {
5310 dhe_found = 1;
5311 break;
5312 }
Remi Gacognec1eab8c2014-06-12 18:20:11 +02005313 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02005314 }
5315 }
Remi Gacogne23d5d372014-10-10 17:04:26 +02005316 SSL_free(ssl);
5317 ssl = NULL;
Lukas Tribus90132722014-08-18 00:56:33 +02005318 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02005319
Lukas Tribus90132722014-08-18 00:56:33 +02005320 if (dhe_found) {
Tim Duesterhus93128532019-11-23 23:45:10 +01005321 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",
5322 err && *err ? *err : "");
William Lallemand8b453912019-11-21 15:48:10 +01005323 cfgerr |= ERR_WARN;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02005324 }
5325
Willy Tarreauef934602016-12-22 23:12:01 +01005326 global_ssl.default_dh_param = 1024;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02005327 }
Remi Gacogne8de54152014-07-15 11:36:40 +02005328
Willy Tarreauef934602016-12-22 23:12:01 +01005329 if (global_ssl.default_dh_param >= 1024) {
Remi Gacogne8de54152014-07-15 11:36:40 +02005330 if (local_dh_1024 == NULL) {
5331 local_dh_1024 = ssl_get_dh_1024();
5332 }
Willy Tarreauef934602016-12-22 23:12:01 +01005333 if (global_ssl.default_dh_param >= 2048) {
Remi Gacogne8de54152014-07-15 11:36:40 +02005334 if (local_dh_2048 == NULL) {
5335 local_dh_2048 = ssl_get_dh_2048();
5336 }
Willy Tarreauef934602016-12-22 23:12:01 +01005337 if (global_ssl.default_dh_param >= 4096) {
Remi Gacogne8de54152014-07-15 11:36:40 +02005338 if (local_dh_4096 == NULL) {
5339 local_dh_4096 = ssl_get_dh_4096();
5340 }
Remi Gacogne8de54152014-07-15 11:36:40 +02005341 }
5342 }
5343 }
5344#endif /* OPENSSL_NO_DH */
Remi Gacognef46cd6e2014-06-12 14:58:40 +02005345
Emeric Brunfc0421f2012-09-07 17:30:07 +02005346 SSL_CTX_set_info_callback(ctx, ssl_sock_infocbk);
Willy Tarreau9a1ab082019-05-09 13:26:41 +02005347#if HA_OPENSSL_VERSION_NUMBER >= 0x00907000L
Emeric Brun29f037d2014-04-25 19:05:36 +02005348 SSL_CTX_set_msg_callback(ctx, ssl_sock_msgcbk);
Willy Tarreau5cbe4ef2014-05-08 22:45:11 +02005349#endif
Emeric Brun29f037d2014-04-25 19:05:36 +02005350
Bernard Spil13c53f82018-02-15 13:34:58 +01005351#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005352 ssl_conf_cur = NULL;
5353 if (ssl_conf && ssl_conf->npn_str)
5354 ssl_conf_cur = ssl_conf;
5355 else if (bind_conf->ssl_conf.npn_str)
5356 ssl_conf_cur = &bind_conf->ssl_conf;
5357 if (ssl_conf_cur)
5358 SSL_CTX_set_next_protos_advertised_cb(ctx, ssl_sock_advertise_npn_protos, ssl_conf_cur);
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02005359#endif
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01005360#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005361 ssl_conf_cur = NULL;
5362 if (ssl_conf && ssl_conf->alpn_str)
5363 ssl_conf_cur = ssl_conf;
5364 else if (bind_conf->ssl_conf.alpn_str)
5365 ssl_conf_cur = &bind_conf->ssl_conf;
5366 if (ssl_conf_cur)
5367 SSL_CTX_set_alpn_select_cb(ctx, ssl_sock_advertise_alpn_protos, ssl_conf_cur);
Willy Tarreauab861d32013-04-02 02:30:41 +02005368#endif
Lukas Tribusd14b49c2019-11-24 18:20:40 +01005369#if ((HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL) || defined(LIBRESSL_VERSION_NUMBER))
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01005370 conf_curves = (ssl_conf && ssl_conf->curves) ? ssl_conf->curves : bind_conf->ssl_conf.curves;
5371 if (conf_curves) {
5372 if (!SSL_CTX_set1_curves_list(ctx, conf_curves)) {
Tim Duesterhus93128532019-11-23 23:45:10 +01005373 memprintf(err, "%sProxy '%s': unable to set SSL curves list to '%s' for bind '%s' at [%s:%d].\n",
5374 err && *err ? *err : "", curproxy->id, conf_curves, bind_conf->arg, bind_conf->file, bind_conf->line);
William Lallemand8b453912019-11-21 15:48:10 +01005375 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01005376 }
Emmanuel Hocdeta52bb152017-03-20 11:11:49 +01005377 (void)SSL_CTX_set_ecdh_auto(ctx, 1);
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01005378 }
5379#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02005380#if defined(SSL_CTX_set_tmp_ecdh) && !defined(OPENSSL_NO_ECDH)
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01005381 if (!conf_curves) {
Emeric Brun2b58d042012-09-20 17:10:03 +02005382 int i;
5383 EC_KEY *ecdh;
Willy Tarreau9a1ab082019-05-09 13:26:41 +02005384#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005385 const char *ecdhe = (ssl_conf && ssl_conf->ecdhe) ? ssl_conf->ecdhe :
Olivier Houchardc2aae742017-09-22 18:26:28 +02005386 (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe :
5387 NULL);
5388
5389 if (ecdhe == NULL) {
Eric Salama3c8bde82019-11-20 11:33:40 +01005390 (void)SSL_CTX_set_ecdh_auto(ctx, 1);
Olivier Houchardc2aae742017-09-22 18:26:28 +02005391 return cfgerr;
5392 }
5393#else
5394 const char *ecdhe = (ssl_conf && ssl_conf->ecdhe) ? ssl_conf->ecdhe :
5395 (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe :
5396 ECDHE_DEFAULT_CURVE);
5397#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02005398
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005399 i = OBJ_sn2nid(ecdhe);
Emeric Brun2b58d042012-09-20 17:10:03 +02005400 if (!i || ((ecdh = EC_KEY_new_by_curve_name(i)) == NULL)) {
Tim Duesterhus93128532019-11-23 23:45:10 +01005401 memprintf(err, "%sProxy '%s': unable to set elliptic named curve to '%s' for bind '%s' at [%s:%d].\n",
5402 err && *err ? *err : "", curproxy->id, ecdhe, bind_conf->arg, bind_conf->file, bind_conf->line);
William Lallemand8b453912019-11-21 15:48:10 +01005403 cfgerr |= ERR_ALERT | ERR_FATAL;
Emeric Brun2b58d042012-09-20 17:10:03 +02005404 }
5405 else {
5406 SSL_CTX_set_tmp_ecdh(ctx, ecdh);
5407 EC_KEY_free(ecdh);
5408 }
5409 }
5410#endif
5411
Emeric Brunfc0421f2012-09-07 17:30:07 +02005412 return cfgerr;
5413}
5414
Evan Broderbe554312013-06-27 00:05:25 -07005415static int ssl_sock_srv_hostcheck(const char *pattern, const char *hostname)
5416{
5417 const char *pattern_wildcard, *pattern_left_label_end, *hostname_left_label_end;
5418 size_t prefixlen, suffixlen;
5419
5420 /* Trivial case */
5421 if (strcmp(pattern, hostname) == 0)
5422 return 1;
5423
Evan Broderbe554312013-06-27 00:05:25 -07005424 /* The rest of this logic is based on RFC 6125, section 6.4.3
5425 * (http://tools.ietf.org/html/rfc6125#section-6.4.3) */
5426
Emeric Bruna848dae2013-10-08 11:27:28 +02005427 pattern_wildcard = NULL;
5428 pattern_left_label_end = pattern;
5429 while (*pattern_left_label_end != '.') {
5430 switch (*pattern_left_label_end) {
5431 case 0:
5432 /* End of label not found */
5433 return 0;
5434 case '*':
5435 /* If there is more than one wildcards */
5436 if (pattern_wildcard)
5437 return 0;
5438 pattern_wildcard = pattern_left_label_end;
5439 break;
5440 }
5441 pattern_left_label_end++;
5442 }
5443
5444 /* If it's not trivial and there is no wildcard, it can't
5445 * match */
5446 if (!pattern_wildcard)
Evan Broderbe554312013-06-27 00:05:25 -07005447 return 0;
5448
5449 /* Make sure all labels match except the leftmost */
5450 hostname_left_label_end = strchr(hostname, '.');
5451 if (!hostname_left_label_end
5452 || strcmp(pattern_left_label_end, hostname_left_label_end) != 0)
5453 return 0;
5454
5455 /* Make sure the leftmost label of the hostname is long enough
5456 * that the wildcard can match */
Emeric Brun369da852013-10-08 11:39:35 +02005457 if (hostname_left_label_end - hostname < (pattern_left_label_end - pattern) - 1)
Evan Broderbe554312013-06-27 00:05:25 -07005458 return 0;
5459
5460 /* Finally compare the string on either side of the
5461 * wildcard */
5462 prefixlen = pattern_wildcard - pattern;
5463 suffixlen = pattern_left_label_end - (pattern_wildcard + 1);
Emeric Bruna848dae2013-10-08 11:27:28 +02005464 if ((prefixlen && (memcmp(pattern, hostname, prefixlen) != 0))
5465 || (suffixlen && (memcmp(pattern_wildcard + 1, hostname_left_label_end - suffixlen, suffixlen) != 0)))
Evan Broderbe554312013-06-27 00:05:25 -07005466 return 0;
5467
5468 return 1;
5469}
5470
5471static int ssl_sock_srv_verifycbk(int ok, X509_STORE_CTX *ctx)
5472{
5473 SSL *ssl;
5474 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01005475 struct ssl_sock_ctx *ssl_ctx;
Willy Tarreau2ab88672017-07-05 18:23:03 +02005476 const char *servername;
Willy Tarreau71d058c2017-07-26 20:09:56 +02005477 const char *sni;
Evan Broderbe554312013-06-27 00:05:25 -07005478
5479 int depth;
5480 X509 *cert;
5481 STACK_OF(GENERAL_NAME) *alt_names;
5482 int i;
5483 X509_NAME *cert_subject;
5484 char *str;
5485
5486 if (ok == 0)
5487 return ok;
5488
5489 ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
Thierry FOURNIER28962c92018-06-17 21:37:05 +02005490 conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Olivier Houchard66ab4982019-02-26 18:37:15 +01005491 ssl_ctx = conn->xprt_ctx;
Evan Broderbe554312013-06-27 00:05:25 -07005492
Willy Tarreauad92a9a2017-07-28 11:38:41 +02005493 /* We're checking if the provided hostnames match the desired one. The
5494 * desired hostname comes from the SNI we presented if any, or if not
5495 * provided then it may have been explicitly stated using a "verifyhost"
5496 * directive. If neither is set, we don't care about the name so the
5497 * verification is OK.
Willy Tarreau2ab88672017-07-05 18:23:03 +02005498 */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005499 servername = SSL_get_servername(ssl_ctx->ssl, TLSEXT_NAMETYPE_host_name);
Willy Tarreau71d058c2017-07-26 20:09:56 +02005500 sni = servername;
Willy Tarreau2ab88672017-07-05 18:23:03 +02005501 if (!servername) {
Willy Tarreau07d94e42018-09-20 10:57:52 +02005502 servername = __objt_server(conn->target)->ssl_ctx.verify_host;
Willy Tarreau2ab88672017-07-05 18:23:03 +02005503 if (!servername)
5504 return ok;
5505 }
Evan Broderbe554312013-06-27 00:05:25 -07005506
5507 /* We only need to verify the CN on the actual server cert,
5508 * not the indirect CAs */
5509 depth = X509_STORE_CTX_get_error_depth(ctx);
5510 if (depth != 0)
5511 return ok;
5512
5513 /* At this point, the cert is *not* OK unless we can find a
5514 * hostname match */
5515 ok = 0;
5516
5517 cert = X509_STORE_CTX_get_current_cert(ctx);
5518 /* It seems like this might happen if verify peer isn't set */
5519 if (!cert)
5520 return ok;
5521
5522 alt_names = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
5523 if (alt_names) {
5524 for (i = 0; !ok && i < sk_GENERAL_NAME_num(alt_names); i++) {
5525 GENERAL_NAME *name = sk_GENERAL_NAME_value(alt_names, i);
5526 if (name->type == GEN_DNS) {
Willy Tarreau9a1ab082019-05-09 13:26:41 +02005527#if HA_OPENSSL_VERSION_NUMBER < 0x00907000L
Emeric Bruna33410c2013-09-17 15:47:48 +02005528 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.ia5) >= 0) {
5529#else
Evan Broderbe554312013-06-27 00:05:25 -07005530 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
Emeric Bruna33410c2013-09-17 15:47:48 +02005531#endif
Evan Broderbe554312013-06-27 00:05:25 -07005532 ok = ssl_sock_srv_hostcheck(str, servername);
5533 OPENSSL_free(str);
5534 }
5535 }
5536 }
Emeric Brun4ad50a42013-09-17 15:19:54 +02005537 sk_GENERAL_NAME_pop_free(alt_names, GENERAL_NAME_free);
Evan Broderbe554312013-06-27 00:05:25 -07005538 }
5539
5540 cert_subject = X509_get_subject_name(cert);
5541 i = -1;
5542 while (!ok && (i = X509_NAME_get_index_by_NID(cert_subject, NID_commonName, i)) != -1) {
5543 X509_NAME_ENTRY *entry = X509_NAME_get_entry(cert_subject, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005544 ASN1_STRING *value;
5545 value = X509_NAME_ENTRY_get_data(entry);
5546 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
Evan Broderbe554312013-06-27 00:05:25 -07005547 ok = ssl_sock_srv_hostcheck(str, servername);
5548 OPENSSL_free(str);
5549 }
5550 }
5551
Willy Tarreau71d058c2017-07-26 20:09:56 +02005552 /* report the mismatch and indicate if SNI was used or not */
5553 if (!ok && !conn->err_code)
5554 conn->err_code = sni ? CO_ER_SSL_MISMATCH_SNI : CO_ER_SSL_MISMATCH;
Evan Broderbe554312013-06-27 00:05:25 -07005555 return ok;
5556}
5557
Emeric Brun94324a42012-10-11 14:00:19 +02005558/* prepare ssl context from servers options. Returns an error count */
Willy Tarreau03209342016-12-22 17:08:28 +01005559int ssl_sock_prepare_srv_ctx(struct server *srv)
Emeric Brun94324a42012-10-11 14:00:19 +02005560{
Willy Tarreau03209342016-12-22 17:08:28 +01005561 struct proxy *curproxy = srv->proxy;
Emeric Brun94324a42012-10-11 14:00:19 +02005562 int cfgerr = 0;
Remi Gacogneaf5c3da2014-05-19 10:29:58 +02005563 long options =
Emeric Brun94324a42012-10-11 14:00:19 +02005564 SSL_OP_ALL | /* all known workarounds for bugs */
5565 SSL_OP_NO_SSLv2 |
5566 SSL_OP_NO_COMPRESSION;
Remi Gacogneaf5c3da2014-05-19 10:29:58 +02005567 long mode =
Emeric Brun94324a42012-10-11 14:00:19 +02005568 SSL_MODE_ENABLE_PARTIAL_WRITE |
5569 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
Willy Tarreau396a1862014-11-13 14:06:52 +01005570 SSL_MODE_RELEASE_BUFFERS |
5571 SSL_MODE_SMALL_BUFFERS;
Emeric Brun850efd52014-01-29 12:24:34 +01005572 int verify = SSL_VERIFY_NONE;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01005573 SSL_CTX *ctx = NULL;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005574 struct tls_version_filter *conf_ssl_methods = &srv->ssl_ctx.methods;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005575 int i, min, max, hole;
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005576 int flags = MC_SSL_O_ALL;
Emeric Brun94324a42012-10-11 14:00:19 +02005577
Thierry Fournier383085f2013-01-24 14:15:43 +01005578 /* Make sure openssl opens /dev/urandom before the chroot */
5579 if (!ssl_initialize_random()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005580 ha_alert("OpenSSL random data generator initialization failed.\n");
Thierry Fournier383085f2013-01-24 14:15:43 +01005581 cfgerr++;
5582 }
5583
Willy Tarreaufce03112015-01-15 21:32:40 +01005584 /* Automatic memory computations need to know we use SSL there */
5585 global.ssl_used_backend = 1;
5586
5587 /* Initiate SSL context for current server */
Emeric Brun821bb9b2017-06-15 16:37:39 +02005588 if (!srv->ssl_ctx.reused_sess) {
Olivier Houcharde6060c52017-11-16 17:42:52 +01005589 if ((srv->ssl_ctx.reused_sess = calloc(1, global.nbthread*sizeof(*srv->ssl_ctx.reused_sess))) == NULL) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005590 ha_alert("Proxy '%s', server '%s' [%s:%d] out of memory.\n",
5591 curproxy->id, srv->id,
5592 srv->conf.file, srv->conf.line);
Emeric Brun821bb9b2017-06-15 16:37:39 +02005593 cfgerr++;
5594 return cfgerr;
5595 }
5596 }
Emeric Brun94324a42012-10-11 14:00:19 +02005597 if (srv->use_ssl)
5598 srv->xprt = &ssl_sock;
5599 if (srv->check.use_ssl)
Cyril Bonté9ce13112014-11-15 22:41:27 +01005600 srv->check.xprt = &ssl_sock;
Emeric Brun94324a42012-10-11 14:00:19 +02005601
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005602 ctx = SSL_CTX_new(SSLv23_client_method());
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01005603 if (!ctx) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005604 ha_alert("config : %s '%s', server '%s': unable to allocate ssl context.\n",
5605 proxy_type_str(curproxy), curproxy->id,
5606 srv->id);
Emeric Brun94324a42012-10-11 14:00:19 +02005607 cfgerr++;
5608 return cfgerr;
5609 }
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005610
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005611 if (conf_ssl_methods->flags && (conf_ssl_methods->min || conf_ssl_methods->max))
Christopher Faulet767a84b2017-11-24 16:50:31 +01005612 ha_warning("config : %s '%s': no-sslv3/no-tlsv1x are ignored for server '%s'. "
5613 "Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
5614 proxy_type_str(curproxy), curproxy->id, srv->id);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005615 else
5616 flags = conf_ssl_methods->flags;
5617
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005618 /* Real min and max should be determinate with configuration and openssl's capabilities */
5619 if (conf_ssl_methods->min)
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005620 flags |= (methodVersions[conf_ssl_methods->min].flag - 1);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005621 if (conf_ssl_methods->max)
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005622 flags |= ~((methodVersions[conf_ssl_methods->max].flag << 1) - 1);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005623
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02005624 /* find min, max and holes */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005625 min = max = CONF_TLSV_NONE;
5626 hole = 0;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005627 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005628 /* version is in openssl && version not disable in configuration */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005629 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005630 if (min) {
5631 if (hole) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005632 ha_warning("config : %s '%s': SSL/TLS versions range not contiguous for server '%s'. "
5633 "Hole find for %s. Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
5634 proxy_type_str(curproxy), curproxy->id, srv->id,
5635 methodVersions[hole].name);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005636 hole = 0;
5637 }
5638 max = i;
5639 }
5640 else {
5641 min = max = i;
5642 }
5643 }
5644 else {
5645 if (min)
5646 hole = i;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005647 }
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005648 if (!min) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005649 ha_alert("config : %s '%s': all SSL/TLS versions are disabled for server '%s'.\n",
5650 proxy_type_str(curproxy), curproxy->id, srv->id);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005651 cfgerr += 1;
5652 }
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005653
Willy Tarreau9a1ab082019-05-09 13:26:41 +02005654#if (HA_OPENSSL_VERSION_NUMBER < 0x1010000fL)
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005655 /* Keep force-xxx implementation as it is in older haproxy. It's a
Joseph Herlant017b3da2018-11-15 09:07:59 -08005656 precautionary measure to avoid any surprise with older openssl version. */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005657 if (min == max)
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02005658 methodVersions[min].ctx_set_version(ctx, SET_CLIENT);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005659 else
5660 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
5661 if (flags & methodVersions[i].flag)
5662 options |= methodVersions[i].option;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005663#else /* openssl >= 1.1.0 */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005664 /* set the max_version is required to cap TLS version or activate new TLS (v1.3) */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02005665 methodVersions[min].ctx_set_version(ctx, SET_MIN);
5666 methodVersions[max].ctx_set_version(ctx, SET_MAX);
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005667#endif
5668
5669 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLS_TICKETS)
5670 options |= SSL_OP_NO_TICKET;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01005671 SSL_CTX_set_options(ctx, options);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005672
Willy Tarreau5db847a2019-05-09 14:13:35 +02005673#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005674 if (global_ssl.async)
5675 mode |= SSL_MODE_ASYNC;
5676#endif
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01005677 SSL_CTX_set_mode(ctx, mode);
5678 srv->ssl_ctx.ctx = ctx;
5679
Emeric Bruna7aa3092012-10-26 12:58:00 +02005680 if (srv->ssl_ctx.client_crt) {
5681 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 +01005682 ha_alert("config : %s '%s', server '%s': unable to load SSL private key from PEM file '%s'.\n",
5683 proxy_type_str(curproxy), curproxy->id,
5684 srv->id, srv->ssl_ctx.client_crt);
Emeric Bruna7aa3092012-10-26 12:58:00 +02005685 cfgerr++;
5686 }
5687 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 +01005688 ha_alert("config : %s '%s', server '%s': unable to load ssl certificate from PEM file '%s'.\n",
5689 proxy_type_str(curproxy), curproxy->id,
5690 srv->id, srv->ssl_ctx.client_crt);
Emeric Bruna7aa3092012-10-26 12:58:00 +02005691 cfgerr++;
5692 }
5693 else if (SSL_CTX_check_private_key(srv->ssl_ctx.ctx) <= 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005694 ha_alert("config : %s '%s', server '%s': inconsistencies between private key and certificate loaded from PEM file '%s'.\n",
5695 proxy_type_str(curproxy), curproxy->id,
5696 srv->id, srv->ssl_ctx.client_crt);
Emeric Bruna7aa3092012-10-26 12:58:00 +02005697 cfgerr++;
5698 }
5699 }
Emeric Brun94324a42012-10-11 14:00:19 +02005700
Emeric Brun850efd52014-01-29 12:24:34 +01005701 if (global.ssl_server_verify == SSL_SERVER_VERIFY_REQUIRED)
5702 verify = SSL_VERIFY_PEER;
Emeric Brun850efd52014-01-29 12:24:34 +01005703 switch (srv->ssl_ctx.verify) {
5704 case SSL_SOCK_VERIFY_NONE:
5705 verify = SSL_VERIFY_NONE;
5706 break;
5707 case SSL_SOCK_VERIFY_REQUIRED:
5708 verify = SSL_VERIFY_PEER;
5709 break;
5710 }
Evan Broderbe554312013-06-27 00:05:25 -07005711 SSL_CTX_set_verify(srv->ssl_ctx.ctx,
Emeric Brun850efd52014-01-29 12:24:34 +01005712 verify,
Willy Tarreau2ab88672017-07-05 18:23:03 +02005713 (srv->ssl_ctx.verify_host || (verify & SSL_VERIFY_PEER)) ? ssl_sock_srv_verifycbk : NULL);
Emeric Brun850efd52014-01-29 12:24:34 +01005714 if (verify & SSL_VERIFY_PEER) {
Emeric Brunef42d922012-10-11 16:11:36 +02005715 if (srv->ssl_ctx.ca_file) {
Emmanuel Hocdetd4f9a602019-10-24 11:32:47 +02005716 /* set CAfile to verify */
5717 if (!ssl_set_verify_locations_file(srv->ssl_ctx.ctx, srv->ssl_ctx.ca_file)) {
5718 ha_alert("Proxy '%s', server '%s' [%s:%d] unable to set CA file '%s'.\n",
Christopher Faulet767a84b2017-11-24 16:50:31 +01005719 curproxy->id, srv->id,
5720 srv->conf.file, srv->conf.line, srv->ssl_ctx.ca_file);
Emeric Brunef42d922012-10-11 16:11:36 +02005721 cfgerr++;
5722 }
5723 }
Emeric Brun850efd52014-01-29 12:24:34 +01005724 else {
5725 if (global.ssl_server_verify == SSL_SERVER_VERIFY_REQUIRED)
Christopher Faulet767a84b2017-11-24 16:50:31 +01005726 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",
5727 curproxy->id, srv->id,
5728 srv->conf.file, srv->conf.line);
Emeric Brun850efd52014-01-29 12:24:34 +01005729 else
Christopher Faulet767a84b2017-11-24 16:50:31 +01005730 ha_alert("Proxy '%s', server '%s' [%s:%d] verify is enabled but no CA file specified.\n",
5731 curproxy->id, srv->id,
5732 srv->conf.file, srv->conf.line);
Emeric Brun850efd52014-01-29 12:24:34 +01005733 cfgerr++;
5734 }
Emeric Brunef42d922012-10-11 16:11:36 +02005735#ifdef X509_V_FLAG_CRL_CHECK
5736 if (srv->ssl_ctx.crl_file) {
5737 X509_STORE *store = SSL_CTX_get_cert_store(srv->ssl_ctx.ctx);
5738
Emmanuel Hocdetb270e812019-11-21 19:09:31 +01005739 if (!ssl_set_cert_crl_file(store, srv->ssl_ctx.crl_file)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005740 ha_alert("Proxy '%s', server '%s' [%s:%d] unable to configure CRL file '%s'.\n",
5741 curproxy->id, srv->id,
5742 srv->conf.file, srv->conf.line, srv->ssl_ctx.crl_file);
Emeric Brunef42d922012-10-11 16:11:36 +02005743 cfgerr++;
5744 }
5745 else {
5746 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
5747 }
5748 }
5749#endif
5750 }
5751
Olivier Houchardbd84ac82017-11-03 13:43:35 +01005752 SSL_CTX_set_session_cache_mode(srv->ssl_ctx.ctx, SSL_SESS_CACHE_CLIENT |
5753 SSL_SESS_CACHE_NO_INTERNAL_STORE);
5754 SSL_CTX_sess_set_new_cb(srv->ssl_ctx.ctx, ssl_sess_new_srv_cb);
Emeric Brun94324a42012-10-11 14:00:19 +02005755 if (srv->ssl_ctx.ciphers &&
5756 !SSL_CTX_set_cipher_list(srv->ssl_ctx.ctx, srv->ssl_ctx.ciphers)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005757 ha_alert("Proxy '%s', server '%s' [%s:%d] : unable to set SSL cipher list to '%s'.\n",
5758 curproxy->id, srv->id,
5759 srv->conf.file, srv->conf.line, srv->ssl_ctx.ciphers);
Emeric Brun94324a42012-10-11 14:00:19 +02005760 cfgerr++;
5761 }
Dirkjan Bussink415150f2018-09-14 11:14:21 +02005762
Emmanuel Hocdet839af572019-05-14 16:27:35 +02005763#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02005764 if (srv->ssl_ctx.ciphersuites &&
Pierre Cheynierbc34cd12019-03-21 16:15:47 +00005765 !SSL_CTX_set_ciphersuites(srv->ssl_ctx.ctx, srv->ssl_ctx.ciphersuites)) {
Dirkjan Bussink415150f2018-09-14 11:14:21 +02005766 ha_alert("Proxy '%s', server '%s' [%s:%d] : unable to set TLS 1.3 cipher suites to '%s'.\n",
5767 curproxy->id, srv->id,
5768 srv->conf.file, srv->conf.line, srv->ssl_ctx.ciphersuites);
5769 cfgerr++;
5770 }
5771#endif
Olivier Houchardc7566002018-11-20 23:33:50 +01005772#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
5773 if (srv->ssl_ctx.npn_str)
5774 SSL_CTX_set_next_proto_select_cb(ctx, ssl_sock_srv_select_protos, srv);
5775#endif
5776#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
5777 if (srv->ssl_ctx.alpn_str)
5778 SSL_CTX_set_alpn_protos(ctx, (unsigned char *)srv->ssl_ctx.alpn_str, srv->ssl_ctx.alpn_len);
5779#endif
5780
Emeric Brun94324a42012-10-11 14:00:19 +02005781
5782 return cfgerr;
5783}
5784
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005785/* Walks down the two trees in bind_conf and prepares all certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +02005786 * be NULL, in which case nothing is done. Returns the number of errors
5787 * encountered.
5788 */
Willy Tarreau03209342016-12-22 17:08:28 +01005789int ssl_sock_prepare_all_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02005790{
5791 struct ebmb_node *node;
5792 struct sni_ctx *sni;
5793 int err = 0;
William Lallemand8b453912019-11-21 15:48:10 +01005794 int errcode = 0;
5795 char *errmsg = NULL;
Emeric Brunfc0421f2012-09-07 17:30:07 +02005796
Willy Tarreaufce03112015-01-15 21:32:40 +01005797 /* Automatic memory computations need to know we use SSL there */
5798 global.ssl_used_frontend = 1;
5799
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01005800 /* Make sure openssl opens /dev/urandom before the chroot */
5801 if (!ssl_initialize_random()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005802 ha_alert("OpenSSL random data generator initialization failed.\n");
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01005803 err++;
5804 }
5805 /* Create initial_ctx used to start the ssl connection before do switchctx */
5806 if (!bind_conf->initial_ctx) {
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005807 err += ssl_sock_initial_ctx(bind_conf);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01005808 /* It should not be necessary to call this function, but it's
5809 necessary first to check and move all initialisation related
5810 to initial_ctx in ssl_sock_initial_ctx. */
William Lallemand8b453912019-11-21 15:48:10 +01005811 errcode |= ssl_sock_prepare_ctx(bind_conf, NULL, bind_conf->initial_ctx, &errmsg);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01005812 }
Emeric Brun0bed9942014-10-30 19:25:24 +01005813 if (bind_conf->default_ctx)
William Lallemand8b453912019-11-21 15:48:10 +01005814 errcode |= ssl_sock_prepare_ctx(bind_conf, bind_conf->default_ssl_conf, bind_conf->default_ctx, &errmsg);
Emeric Brun0bed9942014-10-30 19:25:24 +01005815
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005816 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02005817 while (node) {
5818 sni = ebmb_entry(node, struct sni_ctx, name);
Emeric Brun0bed9942014-10-30 19:25:24 +01005819 if (!sni->order && sni->ctx != bind_conf->default_ctx)
5820 /* only initialize the CTX on its first occurrence and
5821 if it is not the default_ctx */
William Lallemand8b453912019-11-21 15:48:10 +01005822 errcode |= ssl_sock_prepare_ctx(bind_conf, sni->conf, sni->ctx, &errmsg);
Emeric Brunfc0421f2012-09-07 17:30:07 +02005823 node = ebmb_next(node);
5824 }
5825
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005826 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02005827 while (node) {
5828 sni = ebmb_entry(node, struct sni_ctx, name);
William Lallemand8b453912019-11-21 15:48:10 +01005829 if (!sni->order && sni->ctx != bind_conf->default_ctx) {
Emeric Brun0bed9942014-10-30 19:25:24 +01005830 /* only initialize the CTX on its first occurrence and
5831 if it is not the default_ctx */
William Lallemand8b453912019-11-21 15:48:10 +01005832 errcode |= ssl_sock_prepare_ctx(bind_conf, sni->conf, sni->ctx, &errmsg);
5833 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02005834 node = ebmb_next(node);
5835 }
William Lallemand8b453912019-11-21 15:48:10 +01005836
5837 if (errcode & ERR_WARN) {
Tim Duesterhusc0e820c2019-11-23 23:52:30 +01005838 ha_warning("%s", errmsg);
William Lallemand8b453912019-11-21 15:48:10 +01005839 } else if (errcode & ERR_CODE) {
Tim Duesterhusc0e820c2019-11-23 23:52:30 +01005840 ha_alert("%s", errmsg);
William Lallemand8b453912019-11-21 15:48:10 +01005841 err++;
5842 }
5843
5844 free(errmsg);
Emeric Brunfc0421f2012-09-07 17:30:07 +02005845 return err;
5846}
5847
Willy Tarreau55d37912016-12-21 23:38:39 +01005848/* Prepares all the contexts for a bind_conf and allocates the shared SSL
5849 * context if needed. Returns < 0 on error, 0 on success. The warnings and
5850 * alerts are directly emitted since the rest of the stack does it below.
5851 */
5852int ssl_sock_prepare_bind_conf(struct bind_conf *bind_conf)
5853{
5854 struct proxy *px = bind_conf->frontend;
5855 int alloc_ctx;
5856 int err;
5857
5858 if (!bind_conf->is_ssl) {
5859 if (bind_conf->default_ctx) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005860 ha_warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
5861 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreau55d37912016-12-21 23:38:39 +01005862 }
5863 return 0;
5864 }
5865 if (!bind_conf->default_ctx) {
Emmanuel Hocdetaa0d6372017-08-09 11:24:25 +02005866 if (bind_conf->strict_sni && !bind_conf->generate_certs) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005867 ha_warning("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d], ssl connections will fail (use 'crt').\n",
5868 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetaa0d6372017-08-09 11:24:25 +02005869 }
5870 else {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005871 ha_alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
5872 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetaa0d6372017-08-09 11:24:25 +02005873 return -1;
5874 }
Willy Tarreau55d37912016-12-21 23:38:39 +01005875 }
William Lallemandc61c0b32017-12-04 18:46:39 +01005876 if (!ssl_shctx && global.tune.sslcachesize) {
William Lallemandc3cd35f2017-11-28 11:04:43 +01005877 alloc_ctx = shctx_init(&ssl_shctx, global.tune.sslcachesize,
Frédéric Lécailleb7838af2018-10-22 16:21:39 +02005878 sizeof(struct sh_ssl_sess_hdr) + SHSESS_BLOCK_MIN_SIZE, -1,
William Lallemandc3cd35f2017-11-28 11:04:43 +01005879 sizeof(*sh_ssl_sess_tree),
5880 ((global.nbthread > 1) || (!global_ssl.private_cache && (global.nbproc > 1))) ? 1 : 0);
Frédéric Lécaille4c8aa112018-10-25 20:22:46 +02005881 if (alloc_ctx <= 0) {
William Lallemandc3cd35f2017-11-28 11:04:43 +01005882 if (alloc_ctx == SHCTX_E_INIT_LOCK)
5883 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");
5884 else
5885 ha_alert("Unable to allocate SSL session cache.\n");
5886 return -1;
5887 }
5888 /* free block callback */
5889 ssl_shctx->free_block = sh_ssl_sess_free_blocks;
5890 /* init the root tree within the extra space */
5891 sh_ssl_sess_tree = (void *)ssl_shctx + sizeof(struct shared_context);
5892 *sh_ssl_sess_tree = EB_ROOT_UNIQUE;
Willy Tarreau55d37912016-12-21 23:38:39 +01005893 }
Willy Tarreau55d37912016-12-21 23:38:39 +01005894 err = 0;
5895 /* initialize all certificate contexts */
5896 err += ssl_sock_prepare_all_ctx(bind_conf);
5897
5898 /* initialize CA variables if the certificates generation is enabled */
5899 err += ssl_sock_load_ca(bind_conf);
5900
5901 return -err;
5902}
Christopher Faulet77fe80c2015-07-29 13:02:40 +02005903
5904/* release ssl context allocated for servers. */
5905void ssl_sock_free_srv_ctx(struct server *srv)
5906{
Olivier Houchardc7566002018-11-20 23:33:50 +01005907#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
5908 if (srv->ssl_ctx.alpn_str)
5909 free(srv->ssl_ctx.alpn_str);
5910#endif
Lukas Tribusda95fd92018-11-25 13:21:27 +01005911#ifdef OPENSSL_NPN_NEGOTIATED
Olivier Houchardc7566002018-11-20 23:33:50 +01005912 if (srv->ssl_ctx.npn_str)
5913 free(srv->ssl_ctx.npn_str);
Lukas Tribus7706b852018-11-26 22:57:17 +01005914#endif
Christopher Faulet77fe80c2015-07-29 13:02:40 +02005915 if (srv->ssl_ctx.ctx)
5916 SSL_CTX_free(srv->ssl_ctx.ctx);
5917}
5918
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005919/* Walks down the two trees in bind_conf and frees all the certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +02005920 * be NULL, in which case nothing is done. The default_ctx is nullified too.
5921 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005922void ssl_sock_free_all_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02005923{
5924 struct ebmb_node *node, *back;
5925 struct sni_ctx *sni;
5926
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005927 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02005928 while (node) {
5929 sni = ebmb_entry(node, struct sni_ctx, name);
5930 back = ebmb_next(node);
5931 ebmb_delete(node);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005932 if (!sni->order) { /* only free the CTX on its first occurrence */
Emeric Brunfc0421f2012-09-07 17:30:07 +02005933 SSL_CTX_free(sni->ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005934 ssl_sock_free_ssl_conf(sni->conf);
5935 free(sni->conf);
5936 sni->conf = NULL;
5937 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02005938 free(sni);
5939 node = back;
5940 }
5941
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005942 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02005943 while (node) {
5944 sni = ebmb_entry(node, struct sni_ctx, name);
5945 back = ebmb_next(node);
5946 ebmb_delete(node);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005947 if (!sni->order) { /* only free the CTX on its first occurrence */
Emeric Brunfc0421f2012-09-07 17:30:07 +02005948 SSL_CTX_free(sni->ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005949 ssl_sock_free_ssl_conf(sni->conf);
5950 free(sni->conf);
5951 sni->conf = NULL;
5952 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02005953 free(sni);
5954 node = back;
5955 }
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01005956 SSL_CTX_free(bind_conf->initial_ctx);
5957 bind_conf->initial_ctx = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005958 bind_conf->default_ctx = NULL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005959 bind_conf->default_ssl_conf = NULL;
Emeric Brune1f38db2012-09-03 20:36:47 +02005960}
5961
Willy Tarreau795cdab2016-12-22 17:30:54 +01005962/* Destroys all the contexts for a bind_conf. This is used during deinit(). */
5963void ssl_sock_destroy_bind_conf(struct bind_conf *bind_conf)
5964{
5965 ssl_sock_free_ca(bind_conf);
5966 ssl_sock_free_all_ctx(bind_conf);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005967 ssl_sock_free_ssl_conf(&bind_conf->ssl_conf);
Willy Tarreau795cdab2016-12-22 17:30:54 +01005968 free(bind_conf->ca_sign_file);
5969 free(bind_conf->ca_sign_pass);
Willy Tarreau17b4aa12018-07-17 10:05:32 +02005970 if (bind_conf->keys_ref && !--bind_conf->keys_ref->refcount) {
Willy Tarreau795cdab2016-12-22 17:30:54 +01005971 free(bind_conf->keys_ref->filename);
5972 free(bind_conf->keys_ref->tlskeys);
5973 LIST_DEL(&bind_conf->keys_ref->list);
5974 free(bind_conf->keys_ref);
5975 }
5976 bind_conf->keys_ref = NULL;
Willy Tarreau795cdab2016-12-22 17:30:54 +01005977 bind_conf->ca_sign_pass = NULL;
5978 bind_conf->ca_sign_file = NULL;
Willy Tarreau795cdab2016-12-22 17:30:54 +01005979}
5980
Christopher Faulet31af49d2015-06-09 17:29:50 +02005981/* Load CA cert file and private key used to generate certificates */
5982int
Willy Tarreau03209342016-12-22 17:08:28 +01005983ssl_sock_load_ca(struct bind_conf *bind_conf)
Christopher Faulet31af49d2015-06-09 17:29:50 +02005984{
Willy Tarreau03209342016-12-22 17:08:28 +01005985 struct proxy *px = bind_conf->frontend;
Christopher Faulet31af49d2015-06-09 17:29:50 +02005986 FILE *fp;
5987 X509 *cacert = NULL;
5988 EVP_PKEY *capkey = NULL;
5989 int err = 0;
5990
Christopher Fauletf8bb0ce2017-09-15 09:52:49 +02005991 if (!bind_conf->generate_certs)
Christopher Faulet31af49d2015-06-09 17:29:50 +02005992 return err;
5993
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005994#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Emeric Brun821bb9b2017-06-15 16:37:39 +02005995 if (global_ssl.ctx_cache) {
Willy Tarreauef934602016-12-22 23:12:01 +01005996 ssl_ctx_lru_tree = lru64_new(global_ssl.ctx_cache);
Emeric Brun821bb9b2017-06-15 16:37:39 +02005997 }
Christopher Fauletd2cab922015-07-28 16:03:47 +02005998 ssl_ctx_lru_seed = (unsigned int)time(NULL);
Emeric Brun821bb9b2017-06-15 16:37:39 +02005999 ssl_ctx_serial = now_ms;
Willy Tarreaua84c2672015-10-09 12:10:13 +02006000#endif
Christopher Fauletd2cab922015-07-28 16:03:47 +02006001
Christopher Faulet31af49d2015-06-09 17:29:50 +02006002 if (!bind_conf->ca_sign_file) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01006003 ha_alert("Proxy '%s': cannot enable certificate generation, "
6004 "no CA certificate File configured at [%s:%d].\n",
6005 px->id, bind_conf->file, bind_conf->line);
Christopher Faulet31af49d2015-06-09 17:29:50 +02006006 goto load_error;
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02006007 }
Christopher Faulet31af49d2015-06-09 17:29:50 +02006008
6009 /* read in the CA certificate */
6010 if (!(fp = fopen(bind_conf->ca_sign_file, "r"))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01006011 ha_alert("Proxy '%s': Failed to read CA certificate file '%s' at [%s:%d].\n",
6012 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Faulet31af49d2015-06-09 17:29:50 +02006013 goto load_error;
6014 }
6015 if (!(cacert = PEM_read_X509(fp, NULL, NULL, NULL))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01006016 ha_alert("Proxy '%s': Failed to read CA certificate file '%s' at [%s:%d].\n",
6017 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02006018 goto read_error;
Christopher Faulet31af49d2015-06-09 17:29:50 +02006019 }
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02006020 rewind(fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02006021 if (!(capkey = PEM_read_PrivateKey(fp, NULL, NULL, bind_conf->ca_sign_pass))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01006022 ha_alert("Proxy '%s': Failed to read CA private key file '%s' at [%s:%d].\n",
6023 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02006024 goto read_error;
Christopher Faulet31af49d2015-06-09 17:29:50 +02006025 }
Christopher Faulet31af49d2015-06-09 17:29:50 +02006026
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02006027 fclose (fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02006028 bind_conf->ca_sign_cert = cacert;
6029 bind_conf->ca_sign_pkey = capkey;
6030 return err;
6031
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02006032 read_error:
6033 fclose (fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02006034 if (capkey) EVP_PKEY_free(capkey);
6035 if (cacert) X509_free(cacert);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02006036 load_error:
6037 bind_conf->generate_certs = 0;
6038 err++;
Christopher Faulet31af49d2015-06-09 17:29:50 +02006039 return err;
6040}
6041
6042/* Release CA cert and private key used to generate certificated */
6043void
6044ssl_sock_free_ca(struct bind_conf *bind_conf)
6045{
Christopher Faulet31af49d2015-06-09 17:29:50 +02006046 if (bind_conf->ca_sign_pkey)
6047 EVP_PKEY_free(bind_conf->ca_sign_pkey);
6048 if (bind_conf->ca_sign_cert)
6049 X509_free(bind_conf->ca_sign_cert);
Willy Tarreau94ff03a2016-12-22 17:57:46 +01006050 bind_conf->ca_sign_pkey = NULL;
6051 bind_conf->ca_sign_cert = NULL;
Christopher Faulet31af49d2015-06-09 17:29:50 +02006052}
6053
Emeric Brun46591952012-05-18 15:47:34 +02006054/*
6055 * This function is called if SSL * context is not yet allocated. The function
6056 * is designed to be called before any other data-layer operation and sets the
6057 * handshake flag on the connection. It is safe to call it multiple times.
6058 * It returns 0 on success and -1 in error case.
6059 */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006060static int ssl_sock_init(struct connection *conn, void **xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02006061{
Olivier Houchard66ab4982019-02-26 18:37:15 +01006062 struct ssl_sock_ctx *ctx;
Emeric Brun46591952012-05-18 15:47:34 +02006063 /* already initialized */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006064 if (*xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02006065 return 0;
6066
Willy Tarreau3c728722014-01-23 13:50:42 +01006067 if (!conn_ctrl_ready(conn))
Willy Tarreauf79c8172013-10-21 16:30:56 +02006068 return 0;
6069
Olivier Houchard66ab4982019-02-26 18:37:15 +01006070 ctx = pool_alloc(ssl_sock_ctx_pool);
6071 if (!ctx) {
6072 conn->err_code = CO_ER_SSL_NO_MEM;
6073 return -1;
6074 }
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02006075 ctx->wait_event.tasklet = tasklet_new();
6076 if (!ctx->wait_event.tasklet) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02006077 conn->err_code = CO_ER_SSL_NO_MEM;
6078 pool_free(ssl_sock_ctx_pool, ctx);
6079 return -1;
6080 }
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02006081 ctx->wait_event.tasklet->process = ssl_sock_io_cb;
6082 ctx->wait_event.tasklet->context = ctx;
Olivier Houchardea8dd942019-05-20 14:02:16 +02006083 ctx->wait_event.events = 0;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006084 ctx->sent_early_data = 0;
Olivier Houchard54907bb2019-12-19 15:02:39 +01006085 ctx->early_buf = BUF_NULL;
Olivier Houcharda8955d52019-04-07 22:00:38 +02006086 ctx->conn = conn;
Willy Tarreau113d52b2020-01-10 09:20:26 +01006087 ctx->subs = NULL;
Emeric Brun5762a0d2019-09-06 15:36:02 +02006088 ctx->xprt_st = 0;
6089 ctx->xprt_ctx = NULL;
Olivier Houcharda8955d52019-04-07 22:00:38 +02006090
6091 /* Only work with sockets for now, this should be adapted when we'll
6092 * add QUIC support.
6093 */
6094 ctx->xprt = xprt_get(XPRT_RAW);
Olivier Houchard19afb272019-05-23 18:24:07 +02006095 if (ctx->xprt->init) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02006096 if (ctx->xprt->init(conn, &ctx->xprt_ctx) != 0)
6097 goto err;
Olivier Houchard19afb272019-05-23 18:24:07 +02006098 }
Olivier Houchard66ab4982019-02-26 18:37:15 +01006099
Willy Tarreau20879a02012-12-03 16:32:10 +01006100 if (global.maxsslconn && sslconns >= global.maxsslconn) {
6101 conn->err_code = CO_ER_SSL_TOO_MANY;
Olivier Houchardea8dd942019-05-20 14:02:16 +02006102 goto err;
Willy Tarreau20879a02012-12-03 16:32:10 +01006103 }
Willy Tarreau403edff2012-09-06 11:58:37 +02006104
Emeric Brun46591952012-05-18 15:47:34 +02006105 /* If it is in client mode initiate SSL session
6106 in connect state otherwise accept state */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01006107 if (objt_server(conn->target)) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01006108 int may_retry = 1;
6109
6110 retry_connect:
Emeric Brun46591952012-05-18 15:47:34 +02006111 /* Alloc a new SSL session ctx */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006112 ctx->ssl = SSL_new(__objt_server(conn->target)->ssl_ctx.ctx);
6113 if (!ctx->ssl) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01006114 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01006115 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01006116 goto retry_connect;
6117 }
Willy Tarreau20879a02012-12-03 16:32:10 +01006118 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006119 goto err;
Willy Tarreau20879a02012-12-03 16:32:10 +01006120 }
Olivier Houcharda8955d52019-04-07 22:00:38 +02006121 ctx->bio = BIO_new(ha_meth);
6122 if (!ctx->bio) {
Olivier Houchardefe5e8e2020-01-24 15:17:38 +01006123 SSL_free(ctx->ssl);
6124 ctx->ssl = NULL;
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 }
Emeric Brun55476152014-11-12 17:35:37 +01006129 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006130 goto err;
Emeric Brun55476152014-11-12 17:35:37 +01006131 }
Olivier Houcharda8955d52019-04-07 22:00:38 +02006132 BIO_set_data(ctx->bio, ctx);
Olivier Houcharda8955d52019-04-07 22:00:38 +02006133 SSL_set_bio(ctx->ssl, ctx->bio, ctx->bio);
Emeric Brun46591952012-05-18 15:47:34 +02006134
Evan Broderbe554312013-06-27 00:05:25 -07006135 /* set connection pointer */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006136 if (!SSL_set_ex_data(ctx->ssl, ssl_app_data_index, conn)) {
6137 SSL_free(ctx->ssl);
6138 ctx->ssl = NULL;
Emeric Brun55476152014-11-12 17:35:37 +01006139 conn->xprt_ctx = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01006140 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01006141 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01006142 goto retry_connect;
6143 }
Emeric Brun55476152014-11-12 17:35:37 +01006144 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006145 goto err;
Emeric Brun55476152014-11-12 17:35:37 +01006146 }
6147
Olivier Houchard66ab4982019-02-26 18:37:15 +01006148 SSL_set_connect_state(ctx->ssl);
Willy Tarreau07d94e42018-09-20 10:57:52 +02006149 if (__objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr) {
6150 const unsigned char *ptr = __objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr;
6151 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 +01006152 if (sess && !SSL_set_session(ctx->ssl, sess)) {
Olivier Houcharde6060c52017-11-16 17:42:52 +01006153 SSL_SESSION_free(sess);
Willy Tarreau07d94e42018-09-20 10:57:52 +02006154 free(__objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr);
6155 __objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr = NULL;
Olivier Houcharde6060c52017-11-16 17:42:52 +01006156 } else if (sess) {
6157 SSL_SESSION_free(sess);
Emeric Brun55476152014-11-12 17:35:37 +01006158 }
6159 }
Evan Broderbe554312013-06-27 00:05:25 -07006160
Emeric Brun46591952012-05-18 15:47:34 +02006161 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +02006162 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Willy Tarreau403edff2012-09-06 11:58:37 +02006163
Olivier Houchard2be5a4c2019-03-08 18:54:43 +01006164 _HA_ATOMIC_ADD(&sslconns, 1);
6165 _HA_ATOMIC_ADD(&totalsslconns, 1);
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006166 *xprt_ctx = ctx;
Olivier Houchardea8dd942019-05-20 14:02:16 +02006167 /* Start the handshake */
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02006168 tasklet_wakeup(ctx->wait_event.tasklet);
Emeric Brun46591952012-05-18 15:47:34 +02006169 return 0;
6170 }
Willy Tarreau3fdb3662012-11-12 00:42:33 +01006171 else if (objt_listener(conn->target)) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01006172 int may_retry = 1;
6173
6174 retry_accept:
Emeric Brun46591952012-05-18 15:47:34 +02006175 /* Alloc a new SSL session ctx */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006176 ctx->ssl = SSL_new(__objt_listener(conn->target)->bind_conf->initial_ctx);
6177 if (!ctx->ssl) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01006178 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01006179 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01006180 goto retry_accept;
6181 }
Willy Tarreau20879a02012-12-03 16:32:10 +01006182 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006183 goto err;
Willy Tarreau20879a02012-12-03 16:32:10 +01006184 }
Olivier Houcharda8955d52019-04-07 22:00:38 +02006185 ctx->bio = BIO_new(ha_meth);
6186 if (!ctx->bio) {
Olivier Houchardefe5e8e2020-01-24 15:17:38 +01006187 SSL_free(ctx->ssl);
6188 ctx->ssl = NULL;
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 }
Emeric Brun55476152014-11-12 17:35:37 +01006193 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006194 goto err;
Emeric Brun55476152014-11-12 17:35:37 +01006195 }
Olivier Houcharda8955d52019-04-07 22:00:38 +02006196 BIO_set_data(ctx->bio, ctx);
Olivier Houcharda8955d52019-04-07 22:00:38 +02006197 SSL_set_bio(ctx->ssl, ctx->bio, ctx->bio);
Emeric Brun46591952012-05-18 15:47:34 +02006198
Emeric Brune1f38db2012-09-03 20:36:47 +02006199 /* set connection pointer */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006200 if (!SSL_set_ex_data(ctx->ssl, ssl_app_data_index, conn)) {
6201 SSL_free(ctx->ssl);
6202 ctx->ssl = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01006203 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01006204 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01006205 goto retry_accept;
6206 }
Emeric Brun55476152014-11-12 17:35:37 +01006207 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006208 goto err;
Emeric Brun55476152014-11-12 17:35:37 +01006209 }
6210
Frédéric Lécaille3139c1b2020-01-24 14:56:18 +01006211#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
6212 if (__objt_listener(conn->target)->bind_conf->ssl_conf.early_data) {
6213 b_alloc(&ctx->early_buf);
6214 SSL_set_max_early_data(ctx->ssl,
6215 /* Only allow early data if we managed to allocate
6216 * a buffer.
6217 */
6218 (!b_is_null(&ctx->early_buf)) ?
6219 global.tune.bufsize - global.tune.maxrewrite : 0);
6220 }
6221#endif
6222
Olivier Houchard66ab4982019-02-26 18:37:15 +01006223 SSL_set_accept_state(ctx->ssl);
Emeric Brune1f38db2012-09-03 20:36:47 +02006224
Emeric Brun46591952012-05-18 15:47:34 +02006225 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +02006226 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Emmanuel Hocdetf967c312019-08-05 18:04:16 +02006227#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Olivier Houchardc2aae742017-09-22 18:26:28 +02006228 conn->flags |= CO_FL_EARLY_SSL_HS;
6229#endif
Willy Tarreau403edff2012-09-06 11:58:37 +02006230
Olivier Houchard2be5a4c2019-03-08 18:54:43 +01006231 _HA_ATOMIC_ADD(&sslconns, 1);
6232 _HA_ATOMIC_ADD(&totalsslconns, 1);
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006233 *xprt_ctx = ctx;
Olivier Houchardea8dd942019-05-20 14:02:16 +02006234 /* Start the handshake */
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02006235 tasklet_wakeup(ctx->wait_event.tasklet);
Emeric Brun46591952012-05-18 15:47:34 +02006236 return 0;
6237 }
6238 /* don't know how to handle such a target */
Willy Tarreau20879a02012-12-03 16:32:10 +01006239 conn->err_code = CO_ER_SSL_NO_TARGET;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006240err:
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02006241 if (ctx && ctx->wait_event.tasklet)
6242 tasklet_free(ctx->wait_event.tasklet);
Olivier Houchard66ab4982019-02-26 18:37:15 +01006243 pool_free(ssl_sock_ctx_pool, ctx);
Emeric Brun46591952012-05-18 15:47:34 +02006244 return -1;
6245}
6246
6247
6248/* This is the callback which is used when an SSL handshake is pending. It
6249 * updates the FD status if it wants some polling before being called again.
6250 * It returns 0 if it fails in a fatal way or needs to poll to go further,
6251 * otherwise it returns non-zero and removes itself from the connection's
6252 * flags (the bit is provided in <flag> by the caller).
6253 */
Olivier Houchard000694c2019-05-23 14:45:12 +02006254static int ssl_sock_handshake(struct connection *conn, unsigned int flag)
Emeric Brun46591952012-05-18 15:47:34 +02006255{
Olivier Houchard66ab4982019-02-26 18:37:15 +01006256 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
Emeric Brun46591952012-05-18 15:47:34 +02006257 int ret;
6258
Willy Tarreau3c728722014-01-23 13:50:42 +01006259 if (!conn_ctrl_ready(conn))
Willy Tarreauf79c8172013-10-21 16:30:56 +02006260 return 0;
6261
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02006262 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02006263 goto out_error;
6264
Willy Tarreau5db847a2019-05-09 14:13:35 +02006265#if HA_OPENSSL_VERSION_NUMBER >= 0x10101000L
Olivier Houchardc2aae742017-09-22 18:26:28 +02006266 /*
6267 * Check if we have early data. If we do, we have to read them
6268 * before SSL_do_handshake() is called, And there's no way to
6269 * detect early data, except to try to read them
6270 */
6271 if (conn->flags & CO_FL_EARLY_SSL_HS) {
Olivier Houchard54907bb2019-12-19 15:02:39 +01006272 size_t read_data = 0;
Olivier Houchardc2aae742017-09-22 18:26:28 +02006273
Olivier Houchard54907bb2019-12-19 15:02:39 +01006274 while (1) {
6275 ret = SSL_read_early_data(ctx->ssl,
6276 b_tail(&ctx->early_buf), b_room(&ctx->early_buf),
6277 &read_data);
6278 if (ret == SSL_READ_EARLY_DATA_ERROR)
6279 goto check_error;
6280 if (read_data > 0) {
6281 conn->flags |= CO_FL_EARLY_DATA;
6282 b_add(&ctx->early_buf, read_data);
6283 }
6284 if (ret == SSL_READ_EARLY_DATA_FINISH) {
6285 conn->flags &= ~CO_FL_EARLY_SSL_HS;
6286 if (!b_data(&ctx->early_buf))
6287 b_free(&ctx->early_buf);
6288 break;
6289 }
6290 }
Olivier Houchardc2aae742017-09-22 18:26:28 +02006291 }
6292#endif
Emeric Brun674b7432012-11-08 19:21:55 +01006293 /* If we use SSL_do_handshake to process a reneg initiated by
6294 * the remote peer, it sometimes returns SSL_ERROR_SSL.
6295 * Usually SSL_write and SSL_read are used and process implicitly
6296 * the reneg handshake.
6297 * Here we use SSL_peek as a workaround for reneg.
6298 */
Willy Tarreauc192b0a2020-01-23 09:11:58 +01006299 if (!(conn->flags & CO_FL_WAIT_L6_CONN) && SSL_renegotiate_pending(ctx->ssl)) {
Emeric Brun674b7432012-11-08 19:21:55 +01006300 char c;
6301
Olivier Houchard66ab4982019-02-26 18:37:15 +01006302 ret = SSL_peek(ctx->ssl, &c, 1);
Emeric Brun674b7432012-11-08 19:21:55 +01006303 if (ret <= 0) {
6304 /* handshake may have not been completed, let's find why */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006305 ret = SSL_get_error(ctx->ssl, ret);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006306
Emeric Brun674b7432012-11-08 19:21:55 +01006307 if (ret == SSL_ERROR_WANT_WRITE) {
6308 /* SSL handshake needs to write, L4 connection may not be ready */
Olivier Houchard03abf2d2019-05-28 10:12:02 +02006309 if (!(ctx->wait_event.events & SUB_RETRY_SEND))
Olivier Houchardea8dd942019-05-20 14:02:16 +02006310 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_SEND, &ctx->wait_event);
Emeric Brun674b7432012-11-08 19:21:55 +01006311 return 0;
6312 }
6313 else if (ret == SSL_ERROR_WANT_READ) {
6314 /* handshake may have been completed but we have
6315 * no more data to read.
6316 */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006317 if (!SSL_renegotiate_pending(ctx->ssl)) {
Emeric Brun674b7432012-11-08 19:21:55 +01006318 ret = 1;
6319 goto reneg_ok;
6320 }
6321 /* SSL handshake needs to read, L4 connection is ready */
Olivier Houchard03abf2d2019-05-28 10:12:02 +02006322 if (!(ctx->wait_event.events & SUB_RETRY_RECV))
Olivier Houchardea8dd942019-05-20 14:02:16 +02006323 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_RECV, &ctx->wait_event);
Emeric Brun674b7432012-11-08 19:21:55 +01006324 return 0;
6325 }
Willy Tarreau5db847a2019-05-09 14:13:35 +02006326#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006327 else if (ret == SSL_ERROR_WANT_ASYNC) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02006328 ssl_async_process_fds(ctx);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006329 return 0;
6330 }
6331#endif
Emeric Brun674b7432012-11-08 19:21:55 +01006332 else if (ret == SSL_ERROR_SYSCALL) {
6333 /* if errno is null, then connection was successfully established */
6334 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
6335 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Willy Tarreau20879a02012-12-03 16:32:10 +01006336 if (!conn->err_code) {
Lukas Tribus49799162019-07-08 14:29:15 +02006337#if defined(OPENSSL_IS_BORINGSSL) || defined(LIBRESSL_VERSION_NUMBER)
6338 /* do not handle empty handshakes in BoringSSL or LibreSSL */
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01006339 conn->err_code = CO_ER_SSL_HANDSHAKE;
6340#else
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006341 int empty_handshake;
Willy Tarreau5db847a2019-05-09 14:13:35 +02006342#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL)
Lukas Tribus49799162019-07-08 14:29:15 +02006343 /* use SSL_get_state() in OpenSSL >= 1.1.0; SSL_state() is broken */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006344 OSSL_HANDSHAKE_STATE state = SSL_get_state((SSL *)ctx->ssl);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006345 empty_handshake = state == TLS_ST_BEFORE;
6346#else
Lukas Tribus49799162019-07-08 14:29:15 +02006347 /* access packet_length directly in OpenSSL <= 1.0.2; SSL_state() is broken */
6348 empty_handshake = !ctx->ssl->packet_length;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006349#endif
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006350 if (empty_handshake) {
Emeric Brun29f037d2014-04-25 19:05:36 +02006351 if (!errno) {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006352 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emeric Brun29f037d2014-04-25 19:05:36 +02006353 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
6354 else
6355 conn->err_code = CO_ER_SSL_EMPTY;
6356 }
6357 else {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006358 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emeric Brun29f037d2014-04-25 19:05:36 +02006359 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
6360 else
6361 conn->err_code = CO_ER_SSL_ABORT;
6362 }
6363 }
6364 else {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006365 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emeric Brun29f037d2014-04-25 19:05:36 +02006366 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
Willy Tarreau20879a02012-12-03 16:32:10 +01006367 else
Emeric Brun29f037d2014-04-25 19:05:36 +02006368 conn->err_code = CO_ER_SSL_HANDSHAKE;
6369 }
Lukas Tribus49799162019-07-08 14:29:15 +02006370#endif /* BoringSSL or LibreSSL */
Willy Tarreau20879a02012-12-03 16:32:10 +01006371 }
Emeric Brun674b7432012-11-08 19:21:55 +01006372 goto out_error;
6373 }
6374 else {
6375 /* Fail on all other handshake errors */
6376 /* Note: OpenSSL may leave unread bytes in the socket's
6377 * buffer, causing an RST to be emitted upon close() on
6378 * TCP sockets. We first try to drain possibly pending
6379 * data to avoid this as much as possible.
6380 */
Willy Tarreaud85c4852015-03-13 00:40:28 +01006381 conn_sock_drain(conn);
Willy Tarreau20879a02012-12-03 16:32:10 +01006382 if (!conn->err_code)
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006383 conn->err_code = (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT) ?
Willy Tarreauf51c6982014-04-25 20:02:39 +02006384 CO_ER_SSL_KILLED_HB : CO_ER_SSL_HANDSHAKE;
Emeric Brun674b7432012-11-08 19:21:55 +01006385 goto out_error;
6386 }
6387 }
6388 /* read some data: consider handshake completed */
6389 goto reneg_ok;
6390 }
Olivier Houchard66ab4982019-02-26 18:37:15 +01006391 ret = SSL_do_handshake(ctx->ssl);
Olivier Houchardc2aae742017-09-22 18:26:28 +02006392check_error:
Emeric Brun46591952012-05-18 15:47:34 +02006393 if (ret != 1) {
6394 /* handshake did not complete, let's find why */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006395 ret = SSL_get_error(ctx->ssl, ret);
Emeric Brun46591952012-05-18 15:47:34 +02006396
6397 if (ret == SSL_ERROR_WANT_WRITE) {
6398 /* SSL handshake needs to write, L4 connection may not be ready */
Olivier Houchard03abf2d2019-05-28 10:12:02 +02006399 if (!(ctx->wait_event.events & SUB_RETRY_SEND))
Olivier Houchardea8dd942019-05-20 14:02:16 +02006400 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_SEND, &ctx->wait_event);
Emeric Brun46591952012-05-18 15:47:34 +02006401 return 0;
6402 }
6403 else if (ret == SSL_ERROR_WANT_READ) {
6404 /* SSL handshake needs to read, L4 connection is ready */
Olivier Houchardea8dd942019-05-20 14:02:16 +02006405 if (!(ctx->wait_event.events & SUB_RETRY_RECV))
Olivier Houchardea8dd942019-05-20 14:02:16 +02006406 ctx->xprt->subscribe(conn, ctx->xprt_ctx,
6407 SUB_RETRY_RECV, &ctx->wait_event);
Emeric Brun46591952012-05-18 15:47:34 +02006408 return 0;
6409 }
Willy Tarreau5db847a2019-05-09 14:13:35 +02006410#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006411 else if (ret == SSL_ERROR_WANT_ASYNC) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02006412 ssl_async_process_fds(ctx);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006413 return 0;
6414 }
6415#endif
Willy Tarreau89230192012-09-28 20:22:13 +02006416 else if (ret == SSL_ERROR_SYSCALL) {
6417 /* if errno is null, then connection was successfully established */
6418 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
6419 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01006420 if (!conn->err_code) {
Lukas Tribus49799162019-07-08 14:29:15 +02006421#if defined(OPENSSL_IS_BORINGSSL) || defined(LIBRESSL_VERSION_NUMBER)
6422 /* do not handle empty handshakes in BoringSSL or LibreSSL */
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01006423 conn->err_code = CO_ER_SSL_HANDSHAKE;
6424#else
6425 int empty_handshake;
Willy Tarreau5db847a2019-05-09 14:13:35 +02006426#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL)
Lukas Tribus49799162019-07-08 14:29:15 +02006427 /* use SSL_get_state() in OpenSSL >= 1.1.0; SSL_state() is broken */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006428 OSSL_HANDSHAKE_STATE state = SSL_get_state(ctx->ssl);
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01006429 empty_handshake = state == TLS_ST_BEFORE;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006430#else
Lukas Tribus49799162019-07-08 14:29:15 +02006431 /* access packet_length directly in OpenSSL <= 1.0.2; SSL_state() is broken */
6432 empty_handshake = !ctx->ssl->packet_length;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006433#endif
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01006434 if (empty_handshake) {
6435 if (!errno) {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006436 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01006437 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
6438 else
6439 conn->err_code = CO_ER_SSL_EMPTY;
6440 }
6441 else {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006442 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01006443 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
6444 else
6445 conn->err_code = CO_ER_SSL_ABORT;
6446 }
Emeric Brun29f037d2014-04-25 19:05:36 +02006447 }
6448 else {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006449 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emeric Brun29f037d2014-04-25 19:05:36 +02006450 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
6451 else
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01006452 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun29f037d2014-04-25 19:05:36 +02006453 }
Lukas Tribus49799162019-07-08 14:29:15 +02006454#endif /* BoringSSL or LibreSSL */
Emeric Brun29f037d2014-04-25 19:05:36 +02006455 }
Willy Tarreau89230192012-09-28 20:22:13 +02006456 goto out_error;
6457 }
Emeric Brun46591952012-05-18 15:47:34 +02006458 else {
6459 /* Fail on all other handshake errors */
Willy Tarreau566dc552012-10-19 20:52:18 +02006460 /* Note: OpenSSL may leave unread bytes in the socket's
6461 * buffer, causing an RST to be emitted upon close() on
6462 * TCP sockets. We first try to drain possibly pending
6463 * data to avoid this as much as possible.
6464 */
Willy Tarreaud85c4852015-03-13 00:40:28 +01006465 conn_sock_drain(conn);
Willy Tarreau20879a02012-12-03 16:32:10 +01006466 if (!conn->err_code)
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006467 conn->err_code = (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT) ?
Willy Tarreauf51c6982014-04-25 20:02:39 +02006468 CO_ER_SSL_KILLED_HB : CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02006469 goto out_error;
6470 }
6471 }
Willy Tarreau5db847a2019-05-09 14:13:35 +02006472#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Olivier Houchard522eea72017-11-03 16:27:47 +01006473 else {
6474 /*
6475 * If the server refused the early data, we have to send a
6476 * 425 to the client, as we no longer have the data to sent
6477 * them again.
6478 */
6479 if ((conn->flags & CO_FL_EARLY_DATA) && (objt_server(conn->target))) {
Olivier Houchard66ab4982019-02-26 18:37:15 +01006480 if (SSL_get_early_data_status(ctx->ssl) == SSL_EARLY_DATA_REJECTED) {
Olivier Houchard522eea72017-11-03 16:27:47 +01006481 conn->err_code = CO_ER_SSL_EARLY_FAILED;
6482 goto out_error;
6483 }
6484 }
6485 }
6486#endif
6487
Emeric Brun46591952012-05-18 15:47:34 +02006488
Emeric Brun674b7432012-11-08 19:21:55 +01006489reneg_ok:
Emeric Brunb5e42a82017-06-06 12:35:14 +00006490
Willy Tarreau5db847a2019-05-09 14:13:35 +02006491#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00006492 /* ASYNC engine API doesn't support moving read/write
6493 * buffers. So we disable ASYNC mode right after
6494 * the handshake to avoid buffer oveflows.
6495 */
6496 if (global_ssl.async)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006497 SSL_clear_mode(ctx->ssl, SSL_MODE_ASYNC);
Emeric Brunb5e42a82017-06-06 12:35:14 +00006498#endif
Emeric Brun46591952012-05-18 15:47:34 +02006499 /* Handshake succeeded */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006500 if (!SSL_session_reused(ctx->ssl)) {
Willy Tarreau0c9c2722014-05-28 12:28:58 +02006501 if (objt_server(conn->target)) {
6502 update_freq_ctr(&global.ssl_be_keys_per_sec, 1);
6503 if (global.ssl_be_keys_per_sec.curr_ctr > global.ssl_be_keys_max)
6504 global.ssl_be_keys_max = global.ssl_be_keys_per_sec.curr_ctr;
Emeric Brun46591952012-05-18 15:47:34 +02006505 }
Willy Tarreau0c9c2722014-05-28 12:28:58 +02006506 else {
6507 update_freq_ctr(&global.ssl_fe_keys_per_sec, 1);
6508 if (global.ssl_fe_keys_per_sec.curr_ctr > global.ssl_fe_keys_max)
6509 global.ssl_fe_keys_max = global.ssl_fe_keys_per_sec.curr_ctr;
6510 }
Emeric Brun46591952012-05-18 15:47:34 +02006511 }
6512
6513 /* The connection is now established at both layers, it's time to leave */
6514 conn->flags &= ~(flag | CO_FL_WAIT_L4_CONN | CO_FL_WAIT_L6_CONN);
6515 return 1;
6516
6517 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01006518 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02006519 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01006520 ERR_clear_error();
6521
Emeric Brun9fa89732012-10-04 17:09:56 +02006522 /* free resumed session if exists */
Willy Tarreau07d94e42018-09-20 10:57:52 +02006523 if (objt_server(conn->target) && __objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr) {
6524 free(__objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr);
6525 __objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr = NULL;
Emeric Brun9fa89732012-10-04 17:09:56 +02006526 }
6527
Emeric Brun46591952012-05-18 15:47:34 +02006528 /* Fail on all other handshake errors */
6529 conn->flags |= CO_FL_ERROR;
Willy Tarreau20879a02012-12-03 16:32:10 +01006530 if (!conn->err_code)
6531 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02006532 return 0;
6533}
6534
Willy Tarreauee1a6fc2020-01-17 07:52:13 +01006535/* Called from the upper layer, to subscribe <es> to events <event_type>. The
6536 * event subscriber <es> is not allowed to change from a previous call as long
6537 * as at least one event is still subscribed. The <event_type> must only be a
6538 * combination of SUB_RETRY_RECV and SUB_RETRY_SEND. It always returns 0,
6539 * unless the transport layer was already released.
6540 */
6541static int ssl_subscribe(struct connection *conn, void *xprt_ctx, int event_type, struct wait_event *es)
Olivier Houcharddf357842019-03-21 16:30:07 +01006542{
Olivier Houchardea8dd942019-05-20 14:02:16 +02006543 struct ssl_sock_ctx *ctx = xprt_ctx;
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006544
Olivier Houchard0ff28652019-06-24 18:57:39 +02006545 if (!ctx)
6546 return -1;
6547
Willy Tarreau113d52b2020-01-10 09:20:26 +01006548 BUG_ON(event_type & ~(SUB_RETRY_SEND|SUB_RETRY_RECV));
Willy Tarreauee1a6fc2020-01-17 07:52:13 +01006549 BUG_ON(ctx->subs && ctx->subs != es);
Olivier Houchardea8dd942019-05-20 14:02:16 +02006550
Willy Tarreauee1a6fc2020-01-17 07:52:13 +01006551 ctx->subs = es;
6552 es->events |= event_type;
Willy Tarreau113d52b2020-01-10 09:20:26 +01006553
6554 /* we may have to subscribe to lower layers for new events */
6555 event_type &= ~ctx->wait_event.events;
6556 if (event_type && !(conn->flags & CO_FL_SSL_WAIT_HS))
6557 ctx->xprt->subscribe(conn, ctx->xprt_ctx, event_type, &ctx->wait_event);
Olivier Houchardea8dd942019-05-20 14:02:16 +02006558 return 0;
Olivier Houcharddf357842019-03-21 16:30:07 +01006559}
6560
Willy Tarreauee1a6fc2020-01-17 07:52:13 +01006561/* Called from the upper layer, to unsubscribe <es> from events <event_type>.
6562 * The <es> pointer is not allowed to differ from the one passed to the
6563 * subscribe() call. It always returns zero.
6564 */
6565static int ssl_unsubscribe(struct connection *conn, void *xprt_ctx, int event_type, struct wait_event *es)
Olivier Houcharddf357842019-03-21 16:30:07 +01006566{
Olivier Houchardea8dd942019-05-20 14:02:16 +02006567 struct ssl_sock_ctx *ctx = xprt_ctx;
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006568
Willy Tarreau113d52b2020-01-10 09:20:26 +01006569 BUG_ON(event_type & ~(SUB_RETRY_SEND|SUB_RETRY_RECV));
Willy Tarreauee1a6fc2020-01-17 07:52:13 +01006570 BUG_ON(ctx->subs && ctx->subs != es);
Olivier Houchardea8dd942019-05-20 14:02:16 +02006571
Willy Tarreauee1a6fc2020-01-17 07:52:13 +01006572 es->events &= ~event_type;
6573 if (!es->events)
Willy Tarreau113d52b2020-01-10 09:20:26 +01006574 ctx->subs = NULL;
6575
6576 /* If we subscribed, and we're not doing the handshake,
6577 * then we subscribed because the upper layer asked for it,
6578 * as the upper layer is no longer interested, we can
6579 * unsubscribe too.
6580 */
6581 event_type &= ctx->wait_event.events;
6582 if (event_type && !(ctx->conn->flags & CO_FL_SSL_WAIT_HS))
6583 conn_unsubscribe(conn, ctx->xprt_ctx, event_type, &ctx->wait_event);
Olivier Houchardea8dd942019-05-20 14:02:16 +02006584
6585 return 0;
Olivier Houcharddf357842019-03-21 16:30:07 +01006586}
6587
Olivier Houchard2e055482019-05-27 19:50:12 +02006588/* Use the provided XPRT as an underlying XPRT, and provide the old one.
6589 * Returns 0 on success, and non-zero on failure.
6590 */
6591static 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)
6592{
6593 struct ssl_sock_ctx *ctx = xprt_ctx;
6594
6595 if (oldxprt_ops != NULL)
6596 *oldxprt_ops = ctx->xprt;
6597 if (oldxprt_ctx != NULL)
6598 *oldxprt_ctx = ctx->xprt_ctx;
6599 ctx->xprt = toadd_ops;
6600 ctx->xprt_ctx = toadd_ctx;
6601 return 0;
6602}
6603
Olivier Houchard5149b592019-05-23 17:47:36 +02006604/* Remove the specified xprt. If if it our underlying XPRT, remove it and
6605 * return 0, otherwise just call the remove_xprt method from the underlying
6606 * XPRT.
6607 */
6608static int ssl_remove_xprt(struct connection *conn, void *xprt_ctx, void *toremove_ctx, const struct xprt_ops *newops, void *newctx)
6609{
6610 struct ssl_sock_ctx *ctx = xprt_ctx;
6611
6612 if (ctx->xprt_ctx == toremove_ctx) {
6613 ctx->xprt_ctx = newctx;
6614 ctx->xprt = newops;
6615 return 0;
6616 }
6617 return (ctx->xprt->remove_xprt(conn, ctx->xprt_ctx, toremove_ctx, newops, newctx));
6618}
6619
Olivier Houchardea8dd942019-05-20 14:02:16 +02006620static struct task *ssl_sock_io_cb(struct task *t, void *context, unsigned short state)
6621{
6622 struct ssl_sock_ctx *ctx = context;
6623
6624 /* First if we're doing an handshake, try that */
6625 if (ctx->conn->flags & CO_FL_SSL_WAIT_HS)
6626 ssl_sock_handshake(ctx->conn, CO_FL_SSL_WAIT_HS);
6627 /* If we had an error, or the handshake is done and I/O is available,
6628 * let the upper layer know.
Olivier Houchard477902b2020-01-22 18:08:48 +01006629 * If no mux was set up yet, then call conn_create_mux()
Olivier Houchardea8dd942019-05-20 14:02:16 +02006630 * we can't be sure conn_fd_handler() will be called again.
6631 */
6632 if ((ctx->conn->flags & CO_FL_ERROR) ||
6633 !(ctx->conn->flags & CO_FL_SSL_WAIT_HS)) {
6634 int ret = 0;
6635 int woke = 0;
6636
6637 /* On error, wake any waiter */
Willy Tarreau113d52b2020-01-10 09:20:26 +01006638 if (ctx->subs) {
6639 tasklet_wakeup(ctx->subs->tasklet);
6640 ctx->subs->events = 0;
Olivier Houchardea8dd942019-05-20 14:02:16 +02006641 woke = 1;
Willy Tarreau113d52b2020-01-10 09:20:26 +01006642 ctx->subs = NULL;
Olivier Houchardea8dd942019-05-20 14:02:16 +02006643 }
Willy Tarreau113d52b2020-01-10 09:20:26 +01006644
Olivier Houchardea8dd942019-05-20 14:02:16 +02006645 /* If we're the first xprt for the connection, let the
Olivier Houchard477902b2020-01-22 18:08:48 +01006646 * upper layers know. If we have no mux, create it,
6647 * and once we have a mux, call its wake method if we didn't
6648 * woke a tasklet already.
Olivier Houchardea8dd942019-05-20 14:02:16 +02006649 */
6650 if (ctx->conn->xprt_ctx == ctx) {
Olivier Houchard477902b2020-01-22 18:08:48 +01006651 if (!ctx->conn->mux)
6652 ret = conn_create_mux(ctx->conn);
Olivier Houchardea8dd942019-05-20 14:02:16 +02006653 if (ret >= 0 && !woke && ctx->conn->mux && ctx->conn->mux->wake)
6654 ctx->conn->mux->wake(ctx->conn);
6655 return NULL;
6656 }
6657 }
Olivier Houchard54907bb2019-12-19 15:02:39 +01006658#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
6659 /* If we have early data and somebody wants to receive, let them */
Willy Tarreau113d52b2020-01-10 09:20:26 +01006660 else if (b_data(&ctx->early_buf) && ctx->subs &&
6661 ctx->subs->events & SUB_RETRY_RECV) {
6662 tasklet_wakeup(ctx->subs->tasklet);
6663 ctx->subs->events &= ~SUB_RETRY_RECV;
6664 if (!ctx->subs->events)
6665 ctx->subs = NULL;
Olivier Houchard54907bb2019-12-19 15:02:39 +01006666 }
6667#endif
Olivier Houchardea8dd942019-05-20 14:02:16 +02006668 return NULL;
6669}
6670
Emeric Brun46591952012-05-18 15:47:34 +02006671/* Receive up to <count> bytes from connection <conn>'s socket and store them
Willy Tarreauabf08d92014-01-14 11:31:27 +01006672 * into buffer <buf>. Only one call to recv() is performed, unless the
Emeric Brun46591952012-05-18 15:47:34 +02006673 * buffer wraps, in which case a second call may be performed. The connection's
6674 * flags are updated with whatever special event is detected (error, read0,
6675 * empty). The caller is responsible for taking care of those events and
6676 * avoiding the call if inappropriate. The function does not call the
6677 * connection's polling update function, so the caller is responsible for this.
6678 */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006679static 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 +02006680{
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006681 struct ssl_sock_ctx *ctx = xprt_ctx;
Willy Tarreaubfc4d772018-07-18 11:22:03 +02006682 ssize_t ret;
6683 size_t try, done = 0;
Emeric Brun46591952012-05-18 15:47:34 +02006684
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006685 if (!ctx)
Emeric Brun46591952012-05-18 15:47:34 +02006686 goto out_error;
6687
Olivier Houchard54907bb2019-12-19 15:02:39 +01006688#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
6689 if (b_data(&ctx->early_buf)) {
6690 try = b_contig_space(buf);
6691 if (try > b_data(&ctx->early_buf))
6692 try = b_data(&ctx->early_buf);
6693 memcpy(b_tail(buf), b_head(&ctx->early_buf), try);
6694 b_add(buf, try);
6695 b_del(&ctx->early_buf, try);
6696 if (b_data(&ctx->early_buf) == 0)
6697 b_free(&ctx->early_buf);
6698 return try;
6699 }
6700#endif
6701
Willy Tarreau911db9b2020-01-23 16:27:54 +01006702 if (conn->flags & (CO_FL_WAIT_XPRT | CO_FL_SSL_WAIT_HS))
Emeric Brun46591952012-05-18 15:47:34 +02006703 /* a handshake was requested */
6704 return 0;
6705
Emeric Brun46591952012-05-18 15:47:34 +02006706 /* read the largest possible block. For this, we perform only one call
6707 * to recv() unless the buffer wraps and we exactly fill the first hunk,
6708 * in which case we accept to do it once again. A new attempt is made on
6709 * EINTR too.
6710 */
Willy Tarreau00b0fb92014-01-17 11:09:40 +01006711 while (count > 0) {
Olivier Houchardc2aae742017-09-22 18:26:28 +02006712
Willy Tarreau591d4452018-06-15 17:21:00 +02006713 try = b_contig_space(buf);
6714 if (!try)
6715 break;
6716
Willy Tarreauabf08d92014-01-14 11:31:27 +01006717 if (try > count)
6718 try = count;
Willy Tarreau591d4452018-06-15 17:21:00 +02006719
Olivier Houchard66ab4982019-02-26 18:37:15 +01006720 ret = SSL_read(ctx->ssl, b_tail(buf), try);
Emmanuel Hocdetf967c312019-08-05 18:04:16 +02006721
Emeric Brune1f38db2012-09-03 20:36:47 +02006722 if (conn->flags & CO_FL_ERROR) {
6723 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01006724 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02006725 }
Emeric Brun46591952012-05-18 15:47:34 +02006726 if (ret > 0) {
Olivier Houchardacd14032018-06-28 18:17:23 +02006727 b_add(buf, ret);
Emeric Brun46591952012-05-18 15:47:34 +02006728 done += ret;
Emeric Brun46591952012-05-18 15:47:34 +02006729 count -= ret;
Emeric Brun46591952012-05-18 15:47:34 +02006730 }
Emeric Brun46591952012-05-18 15:47:34 +02006731 else {
Olivier Houchard66ab4982019-02-26 18:37:15 +01006732 ret = SSL_get_error(ctx->ssl, ret);
Emeric Brun46591952012-05-18 15:47:34 +02006733 if (ret == SSL_ERROR_WANT_WRITE) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01006734 /* handshake is running, and it needs to enable write */
Emeric Brun46591952012-05-18 15:47:34 +02006735 conn->flags |= CO_FL_SSL_WAIT_HS;
Olivier Houchardea8dd942019-05-20 14:02:16 +02006736 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_SEND, &ctx->wait_event);
Willy Tarreau5db847a2019-05-09 14:13:35 +02006737#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00006738 /* Async mode can be re-enabled, because we're leaving data state.*/
6739 if (global_ssl.async)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006740 SSL_set_mode(ctx->ssl, SSL_MODE_ASYNC);
Emeric Brunb5e42a82017-06-06 12:35:14 +00006741#endif
Emeric Brun46591952012-05-18 15:47:34 +02006742 break;
6743 }
6744 else if (ret == SSL_ERROR_WANT_READ) {
Olivier Houchard66ab4982019-02-26 18:37:15 +01006745 if (SSL_renegotiate_pending(ctx->ssl)) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02006746 ctx->xprt->subscribe(conn, ctx->xprt_ctx,
6747 SUB_RETRY_RECV,
6748 &ctx->wait_event);
Emeric Brun282a76a2012-11-08 18:02:56 +01006749 /* handshake is running, and it may need to re-enable read */
6750 conn->flags |= CO_FL_SSL_WAIT_HS;
Willy Tarreau5db847a2019-05-09 14:13:35 +02006751#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00006752 /* Async mode can be re-enabled, because we're leaving data state.*/
6753 if (global_ssl.async)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006754 SSL_set_mode(ctx->ssl, SSL_MODE_ASYNC);
Emeric Brunb5e42a82017-06-06 12:35:14 +00006755#endif
Emeric Brun282a76a2012-11-08 18:02:56 +01006756 break;
6757 }
Emeric Brun46591952012-05-18 15:47:34 +02006758 break;
Olivier Houchardc2aae742017-09-22 18:26:28 +02006759 } else if (ret == SSL_ERROR_ZERO_RETURN)
6760 goto read0;
Christopher Faulet4ac77a92018-02-19 14:25:15 +01006761 /* For SSL_ERROR_SYSCALL, make sure to clear the error
6762 * stack before shutting down the connection for
6763 * reading. */
Olivier Houchard7e2e5052018-02-13 15:17:23 +01006764 if (ret == SSL_ERROR_SYSCALL && (!errno || errno == EAGAIN))
6765 goto clear_ssl_error;
Emeric Brun46591952012-05-18 15:47:34 +02006766 /* otherwise it's a real error */
6767 goto out_error;
6768 }
6769 }
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02006770 leave:
Emeric Brun46591952012-05-18 15:47:34 +02006771 return done;
6772
Christopher Faulet4ac77a92018-02-19 14:25:15 +01006773 clear_ssl_error:
6774 /* Clear openssl global errors stack */
6775 ssl_sock_dump_errors(conn);
6776 ERR_clear_error();
Emeric Brun46591952012-05-18 15:47:34 +02006777 read0:
6778 conn_sock_read0(conn);
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02006779 goto leave;
Christopher Faulet4ac77a92018-02-19 14:25:15 +01006780
Emeric Brun46591952012-05-18 15:47:34 +02006781 out_error:
Olivier Houchard7e2e5052018-02-13 15:17:23 +01006782 conn->flags |= CO_FL_ERROR;
Emeric Brun644cde02012-12-14 11:21:13 +01006783 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02006784 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01006785 ERR_clear_error();
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02006786 goto leave;
Emeric Brun46591952012-05-18 15:47:34 +02006787}
6788
6789
Willy Tarreau787db9a2018-06-14 18:31:46 +02006790/* Send up to <count> pending bytes from buffer <buf> to connection <conn>'s
6791 * socket. <flags> may contain some CO_SFL_* flags to hint the system about
6792 * other pending data for example, but this flag is ignored at the moment.
Emeric Brun46591952012-05-18 15:47:34 +02006793 * Only one call to send() is performed, unless the buffer wraps, in which case
6794 * a second call may be performed. The connection's flags are updated with
6795 * whatever special event is detected (error, empty). The caller is responsible
6796 * for taking care of those events and avoiding the call if inappropriate. The
6797 * function does not call the connection's polling update function, so the caller
Willy Tarreau787db9a2018-06-14 18:31:46 +02006798 * is responsible for this. The buffer's output is not adjusted, it's up to the
6799 * caller to take care of this. It's up to the caller to update the buffer's
6800 * contents based on the return value.
Emeric Brun46591952012-05-18 15:47:34 +02006801 */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006802static 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 +02006803{
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006804 struct ssl_sock_ctx *ctx = xprt_ctx;
Willy Tarreau787db9a2018-06-14 18:31:46 +02006805 ssize_t ret;
6806 size_t try, done;
Emeric Brun46591952012-05-18 15:47:34 +02006807
6808 done = 0;
6809
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006810 if (!ctx)
Emeric Brun46591952012-05-18 15:47:34 +02006811 goto out_error;
6812
Willy Tarreau911db9b2020-01-23 16:27:54 +01006813 if (conn->flags & (CO_FL_WAIT_XPRT | CO_FL_SSL_WAIT_HS | CO_FL_EARLY_SSL_HS))
Emeric Brun46591952012-05-18 15:47:34 +02006814 /* a handshake was requested */
6815 return 0;
6816
6817 /* send the largest possible block. For this we perform only one call
6818 * to send() unless the buffer wraps and we exactly fill the first hunk,
6819 * in which case we accept to do it once again.
6820 */
Willy Tarreau787db9a2018-06-14 18:31:46 +02006821 while (count) {
Willy Tarreau5db847a2019-05-09 14:13:35 +02006822#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Olivier Houchardc2aae742017-09-22 18:26:28 +02006823 size_t written_data;
6824#endif
6825
Willy Tarreau787db9a2018-06-14 18:31:46 +02006826 try = b_contig_data(buf, done);
6827 if (try > count)
6828 try = count;
Willy Tarreaubfd59462013-02-21 07:46:09 +01006829
Willy Tarreau7bed9452014-02-02 02:00:24 +01006830 if (!(flags & CO_SFL_STREAMER) &&
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006831 !(ctx->xprt_st & SSL_SOCK_SEND_UNLIMITED) &&
Willy Tarreauef934602016-12-22 23:12:01 +01006832 global_ssl.max_record && try > global_ssl.max_record) {
6833 try = global_ssl.max_record;
Willy Tarreau518cedd2014-02-17 15:43:01 +01006834 }
6835 else {
6836 /* we need to keep the information about the fact that
6837 * we're not limiting the upcoming send(), because if it
6838 * fails, we'll have to retry with at least as many data.
6839 */
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006840 ctx->xprt_st |= SSL_SOCK_SEND_UNLIMITED;
Willy Tarreau518cedd2014-02-17 15:43:01 +01006841 }
Willy Tarreaubfd59462013-02-21 07:46:09 +01006842
Willy Tarreau5db847a2019-05-09 14:13:35 +02006843#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Olivier Houchard010941f2019-05-03 20:56:19 +02006844 if (!SSL_is_init_finished(ctx->ssl) && conn_is_back(conn)) {
Olivier Houchardc2aae742017-09-22 18:26:28 +02006845 unsigned int max_early;
6846
Olivier Houchard522eea72017-11-03 16:27:47 +01006847 if (objt_listener(conn->target))
Olivier Houchard66ab4982019-02-26 18:37:15 +01006848 max_early = SSL_get_max_early_data(ctx->ssl);
Olivier Houchard522eea72017-11-03 16:27:47 +01006849 else {
Olivier Houchard66ab4982019-02-26 18:37:15 +01006850 if (SSL_get0_session(ctx->ssl))
6851 max_early = SSL_SESSION_get_max_early_data(SSL_get0_session(ctx->ssl));
Olivier Houchard522eea72017-11-03 16:27:47 +01006852 else
6853 max_early = 0;
6854 }
6855
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006856 if (try + ctx->sent_early_data > max_early) {
6857 try -= (try + ctx->sent_early_data) - max_early;
Olivier Houchard522eea72017-11-03 16:27:47 +01006858 if (try <= 0) {
Olivier Houchard010941f2019-05-03 20:56:19 +02006859 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Olivier Houchard965e84e2019-06-15 20:59:30 +02006860 tasklet_wakeup(ctx->wait_event.tasklet);
Olivier Houchardc2aae742017-09-22 18:26:28 +02006861 break;
Olivier Houchard522eea72017-11-03 16:27:47 +01006862 }
Olivier Houchardc2aae742017-09-22 18:26:28 +02006863 }
Olivier Houchard66ab4982019-02-26 18:37:15 +01006864 ret = SSL_write_early_data(ctx->ssl, b_peek(buf, done), try, &written_data);
Olivier Houchardc2aae742017-09-22 18:26:28 +02006865 if (ret == 1) {
6866 ret = written_data;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006867 ctx->sent_early_data += ret;
Olivier Houchard965e84e2019-06-15 20:59:30 +02006868 if (objt_server(conn->target)) {
Olivier Houchard522eea72017-11-03 16:27:47 +01006869 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN | CO_FL_EARLY_DATA;
Olivier Houchard965e84e2019-06-15 20:59:30 +02006870 /* Initiate the handshake, now */
6871 tasklet_wakeup(ctx->wait_event.tasklet);
6872 }
Olivier Houchard522eea72017-11-03 16:27:47 +01006873
Olivier Houchardc2aae742017-09-22 18:26:28 +02006874 }
6875
6876 } else
6877#endif
Olivier Houchard66ab4982019-02-26 18:37:15 +01006878 ret = SSL_write(ctx->ssl, b_peek(buf, done), try);
Willy Tarreau518cedd2014-02-17 15:43:01 +01006879
Emeric Brune1f38db2012-09-03 20:36:47 +02006880 if (conn->flags & CO_FL_ERROR) {
6881 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01006882 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02006883 }
Emeric Brun46591952012-05-18 15:47:34 +02006884 if (ret > 0) {
Willy Tarreauc192b0a2020-01-23 09:11:58 +01006885 /* A send succeeded, so we can consider ourself connected */
6886 conn->flags &= ~CO_FL_WAIT_L4L6;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006887 ctx->xprt_st &= ~SSL_SOCK_SEND_UNLIMITED;
Willy Tarreau787db9a2018-06-14 18:31:46 +02006888 count -= ret;
Emeric Brun46591952012-05-18 15:47:34 +02006889 done += ret;
Emeric Brun46591952012-05-18 15:47:34 +02006890 }
6891 else {
Olivier Houchard66ab4982019-02-26 18:37:15 +01006892 ret = SSL_get_error(ctx->ssl, ret);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006893
Emeric Brun46591952012-05-18 15:47:34 +02006894 if (ret == SSL_ERROR_WANT_WRITE) {
Olivier Houchard66ab4982019-02-26 18:37:15 +01006895 if (SSL_renegotiate_pending(ctx->ssl)) {
Emeric Brun282a76a2012-11-08 18:02:56 +01006896 /* handshake is running, and it may need to re-enable write */
6897 conn->flags |= CO_FL_SSL_WAIT_HS;
Olivier Houchardea8dd942019-05-20 14:02:16 +02006898 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_SEND, &ctx->wait_event);
Willy Tarreau5db847a2019-05-09 14:13:35 +02006899#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00006900 /* Async mode can be re-enabled, because we're leaving data state.*/
6901 if (global_ssl.async)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006902 SSL_set_mode(ctx->ssl, SSL_MODE_ASYNC);
Emeric Brunb5e42a82017-06-06 12:35:14 +00006903#endif
Emeric Brun282a76a2012-11-08 18:02:56 +01006904 break;
6905 }
Olivier Houchardea8dd942019-05-20 14:02:16 +02006906
Emeric Brun46591952012-05-18 15:47:34 +02006907 break;
6908 }
6909 else if (ret == SSL_ERROR_WANT_READ) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01006910 /* handshake is running, and it needs to enable read */
Emeric Brun46591952012-05-18 15:47:34 +02006911 conn->flags |= CO_FL_SSL_WAIT_HS;
Olivier Houchardea8dd942019-05-20 14:02:16 +02006912 ctx->xprt->subscribe(conn, ctx->xprt_ctx,
6913 SUB_RETRY_RECV,
6914 &ctx->wait_event);
Willy Tarreau5db847a2019-05-09 14:13:35 +02006915#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00006916 /* Async mode can be re-enabled, because we're leaving data state.*/
6917 if (global_ssl.async)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006918 SSL_set_mode(ctx->ssl, SSL_MODE_ASYNC);
Emeric Brunb5e42a82017-06-06 12:35:14 +00006919#endif
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006920 break;
6921 }
Emeric Brun46591952012-05-18 15:47:34 +02006922 goto out_error;
6923 }
6924 }
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02006925 leave:
Emeric Brun46591952012-05-18 15:47:34 +02006926 return done;
6927
6928 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01006929 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02006930 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01006931 ERR_clear_error();
6932
Emeric Brun46591952012-05-18 15:47:34 +02006933 conn->flags |= CO_FL_ERROR;
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02006934 goto leave;
Emeric Brun46591952012-05-18 15:47:34 +02006935}
6936
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006937static void ssl_sock_close(struct connection *conn, void *xprt_ctx) {
Emeric Brun46591952012-05-18 15:47:34 +02006938
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006939 struct ssl_sock_ctx *ctx = xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006940
Olivier Houchardea8dd942019-05-20 14:02:16 +02006941
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006942 if (ctx) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02006943 if (ctx->wait_event.events != 0)
6944 ctx->xprt->unsubscribe(ctx->conn, ctx->xprt_ctx,
6945 ctx->wait_event.events,
6946 &ctx->wait_event);
Willy Tarreau113d52b2020-01-10 09:20:26 +01006947 if (ctx->subs) {
6948 ctx->subs->events = 0;
6949 tasklet_wakeup(ctx->subs->tasklet);
Olivier Houchardea8dd942019-05-20 14:02:16 +02006950 }
Willy Tarreau113d52b2020-01-10 09:20:26 +01006951
Olivier Houchard692c1d02019-05-23 18:41:47 +02006952 if (ctx->xprt->close)
6953 ctx->xprt->close(conn, ctx->xprt_ctx);
Willy Tarreau5db847a2019-05-09 14:13:35 +02006954#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brun3854e012017-05-17 20:42:48 +02006955 if (global_ssl.async) {
6956 OSSL_ASYNC_FD all_fd[32], afd;
6957 size_t num_all_fds = 0;
6958 int i;
6959
Olivier Houchard66ab4982019-02-26 18:37:15 +01006960 SSL_get_all_async_fds(ctx->ssl, NULL, &num_all_fds);
Emeric Brun3854e012017-05-17 20:42:48 +02006961 if (num_all_fds > 32) {
6962 send_log(NULL, LOG_EMERG, "haproxy: openssl returns too many async fds. It seems a bug. Process may crash\n");
6963 return;
6964 }
6965
Olivier Houchard66ab4982019-02-26 18:37:15 +01006966 SSL_get_all_async_fds(ctx->ssl, all_fd, &num_all_fds);
Emeric Brun3854e012017-05-17 20:42:48 +02006967
6968 /* If an async job is pending, we must try to
6969 to catch the end using polling before calling
6970 SSL_free */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006971 if (num_all_fds && SSL_waiting_for_async(ctx->ssl)) {
Emeric Brun3854e012017-05-17 20:42:48 +02006972 for (i=0 ; i < num_all_fds ; i++) {
6973 /* switch on an handler designed to
6974 * handle the SSL_free
6975 */
6976 afd = all_fd[i];
6977 fdtab[afd].iocb = ssl_async_fd_free;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006978 fdtab[afd].owner = ctx->ssl;
Emeric Brun3854e012017-05-17 20:42:48 +02006979 fd_want_recv(afd);
Emeric Brunce9e01c2017-05-31 10:02:53 +00006980 /* To ensure that the fd cache won't be used
6981 * and we'll catch a real RD event.
6982 */
6983 fd_cant_recv(afd);
Emeric Brun3854e012017-05-17 20:42:48 +02006984 }
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02006985 tasklet_free(ctx->wait_event.tasklet);
Olivier Houchard66ab4982019-02-26 18:37:15 +01006986 pool_free(ssl_sock_ctx_pool, ctx);
Olivier Houchard2be5a4c2019-03-08 18:54:43 +01006987 _HA_ATOMIC_ADD(&jobs, 1);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006988 return;
6989 }
Emeric Brun3854e012017-05-17 20:42:48 +02006990 /* Else we can remove the fds from the fdtab
6991 * and call SSL_free.
6992 * note: we do a fd_remove and not a delete
6993 * because the fd is owned by the engine.
6994 * the engine is responsible to close
6995 */
6996 for (i=0 ; i < num_all_fds ; i++)
6997 fd_remove(all_fd[i]);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006998 }
6999#endif
Olivier Houchard66ab4982019-02-26 18:37:15 +01007000 SSL_free(ctx->ssl);
Olivier Houchard54907bb2019-12-19 15:02:39 +01007001 b_free(&ctx->early_buf);
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02007002 tasklet_free(ctx->wait_event.tasklet);
Olivier Houchard66ab4982019-02-26 18:37:15 +01007003 pool_free(ssl_sock_ctx_pool, ctx);
Olivier Houchard2be5a4c2019-03-08 18:54:43 +01007004 _HA_ATOMIC_SUB(&sslconns, 1);
Emeric Brun46591952012-05-18 15:47:34 +02007005 }
Emeric Brun46591952012-05-18 15:47:34 +02007006}
7007
7008/* This function tries to perform a clean shutdown on an SSL connection, and in
7009 * any case, flags the connection as reusable if no handshake was in progress.
7010 */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01007011static void ssl_sock_shutw(struct connection *conn, void *xprt_ctx, int clean)
Emeric Brun46591952012-05-18 15:47:34 +02007012{
Olivier Houcharde179d0e2019-03-21 18:27:17 +01007013 struct ssl_sock_ctx *ctx = xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007014
Willy Tarreau911db9b2020-01-23 16:27:54 +01007015 if (conn->flags & (CO_FL_WAIT_XPRT | CO_FL_SSL_WAIT_HS))
Emeric Brun46591952012-05-18 15:47:34 +02007016 return;
Emmanuel Hocdet405ff312017-01-08 14:07:39 +01007017 if (!clean)
7018 /* don't sent notify on SSL_shutdown */
Olivier Houchard66ab4982019-02-26 18:37:15 +01007019 SSL_set_quiet_shutdown(ctx->ssl, 1);
Emeric Brun46591952012-05-18 15:47:34 +02007020 /* no handshake was in progress, try a clean ssl shutdown */
Olivier Houchard66ab4982019-02-26 18:37:15 +01007021 if (SSL_shutdown(ctx->ssl) <= 0) {
Emeric Brun644cde02012-12-14 11:21:13 +01007022 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02007023 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01007024 ERR_clear_error();
7025 }
Emeric Brun46591952012-05-18 15:47:34 +02007026}
7027
William Lallemandd4f946c2019-12-05 10:26:40 +01007028/* fill a buffer with the algorithm and size of a public key */
7029static int cert_get_pkey_algo(X509 *crt, struct buffer *out)
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01007030{
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01007031 int bits = 0;
7032 int sig = TLSEXT_signature_anonymous;
7033 int len = -1;
Emmanuel Hocdetc3775d22019-11-04 18:19:32 +01007034 EVP_PKEY *pkey;
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01007035
Emmanuel Hocdetc3775d22019-11-04 18:19:32 +01007036 pkey = X509_get_pubkey(crt);
7037 if (pkey) {
7038 bits = EVP_PKEY_bits(pkey);
7039 switch(EVP_PKEY_base_id(pkey)) {
7040 case EVP_PKEY_RSA:
7041 sig = TLSEXT_signature_rsa;
7042 break;
7043 case EVP_PKEY_EC:
7044 sig = TLSEXT_signature_ecdsa;
7045 break;
7046 case EVP_PKEY_DSA:
7047 sig = TLSEXT_signature_dsa;
7048 break;
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01007049 }
Emmanuel Hocdetc3775d22019-11-04 18:19:32 +01007050 EVP_PKEY_free(pkey);
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01007051 }
7052
7053 switch(sig) {
7054 case TLSEXT_signature_rsa:
7055 len = chunk_printf(out, "RSA%d", bits);
7056 break;
7057 case TLSEXT_signature_ecdsa:
7058 len = chunk_printf(out, "EC%d", bits);
7059 break;
7060 case TLSEXT_signature_dsa:
7061 len = chunk_printf(out, "DSA%d", bits);
7062 break;
7063 default:
7064 return 0;
7065 }
7066 if (len < 0)
7067 return 0;
7068 return 1;
7069}
7070
William Lallemandd4f946c2019-12-05 10:26:40 +01007071/* used for ppv2 pkey alog (can be used for logging) */
7072int ssl_sock_get_pkey_algo(struct connection *conn, struct buffer *out)
7073{
7074 struct ssl_sock_ctx *ctx;
7075 X509 *crt;
7076
7077 if (!ssl_sock_is_ssl(conn))
7078 return 0;
7079
7080 ctx = conn->xprt_ctx;
7081
7082 crt = SSL_get_certificate(ctx->ssl);
7083 if (!crt)
7084 return 0;
7085
7086 return cert_get_pkey_algo(crt, out);
7087}
7088
Emmanuel Hocdet283e0042017-11-02 14:05:23 +01007089/* used for ppv2 cert signature (can be used for logging) */
7090const char *ssl_sock_get_cert_sig(struct connection *conn)
7091{
Christopher Faulet82004142019-09-10 10:12:03 +02007092 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007093
Emmanuel Hocdet283e0042017-11-02 14:05:23 +01007094 __OPENSSL_110_CONST__ ASN1_OBJECT *algorithm;
7095 X509 *crt;
7096
7097 if (!ssl_sock_is_ssl(conn))
7098 return NULL;
Christopher Faulet82004142019-09-10 10:12:03 +02007099 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007100 crt = SSL_get_certificate(ctx->ssl);
Emmanuel Hocdet283e0042017-11-02 14:05:23 +01007101 if (!crt)
7102 return NULL;
7103 X509_ALGOR_get0(&algorithm, NULL, NULL, X509_get0_tbs_sigalg(crt));
7104 return OBJ_nid2sn(OBJ_obj2nid(algorithm));
7105}
7106
Emmanuel Hocdet253c3b72018-02-01 18:29:59 +01007107/* used for ppv2 authority */
7108const char *ssl_sock_get_sni(struct connection *conn)
7109{
7110#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Christopher Faulet82004142019-09-10 10:12:03 +02007111 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007112
Emmanuel Hocdet253c3b72018-02-01 18:29:59 +01007113 if (!ssl_sock_is_ssl(conn))
7114 return NULL;
Christopher Faulet82004142019-09-10 10:12:03 +02007115 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007116 return SSL_get_servername(ctx->ssl, TLSEXT_NAMETYPE_host_name);
Emmanuel Hocdet253c3b72018-02-01 18:29:59 +01007117#else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007118 return NULL;
Emmanuel Hocdet253c3b72018-02-01 18:29:59 +01007119#endif
7120}
7121
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02007122/* used for logging/ppv2, may be changed for a sample fetch later */
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02007123const char *ssl_sock_get_cipher_name(struct connection *conn)
7124{
Christopher Faulet82004142019-09-10 10:12:03 +02007125 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007126
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02007127 if (!ssl_sock_is_ssl(conn))
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02007128 return NULL;
Christopher Faulet82004142019-09-10 10:12:03 +02007129 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007130 return SSL_get_cipher_name(ctx->ssl);
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02007131}
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_proto_version(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_version(ctx->ssl);
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02007142}
7143
Willy Tarreau8d598402012-10-22 17:58:39 +02007144/* Extract a serial from a cert, and copy it to a chunk.
7145 * Returns 1 if serial is found and copied, 0 if no serial found and
7146 * -1 if output is not large enough.
7147 */
7148static int
Willy Tarreau83061a82018-07-13 11:56:34 +02007149ssl_sock_get_serial(X509 *crt, struct buffer *out)
Willy Tarreau8d598402012-10-22 17:58:39 +02007150{
7151 ASN1_INTEGER *serial;
7152
7153 serial = X509_get_serialNumber(crt);
7154 if (!serial)
7155 return 0;
7156
7157 if (out->size < serial->length)
7158 return -1;
7159
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007160 memcpy(out->area, serial->data, serial->length);
7161 out->data = serial->length;
Willy Tarreau8d598402012-10-22 17:58:39 +02007162 return 1;
7163}
7164
Emeric Brun43e79582014-10-29 19:03:26 +01007165/* Extract a cert to der, and copy it to a chunk.
Joseph Herlant017b3da2018-11-15 09:07:59 -08007166 * Returns 1 if the cert is found and copied, 0 on der conversion failure
7167 * and -1 if the output is not large enough.
Emeric Brun43e79582014-10-29 19:03:26 +01007168 */
7169static int
Willy Tarreau83061a82018-07-13 11:56:34 +02007170ssl_sock_crt2der(X509 *crt, struct buffer *out)
Emeric Brun43e79582014-10-29 19:03:26 +01007171{
7172 int len;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007173 unsigned char *p = (unsigned char *) out->area;;
Emeric Brun43e79582014-10-29 19:03:26 +01007174
7175 len =i2d_X509(crt, NULL);
7176 if (len <= 0)
7177 return 1;
7178
7179 if (out->size < len)
7180 return -1;
7181
7182 i2d_X509(crt,&p);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007183 out->data = len;
Emeric Brun43e79582014-10-29 19:03:26 +01007184 return 1;
7185}
7186
Emeric Brunce5ad802012-10-22 14:11:22 +02007187
Willy Tarreau83061a82018-07-13 11:56:34 +02007188/* Copy Date in ASN1_UTCTIME format in struct buffer out.
Emeric Brunce5ad802012-10-22 14:11:22 +02007189 * Returns 1 if serial is found and copied, 0 if no valid time found
7190 * and -1 if output is not large enough.
7191 */
7192static int
Willy Tarreau83061a82018-07-13 11:56:34 +02007193ssl_sock_get_time(ASN1_TIME *tm, struct buffer *out)
Emeric Brunce5ad802012-10-22 14:11:22 +02007194{
7195 if (tm->type == V_ASN1_GENERALIZEDTIME) {
7196 ASN1_GENERALIZEDTIME *gentm = (ASN1_GENERALIZEDTIME *)tm;
7197
7198 if (gentm->length < 12)
7199 return 0;
7200 if (gentm->data[0] != 0x32 || gentm->data[1] != 0x30)
7201 return 0;
7202 if (out->size < gentm->length-2)
7203 return -1;
7204
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007205 memcpy(out->area, gentm->data+2, gentm->length-2);
7206 out->data = gentm->length-2;
Emeric Brunce5ad802012-10-22 14:11:22 +02007207 return 1;
7208 }
7209 else if (tm->type == V_ASN1_UTCTIME) {
7210 ASN1_UTCTIME *utctm = (ASN1_UTCTIME *)tm;
7211
7212 if (utctm->length < 10)
7213 return 0;
7214 if (utctm->data[0] >= 0x35)
7215 return 0;
7216 if (out->size < utctm->length)
7217 return -1;
7218
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007219 memcpy(out->area, utctm->data, utctm->length);
7220 out->data = utctm->length;
Emeric Brunce5ad802012-10-22 14:11:22 +02007221 return 1;
7222 }
7223
7224 return 0;
7225}
7226
Emeric Brun87855892012-10-17 17:39:35 +02007227/* Extract an entry from a X509_NAME and copy its value to an output chunk.
7228 * Returns 1 if entry found, 0 if entry not found, or -1 if output not large enough.
7229 */
7230static int
Willy Tarreau83061a82018-07-13 11:56:34 +02007231ssl_sock_get_dn_entry(X509_NAME *a, const struct buffer *entry, int pos,
7232 struct buffer *out)
Emeric Brun87855892012-10-17 17:39:35 +02007233{
7234 X509_NAME_ENTRY *ne;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007235 ASN1_OBJECT *obj;
7236 ASN1_STRING *data;
7237 const unsigned char *data_ptr;
7238 int data_len;
Emeric Brun87855892012-10-17 17:39:35 +02007239 int i, j, n;
7240 int cur = 0;
7241 const char *s;
7242 char tmp[128];
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007243 int name_count;
7244
7245 name_count = X509_NAME_entry_count(a);
Emeric Brun87855892012-10-17 17:39:35 +02007246
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007247 out->data = 0;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007248 for (i = 0; i < name_count; i++) {
Emeric Brun87855892012-10-17 17:39:35 +02007249 if (pos < 0)
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007250 j = (name_count-1) - i;
Emeric Brun87855892012-10-17 17:39:35 +02007251 else
7252 j = i;
7253
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007254 ne = X509_NAME_get_entry(a, j);
7255 obj = X509_NAME_ENTRY_get_object(ne);
7256 data = X509_NAME_ENTRY_get_data(ne);
7257 data_ptr = ASN1_STRING_get0_data(data);
7258 data_len = ASN1_STRING_length(data);
7259 n = OBJ_obj2nid(obj);
Emeric Brun87855892012-10-17 17:39:35 +02007260 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007261 i2t_ASN1_OBJECT(tmp, sizeof(tmp), obj);
Emeric Brun87855892012-10-17 17:39:35 +02007262 s = tmp;
7263 }
7264
7265 if (chunk_strcasecmp(entry, s) != 0)
7266 continue;
7267
7268 if (pos < 0)
7269 cur--;
7270 else
7271 cur++;
7272
7273 if (cur != pos)
7274 continue;
7275
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007276 if (data_len > out->size)
Emeric Brun87855892012-10-17 17:39:35 +02007277 return -1;
7278
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007279 memcpy(out->area, data_ptr, data_len);
7280 out->data = data_len;
Emeric Brun87855892012-10-17 17:39:35 +02007281 return 1;
7282 }
7283
7284 return 0;
7285
William Lallemandd4f946c2019-12-05 10:26:40 +01007286}
7287
7288/*
7289 * Extract and format the DNS SAN extensions and copy result into a chuink
7290 * Return 0;
7291 */
7292#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
7293static int ssl_sock_get_san_oneline(X509 *cert, struct buffer *out)
7294{
7295 int i;
7296 char *str;
7297 STACK_OF(GENERAL_NAME) *names = NULL;
7298
7299 names = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
7300 if (names) {
7301 for (i = 0; i < sk_GENERAL_NAME_num(names); i++) {
7302 GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i);
7303 if (i > 0)
7304 chunk_appendf(out, ", ");
7305 if (name->type == GEN_DNS) {
7306 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
7307 chunk_appendf(out, "DNS:%s", str);
7308 OPENSSL_free(str);
7309 }
7310 }
7311 }
7312 sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
7313 }
7314 return 0;
Emeric Brun87855892012-10-17 17:39:35 +02007315}
William Lallemandd4f946c2019-12-05 10:26:40 +01007316#endif
Emeric Brun87855892012-10-17 17:39:35 +02007317
Elliot Otchet71f82972020-01-15 08:12:14 -05007318/*
7319 * Extract the DN in the specified format from the X509_NAME and copy result to a chunk.
7320 * Currently supports rfc2253 for returning LDAP V3 DNs.
7321 * Returns 1 if dn entries exist, 0 if no dn entry was found.
7322 */
7323static int
7324ssl_sock_get_dn_formatted(X509_NAME *a, const struct buffer *format, struct buffer *out)
7325{
7326 BIO *bio = NULL;
7327 int ret = 0;
7328 int data_len = 0;
7329
7330 if (chunk_strcmp(format, "rfc2253") == 0) {
7331 bio = BIO_new(BIO_s_mem());
7332 if (bio == NULL)
7333 goto out;
7334
7335 if (X509_NAME_print_ex(bio, a, 0, XN_FLAG_RFC2253) < 0)
7336 goto out;
7337
7338 if ((data_len = BIO_read(bio, out->area, out->size)) <= 0)
7339 goto out;
7340
7341 out->data = data_len;
7342
7343 ret = 1;
7344 }
7345out:
7346 if (bio)
7347 BIO_free(bio);
7348 return ret;
7349}
7350
Emeric Brun87855892012-10-17 17:39:35 +02007351/* Extract and format full DN from a X509_NAME and copy result into a chunk
7352 * Returns 1 if dn entries exits, 0 if no dn entry found or -1 if output is not large enough.
7353 */
7354static int
Willy Tarreau83061a82018-07-13 11:56:34 +02007355ssl_sock_get_dn_oneline(X509_NAME *a, struct buffer *out)
Emeric Brun87855892012-10-17 17:39:35 +02007356{
7357 X509_NAME_ENTRY *ne;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007358 ASN1_OBJECT *obj;
7359 ASN1_STRING *data;
7360 const unsigned char *data_ptr;
7361 int data_len;
Emeric Brun87855892012-10-17 17:39:35 +02007362 int i, n, ln;
7363 int l = 0;
7364 const char *s;
7365 char *p;
7366 char tmp[128];
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007367 int name_count;
7368
7369
7370 name_count = X509_NAME_entry_count(a);
Emeric Brun87855892012-10-17 17:39:35 +02007371
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007372 out->data = 0;
7373 p = out->area;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007374 for (i = 0; i < name_count; i++) {
7375 ne = X509_NAME_get_entry(a, i);
7376 obj = X509_NAME_ENTRY_get_object(ne);
7377 data = X509_NAME_ENTRY_get_data(ne);
7378 data_ptr = ASN1_STRING_get0_data(data);
7379 data_len = ASN1_STRING_length(data);
7380 n = OBJ_obj2nid(obj);
Emeric Brun87855892012-10-17 17:39:35 +02007381 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007382 i2t_ASN1_OBJECT(tmp, sizeof(tmp), obj);
Emeric Brun87855892012-10-17 17:39:35 +02007383 s = tmp;
7384 }
7385 ln = strlen(s);
7386
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007387 l += 1 + ln + 1 + data_len;
Emeric Brun87855892012-10-17 17:39:35 +02007388 if (l > out->size)
7389 return -1;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007390 out->data = l;
Emeric Brun87855892012-10-17 17:39:35 +02007391
7392 *(p++)='/';
7393 memcpy(p, s, ln);
7394 p += ln;
7395 *(p++)='=';
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007396 memcpy(p, data_ptr, data_len);
7397 p += data_len;
Emeric Brun87855892012-10-17 17:39:35 +02007398 }
7399
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007400 if (!out->data)
Emeric Brun87855892012-10-17 17:39:35 +02007401 return 0;
7402
7403 return 1;
7404}
7405
Olivier Houchardab28a322018-12-21 19:45:40 +01007406void ssl_sock_set_alpn(struct connection *conn, const unsigned char *alpn, int len)
7407{
7408#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Christopher Faulet82004142019-09-10 10:12:03 +02007409 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007410
Olivier Houcharde488ea82019-06-28 14:10:33 +02007411 if (!ssl_sock_is_ssl(conn))
7412 return;
Christopher Faulet82004142019-09-10 10:12:03 +02007413 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007414 SSL_set_alpn_protos(ctx->ssl, alpn, len);
Olivier Houchardab28a322018-12-21 19:45:40 +01007415#endif
7416}
7417
Willy Tarreau119a4082016-12-22 21:58:38 +01007418/* Sets advertised SNI for outgoing connections. Please set <hostname> to NULL
7419 * to disable SNI.
7420 */
Willy Tarreau63076412015-07-10 11:33:32 +02007421void ssl_sock_set_servername(struct connection *conn, const char *hostname)
7422{
7423#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Christopher Faulet82004142019-09-10 10:12:03 +02007424 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007425
Willy Tarreau119a4082016-12-22 21:58:38 +01007426 char *prev_name;
7427
Willy Tarreau63076412015-07-10 11:33:32 +02007428 if (!ssl_sock_is_ssl(conn))
7429 return;
Christopher Faulet82004142019-09-10 10:12:03 +02007430 ctx = conn->xprt_ctx;
Willy Tarreau63076412015-07-10 11:33:32 +02007431
Willy Tarreau119a4082016-12-22 21:58:38 +01007432 /* if the SNI changes, we must destroy the reusable context so that a
7433 * new connection will present a new SNI. As an optimization we could
7434 * later imagine having a small cache of ssl_ctx to hold a few SNI per
7435 * server.
7436 */
Olivier Houchard66ab4982019-02-26 18:37:15 +01007437 prev_name = (char *)SSL_get_servername(ctx->ssl, TLSEXT_NAMETYPE_host_name);
Willy Tarreau119a4082016-12-22 21:58:38 +01007438 if ((!prev_name && hostname) ||
7439 (prev_name && (!hostname || strcmp(hostname, prev_name) != 0)))
Olivier Houchard66ab4982019-02-26 18:37:15 +01007440 SSL_set_session(ctx->ssl, NULL);
Willy Tarreau119a4082016-12-22 21:58:38 +01007441
Olivier Houchard66ab4982019-02-26 18:37:15 +01007442 SSL_set_tlsext_host_name(ctx->ssl, hostname);
Willy Tarreau63076412015-07-10 11:33:32 +02007443#endif
7444}
7445
Emeric Brun0abf8362014-06-24 18:26:41 +02007446/* Extract peer certificate's common name into the chunk dest
7447 * Returns
7448 * the len of the extracted common name
7449 * or 0 if no CN found in DN
7450 * or -1 on error case (i.e. no peer certificate)
7451 */
Willy Tarreau83061a82018-07-13 11:56:34 +02007452int ssl_sock_get_remote_common_name(struct connection *conn,
7453 struct buffer *dest)
David Safb76832014-05-08 23:42:08 -04007454{
Christopher Faulet82004142019-09-10 10:12:03 +02007455 struct ssl_sock_ctx *ctx;
David Safb76832014-05-08 23:42:08 -04007456 X509 *crt = NULL;
7457 X509_NAME *name;
David Safb76832014-05-08 23:42:08 -04007458 const char find_cn[] = "CN";
Willy Tarreau83061a82018-07-13 11:56:34 +02007459 const struct buffer find_cn_chunk = {
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007460 .area = (char *)&find_cn,
7461 .data = sizeof(find_cn)-1
David Safb76832014-05-08 23:42:08 -04007462 };
Emeric Brun0abf8362014-06-24 18:26:41 +02007463 int result = -1;
David Safb76832014-05-08 23:42:08 -04007464
7465 if (!ssl_sock_is_ssl(conn))
Emeric Brun0abf8362014-06-24 18:26:41 +02007466 goto out;
Christopher Faulet82004142019-09-10 10:12:03 +02007467 ctx = conn->xprt_ctx;
David Safb76832014-05-08 23:42:08 -04007468
7469 /* SSL_get_peer_certificate, it increase X509 * ref count */
Olivier Houchard66ab4982019-02-26 18:37:15 +01007470 crt = SSL_get_peer_certificate(ctx->ssl);
David Safb76832014-05-08 23:42:08 -04007471 if (!crt)
7472 goto out;
7473
7474 name = X509_get_subject_name(crt);
7475 if (!name)
7476 goto out;
David Safb76832014-05-08 23:42:08 -04007477
Emeric Brun0abf8362014-06-24 18:26:41 +02007478 result = ssl_sock_get_dn_entry(name, &find_cn_chunk, 1, dest);
7479out:
David Safb76832014-05-08 23:42:08 -04007480 if (crt)
7481 X509_free(crt);
7482
7483 return result;
7484}
7485
Dave McCowan328fb582014-07-30 10:39:13 -04007486/* returns 1 if client passed a certificate for this session, 0 if not */
7487int ssl_sock_get_cert_used_sess(struct connection *conn)
7488{
Christopher Faulet82004142019-09-10 10:12:03 +02007489 struct ssl_sock_ctx *ctx;
Dave McCowan328fb582014-07-30 10:39:13 -04007490 X509 *crt = NULL;
7491
7492 if (!ssl_sock_is_ssl(conn))
7493 return 0;
Christopher Faulet82004142019-09-10 10:12:03 +02007494 ctx = conn->xprt_ctx;
Dave McCowan328fb582014-07-30 10:39:13 -04007495
7496 /* SSL_get_peer_certificate, it increase X509 * ref count */
Olivier Houchard66ab4982019-02-26 18:37:15 +01007497 crt = SSL_get_peer_certificate(ctx->ssl);
Dave McCowan328fb582014-07-30 10:39:13 -04007498 if (!crt)
7499 return 0;
7500
7501 X509_free(crt);
7502 return 1;
7503}
7504
7505/* returns 1 if client passed a certificate for this connection, 0 if not */
7506int ssl_sock_get_cert_used_conn(struct connection *conn)
David Safb76832014-05-08 23:42:08 -04007507{
Christopher Faulet82004142019-09-10 10:12:03 +02007508 struct ssl_sock_ctx *ctx;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007509
David Safb76832014-05-08 23:42:08 -04007510 if (!ssl_sock_is_ssl(conn))
7511 return 0;
Christopher Faulet82004142019-09-10 10:12:03 +02007512 ctx = conn->xprt_ctx;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007513 return SSL_SOCK_ST_FL_VERIFY_DONE & ctx->xprt_st ? 1 : 0;
David Safb76832014-05-08 23:42:08 -04007514}
7515
7516/* returns result from SSL verify */
7517unsigned int ssl_sock_get_verify_result(struct connection *conn)
7518{
Christopher Faulet82004142019-09-10 10:12:03 +02007519 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007520
David Safb76832014-05-08 23:42:08 -04007521 if (!ssl_sock_is_ssl(conn))
7522 return (unsigned int)X509_V_ERR_APPLICATION_VERIFICATION;
Christopher Faulet82004142019-09-10 10:12:03 +02007523 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007524 return (unsigned int)SSL_get_verify_result(ctx->ssl);
David Safb76832014-05-08 23:42:08 -04007525}
7526
Willy Tarreau8743f7e2016-12-04 18:44:29 +01007527/* Returns the application layer protocol name in <str> and <len> when known.
7528 * Zero is returned if the protocol name was not found, otherwise non-zero is
7529 * returned. The string is allocated in the SSL context and doesn't have to be
7530 * freed by the caller. NPN is also checked if available since older versions
7531 * of openssl (1.0.1) which are more common in field only support this one.
7532 */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01007533static int ssl_sock_get_alpn(const struct connection *conn, void *xprt_ctx, const char **str, int *len)
Willy Tarreau8743f7e2016-12-04 18:44:29 +01007534{
Olivier Houchard66ab4982019-02-26 18:37:15 +01007535#if defined(TLSEXT_TYPE_application_layer_protocol_negotiation) || \
7536 defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Olivier Houcharde179d0e2019-03-21 18:27:17 +01007537 struct ssl_sock_ctx *ctx = xprt_ctx;
7538 if (!ctx)
Willy Tarreau8743f7e2016-12-04 18:44:29 +01007539 return 0;
7540
7541 *str = NULL;
7542
7543#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Olivier Houchard66ab4982019-02-26 18:37:15 +01007544 SSL_get0_alpn_selected(ctx->ssl, (const unsigned char **)str, (unsigned *)len);
Willy Tarreau8743f7e2016-12-04 18:44:29 +01007545 if (*str)
7546 return 1;
7547#endif
Bernard Spil13c53f82018-02-15 13:34:58 +01007548#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007549 SSL_get0_next_proto_negotiated(ctx->ssl, (const unsigned char **)str, (unsigned *)len);
Willy Tarreau8743f7e2016-12-04 18:44:29 +01007550 if (*str)
7551 return 1;
7552#endif
Olivier Houcharde179d0e2019-03-21 18:27:17 +01007553#endif
Willy Tarreau8743f7e2016-12-04 18:44:29 +01007554 return 0;
7555}
7556
Willy Tarreau7875d092012-09-10 08:20:03 +02007557/***** Below are some sample fetching functions for ACL/patterns *****/
7558
Olivier Houchardccaa7de2017-10-02 11:51:03 +02007559static int
7560smp_fetch_ssl_fc_has_early(const struct arg *args, struct sample *smp, const char *kw, void *private)
7561{
7562 struct connection *conn;
7563
7564 conn = objt_conn(smp->sess->origin);
7565 if (!conn || conn->xprt != &ssl_sock)
7566 return 0;
7567
7568 smp->flags = 0;
7569 smp->data.type = SMP_T_BOOL;
Emmanuel Hocdetc9858012019-08-07 14:44:49 +02007570#ifdef OPENSSL_IS_BORINGSSL
7571 {
7572 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
7573 smp->data.u.sint = (SSL_in_early_data(ctx->ssl) &&
7574 SSL_early_data_accepted(ctx->ssl));
7575 }
7576#else
Olivier Houchard25ae45a2017-11-29 19:51:19 +01007577 smp->data.u.sint = ((conn->flags & CO_FL_EARLY_DATA) &&
Olivier Houchard220a26c2020-01-23 14:57:36 +01007578 (conn->flags & (CO_FL_EARLY_SSL_HS | CO_FL_SSL_WAIT_HS))) ? 1 : 0;
Emmanuel Hocdetc9858012019-08-07 14:44:49 +02007579#endif
Olivier Houchardccaa7de2017-10-02 11:51:03 +02007580 return 1;
7581}
7582
Emeric Brune64aef12012-09-21 13:15:06 +02007583/* boolean, returns true if client cert was present */
7584static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007585smp_fetch_ssl_fc_has_crt(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brune64aef12012-09-21 13:15:06 +02007586{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007587 struct connection *conn;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007588 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007589
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007590 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007591 if (!conn || conn->xprt != &ssl_sock)
Emeric Brune64aef12012-09-21 13:15:06 +02007592 return 0;
7593
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007594 ctx = conn->xprt_ctx;
7595
Willy Tarreau911db9b2020-01-23 16:27:54 +01007596 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Brune64aef12012-09-21 13:15:06 +02007597 smp->flags |= SMP_F_MAY_CHANGE;
7598 return 0;
7599 }
7600
7601 smp->flags = 0;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007602 smp->data.type = SMP_T_BOOL;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007603 smp->data.u.sint = SSL_SOCK_ST_FL_VERIFY_DONE & ctx->xprt_st ? 1 : 0;
Emeric Brune64aef12012-09-21 13:15:06 +02007604
7605 return 1;
7606}
7607
Emeric Brun43e79582014-10-29 19:03:26 +01007608/* binary, returns a certificate in a binary chunk (der/raw).
7609 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7610 * should be use.
7611 */
7612static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007613smp_fetch_ssl_x_der(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun43e79582014-10-29 19:03:26 +01007614{
7615 int cert_peer = (kw[4] == 'c') ? 1 : 0;
7616 X509 *crt = NULL;
7617 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02007618 struct buffer *smp_trash;
Emeric Brun43e79582014-10-29 19:03:26 +01007619 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007620 struct ssl_sock_ctx *ctx;
Emeric Brun43e79582014-10-29 19:03:26 +01007621
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007622 conn = objt_conn(smp->sess->origin);
Emeric Brun43e79582014-10-29 19:03:26 +01007623 if (!conn || conn->xprt != &ssl_sock)
7624 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007625 ctx = conn->xprt_ctx;
Emeric Brun43e79582014-10-29 19:03:26 +01007626
Willy Tarreau911db9b2020-01-23 16:27:54 +01007627 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Brun43e79582014-10-29 19:03:26 +01007628 smp->flags |= SMP_F_MAY_CHANGE;
7629 return 0;
7630 }
7631
7632 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007633 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brun43e79582014-10-29 19:03:26 +01007634 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007635 crt = SSL_get_certificate(ctx->ssl);
Emeric Brun43e79582014-10-29 19:03:26 +01007636
7637 if (!crt)
7638 goto out;
7639
7640 smp_trash = get_trash_chunk();
7641 if (ssl_sock_crt2der(crt, smp_trash) <= 0)
7642 goto out;
7643
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007644 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007645 smp->data.type = SMP_T_BIN;
Emeric Brun43e79582014-10-29 19:03:26 +01007646 ret = 1;
7647out:
7648 /* SSL_get_peer_certificate, it increase X509 * ref count */
7649 if (cert_peer && crt)
7650 X509_free(crt);
7651 return ret;
7652}
7653
Emeric Brunba841a12014-04-30 17:05:08 +02007654/* binary, returns serial of certificate in a binary chunk.
7655 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7656 * should be use.
7657 */
Willy Tarreau8d598402012-10-22 17:58:39 +02007658static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007659smp_fetch_ssl_x_serial(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau8d598402012-10-22 17:58:39 +02007660{
Emeric Brunba841a12014-04-30 17:05:08 +02007661 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Willy Tarreau8d598402012-10-22 17:58:39 +02007662 X509 *crt = NULL;
7663 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02007664 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007665 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007666 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007667
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007668 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007669 if (!conn || conn->xprt != &ssl_sock)
Willy Tarreau8d598402012-10-22 17:58:39 +02007670 return 0;
7671
Olivier Houchard66ab4982019-02-26 18:37:15 +01007672 ctx = conn->xprt_ctx;
7673
Willy Tarreau911db9b2020-01-23 16:27:54 +01007674 if (conn->flags & CO_FL_WAIT_XPRT) {
Willy Tarreau8d598402012-10-22 17:58:39 +02007675 smp->flags |= SMP_F_MAY_CHANGE;
7676 return 0;
7677 }
7678
Emeric Brunba841a12014-04-30 17:05:08 +02007679 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007680 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007681 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007682 crt = SSL_get_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007683
Willy Tarreau8d598402012-10-22 17:58:39 +02007684 if (!crt)
7685 goto out;
7686
Willy Tarreau47ca5452012-12-23 20:22:19 +01007687 smp_trash = get_trash_chunk();
Willy Tarreau8d598402012-10-22 17:58:39 +02007688 if (ssl_sock_get_serial(crt, smp_trash) <= 0)
7689 goto out;
7690
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007691 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007692 smp->data.type = SMP_T_BIN;
Willy Tarreau8d598402012-10-22 17:58:39 +02007693 ret = 1;
7694out:
Emeric Brunba841a12014-04-30 17:05:08 +02007695 /* SSL_get_peer_certificate, it increase X509 * ref count */
7696 if (cert_peer && crt)
Willy Tarreau8d598402012-10-22 17:58:39 +02007697 X509_free(crt);
7698 return ret;
7699}
Emeric Brune64aef12012-09-21 13:15:06 +02007700
Emeric Brunba841a12014-04-30 17:05:08 +02007701/* binary, returns the client certificate's SHA-1 fingerprint (SHA-1 hash of DER-encoded certificate) in a binary chunk.
7702 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7703 * should be use.
7704 */
James Votha051b4a2013-05-14 20:37:59 +02007705static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007706smp_fetch_ssl_x_sha1(const struct arg *args, struct sample *smp, const char *kw, void *private)
James Votha051b4a2013-05-14 20:37:59 +02007707{
Emeric Brunba841a12014-04-30 17:05:08 +02007708 int cert_peer = (kw[4] == 'c') ? 1 : 0;
James Votha051b4a2013-05-14 20:37:59 +02007709 X509 *crt = NULL;
7710 const EVP_MD *digest;
7711 int ret = 0;
Willy Tarreau105599c2020-02-25 08:59:23 +01007712 unsigned int len = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02007713 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007714 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007715 struct ssl_sock_ctx *ctx;
James Votha051b4a2013-05-14 20:37:59 +02007716
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007717 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007718 if (!conn || conn->xprt != &ssl_sock)
7719 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007720 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007721
Willy Tarreau911db9b2020-01-23 16:27:54 +01007722 if (conn->flags & CO_FL_WAIT_XPRT) {
James Votha051b4a2013-05-14 20:37:59 +02007723 smp->flags |= SMP_F_MAY_CHANGE;
7724 return 0;
7725 }
7726
Emeric Brunba841a12014-04-30 17:05:08 +02007727 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007728 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007729 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007730 crt = SSL_get_certificate(ctx->ssl);
James Votha051b4a2013-05-14 20:37:59 +02007731 if (!crt)
7732 goto out;
7733
7734 smp_trash = get_trash_chunk();
7735 digest = EVP_sha1();
Willy Tarreau105599c2020-02-25 08:59:23 +01007736 X509_digest(crt, digest, (unsigned char *) smp_trash->area, &len);
7737 smp_trash->data = len;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007738 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007739 smp->data.type = SMP_T_BIN;
James Votha051b4a2013-05-14 20:37:59 +02007740 ret = 1;
7741out:
Emeric Brunba841a12014-04-30 17:05:08 +02007742 /* SSL_get_peer_certificate, it increase X509 * ref count */
7743 if (cert_peer && crt)
James Votha051b4a2013-05-14 20:37:59 +02007744 X509_free(crt);
7745 return ret;
7746}
7747
Emeric Brunba841a12014-04-30 17:05:08 +02007748/* string, returns certificate's notafter date in ASN1_UTCTIME format.
7749 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7750 * should be use.
7751 */
Emeric Brunce5ad802012-10-22 14:11:22 +02007752static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007753smp_fetch_ssl_x_notafter(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunce5ad802012-10-22 14:11:22 +02007754{
Emeric Brunba841a12014-04-30 17:05:08 +02007755 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brunce5ad802012-10-22 14:11:22 +02007756 X509 *crt = NULL;
7757 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02007758 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007759 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007760 struct ssl_sock_ctx *ctx;
Emeric Brunce5ad802012-10-22 14:11:22 +02007761
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007762 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007763 if (!conn || conn->xprt != &ssl_sock)
7764 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007765 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007766
Willy Tarreau911db9b2020-01-23 16:27:54 +01007767 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Brunce5ad802012-10-22 14:11:22 +02007768 smp->flags |= SMP_F_MAY_CHANGE;
7769 return 0;
7770 }
7771
Emeric Brunba841a12014-04-30 17:05:08 +02007772 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007773 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007774 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007775 crt = SSL_get_certificate(ctx->ssl);
Emeric Brunce5ad802012-10-22 14:11:22 +02007776 if (!crt)
7777 goto out;
7778
Willy Tarreau47ca5452012-12-23 20:22:19 +01007779 smp_trash = get_trash_chunk();
Rosen Penev68185952018-12-14 08:47:02 -08007780 if (ssl_sock_get_time(X509_getm_notAfter(crt), smp_trash) <= 0)
Emeric Brunce5ad802012-10-22 14:11:22 +02007781 goto out;
7782
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007783 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007784 smp->data.type = SMP_T_STR;
Emeric Brunce5ad802012-10-22 14:11:22 +02007785 ret = 1;
7786out:
Emeric Brunba841a12014-04-30 17:05:08 +02007787 /* SSL_get_peer_certificate, it increase X509 * ref count */
7788 if (cert_peer && crt)
Emeric Brunce5ad802012-10-22 14:11:22 +02007789 X509_free(crt);
7790 return ret;
7791}
7792
Emeric Brunba841a12014-04-30 17:05:08 +02007793/* string, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. of certificate's issuer
7794 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7795 * should be use.
7796 */
Emeric Brun87855892012-10-17 17:39:35 +02007797static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007798smp_fetch_ssl_x_i_dn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun87855892012-10-17 17:39:35 +02007799{
Emeric Brunba841a12014-04-30 17:05:08 +02007800 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun87855892012-10-17 17:39:35 +02007801 X509 *crt = NULL;
7802 X509_NAME *name;
7803 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02007804 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007805 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007806 struct ssl_sock_ctx *ctx;
Emeric Brun87855892012-10-17 17:39:35 +02007807
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007808 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007809 if (!conn || conn->xprt != &ssl_sock)
7810 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007811 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007812
Willy Tarreau911db9b2020-01-23 16:27:54 +01007813 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Brun87855892012-10-17 17:39:35 +02007814 smp->flags |= SMP_F_MAY_CHANGE;
7815 return 0;
7816 }
7817
Emeric Brunba841a12014-04-30 17:05:08 +02007818 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007819 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007820 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007821 crt = SSL_get_certificate(ctx->ssl);
Emeric Brun87855892012-10-17 17:39:35 +02007822 if (!crt)
7823 goto out;
7824
7825 name = X509_get_issuer_name(crt);
7826 if (!name)
7827 goto out;
7828
Willy Tarreau47ca5452012-12-23 20:22:19 +01007829 smp_trash = get_trash_chunk();
Elliot Otchet71f82972020-01-15 08:12:14 -05007830 if (args && args[0].type == ARGT_STR && args[0].data.str.data > 0) {
Emeric Brun87855892012-10-17 17:39:35 +02007831 int pos = 1;
7832
7833 if (args[1].type == ARGT_SINT)
7834 pos = args[1].data.sint;
Emeric Brun87855892012-10-17 17:39:35 +02007835
7836 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
7837 goto out;
7838 }
Elliot Otchet71f82972020-01-15 08:12:14 -05007839 else if (args && args[2].type == ARGT_STR && args[2].data.str.data > 0) {
7840 if (ssl_sock_get_dn_formatted(name, &args[2].data.str, smp_trash) <= 0)
7841 goto out;
7842 }
Emeric Brun87855892012-10-17 17:39:35 +02007843 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
7844 goto out;
7845
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007846 smp->data.type = SMP_T_STR;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007847 smp->data.u.str = *smp_trash;
Emeric Brun87855892012-10-17 17:39:35 +02007848 ret = 1;
7849out:
Emeric Brunba841a12014-04-30 17:05:08 +02007850 /* SSL_get_peer_certificate, it increase X509 * ref count */
7851 if (cert_peer && crt)
Emeric Brun87855892012-10-17 17:39:35 +02007852 X509_free(crt);
7853 return ret;
7854}
7855
Emeric Brunba841a12014-04-30 17:05:08 +02007856/* string, returns notbefore date in ASN1_UTCTIME format.
7857 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7858 * should be use.
7859 */
Emeric Brunce5ad802012-10-22 14:11:22 +02007860static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007861smp_fetch_ssl_x_notbefore(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunce5ad802012-10-22 14:11:22 +02007862{
Emeric Brunba841a12014-04-30 17:05:08 +02007863 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brunce5ad802012-10-22 14:11:22 +02007864 X509 *crt = NULL;
7865 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02007866 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007867 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007868 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007869
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007870 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007871 if (!conn || conn->xprt != &ssl_sock)
Emeric Brunce5ad802012-10-22 14:11:22 +02007872 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007873 ctx = conn->xprt_ctx;
Emeric Brunce5ad802012-10-22 14:11:22 +02007874
Willy Tarreau911db9b2020-01-23 16:27:54 +01007875 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Brunce5ad802012-10-22 14:11:22 +02007876 smp->flags |= SMP_F_MAY_CHANGE;
7877 return 0;
7878 }
7879
Emeric Brunba841a12014-04-30 17:05:08 +02007880 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007881 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007882 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007883 crt = SSL_get_certificate(ctx->ssl);
Emeric Brunce5ad802012-10-22 14:11:22 +02007884 if (!crt)
7885 goto out;
7886
Willy Tarreau47ca5452012-12-23 20:22:19 +01007887 smp_trash = get_trash_chunk();
Rosen Penev68185952018-12-14 08:47:02 -08007888 if (ssl_sock_get_time(X509_getm_notBefore(crt), smp_trash) <= 0)
Emeric Brunce5ad802012-10-22 14:11:22 +02007889 goto out;
7890
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007891 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007892 smp->data.type = SMP_T_STR;
Emeric Brunce5ad802012-10-22 14:11:22 +02007893 ret = 1;
7894out:
Emeric Brunba841a12014-04-30 17:05:08 +02007895 /* SSL_get_peer_certificate, it increase X509 * ref count */
7896 if (cert_peer && crt)
Emeric Brunce5ad802012-10-22 14:11:22 +02007897 X509_free(crt);
7898 return ret;
7899}
7900
Emeric Brunba841a12014-04-30 17:05:08 +02007901/* string, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. of certificate's subject
7902 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7903 * should be use.
7904 */
Emeric Brun87855892012-10-17 17:39:35 +02007905static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007906smp_fetch_ssl_x_s_dn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun87855892012-10-17 17:39:35 +02007907{
Emeric Brunba841a12014-04-30 17:05:08 +02007908 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun87855892012-10-17 17:39:35 +02007909 X509 *crt = NULL;
7910 X509_NAME *name;
7911 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02007912 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007913 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007914 struct ssl_sock_ctx *ctx;
Emeric Brun87855892012-10-17 17:39:35 +02007915
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007916 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007917 if (!conn || conn->xprt != &ssl_sock)
7918 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007919 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007920
Willy Tarreau911db9b2020-01-23 16:27:54 +01007921 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Brun87855892012-10-17 17:39:35 +02007922 smp->flags |= SMP_F_MAY_CHANGE;
7923 return 0;
7924 }
7925
Emeric Brunba841a12014-04-30 17:05:08 +02007926 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007927 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007928 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007929 crt = SSL_get_certificate(ctx->ssl);
Emeric Brun87855892012-10-17 17:39:35 +02007930 if (!crt)
7931 goto out;
7932
7933 name = X509_get_subject_name(crt);
7934 if (!name)
7935 goto out;
7936
Willy Tarreau47ca5452012-12-23 20:22:19 +01007937 smp_trash = get_trash_chunk();
Elliot Otchet71f82972020-01-15 08:12:14 -05007938 if (args && args[0].type == ARGT_STR && args[0].data.str.data > 0) {
Emeric Brun87855892012-10-17 17:39:35 +02007939 int pos = 1;
7940
7941 if (args[1].type == ARGT_SINT)
7942 pos = args[1].data.sint;
Emeric Brun87855892012-10-17 17:39:35 +02007943
7944 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
7945 goto out;
7946 }
Elliot Otchet71f82972020-01-15 08:12:14 -05007947 else if (args && args[2].type == ARGT_STR && args[2].data.str.data > 0) {
7948 if (ssl_sock_get_dn_formatted(name, &args[2].data.str, smp_trash) <= 0)
7949 goto out;
7950 }
Emeric Brun87855892012-10-17 17:39:35 +02007951 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
7952 goto out;
7953
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007954 smp->data.type = SMP_T_STR;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007955 smp->data.u.str = *smp_trash;
Emeric Brun87855892012-10-17 17:39:35 +02007956 ret = 1;
7957out:
Emeric Brunba841a12014-04-30 17:05:08 +02007958 /* SSL_get_peer_certificate, it increase X509 * ref count */
7959 if (cert_peer && crt)
Emeric Brun87855892012-10-17 17:39:35 +02007960 X509_free(crt);
7961 return ret;
7962}
Emeric Brun9143d372012-12-20 15:44:16 +01007963
7964/* integer, returns true if current session use a client certificate */
7965static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007966smp_fetch_ssl_c_used(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun9143d372012-12-20 15:44:16 +01007967{
7968 X509 *crt;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007969 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007970 struct ssl_sock_ctx *ctx;
Emeric Brun9143d372012-12-20 15:44:16 +01007971
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007972 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007973 if (!conn || conn->xprt != &ssl_sock)
7974 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007975 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007976
Willy Tarreau911db9b2020-01-23 16:27:54 +01007977 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Brun9143d372012-12-20 15:44:16 +01007978 smp->flags |= SMP_F_MAY_CHANGE;
7979 return 0;
7980 }
7981
7982 /* SSL_get_peer_certificate returns a ptr on allocated X509 struct */
Olivier Houchard66ab4982019-02-26 18:37:15 +01007983 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brun9143d372012-12-20 15:44:16 +01007984 if (crt) {
7985 X509_free(crt);
7986 }
7987
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007988 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007989 smp->data.u.sint = (crt != NULL);
Emeric Brun9143d372012-12-20 15:44:16 +01007990 return 1;
7991}
7992
Emeric Brunba841a12014-04-30 17:05:08 +02007993/* integer, returns the certificate version
7994 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7995 * should be use.
7996 */
Emeric Bruna7359fd2012-10-17 15:03:11 +02007997static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007998smp_fetch_ssl_x_version(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Bruna7359fd2012-10-17 15:03:11 +02007999{
Emeric Brunba841a12014-04-30 17:05:08 +02008000 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Bruna7359fd2012-10-17 15:03:11 +02008001 X509 *crt;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008002 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008003 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008004
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02008005 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008006 if (!conn || conn->xprt != &ssl_sock)
Emeric Bruna7359fd2012-10-17 15:03:11 +02008007 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008008 ctx = conn->xprt_ctx;
Emeric Bruna7359fd2012-10-17 15:03:11 +02008009
Willy Tarreau911db9b2020-01-23 16:27:54 +01008010 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Bruna7359fd2012-10-17 15:03:11 +02008011 smp->flags |= SMP_F_MAY_CHANGE;
8012 return 0;
8013 }
8014
Emeric Brunba841a12014-04-30 17:05:08 +02008015 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01008016 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02008017 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01008018 crt = SSL_get_certificate(ctx->ssl);
Emeric Bruna7359fd2012-10-17 15:03:11 +02008019 if (!crt)
8020 return 0;
8021
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02008022 smp->data.u.sint = (unsigned int)(1 + X509_get_version(crt));
Emeric Brunba841a12014-04-30 17:05:08 +02008023 /* SSL_get_peer_certificate increase X509 * ref count */
8024 if (cert_peer)
8025 X509_free(crt);
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008026 smp->data.type = SMP_T_SINT;
Emeric Bruna7359fd2012-10-17 15:03:11 +02008027
8028 return 1;
8029}
8030
Emeric Brunba841a12014-04-30 17:05:08 +02008031/* string, returns the certificate's signature algorithm.
8032 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
8033 * should be use.
8034 */
Emeric Brun7f56e742012-10-19 18:15:40 +02008035static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008036smp_fetch_ssl_x_sig_alg(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun7f56e742012-10-19 18:15:40 +02008037{
Emeric Brunba841a12014-04-30 17:05:08 +02008038 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun7f56e742012-10-19 18:15:40 +02008039 X509 *crt;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02008040 __OPENSSL_110_CONST__ ASN1_OBJECT *algorithm;
Emeric Brun7f56e742012-10-19 18:15:40 +02008041 int nid;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008042 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008043 struct ssl_sock_ctx *ctx;
Emeric Brun7f56e742012-10-19 18:15:40 +02008044
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02008045 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008046 if (!conn || conn->xprt != &ssl_sock)
8047 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008048 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008049
Willy Tarreau911db9b2020-01-23 16:27:54 +01008050 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Brun7f56e742012-10-19 18:15:40 +02008051 smp->flags |= SMP_F_MAY_CHANGE;
8052 return 0;
8053 }
8054
Emeric Brunba841a12014-04-30 17:05:08 +02008055 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01008056 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02008057 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01008058 crt = SSL_get_certificate(ctx->ssl);
Emeric Brun7f56e742012-10-19 18:15:40 +02008059 if (!crt)
8060 return 0;
8061
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02008062 X509_ALGOR_get0(&algorithm, NULL, NULL, X509_get0_tbs_sigalg(crt));
8063 nid = OBJ_obj2nid(algorithm);
Emeric Brun7f56e742012-10-19 18:15:40 +02008064
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008065 smp->data.u.str.area = (char *)OBJ_nid2sn(nid);
8066 if (!smp->data.u.str.area) {
Emeric Brunba841a12014-04-30 17:05:08 +02008067 /* SSL_get_peer_certificate increase X509 * ref count */
8068 if (cert_peer)
8069 X509_free(crt);
Emeric Brun7f56e742012-10-19 18:15:40 +02008070 return 0;
Emeric Brun9bf3ba22013-10-07 14:31:44 +02008071 }
Emeric Brun7f56e742012-10-19 18:15:40 +02008072
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008073 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008074 smp->flags |= SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008075 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brunba841a12014-04-30 17:05:08 +02008076 /* SSL_get_peer_certificate increase X509 * ref count */
8077 if (cert_peer)
8078 X509_free(crt);
Emeric Brun7f56e742012-10-19 18:15:40 +02008079
8080 return 1;
8081}
8082
Emeric Brunba841a12014-04-30 17:05:08 +02008083/* string, returns the certificate's key algorithm.
8084 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
8085 * should be use.
8086 */
Emeric Brun521a0112012-10-22 12:22:55 +02008087static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008088smp_fetch_ssl_x_key_alg(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun521a0112012-10-22 12:22:55 +02008089{
Emeric Brunba841a12014-04-30 17:05:08 +02008090 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun521a0112012-10-22 12:22:55 +02008091 X509 *crt;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02008092 ASN1_OBJECT *algorithm;
Emeric Brun521a0112012-10-22 12:22:55 +02008093 int nid;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008094 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008095 struct ssl_sock_ctx *ctx;
Emeric Brun521a0112012-10-22 12:22:55 +02008096
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02008097 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008098 if (!conn || conn->xprt != &ssl_sock)
8099 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008100 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008101
Willy Tarreau911db9b2020-01-23 16:27:54 +01008102 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Brun521a0112012-10-22 12:22:55 +02008103 smp->flags |= SMP_F_MAY_CHANGE;
8104 return 0;
8105 }
8106
Emeric Brunba841a12014-04-30 17:05:08 +02008107 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01008108 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02008109 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01008110 crt = SSL_get_certificate(ctx->ssl);
Emeric Brun521a0112012-10-22 12:22:55 +02008111 if (!crt)
8112 return 0;
8113
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02008114 X509_PUBKEY_get0_param(&algorithm, NULL, NULL, NULL, X509_get_X509_PUBKEY(crt));
8115 nid = OBJ_obj2nid(algorithm);
Emeric Brun521a0112012-10-22 12:22:55 +02008116
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008117 smp->data.u.str.area = (char *)OBJ_nid2sn(nid);
8118 if (!smp->data.u.str.area) {
Emeric Brunba841a12014-04-30 17:05:08 +02008119 /* SSL_get_peer_certificate increase X509 * ref count */
8120 if (cert_peer)
8121 X509_free(crt);
Emeric Brun521a0112012-10-22 12:22:55 +02008122 return 0;
Emeric Brun9bf3ba22013-10-07 14:31:44 +02008123 }
Emeric Brun521a0112012-10-22 12:22:55 +02008124
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008125 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008126 smp->flags |= SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008127 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brunba841a12014-04-30 17:05:08 +02008128 if (cert_peer)
8129 X509_free(crt);
Emeric Brun521a0112012-10-22 12:22:55 +02008130
8131 return 1;
8132}
8133
Emeric Brun645ae792014-04-30 14:21:06 +02008134/* boolean, returns true if front conn. transport layer is SSL.
8135 * This function is also usable on backend conn if the fetch keyword 5th
8136 * char is 'b'.
8137 */
Willy Tarreau7875d092012-09-10 08:20:03 +02008138static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008139smp_fetch_ssl_fc(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02008140{
Emeric Bruneb8def92018-02-19 15:59:48 +01008141 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
8142 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008143
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008144 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02008145 smp->data.u.sint = (conn && conn->xprt == &ssl_sock);
Willy Tarreau7875d092012-09-10 08:20:03 +02008146 return 1;
8147}
8148
Emeric Brun2525b6b2012-10-18 15:59:43 +02008149/* boolean, returns true if client present a SNI */
Willy Tarreau7875d092012-09-10 08:20:03 +02008150static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008151smp_fetch_ssl_fc_has_sni(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02008152{
8153#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02008154 struct connection *conn = objt_conn(smp->sess->origin);
Olivier Houchard66ab4982019-02-26 18:37:15 +01008155 struct ssl_sock_ctx *ctx = conn ? conn->xprt_ctx : NULL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008156
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008157 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02008158 smp->data.u.sint = (conn && conn->xprt == &ssl_sock) &&
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008159 conn->xprt_ctx &&
Olivier Houchard66ab4982019-02-26 18:37:15 +01008160 SSL_get_servername(ctx->ssl, TLSEXT_NAMETYPE_host_name) != NULL;
Willy Tarreau7875d092012-09-10 08:20:03 +02008161 return 1;
8162#else
8163 return 0;
8164#endif
8165}
8166
Emeric Brun74f7ffa2018-02-19 16:14:12 +01008167/* boolean, returns true if client session has been resumed.
8168 * This function is also usable on backend conn if the fetch keyword 5th
8169 * char is 'b'.
8170 */
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02008171static int
8172smp_fetch_ssl_fc_is_resumed(const struct arg *args, struct sample *smp, const char *kw, void *private)
8173{
Emeric Brun74f7ffa2018-02-19 16:14:12 +01008174 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
8175 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008176 struct ssl_sock_ctx *ctx = conn ? conn->xprt_ctx : NULL;
Emeric Brun74f7ffa2018-02-19 16:14:12 +01008177
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02008178
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008179 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02008180 smp->data.u.sint = (conn && conn->xprt == &ssl_sock) &&
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02008181 conn->xprt_ctx &&
Olivier Houchard66ab4982019-02-26 18:37:15 +01008182 SSL_session_reused(ctx->ssl);
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02008183 return 1;
8184}
8185
Emeric Brun645ae792014-04-30 14:21:06 +02008186/* string, returns the used cipher if front conn. transport layer is SSL.
8187 * This function is also usable on backend conn if the fetch keyword 5th
8188 * char is 'b'.
8189 */
Emeric Brun589fcad2012-10-16 14:13:26 +02008190static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008191smp_fetch_ssl_fc_cipher(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02008192{
Emeric Bruneb8def92018-02-19 15:59:48 +01008193 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
8194 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008195 struct ssl_sock_ctx *ctx;
Emeric Brun589fcad2012-10-16 14:13:26 +02008196
Willy Tarreaube508f12016-03-10 11:47:01 +01008197 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008198 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02008199 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008200 ctx = conn->xprt_ctx;
Emeric Brun589fcad2012-10-16 14:13:26 +02008201
Olivier Houchard66ab4982019-02-26 18:37:15 +01008202 smp->data.u.str.area = (char *)SSL_get_cipher_name(ctx->ssl);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008203 if (!smp->data.u.str.area)
Emeric Brun589fcad2012-10-16 14:13:26 +02008204 return 0;
8205
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008206 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008207 smp->flags |= SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008208 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brun589fcad2012-10-16 14:13:26 +02008209
8210 return 1;
8211}
8212
Emeric Brun645ae792014-04-30 14:21:06 +02008213/* integer, returns the algoritm's keysize if front conn. transport layer
8214 * is SSL.
8215 * This function is also usable on backend conn if the fetch keyword 5th
8216 * char is 'b'.
8217 */
Emeric Brun589fcad2012-10-16 14:13:26 +02008218static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008219smp_fetch_ssl_fc_alg_keysize(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02008220{
Emeric Bruneb8def92018-02-19 15:59:48 +01008221 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
8222 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008223 struct ssl_sock_ctx *ctx;
Willy Tarreaue237fe12016-03-10 17:05:28 +01008224 int sint;
Willy Tarreaube508f12016-03-10 11:47:01 +01008225
Emeric Brun589fcad2012-10-16 14:13:26 +02008226 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008227 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02008228 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008229 ctx = conn->xprt_ctx;
Emeric Brun589fcad2012-10-16 14:13:26 +02008230
Olivier Houchard66ab4982019-02-26 18:37:15 +01008231 if (!SSL_get_cipher_bits(ctx->ssl, &sint))
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008232 return 0;
8233
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02008234 smp->data.u.sint = sint;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008235 smp->data.type = SMP_T_SINT;
Emeric Brun589fcad2012-10-16 14:13:26 +02008236
8237 return 1;
8238}
8239
Emeric Brun645ae792014-04-30 14:21:06 +02008240/* integer, returns the used keysize if front conn. transport layer is SSL.
8241 * This function is also usable on backend conn if the fetch keyword 5th
8242 * char is 'b'.
8243 */
Emeric Brun589fcad2012-10-16 14:13:26 +02008244static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008245smp_fetch_ssl_fc_use_keysize(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02008246{
Emeric Bruneb8def92018-02-19 15:59:48 +01008247 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
8248 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008249 struct ssl_sock_ctx *ctx;
Willy Tarreaube508f12016-03-10 11:47:01 +01008250
Emeric Brun589fcad2012-10-16 14:13:26 +02008251 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008252 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8253 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008254 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008255
Olivier Houchard66ab4982019-02-26 18:37:15 +01008256 smp->data.u.sint = (unsigned int)SSL_get_cipher_bits(ctx->ssl, NULL);
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02008257 if (!smp->data.u.sint)
Emeric Brun589fcad2012-10-16 14:13:26 +02008258 return 0;
8259
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008260 smp->data.type = SMP_T_SINT;
Emeric Brun589fcad2012-10-16 14:13:26 +02008261
8262 return 1;
8263}
8264
Bernard Spil13c53f82018-02-15 13:34:58 +01008265#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Willy Tarreau7875d092012-09-10 08:20:03 +02008266static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008267smp_fetch_ssl_fc_npn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreaua33c6542012-10-15 13:19:06 +02008268{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008269 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008270 struct ssl_sock_ctx *ctx;
Willy Tarreau105599c2020-02-25 08:59:23 +01008271 unsigned int len = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008272
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008273 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008274 smp->data.type = SMP_T_STR;
Willy Tarreaua33c6542012-10-15 13:19:06 +02008275
Olivier Houchard6b77f492018-11-22 18:18:29 +01008276 conn = (kw[4] != 'b' ) ? objt_conn(smp->sess->origin) :
8277 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008278 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8279 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008280 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008281
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008282 smp->data.u.str.area = NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008283 SSL_get0_next_proto_negotiated(ctx->ssl,
Willy Tarreau105599c2020-02-25 08:59:23 +01008284 (const unsigned char **)&smp->data.u.str.area,
8285 &len);
Willy Tarreaua33c6542012-10-15 13:19:06 +02008286
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008287 if (!smp->data.u.str.area)
Willy Tarreaua33c6542012-10-15 13:19:06 +02008288 return 0;
8289
Willy Tarreau105599c2020-02-25 08:59:23 +01008290 smp->data.u.str.data = len;
Willy Tarreaua33c6542012-10-15 13:19:06 +02008291 return 1;
Willy Tarreaua33c6542012-10-15 13:19:06 +02008292}
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02008293#endif
Willy Tarreaua33c6542012-10-15 13:19:06 +02008294
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01008295#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02008296static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008297smp_fetch_ssl_fc_alpn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreauab861d32013-04-02 02:30:41 +02008298{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008299 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008300 struct ssl_sock_ctx *ctx;
Willy Tarreau105599c2020-02-25 08:59:23 +01008301 unsigned int len = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008302
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008303 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008304 smp->data.type = SMP_T_STR;
Willy Tarreauab861d32013-04-02 02:30:41 +02008305
Olivier Houchard6b77f492018-11-22 18:18:29 +01008306 conn = (kw[4] != 'b' ) ? objt_conn(smp->sess->origin) :
8307 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
8308
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008309 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Willy Tarreauab861d32013-04-02 02:30:41 +02008310 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008311 ctx = conn->xprt_ctx;
Willy Tarreauab861d32013-04-02 02:30:41 +02008312
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008313 smp->data.u.str.area = NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008314 SSL_get0_alpn_selected(ctx->ssl,
Willy Tarreau105599c2020-02-25 08:59:23 +01008315 (const unsigned char **)&smp->data.u.str.area,
8316 &len);
Willy Tarreauab861d32013-04-02 02:30:41 +02008317
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008318 if (!smp->data.u.str.area)
Willy Tarreauab861d32013-04-02 02:30:41 +02008319 return 0;
8320
Willy Tarreau105599c2020-02-25 08:59:23 +01008321 smp->data.u.str.data = len;
Willy Tarreauab861d32013-04-02 02:30:41 +02008322 return 1;
8323}
8324#endif
8325
Emeric Brun645ae792014-04-30 14:21:06 +02008326/* string, returns the used protocol if front conn. transport layer is SSL.
8327 * This function is also usable on backend conn if the fetch keyword 5th
8328 * char is 'b'.
8329 */
Willy Tarreaua33c6542012-10-15 13:19:06 +02008330static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008331smp_fetch_ssl_fc_protocol(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02008332{
Emeric Bruneb8def92018-02-19 15:59:48 +01008333 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
8334 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008335 struct ssl_sock_ctx *ctx;
Willy Tarreaube508f12016-03-10 11:47:01 +01008336
Emeric Brun589fcad2012-10-16 14:13:26 +02008337 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008338 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8339 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008340 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008341
Olivier Houchard66ab4982019-02-26 18:37:15 +01008342 smp->data.u.str.area = (char *)SSL_get_version(ctx->ssl);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008343 if (!smp->data.u.str.area)
Emeric Brun589fcad2012-10-16 14:13:26 +02008344 return 0;
8345
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008346 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008347 smp->flags = SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008348 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brun589fcad2012-10-16 14:13:26 +02008349
8350 return 1;
8351}
8352
Willy Tarreau87b09662015-04-03 00:22:06 +02008353/* binary, returns the SSL stream id if front conn. transport layer is SSL.
Emeric Brun645ae792014-04-30 14:21:06 +02008354 * This function is also usable on backend conn if the fetch keyword 5th
8355 * char is 'b'.
8356 */
Willy Tarreau9a1ab082019-05-09 13:26:41 +02008357#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
Emeric Brun589fcad2012-10-16 14:13:26 +02008358static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008359smp_fetch_ssl_fc_session_id(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunfe68f682012-10-16 14:59:28 +02008360{
Emeric Bruneb8def92018-02-19 15:59:48 +01008361 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
8362 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaue237fe12016-03-10 17:05:28 +01008363 SSL_SESSION *ssl_sess;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008364 struct ssl_sock_ctx *ctx;
Willy Tarreau105599c2020-02-25 08:59:23 +01008365 unsigned int len = 0;
Willy Tarreaube508f12016-03-10 11:47:01 +01008366
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008367 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008368 smp->data.type = SMP_T_BIN;
Emeric Brunfe68f682012-10-16 14:59:28 +02008369
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008370 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8371 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008372 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008373
Olivier Houchard66ab4982019-02-26 18:37:15 +01008374 ssl_sess = SSL_get_session(ctx->ssl);
Willy Tarreau192252e2015-04-04 01:47:55 +02008375 if (!ssl_sess)
Emeric Brunfe68f682012-10-16 14:59:28 +02008376 return 0;
8377
Willy Tarreau105599c2020-02-25 08:59:23 +01008378 smp->data.u.str.area = (char *)SSL_SESSION_get_id(ssl_sess, &len);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008379 if (!smp->data.u.str.area || !smp->data.u.str.data)
Emeric Brunfe68f682012-10-16 14:59:28 +02008380 return 0;
8381
Willy Tarreau105599c2020-02-25 08:59:23 +01008382 smp->data.u.str.data = len;
Emeric Brunfe68f682012-10-16 14:59:28 +02008383 return 1;
Emeric Brunfe68f682012-10-16 14:59:28 +02008384}
Patrick Hemmer41966772018-04-28 19:15:48 -04008385#endif
8386
Emeric Brunfe68f682012-10-16 14:59:28 +02008387
Emmanuel Hocdet839af572019-05-14 16:27:35 +02008388#if HA_OPENSSL_VERSION_NUMBER >= 0x10100000L
Patrick Hemmere0275472018-04-28 19:15:51 -04008389static int
Patrick Hemmer65674662019-06-04 08:13:03 -04008390smp_fetch_ssl_fc_random(const struct arg *args, struct sample *smp, const char *kw, void *private)
8391{
8392 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
8393 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
8394 struct buffer *data;
8395 struct ssl_sock_ctx *ctx;
8396
8397 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8398 return 0;
8399 ctx = conn->xprt_ctx;
8400
8401 data = get_trash_chunk();
8402 if (kw[7] == 'c')
8403 data->data = SSL_get_client_random(ctx->ssl,
8404 (unsigned char *) data->area,
8405 data->size);
8406 else
8407 data->data = SSL_get_server_random(ctx->ssl,
8408 (unsigned char *) data->area,
8409 data->size);
8410 if (!data->data)
8411 return 0;
8412
8413 smp->flags = 0;
8414 smp->data.type = SMP_T_BIN;
8415 smp->data.u.str = *data;
8416
8417 return 1;
8418}
8419
8420static int
Patrick Hemmere0275472018-04-28 19:15:51 -04008421smp_fetch_ssl_fc_session_key(const struct arg *args, struct sample *smp, const char *kw, void *private)
8422{
8423 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
8424 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
8425 SSL_SESSION *ssl_sess;
Willy Tarreau83061a82018-07-13 11:56:34 +02008426 struct buffer *data;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008427 struct ssl_sock_ctx *ctx;
Patrick Hemmere0275472018-04-28 19:15:51 -04008428
8429 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8430 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008431 ctx = conn->xprt_ctx;
Patrick Hemmere0275472018-04-28 19:15:51 -04008432
Olivier Houchard66ab4982019-02-26 18:37:15 +01008433 ssl_sess = SSL_get_session(ctx->ssl);
Patrick Hemmere0275472018-04-28 19:15:51 -04008434 if (!ssl_sess)
8435 return 0;
8436
8437 data = get_trash_chunk();
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008438 data->data = SSL_SESSION_get_master_key(ssl_sess,
8439 (unsigned char *) data->area,
8440 data->size);
8441 if (!data->data)
Patrick Hemmere0275472018-04-28 19:15:51 -04008442 return 0;
8443
8444 smp->flags = 0;
8445 smp->data.type = SMP_T_BIN;
8446 smp->data.u.str = *data;
8447
8448 return 1;
8449}
8450#endif
8451
Patrick Hemmer41966772018-04-28 19:15:48 -04008452#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emeric Brunfe68f682012-10-16 14:59:28 +02008453static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008454smp_fetch_ssl_fc_sni(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02008455{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008456 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008457 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008458
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008459 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008460 smp->data.type = SMP_T_STR;
Willy Tarreau7875d092012-09-10 08:20:03 +02008461
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02008462 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008463 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8464 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008465 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008466
Olivier Houchard66ab4982019-02-26 18:37:15 +01008467 smp->data.u.str.area = (char *)SSL_get_servername(ctx->ssl, TLSEXT_NAMETYPE_host_name);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008468 if (!smp->data.u.str.area)
Willy Tarreau3e394c92012-09-14 23:56:58 +02008469 return 0;
8470
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008471 smp->data.u.str.data = strlen(smp->data.u.str.area);
Willy Tarreau7875d092012-09-10 08:20:03 +02008472 return 1;
Willy Tarreau7875d092012-09-10 08:20:03 +02008473}
Patrick Hemmer41966772018-04-28 19:15:48 -04008474#endif
Willy Tarreau7875d092012-09-10 08:20:03 +02008475
David Sc1ad52e2014-04-08 18:48:47 -04008476static int
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008477smp_fetch_ssl_fc_cl_bin(const struct arg *args, struct sample *smp, const char *kw, void *private)
8478{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008479 struct connection *conn;
8480 struct ssl_capture *capture;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008481 struct ssl_sock_ctx *ctx;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008482
8483 conn = objt_conn(smp->sess->origin);
8484 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8485 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008486 ctx = conn->xprt_ctx;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008487
Olivier Houchard66ab4982019-02-26 18:37:15 +01008488 capture = SSL_get_ex_data(ctx->ssl, ssl_capture_ptr_index);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008489 if (!capture)
8490 return 0;
8491
8492 smp->flags = SMP_F_CONST;
8493 smp->data.type = SMP_T_BIN;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008494 smp->data.u.str.area = capture->ciphersuite;
8495 smp->data.u.str.data = capture->ciphersuite_len;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008496 return 1;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008497}
8498
8499static int
8500smp_fetch_ssl_fc_cl_hex(const struct arg *args, struct sample *smp, const char *kw, void *private)
8501{
Willy Tarreau83061a82018-07-13 11:56:34 +02008502 struct buffer *data;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008503
8504 if (!smp_fetch_ssl_fc_cl_bin(args, smp, kw, private))
8505 return 0;
8506
8507 data = get_trash_chunk();
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008508 dump_binary(data, smp->data.u.str.area, smp->data.u.str.data);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008509 smp->data.type = SMP_T_BIN;
8510 smp->data.u.str = *data;
8511 return 1;
8512}
8513
8514static int
8515smp_fetch_ssl_fc_cl_xxh64(const struct arg *args, struct sample *smp, const char *kw, void *private)
8516{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008517 struct connection *conn;
8518 struct ssl_capture *capture;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008519 struct ssl_sock_ctx *ctx;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008520
8521 conn = objt_conn(smp->sess->origin);
8522 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8523 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008524 ctx = conn->xprt_ctx;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008525
Olivier Houchard66ab4982019-02-26 18:37:15 +01008526 capture = SSL_get_ex_data(ctx->ssl, ssl_capture_ptr_index);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008527 if (!capture)
8528 return 0;
8529
8530 smp->data.type = SMP_T_SINT;
8531 smp->data.u.sint = capture->xxh64;
8532 return 1;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008533}
8534
8535static int
8536smp_fetch_ssl_fc_cl_str(const struct arg *args, struct sample *smp, const char *kw, void *private)
8537{
Willy Tarreau5db847a2019-05-09 14:13:35 +02008538#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL)
Willy Tarreau83061a82018-07-13 11:56:34 +02008539 struct buffer *data;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008540 int i;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008541
8542 if (!smp_fetch_ssl_fc_cl_bin(args, smp, kw, private))
8543 return 0;
8544
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008545 data = get_trash_chunk();
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008546 for (i = 0; i + 1 < smp->data.u.str.data; i += 2) {
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02008547 const char *str;
8548 const SSL_CIPHER *cipher;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008549 const unsigned char *bin = (const unsigned char *) smp->data.u.str.area + i;
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02008550 uint16_t id = (bin[0] << 8) | bin[1];
8551#if defined(OPENSSL_IS_BORINGSSL)
8552 cipher = SSL_get_cipher_by_value(id);
8553#else
Willy Tarreaub7290772018-10-15 11:01:59 +02008554 struct connection *conn = __objt_conn(smp->sess->origin);
Olivier Houchard66ab4982019-02-26 18:37:15 +01008555 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
8556 cipher = SSL_CIPHER_find(ctx->ssl, bin);
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02008557#endif
8558 str = SSL_CIPHER_get_name(cipher);
8559 if (!str || strcmp(str, "(NONE)") == 0)
8560 chunk_appendf(data, "%sUNKNOWN(%04x)", i == 0 ? "" : ",", id);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008561 else
8562 chunk_appendf(data, "%s%s", i == 0 ? "" : ",", str);
8563 }
8564 smp->data.type = SMP_T_STR;
8565 smp->data.u.str = *data;
8566 return 1;
8567#else
8568 return smp_fetch_ssl_fc_cl_xxh64(args, smp, kw, private);
8569#endif
8570}
8571
Willy Tarreau9a1ab082019-05-09 13:26:41 +02008572#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008573static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008574smp_fetch_ssl_fc_unique_id(const struct arg *args, struct sample *smp, const char *kw, void *private)
David Sc1ad52e2014-04-08 18:48:47 -04008575{
Emeric Bruneb8def92018-02-19 15:59:48 +01008576 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
8577 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
David Sc1ad52e2014-04-08 18:48:47 -04008578 int finished_len;
Willy Tarreau83061a82018-07-13 11:56:34 +02008579 struct buffer *finished_trash;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008580 struct ssl_sock_ctx *ctx;
David Sc1ad52e2014-04-08 18:48:47 -04008581
8582 smp->flags = 0;
David Sc1ad52e2014-04-08 18:48:47 -04008583 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8584 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008585 ctx = conn->xprt_ctx;
David Sc1ad52e2014-04-08 18:48:47 -04008586
Willy Tarreau911db9b2020-01-23 16:27:54 +01008587 if (conn->flags & CO_FL_WAIT_XPRT) {
David Sc1ad52e2014-04-08 18:48:47 -04008588 smp->flags |= SMP_F_MAY_CHANGE;
8589 return 0;
8590 }
8591
8592 finished_trash = get_trash_chunk();
Olivier Houchard66ab4982019-02-26 18:37:15 +01008593 if (!SSL_session_reused(ctx->ssl))
8594 finished_len = SSL_get_peer_finished(ctx->ssl,
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008595 finished_trash->area,
8596 finished_trash->size);
David Sc1ad52e2014-04-08 18:48:47 -04008597 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01008598 finished_len = SSL_get_finished(ctx->ssl,
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008599 finished_trash->area,
8600 finished_trash->size);
David Sc1ad52e2014-04-08 18:48:47 -04008601
8602 if (!finished_len)
8603 return 0;
8604
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008605 finished_trash->data = finished_len;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02008606 smp->data.u.str = *finished_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008607 smp->data.type = SMP_T_BIN;
David Sc1ad52e2014-04-08 18:48:47 -04008608
8609 return 1;
David Sc1ad52e2014-04-08 18:48:47 -04008610}
Patrick Hemmer41966772018-04-28 19:15:48 -04008611#endif
David Sc1ad52e2014-04-08 18:48:47 -04008612
Emeric Brun2525b6b2012-10-18 15:59:43 +02008613/* integer, returns the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02008614static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008615smp_fetch_ssl_c_ca_err(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunf282a812012-09-21 15:27:54 +02008616{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008617 struct connection *conn;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008618 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008619
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02008620 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008621 if (!conn || conn->xprt != &ssl_sock)
8622 return 0;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008623 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008624
Willy Tarreau911db9b2020-01-23 16:27:54 +01008625 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Brunf282a812012-09-21 15:27:54 +02008626 smp->flags = SMP_F_MAY_CHANGE;
8627 return 0;
8628 }
8629
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008630 smp->data.type = SMP_T_SINT;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008631 smp->data.u.sint = (unsigned long long int)SSL_SOCK_ST_TO_CA_ERROR(ctx->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02008632 smp->flags = 0;
8633
8634 return 1;
8635}
8636
Emeric Brun2525b6b2012-10-18 15:59:43 +02008637/* integer, returns the depth of the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02008638static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008639smp_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 +02008640{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008641 struct connection *conn;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008642 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008643
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02008644 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008645 if (!conn || conn->xprt != &ssl_sock)
Emeric Brunf282a812012-09-21 15:27:54 +02008646 return 0;
8647
Willy Tarreau911db9b2020-01-23 16:27:54 +01008648 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Brunf282a812012-09-21 15:27:54 +02008649 smp->flags = SMP_F_MAY_CHANGE;
8650 return 0;
8651 }
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008652 ctx = conn->xprt_ctx;
Emeric Brunf282a812012-09-21 15:27:54 +02008653
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008654 smp->data.type = SMP_T_SINT;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008655 smp->data.u.sint = (long long int)SSL_SOCK_ST_TO_CAEDEPTH(ctx->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02008656 smp->flags = 0;
8657
8658 return 1;
8659}
8660
Emeric Brun2525b6b2012-10-18 15:59:43 +02008661/* integer, returns the first verify error on client certificate */
Emeric Brunf282a812012-09-21 15:27:54 +02008662static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008663smp_fetch_ssl_c_err(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunf282a812012-09-21 15:27:54 +02008664{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008665 struct connection *conn;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008666 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008667
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02008668 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008669 if (!conn || conn->xprt != &ssl_sock)
8670 return 0;
8671
Willy Tarreau911db9b2020-01-23 16:27:54 +01008672 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Brunf282a812012-09-21 15:27:54 +02008673 smp->flags = SMP_F_MAY_CHANGE;
8674 return 0;
8675 }
8676
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008677 ctx = conn->xprt_ctx;
8678
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008679 smp->data.type = SMP_T_SINT;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008680 smp->data.u.sint = (long long int)SSL_SOCK_ST_TO_CRTERROR(ctx->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02008681 smp->flags = 0;
8682
8683 return 1;
8684}
8685
Emeric Brun2525b6b2012-10-18 15:59:43 +02008686/* integer, returns the verify result on client cert */
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02008687static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008688smp_fetch_ssl_c_verify(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02008689{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008690 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008691 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008692
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02008693 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008694 if (!conn || conn->xprt != &ssl_sock)
8695 return 0;
8696
Willy Tarreau911db9b2020-01-23 16:27:54 +01008697 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02008698 smp->flags = SMP_F_MAY_CHANGE;
8699 return 0;
8700 }
8701
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008702 if (!conn->xprt_ctx)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02008703 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008704 ctx = conn->xprt_ctx;
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02008705
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008706 smp->data.type = SMP_T_SINT;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008707 smp->data.u.sint = (long long int)SSL_get_verify_result(ctx->ssl);
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02008708 smp->flags = 0;
8709
8710 return 1;
8711}
8712
Emmanuel Hocdet842e94e2019-12-16 16:39:17 +01008713/* for ca-file and ca-verify-file */
8714static 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 +02008715{
8716 if (!*args[cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01008717 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
Emeric Brund94b3fe2012-09-20 18:23:56 +02008718 return ERR_ALERT | ERR_FATAL;
8719 }
8720
Willy Tarreauef934602016-12-22 23:12:01 +01008721 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
Emmanuel Hocdet842e94e2019-12-16 16:39:17 +01008722 memprintf(ca_file_p, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02008723 else
Emmanuel Hocdet842e94e2019-12-16 16:39:17 +01008724 memprintf(ca_file_p, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02008725
Emmanuel Hocdet842e94e2019-12-16 16:39:17 +01008726 if (!ssl_store_load_locations_file(*ca_file_p)) {
8727 memprintf(err, "'%s' : unable to load %s", args[cur_arg], *ca_file_p);
Emmanuel Hocdetd4f9a602019-10-24 11:32:47 +02008728 return ERR_ALERT | ERR_FATAL;
8729 }
Emeric Brund94b3fe2012-09-20 18:23:56 +02008730 return 0;
8731}
Emmanuel Hocdet842e94e2019-12-16 16:39:17 +01008732
8733/* parse the "ca-file" bind keyword */
8734static int ssl_bind_parse_ca_file(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
8735{
8736 return ssl_bind_parse_ca_file_common(args, cur_arg, &conf->ca_file, err);
8737}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008738static int bind_parse_ca_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8739{
8740 return ssl_bind_parse_ca_file(args, cur_arg, px, &conf->ssl_conf, err);
8741}
Emeric Brund94b3fe2012-09-20 18:23:56 +02008742
Emmanuel Hocdet842e94e2019-12-16 16:39:17 +01008743/* parse the "ca-verify-file" bind keyword */
8744static int ssl_bind_parse_ca_verify_file(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
8745{
8746 return ssl_bind_parse_ca_file_common(args, cur_arg, &conf->ca_verify_file, err);
8747}
8748static int bind_parse_ca_verify_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8749{
8750 return ssl_bind_parse_ca_verify_file(args, cur_arg, px, &conf->ssl_conf, err);
8751}
8752
Christopher Faulet31af49d2015-06-09 17:29:50 +02008753/* parse the "ca-sign-file" bind keyword */
8754static int bind_parse_ca_sign_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8755{
8756 if (!*args[cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01008757 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
Christopher Faulet31af49d2015-06-09 17:29:50 +02008758 return ERR_ALERT | ERR_FATAL;
8759 }
8760
Willy Tarreauef934602016-12-22 23:12:01 +01008761 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
8762 memprintf(&conf->ca_sign_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Christopher Faulet31af49d2015-06-09 17:29:50 +02008763 else
8764 memprintf(&conf->ca_sign_file, "%s", args[cur_arg + 1]);
8765
8766 return 0;
8767}
8768
Bertrand Jacquinff13c062016-11-13 16:37:11 +00008769/* parse the "ca-sign-pass" bind keyword */
Christopher Faulet31af49d2015-06-09 17:29:50 +02008770static int bind_parse_ca_sign_pass(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8771{
8772 if (!*args[cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01008773 memprintf(err, "'%s' : missing CAkey password", args[cur_arg]);
Christopher Faulet31af49d2015-06-09 17:29:50 +02008774 return ERR_ALERT | ERR_FATAL;
8775 }
8776 memprintf(&conf->ca_sign_pass, "%s", args[cur_arg + 1]);
8777 return 0;
8778}
8779
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008780/* parse the "ciphers" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008781static 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 +02008782{
8783 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02008784 memprintf(err, "'%s' : missing cipher suite", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008785 return ERR_ALERT | ERR_FATAL;
8786 }
8787
Emeric Brun76d88952012-10-05 15:47:31 +02008788 free(conf->ciphers);
Willy Tarreau4348fad2012-09-20 16:48:07 +02008789 conf->ciphers = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008790 return 0;
8791}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008792static int bind_parse_ciphers(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8793{
8794 return ssl_bind_parse_ciphers(args, cur_arg, px, &conf->ssl_conf, err);
8795}
Dirkjan Bussink415150f2018-09-14 11:14:21 +02008796
Emmanuel Hocdet839af572019-05-14 16:27:35 +02008797#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02008798/* parse the "ciphersuites" bind keyword */
8799static int ssl_bind_parse_ciphersuites(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
8800{
8801 if (!*args[cur_arg + 1]) {
8802 memprintf(err, "'%s' : missing cipher suite", args[cur_arg]);
8803 return ERR_ALERT | ERR_FATAL;
8804 }
8805
8806 free(conf->ciphersuites);
8807 conf->ciphersuites = strdup(args[cur_arg + 1]);
8808 return 0;
8809}
8810static int bind_parse_ciphersuites(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8811{
8812 return ssl_bind_parse_ciphersuites(args, cur_arg, px, &conf->ssl_conf, err);
8813}
8814#endif
8815
Willy Tarreaubbc91962019-10-16 16:42:19 +02008816/* parse the "crt" bind keyword. Returns a set of ERR_* flags possibly with an error in <err>. */
Willy Tarreau4348fad2012-09-20 16:48:07 +02008817static 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 +02008818{
Willy Tarreau38011032013-08-13 16:59:39 +02008819 char path[MAXPATHLEN];
Willy Tarreaub75d6922014-04-14 18:05:41 +02008820
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008821 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02008822 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008823 return ERR_ALERT | ERR_FATAL;
8824 }
8825
Willy Tarreauef934602016-12-22 23:12:01 +01008826 if ((*args[cur_arg + 1] != '/' ) && global_ssl.crt_base) {
8827 if ((strlen(global_ssl.crt_base) + 1 + strlen(args[cur_arg + 1]) + 1) > MAXPATHLEN) {
Emeric Brunc8e8d122012-10-02 18:42:10 +02008828 memprintf(err, "'%s' : path too long", args[cur_arg]);
8829 return ERR_ALERT | ERR_FATAL;
8830 }
Willy Tarreauef934602016-12-22 23:12:01 +01008831 snprintf(path, sizeof(path), "%s/%s", global_ssl.crt_base, args[cur_arg + 1]);
Willy Tarreaubbc91962019-10-16 16:42:19 +02008832 return ssl_sock_load_cert(path, conf, err);
Emeric Brunc8e8d122012-10-02 18:42:10 +02008833 }
8834
Willy Tarreaubbc91962019-10-16 16:42:19 +02008835 return ssl_sock_load_cert(args[cur_arg + 1], conf, err);
Emeric Brund94b3fe2012-09-20 18:23:56 +02008836}
8837
Willy Tarreaubbc91962019-10-16 16:42:19 +02008838/* 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 +01008839static int bind_parse_crt_list(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8840{
Willy Tarreaubbc91962019-10-16 16:42:19 +02008841 int err_code;
8842
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01008843 if (!*args[cur_arg + 1]) {
8844 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
8845 return ERR_ALERT | ERR_FATAL;
8846 }
8847
Willy Tarreaubbc91962019-10-16 16:42:19 +02008848 err_code = ssl_sock_load_cert_list_file(args[cur_arg + 1], conf, px, err);
8849 if (err_code)
Willy Tarreauad1731d2013-04-02 17:35:58 +02008850 memprintf(err, "'%s' : %s", args[cur_arg], *err);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01008851
Willy Tarreaubbc91962019-10-16 16:42:19 +02008852 return err_code;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01008853}
8854
Emeric Brunfb510ea2012-10-05 12:00:26 +02008855/* parse the "crl-file" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008856static 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 +02008857{
Emeric Brun051cdab2012-10-02 19:25:50 +02008858#ifndef X509_V_FLAG_CRL_CHECK
Tim Duesterhus93128532019-11-23 23:45:10 +01008859 memprintf(err, "'%s' : library does not support CRL verify", args[cur_arg]);
Emeric Brun051cdab2012-10-02 19:25:50 +02008860 return ERR_ALERT | ERR_FATAL;
8861#else
Emeric Brund94b3fe2012-09-20 18:23:56 +02008862 if (!*args[cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01008863 memprintf(err, "'%s' : missing CRLfile path", args[cur_arg]);
Emeric Brund94b3fe2012-09-20 18:23:56 +02008864 return ERR_ALERT | ERR_FATAL;
8865 }
Emeric Brun2b58d042012-09-20 17:10:03 +02008866
Willy Tarreauef934602016-12-22 23:12:01 +01008867 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
8868 memprintf(&conf->crl_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02008869 else
8870 memprintf(&conf->crl_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02008871
Emmanuel Hocdetb270e812019-11-21 19:09:31 +01008872 if (!ssl_store_load_locations_file(conf->crl_file)) {
8873 memprintf(err, "'%s' : unable to load %s", args[cur_arg], conf->crl_file);
8874 return ERR_ALERT | ERR_FATAL;
8875 }
Emeric Brun2b58d042012-09-20 17:10:03 +02008876 return 0;
Emeric Brun051cdab2012-10-02 19:25:50 +02008877#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02008878}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008879static int bind_parse_crl_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8880{
8881 return ssl_bind_parse_crl_file(args, cur_arg, px, &conf->ssl_conf, err);
8882}
Emeric Brun2b58d042012-09-20 17:10:03 +02008883
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01008884/* parse the "curves" bind keyword keyword */
8885static int ssl_bind_parse_curves(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
8886{
Lukas Tribusd14b49c2019-11-24 18:20:40 +01008887#if ((HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL) || defined(LIBRESSL_VERSION_NUMBER))
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01008888 if (!*args[cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01008889 memprintf(err, "'%s' : missing curve suite", args[cur_arg]);
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01008890 return ERR_ALERT | ERR_FATAL;
8891 }
8892 conf->curves = strdup(args[cur_arg + 1]);
8893 return 0;
8894#else
Tim Duesterhus93128532019-11-23 23:45:10 +01008895 memprintf(err, "'%s' : library does not support curve suite", args[cur_arg]);
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01008896 return ERR_ALERT | ERR_FATAL;
8897#endif
8898}
8899static int bind_parse_curves(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8900{
8901 return ssl_bind_parse_curves(args, cur_arg, px, &conf->ssl_conf, err);
8902}
8903
Bertrand Jacquinff13c062016-11-13 16:37:11 +00008904/* parse the "ecdhe" bind keyword keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008905static 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 +02008906{
Willy Tarreau9a1ab082019-05-09 13:26:41 +02008907#if HA_OPENSSL_VERSION_NUMBER < 0x0090800fL
Tim Duesterhus93128532019-11-23 23:45:10 +01008908 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (too old)", args[cur_arg]);
Emeric Brun2b58d042012-09-20 17:10:03 +02008909 return ERR_ALERT | ERR_FATAL;
8910#elif defined(OPENSSL_NO_ECDH)
Tim Duesterhus93128532019-11-23 23:45:10 +01008911 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 +02008912 return ERR_ALERT | ERR_FATAL;
8913#else
8914 if (!*args[cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01008915 memprintf(err, "'%s' : missing named curve", args[cur_arg]);
Emeric Brun2b58d042012-09-20 17:10:03 +02008916 return ERR_ALERT | ERR_FATAL;
8917 }
8918
8919 conf->ecdhe = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008920
8921 return 0;
Emeric Brun2b58d042012-09-20 17:10:03 +02008922#endif
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008923}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008924static int bind_parse_ecdhe(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8925{
8926 return ssl_bind_parse_ecdhe(args, cur_arg, px, &conf->ssl_conf, err);
8927}
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008928
Bertrand Jacquinff13c062016-11-13 16:37:11 +00008929/* parse the "crt-ignore-err" and "ca-ignore-err" bind keywords */
Emeric Brun81c00f02012-09-21 14:31:21 +02008930static int bind_parse_ignore_err(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8931{
8932 int code;
8933 char *p = args[cur_arg + 1];
8934 unsigned long long *ignerr = &conf->crt_ignerr;
8935
8936 if (!*p) {
Tim Duesterhus93128532019-11-23 23:45:10 +01008937 memprintf(err, "'%s' : missing error IDs list", args[cur_arg]);
Emeric Brun81c00f02012-09-21 14:31:21 +02008938 return ERR_ALERT | ERR_FATAL;
8939 }
8940
8941 if (strcmp(args[cur_arg], "ca-ignore-err") == 0)
8942 ignerr = &conf->ca_ignerr;
8943
8944 if (strcmp(p, "all") == 0) {
8945 *ignerr = ~0ULL;
8946 return 0;
8947 }
8948
8949 while (p) {
8950 code = atoi(p);
8951 if ((code <= 0) || (code > 63)) {
Tim Duesterhus93128532019-11-23 23:45:10 +01008952 memprintf(err, "'%s' : ID '%d' out of range (1..63) in error IDs list '%s'",
8953 args[cur_arg], code, args[cur_arg + 1]);
Emeric Brun81c00f02012-09-21 14:31:21 +02008954 return ERR_ALERT | ERR_FATAL;
8955 }
8956 *ignerr |= 1ULL << code;
8957 p = strchr(p, ',');
8958 if (p)
8959 p++;
8960 }
8961
Emeric Brun2cb7ae52012-10-05 14:14:21 +02008962 return 0;
8963}
8964
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008965/* parse tls_method_options "no-xxx" and "force-xxx" */
8966static int parse_tls_method_options(char *arg, struct tls_version_filter *methods, char **err)
Emeric Brun2cb7ae52012-10-05 14:14:21 +02008967{
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008968 uint16_t v;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008969 char *p;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008970 p = strchr(arg, '-');
8971 if (!p)
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008972 goto fail;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008973 p++;
8974 if (!strcmp(p, "sslv3"))
8975 v = CONF_SSLV3;
8976 else if (!strcmp(p, "tlsv10"))
8977 v = CONF_TLSV10;
8978 else if (!strcmp(p, "tlsv11"))
8979 v = CONF_TLSV11;
8980 else if (!strcmp(p, "tlsv12"))
8981 v = CONF_TLSV12;
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +02008982 else if (!strcmp(p, "tlsv13"))
8983 v = CONF_TLSV13;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008984 else
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008985 goto fail;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008986 if (!strncmp(arg, "no-", 3))
8987 methods->flags |= methodVersions[v].flag;
8988 else if (!strncmp(arg, "force-", 6))
8989 methods->min = methods->max = v;
8990 else
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008991 goto fail;
Emeric Brun2d0c4822012-10-02 13:45:20 +02008992 return 0;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008993 fail:
Tim Duesterhus93128532019-11-23 23:45:10 +01008994 memprintf(err, "'%s' : option not implemented", arg);
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008995 return ERR_ALERT | ERR_FATAL;
Emeric Brun2d0c4822012-10-02 13:45:20 +02008996}
8997
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008998static 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 +02008999{
Emmanuel Hocdet43664762017-08-09 18:26:20 +02009000 return parse_tls_method_options(args[cur_arg], &conf->ssl_conf.ssl_methods, err);
Emeric Brun2cb7ae52012-10-05 14:14:21 +02009001}
9002
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02009003static 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 +02009004{
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02009005 return parse_tls_method_options(args[*cur_arg], &newsrv->ssl_ctx.methods, err);
9006}
9007
9008/* parse tls_method min/max: "ssl-min-ver" and "ssl-max-ver" */
9009static int parse_tls_method_minmax(char **args, int cur_arg, struct tls_version_filter *methods, char **err)
9010{
9011 uint16_t i, v = 0;
9012 char *argv = args[cur_arg + 1];
9013 if (!*argv) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009014 memprintf(err, "'%s' : missing the ssl/tls version", args[cur_arg]);
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02009015 return ERR_ALERT | ERR_FATAL;
9016 }
9017 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
9018 if (!strcmp(argv, methodVersions[i].name))
9019 v = i;
9020 if (!v) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009021 memprintf(err, "'%s' : unknown ssl/tls version", args[cur_arg + 1]);
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02009022 return ERR_ALERT | ERR_FATAL;
9023 }
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02009024 if (!strcmp("ssl-min-ver", args[cur_arg]))
9025 methods->min = v;
9026 else if (!strcmp("ssl-max-ver", args[cur_arg]))
9027 methods->max = v;
9028 else {
Tim Duesterhus93128532019-11-23 23:45:10 +01009029 memprintf(err, "'%s' : option not implemented", args[cur_arg]);
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02009030 return ERR_ALERT | ERR_FATAL;
9031 }
Emeric Brun2cb7ae52012-10-05 14:14:21 +02009032 return 0;
Emeric Brun2cb7ae52012-10-05 14:14:21 +02009033}
Emeric Brun2cb7ae52012-10-05 14:14:21 +02009034
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02009035static int ssl_bind_parse_tls_method_minmax(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
9036{
Willy Tarreau9a1ab082019-05-09 13:26:41 +02009037#if (HA_OPENSSL_VERSION_NUMBER < 0x10101000L) && !defined(OPENSSL_IS_BORINGSSL)
Christopher Faulet767a84b2017-11-24 16:50:31 +01009038 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 +02009039#endif
9040 return parse_tls_method_minmax(args, cur_arg, &conf->ssl_methods, err);
9041}
9042
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02009043static int bind_parse_tls_method_minmax(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
9044{
Emmanuel Hocdet43664762017-08-09 18:26:20 +02009045 return parse_tls_method_minmax(args, cur_arg, &conf->ssl_conf.ssl_methods, err);
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02009046}
9047
9048static int srv_parse_tls_method_minmax(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9049{
9050 return parse_tls_method_minmax(args, *cur_arg, &newsrv->ssl_ctx.methods, err);
9051}
9052
Emeric Brun2d0c4822012-10-02 13:45:20 +02009053/* parse the "no-tls-tickets" bind keyword */
Emmanuel Hocdet4608ed92017-01-20 13:06:27 +01009054static 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 +02009055{
Emeric Brun89675492012-10-05 13:48:26 +02009056 conf->ssl_options |= BC_SSL_O_NO_TLS_TICKETS;
Emeric Brun81c00f02012-09-21 14:31:21 +02009057 return 0;
9058}
Emeric Brun2d0c4822012-10-02 13:45:20 +02009059
Olivier Houchardc2aae742017-09-22 18:26:28 +02009060/* parse the "allow-0rtt" bind keyword */
9061static int ssl_bind_parse_allow_0rtt(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
9062{
9063 conf->early_data = 1;
9064 return 0;
9065}
9066
9067static int bind_parse_allow_0rtt(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
9068{
Olivier Houchard9679ac92017-10-27 14:58:08 +02009069 conf->ssl_conf.early_data = 1;
Olivier Houchardc2aae742017-09-22 18:26:28 +02009070 return 0;
9071}
9072
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02009073/* parse the "npn" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01009074static 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 +02009075{
Bernard Spil13c53f82018-02-15 13:34:58 +01009076#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02009077 char *p1, *p2;
9078
9079 if (!*args[cur_arg + 1]) {
9080 memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[cur_arg]);
9081 return ERR_ALERT | ERR_FATAL;
9082 }
9083
9084 free(conf->npn_str);
9085
Willy Tarreau3724da12016-02-12 17:11:12 +01009086 /* the NPN string is built as a suite of (<len> <name>)*,
9087 * so we reuse each comma to store the next <len> and need
9088 * one more for the end of the string.
9089 */
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02009090 conf->npn_len = strlen(args[cur_arg + 1]) + 1;
Willy Tarreau3724da12016-02-12 17:11:12 +01009091 conf->npn_str = calloc(1, conf->npn_len + 1);
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02009092 memcpy(conf->npn_str + 1, args[cur_arg + 1], conf->npn_len);
9093
9094 /* replace commas with the name length */
9095 p1 = conf->npn_str;
9096 p2 = p1 + 1;
9097 while (1) {
9098 p2 = memchr(p1 + 1, ',', conf->npn_str + conf->npn_len - (p1 + 1));
9099 if (!p2)
9100 p2 = p1 + 1 + strlen(p1 + 1);
9101
9102 if (p2 - (p1 + 1) > 255) {
9103 *p2 = '\0';
9104 memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
9105 return ERR_ALERT | ERR_FATAL;
9106 }
9107
9108 *p1 = p2 - (p1 + 1);
9109 p1 = p2;
9110
9111 if (!*p2)
9112 break;
9113
9114 *(p2++) = '\0';
9115 }
9116 return 0;
9117#else
Tim Duesterhus93128532019-11-23 23:45:10 +01009118 memprintf(err, "'%s' : library does not support TLS NPN extension", args[cur_arg]);
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02009119 return ERR_ALERT | ERR_FATAL;
9120#endif
9121}
9122
Emmanuel Hocdet98263292016-12-29 18:26:15 +01009123static int bind_parse_npn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
9124{
9125 return ssl_bind_parse_npn(args, cur_arg, px, &conf->ssl_conf, err);
9126}
9127
Willy Tarreauab861d32013-04-02 02:30:41 +02009128/* parse the "alpn" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01009129static 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 +02009130{
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01009131#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02009132 char *p1, *p2;
9133
9134 if (!*args[cur_arg + 1]) {
9135 memprintf(err, "'%s' : missing the comma-delimited ALPN protocol suite", args[cur_arg]);
9136 return ERR_ALERT | ERR_FATAL;
9137 }
9138
9139 free(conf->alpn_str);
9140
Marcoen Hirschbergbef60912016-02-12 17:05:24 +01009141 /* the ALPN string is built as a suite of (<len> <name>)*,
9142 * so we reuse each comma to store the next <len> and need
9143 * one more for the end of the string.
9144 */
Willy Tarreauab861d32013-04-02 02:30:41 +02009145 conf->alpn_len = strlen(args[cur_arg + 1]) + 1;
Marcoen Hirschbergbef60912016-02-12 17:05:24 +01009146 conf->alpn_str = calloc(1, conf->alpn_len + 1);
Willy Tarreauab861d32013-04-02 02:30:41 +02009147 memcpy(conf->alpn_str + 1, args[cur_arg + 1], conf->alpn_len);
9148
9149 /* replace commas with the name length */
9150 p1 = conf->alpn_str;
9151 p2 = p1 + 1;
9152 while (1) {
9153 p2 = memchr(p1 + 1, ',', conf->alpn_str + conf->alpn_len - (p1 + 1));
9154 if (!p2)
9155 p2 = p1 + 1 + strlen(p1 + 1);
9156
9157 if (p2 - (p1 + 1) > 255) {
9158 *p2 = '\0';
9159 memprintf(err, "'%s' : ALPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
9160 return ERR_ALERT | ERR_FATAL;
9161 }
9162
9163 *p1 = p2 - (p1 + 1);
9164 p1 = p2;
9165
9166 if (!*p2)
9167 break;
9168
9169 *(p2++) = '\0';
9170 }
9171 return 0;
9172#else
Tim Duesterhus93128532019-11-23 23:45:10 +01009173 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[cur_arg]);
Willy Tarreauab861d32013-04-02 02:30:41 +02009174 return ERR_ALERT | ERR_FATAL;
9175#endif
9176}
9177
Emmanuel Hocdet98263292016-12-29 18:26:15 +01009178static int bind_parse_alpn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
9179{
9180 return ssl_bind_parse_alpn(args, cur_arg, px, &conf->ssl_conf, err);
9181}
9182
Willy Tarreau79eeafa2012-09-14 07:53:05 +02009183/* parse the "ssl" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02009184static 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 +02009185{
Willy Tarreau71a8c7c2016-12-21 22:04:54 +01009186 conf->xprt = &ssl_sock;
Willy Tarreau4348fad2012-09-20 16:48:07 +02009187 conf->is_ssl = 1;
Emeric Brun76d88952012-10-05 15:47:31 +02009188
Emmanuel Hocdet98263292016-12-29 18:26:15 +01009189 if (global_ssl.listen_default_ciphers && !conf->ssl_conf.ciphers)
9190 conf->ssl_conf.ciphers = strdup(global_ssl.listen_default_ciphers);
Emmanuel Hocdet839af572019-05-14 16:27:35 +02009191#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009192 if (global_ssl.listen_default_ciphersuites && !conf->ssl_conf.ciphersuites)
9193 conf->ssl_conf.ciphersuites = strdup(global_ssl.listen_default_ciphersuites);
9194#endif
Emmanuel Hocdet4608ed92017-01-20 13:06:27 +01009195 conf->ssl_options |= global_ssl.listen_default_ssloptions;
Emmanuel Hocdet43664762017-08-09 18:26:20 +02009196 conf->ssl_conf.ssl_methods.flags |= global_ssl.listen_default_sslmethods.flags;
9197 if (!conf->ssl_conf.ssl_methods.min)
9198 conf->ssl_conf.ssl_methods.min = global_ssl.listen_default_sslmethods.min;
9199 if (!conf->ssl_conf.ssl_methods.max)
9200 conf->ssl_conf.ssl_methods.max = global_ssl.listen_default_sslmethods.max;
Emeric Brun76d88952012-10-05 15:47:31 +02009201
Willy Tarreau79eeafa2012-09-14 07:53:05 +02009202 return 0;
9203}
9204
Lukas Tribus53ae85c2017-05-04 15:45:40 +00009205/* parse the "prefer-client-ciphers" bind keyword */
9206static int bind_parse_pcc(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
9207{
9208 conf->ssl_options |= BC_SSL_O_PREF_CLIE_CIPH;
9209 return 0;
9210}
9211
Christopher Faulet31af49d2015-06-09 17:29:50 +02009212/* parse the "generate-certificates" bind keyword */
9213static int bind_parse_generate_certs(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
9214{
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01009215#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Christopher Faulet31af49d2015-06-09 17:29:50 +02009216 conf->generate_certs = 1;
9217#else
9218 memprintf(err, "%sthis version of openssl cannot generate SSL certificates.\n",
9219 err && *err ? *err : "");
9220#endif
9221 return 0;
9222}
9223
Emmanuel Hocdet65623372013-01-24 17:17:15 +01009224/* parse the "strict-sni" bind keyword */
9225static int bind_parse_strict_sni(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
9226{
9227 conf->strict_sni = 1;
9228 return 0;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009229}
9230
9231/* parse the "tls-ticket-keys" bind keyword */
9232static int bind_parse_tls_ticket_keys(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
9233{
9234#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
Christopher Faulete566f3d2019-10-21 09:55:49 +02009235 FILE *f = NULL;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009236 int i = 0;
9237 char thisline[LINESIZE];
Christopher Faulete566f3d2019-10-21 09:55:49 +02009238 struct tls_keys_ref *keys_ref = NULL;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009239
9240 if (!*args[cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009241 memprintf(err, "'%s' : missing TLS ticket keys file path", args[cur_arg]);
Christopher Faulete566f3d2019-10-21 09:55:49 +02009242 goto fail;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009243 }
9244
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02009245 keys_ref = tlskeys_ref_lookup(args[cur_arg + 1]);
Willy Tarreau17b4aa12018-07-17 10:05:32 +02009246 if (keys_ref) {
9247 keys_ref->refcount++;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02009248 conf->keys_ref = keys_ref;
9249 return 0;
9250 }
9251
Christopher Faulete566f3d2019-10-21 09:55:49 +02009252 keys_ref = calloc(1, sizeof(*keys_ref));
Emeric Brun09852f72019-01-10 10:51:13 +01009253 if (!keys_ref) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009254 memprintf(err, "'%s' : allocation error", args[cur_arg+1]);
Christopher Faulete566f3d2019-10-21 09:55:49 +02009255 goto fail;
Emeric Brun09852f72019-01-10 10:51:13 +01009256 }
9257
Emeric Brun9e754772019-01-10 17:51:55 +01009258 keys_ref->tlskeys = malloc(TLS_TICKETS_NO * sizeof(union tls_sess_key));
Emeric Brun09852f72019-01-10 10:51:13 +01009259 if (!keys_ref->tlskeys) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009260 memprintf(err, "'%s' : allocation error", args[cur_arg+1]);
Christopher Faulete566f3d2019-10-21 09:55:49 +02009261 goto fail;
Emeric Brun09852f72019-01-10 10:51:13 +01009262 }
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009263
9264 if ((f = fopen(args[cur_arg + 1], "r")) == NULL) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009265 memprintf(err, "'%s' : unable to load ssl tickets keys file", args[cur_arg+1]);
Christopher Faulete566f3d2019-10-21 09:55:49 +02009266 goto fail;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009267 }
9268
Nenad Merdanovic146defa2015-05-09 08:46:00 +02009269 keys_ref->filename = strdup(args[cur_arg + 1]);
Emeric Brun09852f72019-01-10 10:51:13 +01009270 if (!keys_ref->filename) {
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 Merdanovic146defa2015-05-09 08:46:00 +02009274
Emeric Brun9e754772019-01-10 17:51:55 +01009275 keys_ref->key_size_bits = 0;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009276 while (fgets(thisline, sizeof(thisline), f) != NULL) {
9277 int len = strlen(thisline);
Emeric Brun9e754772019-01-10 17:51:55 +01009278 int dec_size;
9279
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009280 /* Strip newline characters from the end */
9281 if(thisline[len - 1] == '\n')
9282 thisline[--len] = 0;
9283
9284 if(thisline[len - 1] == '\r')
9285 thisline[--len] = 0;
9286
Emeric Brun9e754772019-01-10 17:51:55 +01009287 dec_size = base64dec(thisline, len, (char *) (keys_ref->tlskeys + i % TLS_TICKETS_NO), sizeof(union tls_sess_key));
9288 if (dec_size < 0) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009289 memprintf(err, "'%s' : unable to decode base64 key on line %d", args[cur_arg+1], i + 1);
Christopher Faulete566f3d2019-10-21 09:55:49 +02009290 goto fail;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009291 }
Emeric Brun9e754772019-01-10 17:51:55 +01009292 else if (!keys_ref->key_size_bits && (dec_size == sizeof(struct tls_sess_key_128))) {
9293 keys_ref->key_size_bits = 128;
9294 }
9295 else if (!keys_ref->key_size_bits && (dec_size == sizeof(struct tls_sess_key_256))) {
9296 keys_ref->key_size_bits = 256;
9297 }
9298 else if (((dec_size != sizeof(struct tls_sess_key_128)) && (dec_size != sizeof(struct tls_sess_key_256)))
9299 || ((dec_size == sizeof(struct tls_sess_key_128) && (keys_ref->key_size_bits != 128)))
9300 || ((dec_size == sizeof(struct tls_sess_key_256) && (keys_ref->key_size_bits != 256)))) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009301 memprintf(err, "'%s' : wrong sized key on line %d", args[cur_arg+1], i + 1);
Christopher Faulete566f3d2019-10-21 09:55:49 +02009302 goto fail;
Emeric Brun9e754772019-01-10 17:51:55 +01009303 }
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009304 i++;
9305 }
9306
9307 if (i < TLS_TICKETS_NO) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009308 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 +02009309 goto fail;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009310 }
9311
9312 fclose(f);
9313
9314 /* Use penultimate key for encryption, handle when TLS_TICKETS_NO = 1 */
Nenad Merdanovic17891152016-03-25 22:16:57 +01009315 i -= 2;
9316 keys_ref->tls_ticket_enc_index = i < 0 ? 0 : i % TLS_TICKETS_NO;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02009317 keys_ref->unique_id = -1;
Willy Tarreau17b4aa12018-07-17 10:05:32 +02009318 keys_ref->refcount = 1;
Christopher Faulet16f45c82018-02-16 11:23:49 +01009319 HA_RWLOCK_INIT(&keys_ref->lock);
Nenad Merdanovic146defa2015-05-09 08:46:00 +02009320 conf->keys_ref = keys_ref;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009321
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02009322 LIST_ADD(&tlskeys_reference, &keys_ref->list);
9323
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009324 return 0;
Christopher Faulete566f3d2019-10-21 09:55:49 +02009325
9326 fail:
9327 if (f)
9328 fclose(f);
9329 if (keys_ref) {
9330 free(keys_ref->filename);
9331 free(keys_ref->tlskeys);
9332 free(keys_ref);
9333 }
9334 return ERR_ALERT | ERR_FATAL;
9335
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009336#else
Tim Duesterhus93128532019-11-23 23:45:10 +01009337 memprintf(err, "'%s' : TLS ticket callback extension not supported", args[cur_arg]);
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009338 return ERR_ALERT | ERR_FATAL;
9339#endif /* SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB */
Emmanuel Hocdet65623372013-01-24 17:17:15 +01009340}
9341
Emeric Brund94b3fe2012-09-20 18:23:56 +02009342/* parse the "verify" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01009343static 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 +02009344{
9345 if (!*args[cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009346 memprintf(err, "'%s' : missing verify method", args[cur_arg]);
Emeric Brund94b3fe2012-09-20 18:23:56 +02009347 return ERR_ALERT | ERR_FATAL;
9348 }
9349
9350 if (strcmp(args[cur_arg + 1], "none") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01009351 conf->verify = SSL_SOCK_VERIFY_NONE;
Emeric Brund94b3fe2012-09-20 18:23:56 +02009352 else if (strcmp(args[cur_arg + 1], "optional") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01009353 conf->verify = SSL_SOCK_VERIFY_OPTIONAL;
Emeric Brund94b3fe2012-09-20 18:23:56 +02009354 else if (strcmp(args[cur_arg + 1], "required") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01009355 conf->verify = SSL_SOCK_VERIFY_REQUIRED;
Emeric Brund94b3fe2012-09-20 18:23:56 +02009356 else {
Tim Duesterhus93128532019-11-23 23:45:10 +01009357 memprintf(err, "'%s' : unknown verify method '%s', only 'none', 'optional', and 'required' are supported\n",
9358 args[cur_arg], args[cur_arg + 1]);
Emeric Brund94b3fe2012-09-20 18:23:56 +02009359 return ERR_ALERT | ERR_FATAL;
9360 }
9361
9362 return 0;
9363}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01009364static int bind_parse_verify(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
9365{
9366 return ssl_bind_parse_verify(args, cur_arg, px, &conf->ssl_conf, err);
9367}
Emeric Brund94b3fe2012-09-20 18:23:56 +02009368
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02009369/* parse the "no-ca-names" bind keyword */
9370static int ssl_bind_parse_no_ca_names(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
9371{
9372 conf->no_ca_names = 1;
9373 return 0;
9374}
9375static int bind_parse_no_ca_names(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
9376{
9377 return ssl_bind_parse_no_ca_names(args, cur_arg, px, &conf->ssl_conf, err);
9378}
9379
Willy Tarreau92faadf2012-10-10 23:04:25 +02009380/************** "server" keywords ****************/
9381
Olivier Houchardc7566002018-11-20 23:33:50 +01009382/* parse the "npn" bind keyword */
9383static int srv_parse_npn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9384{
9385#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
9386 char *p1, *p2;
9387
9388 if (!*args[*cur_arg + 1]) {
9389 memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[*cur_arg]);
9390 return ERR_ALERT | ERR_FATAL;
9391 }
9392
9393 free(newsrv->ssl_ctx.npn_str);
9394
9395 /* the NPN string is built as a suite of (<len> <name>)*,
9396 * so we reuse each comma to store the next <len> and need
9397 * one more for the end of the string.
9398 */
9399 newsrv->ssl_ctx.npn_len = strlen(args[*cur_arg + 1]) + 1;
9400 newsrv->ssl_ctx.npn_str = calloc(1, newsrv->ssl_ctx.npn_len + 1);
9401 memcpy(newsrv->ssl_ctx.npn_str + 1, args[*cur_arg + 1],
9402 newsrv->ssl_ctx.npn_len);
9403
9404 /* replace commas with the name length */
9405 p1 = newsrv->ssl_ctx.npn_str;
9406 p2 = p1 + 1;
9407 while (1) {
9408 p2 = memchr(p1 + 1, ',', newsrv->ssl_ctx.npn_str +
9409 newsrv->ssl_ctx.npn_len - (p1 + 1));
9410 if (!p2)
9411 p2 = p1 + 1 + strlen(p1 + 1);
9412
9413 if (p2 - (p1 + 1) > 255) {
9414 *p2 = '\0';
9415 memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[*cur_arg], p1 + 1);
9416 return ERR_ALERT | ERR_FATAL;
9417 }
9418
9419 *p1 = p2 - (p1 + 1);
9420 p1 = p2;
9421
9422 if (!*p2)
9423 break;
9424
9425 *(p2++) = '\0';
9426 }
9427 return 0;
9428#else
Tim Duesterhus93128532019-11-23 23:45:10 +01009429 memprintf(err, "'%s' : library does not support TLS NPN extension", args[*cur_arg]);
Olivier Houchardc7566002018-11-20 23:33:50 +01009430 return ERR_ALERT | ERR_FATAL;
9431#endif
9432}
9433
Olivier Houchard92150142018-12-21 19:47:01 +01009434/* parse the "alpn" or the "check-alpn" server keyword */
Olivier Houchardc7566002018-11-20 23:33:50 +01009435static int srv_parse_alpn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9436{
9437#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
9438 char *p1, *p2;
Olivier Houchard92150142018-12-21 19:47:01 +01009439 char **alpn_str;
9440 int *alpn_len;
Olivier Houchardc7566002018-11-20 23:33:50 +01009441
Olivier Houchard92150142018-12-21 19:47:01 +01009442 if (*args[*cur_arg] == 'c') {
9443 alpn_str = &newsrv->check.alpn_str;
9444 alpn_len = &newsrv->check.alpn_len;
9445 } else {
9446 alpn_str = &newsrv->ssl_ctx.alpn_str;
9447 alpn_len = &newsrv->ssl_ctx.alpn_len;
9448
9449 }
Olivier Houchardc7566002018-11-20 23:33:50 +01009450 if (!*args[*cur_arg + 1]) {
9451 memprintf(err, "'%s' : missing the comma-delimited ALPN protocol suite", args[*cur_arg]);
9452 return ERR_ALERT | ERR_FATAL;
9453 }
9454
Olivier Houchard92150142018-12-21 19:47:01 +01009455 free(*alpn_str);
Olivier Houchardc7566002018-11-20 23:33:50 +01009456
9457 /* the ALPN string is built as a suite of (<len> <name>)*,
9458 * so we reuse each comma to store the next <len> and need
9459 * one more for the end of the string.
9460 */
Olivier Houchard92150142018-12-21 19:47:01 +01009461 *alpn_len = strlen(args[*cur_arg + 1]) + 1;
9462 *alpn_str = calloc(1, *alpn_len + 1);
9463 memcpy(*alpn_str + 1, args[*cur_arg + 1], *alpn_len);
Olivier Houchardc7566002018-11-20 23:33:50 +01009464
9465 /* replace commas with the name length */
Olivier Houchard92150142018-12-21 19:47:01 +01009466 p1 = *alpn_str;
Olivier Houchardc7566002018-11-20 23:33:50 +01009467 p2 = p1 + 1;
9468 while (1) {
Olivier Houchard92150142018-12-21 19:47:01 +01009469 p2 = memchr(p1 + 1, ',', *alpn_str + *alpn_len - (p1 + 1));
Olivier Houchardc7566002018-11-20 23:33:50 +01009470 if (!p2)
9471 p2 = p1 + 1 + strlen(p1 + 1);
9472
9473 if (p2 - (p1 + 1) > 255) {
9474 *p2 = '\0';
9475 memprintf(err, "'%s' : ALPN protocol name too long : '%s'", args[*cur_arg], p1 + 1);
9476 return ERR_ALERT | ERR_FATAL;
9477 }
9478
9479 *p1 = p2 - (p1 + 1);
9480 p1 = p2;
9481
9482 if (!*p2)
9483 break;
9484
9485 *(p2++) = '\0';
9486 }
9487 return 0;
9488#else
Tim Duesterhus93128532019-11-23 23:45:10 +01009489 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[*cur_arg]);
Olivier Houchardc7566002018-11-20 23:33:50 +01009490 return ERR_ALERT | ERR_FATAL;
9491#endif
9492}
9493
Emeric Brunef42d922012-10-11 16:11:36 +02009494/* parse the "ca-file" server keyword */
9495static int srv_parse_ca_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9496{
9497 if (!*args[*cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009498 memprintf(err, "'%s' : missing CAfile path", args[*cur_arg]);
Emeric Brunef42d922012-10-11 16:11:36 +02009499 return ERR_ALERT | ERR_FATAL;
9500 }
9501
Willy Tarreauef934602016-12-22 23:12:01 +01009502 if ((*args[*cur_arg + 1] != '/') && global_ssl.ca_base)
9503 memprintf(&newsrv->ssl_ctx.ca_file, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02009504 else
9505 memprintf(&newsrv->ssl_ctx.ca_file, "%s", args[*cur_arg + 1]);
9506
Emmanuel Hocdetd4f9a602019-10-24 11:32:47 +02009507 if (!ssl_store_load_locations_file(newsrv->ssl_ctx.ca_file)) {
9508 memprintf(err, "'%s' : unable to load %s", args[*cur_arg], newsrv->ssl_ctx.ca_file);
9509 return ERR_ALERT | ERR_FATAL;
9510 }
Emeric Brunef42d922012-10-11 16:11:36 +02009511 return 0;
9512}
9513
Olivier Houchard9130a962017-10-17 17:33:43 +02009514/* parse the "check-sni" server keyword */
9515static int srv_parse_check_sni(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9516{
9517 if (!*args[*cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009518 memprintf(err, "'%s' : missing SNI", args[*cur_arg]);
Olivier Houchard9130a962017-10-17 17:33:43 +02009519 return ERR_ALERT | ERR_FATAL;
9520 }
9521
9522 newsrv->check.sni = strdup(args[*cur_arg + 1]);
9523 if (!newsrv->check.sni) {
9524 memprintf(err, "'%s' : failed to allocate memory", args[*cur_arg]);
9525 return ERR_ALERT | ERR_FATAL;
9526 }
9527 return 0;
9528
9529}
9530
Willy Tarreau92faadf2012-10-10 23:04:25 +02009531/* parse the "check-ssl" server keyword */
9532static int srv_parse_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9533{
9534 newsrv->check.use_ssl = 1;
Willy Tarreauef934602016-12-22 23:12:01 +01009535 if (global_ssl.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
9536 newsrv->ssl_ctx.ciphers = strdup(global_ssl.connect_default_ciphers);
Emmanuel Hocdet839af572019-05-14 16:27:35 +02009537#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009538 if (global_ssl.connect_default_ciphersuites && !newsrv->ssl_ctx.ciphersuites)
9539 newsrv->ssl_ctx.ciphersuites = strdup(global_ssl.connect_default_ciphersuites);
9540#endif
Willy Tarreauef934602016-12-22 23:12:01 +01009541 newsrv->ssl_ctx.options |= global_ssl.connect_default_ssloptions;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02009542 newsrv->ssl_ctx.methods.flags |= global_ssl.connect_default_sslmethods.flags;
9543 if (!newsrv->ssl_ctx.methods.min)
9544 newsrv->ssl_ctx.methods.min = global_ssl.connect_default_sslmethods.min;
9545 if (!newsrv->ssl_ctx.methods.max)
9546 newsrv->ssl_ctx.methods.max = global_ssl.connect_default_sslmethods.max;
9547
Willy Tarreau92faadf2012-10-10 23:04:25 +02009548 return 0;
9549}
9550
9551/* parse the "ciphers" server keyword */
9552static int srv_parse_ciphers(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9553{
9554 if (!*args[*cur_arg + 1]) {
9555 memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
9556 return ERR_ALERT | ERR_FATAL;
9557 }
9558
9559 free(newsrv->ssl_ctx.ciphers);
9560 newsrv->ssl_ctx.ciphers = strdup(args[*cur_arg + 1]);
9561 return 0;
9562}
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009563
Emmanuel Hocdet839af572019-05-14 16:27:35 +02009564#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009565/* parse the "ciphersuites" server keyword */
9566static int srv_parse_ciphersuites(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9567{
9568 if (!*args[*cur_arg + 1]) {
9569 memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
9570 return ERR_ALERT | ERR_FATAL;
9571 }
9572
9573 free(newsrv->ssl_ctx.ciphersuites);
9574 newsrv->ssl_ctx.ciphersuites = strdup(args[*cur_arg + 1]);
9575 return 0;
9576}
9577#endif
Willy Tarreau92faadf2012-10-10 23:04:25 +02009578
Emeric Brunef42d922012-10-11 16:11:36 +02009579/* parse the "crl-file" server keyword */
9580static int srv_parse_crl_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9581{
9582#ifndef X509_V_FLAG_CRL_CHECK
Tim Duesterhus93128532019-11-23 23:45:10 +01009583 memprintf(err, "'%s' : library does not support CRL verify", args[*cur_arg]);
Emeric Brunef42d922012-10-11 16:11:36 +02009584 return ERR_ALERT | ERR_FATAL;
9585#else
9586 if (!*args[*cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009587 memprintf(err, "'%s' : missing CRLfile path", args[*cur_arg]);
Emeric Brunef42d922012-10-11 16:11:36 +02009588 return ERR_ALERT | ERR_FATAL;
9589 }
9590
Willy Tarreauef934602016-12-22 23:12:01 +01009591 if ((*args[*cur_arg + 1] != '/') && global_ssl.ca_base)
9592 memprintf(&newsrv->ssl_ctx.crl_file, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02009593 else
9594 memprintf(&newsrv->ssl_ctx.crl_file, "%s", args[*cur_arg + 1]);
9595
Emmanuel Hocdetb270e812019-11-21 19:09:31 +01009596 if (!ssl_store_load_locations_file(newsrv->ssl_ctx.crl_file)) {
9597 memprintf(err, "'%s' : unable to load %s", args[*cur_arg], newsrv->ssl_ctx.crl_file);
9598 return ERR_ALERT | ERR_FATAL;
9599 }
Emeric Brunef42d922012-10-11 16:11:36 +02009600 return 0;
9601#endif
9602}
9603
Emeric Bruna7aa3092012-10-26 12:58:00 +02009604/* parse the "crt" server keyword */
9605static int srv_parse_crt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9606{
9607 if (!*args[*cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009608 memprintf(err, "'%s' : missing certificate file path", args[*cur_arg]);
Emeric Bruna7aa3092012-10-26 12:58:00 +02009609 return ERR_ALERT | ERR_FATAL;
9610 }
9611
Willy Tarreauef934602016-12-22 23:12:01 +01009612 if ((*args[*cur_arg + 1] != '/') && global_ssl.crt_base)
Christopher Fauletff3a41e2017-11-23 09:13:32 +01009613 memprintf(&newsrv->ssl_ctx.client_crt, "%s/%s", global_ssl.crt_base, args[*cur_arg + 1]);
Emeric Bruna7aa3092012-10-26 12:58:00 +02009614 else
9615 memprintf(&newsrv->ssl_ctx.client_crt, "%s", args[*cur_arg + 1]);
9616
9617 return 0;
9618}
Emeric Brunef42d922012-10-11 16:11:36 +02009619
Frédéric Lécaille340ae602017-03-13 10:38:04 +01009620/* parse the "no-check-ssl" server keyword */
9621static int srv_parse_no_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9622{
9623 newsrv->check.use_ssl = 0;
9624 free(newsrv->ssl_ctx.ciphers);
9625 newsrv->ssl_ctx.ciphers = NULL;
9626 newsrv->ssl_ctx.options &= ~global_ssl.connect_default_ssloptions;
9627 return 0;
9628}
9629
Frédéric Lécaillee892c4c2017-03-13 12:08:01 +01009630/* parse the "no-send-proxy-v2-ssl" server keyword */
9631static int srv_parse_no_send_proxy_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9632{
9633 newsrv->pp_opts &= ~SRV_PP_V2;
9634 newsrv->pp_opts &= ~SRV_PP_V2_SSL;
9635 return 0;
9636}
9637
9638/* parse the "no-send-proxy-v2-ssl-cn" server keyword */
9639static int srv_parse_no_send_proxy_cn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9640{
9641 newsrv->pp_opts &= ~SRV_PP_V2;
9642 newsrv->pp_opts &= ~SRV_PP_V2_SSL;
9643 newsrv->pp_opts &= ~SRV_PP_V2_SSL_CN;
9644 return 0;
9645}
9646
Frédéric Lécaillee381d762017-03-13 11:54:17 +01009647/* parse the "no-ssl" server keyword */
9648static int srv_parse_no_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9649{
9650 newsrv->use_ssl = 0;
9651 free(newsrv->ssl_ctx.ciphers);
9652 newsrv->ssl_ctx.ciphers = NULL;
9653 return 0;
9654}
9655
Olivier Houchard522eea72017-11-03 16:27:47 +01009656/* parse the "allow-0rtt" server keyword */
9657static int srv_parse_allow_0rtt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9658{
9659 newsrv->ssl_ctx.options |= SRV_SSL_O_EARLY_DATA;
9660 return 0;
9661}
9662
Willy Tarreau2a3fb1c2015-02-05 16:47:07 +01009663/* parse the "no-ssl-reuse" server keyword */
9664static int srv_parse_no_ssl_reuse(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9665{
9666 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_REUSE;
9667 return 0;
9668}
9669
Emeric Brunf9c5c472012-10-11 15:28:34 +02009670/* parse the "no-tls-tickets" server keyword */
9671static int srv_parse_no_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9672{
9673 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLS_TICKETS;
9674 return 0;
9675}
David Safb76832014-05-08 23:42:08 -04009676/* parse the "send-proxy-v2-ssl" server keyword */
9677static int srv_parse_send_proxy_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9678{
9679 newsrv->pp_opts |= SRV_PP_V2;
9680 newsrv->pp_opts |= SRV_PP_V2_SSL;
9681 return 0;
9682}
9683
9684/* parse the "send-proxy-v2-ssl-cn" server keyword */
9685static int srv_parse_send_proxy_cn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9686{
9687 newsrv->pp_opts |= SRV_PP_V2;
9688 newsrv->pp_opts |= SRV_PP_V2_SSL;
9689 newsrv->pp_opts |= SRV_PP_V2_SSL_CN;
9690 return 0;
9691}
Emeric Brunf9c5c472012-10-11 15:28:34 +02009692
Willy Tarreau732eac42015-07-09 11:40:25 +02009693/* parse the "sni" server keyword */
9694static int srv_parse_sni(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9695{
9696#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
9697 memprintf(err, "'%s' : the current SSL library doesn't support the SNI TLS extension", args[*cur_arg]);
9698 return ERR_ALERT | ERR_FATAL;
9699#else
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01009700 char *arg;
Willy Tarreau732eac42015-07-09 11:40:25 +02009701
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01009702 arg = args[*cur_arg + 1];
9703 if (!*arg) {
Willy Tarreau732eac42015-07-09 11:40:25 +02009704 memprintf(err, "'%s' : missing sni expression", args[*cur_arg]);
9705 return ERR_ALERT | ERR_FATAL;
9706 }
9707
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01009708 free(newsrv->sni_expr);
9709 newsrv->sni_expr = strdup(arg);
Willy Tarreau732eac42015-07-09 11:40:25 +02009710
Willy Tarreau732eac42015-07-09 11:40:25 +02009711 return 0;
9712#endif
9713}
9714
Willy Tarreau92faadf2012-10-10 23:04:25 +02009715/* parse the "ssl" server keyword */
9716static int srv_parse_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9717{
9718 newsrv->use_ssl = 1;
Willy Tarreauef934602016-12-22 23:12:01 +01009719 if (global_ssl.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
9720 newsrv->ssl_ctx.ciphers = strdup(global_ssl.connect_default_ciphers);
Emmanuel Hocdet839af572019-05-14 16:27:35 +02009721#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009722 if (global_ssl.connect_default_ciphersuites && !newsrv->ssl_ctx.ciphersuites)
9723 newsrv->ssl_ctx.ciphersuites = strdup(global_ssl.connect_default_ciphersuites);
9724#endif
Willy Tarreau92faadf2012-10-10 23:04:25 +02009725 return 0;
9726}
9727
Frédéric Lécaille2cfcdbe2017-03-13 11:32:20 +01009728/* parse the "ssl-reuse" server keyword */
9729static int srv_parse_ssl_reuse(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9730{
9731 newsrv->ssl_ctx.options &= ~SRV_SSL_O_NO_REUSE;
9732 return 0;
9733}
9734
Frédéric Lécaille2cfcdbe2017-03-13 11:32:20 +01009735/* parse the "tls-tickets" server keyword */
9736static int srv_parse_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9737{
9738 newsrv->ssl_ctx.options &= ~SRV_SSL_O_NO_TLS_TICKETS;
9739 return 0;
9740}
9741
Emeric Brunef42d922012-10-11 16:11:36 +02009742/* parse the "verify" server keyword */
9743static int srv_parse_verify(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9744{
9745 if (!*args[*cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009746 memprintf(err, "'%s' : missing verify method", args[*cur_arg]);
Emeric Brunef42d922012-10-11 16:11:36 +02009747 return ERR_ALERT | ERR_FATAL;
9748 }
9749
9750 if (strcmp(args[*cur_arg + 1], "none") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01009751 newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_NONE;
Emeric Brunef42d922012-10-11 16:11:36 +02009752 else if (strcmp(args[*cur_arg + 1], "required") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01009753 newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_REQUIRED;
Emeric Brunef42d922012-10-11 16:11:36 +02009754 else {
Tim Duesterhus93128532019-11-23 23:45:10 +01009755 memprintf(err, "'%s' : unknown verify method '%s', only 'none' and 'required' are supported\n",
9756 args[*cur_arg], args[*cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02009757 return ERR_ALERT | ERR_FATAL;
9758 }
9759
Evan Broderbe554312013-06-27 00:05:25 -07009760 return 0;
9761}
9762
9763/* parse the "verifyhost" server keyword */
9764static int srv_parse_verifyhost(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9765{
9766 if (!*args[*cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009767 memprintf(err, "'%s' : missing hostname to verify against", args[*cur_arg]);
Evan Broderbe554312013-06-27 00:05:25 -07009768 return ERR_ALERT | ERR_FATAL;
9769 }
9770
Frédéric Lécaille273f3212017-03-13 15:52:01 +01009771 free(newsrv->ssl_ctx.verify_host);
Evan Broderbe554312013-06-27 00:05:25 -07009772 newsrv->ssl_ctx.verify_host = strdup(args[*cur_arg + 1]);
9773
Emeric Brunef42d922012-10-11 16:11:36 +02009774 return 0;
9775}
9776
Emeric Brun2c86cbf2014-10-30 15:56:50 +01009777/* parse the "ssl-default-bind-options" keyword in global section */
9778static int ssl_parse_default_bind_options(char **args, int section_type, struct proxy *curpx,
9779 struct proxy *defpx, const char *file, int line,
9780 char **err) {
9781 int i = 1;
9782
9783 if (*(args[i]) == 0) {
9784 memprintf(err, "global statement '%s' expects an option as an argument.", args[0]);
9785 return -1;
9786 }
9787 while (*(args[i])) {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02009788 if (!strcmp(args[i], "no-tls-tickets"))
Willy Tarreauef934602016-12-22 23:12:01 +01009789 global_ssl.listen_default_ssloptions |= BC_SSL_O_NO_TLS_TICKETS;
Lukas Tribus53ae85c2017-05-04 15:45:40 +00009790 else if (!strcmp(args[i], "prefer-client-ciphers"))
9791 global_ssl.listen_default_ssloptions |= BC_SSL_O_PREF_CLIE_CIPH;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02009792 else if (!strcmp(args[i], "ssl-min-ver") || !strcmp(args[i], "ssl-max-ver")) {
9793 if (!parse_tls_method_minmax(args, i, &global_ssl.listen_default_sslmethods, err))
9794 i++;
9795 else {
9796 memprintf(err, "%s on global statement '%s'.", *err, args[0]);
9797 return -1;
9798 }
9799 }
9800 else if (parse_tls_method_options(args[i], &global_ssl.listen_default_sslmethods, err)) {
Emeric Brun2c86cbf2014-10-30 15:56:50 +01009801 memprintf(err, "unknown option '%s' on global statement '%s'.", args[i], args[0]);
9802 return -1;
9803 }
9804 i++;
9805 }
9806 return 0;
9807}
9808
9809/* parse the "ssl-default-server-options" keyword in global section */
9810static int ssl_parse_default_server_options(char **args, int section_type, struct proxy *curpx,
9811 struct proxy *defpx, const char *file, int line,
9812 char **err) {
9813 int i = 1;
9814
9815 if (*(args[i]) == 0) {
9816 memprintf(err, "global statement '%s' expects an option as an argument.", args[0]);
9817 return -1;
9818 }
9819 while (*(args[i])) {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02009820 if (!strcmp(args[i], "no-tls-tickets"))
Willy Tarreauef934602016-12-22 23:12:01 +01009821 global_ssl.connect_default_ssloptions |= SRV_SSL_O_NO_TLS_TICKETS;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02009822 else if (!strcmp(args[i], "ssl-min-ver") || !strcmp(args[i], "ssl-max-ver")) {
9823 if (!parse_tls_method_minmax(args, i, &global_ssl.connect_default_sslmethods, err))
9824 i++;
9825 else {
9826 memprintf(err, "%s on global statement '%s'.", *err, args[0]);
9827 return -1;
9828 }
9829 }
9830 else if (parse_tls_method_options(args[i], &global_ssl.connect_default_sslmethods, err)) {
Emeric Brun2c86cbf2014-10-30 15:56:50 +01009831 memprintf(err, "unknown option '%s' on global statement '%s'.", args[i], args[0]);
9832 return -1;
9833 }
9834 i++;
9835 }
9836 return 0;
9837}
9838
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01009839/* parse the "ca-base" / "crt-base" keywords in global section.
9840 * Returns <0 on alert, >0 on warning, 0 on success.
9841 */
9842static int ssl_parse_global_ca_crt_base(char **args, int section_type, struct proxy *curpx,
9843 struct proxy *defpx, const char *file, int line,
9844 char **err)
9845{
9846 char **target;
9847
Willy Tarreauef934602016-12-22 23:12:01 +01009848 target = (args[0][1] == 'a') ? &global_ssl.ca_base : &global_ssl.crt_base;
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01009849
9850 if (too_many_args(1, args, err, NULL))
9851 return -1;
9852
9853 if (*target) {
9854 memprintf(err, "'%s' already specified.", args[0]);
9855 return -1;
9856 }
9857
9858 if (*(args[1]) == 0) {
9859 memprintf(err, "global statement '%s' expects a directory path as an argument.", args[0]);
9860 return -1;
9861 }
9862 *target = strdup(args[1]);
9863 return 0;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00009864}
9865
Emmanuel Hocdet70df7bf2019-01-04 11:08:20 +01009866/* "issuers-chain-path" load chain certificate in global */
9867static int ssl_load_global_issuer_from_BIO(BIO *in, char *fp, char **err)
9868{
9869 X509 *ca;
9870 X509_NAME *name = NULL;
9871 ASN1_OCTET_STRING *skid = NULL;
9872 STACK_OF(X509) *chain = NULL;
9873 struct issuer_chain *issuer;
9874 struct eb64_node *node;
9875 char *path;
9876 u64 key;
9877 int ret = 0;
9878
9879 while ((ca = PEM_read_bio_X509(in, NULL, NULL, NULL))) {
9880 if (chain == NULL) {
9881 chain = sk_X509_new_null();
9882 skid = X509_get_ext_d2i(ca, NID_subject_key_identifier, NULL, NULL);
9883 name = X509_get_subject_name(ca);
9884 }
9885 if (!sk_X509_push(chain, ca)) {
9886 X509_free(ca);
9887 goto end;
9888 }
9889 }
9890 if (!chain) {
9891 memprintf(err, "unable to load issuers-chain %s : pem certificate not found.\n", fp);
9892 goto end;
9893 }
9894 if (!skid) {
9895 memprintf(err, "unable to load issuers-chain %s : SubjectKeyIdentifier not found.\n", fp);
9896 goto end;
9897 }
9898 if (!name) {
9899 memprintf(err, "unable to load issuers-chain %s : SubjectName not found.\n", fp);
9900 goto end;
9901 }
9902 key = XXH64(ASN1_STRING_get0_data(skid), ASN1_STRING_length(skid), 0);
William Lallemande0f3fd52020-02-25 14:53:06 +01009903 for (node = eb64_lookup(&cert_issuer_tree, key); node; node = eb64_next(node)) {
Emmanuel Hocdet70df7bf2019-01-04 11:08:20 +01009904 issuer = container_of(node, typeof(*issuer), node);
9905 if (!X509_NAME_cmp(name, X509_get_subject_name(sk_X509_value(issuer->chain, 0)))) {
9906 memprintf(err, "duplicate issuers-chain %s: %s already in store\n", fp, issuer->path);
9907 goto end;
9908 }
9909 }
9910 issuer = calloc(1, sizeof *issuer);
9911 path = strdup(fp);
9912 if (!issuer || !path) {
9913 free(issuer);
9914 free(path);
9915 goto end;
9916 }
9917 issuer->node.key = key;
9918 issuer->path = path;
9919 issuer->chain = chain;
9920 chain = NULL;
William Lallemande0f3fd52020-02-25 14:53:06 +01009921 eb64_insert(&cert_issuer_tree, &issuer->node);
Emmanuel Hocdet70df7bf2019-01-04 11:08:20 +01009922 ret = 1;
9923 end:
9924 if (skid)
9925 ASN1_OCTET_STRING_free(skid);
9926 if (chain)
9927 sk_X509_pop_free(chain, X509_free);
9928 return ret;
9929}
9930
Emmanuel Hocdet75a7aa12020-02-18 15:19:24 +01009931static struct issuer_chain* ssl_get_issuer_chain(X509 *cert)
9932{
9933 AUTHORITY_KEYID *akid;
9934 struct issuer_chain *issuer = NULL;
9935
9936 akid = X509_get_ext_d2i(cert, NID_authority_key_identifier, NULL, NULL);
9937 if (akid) {
9938 struct eb64_node *node;
9939 u64 hk;
9940 hk = XXH64(ASN1_STRING_get0_data(akid->keyid), ASN1_STRING_length(akid->keyid), 0);
9941 for (node = eb64_lookup(&cert_issuer_tree, hk); node; node = eb64_next(node)) {
9942 struct issuer_chain *ti = container_of(node, typeof(*issuer), node);
9943 if (X509_check_issued(sk_X509_value(ti->chain, 0), cert) == X509_V_OK) {
9944 issuer = ti;
9945 break;
9946 }
9947 }
9948 AUTHORITY_KEYID_free(akid);
9949 }
9950 return issuer;
9951}
9952
Emmanuel Hocdet70df7bf2019-01-04 11:08:20 +01009953static void ssl_free_global_issuers(void)
9954{
9955 struct eb64_node *node, *back;
9956 struct issuer_chain *issuer;
9957
William Lallemande0f3fd52020-02-25 14:53:06 +01009958 node = eb64_first(&cert_issuer_tree);
Emmanuel Hocdet70df7bf2019-01-04 11:08:20 +01009959 while (node) {
9960 issuer = container_of(node, typeof(*issuer), node);
9961 back = eb64_next(node);
9962 eb64_delete(node);
9963 free(issuer->path);
9964 sk_X509_pop_free(issuer->chain, X509_free);
9965 free(issuer);
9966 node = back;
9967 }
9968}
9969
9970static int ssl_load_global_issuers_from_path(char **args, int section_type, struct proxy *curpx,
9971 struct proxy *defpx, const char *file, int line,
9972 char **err)
9973{
9974 char *path;
9975 struct dirent **de_list;
9976 int i, n;
9977 struct stat buf;
9978 char *end;
9979 char fp[MAXPATHLEN+1];
9980
9981 if (too_many_args(1, args, err, NULL))
9982 return -1;
9983
9984 path = args[1];
9985 if (*path == 0 || stat(path, &buf)) {
9986 memprintf(err, "%sglobal statement '%s' expects a directory path as an argument.\n",
9987 err && *err ? *err : "", args[0]);
9988 return -1;
9989 }
9990 if (S_ISDIR(buf.st_mode) == 0) {
9991 memprintf(err, "%sglobal statement '%s': %s is not a directory.\n",
9992 err && *err ? *err : "", args[0], path);
9993 return -1;
9994 }
9995
9996 /* strip trailing slashes, including first one */
9997 for (end = path + strlen(path) - 1; end >= path && *end == '/'; end--)
9998 *end = 0;
9999 /* path already parsed? */
10000 if (global_ssl.issuers_chain_path && strcmp(global_ssl.issuers_chain_path, path) == 0)
10001 return 0;
10002 /* overwrite old issuers_chain_path */
10003 free(global_ssl.issuers_chain_path);
10004 global_ssl.issuers_chain_path = strdup(path);
10005 ssl_free_global_issuers();
10006
10007 n = scandir(path, &de_list, 0, alphasort);
10008 if (n < 0) {
10009 memprintf(err, "%sglobal statement '%s': unable to scan directory '%s' : %s.\n",
10010 err && *err ? *err : "", args[0], path, strerror(errno));
10011 return -1;
10012 }
10013 for (i = 0; i < n; i++) {
10014 struct dirent *de = de_list[i];
10015 BIO *in = NULL;
10016 char *warn = NULL;
10017
10018 snprintf(fp, sizeof(fp), "%s/%s", path, de->d_name);
10019 free(de);
10020 if (stat(fp, &buf) != 0) {
10021 ha_warning("unable to stat certificate from file '%s' : %s.\n", fp, strerror(errno));
10022 goto next;
10023 }
10024 if (!S_ISREG(buf.st_mode))
10025 goto next;
10026
10027 in = BIO_new(BIO_s_file());
10028 if (in == NULL)
10029 goto next;
10030 if (BIO_read_filename(in, fp) <= 0)
10031 goto next;
10032 ssl_load_global_issuer_from_BIO(in, fp, &warn);
10033 if (warn) {
Tim Duesterhuse8aa5f22020-02-19 11:41:13 +010010034 ha_warning("%s", warn);
Emmanuel Hocdet70df7bf2019-01-04 11:08:20 +010010035 free(warn);
10036 warn = NULL;
10037 }
10038 next:
10039 if (in)
10040 BIO_free(in);
10041 }
10042 free(de_list);
10043
10044 return 0;
10045}
10046
Grant Zhangfa6c7ee2017-01-14 01:42:15 +000010047/* parse the "ssl-mode-async" keyword in global section.
10048 * Returns <0 on alert, >0 on warning, 0 on success.
10049 */
10050static int ssl_parse_global_ssl_async(char **args, int section_type, struct proxy *curpx,
10051 struct proxy *defpx, const char *file, int line,
10052 char **err)
10053{
Willy Tarreau5db847a2019-05-09 14:13:35 +020010054#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +000010055 global_ssl.async = 1;
Emeric Brunece0c332017-12-06 13:51:49 +010010056 global.ssl_used_async_engines = nb_engines;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +000010057 return 0;
10058#else
10059 memprintf(err, "'%s': openssl library does not support async mode", args[0]);
10060 return -1;
10061#endif
10062}
10063
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020010064#ifndef OPENSSL_NO_ENGINE
Grant Zhangfa6c7ee2017-01-14 01:42:15 +000010065static int ssl_check_async_engine_count(void) {
10066 int err_code = 0;
10067
Emeric Brun3854e012017-05-17 20:42:48 +020010068 if (global_ssl.async && (openssl_engines_initialized > 32)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +010010069 ha_alert("ssl-mode-async only supports a maximum of 32 engines.\n");
Grant Zhangfa6c7ee2017-01-14 01:42:15 +000010070 err_code = ERR_ABORT;
10071 }
10072 return err_code;
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +010010073}
10074
Grant Zhang872f9c22017-01-21 01:10:18 +000010075/* parse the "ssl-engine" keyword in global section.
10076 * Returns <0 on alert, >0 on warning, 0 on success.
10077 */
10078static int ssl_parse_global_ssl_engine(char **args, int section_type, struct proxy *curpx,
10079 struct proxy *defpx, const char *file, int line,
10080 char **err)
10081{
10082 char *algo;
10083 int ret = -1;
10084
10085 if (*(args[1]) == 0) {
10086 memprintf(err, "global statement '%s' expects a valid engine name as an argument.", args[0]);
10087 return ret;
10088 }
10089
10090 if (*(args[2]) == 0) {
10091 /* if no list of algorithms is given, it defaults to ALL */
10092 algo = strdup("ALL");
10093 goto add_engine;
10094 }
10095
10096 /* otherwise the expected format is ssl-engine <engine_name> algo <list of algo> */
10097 if (strcmp(args[2], "algo") != 0) {
10098 memprintf(err, "global statement '%s' expects to have algo keyword.", args[0]);
10099 return ret;
10100 }
10101
10102 if (*(args[3]) == 0) {
10103 memprintf(err, "global statement '%s' expects algorithm names as an argument.", args[0]);
10104 return ret;
10105 }
10106 algo = strdup(args[3]);
10107
10108add_engine:
10109 if (ssl_init_single_engine(args[1], algo)==0) {
10110 openssl_engines_initialized++;
10111 ret = 0;
10112 }
10113 free(algo);
10114 return ret;
10115}
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020010116#endif
Grant Zhang872f9c22017-01-21 01:10:18 +000010117
Willy Tarreauf22e9682016-12-21 23:23:19 +010010118/* parse the "ssl-default-bind-ciphers" / "ssl-default-server-ciphers" keywords
10119 * in global section. Returns <0 on alert, >0 on warning, 0 on success.
10120 */
10121static int ssl_parse_global_ciphers(char **args, int section_type, struct proxy *curpx,
10122 struct proxy *defpx, const char *file, int line,
10123 char **err)
10124{
10125 char **target;
10126
Willy Tarreauef934602016-12-22 23:12:01 +010010127 target = (args[0][12] == 'b') ? &global_ssl.listen_default_ciphers : &global_ssl.connect_default_ciphers;
Willy Tarreauf22e9682016-12-21 23:23:19 +010010128
10129 if (too_many_args(1, args, err, NULL))
10130 return -1;
10131
10132 if (*(args[1]) == 0) {
10133 memprintf(err, "global statement '%s' expects a cipher suite as an argument.", args[0]);
10134 return -1;
10135 }
10136
10137 free(*target);
10138 *target = strdup(args[1]);
10139 return 0;
10140}
Dirkjan Bussink415150f2018-09-14 11:14:21 +020010141
Emmanuel Hocdet839af572019-05-14 16:27:35 +020010142#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +020010143/* parse the "ssl-default-bind-ciphersuites" / "ssl-default-server-ciphersuites" keywords
10144 * in global section. Returns <0 on alert, >0 on warning, 0 on success.
10145 */
10146static int ssl_parse_global_ciphersuites(char **args, int section_type, struct proxy *curpx,
10147 struct proxy *defpx, const char *file, int line,
10148 char **err)
10149{
10150 char **target;
10151
10152 target = (args[0][12] == 'b') ? &global_ssl.listen_default_ciphersuites : &global_ssl.connect_default_ciphersuites;
10153
10154 if (too_many_args(1, args, err, NULL))
10155 return -1;
10156
10157 if (*(args[1]) == 0) {
10158 memprintf(err, "global statement '%s' expects a cipher suite as an argument.", args[0]);
10159 return -1;
10160 }
10161
10162 free(*target);
10163 *target = strdup(args[1]);
10164 return 0;
10165}
10166#endif
Willy Tarreauf22e9682016-12-21 23:23:19 +010010167
Willy Tarreau9ceda382016-12-21 23:13:03 +010010168/* parse various global tune.ssl settings consisting in positive integers.
10169 * Returns <0 on alert, >0 on warning, 0 on success.
10170 */
10171static int ssl_parse_global_int(char **args, int section_type, struct proxy *curpx,
10172 struct proxy *defpx, const char *file, int line,
10173 char **err)
10174{
10175 int *target;
10176
10177 if (strcmp(args[0], "tune.ssl.cachesize") == 0)
10178 target = &global.tune.sslcachesize;
10179 else if (strcmp(args[0], "tune.ssl.maxrecord") == 0)
Willy Tarreauef934602016-12-22 23:12:01 +010010180 target = (int *)&global_ssl.max_record;
Willy Tarreau9ceda382016-12-21 23:13:03 +010010181 else if (strcmp(args[0], "tune.ssl.ssl-ctx-cache-size") == 0)
Willy Tarreauef934602016-12-22 23:12:01 +010010182 target = &global_ssl.ctx_cache;
Willy Tarreau0bea58d2016-12-21 23:17:25 +010010183 else if (strcmp(args[0], "maxsslconn") == 0)
10184 target = &global.maxsslconn;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +010010185 else if (strcmp(args[0], "tune.ssl.capture-cipherlist-size") == 0)
10186 target = &global_ssl.capture_cipherlist;
Willy Tarreau9ceda382016-12-21 23:13:03 +010010187 else {
10188 memprintf(err, "'%s' keyword not unhandled (please report this bug).", args[0]);
10189 return -1;
10190 }
10191
10192 if (too_many_args(1, args, err, NULL))
10193 return -1;
10194
10195 if (*(args[1]) == 0) {
10196 memprintf(err, "'%s' expects an integer argument.", args[0]);
10197 return -1;
10198 }
10199
10200 *target = atoi(args[1]);
10201 if (*target < 0) {
10202 memprintf(err, "'%s' expects a positive numeric value.", args[0]);
10203 return -1;
10204 }
10205 return 0;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +010010206}
10207
10208static int ssl_parse_global_capture_cipherlist(char **args, int section_type, struct proxy *curpx,
10209 struct proxy *defpx, const char *file, int line,
10210 char **err)
10211{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +010010212 int ret;
10213
10214 ret = ssl_parse_global_int(args, section_type, curpx, defpx, file, line, err);
10215 if (ret != 0)
10216 return ret;
10217
Willy Tarreaubafbe012017-11-24 17:34:44 +010010218 if (pool_head_ssl_capture) {
Thierry FOURNIER5bf77322017-02-25 12:45:22 +010010219 memprintf(err, "'%s' is already configured.", args[0]);
10220 return -1;
10221 }
10222
Willy Tarreaubafbe012017-11-24 17:34:44 +010010223 pool_head_ssl_capture = create_pool("ssl-capture", sizeof(struct ssl_capture) + global_ssl.capture_cipherlist, MEM_F_SHARED);
10224 if (!pool_head_ssl_capture) {
Thierry FOURNIER5bf77322017-02-25 12:45:22 +010010225 memprintf(err, "Out of memory error.");
10226 return -1;
10227 }
10228 return 0;
Willy Tarreau9ceda382016-12-21 23:13:03 +010010229}
10230
10231/* parse "ssl.force-private-cache".
10232 * Returns <0 on alert, >0 on warning, 0 on success.
10233 */
10234static int ssl_parse_global_private_cache(char **args, int section_type, struct proxy *curpx,
10235 struct proxy *defpx, const char *file, int line,
10236 char **err)
10237{
10238 if (too_many_args(0, args, err, NULL))
10239 return -1;
10240
Willy Tarreauef934602016-12-22 23:12:01 +010010241 global_ssl.private_cache = 1;
Willy Tarreau9ceda382016-12-21 23:13:03 +010010242 return 0;
10243}
10244
10245/* parse "ssl.lifetime".
10246 * Returns <0 on alert, >0 on warning, 0 on success.
10247 */
10248static int ssl_parse_global_lifetime(char **args, int section_type, struct proxy *curpx,
10249 struct proxy *defpx, const char *file, int line,
10250 char **err)
10251{
10252 const char *res;
10253
10254 if (too_many_args(1, args, err, NULL))
10255 return -1;
10256
10257 if (*(args[1]) == 0) {
10258 memprintf(err, "'%s' expects ssl sessions <lifetime> in seconds as argument.", args[0]);
10259 return -1;
10260 }
10261
Willy Tarreauef934602016-12-22 23:12:01 +010010262 res = parse_time_err(args[1], &global_ssl.life_time, TIME_UNIT_S);
Willy Tarreau9faebe32019-06-07 19:00:37 +020010263 if (res == PARSE_TIME_OVER) {
10264 memprintf(err, "timer overflow in argument '%s' to <%s> (maximum value is 2147483647 s or ~68 years).",
10265 args[1], args[0]);
10266 return -1;
10267 }
10268 else if (res == PARSE_TIME_UNDER) {
10269 memprintf(err, "timer underflow in argument '%s' to <%s> (minimum non-null value is 1 s).",
10270 args[1], args[0]);
10271 return -1;
10272 }
10273 else if (res) {
Willy Tarreau9ceda382016-12-21 23:13:03 +010010274 memprintf(err, "unexpected character '%c' in argument to <%s>.", *res, args[0]);
10275 return -1;
10276 }
10277 return 0;
10278}
10279
10280#ifndef OPENSSL_NO_DH
Willy Tarreau14e36a12016-12-21 23:28:13 +010010281/* parse "ssl-dh-param-file".
10282 * Returns <0 on alert, >0 on warning, 0 on success.
10283 */
10284static int ssl_parse_global_dh_param_file(char **args, int section_type, struct proxy *curpx,
10285 struct proxy *defpx, const char *file, int line,
10286 char **err)
10287{
10288 if (too_many_args(1, args, err, NULL))
10289 return -1;
10290
10291 if (*(args[1]) == 0) {
10292 memprintf(err, "'%s' expects a file path as an argument.", args[0]);
10293 return -1;
10294 }
10295
10296 if (ssl_sock_load_global_dh_param_from_file(args[1])) {
10297 memprintf(err, "'%s': unable to load DH parameters from file <%s>.", args[0], args[1]);
10298 return -1;
10299 }
10300 return 0;
10301}
10302
Willy Tarreau9ceda382016-12-21 23:13:03 +010010303/* parse "ssl.default-dh-param".
10304 * Returns <0 on alert, >0 on warning, 0 on success.
10305 */
10306static int ssl_parse_global_default_dh(char **args, int section_type, struct proxy *curpx,
10307 struct proxy *defpx, const char *file, int line,
10308 char **err)
10309{
10310 if (too_many_args(1, args, err, NULL))
10311 return -1;
10312
10313 if (*(args[1]) == 0) {
10314 memprintf(err, "'%s' expects an integer argument.", args[0]);
10315 return -1;
10316 }
10317
Willy Tarreauef934602016-12-22 23:12:01 +010010318 global_ssl.default_dh_param = atoi(args[1]);
10319 if (global_ssl.default_dh_param < 1024) {
Willy Tarreau9ceda382016-12-21 23:13:03 +010010320 memprintf(err, "'%s' expects a value >= 1024.", args[0]);
10321 return -1;
10322 }
10323 return 0;
10324}
10325#endif
10326
William Lallemand3af48e72020-02-03 17:15:52 +010010327
10328/*
10329 * parse "ssl-load-extra-files".
10330 * multiple arguments are allowed: "bundle", "sctl", "ocsp", "issuer", "all", "none"
10331 */
10332static int ssl_parse_global_extra_files(char **args, int section_type, struct proxy *curpx,
10333 struct proxy *defpx, const char *file, int line,
10334 char **err)
10335{
10336 int i;
10337 int gf = SSL_GF_NONE;
10338
10339 if (*(args[1]) == 0)
10340 goto err_arg;
10341
10342 for (i = 1; *args[i]; i++) {
10343
10344 if (!strcmp("bundle", args[i])) {
10345 gf |= SSL_GF_BUNDLE;
10346
10347 } else if (!strcmp("sctl", args[i])) {
10348 gf |= SSL_GF_SCTL;
10349
10350 } else if (!strcmp("ocsp", args[i])){
10351 gf |= SSL_GF_OCSP;
10352
10353 } else if (!strcmp("issuer", args[i])){
10354 gf |= SSL_GF_OCSP_ISSUER;
10355
William Lallemand4c5adbf2020-02-24 14:23:22 +010010356 } else if (!strcmp("key", args[i])) {
10357 gf |= SSL_GF_KEY;
10358
William Lallemand3af48e72020-02-03 17:15:52 +010010359 } else if (!strcmp("none", args[i])) {
10360 if (gf != SSL_GF_NONE)
10361 goto err_alone;
10362 gf = SSL_GF_NONE;
10363 i++;
10364 break;
10365
10366 } else if (!strcmp("all", args[i])) {
10367 if (gf != SSL_GF_NONE)
10368 goto err_alone;
10369 gf = SSL_GF_ALL;
10370 i++;
10371 break;
10372 } else {
10373 goto err_arg;
10374 }
10375 }
10376 /* break from loop but there are still arguments */
10377 if (*args[i])
10378 goto err_alone;
10379
10380 global_ssl.extra_files = gf;
10381
10382 return 0;
10383
10384err_alone:
10385 memprintf(err, "'%s' 'none' and 'all' can be only used alone", args[0]);
10386 return -1;
10387
10388err_arg:
10389 memprintf(err, "'%s' expects one or multiple arguments (none, all, bundle, sctl, ocsp, issuer).", args[0]);
10390 return -1;
10391}
10392
Willy Tarreau9ceda382016-12-21 23:13:03 +010010393
William Lallemand32af2032016-10-29 18:09:35 +020010394/* This function is used with TLS ticket keys management. It permits to browse
10395 * each reference. The variable <getnext> must contain the current node,
10396 * <end> point to the root node.
10397 */
10398#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
10399static inline
10400struct tls_keys_ref *tlskeys_list_get_next(struct tls_keys_ref *getnext, struct list *end)
10401{
10402 struct tls_keys_ref *ref = getnext;
10403
10404 while (1) {
10405
10406 /* Get next list entry. */
10407 ref = LIST_NEXT(&ref->list, struct tls_keys_ref *, list);
10408
10409 /* If the entry is the last of the list, return NULL. */
10410 if (&ref->list == end)
10411 return NULL;
10412
10413 return ref;
10414 }
10415}
10416
10417static inline
10418struct tls_keys_ref *tlskeys_ref_lookup_ref(const char *reference)
10419{
10420 int id;
10421 char *error;
10422
10423 /* If the reference starts by a '#', this is numeric id. */
10424 if (reference[0] == '#') {
10425 /* Try to convert the numeric id. If the conversion fails, the lookup fails. */
10426 id = strtol(reference + 1, &error, 10);
10427 if (*error != '\0')
10428 return NULL;
10429
10430 /* Perform the unique id lookup. */
10431 return tlskeys_ref_lookupid(id);
10432 }
10433
10434 /* Perform the string lookup. */
10435 return tlskeys_ref_lookup(reference);
10436}
10437#endif
10438
10439
10440#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
10441
10442static int cli_io_handler_tlskeys_files(struct appctx *appctx);
10443
10444static inline int cli_io_handler_tlskeys_entries(struct appctx *appctx) {
10445 return cli_io_handler_tlskeys_files(appctx);
10446}
10447
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010448/* dumps all tls keys. Relies on cli.i0 (non-null = only list file names), cli.i1
10449 * (next index to be dumped), and cli.p0 (next key reference).
10450 */
William Lallemand32af2032016-10-29 18:09:35 +020010451static int cli_io_handler_tlskeys_files(struct appctx *appctx) {
10452
10453 struct stream_interface *si = appctx->owner;
10454
10455 switch (appctx->st2) {
10456 case STAT_ST_INIT:
10457 /* Display the column headers. If the message cannot be sent,
Joseph Herlant017b3da2018-11-15 09:07:59 -080010458 * quit the function with returning 0. The function is called
William Lallemand32af2032016-10-29 18:09:35 +020010459 * later and restart at the state "STAT_ST_INIT".
10460 */
10461 chunk_reset(&trash);
10462
10463 if (appctx->io_handler == cli_io_handler_tlskeys_entries)
10464 chunk_appendf(&trash, "# id secret\n");
10465 else
10466 chunk_appendf(&trash, "# id (file)\n");
10467
Willy Tarreau06d80a92017-10-19 14:32:15 +020010468 if (ci_putchk(si_ic(si), &trash) == -1) {
Willy Tarreaudb398432018-11-15 11:08:52 +010010469 si_rx_room_blk(si);
William Lallemand32af2032016-10-29 18:09:35 +020010470 return 0;
10471 }
10472
William Lallemand32af2032016-10-29 18:09:35 +020010473 /* Now, we start the browsing of the references lists.
10474 * Note that the following call to LIST_ELEM return bad pointer. The only
10475 * available field of this pointer is <list>. It is used with the function
10476 * tlskeys_list_get_next() for retruning the first available entry
10477 */
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010478 if (appctx->ctx.cli.p0 == NULL) {
10479 appctx->ctx.cli.p0 = LIST_ELEM(&tlskeys_reference, struct tls_keys_ref *, list);
10480 appctx->ctx.cli.p0 = tlskeys_list_get_next(appctx->ctx.cli.p0, &tlskeys_reference);
William Lallemand32af2032016-10-29 18:09:35 +020010481 }
10482
10483 appctx->st2 = STAT_ST_LIST;
10484 /* fall through */
10485
10486 case STAT_ST_LIST:
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010487 while (appctx->ctx.cli.p0) {
10488 struct tls_keys_ref *ref = appctx->ctx.cli.p0;
William Lallemand32af2032016-10-29 18:09:35 +020010489
10490 chunk_reset(&trash);
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010491 if (appctx->io_handler == cli_io_handler_tlskeys_entries && appctx->ctx.cli.i1 == 0)
William Lallemand32af2032016-10-29 18:09:35 +020010492 chunk_appendf(&trash, "# ");
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010493
10494 if (appctx->ctx.cli.i1 == 0)
10495 chunk_appendf(&trash, "%d (%s)\n", ref->unique_id, ref->filename);
10496
William Lallemand32af2032016-10-29 18:09:35 +020010497 if (appctx->io_handler == cli_io_handler_tlskeys_entries) {
Christopher Faulet16f45c82018-02-16 11:23:49 +010010498 int head;
10499
10500 HA_RWLOCK_RDLOCK(TLSKEYS_REF_LOCK, &ref->lock);
10501 head = ref->tls_ticket_enc_index;
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010502 while (appctx->ctx.cli.i1 < TLS_TICKETS_NO) {
Willy Tarreau83061a82018-07-13 11:56:34 +020010503 struct buffer *t2 = get_trash_chunk();
William Lallemand32af2032016-10-29 18:09:35 +020010504
10505 chunk_reset(t2);
10506 /* should never fail here because we dump only a key in the t2 buffer */
Emeric Brun9e754772019-01-10 17:51:55 +010010507 if (ref->key_size_bits == 128) {
10508 t2->data = a2base64((char *)(ref->tlskeys + (head + 2 + appctx->ctx.cli.i1) % TLS_TICKETS_NO),
10509 sizeof(struct tls_sess_key_128),
10510 t2->area, t2->size);
10511 chunk_appendf(&trash, "%d.%d %s\n", ref->unique_id, appctx->ctx.cli.i1,
10512 t2->area);
10513 }
10514 else if (ref->key_size_bits == 256) {
10515 t2->data = a2base64((char *)(ref->tlskeys + (head + 2 + appctx->ctx.cli.i1) % TLS_TICKETS_NO),
10516 sizeof(struct tls_sess_key_256),
10517 t2->area, t2->size);
10518 chunk_appendf(&trash, "%d.%d %s\n", ref->unique_id, appctx->ctx.cli.i1,
10519 t2->area);
10520 }
10521 else {
10522 /* This case should never happen */
10523 chunk_appendf(&trash, "%d.%d <unknown>\n", ref->unique_id, appctx->ctx.cli.i1);
10524 }
William Lallemand32af2032016-10-29 18:09:35 +020010525
Willy Tarreau06d80a92017-10-19 14:32:15 +020010526 if (ci_putchk(si_ic(si), &trash) == -1) {
William Lallemand32af2032016-10-29 18:09:35 +020010527 /* let's try again later from this stream. We add ourselves into
10528 * this stream's users so that it can remove us upon termination.
10529 */
Christopher Faulet16f45c82018-02-16 11:23:49 +010010530 HA_RWLOCK_RDUNLOCK(TLSKEYS_REF_LOCK, &ref->lock);
Willy Tarreaudb398432018-11-15 11:08:52 +010010531 si_rx_room_blk(si);
William Lallemand32af2032016-10-29 18:09:35 +020010532 return 0;
10533 }
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010534 appctx->ctx.cli.i1++;
William Lallemand32af2032016-10-29 18:09:35 +020010535 }
Christopher Faulet16f45c82018-02-16 11:23:49 +010010536 HA_RWLOCK_RDUNLOCK(TLSKEYS_REF_LOCK, &ref->lock);
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010537 appctx->ctx.cli.i1 = 0;
William Lallemand32af2032016-10-29 18:09:35 +020010538 }
Willy Tarreau06d80a92017-10-19 14:32:15 +020010539 if (ci_putchk(si_ic(si), &trash) == -1) {
William Lallemand32af2032016-10-29 18:09:35 +020010540 /* let's try again later from this stream. We add ourselves into
10541 * this stream's users so that it can remove us upon termination.
10542 */
Willy Tarreaudb398432018-11-15 11:08:52 +010010543 si_rx_room_blk(si);
William Lallemand32af2032016-10-29 18:09:35 +020010544 return 0;
10545 }
10546
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010547 if (appctx->ctx.cli.i0 == 0) /* don't display everything if not necessary */
William Lallemand32af2032016-10-29 18:09:35 +020010548 break;
10549
10550 /* get next list entry and check the end of the list */
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010551 appctx->ctx.cli.p0 = tlskeys_list_get_next(appctx->ctx.cli.p0, &tlskeys_reference);
William Lallemand32af2032016-10-29 18:09:35 +020010552 }
10553
10554 appctx->st2 = STAT_ST_FIN;
10555 /* fall through */
10556
10557 default:
10558 appctx->st2 = STAT_ST_FIN;
10559 return 1;
10560 }
10561 return 0;
10562}
10563
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010564/* sets cli.i0 to non-zero if only file lists should be dumped */
Aurélien Nephtaliabbf6072018-04-18 13:26:46 +020010565static int cli_parse_show_tlskeys(char **args, char *payload, struct appctx *appctx, void *private)
William Lallemand32af2032016-10-29 18:09:35 +020010566{
William Lallemand32af2032016-10-29 18:09:35 +020010567 /* no parameter, shows only file list */
10568 if (!*args[2]) {
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010569 appctx->ctx.cli.i0 = 1;
William Lallemand32af2032016-10-29 18:09:35 +020010570 appctx->io_handler = cli_io_handler_tlskeys_files;
Willy Tarreau3067bfa2016-12-05 14:50:15 +010010571 return 0;
William Lallemand32af2032016-10-29 18:09:35 +020010572 }
10573
10574 if (args[2][0] == '*') {
10575 /* list every TLS ticket keys */
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010576 appctx->ctx.cli.i0 = 1;
William Lallemand32af2032016-10-29 18:09:35 +020010577 } else {
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010578 appctx->ctx.cli.p0 = tlskeys_ref_lookup_ref(args[2]);
Willy Tarreau9d008692019-08-09 11:21:01 +020010579 if (!appctx->ctx.cli.p0)
10580 return cli_err(appctx, "'show tls-keys' unable to locate referenced filename\n");
William Lallemand32af2032016-10-29 18:09:35 +020010581 }
William Lallemand32af2032016-10-29 18:09:35 +020010582 appctx->io_handler = cli_io_handler_tlskeys_entries;
Willy Tarreau3067bfa2016-12-05 14:50:15 +010010583 return 0;
William Lallemand32af2032016-10-29 18:09:35 +020010584}
10585
Aurélien Nephtaliabbf6072018-04-18 13:26:46 +020010586static int cli_parse_set_tlskeys(char **args, char *payload, struct appctx *appctx, void *private)
William Lallemand32af2032016-10-29 18:09:35 +020010587{
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010588 struct tls_keys_ref *ref;
Willy Tarreau1c913e42018-08-22 05:26:57 +020010589 int ret;
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010590
William Lallemand32af2032016-10-29 18:09:35 +020010591 /* Expect two parameters: the filename and the new new TLS key in encoding */
Willy Tarreau9d008692019-08-09 11:21:01 +020010592 if (!*args[3] || !*args[4])
10593 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 +020010594
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010595 ref = tlskeys_ref_lookup_ref(args[3]);
Willy Tarreau9d008692019-08-09 11:21:01 +020010596 if (!ref)
10597 return cli_err(appctx, "'set ssl tls-key' unable to locate referenced filename\n");
William Lallemand32af2032016-10-29 18:09:35 +020010598
Willy Tarreau1c913e42018-08-22 05:26:57 +020010599 ret = base64dec(args[4], strlen(args[4]), trash.area, trash.size);
Willy Tarreau9d008692019-08-09 11:21:01 +020010600 if (ret < 0)
10601 return cli_err(appctx, "'set ssl tls-key' received invalid base64 encoded TLS key.\n");
Emeric Brun9e754772019-01-10 17:51:55 +010010602
Willy Tarreau1c913e42018-08-22 05:26:57 +020010603 trash.data = ret;
Willy Tarreau9d008692019-08-09 11:21:01 +020010604 if (ssl_sock_update_tlskey_ref(ref, &trash) < 0)
10605 return cli_err(appctx, "'set ssl tls-key' received a key of wrong size.\n");
William Lallemand32af2032016-10-29 18:09:35 +020010606
Willy Tarreau9d008692019-08-09 11:21:01 +020010607 return cli_msg(appctx, LOG_INFO, "TLS ticket key updated!\n");
William Lallemand32af2032016-10-29 18:09:35 +020010608}
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +010010609#endif
William Lallemand32af2032016-10-29 18:09:35 +020010610
William Lallemand44b35322019-10-17 16:28:40 +020010611
10612/* Type of SSL payloads that can be updated over the CLI */
10613
10614enum {
10615 CERT_TYPE_PEM = 0,
William Lallemand4c5adbf2020-02-24 14:23:22 +010010616 CERT_TYPE_KEY,
Emmanuel Hocdetf6ac4fa2019-10-30 17:41:27 +010010617#if ((defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP) || defined OPENSSL_IS_BORINGSSL)
William Lallemand44b35322019-10-17 16:28:40 +020010618 CERT_TYPE_OCSP,
Emmanuel Hocdetf6ac4fa2019-10-30 17:41:27 +010010619#endif
William Lallemand44b35322019-10-17 16:28:40 +020010620 CERT_TYPE_ISSUER,
Emmanuel Hocdetf6ac4fa2019-10-30 17:41:27 +010010621#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
William Lallemand44b35322019-10-17 16:28:40 +020010622 CERT_TYPE_SCTL,
Emmanuel Hocdetf6ac4fa2019-10-30 17:41:27 +010010623#endif
William Lallemand44b35322019-10-17 16:28:40 +020010624 CERT_TYPE_MAX,
10625};
10626
10627struct {
10628 const char *ext;
10629 int type;
10630 int (*load)(const char *path, char *payload, struct cert_key_and_chain *ckch, char **err);
10631 /* add a parsing callback */
William Lallemandf29cdef2019-10-23 15:00:52 +020010632} cert_exts[CERT_TYPE_MAX+1] = {
William Lallemand44b35322019-10-17 16:28:40 +020010633 [CERT_TYPE_PEM] = { "", CERT_TYPE_PEM, &ssl_sock_load_pem_into_ckch }, /* default mode, no extensions */
William Lallemand4c5adbf2020-02-24 14:23:22 +010010634 [CERT_TYPE_KEY] = { "key", CERT_TYPE_KEY, &ssl_sock_load_key_into_ckch },
William Lallemand541a5342019-10-23 14:11:54 +020010635#if ((defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP) || defined OPENSSL_IS_BORINGSSL)
William Lallemand44b35322019-10-17 16:28:40 +020010636 [CERT_TYPE_OCSP] = { "ocsp", CERT_TYPE_OCSP, &ssl_sock_load_ocsp_response_from_file },
William Lallemand541a5342019-10-23 14:11:54 +020010637#endif
10638#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
William Lallemand44b35322019-10-17 16:28:40 +020010639 [CERT_TYPE_SCTL] = { "sctl", CERT_TYPE_SCTL, &ssl_sock_load_sctl_from_file },
William Lallemand541a5342019-10-23 14:11:54 +020010640#endif
William Lallemand44b35322019-10-17 16:28:40 +020010641 [CERT_TYPE_ISSUER] = { "issuer", CERT_TYPE_ISSUER, &ssl_sock_load_issuer_file_into_ckch },
William Lallemandf29cdef2019-10-23 15:00:52 +020010642 [CERT_TYPE_MAX] = { NULL, CERT_TYPE_MAX, NULL },
William Lallemand44b35322019-10-17 16:28:40 +020010643};
10644
William Lallemand430413e2019-10-28 14:30:47 +010010645/* states of the CLI IO handler for 'set ssl cert' */
10646enum {
10647 SETCERT_ST_INIT = 0,
10648 SETCERT_ST_GEN,
10649 SETCERT_ST_INSERT,
10650 SETCERT_ST_FIN,
10651};
William Lallemand8f840d72019-10-23 10:53:05 +020010652
William Lallemandd4f946c2019-12-05 10:26:40 +010010653/* release function of the `show ssl cert' command */
10654static void cli_release_show_cert(struct appctx *appctx)
10655{
10656 HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
10657}
10658
10659/* IO handler of "show ssl cert <filename>" */
10660static int cli_io_handler_show_cert(struct appctx *appctx)
10661{
10662 struct buffer *trash = alloc_trash_chunk();
10663 struct ebmb_node *node;
10664 struct stream_interface *si = appctx->owner;
10665 struct ckch_store *ckchs;
William Lallemandd4f946c2019-12-05 10:26:40 +010010666
10667 if (trash == NULL)
10668 return 1;
10669
10670 if (!appctx->ctx.ssl.old_ckchs) {
10671 if (ckchs_transaction.old_ckchs) {
10672 ckchs = ckchs_transaction.old_ckchs;
10673 chunk_appendf(trash, "# transaction\n");
10674 if (!ckchs->multi) {
10675 chunk_appendf(trash, "*%s\n", ckchs->path);
William Lallemandba22e902019-12-18 20:36:01 +010010676#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
William Lallemandd4f946c2019-12-05 10:26:40 +010010677 } else {
William Lallemanda25a19f2020-01-29 00:04:24 +010010678 int n;
10679
William Lallemandd4f946c2019-12-05 10:26:40 +010010680 chunk_appendf(trash, "*%s:", ckchs->path);
10681 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
10682 if (ckchs->ckch[n].cert)
10683 chunk_appendf(trash, " %s.%s\n", ckchs->path, SSL_SOCK_KEYTYPE_NAMES[n]);
10684 }
10685 chunk_appendf(trash, "\n");
William Lallemandba22e902019-12-18 20:36:01 +010010686#endif
William Lallemandd4f946c2019-12-05 10:26:40 +010010687 }
10688 }
10689 }
10690
10691 if (!appctx->ctx.cli.p0) {
10692 chunk_appendf(trash, "# filename\n");
10693 node = ebmb_first(&ckchs_tree);
10694 } else {
10695 node = &((struct ckch_store *)appctx->ctx.cli.p0)->node;
10696 }
10697 while (node) {
10698 ckchs = ebmb_entry(node, struct ckch_store, node);
10699 if (!ckchs->multi) {
10700 chunk_appendf(trash, "%s\n", ckchs->path);
William Lallemandba22e902019-12-18 20:36:01 +010010701#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
William Lallemandd4f946c2019-12-05 10:26:40 +010010702 } else {
William Lallemanda25a19f2020-01-29 00:04:24 +010010703 int n;
10704
William Lallemandd4f946c2019-12-05 10:26:40 +010010705 chunk_appendf(trash, "%s:", ckchs->path);
10706 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
10707 if (ckchs->ckch[n].cert)
10708 chunk_appendf(trash, " %s.%s", ckchs->path, SSL_SOCK_KEYTYPE_NAMES[n]);
10709 }
10710 chunk_appendf(trash, "\n");
William Lallemandba22e902019-12-18 20:36:01 +010010711#endif
William Lallemandd4f946c2019-12-05 10:26:40 +010010712 }
10713
10714 node = ebmb_next(node);
10715 if (ci_putchk(si_ic(si), trash) == -1) {
10716 si_rx_room_blk(si);
10717 goto yield;
10718 }
10719 }
10720
10721 appctx->ctx.cli.p0 = NULL;
10722 free_trash_chunk(trash);
10723 return 1;
10724yield:
10725
10726 free_trash_chunk(trash);
10727 appctx->ctx.cli.p0 = ckchs;
10728 return 0; /* should come back */
10729}
10730
10731/* IO handler of the details "show ssl cert <filename>" */
10732static int cli_io_handler_show_cert_detail(struct appctx *appctx)
10733{
10734 struct stream_interface *si = appctx->owner;
10735 struct ckch_store *ckchs = appctx->ctx.cli.p0;
10736 struct buffer *out = alloc_trash_chunk();
10737 struct buffer *tmp = alloc_trash_chunk();
10738 X509_NAME *name = NULL;
Emmanuel Hocdetcf8cf6c2020-02-18 16:06:14 +010010739 STACK_OF(X509) *chain;
Willy Tarreau105599c2020-02-25 08:59:23 +010010740 unsigned int len = 0;
William Lallemandd4f946c2019-12-05 10:26:40 +010010741 int write = -1;
10742 BIO *bio = NULL;
William Lallemand35f4a9d2020-02-25 11:56:32 +010010743 int i;
William Lallemandd4f946c2019-12-05 10:26:40 +010010744
10745 if (!tmp || !out)
10746 goto end;
10747
10748 if (!ckchs->multi) {
10749 chunk_appendf(out, "Filename: ");
10750 if (ckchs == ckchs_transaction.new_ckchs)
10751 chunk_appendf(out, "*");
10752 chunk_appendf(out, "%s\n", ckchs->path);
Emmanuel Hocdetcf8cf6c2020-02-18 16:06:14 +010010753
10754 chain = ckchs->ckch->chain;
10755 if (chain == NULL) {
10756 struct issuer_chain *issuer;
10757 issuer = ssl_get_issuer_chain(ckchs->ckch->cert);
10758 if (issuer) {
10759 chain = issuer->chain;
10760 chunk_appendf(out, "Chain Filename: ");
10761 chunk_appendf(out, "%s\n", issuer->path);
10762 }
10763 }
William Lallemandd4f946c2019-12-05 10:26:40 +010010764 chunk_appendf(out, "Serial: ");
10765 if (ssl_sock_get_serial(ckchs->ckch->cert, tmp) == -1)
10766 goto end;
10767 dump_binary(out, tmp->area, tmp->data);
10768 chunk_appendf(out, "\n");
10769
10770 chunk_appendf(out, "notBefore: ");
10771 chunk_reset(tmp);
10772 if ((bio = BIO_new(BIO_s_mem())) == NULL)
10773 goto end;
10774 if (ASN1_TIME_print(bio, X509_getm_notBefore(ckchs->ckch->cert)) == 0)
10775 goto end;
10776 write = BIO_read(bio, tmp->area, tmp->size-1);
10777 tmp->area[write] = '\0';
10778 BIO_free(bio);
10779 chunk_appendf(out, "%s\n", tmp->area);
10780
10781 chunk_appendf(out, "notAfter: ");
10782 chunk_reset(tmp);
10783 if ((bio = BIO_new(BIO_s_mem())) == NULL)
10784 goto end;
10785 if (ASN1_TIME_print(bio, X509_getm_notAfter(ckchs->ckch->cert)) == 0)
10786 goto end;
10787 if ((write = BIO_read(bio, tmp->area, tmp->size-1)) <= 0)
10788 goto end;
10789 tmp->area[write] = '\0';
10790 BIO_free(bio);
10791 chunk_appendf(out, "%s\n", tmp->area);
10792
William Lallemandd4f946c2019-12-05 10:26:40 +010010793#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
10794 chunk_appendf(out, "Subject Alternative Name: ");
10795 if (ssl_sock_get_san_oneline(ckchs->ckch->cert, out) == -1)
10796 goto end;
10797 *(out->area + out->data) = '\0';
10798 chunk_appendf(out, "\n");
10799#endif
10800 chunk_reset(tmp);
10801 chunk_appendf(out, "Algorithm: ");
10802 if (cert_get_pkey_algo(ckchs->ckch->cert, tmp) == 0)
10803 goto end;
10804 chunk_appendf(out, "%s\n", tmp->area);
10805
10806 chunk_reset(tmp);
10807 chunk_appendf(out, "SHA1 FingerPrint: ");
Willy Tarreau105599c2020-02-25 08:59:23 +010010808 if (X509_digest(ckchs->ckch->cert, EVP_sha1(), (unsigned char *) tmp->area, &len) == 0)
William Lallemandd4f946c2019-12-05 10:26:40 +010010809 goto end;
Willy Tarreau105599c2020-02-25 08:59:23 +010010810 tmp->data = len;
William Lallemandd4f946c2019-12-05 10:26:40 +010010811 dump_binary(out, tmp->area, tmp->data);
10812 chunk_appendf(out, "\n");
William Lallemand35f4a9d2020-02-25 11:56:32 +010010813
William Lallemanda90e5932020-02-25 14:07:58 +010010814 chunk_appendf(out, "Subject: ");
10815 if ((name = X509_get_subject_name(ckchs->ckch->cert)) == NULL)
10816 goto end;
10817 if ((ssl_sock_get_dn_oneline(name, tmp)) == -1)
10818 goto end;
10819 *(tmp->area + tmp->data) = '\0';
10820 chunk_appendf(out, "%s\n", tmp->area);
10821
10822 chunk_appendf(out, "Issuer: ");
10823 if ((name = X509_get_issuer_name(ckchs->ckch->cert)) == NULL)
10824 goto end;
10825 if ((ssl_sock_get_dn_oneline(name, tmp)) == -1)
10826 goto end;
10827 *(tmp->area + tmp->data) = '\0';
10828 chunk_appendf(out, "%s\n", tmp->area);
10829
William Lallemand35f4a9d2020-02-25 11:56:32 +010010830 /* Displays subject of each certificate in the chain */
Emmanuel Hocdetcf8cf6c2020-02-18 16:06:14 +010010831 for (i = 0; i < sk_X509_num(chain); i++) {
10832 X509 *ca = sk_X509_value(chain, i);
William Lallemand35f4a9d2020-02-25 11:56:32 +010010833
William Lallemandbb7288a2020-02-25 14:04:33 +010010834 chunk_appendf(out, "Chain Subject: ");
William Lallemand35f4a9d2020-02-25 11:56:32 +010010835 if ((name = X509_get_subject_name(ca)) == NULL)
10836 goto end;
10837 if ((ssl_sock_get_dn_oneline(name, tmp)) == -1)
10838 goto end;
10839 *(tmp->area + tmp->data) = '\0';
10840 chunk_appendf(out, "%s\n", tmp->area);
10841
William Lallemandbb7288a2020-02-25 14:04:33 +010010842 chunk_appendf(out, "Chain Issuer: ");
10843 if ((name = X509_get_issuer_name(ca)) == NULL)
10844 goto end;
10845 if ((ssl_sock_get_dn_oneline(name, tmp)) == -1)
10846 goto end;
10847 *(tmp->area + tmp->data) = '\0';
10848 chunk_appendf(out, "%s\n", tmp->area);
William Lallemand35f4a9d2020-02-25 11:56:32 +010010849 }
William Lallemandd4f946c2019-12-05 10:26:40 +010010850 }
10851
10852 if (ci_putchk(si_ic(si), out) == -1) {
10853 si_rx_room_blk(si);
10854 goto yield;
10855 }
10856
10857end:
10858 free_trash_chunk(tmp);
10859 free_trash_chunk(out);
10860 return 1;
10861yield:
10862 free_trash_chunk(tmp);
10863 free_trash_chunk(out);
10864 return 0; /* should come back */
10865}
10866
10867/* parsing function for 'show ssl cert [certfile]' */
10868static int cli_parse_show_cert(char **args, char *payload, struct appctx *appctx, void *private)
10869{
10870 struct ckch_store *ckchs;
10871
10872 if (!cli_has_level(appctx, ACCESS_LVL_OPER))
10873 return cli_err(appctx, "Can't allocate memory!\n");
10874
10875 /* The operations on the CKCH architecture are locked so we can
10876 * manipulate ckch_store and ckch_inst */
10877 if (HA_SPIN_TRYLOCK(CKCH_LOCK, &ckch_lock))
10878 return cli_err(appctx, "Can't show!\nOperations on certificates are currently locked!\n");
10879
10880 /* check if there is a certificate to lookup */
10881 if (*args[3]) {
10882 if (*args[3] == '*') {
10883 if (!ckchs_transaction.new_ckchs)
10884 goto error;
10885
10886 ckchs = ckchs_transaction.new_ckchs;
10887
10888 if (strcmp(args[3] + 1, ckchs->path))
10889 goto error;
10890
10891 } else {
10892 if ((ckchs = ckchs_lookup(args[3])) == NULL)
10893 goto error;
10894
10895 }
10896
10897 if (ckchs->multi)
10898 goto error;
10899
10900 appctx->ctx.cli.p0 = ckchs;
10901 /* use the IO handler that shows details */
10902 appctx->io_handler = cli_io_handler_show_cert_detail;
10903 }
10904
10905 return 0;
10906
10907error:
10908 HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
10909 return cli_err(appctx, "Can't display the certificate: Not found or the certificate is a bundle!\n");
10910}
10911
William Lallemand430413e2019-10-28 14:30:47 +010010912/* release function of the `set ssl cert' command, free things and unlock the spinlock */
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010913static void cli_release_commit_cert(struct appctx *appctx)
William Lallemand8f840d72019-10-23 10:53:05 +020010914{
10915 struct ckch_store *new_ckchs;
10916 struct ckch_inst *ckchi, *ckchis;
William Lallemand8f840d72019-10-23 10:53:05 +020010917
William Lallemand430413e2019-10-28 14:30:47 +010010918 HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
William Lallemand8f840d72019-10-23 10:53:05 +020010919
William Lallemand430413e2019-10-28 14:30:47 +010010920 if (appctx->st2 != SETCERT_ST_FIN) {
William Lallemand8f840d72019-10-23 10:53:05 +020010921 /* 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 +010010922 new_ckchs = appctx->ctx.ssl.new_ckchs;
William Lallemand8f840d72019-10-23 10:53:05 +020010923
William Lallemandbeea2a42019-10-30 17:45:33 +010010924 if (!new_ckchs)
10925 return;
William Lallemand8f840d72019-10-23 10:53:05 +020010926
William Lallemandbeea2a42019-10-30 17:45:33 +010010927 /* if the allocation failed, we need to free everything from the temporary list */
10928 list_for_each_entry_safe(ckchi, ckchis, &new_ckchs->ckch_inst, by_ckchs) {
10929 struct sni_ctx *sc0, *sc0s;
William Lallemand8f840d72019-10-23 10:53:05 +020010930
William Lallemandbeea2a42019-10-30 17:45:33 +010010931 list_for_each_entry_safe(sc0, sc0s, &ckchi->sni_ctx, by_ckch_inst) {
10932 if (sc0->order == 0) /* we only free if it's the first inserted */
10933 SSL_CTX_free(sc0->ctx);
10934 LIST_DEL(&sc0->by_ckch_inst);
10935 free(sc0);
William Lallemand8f840d72019-10-23 10:53:05 +020010936 }
William Lallemandbeea2a42019-10-30 17:45:33 +010010937 LIST_DEL(&ckchi->by_ckchs);
10938 free(ckchi);
William Lallemand8f840d72019-10-23 10:53:05 +020010939 }
William Lallemandbeea2a42019-10-30 17:45:33 +010010940 ckchs_free(new_ckchs);
William Lallemand8f840d72019-10-23 10:53:05 +020010941 }
10942}
10943
10944
10945/*
10946 * This function tries to create the new ckch_inst and their SNIs
10947 */
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010948static int cli_io_handler_commit_cert(struct appctx *appctx)
William Lallemand8f840d72019-10-23 10:53:05 +020010949{
10950 struct stream_interface *si = appctx->owner;
10951 int y = 0;
10952 char *err = NULL;
10953 int errcode = 0;
10954 struct ckch_store *old_ckchs, *new_ckchs = NULL;
10955 struct ckch_inst *ckchi, *ckchis;
William Lallemand8f840d72019-10-23 10:53:05 +020010956 struct buffer *trash = alloc_trash_chunk();
William Lallemand8ef0c2a2019-11-21 16:30:34 +010010957 struct sni_ctx *sc0, *sc0s;
William Lallemand8f840d72019-10-23 10:53:05 +020010958
William Lallemand33cc76f2019-10-31 11:43:45 +010010959 if (trash == NULL)
10960 goto error;
10961
William Lallemand8f840d72019-10-23 10:53:05 +020010962 if (unlikely(si_ic(si)->flags & (CF_WRITE_ERROR|CF_SHUTW)))
10963 goto error;
10964
William Lallemand430413e2019-10-28 14:30:47 +010010965 while (1) {
10966 switch (appctx->st2) {
10967 case SETCERT_ST_INIT:
10968 /* This state just print the update message */
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010969 chunk_printf(trash, "Committing %s", ckchs_transaction.path);
William Lallemand430413e2019-10-28 14:30:47 +010010970 if (ci_putchk(si_ic(si), trash) == -1) {
10971 si_rx_room_blk(si);
William Lallemand8f840d72019-10-23 10:53:05 +020010972 goto yield;
William Lallemand430413e2019-10-28 14:30:47 +010010973 }
10974 appctx->st2 = SETCERT_ST_GEN;
10975 /* fallthrough */
10976 case SETCERT_ST_GEN:
10977 /*
10978 * This state generates the ckch instances with their
10979 * sni_ctxs and SSL_CTX.
10980 *
William Lallemand430413e2019-10-28 14:30:47 +010010981 * Since the SSL_CTX generation can be CPU consumer, we
10982 * yield every 10 instances.
10983 */
William Lallemand8f840d72019-10-23 10:53:05 +020010984
William Lallemandbeea2a42019-10-30 17:45:33 +010010985 old_ckchs = appctx->ctx.ssl.old_ckchs;
10986 new_ckchs = appctx->ctx.ssl.new_ckchs;
William Lallemand8f840d72019-10-23 10:53:05 +020010987
William Lallemandbeea2a42019-10-30 17:45:33 +010010988 if (!new_ckchs)
10989 continue;
William Lallemand8f840d72019-10-23 10:53:05 +020010990
William Lallemandbeea2a42019-10-30 17:45:33 +010010991 /* get the next ckchi to regenerate */
10992 ckchi = appctx->ctx.ssl.next_ckchi;
10993 /* we didn't start yet, set it to the first elem */
10994 if (ckchi == NULL)
10995 ckchi = LIST_ELEM(old_ckchs->ckch_inst.n, typeof(ckchi), by_ckchs);
William Lallemand8f840d72019-10-23 10:53:05 +020010996
William Lallemandbeea2a42019-10-30 17:45:33 +010010997 /* walk through the old ckch_inst and creates new ckch_inst using the updated ckchs */
10998 list_for_each_entry_from(ckchi, &old_ckchs->ckch_inst, by_ckchs) {
10999 struct ckch_inst *new_inst;
William Lallemand38df1c82019-12-04 15:39:35 +010011000 char **sni_filter = NULL;
11001 int fcount = 0;
William Lallemand8f840d72019-10-23 10:53:05 +020011002
William Lallemandbeea2a42019-10-30 17:45:33 +010011003 /* it takes a lot of CPU to creates SSL_CTXs, so we yield every 10 CKCH instances */
11004 if (y >= 10) {
11005 /* save the next ckchi to compute */
11006 appctx->ctx.ssl.next_ckchi = ckchi;
11007 goto yield;
11008 }
William Lallemand8f840d72019-10-23 10:53:05 +020011009
William Lallemand38df1c82019-12-04 15:39:35 +010011010 errcode |= ckch_inst_sni_ctx_to_sni_filters(ckchi, &sni_filter, &fcount, &err);
11011 if (errcode & ERR_CODE)
11012 goto error;
11013
William Lallemandbeea2a42019-10-30 17:45:33 +010011014 if (new_ckchs->multi)
William Lallemand38df1c82019-12-04 15:39:35 +010011015 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 +010011016 else
William Lallemand38df1c82019-12-04 15:39:35 +010011017 errcode |= ckch_inst_new_load_store(new_ckchs->path, new_ckchs, ckchi->bind_conf, ckchi->ssl_conf, sni_filter, fcount, &new_inst, &err);
11018
11019 free_sni_filters(sni_filter, fcount);
11020 sni_filter = NULL;
William Lallemand8f840d72019-10-23 10:53:05 +020011021
William Lallemandbeea2a42019-10-30 17:45:33 +010011022 if (errcode & ERR_CODE)
11023 goto error;
William Lallemand8f840d72019-10-23 10:53:05 +020011024
William Lallemand21724f02019-11-04 17:56:13 +010011025 /* if the previous ckchi was used as the default */
11026 if (ckchi->is_default)
11027 new_inst->is_default = 1;
11028
William Lallemand8ef0c2a2019-11-21 16:30:34 +010011029 /* we need to initialize the SSL_CTX generated */
William Lallemand696f3172020-02-07 20:45:24 +010011030 /* this iterate on the newly generated SNIs in the new instance to prepare their SSL_CTX */
11031 list_for_each_entry_safe(sc0, sc0s, &new_inst->sni_ctx, by_ckch_inst) {
William Lallemand8ef0c2a2019-11-21 16:30:34 +010011032 if (!sc0->order) { /* we initiliazed only the first SSL_CTX because it's the same in the other sni_ctx's */
11033 errcode |= ssl_sock_prepare_ctx(ckchi->bind_conf, ckchi->ssl_conf, sc0->ctx, &err);
11034 if (errcode & ERR_CODE)
11035 goto error;
11036 }
11037 }
11038
11039
William Lallemandbeea2a42019-10-30 17:45:33 +010011040 /* display one dot per new instance */
11041 chunk_appendf(trash, ".");
11042 /* link the new ckch_inst to the duplicate */
11043 LIST_ADDQ(&new_ckchs->ckch_inst, &new_inst->by_ckchs);
11044 y++;
11045 }
William Lallemand430413e2019-10-28 14:30:47 +010011046 appctx->st2 = SETCERT_ST_INSERT;
11047 /* fallthrough */
11048 case SETCERT_ST_INSERT:
11049 /* The generation is finished, we can insert everything */
William Lallemand8f840d72019-10-23 10:53:05 +020011050
William Lallemandbeea2a42019-10-30 17:45:33 +010011051 old_ckchs = appctx->ctx.ssl.old_ckchs;
11052 new_ckchs = appctx->ctx.ssl.new_ckchs;
William Lallemand8f840d72019-10-23 10:53:05 +020011053
William Lallemandbeea2a42019-10-30 17:45:33 +010011054 if (!new_ckchs)
11055 continue;
William Lallemand430413e2019-10-28 14:30:47 +010011056
William Lallemand21724f02019-11-04 17:56:13 +010011057 /* First, we insert every new SNIs in the trees, also replace the default_ctx */
William Lallemandbeea2a42019-10-30 17:45:33 +010011058 list_for_each_entry_safe(ckchi, ckchis, &new_ckchs->ckch_inst, by_ckchs) {
11059 HA_RWLOCK_WRLOCK(SNI_LOCK, &ckchi->bind_conf->sni_lock);
11060 ssl_sock_load_cert_sni(ckchi, ckchi->bind_conf);
11061 HA_RWLOCK_WRUNLOCK(SNI_LOCK, &ckchi->bind_conf->sni_lock);
11062 }
William Lallemand8f840d72019-10-23 10:53:05 +020011063
William Lallemandbeea2a42019-10-30 17:45:33 +010011064 /* delete the old sni_ctx, the old ckch_insts and the ckch_store */
11065 list_for_each_entry_safe(ckchi, ckchis, &old_ckchs->ckch_inst, by_ckchs) {
William Lallemand430413e2019-10-28 14:30:47 +010011066
William Lallemandbeea2a42019-10-30 17:45:33 +010011067 HA_RWLOCK_WRLOCK(SNI_LOCK, &ckchi->bind_conf->sni_lock);
11068 list_for_each_entry_safe(sc0, sc0s, &ckchi->sni_ctx, by_ckch_inst) {
11069 ebmb_delete(&sc0->name);
11070 LIST_DEL(&sc0->by_ckch_inst);
11071 free(sc0);
William Lallemand430413e2019-10-28 14:30:47 +010011072 }
William Lallemandbeea2a42019-10-30 17:45:33 +010011073 HA_RWLOCK_WRUNLOCK(SNI_LOCK, &ckchi->bind_conf->sni_lock);
11074 LIST_DEL(&ckchi->by_ckchs);
11075 free(ckchi);
11076 }
William Lallemand8f840d72019-10-23 10:53:05 +020011077
William Lallemandbeea2a42019-10-30 17:45:33 +010011078 /* Replace the old ckchs by the new one */
11079 ebmb_delete(&old_ckchs->node);
11080 ckchs_free(old_ckchs);
11081 ebst_insert(&ckchs_tree, &new_ckchs->node);
William Lallemand430413e2019-10-28 14:30:47 +010011082 appctx->st2 = SETCERT_ST_FIN;
11083 /* fallthrough */
11084 case SETCERT_ST_FIN:
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011085 /* we achieved the transaction, we can set everything to NULL */
11086 free(ckchs_transaction.path);
11087 ckchs_transaction.path = NULL;
11088 ckchs_transaction.new_ckchs = NULL;
11089 ckchs_transaction.old_ckchs = NULL;
William Lallemand430413e2019-10-28 14:30:47 +010011090 goto end;
11091 }
William Lallemand8f840d72019-10-23 10:53:05 +020011092 }
William Lallemand430413e2019-10-28 14:30:47 +010011093end:
William Lallemand8f840d72019-10-23 10:53:05 +020011094
William Lallemanded442432019-11-21 16:41:07 +010011095 chunk_appendf(trash, "\n");
11096 if (errcode & ERR_WARN)
Tim Duesterhusc0e820c2019-11-23 23:52:30 +010011097 chunk_appendf(trash, "%s", err);
William Lallemanded442432019-11-21 16:41:07 +010011098 chunk_appendf(trash, "Success!\n");
William Lallemand430413e2019-10-28 14:30:47 +010011099 if (ci_putchk(si_ic(si), trash) == -1)
11100 si_rx_room_blk(si);
11101 free_trash_chunk(trash);
11102 /* success: call the release function and don't come back */
11103 return 1;
William Lallemand8f840d72019-10-23 10:53:05 +020011104yield:
11105 /* store the state */
11106 if (ci_putchk(si_ic(si), trash) == -1)
11107 si_rx_room_blk(si);
11108 free_trash_chunk(trash);
11109 si_rx_endp_more(si); /* let's come back later */
William Lallemand8f840d72019-10-23 10:53:05 +020011110 return 0; /* should come back */
11111
11112error:
11113 /* spin unlock and free are done in the release function */
William Lallemand33cc76f2019-10-31 11:43:45 +010011114 if (trash) {
11115 chunk_appendf(trash, "\n%sFailed!\n", err);
11116 if (ci_putchk(si_ic(si), trash) == -1)
11117 si_rx_room_blk(si);
11118 free_trash_chunk(trash);
11119 }
William Lallemand430413e2019-10-28 14:30:47 +010011120 /* error: call the release function and don't come back */
11121 return 1;
William Lallemand8f840d72019-10-23 10:53:05 +020011122}
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011123
11124/*
11125 * Parsing function of 'commit ssl cert'
11126 */
11127static int cli_parse_commit_cert(char **args, char *payload, struct appctx *appctx, void *private)
11128{
11129 char *err = NULL;
11130
William Lallemand230662a2019-12-03 13:32:54 +010011131 if (!cli_has_level(appctx, ACCESS_LVL_ADMIN))
11132 return 1;
11133
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011134 if (!*args[3])
11135 return cli_err(appctx, "'commit ssl cert expects a filename\n");
11136
11137 /* The operations on the CKCH architecture are locked so we can
11138 * manipulate ckch_store and ckch_inst */
11139 if (HA_SPIN_TRYLOCK(CKCH_LOCK, &ckch_lock))
11140 return cli_err(appctx, "Can't commit the certificate!\nOperations on certificates are currently locked!\n");
11141
11142 if (!ckchs_transaction.path) {
11143 memprintf(&err, "No ongoing transaction! !\n");
11144 goto error;
11145 }
11146
11147 if (strcmp(ckchs_transaction.path, args[3]) != 0) {
11148 memprintf(&err, "The ongoing transaction is about '%s' but you are trying to set '%s'\n", ckchs_transaction.path, args[3]);
11149 goto error;
11150 }
11151
William Lallemand4c5adbf2020-02-24 14:23:22 +010011152#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
11153 if (ckchs_transaction.new_ckchs->multi) {
11154 int n;
11155
11156 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
11157 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)) {
11158 memprintf(&err, "inconsistencies between private key and certificate loaded '%s'.\n", ckchs_transaction.path);
11159 goto error;
11160 }
11161 }
11162 } else
11163#endif
11164 {
11165 if (!X509_check_private_key(ckchs_transaction.new_ckchs->ckch->cert, ckchs_transaction.new_ckchs->ckch->key)) {
11166 memprintf(&err, "inconsistencies between private key and certificate loaded '%s'.\n", ckchs_transaction.path);
11167 goto error;
11168 }
11169 }
11170
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011171 /* init the appctx structure */
11172 appctx->st2 = SETCERT_ST_INIT;
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011173 appctx->ctx.ssl.next_ckchi = NULL;
11174 appctx->ctx.ssl.new_ckchs = ckchs_transaction.new_ckchs;
11175 appctx->ctx.ssl.old_ckchs = ckchs_transaction.old_ckchs;
11176
11177 /* we don't unlock there, it will be unlock after the IO handler, in the release handler */
11178 return 0;
11179
11180error:
11181
11182 HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
11183 err = memprintf(&err, "%sCan't commit %s!\n", err ? err : "", args[3]);
11184
11185 return cli_dynerr(appctx, err);
11186}
11187
William Lallemand8f840d72019-10-23 10:53:05 +020011188/*
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011189 * Parsing function of `set ssl cert`, it updates or creates a temporary ckch.
William Lallemand8f840d72019-10-23 10:53:05 +020011190 */
William Lallemand150bfa82019-09-19 17:12:49 +020011191static int cli_parse_set_cert(char **args, char *payload, struct appctx *appctx, void *private)
11192{
William Lallemand0c3b7d92019-10-18 11:27:07 +020011193 struct ckch_store *new_ckchs = NULL;
William Lallemand8f840d72019-10-23 10:53:05 +020011194 struct ckch_store *old_ckchs = NULL;
William Lallemand150bfa82019-09-19 17:12:49 +020011195 char *err = NULL;
William Lallemand963b2e72019-10-14 11:38:36 +020011196 int i;
William Lallemand849eed62019-10-17 16:23:50 +020011197 int bundle = -1; /* TRUE if >= 0 (ckch index) */
Emeric Brunf69ed1d2019-10-17 11:56:56 +020011198 int errcode = 0;
William Lallemand44b35322019-10-17 16:28:40 +020011199 char *end;
11200 int type = CERT_TYPE_PEM;
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011201 struct cert_key_and_chain *ckch;
11202 struct buffer *buf;
William Lallemand8f840d72019-10-23 10:53:05 +020011203
William Lallemand230662a2019-12-03 13:32:54 +010011204 if (!cli_has_level(appctx, ACCESS_LVL_ADMIN))
11205 return 1;
11206
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011207 if ((buf = alloc_trash_chunk()) == NULL)
11208 return cli_err(appctx, "Can't allocate memory\n");
William Lallemand150bfa82019-09-19 17:12:49 +020011209
11210 if (!*args[3] || !payload)
11211 return cli_err(appctx, "'set ssl cert expects a filename and a certificat as a payload\n");
11212
11213 /* The operations on the CKCH architecture are locked so we can
11214 * manipulate ckch_store and ckch_inst */
11215 if (HA_SPIN_TRYLOCK(CKCH_LOCK, &ckch_lock))
11216 return cli_err(appctx, "Can't update the certificate!\nOperations on certificates are currently locked!\n");
11217
William Lallemand8f840d72019-10-23 10:53:05 +020011218 if (!chunk_strcpy(buf, args[3])) {
11219 memprintf(&err, "%sCan't allocate memory\n", err ? err : "");
11220 errcode |= ERR_ALERT | ERR_FATAL;
11221 goto end;
11222 }
11223
William Lallemand44b35322019-10-17 16:28:40 +020011224 /* check which type of file we want to update */
William Lallemandf29cdef2019-10-23 15:00:52 +020011225 for (i = 0; cert_exts[i].type < CERT_TYPE_MAX; i++) {
William Lallemand8f840d72019-10-23 10:53:05 +020011226 end = strrchr(buf->area, '.');
William Lallemand44b35322019-10-17 16:28:40 +020011227 if (end && *cert_exts[i].ext && (!strcmp(end + 1, cert_exts[i].ext))) {
11228 *end = '\0';
11229 type = cert_exts[i].type;
11230 break;
11231 }
11232 }
11233
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011234 appctx->ctx.ssl.old_ckchs = NULL;
11235 appctx->ctx.ssl.new_ckchs = NULL;
William Lallemand849eed62019-10-17 16:23:50 +020011236
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011237 /* if there is an ongoing transaction */
11238 if (ckchs_transaction.path) {
11239 /* 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 +020011240#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011241 if (ckchs_transaction.new_ckchs->multi) {
Emmanuel Hocdet40f2f1e2019-10-30 17:31:28 +010011242 char *end;
William Lallemand963b2e72019-10-14 11:38:36 +020011243 int j;
William Lallemand150bfa82019-09-19 17:12:49 +020011244
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011245 /* check if it was used in a bundle by removing the
William Lallemand963b2e72019-10-14 11:38:36 +020011246 * .dsa/.rsa/.ecdsa at the end of the filename */
William Lallemand8f840d72019-10-23 10:53:05 +020011247 end = strrchr(buf->area, '.');
Emmanuel Hocdet40f2f1e2019-10-30 17:31:28 +010011248 for (j = 0; end && j < SSL_SOCK_NUM_KEYTYPES; j++) {
William Lallemand963b2e72019-10-14 11:38:36 +020011249 if (!strcmp(end + 1, SSL_SOCK_KEYTYPE_NAMES[j])) {
11250 bundle = j; /* keep the type of certificate so we insert it at the right place */
11251 *end = '\0'; /* it's a bundle let's end the string*/
11252 break;
11253 }
William Lallemand150bfa82019-09-19 17:12:49 +020011254 }
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011255 if (bundle < 0) {
11256 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);
11257 errcode |= ERR_ALERT | ERR_FATAL;
11258 goto end;
11259 }
11260 }
11261#endif
11262
11263 /* if there is an ongoing transaction, check if this is the same file */
11264 if (strcmp(ckchs_transaction.path, buf->area) != 0) {
11265 memprintf(&err, "The ongoing transaction is about '%s' but you are trying to set '%s'\n", ckchs_transaction.path, buf->area);
11266 errcode |= ERR_ALERT | ERR_FATAL;
11267 goto end;
William Lallemand150bfa82019-09-19 17:12:49 +020011268 }
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011269
11270 appctx->ctx.ssl.old_ckchs = ckchs_transaction.new_ckchs;
11271
11272 } else {
11273 struct ckch_store *find_ckchs[2] = { NULL, NULL };
11274
11275 /* lookup for the certificate in the tree:
11276 * check if this is used as a bundle AND as a unique certificate */
11277 for (i = 0; i < 2; i++) {
11278
11279 if ((find_ckchs[i] = ckchs_lookup(buf->area)) != NULL) {
11280 /* only the bundle name is in the tree and you should
11281 * never update a bundle name, only a filename */
11282 if (bundle < 0 && find_ckchs[i]->multi) {
11283 /* we tried to look for a non-bundle and we found a bundle */
11284 memprintf(&err, "%s%s is a multi-cert bundle. Try updating %s.{dsa,rsa,ecdsa}\n",
11285 err ? err : "", args[3], args[3]);
11286 errcode |= ERR_ALERT | ERR_FATAL;
11287 goto end;
11288 }
William Lallemand3246d942019-11-04 14:02:11 +010011289 /* If we want a bundle but this is not a bundle
11290 * example: When you try to update <file>.rsa, but
11291 * <file> is a regular file */
11292 if (bundle >= 0 && find_ckchs[i]->multi == 0) {
11293 find_ckchs[i] = NULL;
11294 break;
11295 }
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011296 }
11297#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
11298 {
Emmanuel Hocdet40f2f1e2019-10-30 17:31:28 +010011299 char *end;
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011300 int j;
11301
11302 /* check if it was used in a bundle by removing the
11303 * .dsa/.rsa/.ecdsa at the end of the filename */
11304 end = strrchr(buf->area, '.');
Emmanuel Hocdet40f2f1e2019-10-30 17:31:28 +010011305 for (j = 0; end && j < SSL_SOCK_NUM_KEYTYPES; j++) {
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011306 if (!strcmp(end + 1, SSL_SOCK_KEYTYPE_NAMES[j])) {
11307 bundle = j; /* keep the type of certificate so we insert it at the right place */
11308 *end = '\0'; /* it's a bundle let's end the string*/
11309 break;
11310 }
11311 }
William Lallemand37031b82019-11-04 13:38:53 +010011312 if (bundle < 0) /* we didn't find a bundle extension */
11313 break;
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011314 }
William Lallemand963b2e72019-10-14 11:38:36 +020011315#else
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011316 /* bundles are not supported here, so we don't need to lookup again */
11317 break;
William Lallemand963b2e72019-10-14 11:38:36 +020011318#endif
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011319 }
11320
11321 if (find_ckchs[0] && find_ckchs[1]) {
11322 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",
11323 err ? err : "", find_ckchs[0]->path, find_ckchs[1]->path);
11324 errcode |= ERR_ALERT | ERR_FATAL;
11325 goto end;
11326 }
11327
11328 appctx->ctx.ssl.old_ckchs = find_ckchs[0] ? find_ckchs[0] : find_ckchs[1];
William Lallemand150bfa82019-09-19 17:12:49 +020011329 }
11330
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011331 if (!appctx->ctx.ssl.old_ckchs) {
11332 memprintf(&err, "%sCan't replace a certificate which is not referenced by the configuration!\n",
William Lallemand150bfa82019-09-19 17:12:49 +020011333 err ? err : "");
Emeric Brunf69ed1d2019-10-17 11:56:56 +020011334 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemand8f840d72019-10-23 10:53:05 +020011335 goto end;
William Lallemand150bfa82019-09-19 17:12:49 +020011336 }
11337
William Lallemand8a7fdf02019-11-04 10:59:32 +010011338 if (!appctx->ctx.ssl.path) {
11339 /* this is a new transaction, set the path of the transaction */
11340 appctx->ctx.ssl.path = strdup(appctx->ctx.ssl.old_ckchs->path);
11341 if (!appctx->ctx.ssl.path) {
11342 memprintf(&err, "%sCan't allocate memory\n", err ? err : "");
11343 errcode |= ERR_ALERT | ERR_FATAL;
11344 goto end;
11345 }
11346 }
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011347
11348 old_ckchs = appctx->ctx.ssl.old_ckchs;
11349
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011350 /* duplicate the ckch store */
11351 new_ckchs = ckchs_dup(old_ckchs);
11352 if (!new_ckchs) {
11353 memprintf(&err, "%sCannot allocate memory!\n",
11354 err ? err : "");
11355 errcode |= ERR_ALERT | ERR_FATAL;
11356 goto end;
11357 }
11358
11359 if (!new_ckchs->multi)
11360 ckch = new_ckchs->ckch;
11361 else
11362 ckch = &new_ckchs->ckch[bundle];
11363
11364 /* appply the change on the duplicate */
11365 if (cert_exts[type].load(buf->area, payload, ckch, &err) != 0) {
11366 memprintf(&err, "%sCan't load the payload\n", err ? err : "");
11367 errcode |= ERR_ALERT | ERR_FATAL;
11368 goto end;
11369 }
11370
11371 appctx->ctx.ssl.new_ckchs = new_ckchs;
11372
11373 /* we succeed, we can save the ckchs in the transaction */
11374
11375 /* if there wasn't a transaction, update the old ckchs */
William Dauchyc8bb1532019-11-24 15:04:20 +010011376 if (!ckchs_transaction.old_ckchs) {
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011377 ckchs_transaction.old_ckchs = appctx->ctx.ssl.old_ckchs;
11378 ckchs_transaction.path = appctx->ctx.ssl.path;
11379 err = memprintf(&err, "Transaction created for certificate %s!\n", ckchs_transaction.path);
11380 } else {
11381 err = memprintf(&err, "Transaction updated for certificate %s!\n", ckchs_transaction.path);
11382
11383 }
11384
11385 /* free the previous ckchs if there was a transaction */
11386 ckchs_free(ckchs_transaction.new_ckchs);
11387
11388 ckchs_transaction.new_ckchs = appctx->ctx.ssl.new_ckchs;
11389
11390
William Lallemand8f840d72019-10-23 10:53:05 +020011391 /* creates the SNI ctxs later in the IO handler */
William Lallemand150bfa82019-09-19 17:12:49 +020011392
William Lallemand8f840d72019-10-23 10:53:05 +020011393end:
11394 free_trash_chunk(buf);
William Lallemand150bfa82019-09-19 17:12:49 +020011395
Emeric Brunf69ed1d2019-10-17 11:56:56 +020011396 if (errcode & ERR_CODE) {
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011397
11398 ckchs_free(appctx->ctx.ssl.new_ckchs);
11399 appctx->ctx.ssl.new_ckchs = NULL;
11400
11401 appctx->ctx.ssl.old_ckchs = NULL;
11402
11403 free(appctx->ctx.ssl.path);
11404 appctx->ctx.ssl.path = NULL;
11405
11406 HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
William Lallemand44b35322019-10-17 16:28:40 +020011407 return cli_dynerr(appctx, memprintf(&err, "%sCan't update %s!\n", err ? err : "", args[3]));
William Lallemand430413e2019-10-28 14:30:47 +010011408 } else {
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011409
11410 HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
11411 return cli_dynmsg(appctx, LOG_NOTICE, err);
William Lallemand430413e2019-10-28 14:30:47 +010011412 }
William Lallemand8f840d72019-10-23 10:53:05 +020011413 /* TODO: handle the ERR_WARN which are not handled because of the io_handler */
William Lallemand150bfa82019-09-19 17:12:49 +020011414}
11415
William Lallemand0bc9c8a2019-11-19 15:51:51 +010011416/* parsing function of 'abort ssl cert' */
11417static int cli_parse_abort_cert(char **args, char *payload, struct appctx *appctx, void *private)
11418{
11419 char *err = NULL;
11420
William Lallemand230662a2019-12-03 13:32:54 +010011421 if (!cli_has_level(appctx, ACCESS_LVL_ADMIN))
11422 return 1;
11423
William Lallemand0bc9c8a2019-11-19 15:51:51 +010011424 if (!*args[3])
11425 return cli_err(appctx, "'abort ssl cert' expects a filename\n");
11426
11427 /* The operations on the CKCH architecture are locked so we can
11428 * manipulate ckch_store and ckch_inst */
11429 if (HA_SPIN_TRYLOCK(CKCH_LOCK, &ckch_lock))
11430 return cli_err(appctx, "Can't abort!\nOperations on certificates are currently locked!\n");
11431
11432 if (!ckchs_transaction.path) {
11433 memprintf(&err, "No ongoing transaction!\n");
11434 goto error;
11435 }
11436
11437 if (strcmp(ckchs_transaction.path, args[3]) != 0) {
11438 memprintf(&err, "The ongoing transaction is about '%s' but you are trying to abort a transaction for '%s'\n", ckchs_transaction.path, args[3]);
11439 goto error;
11440 }
11441
11442 /* Only free the ckchs there, because the SNI and instances were not generated yet */
11443 ckchs_free(ckchs_transaction.new_ckchs);
11444 ckchs_transaction.new_ckchs = NULL;
11445 ckchs_free(ckchs_transaction.old_ckchs);
11446 ckchs_transaction.old_ckchs = NULL;
11447 free(ckchs_transaction.path);
11448 ckchs_transaction.path = NULL;
11449
11450 HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
11451
11452 err = memprintf(&err, "Transaction aborted for certificate '%s'!\n", args[3]);
11453 return cli_dynmsg(appctx, LOG_NOTICE, err);
11454
11455error:
11456 HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
11457
11458 return cli_dynerr(appctx, err);
11459}
11460
Aurélien Nephtaliabbf6072018-04-18 13:26:46 +020011461static int cli_parse_set_ocspresponse(char **args, char *payload, struct appctx *appctx, void *private)
William Lallemand32af2032016-10-29 18:09:35 +020011462{
11463#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
11464 char *err = NULL;
Willy Tarreau1c913e42018-08-22 05:26:57 +020011465 int i, j, ret;
Aurélien Nephtali1e0867c2018-04-18 14:04:58 +020011466
11467 if (!payload)
11468 payload = args[3];
William Lallemand32af2032016-10-29 18:09:35 +020011469
11470 /* Expect one parameter: the new response in base64 encoding */
Willy Tarreau9d008692019-08-09 11:21:01 +020011471 if (!*payload)
11472 return cli_err(appctx, "'set ssl ocsp-response' expects response in base64 encoding.\n");
Aurélien Nephtali1e0867c2018-04-18 14:04:58 +020011473
11474 /* remove \r and \n from the payload */
11475 for (i = 0, j = 0; payload[i]; i++) {
11476 if (payload[i] == '\r' || payload[i] == '\n')
11477 continue;
11478 payload[j++] = payload[i];
11479 }
11480 payload[j] = 0;
William Lallemand32af2032016-10-29 18:09:35 +020011481
Willy Tarreau1c913e42018-08-22 05:26:57 +020011482 ret = base64dec(payload, j, trash.area, trash.size);
Willy Tarreau9d008692019-08-09 11:21:01 +020011483 if (ret < 0)
11484 return cli_err(appctx, "'set ssl ocsp-response' received invalid base64 encoded response.\n");
William Lallemand32af2032016-10-29 18:09:35 +020011485
Willy Tarreau1c913e42018-08-22 05:26:57 +020011486 trash.data = ret;
William Lallemand32af2032016-10-29 18:09:35 +020011487 if (ssl_sock_update_ocsp_response(&trash, &err)) {
Willy Tarreau9d008692019-08-09 11:21:01 +020011488 if (err)
11489 return cli_dynerr(appctx, memprintf(&err, "%s.\n", err));
11490 else
11491 return cli_err(appctx, "Failed to update OCSP response.\n");
William Lallemand32af2032016-10-29 18:09:35 +020011492 }
Willy Tarreau9d008692019-08-09 11:21:01 +020011493
11494 return cli_msg(appctx, LOG_INFO, "OCSP Response updated!\n");
William Lallemand32af2032016-10-29 18:09:35 +020011495#else
Willy Tarreau9d008692019-08-09 11:21:01 +020011496 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 +020011497#endif
11498
Nenad Merdanovicc31499d2019-03-23 11:00:32 +010011499}
11500
Willy Tarreau86a394e2019-05-09 14:15:32 +020011501#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000100fL)
Nenad Merdanovicc31499d2019-03-23 11:00:32 +010011502static inline int sample_conv_var2smp_str(const struct arg *arg, struct sample *smp)
11503{
11504 switch (arg->type) {
11505 case ARGT_STR:
11506 smp->data.type = SMP_T_STR;
11507 smp->data.u.str = arg->data.str;
11508 return 1;
11509 case ARGT_VAR:
11510 if (!vars_get_by_desc(&arg->data.var, smp))
11511 return 0;
11512 if (!sample_casts[smp->data.type][SMP_T_STR])
11513 return 0;
11514 if (!sample_casts[smp->data.type][SMP_T_STR](smp))
11515 return 0;
11516 return 1;
11517 default:
11518 return 0;
11519 }
11520}
11521
11522static int check_aes_gcm(struct arg *args, struct sample_conv *conv,
11523 const char *file, int line, char **err)
11524{
11525 switch(args[0].data.sint) {
11526 case 128:
11527 case 192:
11528 case 256:
11529 break;
11530 default:
11531 memprintf(err, "key size must be 128, 192 or 256 (bits).");
11532 return 0;
11533 }
11534 /* Try to decode a variable. */
11535 vars_check_arg(&args[1], NULL);
11536 vars_check_arg(&args[2], NULL);
11537 vars_check_arg(&args[3], NULL);
11538 return 1;
11539}
11540
11541/* Arguements: AES size in bits, nonce, key, tag. The last three arguments are base64 encoded */
11542static int sample_conv_aes_gcm_dec(const struct arg *arg_p, struct sample *smp, void *private)
11543{
11544 struct sample nonce, key, aead_tag;
11545 struct buffer *smp_trash, *smp_trash_alloc;
11546 EVP_CIPHER_CTX *ctx;
11547 int dec_size, ret;
11548
11549 smp_set_owner(&nonce, smp->px, smp->sess, smp->strm, smp->opt);
11550 if (!sample_conv_var2smp_str(&arg_p[1], &nonce))
11551 return 0;
11552
11553 smp_set_owner(&key, smp->px, smp->sess, smp->strm, smp->opt);
11554 if (!sample_conv_var2smp_str(&arg_p[2], &key))
11555 return 0;
11556
11557 smp_set_owner(&aead_tag, smp->px, smp->sess, smp->strm, smp->opt);
11558 if (!sample_conv_var2smp_str(&arg_p[3], &aead_tag))
11559 return 0;
11560
11561 smp_trash = get_trash_chunk();
11562 smp_trash_alloc = alloc_trash_chunk();
11563 if (!smp_trash_alloc)
11564 return 0;
11565
11566 ctx = EVP_CIPHER_CTX_new();
11567
11568 if (!ctx)
11569 goto err;
11570
11571 dec_size = base64dec(nonce.data.u.str.area, nonce.data.u.str.data, smp_trash->area, smp_trash->size);
11572 if (dec_size < 0)
11573 goto err;
11574 smp_trash->data = dec_size;
11575
11576 /* Set cipher type and mode */
11577 switch(arg_p[0].data.sint) {
11578 case 128:
11579 EVP_DecryptInit_ex(ctx, EVP_aes_128_gcm(), NULL, NULL, NULL);
11580 break;
11581 case 192:
11582 EVP_DecryptInit_ex(ctx, EVP_aes_192_gcm(), NULL, NULL, NULL);
11583 break;
11584 case 256:
11585 EVP_DecryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL);
11586 break;
11587 }
11588
11589 EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, smp_trash->data, NULL);
11590
11591 /* Initialise IV */
11592 if(!EVP_DecryptInit_ex(ctx, NULL, NULL, NULL, (unsigned char *) smp_trash->area))
11593 goto err;
11594
11595 dec_size = base64dec(key.data.u.str.area, key.data.u.str.data, smp_trash->area, smp_trash->size);
11596 if (dec_size < 0)
11597 goto err;
11598 smp_trash->data = dec_size;
11599
11600 /* Initialise key */
11601 if (!EVP_DecryptInit_ex(ctx, NULL, NULL, (unsigned char *) smp_trash->area, NULL))
11602 goto err;
11603
11604 if (!EVP_DecryptUpdate(ctx, (unsigned char *) smp_trash->area, (int *) &smp_trash->data,
11605 (unsigned char *) smp->data.u.str.area, (int) smp->data.u.str.data))
11606 goto err;
11607
11608 dec_size = base64dec(aead_tag.data.u.str.area, aead_tag.data.u.str.data, smp_trash_alloc->area, smp_trash_alloc->size);
11609 if (dec_size < 0)
11610 goto err;
11611 smp_trash_alloc->data = dec_size;
11612 dec_size = smp_trash->data;
11613
11614 EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, smp_trash_alloc->data, (void *) smp_trash_alloc->area);
11615 ret = EVP_DecryptFinal_ex(ctx, (unsigned char *) smp_trash->area + smp_trash->data, (int *) &smp_trash->data);
11616
11617 if (ret <= 0)
11618 goto err;
11619
11620 smp->data.u.str.data = dec_size + smp_trash->data;
11621 smp->data.u.str.area = smp_trash->area;
11622 smp->data.type = SMP_T_BIN;
11623 smp->flags &= ~SMP_F_CONST;
11624 free_trash_chunk(smp_trash_alloc);
11625 return 1;
11626
11627err:
11628 free_trash_chunk(smp_trash_alloc);
11629 return 0;
William Lallemand32af2032016-10-29 18:09:35 +020011630}
Nenad Merdanovicc31499d2019-03-23 11:00:32 +010011631# endif
William Lallemand32af2032016-10-29 18:09:35 +020011632
Elliot Otchet71f82972020-01-15 08:12:14 -050011633/* Argument validation functions */
11634
11635/* This function is used to validate the arguments passed to any "x_dn" ssl
11636 * keywords. These keywords support specifying a third parameter that must be
11637 * either empty or the value "rfc2253". Returns 0 on error, non-zero if OK.
11638 */
11639int val_dnfmt(struct arg *arg, char **err_msg)
11640{
11641 if (arg && arg[2].type == ARGT_STR && arg[2].data.str.data > 0 && (strcmp(arg[2].data.str.area, "rfc2253") != 0)) {
11642 memprintf(err_msg, "only rfc2253 or a blank value are currently supported as the format argument.");
11643 return 0;
11644 }
11645 return 1;
11646}
11647
William Lallemand32af2032016-10-29 18:09:35 +020011648/* register cli keywords */
11649static struct cli_kw_list cli_kws = {{ },{
11650#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
11651 { { "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 +020011652 { { "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 +020011653#endif
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +010011654 { { "set", "ssl", "ocsp-response", NULL }, NULL, cli_parse_set_ocspresponse, NULL },
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011655 { { "set", "ssl", "cert", NULL }, "set ssl cert <certfile> <payload> : replace a certificate file", cli_parse_set_cert, NULL, NULL },
11656 { { "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 +010011657 { { "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 +010011658 { { "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 +020011659 { { NULL }, NULL, NULL, NULL }
11660}};
11661
Willy Tarreau0108d902018-11-25 19:14:37 +010011662INITCALL1(STG_REGISTER, cli_register_kw, &cli_kws);
William Lallemand32af2032016-10-29 18:09:35 +020011663
Willy Tarreau7875d092012-09-10 08:20:03 +020011664/* Note: must not be declared <const> as its list will be overwritten.
11665 * Please take care of keeping this list alphabetically sorted.
11666 */
Willy Tarreaudc13c112013-06-21 23:16:39 +020011667static struct sample_fetch_kw_list sample_fetch_keywords = {ILH, {
Emeric Brun645ae792014-04-30 14:21:06 +020011668 { "ssl_bc", smp_fetch_ssl_fc, 0, NULL, SMP_T_BOOL, SMP_USE_L5SRV },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +020011669 { "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 +010011670#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Jérôme Magnine064a802018-12-03 22:21:04 +010011671 { "ssl_bc_alpn", smp_fetch_ssl_fc_alpn, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
Olivier Houchard6b77f492018-11-22 18:18:29 +010011672#endif
Emeric Brun645ae792014-04-30 14:21:06 +020011673 { "ssl_bc_cipher", smp_fetch_ssl_fc_cipher, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
Olivier Houchard6b77f492018-11-22 18:18:29 +010011674#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
11675 { "ssl_bc_npn", smp_fetch_ssl_fc_npn, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
11676#endif
Emeric Brun74f7ffa2018-02-19 16:14:12 +010011677 { "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 +020011678 { "ssl_bc_protocol", smp_fetch_ssl_fc_protocol, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
Emeric Brunb73a9b02014-04-30 18:49:19 +020011679 { "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 +020011680 { "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 +020011681#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
Emeric Brun645ae792014-04-30 14:21:06 +020011682 { "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 -040011683#endif
Emmanuel Hocdet839af572019-05-14 16:27:35 +020011684#if HA_OPENSSL_VERSION_NUMBER >= 0x10100000L
Patrick Hemmer65674662019-06-04 08:13:03 -040011685 { "ssl_bc_client_random", smp_fetch_ssl_fc_random, 0, NULL, SMP_T_BIN, SMP_USE_L5SRV },
11686 { "ssl_bc_server_random", smp_fetch_ssl_fc_random, 0, NULL, SMP_T_BIN, SMP_USE_L5SRV },
Patrick Hemmere0275472018-04-28 19:15:51 -040011687 { "ssl_bc_session_key", smp_fetch_ssl_fc_session_key, 0, NULL, SMP_T_BIN, SMP_USE_L5SRV },
11688#endif
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +020011689 { "ssl_c_ca_err", smp_fetch_ssl_c_ca_err, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
11690 { "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 +010011691 { "ssl_c_der", smp_fetch_ssl_x_der, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +020011692 { "ssl_c_err", smp_fetch_ssl_c_err, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Elliot Otchet71f82972020-01-15 08:12:14 -050011693 { "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 +020011694 { "ssl_c_key_alg", smp_fetch_ssl_x_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
11695 { "ssl_c_notafter", smp_fetch_ssl_x_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
11696 { "ssl_c_notbefore", smp_fetch_ssl_x_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
11697 { "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 -050011698 { "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 +020011699 { "ssl_c_serial", smp_fetch_ssl_x_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
11700 { "ssl_c_sha1", smp_fetch_ssl_x_sha1, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +010011701 { "ssl_c_used", smp_fetch_ssl_c_used, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +020011702 { "ssl_c_verify", smp_fetch_ssl_c_verify, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
11703 { "ssl_c_version", smp_fetch_ssl_x_version, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Emeric Brun43e79582014-10-29 19:03:26 +010011704 { "ssl_f_der", smp_fetch_ssl_x_der, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Elliot Otchet71f82972020-01-15 08:12:14 -050011705 { "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 +020011706 { "ssl_f_key_alg", smp_fetch_ssl_x_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
11707 { "ssl_f_notafter", smp_fetch_ssl_x_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
11708 { "ssl_f_notbefore", smp_fetch_ssl_x_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
11709 { "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 -050011710 { "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 +020011711 { "ssl_f_serial", smp_fetch_ssl_x_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Emeric Brun55f4fa82014-04-30 17:11:25 +020011712 { "ssl_f_sha1", smp_fetch_ssl_x_sha1, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +020011713 { "ssl_f_version", smp_fetch_ssl_x_version, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +010011714 { "ssl_fc", smp_fetch_ssl_fc, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +020011715 { "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 +010011716 { "ssl_fc_cipher", smp_fetch_ssl_fc_cipher, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +010011717 { "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 +020011718 { "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 +010011719 { "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 +020011720 { "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 +010011721#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +010011722 { "ssl_fc_npn", smp_fetch_ssl_fc_npn, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreaua33c6542012-10-15 13:19:06 +020011723#endif
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +010011724#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +010011725 { "ssl_fc_alpn", smp_fetch_ssl_fc_alpn, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreauab861d32013-04-02 02:30:41 +020011726#endif
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +010011727 { "ssl_fc_protocol", smp_fetch_ssl_fc_protocol, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreau9a1ab082019-05-09 13:26:41 +020011728#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
Emeric Brunb73a9b02014-04-30 18:49:19 +020011729 { "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 -040011730#endif
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +020011731 { "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 +020011732#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +010011733 { "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 -040011734#endif
Emmanuel Hocdet839af572019-05-14 16:27:35 +020011735#if HA_OPENSSL_VERSION_NUMBER >= 0x10100000L
Patrick Hemmer65674662019-06-04 08:13:03 -040011736 { "ssl_fc_client_random", smp_fetch_ssl_fc_random, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
11737 { "ssl_fc_server_random", smp_fetch_ssl_fc_random, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Patrick Hemmere0275472018-04-28 19:15:51 -040011738 { "ssl_fc_session_key", smp_fetch_ssl_fc_session_key, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
11739#endif
Patrick Hemmer41966772018-04-28 19:15:48 -040011740#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +010011741 { "ssl_fc_sni", smp_fetch_ssl_fc_sni, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Patrick Hemmer41966772018-04-28 19:15:48 -040011742#endif
Thierry FOURNIER5bf77322017-02-25 12:45:22 +010011743 { "ssl_fc_cipherlist_bin", smp_fetch_ssl_fc_cl_bin, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
11744 { "ssl_fc_cipherlist_hex", smp_fetch_ssl_fc_cl_hex, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
11745 { "ssl_fc_cipherlist_str", smp_fetch_ssl_fc_cl_str, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
11746 { "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 +020011747 { NULL, NULL, 0, 0, 0 },
11748}};
11749
Willy Tarreau0108d902018-11-25 19:14:37 +010011750INITCALL1(STG_REGISTER, sample_register_fetches, &sample_fetch_keywords);
11751
Willy Tarreau7875d092012-09-10 08:20:03 +020011752/* Note: must not be declared <const> as its list will be overwritten.
11753 * Please take care of keeping this list alphabetically sorted.
11754 */
Willy Tarreaudc13c112013-06-21 23:16:39 +020011755static struct acl_kw_list acl_kws = {ILH, {
Thierry FOURNIERc5a4e982014-03-05 16:07:08 +010011756 { "ssl_fc_sni_end", "ssl_fc_sni", PAT_MATCH_END },
11757 { "ssl_fc_sni_reg", "ssl_fc_sni", PAT_MATCH_REG },
Willy Tarreau8ed669b2013-01-11 15:49:37 +010011758 { /* END */ },
Willy Tarreau7875d092012-09-10 08:20:03 +020011759}};
11760
Willy Tarreau0108d902018-11-25 19:14:37 +010011761INITCALL1(STG_REGISTER, acl_register_keywords, &acl_kws);
11762
Willy Tarreau79eeafa2012-09-14 07:53:05 +020011763/* Note: must not be declared <const> as its list will be overwritten.
11764 * Please take care of keeping this list alphabetically sorted, doing so helps
11765 * all code contributors.
11766 * Optional keywords are also declared with a NULL ->parse() function so that
11767 * the config parser can report an appropriate error when a known keyword was
11768 * not enabled.
11769 */
Emmanuel Hocdet98263292016-12-29 18:26:15 +010011770static struct ssl_bind_kw ssl_bind_kws[] = {
Olivier Houchardc2aae742017-09-22 18:26:28 +020011771 { "allow-0rtt", ssl_bind_parse_allow_0rtt, 0 }, /* allow 0-RTT */
Emmanuel Hocdet98263292016-12-29 18:26:15 +010011772 { "alpn", ssl_bind_parse_alpn, 1 }, /* set ALPN supported protocols */
Emmanuel Hocdet842e94e2019-12-16 16:39:17 +010011773 { "ca-file", ssl_bind_parse_ca_file, 1 }, /* set CAfile to process ca-names and verify on client cert */
11774 { "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 +010011775 { "ciphers", ssl_bind_parse_ciphers, 1 }, /* set SSL cipher suite */
Emmanuel Hocdet839af572019-05-14 16:27:35 +020011776#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +020011777 { "ciphersuites", ssl_bind_parse_ciphersuites, 1 }, /* set TLS 1.3 cipher suite */
11778#endif
Emmanuel Hocdet98263292016-12-29 18:26:15 +010011779 { "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 +010011780 { "curves", ssl_bind_parse_curves, 1 }, /* set SSL curve suite */
Emmanuel Hocdet98263292016-12-29 18:26:15 +010011781 { "ecdhe", ssl_bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +020011782 { "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 +010011783 { "npn", ssl_bind_parse_npn, 1 }, /* set NPN supported protocols */
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +020011784 { "ssl-min-ver", ssl_bind_parse_tls_method_minmax,1 }, /* minimum version */
11785 { "ssl-max-ver", ssl_bind_parse_tls_method_minmax,1 }, /* maximum version */
Emmanuel Hocdet98263292016-12-29 18:26:15 +010011786 { "verify", ssl_bind_parse_verify, 1 }, /* set SSL verify method */
11787 { NULL, NULL, 0 },
11788};
11789
Willy Tarreau0108d902018-11-25 19:14:37 +010011790/* no initcall for ssl_bind_kws, these ones are parsed in the parser loop */
11791
Willy Tarreau51fb7652012-09-18 18:24:39 +020011792static struct bind_kw_list bind_kws = { "SSL", { }, {
Olivier Houchardc2aae742017-09-22 18:26:28 +020011793 { "allow-0rtt", bind_parse_allow_0rtt, 0 }, /* Allow 0RTT */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +020011794 { "alpn", bind_parse_alpn, 1 }, /* set ALPN supported protocols */
Emmanuel Hocdet842e94e2019-12-16 16:39:17 +010011795 { "ca-file", bind_parse_ca_file, 1 }, /* set CAfile to process ca-names and verify on client cert */
11796 { "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 +020011797 { "ca-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ignore on verify depth > 0 */
11798 { "ca-sign-file", bind_parse_ca_sign_file, 1 }, /* set CAFile used to generate and sign server certs */
11799 { "ca-sign-pass", bind_parse_ca_sign_pass, 1 }, /* set CAKey passphrase */
11800 { "ciphers", bind_parse_ciphers, 1 }, /* set SSL cipher suite */
Emmanuel Hocdet839af572019-05-14 16:27:35 +020011801#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +020011802 { "ciphersuites", bind_parse_ciphersuites, 1 }, /* set TLS 1.3 cipher suite */
11803#endif
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +020011804 { "crl-file", bind_parse_crl_file, 1 }, /* set certificat revocation list file use on client cert verify */
11805 { "crt", bind_parse_crt, 1 }, /* load SSL certificates from this location */
11806 { "crt-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ingore on verify depth == 0 */
11807 { "crt-list", bind_parse_crt_list, 1 }, /* load a list of crt from this location */
11808 { "curves", bind_parse_curves, 1 }, /* set SSL curve suite */
11809 { "ecdhe", bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
11810 { "force-sslv3", bind_parse_tls_method_options, 0 }, /* force SSLv3 */
11811 { "force-tlsv10", bind_parse_tls_method_options, 0 }, /* force TLSv10 */
11812 { "force-tlsv11", bind_parse_tls_method_options, 0 }, /* force TLSv11 */
11813 { "force-tlsv12", bind_parse_tls_method_options, 0 }, /* force TLSv12 */
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +020011814 { "force-tlsv13", bind_parse_tls_method_options, 0 }, /* force TLSv13 */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +020011815 { "generate-certificates", bind_parse_generate_certs, 0 }, /* enable the server certificates generation */
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +020011816 { "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 +020011817 { "no-sslv3", bind_parse_tls_method_options, 0 }, /* disable SSLv3 */
11818 { "no-tlsv10", bind_parse_tls_method_options, 0 }, /* disable TLSv10 */
11819 { "no-tlsv11", bind_parse_tls_method_options, 0 }, /* disable TLSv11 */
11820 { "no-tlsv12", bind_parse_tls_method_options, 0 }, /* disable TLSv12 */
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +020011821 { "no-tlsv13", bind_parse_tls_method_options, 0 }, /* disable TLSv13 */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +020011822 { "no-tls-tickets", bind_parse_no_tls_tickets, 0 }, /* disable session resumption tickets */
11823 { "ssl", bind_parse_ssl, 0 }, /* enable SSL processing */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +020011824 { "ssl-min-ver", bind_parse_tls_method_minmax, 1 }, /* minimum version */
11825 { "ssl-max-ver", bind_parse_tls_method_minmax, 1 }, /* maximum version */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +020011826 { "strict-sni", bind_parse_strict_sni, 0 }, /* refuse negotiation if sni doesn't match a certificate */
11827 { "tls-ticket-keys", bind_parse_tls_ticket_keys, 1 }, /* set file to load TLS ticket keys from */
11828 { "verify", bind_parse_verify, 1 }, /* set SSL verify method */
11829 { "npn", bind_parse_npn, 1 }, /* set NPN supported protocols */
11830 { "prefer-client-ciphers", bind_parse_pcc, 0 }, /* prefer client ciphers */
Willy Tarreau79eeafa2012-09-14 07:53:05 +020011831 { NULL, NULL, 0 },
11832}};
Emeric Brun46591952012-05-18 15:47:34 +020011833
Willy Tarreau0108d902018-11-25 19:14:37 +010011834INITCALL1(STG_REGISTER, bind_register_keywords, &bind_kws);
11835
Willy Tarreau92faadf2012-10-10 23:04:25 +020011836/* Note: must not be declared <const> as its list will be overwritten.
11837 * Please take care of keeping this list alphabetically sorted, doing so helps
11838 * all code contributors.
11839 * Optional keywords are also declared with a NULL ->parse() function so that
11840 * the config parser can report an appropriate error when a known keyword was
11841 * not enabled.
11842 */
11843static struct srv_kw_list srv_kws = { "SSL", { }, {
Olivier Houchard522eea72017-11-03 16:27:47 +010011844 { "allow-0rtt", srv_parse_allow_0rtt, 0, 1 }, /* Allow using early data on this server */
Olivier Houchardc7566002018-11-20 23:33:50 +010011845 { "alpn", srv_parse_alpn, 1, 1 }, /* Set ALPN supported protocols */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +020011846 { "ca-file", srv_parse_ca_file, 1, 1 }, /* set CAfile to process verify server cert */
Olivier Houchard92150142018-12-21 19:47:01 +010011847 { "check-alpn", srv_parse_alpn, 1, 1 }, /* Set ALPN used for checks */
Olivier Houchard9130a962017-10-17 17:33:43 +020011848 { "check-sni", srv_parse_check_sni, 1, 1 }, /* set SNI */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +020011849 { "check-ssl", srv_parse_check_ssl, 0, 1 }, /* enable SSL for health checks */
11850 { "ciphers", srv_parse_ciphers, 1, 1 }, /* select the cipher suite */
Emmanuel Hocdet839af572019-05-14 16:27:35 +020011851#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +020011852 { "ciphersuites", srv_parse_ciphersuites, 1, 1 }, /* select the cipher suite */
11853#endif
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +020011854 { "crl-file", srv_parse_crl_file, 1, 1 }, /* set certificate revocation list file use on server cert verify */
11855 { "crt", srv_parse_crt, 1, 1 }, /* set client certificate */
11856 { "force-sslv3", srv_parse_tls_method_options, 0, 1 }, /* force SSLv3 */
11857 { "force-tlsv10", srv_parse_tls_method_options, 0, 1 }, /* force TLSv10 */
11858 { "force-tlsv11", srv_parse_tls_method_options, 0, 1 }, /* force TLSv11 */
11859 { "force-tlsv12", srv_parse_tls_method_options, 0, 1 }, /* force TLSv12 */
11860 { "force-tlsv13", srv_parse_tls_method_options, 0, 1 }, /* force TLSv13 */
11861 { "no-check-ssl", srv_parse_no_check_ssl, 0, 1 }, /* disable SSL for health checks */
11862 { "no-send-proxy-v2-ssl", srv_parse_no_send_proxy_ssl, 0, 1 }, /* do not send PROXY protocol header v2 with SSL info */
11863 { "no-send-proxy-v2-ssl-cn", srv_parse_no_send_proxy_cn, 0, 1 }, /* do not send PROXY protocol header v2 with CN */
11864 { "no-ssl", srv_parse_no_ssl, 0, 1 }, /* disable SSL processing */
11865 { "no-ssl-reuse", srv_parse_no_ssl_reuse, 0, 1 }, /* disable session reuse */
11866 { "no-sslv3", srv_parse_tls_method_options, 0, 0 }, /* disable SSLv3 */
11867 { "no-tlsv10", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv10 */
11868 { "no-tlsv11", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv11 */
11869 { "no-tlsv12", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv12 */
11870 { "no-tlsv13", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv13 */
11871 { "no-tls-tickets", srv_parse_no_tls_tickets, 0, 1 }, /* disable session resumption tickets */
Olivier Houchardc7566002018-11-20 23:33:50 +010011872 { "npn", srv_parse_npn, 1, 1 }, /* Set NPN supported protocols */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +020011873 { "send-proxy-v2-ssl", srv_parse_send_proxy_ssl, 0, 1 }, /* send PROXY protocol header v2 with SSL info */
11874 { "send-proxy-v2-ssl-cn", srv_parse_send_proxy_cn, 0, 1 }, /* send PROXY protocol header v2 with CN */
11875 { "sni", srv_parse_sni, 1, 1 }, /* send SNI extension */
11876 { "ssl", srv_parse_ssl, 0, 1 }, /* enable SSL processing */
11877 { "ssl-min-ver", srv_parse_tls_method_minmax, 1, 1 }, /* minimum version */
11878 { "ssl-max-ver", srv_parse_tls_method_minmax, 1, 1 }, /* maximum version */
11879 { "ssl-reuse", srv_parse_ssl_reuse, 0, 1 }, /* enable session reuse */
11880 { "tls-tickets", srv_parse_tls_tickets, 0, 1 }, /* enable session resumption tickets */
11881 { "verify", srv_parse_verify, 1, 1 }, /* set SSL verify method */
11882 { "verifyhost", srv_parse_verifyhost, 1, 1 }, /* require that SSL cert verifies for hostname */
Willy Tarreau92faadf2012-10-10 23:04:25 +020011883 { NULL, NULL, 0, 0 },
11884}};
11885
Willy Tarreau0108d902018-11-25 19:14:37 +010011886INITCALL1(STG_REGISTER, srv_register_keywords, &srv_kws);
11887
Emeric Brun2c86cbf2014-10-30 15:56:50 +010011888static struct cfg_kw_list cfg_kws = {ILH, {
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +010011889 { CFG_GLOBAL, "ca-base", ssl_parse_global_ca_crt_base },
11890 { CFG_GLOBAL, "crt-base", ssl_parse_global_ca_crt_base },
Emmanuel Hocdet70df7bf2019-01-04 11:08:20 +010011891 { CFG_GLOBAL, "issuers-chain-path", ssl_load_global_issuers_from_path },
Willy Tarreau0bea58d2016-12-21 23:17:25 +010011892 { CFG_GLOBAL, "maxsslconn", ssl_parse_global_int },
Emeric Brun2c86cbf2014-10-30 15:56:50 +010011893 { CFG_GLOBAL, "ssl-default-bind-options", ssl_parse_default_bind_options },
11894 { CFG_GLOBAL, "ssl-default-server-options", ssl_parse_default_server_options },
Willy Tarreau14e36a12016-12-21 23:28:13 +010011895#ifndef OPENSSL_NO_DH
11896 { CFG_GLOBAL, "ssl-dh-param-file", ssl_parse_global_dh_param_file },
11897#endif
Grant Zhangfa6c7ee2017-01-14 01:42:15 +000011898 { CFG_GLOBAL, "ssl-mode-async", ssl_parse_global_ssl_async },
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020011899#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +000011900 { CFG_GLOBAL, "ssl-engine", ssl_parse_global_ssl_engine },
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020011901#endif
Willy Tarreau9ceda382016-12-21 23:13:03 +010011902 { CFG_GLOBAL, "tune.ssl.cachesize", ssl_parse_global_int },
11903#ifndef OPENSSL_NO_DH
11904 { CFG_GLOBAL, "tune.ssl.default-dh-param", ssl_parse_global_default_dh },
11905#endif
11906 { CFG_GLOBAL, "tune.ssl.force-private-cache", ssl_parse_global_private_cache },
11907 { CFG_GLOBAL, "tune.ssl.lifetime", ssl_parse_global_lifetime },
11908 { CFG_GLOBAL, "tune.ssl.maxrecord", ssl_parse_global_int },
11909 { CFG_GLOBAL, "tune.ssl.ssl-ctx-cache-size", ssl_parse_global_int },
Thierry FOURNIER5bf77322017-02-25 12:45:22 +010011910 { CFG_GLOBAL, "tune.ssl.capture-cipherlist-size", ssl_parse_global_capture_cipherlist },
Willy Tarreauf22e9682016-12-21 23:23:19 +010011911 { CFG_GLOBAL, "ssl-default-bind-ciphers", ssl_parse_global_ciphers },
11912 { CFG_GLOBAL, "ssl-default-server-ciphers", ssl_parse_global_ciphers },
Emmanuel Hocdet839af572019-05-14 16:27:35 +020011913#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +020011914 { CFG_GLOBAL, "ssl-default-bind-ciphersuites", ssl_parse_global_ciphersuites },
11915 { CFG_GLOBAL, "ssl-default-server-ciphersuites", ssl_parse_global_ciphersuites },
11916#endif
William Lallemand3af48e72020-02-03 17:15:52 +010011917 { CFG_GLOBAL, "ssl-load-extra-files", ssl_parse_global_extra_files },
Emeric Brun2c86cbf2014-10-30 15:56:50 +010011918 { 0, NULL, NULL },
11919}};
11920
Willy Tarreau0108d902018-11-25 19:14:37 +010011921INITCALL1(STG_REGISTER, cfg_register_keywords, &cfg_kws);
11922
Nenad Merdanovicc31499d2019-03-23 11:00:32 +010011923/* Note: must not be declared <const> as its list will be overwritten */
11924static struct sample_conv_kw_list conv_kws = {ILH, {
Willy Tarreau86a394e2019-05-09 14:15:32 +020011925#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000100fL)
Nenad Merdanovicc31499d2019-03-23 11:00:32 +010011926 { "aes_gcm_dec", sample_conv_aes_gcm_dec, ARG4(4,SINT,STR,STR,STR), check_aes_gcm, SMP_T_BIN, SMP_T_BIN },
11927#endif
11928 { NULL, NULL, 0, 0, 0 },
11929}};
11930
11931INITCALL1(STG_REGISTER, sample_register_convs, &conv_kws);
11932
Willy Tarreauf7bc57c2012-10-03 00:19:48 +020011933/* transport-layer operations for SSL sockets */
Willy Tarreaud9f5cca2016-12-22 21:08:52 +010011934static struct xprt_ops ssl_sock = {
Emeric Brun46591952012-05-18 15:47:34 +020011935 .snd_buf = ssl_sock_from_buf,
11936 .rcv_buf = ssl_sock_to_buf,
Olivier Houcharddf357842019-03-21 16:30:07 +010011937 .subscribe = ssl_subscribe,
11938 .unsubscribe = ssl_unsubscribe,
Olivier Houchard5149b592019-05-23 17:47:36 +020011939 .remove_xprt = ssl_remove_xprt,
Olivier Houchard2e055482019-05-27 19:50:12 +020011940 .add_xprt = ssl_add_xprt,
Emeric Brun46591952012-05-18 15:47:34 +020011941 .rcv_pipe = NULL,
11942 .snd_pipe = NULL,
11943 .shutr = NULL,
11944 .shutw = ssl_sock_shutw,
11945 .close = ssl_sock_close,
11946 .init = ssl_sock_init,
Willy Tarreau55d37912016-12-21 23:38:39 +010011947 .prepare_bind_conf = ssl_sock_prepare_bind_conf,
Willy Tarreau795cdab2016-12-22 17:30:54 +010011948 .destroy_bind_conf = ssl_sock_destroy_bind_conf,
Willy Tarreau17d45382016-12-22 21:16:08 +010011949 .prepare_srv = ssl_sock_prepare_srv_ctx,
11950 .destroy_srv = ssl_sock_free_srv_ctx,
Willy Tarreau8743f7e2016-12-04 18:44:29 +010011951 .get_alpn = ssl_sock_get_alpn,
Willy Tarreau8e0bb0a2016-11-24 16:58:12 +010011952 .name = "SSL",
Emeric Brun46591952012-05-18 15:47:34 +020011953};
11954
Olivier Houchardccaa7de2017-10-02 11:51:03 +020011955enum act_return ssl_action_wait_for_hs(struct act_rule *rule, struct proxy *px,
11956 struct session *sess, struct stream *s, int flags)
11957{
11958 struct connection *conn;
Olivier Houchard6fa63d92017-11-27 18:41:32 +010011959 struct conn_stream *cs;
Olivier Houchardccaa7de2017-10-02 11:51:03 +020011960
11961 conn = objt_conn(sess->origin);
Olivier Houchard6fa63d92017-11-27 18:41:32 +010011962 cs = objt_cs(s->si[0].end);
Olivier Houchardccaa7de2017-10-02 11:51:03 +020011963
Olivier Houchard6fa63d92017-11-27 18:41:32 +010011964 if (conn && cs) {
Olivier Houchardccaa7de2017-10-02 11:51:03 +020011965 if (conn->flags & (CO_FL_EARLY_SSL_HS | CO_FL_SSL_WAIT_HS)) {
Olivier Houchard6fa63d92017-11-27 18:41:32 +010011966 cs->flags |= CS_FL_WAIT_FOR_HS;
Olivier Houchardccaa7de2017-10-02 11:51:03 +020011967 s->req.flags |= CF_READ_NULL;
11968 return ACT_RET_YIELD;
11969 }
11970 }
11971 return (ACT_RET_CONT);
11972}
11973
11974static enum act_parse_ret ssl_parse_wait_for_hs(const char **args, int *orig_arg, struct proxy *px, struct act_rule *rule, char **err)
11975{
11976 rule->action_ptr = ssl_action_wait_for_hs;
11977
11978 return ACT_RET_PRS_OK;
11979}
11980
11981static struct action_kw_list http_req_actions = {ILH, {
11982 { "wait-for-handshake", ssl_parse_wait_for_hs },
11983 { /* END */ }
11984}};
11985
Willy Tarreau0108d902018-11-25 19:14:37 +010011986INITCALL1(STG_REGISTER, http_req_keywords_register, &http_req_actions);
11987
Willy Tarreau5db847a2019-05-09 14:13:35 +020011988#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +010011989
11990static void ssl_sock_sctl_free_func(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, long argl, void *argp)
11991{
11992 if (ptr) {
11993 chunk_destroy(ptr);
11994 free(ptr);
11995 }
11996}
11997
11998#endif
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +010011999static void ssl_sock_capture_free_func(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, long argl, void *argp)
12000{
Willy Tarreaubafbe012017-11-24 17:34:44 +010012001 pool_free(pool_head_ssl_capture, ptr);
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +010012002}
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +010012003
Emeric Brun46591952012-05-18 15:47:34 +020012004__attribute__((constructor))
Willy Tarreau92faadf2012-10-10 23:04:25 +020012005static void __ssl_sock_init(void)
12006{
Ilya Shipitsin0590f442019-05-25 19:30:50 +050012007#if (!defined(OPENSSL_NO_COMP) && !defined(SSL_OP_NO_COMPRESSION))
Emeric Brun46591952012-05-18 15:47:34 +020012008 STACK_OF(SSL_COMP)* cm;
Ilya Shipitsine242f3d2019-05-25 03:38:14 +050012009 int n;
Ilya Shipitsin0590f442019-05-25 19:30:50 +050012010#endif
Emeric Brun46591952012-05-18 15:47:34 +020012011
Willy Tarreauef934602016-12-22 23:12:01 +010012012 if (global_ssl.listen_default_ciphers)
12013 global_ssl.listen_default_ciphers = strdup(global_ssl.listen_default_ciphers);
12014 if (global_ssl.connect_default_ciphers)
12015 global_ssl.connect_default_ciphers = strdup(global_ssl.connect_default_ciphers);
Emmanuel Hocdet839af572019-05-14 16:27:35 +020012016#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +020012017 if (global_ssl.listen_default_ciphersuites)
12018 global_ssl.listen_default_ciphersuites = strdup(global_ssl.listen_default_ciphersuites);
12019 if (global_ssl.connect_default_ciphersuites)
12020 global_ssl.connect_default_ciphersuites = strdup(global_ssl.connect_default_ciphersuites);
12021#endif
Willy Tarreau610f04b2014-02-13 11:36:41 +010012022
Willy Tarreau13e14102016-12-22 20:25:26 +010012023 xprt_register(XPRT_SSL, &ssl_sock);
Willy Tarreau9a1ab082019-05-09 13:26:41 +020012024#if HA_OPENSSL_VERSION_NUMBER < 0x10100000L
Emeric Brun46591952012-05-18 15:47:34 +020012025 SSL_library_init();
Rosen Penev68185952018-12-14 08:47:02 -080012026#endif
Ilya Shipitsin0590f442019-05-25 19:30:50 +050012027#if (!defined(OPENSSL_NO_COMP) && !defined(SSL_OP_NO_COMPRESSION))
Emeric Brun46591952012-05-18 15:47:34 +020012028 cm = SSL_COMP_get_compression_methods();
Ilya Shipitsine242f3d2019-05-25 03:38:14 +050012029 n = sk_SSL_COMP_num(cm);
12030 while (n--) {
12031 (void) sk_SSL_COMP_pop(cm);
12032 }
Ilya Shipitsin0590f442019-05-25 19:30:50 +050012033#endif
Ilya Shipitsine242f3d2019-05-25 03:38:14 +050012034
Willy Tarreau5db847a2019-05-09 14:13:35 +020012035#if defined(USE_THREAD) && (HA_OPENSSL_VERSION_NUMBER < 0x10100000L)
Emeric Brun821bb9b2017-06-15 16:37:39 +020012036 ssl_locking_init();
12037#endif
Willy Tarreau5db847a2019-05-09 14:13:35 +020012038#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +010012039 sctl_ex_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, ssl_sock_sctl_free_func);
12040#endif
Thierry FOURNIER28962c92018-06-17 21:37:05 +020012041 ssl_app_data_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL);
Thierry FOURNIER16ff0502018-06-17 21:33:01 +020012042 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 +020012043#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +000012044 ENGINE_load_builtin_engines();
Grant Zhangfa6c7ee2017-01-14 01:42:15 +000012045 hap_register_post_check(ssl_check_async_engine_count);
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020012046#endif
Willy Tarreaud1c57502016-12-22 22:46:15 +010012047#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
12048 hap_register_post_check(tlskeys_finalize_config);
12049#endif
Willy Tarreau80713382018-11-26 10:19:54 +010012050
12051 global.ssl_session_max_cost = SSL_SESSION_MAX_COST;
12052 global.ssl_handshake_max_cost = SSL_HANDSHAKE_MAX_COST;
12053
Emmanuel Hocdet70df7bf2019-01-04 11:08:20 +010012054 hap_register_post_deinit(ssl_free_global_issuers);
12055
Willy Tarreau80713382018-11-26 10:19:54 +010012056#ifndef OPENSSL_NO_DH
12057 ssl_dh_ptr_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, NULL);
12058 hap_register_post_deinit(ssl_free_dh);
12059#endif
12060#ifndef OPENSSL_NO_ENGINE
12061 hap_register_post_deinit(ssl_free_engines);
12062#endif
12063 /* Load SSL string for the verbose & debug mode. */
12064 ERR_load_SSL_strings();
Olivier Houcharda8955d52019-04-07 22:00:38 +020012065 ha_meth = BIO_meth_new(0x666, "ha methods");
12066 BIO_meth_set_write(ha_meth, ha_ssl_write);
12067 BIO_meth_set_read(ha_meth, ha_ssl_read);
12068 BIO_meth_set_ctrl(ha_meth, ha_ssl_ctrl);
12069 BIO_meth_set_create(ha_meth, ha_ssl_new);
12070 BIO_meth_set_destroy(ha_meth, ha_ssl_free);
12071 BIO_meth_set_puts(ha_meth, ha_ssl_puts);
12072 BIO_meth_set_gets(ha_meth, ha_ssl_gets);
William Lallemand150bfa82019-09-19 17:12:49 +020012073
12074 HA_SPIN_INIT(&ckch_lock);
Willy Tarreau80713382018-11-26 10:19:54 +010012075}
Willy Tarreaud92aa5c2015-01-15 21:34:39 +010012076
Willy Tarreau80713382018-11-26 10:19:54 +010012077/* Compute and register the version string */
12078static void ssl_register_build_options()
12079{
12080 char *ptr = NULL;
12081 int i;
12082
Willy Tarreauc2c0b612016-12-21 19:23:20 +010012083 memprintf(&ptr, "Built with OpenSSL version : "
12084#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet50e25e12017-03-24 15:20:03 +010012085 "BoringSSL");
Willy Tarreauc2c0b612016-12-21 19:23:20 +010012086#else /* OPENSSL_IS_BORINGSSL */
12087 OPENSSL_VERSION_TEXT
12088 "\nRunning on OpenSSL version : %s%s",
Rosen Penev68185952018-12-14 08:47:02 -080012089 OpenSSL_version(OPENSSL_VERSION),
Willy Tarreau1d158ab2019-05-09 13:41:45 +020012090 ((OPENSSL_VERSION_NUMBER ^ OpenSSL_version_num()) >> 8) ? " (VERSIONS DIFFER!)" : "");
Willy Tarreauc2c0b612016-12-21 19:23:20 +010012091#endif
12092 memprintf(&ptr, "%s\nOpenSSL library supports TLS extensions : "
Willy Tarreau9a1ab082019-05-09 13:26:41 +020012093#if HA_OPENSSL_VERSION_NUMBER < 0x00907000L
Willy Tarreauc2c0b612016-12-21 19:23:20 +010012094 "no (library version too old)"
12095#elif defined(OPENSSL_NO_TLSEXT)
12096 "no (disabled via OPENSSL_NO_TLSEXT)"
12097#else
12098 "yes"
12099#endif
12100 "", ptr);
12101
12102 memprintf(&ptr, "%s\nOpenSSL library supports SNI : "
12103#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
12104 "yes"
12105#else
12106#ifdef OPENSSL_NO_TLSEXT
12107 "no (because of OPENSSL_NO_TLSEXT)"
12108#else
12109 "no (version might be too old, 0.9.8f min needed)"
12110#endif
12111#endif
12112 "", ptr);
12113
Emmanuel Hocdetf80bc242017-07-12 14:25:38 +020012114 memprintf(&ptr, "%s\nOpenSSL library supports :", ptr);
12115 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
12116 if (methodVersions[i].option)
12117 memprintf(&ptr, "%s %s", ptr, methodVersions[i].name);
Emmanuel Hocdet50e25e12017-03-24 15:20:03 +010012118
Willy Tarreauc2c0b612016-12-21 19:23:20 +010012119 hap_register_build_opts(ptr, 1);
Willy Tarreau80713382018-11-26 10:19:54 +010012120}
Willy Tarreauc2c0b612016-12-21 19:23:20 +010012121
Willy Tarreau80713382018-11-26 10:19:54 +010012122INITCALL0(STG_REGISTER, ssl_register_build_options);
Remi Gacogne4f902b82015-05-28 16:23:00 +020012123
Emeric Brun46591952012-05-18 15:47:34 +020012124
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020012125#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +000012126void ssl_free_engines(void) {
12127 struct ssl_engine_list *wl, *wlb;
12128 /* free up engine list */
12129 list_for_each_entry_safe(wl, wlb, &openssl_engines, list) {
12130 ENGINE_finish(wl->e);
12131 ENGINE_free(wl->e);
12132 LIST_DEL(&wl->list);
12133 free(wl);
12134 }
12135}
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020012136#endif
Christopher Faulet31af49d2015-06-09 17:29:50 +020012137
Remi Gacogned3a23c32015-05-28 16:39:47 +020012138#ifndef OPENSSL_NO_DH
Grant Zhang872f9c22017-01-21 01:10:18 +000012139void ssl_free_dh(void) {
12140 if (local_dh_1024) {
12141 DH_free(local_dh_1024);
12142 local_dh_1024 = NULL;
12143 }
12144 if (local_dh_2048) {
12145 DH_free(local_dh_2048);
12146 local_dh_2048 = NULL;
12147 }
12148 if (local_dh_4096) {
12149 DH_free(local_dh_4096);
12150 local_dh_4096 = NULL;
12151 }
Remi Gacogne47783ef2015-05-29 15:53:22 +020012152 if (global_dh) {
12153 DH_free(global_dh);
12154 global_dh = NULL;
12155 }
Grant Zhang872f9c22017-01-21 01:10:18 +000012156}
12157#endif
12158
12159__attribute__((destructor))
12160static void __ssl_sock_deinit(void)
12161{
12162#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Emeric Brun821bb9b2017-06-15 16:37:39 +020012163 if (ssl_ctx_lru_tree) {
12164 lru64_destroy(ssl_ctx_lru_tree);
Christopher Faulet2a944ee2017-11-07 10:42:54 +010012165 HA_RWLOCK_DESTROY(&ssl_ctx_lru_rwlock);
Emeric Brun821bb9b2017-06-15 16:37:39 +020012166 }
Remi Gacogned3a23c32015-05-28 16:39:47 +020012167#endif
12168
Willy Tarreau5db847a2019-05-09 14:13:35 +020012169#if (HA_OPENSSL_VERSION_NUMBER < 0x10100000L)
Remi Gacogned3a23c32015-05-28 16:39:47 +020012170 ERR_remove_state(0);
12171 ERR_free_strings();
12172
12173 EVP_cleanup();
Rosen Penev68185952018-12-14 08:47:02 -080012174#endif
Remi Gacogned3a23c32015-05-28 16:39:47 +020012175
Willy Tarreau5db847a2019-05-09 14:13:35 +020012176#if (HA_OPENSSL_VERSION_NUMBER >= 0x00907000L) && (HA_OPENSSL_VERSION_NUMBER < 0x10100000L)
Remi Gacogned3a23c32015-05-28 16:39:47 +020012177 CRYPTO_cleanup_all_ex_data();
12178#endif
Olivier Houcharda8955d52019-04-07 22:00:38 +020012179 BIO_meth_free(ha_meth);
Remi Gacogned3a23c32015-05-28 16:39:47 +020012180}
12181
12182
Emeric Brun46591952012-05-18 15:47:34 +020012183/*
12184 * Local variables:
12185 * c-indent-level: 8
12186 * c-basic-offset: 8
12187 * End:
12188 */