blob: 577f785539f6d07d410c5d10639189379350021e [file] [log] [blame]
yanbzhu08ce6ab2015-12-02 13:01:29 -05001
Emeric Brun46591952012-05-18 15:47:34 +02002/*
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02003 * SSL/TLS transport layer over SOCK_STREAM sockets
Emeric Brun46591952012-05-18 15:47:34 +02004 *
5 * Copyright (C) 2012 EXCELIANCE, Emeric Brun <ebrun@exceliance.fr>
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version
10 * 2 of the License, or (at your option) any later version.
11 *
Willy Tarreau69845df2012-09-10 09:43:09 +020012 * Acknowledgement:
13 * We'd like to specially thank the Stud project authors for a very clean
14 * and well documented code which helped us understand how the OpenSSL API
15 * ought to be used in non-blocking mode. This is one difficult part which
16 * is not easy to get from the OpenSSL doc, and reading the Stud code made
17 * it much more obvious than the examples in the OpenSSL package. Keep up
18 * the good works, guys !
19 *
20 * Stud is an extremely efficient and scalable SSL/TLS proxy which combines
21 * particularly well with haproxy. For more info about this project, visit :
22 * https://github.com/bumptech/stud
23 *
Emeric Brun46591952012-05-18 15:47:34 +020024 */
25
Willy Tarreau8d164dc2019-05-10 09:35:00 +020026/* Note: do NOT include openssl/xxx.h here, do it in openssl-compat.h */
Emeric Brun46591952012-05-18 15:47:34 +020027#define _GNU_SOURCE
Emeric Brunfc0421f2012-09-07 17:30:07 +020028#include <ctype.h>
29#include <dirent.h>
Emeric Brun46591952012-05-18 15:47:34 +020030#include <errno.h>
31#include <fcntl.h>
32#include <stdio.h>
33#include <stdlib.h>
Emeric Brunfc0421f2012-09-07 17:30:07 +020034#include <string.h>
35#include <unistd.h>
Emeric Brun46591952012-05-18 15:47:34 +020036
37#include <sys/socket.h>
38#include <sys/stat.h>
39#include <sys/types.h>
Christopher Faulet31af49d2015-06-09 17:29:50 +020040#include <netdb.h>
Emeric Brun46591952012-05-18 15:47:34 +020041#include <netinet/tcp.h>
42
Christopher Faulet31af49d2015-06-09 17:29:50 +020043#include <import/lru.h>
44#include <import/xxhash.h>
45
Emeric Brun46591952012-05-18 15:47:34 +020046#include <common/buffer.h>
Willy Tarreau843b7cb2018-07-13 10:54:26 +020047#include <common/chunk.h>
Emeric Brun46591952012-05-18 15:47:34 +020048#include <common/compat.h>
49#include <common/config.h>
50#include <common/debug.h>
Willy Tarreau79eeafa2012-09-14 07:53:05 +020051#include <common/errors.h>
Willy Tarreau0108d902018-11-25 19:14:37 +010052#include <common/initcall.h>
Willy Tarreau55994562019-05-09 14:52:44 +020053#include <common/openssl-compat.h>
Emeric Brun46591952012-05-18 15:47:34 +020054#include <common/standard.h>
55#include <common/ticks.h>
56#include <common/time.h>
Emeric Brun2c86cbf2014-10-30 15:56:50 +010057#include <common/cfgparse.h>
Nenad Merdanovic05552d42015-02-27 19:56:49 +010058#include <common/base64.h>
Emeric Brun46591952012-05-18 15:47:34 +020059
Emeric Brunfc0421f2012-09-07 17:30:07 +020060#include <ebsttree.h>
61
William Lallemand32af2032016-10-29 18:09:35 +020062#include <types/applet.h>
63#include <types/cli.h>
Emeric Brunfc0421f2012-09-07 17:30:07 +020064#include <types/global.h>
65#include <types/ssl_sock.h>
William Lallemand32af2032016-10-29 18:09:35 +020066#include <types/stats.h>
Emeric Brunfc0421f2012-09-07 17:30:07 +020067
Willy Tarreau7875d092012-09-10 08:20:03 +020068#include <proto/acl.h>
69#include <proto/arg.h>
William Lallemand32af2032016-10-29 18:09:35 +020070#include <proto/channel.h>
Emeric Brun46591952012-05-18 15:47:34 +020071#include <proto/connection.h>
William Lallemand32af2032016-10-29 18:09:35 +020072#include <proto/cli.h>
Emeric Brun46591952012-05-18 15:47:34 +020073#include <proto/fd.h>
74#include <proto/freq_ctr.h>
75#include <proto/frontend.h>
Willy Tarreau61c112a2018-10-02 16:43:32 +020076#include <proto/http_rules.h>
Willy Tarreau79eeafa2012-09-14 07:53:05 +020077#include <proto/listener.h>
Thierry FOURNIERed66c292013-11-28 11:05:19 +010078#include <proto/pattern.h>
Christopher Faulet31af49d2015-06-09 17:29:50 +020079#include <proto/proto_tcp.h>
Christopher Fauletfc9cfe42019-07-16 14:54:53 +020080#include <proto/http_ana.h>
Willy Tarreau92faadf2012-10-10 23:04:25 +020081#include <proto/server.h>
William Lallemand32af2032016-10-29 18:09:35 +020082#include <proto/stream_interface.h>
Emeric Brun46591952012-05-18 15:47:34 +020083#include <proto/log.h>
Emeric Brun94324a42012-10-11 14:00:19 +020084#include <proto/proxy.h>
Emeric Brunfc0421f2012-09-07 17:30:07 +020085#include <proto/shctx.h>
Emeric Brun46591952012-05-18 15:47:34 +020086#include <proto/ssl_sock.h>
Willy Tarreau9ad7bd42015-04-03 19:19:59 +020087#include <proto/stream.h>
Emeric Brun46591952012-05-18 15:47:34 +020088#include <proto/task.h>
Nenad Merdanovicc31499d2019-03-23 11:00:32 +010089#include <proto/vars.h>
Emeric Brun46591952012-05-18 15:47:34 +020090
Willy Tarreau9356dac2019-05-10 09:22:53 +020091/* ***** READ THIS before adding code here! *****
92 *
93 * Due to API incompatibilities between multiple OpenSSL versions and their
94 * derivatives, it's often tempting to add macros to (re-)define certain
95 * symbols. Please do not do this here, and do it in common/openssl-compat.h
96 * exclusively so that the whole code consistently uses the same macros.
97 *
98 * Whenever possible if a macro is missing in certain versions, it's better
99 * to conditionally define it in openssl-compat.h than using lots of ifdefs.
100 */
101
Willy Tarreau518cedd2014-02-17 15:43:01 +0100102/* Warning, these are bits, not integers! */
Emeric Brune64aef12012-09-21 13:15:06 +0200103#define SSL_SOCK_ST_FL_VERIFY_DONE 0x00000001
Emeric Brund8b2bb52014-01-28 15:43:53 +0100104#define SSL_SOCK_ST_FL_16K_WBFSIZE 0x00000002
Willy Tarreau518cedd2014-02-17 15:43:01 +0100105#define SSL_SOCK_SEND_UNLIMITED 0x00000004
Emeric Brun29f037d2014-04-25 19:05:36 +0200106#define SSL_SOCK_RECV_HEARTBEAT 0x00000008
107
Emeric Brunf282a812012-09-21 15:27:54 +0200108/* bits 0xFFFF0000 are reserved to store verify errors */
109
110/* Verify errors macros */
111#define SSL_SOCK_CA_ERROR_TO_ST(e) (((e > 63) ? 63 : e) << (16))
112#define SSL_SOCK_CAEDEPTH_TO_ST(d) (((d > 15) ? 15 : d) << (6+16))
113#define SSL_SOCK_CRTERROR_TO_ST(e) (((e > 63) ? 63 : e) << (4+6+16))
114
115#define SSL_SOCK_ST_TO_CA_ERROR(s) ((s >> (16)) & 63)
116#define SSL_SOCK_ST_TO_CAEDEPTH(s) ((s >> (6+16)) & 15)
117#define SSL_SOCK_ST_TO_CRTERROR(s) ((s >> (4+6+16)) & 63)
Emeric Brune64aef12012-09-21 13:15:06 +0200118
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200119/* ssl_methods flags for ssl options */
120#define MC_SSL_O_ALL 0x0000
121#define MC_SSL_O_NO_SSLV3 0x0001 /* disable SSLv3 */
122#define MC_SSL_O_NO_TLSV10 0x0002 /* disable TLSv10 */
123#define MC_SSL_O_NO_TLSV11 0x0004 /* disable TLSv11 */
124#define MC_SSL_O_NO_TLSV12 0x0008 /* disable TLSv12 */
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +0200125#define MC_SSL_O_NO_TLSV13 0x0010 /* disable TLSv13 */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200126
William Lallemand3af48e72020-02-03 17:15:52 +0100127/* file to guess during file loading */
128#define SSL_GF_NONE 0x00000000 /* Don't guess any file, only open the files specified in the configuration files */
129#define SSL_GF_BUNDLE 0x00000001 /* try to open the bundles */
130#define SSL_GF_SCTL 0x00000002 /* try to open the .sctl file */
131#define SSL_GF_OCSP 0x00000004 /* try to open the .ocsp file */
132#define SSL_GF_OCSP_ISSUER 0x00000008 /* try to open the .issuer file if an OCSP file was loaded */
William Lallemand4c5adbf2020-02-24 14:23:22 +0100133#define SSL_GF_KEY 0x00000010 /* try to open the .key file to load a private key */
William Lallemand3af48e72020-02-03 17:15:52 +0100134
William Lallemand4c5adbf2020-02-24 14:23:22 +0100135#define SSL_GF_ALL (SSL_GF_BUNDLE|SSL_GF_SCTL|SSL_GF_OCSP|SSL_GF_OCSP_ISSUER|SSL_GF_KEY)
William Lallemand3af48e72020-02-03 17:15:52 +0100136
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200137/* ssl_methods versions */
138enum {
139 CONF_TLSV_NONE = 0,
140 CONF_TLSV_MIN = 1,
141 CONF_SSLV3 = 1,
142 CONF_TLSV10 = 2,
143 CONF_TLSV11 = 3,
144 CONF_TLSV12 = 4,
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +0200145 CONF_TLSV13 = 5,
146 CONF_TLSV_MAX = 5,
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200147};
148
Emeric Brun850efd52014-01-29 12:24:34 +0100149/* server and bind verify method, it uses a global value as default */
150enum {
151 SSL_SOCK_VERIFY_DEFAULT = 0,
152 SSL_SOCK_VERIFY_REQUIRED = 1,
153 SSL_SOCK_VERIFY_OPTIONAL = 2,
154 SSL_SOCK_VERIFY_NONE = 3,
155};
156
Willy Tarreau71b734c2014-01-28 15:19:44 +0100157int sslconns = 0;
158int totalsslconns = 0;
Willy Tarreaud9f5cca2016-12-22 21:08:52 +0100159static struct xprt_ops ssl_sock;
Emeric Brunece0c332017-12-06 13:51:49 +0100160int nb_engines = 0;
Emeric Brune1f38db2012-09-03 20:36:47 +0200161
William Lallemande0f3fd52020-02-25 14:53:06 +0100162static struct eb_root cert_issuer_tree = EB_ROOT; /* issuers tree from "issuers-chain-path" */
Emmanuel Hocdet75a7aa12020-02-18 15:19:24 +0100163static struct issuer_chain* ssl_get_issuer_chain(X509 *cert);
William Lallemande0f3fd52020-02-25 14:53:06 +0100164
Willy Tarreauef934602016-12-22 23:12:01 +0100165static struct {
166 char *crt_base; /* base directory path for certificates */
167 char *ca_base; /* base directory path for CAs and CRLs */
Emmanuel Hocdet70df7bf2019-01-04 11:08:20 +0100168 char *issuers_chain_path; /* from "issuers-chain-path" */
Emmanuel Hocdet70df7bf2019-01-04 11:08:20 +0100169
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000170 int async; /* whether we use ssl async mode */
Willy Tarreauef934602016-12-22 23:12:01 +0100171
172 char *listen_default_ciphers;
173 char *connect_default_ciphers;
Emmanuel Hocdet839af572019-05-14 16:27:35 +0200174#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +0200175 char *listen_default_ciphersuites;
176 char *connect_default_ciphersuites;
177#endif
Willy Tarreauef934602016-12-22 23:12:01 +0100178 int listen_default_ssloptions;
179 int connect_default_ssloptions;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200180 struct tls_version_filter listen_default_sslmethods;
181 struct tls_version_filter connect_default_sslmethods;
Willy Tarreauef934602016-12-22 23:12:01 +0100182
183 int private_cache; /* Force to use a private session cache even if nbproc > 1 */
184 unsigned int life_time; /* SSL session lifetime in seconds */
185 unsigned int max_record; /* SSL max record size */
186 unsigned int default_dh_param; /* SSL maximum DH parameter size */
187 int ctx_cache; /* max number of entries in the ssl_ctx cache. */
Thierry FOURNIER5bf77322017-02-25 12:45:22 +0100188 int capture_cipherlist; /* Size of the cipherlist buffer. */
William Lallemand3af48e72020-02-03 17:15:52 +0100189 int extra_files; /* which files not defined in the configuration file are we looking for */
Willy Tarreauef934602016-12-22 23:12:01 +0100190} global_ssl = {
191#ifdef LISTEN_DEFAULT_CIPHERS
192 .listen_default_ciphers = LISTEN_DEFAULT_CIPHERS,
193#endif
194#ifdef CONNECT_DEFAULT_CIPHERS
195 .connect_default_ciphers = CONNECT_DEFAULT_CIPHERS,
196#endif
Emmanuel Hocdet839af572019-05-14 16:27:35 +0200197#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +0200198#ifdef LISTEN_DEFAULT_CIPHERSUITES
199 .listen_default_ciphersuites = LISTEN_DEFAULT_CIPHERSUITES,
200#endif
201#ifdef CONNECT_DEFAULT_CIPHERSUITES
202 .connect_default_ciphersuites = CONNECT_DEFAULT_CIPHERSUITES,
203#endif
204#endif
Willy Tarreauef934602016-12-22 23:12:01 +0100205 .listen_default_ssloptions = BC_SSL_O_NONE,
206 .connect_default_ssloptions = SRV_SSL_O_NONE,
207
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200208 .listen_default_sslmethods.flags = MC_SSL_O_ALL,
209 .listen_default_sslmethods.min = CONF_TLSV_NONE,
210 .listen_default_sslmethods.max = CONF_TLSV_NONE,
211 .connect_default_sslmethods.flags = MC_SSL_O_ALL,
212 .connect_default_sslmethods.min = CONF_TLSV_NONE,
213 .connect_default_sslmethods.max = CONF_TLSV_NONE,
214
Willy Tarreauef934602016-12-22 23:12:01 +0100215#ifdef DEFAULT_SSL_MAX_RECORD
216 .max_record = DEFAULT_SSL_MAX_RECORD,
217#endif
218 .default_dh_param = SSL_DEFAULT_DH_PARAM,
219 .ctx_cache = DEFAULT_SSL_CTX_CACHE,
Thierry FOURNIER5bf77322017-02-25 12:45:22 +0100220 .capture_cipherlist = 0,
William Lallemand3af48e72020-02-03 17:15:52 +0100221 .extra_files = SSL_GF_ALL,
Willy Tarreauef934602016-12-22 23:12:01 +0100222};
223
Olivier Houcharda8955d52019-04-07 22:00:38 +0200224static BIO_METHOD *ha_meth;
225
Olivier Houchard66ab4982019-02-26 18:37:15 +0100226struct ssl_sock_ctx {
Olivier Houcharda8955d52019-04-07 22:00:38 +0200227 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +0100228 SSL *ssl;
Olivier Houcharda8955d52019-04-07 22:00:38 +0200229 BIO *bio;
Olivier Houchard5149b592019-05-23 17:47:36 +0200230 const struct xprt_ops *xprt;
Olivier Houchard66ab4982019-02-26 18:37:15 +0100231 void *xprt_ctx;
Olivier Houchardea8dd942019-05-20 14:02:16 +0200232 struct wait_event wait_event;
Willy Tarreau113d52b2020-01-10 09:20:26 +0100233 struct wait_event *subs;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +0100234 int xprt_st; /* transport layer state, initialized to zero */
Olivier Houchard54907bb2019-12-19 15:02:39 +0100235 struct buffer early_buf; /* buffer to store the early data received */
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +0100236 int sent_early_data; /* Amount of early data we sent so far */
237
Olivier Houchard66ab4982019-02-26 18:37:15 +0100238};
239
240DECLARE_STATIC_POOL(ssl_sock_ctx_pool, "ssl_sock_ctx_pool", sizeof(struct ssl_sock_ctx));
241
Olivier Houchardea8dd942019-05-20 14:02:16 +0200242static struct task *ssl_sock_io_cb(struct task *, void *, unsigned short);
Olivier Houchard000694c2019-05-23 14:45:12 +0200243static int ssl_sock_handshake(struct connection *conn, unsigned int flag);
Olivier Houchardea8dd942019-05-20 14:02:16 +0200244
Olivier Houcharda8955d52019-04-07 22:00:38 +0200245/* Methods to implement OpenSSL BIO */
246static int ha_ssl_write(BIO *h, const char *buf, int num)
247{
248 struct buffer tmpbuf;
249 struct ssl_sock_ctx *ctx;
250 int ret;
251
252 ctx = BIO_get_data(h);
253 tmpbuf.size = num;
254 tmpbuf.area = (void *)(uintptr_t)buf;
255 tmpbuf.data = num;
256 tmpbuf.head = 0;
257 ret = ctx->xprt->snd_buf(ctx->conn, ctx->xprt_ctx, &tmpbuf, num, 0);
Olivier Houchardb51937e2019-05-01 17:24:36 +0200258 if (ret == 0 && !(ctx->conn->flags & (CO_FL_ERROR | CO_FL_SOCK_WR_SH))) {
Olivier Houcharda8955d52019-04-07 22:00:38 +0200259 BIO_set_retry_write(h);
Olivier Houcharda28454e2019-04-24 12:04:36 +0200260 ret = -1;
Olivier Houchardb51937e2019-05-01 17:24:36 +0200261 } else if (ret == 0)
262 BIO_clear_retry_flags(h);
Olivier Houcharda8955d52019-04-07 22:00:38 +0200263 return ret;
264}
265
266static int ha_ssl_gets(BIO *h, char *buf, int size)
267{
268
269 return 0;
270}
271
272static int ha_ssl_puts(BIO *h, const char *str)
273{
274
275 return ha_ssl_write(h, str, strlen(str));
276}
277
278static int ha_ssl_read(BIO *h, char *buf, int size)
279{
280 struct buffer tmpbuf;
281 struct ssl_sock_ctx *ctx;
282 int ret;
283
284 ctx = BIO_get_data(h);
285 tmpbuf.size = size;
286 tmpbuf.area = buf;
287 tmpbuf.data = 0;
288 tmpbuf.head = 0;
289 ret = ctx->xprt->rcv_buf(ctx->conn, ctx->xprt_ctx, &tmpbuf, size, 0);
Olivier Houchardb51937e2019-05-01 17:24:36 +0200290 if (ret == 0 && !(ctx->conn->flags & (CO_FL_ERROR | CO_FL_SOCK_RD_SH))) {
Olivier Houcharda8955d52019-04-07 22:00:38 +0200291 BIO_set_retry_read(h);
Olivier Houcharda28454e2019-04-24 12:04:36 +0200292 ret = -1;
Olivier Houchardb51937e2019-05-01 17:24:36 +0200293 } else if (ret == 0)
294 BIO_clear_retry_flags(h);
Olivier Houcharda8955d52019-04-07 22:00:38 +0200295
296 return ret;
297}
298
299static long ha_ssl_ctrl(BIO *h, int cmd, long arg1, void *arg2)
300{
301 int ret = 0;
302 switch (cmd) {
303 case BIO_CTRL_DUP:
304 case BIO_CTRL_FLUSH:
305 ret = 1;
306 break;
307 }
308 return ret;
309}
310
311static int ha_ssl_new(BIO *h)
312{
313 BIO_set_init(h, 1);
314 BIO_set_data(h, NULL);
315 BIO_clear_flags(h, ~0);
316 return 1;
317}
318
319static int ha_ssl_free(BIO *data)
320{
321
322 return 1;
323}
324
325
Willy Tarreau5db847a2019-05-09 14:13:35 +0200326#if defined(USE_THREAD) && (HA_OPENSSL_VERSION_NUMBER < 0x10100000L)
Christopher Faulet9dcf9b62017-11-13 10:34:01 +0100327
Emeric Brun821bb9b2017-06-15 16:37:39 +0200328static HA_RWLOCK_T *ssl_rwlocks;
329
330
331unsigned long ssl_id_function(void)
332{
333 return (unsigned long)tid;
334}
335
336void ssl_locking_function(int mode, int n, const char * file, int line)
337{
338 if (mode & CRYPTO_LOCK) {
339 if (mode & CRYPTO_READ)
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100340 HA_RWLOCK_RDLOCK(SSL_LOCK, &ssl_rwlocks[n]);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200341 else
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100342 HA_RWLOCK_WRLOCK(SSL_LOCK, &ssl_rwlocks[n]);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200343 }
344 else {
345 if (mode & CRYPTO_READ)
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100346 HA_RWLOCK_RDUNLOCK(SSL_LOCK, &ssl_rwlocks[n]);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200347 else
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100348 HA_RWLOCK_WRUNLOCK(SSL_LOCK, &ssl_rwlocks[n]);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200349 }
350}
351
352static int ssl_locking_init(void)
353{
354 int i;
355
356 ssl_rwlocks = malloc(sizeof(HA_RWLOCK_T)*CRYPTO_num_locks());
357 if (!ssl_rwlocks)
358 return -1;
359
360 for (i = 0 ; i < CRYPTO_num_locks() ; i++)
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100361 HA_RWLOCK_INIT(&ssl_rwlocks[i]);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200362
363 CRYPTO_set_id_callback(ssl_id_function);
364 CRYPTO_set_locking_callback(ssl_locking_function);
365
366 return 0;
367}
Christopher Faulet9dcf9b62017-11-13 10:34:01 +0100368
Emeric Brun821bb9b2017-06-15 16:37:39 +0200369#endif
370
William Lallemand150bfa82019-09-19 17:12:49 +0200371__decl_hathreads(HA_SPINLOCK_T ckch_lock);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200372
William Lallemandbc6ca7c2019-10-29 23:48:19 +0100373/* Uncommitted CKCH transaction */
374
375static struct {
376 struct ckch_store *new_ckchs;
377 struct ckch_store *old_ckchs;
378 char *path;
379} ckchs_transaction;
380
Emmanuel Hocdetd4f9a602019-10-24 11:32:47 +0200381/*
Emmanuel Hocdetb270e812019-11-21 19:09:31 +0100382 * deduplicate cafile (and crlfile)
Emmanuel Hocdetd4f9a602019-10-24 11:32:47 +0200383 */
384struct cafile_entry {
385 X509_STORE *ca_store;
Emmanuel Hocdet129d3282019-10-24 18:08:51 +0200386 STACK_OF(X509_NAME) *ca_list;
Emmanuel Hocdetd4f9a602019-10-24 11:32:47 +0200387 struct ebmb_node node;
388 char path[0];
389};
390
391static struct eb_root cafile_tree = EB_ROOT_UNIQUE;
392
393static X509_STORE* ssl_store_get0_locations_file(char *path)
394{
395 struct ebmb_node *eb;
396
397 eb = ebst_lookup(&cafile_tree, path);
398 if (eb) {
399 struct cafile_entry *ca_e;
400 ca_e = ebmb_entry(eb, struct cafile_entry, node);
401 return ca_e->ca_store;
402 }
403 return NULL;
404}
405
406static int ssl_store_load_locations_file(char *path)
407{
408 if (ssl_store_get0_locations_file(path) == NULL) {
409 struct cafile_entry *ca_e;
410 X509_STORE *store = X509_STORE_new();
411 if (X509_STORE_load_locations(store, path, NULL)) {
412 int pathlen;
413 pathlen = strlen(path);
414 ca_e = calloc(1, sizeof(*ca_e) + pathlen + 1);
415 if (ca_e) {
416 memcpy(ca_e->path, path, pathlen + 1);
417 ca_e->ca_store = store;
418 ebst_insert(&cafile_tree, &ca_e->node);
419 return 1;
420 }
421 }
422 X509_STORE_free(store);
423 return 0;
424 }
425 return 1;
426}
427
428/* mimic what X509_STORE_load_locations do with store_ctx */
429static int ssl_set_cert_crl_file(X509_STORE *store_ctx, char *path)
430{
431 X509_STORE *store;
432 store = ssl_store_get0_locations_file(path);
433 if (store_ctx && store) {
434 int i;
435 X509_OBJECT *obj;
436 STACK_OF(X509_OBJECT) *objs = X509_STORE_get0_objects(store);
437 for (i = 0; i < sk_X509_OBJECT_num(objs); i++) {
438 obj = sk_X509_OBJECT_value(objs, i);
439 switch (X509_OBJECT_get_type(obj)) {
440 case X509_LU_X509:
441 X509_STORE_add_cert(store_ctx, X509_OBJECT_get0_X509(obj));
442 break;
443 case X509_LU_CRL:
444 X509_STORE_add_crl(store_ctx, X509_OBJECT_get0_X509_CRL(obj));
445 break;
446 default:
447 break;
448 }
449 }
450 return 1;
451 }
452 return 0;
453}
454
455/* SSL_CTX_load_verify_locations substitute, internaly call X509_STORE_load_locations */
456static int ssl_set_verify_locations_file(SSL_CTX *ctx, char *path)
457{
458 X509_STORE *store_ctx = SSL_CTX_get_cert_store(ctx);
459 return ssl_set_cert_crl_file(store_ctx, path);
460}
461
Emmanuel Hocdet129d3282019-10-24 18:08:51 +0200462/*
463 Extract CA_list from CA_file already in tree.
464 Duplicate ca_name is tracking with ebtree. It's simplify openssl compatibility.
465 Return a shared ca_list: SSL_dup_CA_list must be used before set it on SSL_CTX.
466*/
467static STACK_OF(X509_NAME)* ssl_get_client_ca_file(char *path)
468{
469 struct ebmb_node *eb;
470 struct cafile_entry *ca_e;
471
472 eb = ebst_lookup(&cafile_tree, path);
473 if (!eb)
474 return NULL;
475 ca_e = ebmb_entry(eb, struct cafile_entry, node);
476
477 if (ca_e->ca_list == NULL) {
478 int i;
479 unsigned long key;
480 struct eb_root ca_name_tree = EB_ROOT;
481 struct eb64_node *node, *back;
482 struct {
483 struct eb64_node node;
484 X509_NAME *xname;
485 } *ca_name;
486 STACK_OF(X509_OBJECT) *objs;
487 STACK_OF(X509_NAME) *skn;
488 X509 *x;
489 X509_NAME *xn;
490
491 skn = sk_X509_NAME_new_null();
492 /* take x509 from cafile_tree */
493 objs = X509_STORE_get0_objects(ca_e->ca_store);
494 for (i = 0; i < sk_X509_OBJECT_num(objs); i++) {
495 x = X509_OBJECT_get0_X509(sk_X509_OBJECT_value(objs, i));
496 if (!x)
497 continue;
498 xn = X509_get_subject_name(x);
499 if (!xn)
500 continue;
501 /* Check for duplicates. */
502 key = X509_NAME_hash(xn);
503 for (node = eb64_lookup(&ca_name_tree, key), ca_name = NULL;
504 node && ca_name == NULL;
505 node = eb64_next(node)) {
506 ca_name = container_of(node, typeof(*ca_name), node);
507 if (X509_NAME_cmp(xn, ca_name->xname) != 0)
508 ca_name = NULL;
509 }
510 /* find a duplicate */
511 if (ca_name)
512 continue;
513 ca_name = calloc(1, sizeof *ca_name);
514 xn = X509_NAME_dup(xn);
515 if (!ca_name ||
516 !xn ||
517 !sk_X509_NAME_push(skn, xn)) {
518 free(ca_name);
519 X509_NAME_free(xn);
520 sk_X509_NAME_pop_free(skn, X509_NAME_free);
521 sk_X509_NAME_free(skn);
522 skn = NULL;
523 break;
524 }
525 ca_name->node.key = key;
526 ca_name->xname = xn;
527 eb64_insert(&ca_name_tree, &ca_name->node);
528 }
529 ca_e->ca_list = skn;
530 /* remove temporary ca_name tree */
531 node = eb64_first(&ca_name_tree);
532 while (node) {
533 ca_name = container_of(node, typeof(*ca_name), node);
534 back = eb64_next(node);
535 eb64_delete(node);
536 free(ca_name);
537 node = back;
538 }
539 }
540 return ca_e->ca_list;
541}
542
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +0100543/* This memory pool is used for capturing clienthello parameters. */
Thierry FOURNIER5bf77322017-02-25 12:45:22 +0100544struct ssl_capture {
Thierry FOURNIER5bf77322017-02-25 12:45:22 +0100545 unsigned long long int xxh64;
546 unsigned char ciphersuite_len;
547 char ciphersuite[0];
548};
Willy Tarreaubafbe012017-11-24 17:34:44 +0100549struct pool_head *pool_head_ssl_capture = NULL;
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +0100550static int ssl_capture_ptr_index = -1;
Thierry FOURNIER28962c92018-06-17 21:37:05 +0200551static int ssl_app_data_index = -1;
Willy Tarreauef934602016-12-22 23:12:01 +0100552
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200553#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
554struct list tlskeys_reference = LIST_HEAD_INIT(tlskeys_reference);
555#endif
556
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +0200557#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +0000558static unsigned int openssl_engines_initialized;
559struct list openssl_engines = LIST_HEAD_INIT(openssl_engines);
560struct ssl_engine_list {
561 struct list list;
562 ENGINE *e;
563};
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +0200564#endif
Grant Zhang872f9c22017-01-21 01:10:18 +0000565
Remi Gacogne8de54152014-07-15 11:36:40 +0200566#ifndef OPENSSL_NO_DH
Remi Gacogne4f902b82015-05-28 16:23:00 +0200567static int ssl_dh_ptr_index = -1;
Remi Gacogne47783ef2015-05-29 15:53:22 +0200568static DH *global_dh = NULL;
Remi Gacogne8de54152014-07-15 11:36:40 +0200569static DH *local_dh_1024 = NULL;
570static DH *local_dh_2048 = NULL;
571static DH *local_dh_4096 = NULL;
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +0100572static DH *ssl_get_tmp_dh(SSL *ssl, int export, int keylen);
Remi Gacogne8de54152014-07-15 11:36:40 +0200573#endif /* OPENSSL_NO_DH */
574
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100575#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Christopher Faulet31af49d2015-06-09 17:29:50 +0200576/* X509V3 Extensions that will be added on generated certificates */
577#define X509V3_EXT_SIZE 5
578static char *x509v3_ext_names[X509V3_EXT_SIZE] = {
579 "basicConstraints",
580 "nsComment",
581 "subjectKeyIdentifier",
582 "authorityKeyIdentifier",
583 "keyUsage",
584};
585static char *x509v3_ext_values[X509V3_EXT_SIZE] = {
586 "CA:FALSE",
587 "\"OpenSSL Generated Certificate\"",
588 "hash",
589 "keyid,issuer:always",
590 "nonRepudiation,digitalSignature,keyEncipherment"
591};
Christopher Faulet31af49d2015-06-09 17:29:50 +0200592/* LRU cache to store generated certificate */
593static struct lru64_head *ssl_ctx_lru_tree = NULL;
594static unsigned int ssl_ctx_lru_seed = 0;
Emeric Brun821bb9b2017-06-15 16:37:39 +0200595static unsigned int ssl_ctx_serial;
Willy Tarreau86abe442018-11-25 20:12:18 +0100596__decl_rwlock(ssl_ctx_lru_rwlock);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200597
Willy Tarreauc8ad3be2015-06-17 15:48:26 +0200598#endif // SSL_CTRL_SET_TLSEXT_HOSTNAME
599
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100600static struct ssl_bind_kw ssl_bind_kws[];
601
Willy Tarreau9a1ab082019-05-09 13:26:41 +0200602#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
yanbzhube2774d2015-12-10 15:07:30 -0500603/* The order here matters for picking a default context,
604 * keep the most common keytype at the bottom of the list
605 */
606const char *SSL_SOCK_KEYTYPE_NAMES[] = {
607 "dsa",
608 "ecdsa",
609 "rsa"
610};
611#define SSL_SOCK_NUM_KEYTYPES 3
Willy Tarreau30da7ad2015-12-14 11:28:33 +0100612#else
613#define SSL_SOCK_NUM_KEYTYPES 1
yanbzhube2774d2015-12-10 15:07:30 -0500614#endif
615
William Lallemandc3cd35f2017-11-28 11:04:43 +0100616static struct shared_context *ssl_shctx = NULL; /* ssl shared session cache */
William Lallemand4f45bb92017-10-30 20:08:51 +0100617static struct eb_root *sh_ssl_sess_tree; /* ssl shared session tree */
618
619#define sh_ssl_sess_tree_delete(s) ebmb_delete(&(s)->key);
620
621#define sh_ssl_sess_tree_insert(s) (struct sh_ssl_sess_hdr *)ebmb_insert(sh_ssl_sess_tree, \
622 &(s)->key, SSL_MAX_SSL_SESSION_ID_LENGTH);
623
624#define sh_ssl_sess_tree_lookup(k) (struct sh_ssl_sess_hdr *)ebmb_lookup(sh_ssl_sess_tree, \
625 (k), SSL_MAX_SSL_SESSION_ID_LENGTH);
William Lallemand3f85c9a2017-10-09 16:30:50 +0200626
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100627/*
628 * This function gives the detail of the SSL error. It is used only
629 * if the debug mode and the verbose mode are activated. It dump all
630 * the SSL error until the stack was empty.
631 */
632static forceinline void ssl_sock_dump_errors(struct connection *conn)
633{
634 unsigned long ret;
635
636 if (unlikely(global.mode & MODE_DEBUG)) {
637 while(1) {
638 ret = ERR_get_error();
639 if (ret == 0)
640 return;
641 fprintf(stderr, "fd[%04x] OpenSSL error[0x%lx] %s: %s\n",
Willy Tarreau585744b2017-08-24 14:31:19 +0200642 (unsigned short)conn->handle.fd, ret,
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100643 ERR_func_error_string(ret), ERR_reason_error_string(ret));
644 }
645 }
646}
647
yanbzhube2774d2015-12-10 15:07:30 -0500648
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +0200649#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +0000650static int ssl_init_single_engine(const char *engine_id, const char *def_algorithms)
651{
652 int err_code = ERR_ABORT;
653 ENGINE *engine;
654 struct ssl_engine_list *el;
655
656 /* grab the structural reference to the engine */
657 engine = ENGINE_by_id(engine_id);
658 if (engine == NULL) {
Christopher Faulet767a84b2017-11-24 16:50:31 +0100659 ha_alert("ssl-engine %s: failed to get structural reference\n", engine_id);
Grant Zhang872f9c22017-01-21 01:10:18 +0000660 goto fail_get;
661 }
662
663 if (!ENGINE_init(engine)) {
664 /* the engine couldn't initialise, release it */
Christopher Faulet767a84b2017-11-24 16:50:31 +0100665 ha_alert("ssl-engine %s: failed to initialize\n", engine_id);
Grant Zhang872f9c22017-01-21 01:10:18 +0000666 goto fail_init;
667 }
668
669 if (ENGINE_set_default_string(engine, def_algorithms) == 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +0100670 ha_alert("ssl-engine %s: failed on ENGINE_set_default_string\n", engine_id);
Grant Zhang872f9c22017-01-21 01:10:18 +0000671 goto fail_set_method;
672 }
673
674 el = calloc(1, sizeof(*el));
675 el->e = engine;
676 LIST_ADD(&openssl_engines, &el->list);
Emeric Brunece0c332017-12-06 13:51:49 +0100677 nb_engines++;
678 if (global_ssl.async)
679 global.ssl_used_async_engines = nb_engines;
Grant Zhang872f9c22017-01-21 01:10:18 +0000680 return 0;
681
682fail_set_method:
683 /* release the functional reference from ENGINE_init() */
684 ENGINE_finish(engine);
685
686fail_init:
687 /* release the structural reference from ENGINE_by_id() */
688 ENGINE_free(engine);
689
690fail_get:
691 return err_code;
692}
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +0200693#endif
Grant Zhang872f9c22017-01-21 01:10:18 +0000694
Willy Tarreau5db847a2019-05-09 14:13:35 +0200695#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brun3854e012017-05-17 20:42:48 +0200696/*
697 * openssl async fd handler
698 */
Emeric Brund0e095c2019-04-19 17:15:28 +0200699void ssl_async_fd_handler(int fd)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000700{
Olivier Houchardea8dd942019-05-20 14:02:16 +0200701 struct ssl_sock_ctx *ctx = fdtab[fd].owner;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000702
Emeric Brun3854e012017-05-17 20:42:48 +0200703 /* fd is an async enfine fd, we must stop
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000704 * to poll this fd until it is requested
705 */
Emeric Brunbbc16542017-06-02 15:54:06 +0000706 fd_stop_recv(fd);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000707 fd_cant_recv(fd);
708
709 /* crypto engine is available, let's notify the associated
710 * connection that it can pursue its processing.
711 */
Olivier Houchard03abf2d2019-05-28 10:12:02 +0200712 ssl_sock_io_cb(NULL, ctx, 0);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000713}
714
Emeric Brun3854e012017-05-17 20:42:48 +0200715/*
716 * openssl async delayed SSL_free handler
717 */
Emeric Brund0e095c2019-04-19 17:15:28 +0200718void ssl_async_fd_free(int fd)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000719{
720 SSL *ssl = fdtab[fd].owner;
Emeric Brun3854e012017-05-17 20:42:48 +0200721 OSSL_ASYNC_FD all_fd[32];
722 size_t num_all_fds = 0;
723 int i;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000724
Emeric Brun3854e012017-05-17 20:42:48 +0200725 /* We suppose that the async job for a same SSL *
726 * are serialized. So if we are awake it is
727 * because the running job has just finished
728 * and we can remove all async fds safely
729 */
730 SSL_get_all_async_fds(ssl, NULL, &num_all_fds);
731 if (num_all_fds > 32) {
732 send_log(NULL, LOG_EMERG, "haproxy: openssl returns too many async fds. It seems a bug. Process may crash\n");
733 return;
734 }
735
736 SSL_get_all_async_fds(ssl, all_fd, &num_all_fds);
737 for (i=0 ; i < num_all_fds ; i++)
738 fd_remove(all_fd[i]);
739
740 /* Now we can safely call SSL_free, no more pending job in engines */
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000741 SSL_free(ssl);
Olivier Houchard2be5a4c2019-03-08 18:54:43 +0100742 _HA_ATOMIC_SUB(&sslconns, 1);
743 _HA_ATOMIC_SUB(&jobs, 1);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000744}
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000745/*
Emeric Brun3854e012017-05-17 20:42:48 +0200746 * function used to manage a returned SSL_ERROR_WANT_ASYNC
747 * and enable/disable polling for async fds
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000748 */
Olivier Houchardea8dd942019-05-20 14:02:16 +0200749static inline void ssl_async_process_fds(struct ssl_sock_ctx *ctx)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000750{
Willy Tarreaua9786b62018-01-25 07:22:13 +0100751 OSSL_ASYNC_FD add_fd[32];
Emeric Brun3854e012017-05-17 20:42:48 +0200752 OSSL_ASYNC_FD del_fd[32];
Olivier Houchardea8dd942019-05-20 14:02:16 +0200753 SSL *ssl = ctx->ssl;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000754 size_t num_add_fds = 0;
755 size_t num_del_fds = 0;
Emeric Brun3854e012017-05-17 20:42:48 +0200756 int i;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000757
758 SSL_get_changed_async_fds(ssl, NULL, &num_add_fds, NULL,
759 &num_del_fds);
Emeric Brun3854e012017-05-17 20:42:48 +0200760 if (num_add_fds > 32 || num_del_fds > 32) {
761 send_log(NULL, LOG_EMERG, "haproxy: openssl returns too many async fds. It seems a bug. Process may crash\n");
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000762 return;
763 }
764
Emeric Brun3854e012017-05-17 20:42:48 +0200765 SSL_get_changed_async_fds(ssl, add_fd, &num_add_fds, del_fd, &num_del_fds);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000766
Emeric Brun3854e012017-05-17 20:42:48 +0200767 /* We remove unused fds from the fdtab */
768 for (i=0 ; i < num_del_fds ; i++)
769 fd_remove(del_fd[i]);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000770
Emeric Brun3854e012017-05-17 20:42:48 +0200771 /* We add new fds to the fdtab */
772 for (i=0 ; i < num_add_fds ; i++) {
Olivier Houchardea8dd942019-05-20 14:02:16 +0200773 fd_insert(add_fd[i], ctx, ssl_async_fd_handler, tid_bit);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000774 }
775
Emeric Brun3854e012017-05-17 20:42:48 +0200776 num_add_fds = 0;
777 SSL_get_all_async_fds(ssl, NULL, &num_add_fds);
778 if (num_add_fds > 32) {
779 send_log(NULL, LOG_EMERG, "haproxy: openssl returns too many async fds. It seems a bug. Process may crash\n");
780 return;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000781 }
Emeric Brun3854e012017-05-17 20:42:48 +0200782
783 /* We activate the polling for all known async fds */
784 SSL_get_all_async_fds(ssl, add_fd, &num_add_fds);
Emeric Brunce9e01c2017-05-31 10:02:53 +0000785 for (i=0 ; i < num_add_fds ; i++) {
Emeric Brun3854e012017-05-17 20:42:48 +0200786 fd_want_recv(add_fd[i]);
Emeric Brunce9e01c2017-05-31 10:02:53 +0000787 /* To ensure that the fd cache won't be used
788 * We'll prefer to catch a real RD event
789 * because handling an EAGAIN on this fd will
790 * result in a context switch and also
791 * some engines uses a fd in blocking mode.
792 */
793 fd_cant_recv(add_fd[i]);
794 }
Emeric Brun3854e012017-05-17 20:42:48 +0200795
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000796}
797#endif
798
William Lallemand104a7a62019-10-14 14:14:59 +0200799#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
Emeric Brun4f3c87a2014-06-20 15:46:13 +0200800/*
801 * This function returns the number of seconds elapsed
802 * since the Epoch, 1970-01-01 00:00:00 +0000 (UTC) and the
803 * date presented un ASN1_GENERALIZEDTIME.
804 *
805 * In parsing error case, it returns -1.
806 */
807static long asn1_generalizedtime_to_epoch(ASN1_GENERALIZEDTIME *d)
808{
809 long epoch;
810 char *p, *end;
811 const unsigned short month_offset[12] = {
812 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
813 };
814 int year, month;
815
816 if (!d || (d->type != V_ASN1_GENERALIZEDTIME)) return -1;
817
818 p = (char *)d->data;
819 end = p + d->length;
820
821 if (end - p < 4) return -1;
822 year = 1000 * (p[0] - '0') + 100 * (p[1] - '0') + 10 * (p[2] - '0') + p[3] - '0';
823 p += 4;
824 if (end - p < 2) return -1;
825 month = 10 * (p[0] - '0') + p[1] - '0';
826 if (month < 1 || month > 12) return -1;
827 /* Compute the number of seconds since 1 jan 1970 and the beginning of current month
828 We consider leap years and the current month (<marsh or not) */
829 epoch = ( ((year - 1970) * 365)
830 + ((year - (month < 3)) / 4 - (year - (month < 3)) / 100 + (year - (month < 3)) / 400)
831 - ((1970 - 1) / 4 - (1970 - 1) / 100 + (1970 - 1) / 400)
832 + month_offset[month-1]
833 ) * 24 * 60 * 60;
834 p += 2;
835 if (end - p < 2) return -1;
836 /* Add the number of seconds of completed days of current month */
837 epoch += (10 * (p[0] - '0') + p[1] - '0' - 1) * 24 * 60 * 60;
838 p += 2;
839 if (end - p < 2) return -1;
840 /* Add the completed hours of the current day */
841 epoch += (10 * (p[0] - '0') + p[1] - '0') * 60 * 60;
842 p += 2;
843 if (end - p < 2) return -1;
844 /* Add the completed minutes of the current hour */
845 epoch += (10 * (p[0] - '0') + p[1] - '0') * 60;
846 p += 2;
847 if (p == end) return -1;
848 /* Test if there is available seconds */
849 if (p[0] < '0' || p[0] > '9')
850 goto nosec;
851 if (end - p < 2) return -1;
852 /* Add the seconds of the current minute */
853 epoch += 10 * (p[0] - '0') + p[1] - '0';
854 p += 2;
855 if (p == end) return -1;
856 /* Ignore seconds float part if present */
857 if (p[0] == '.') {
858 do {
859 if (++p == end) return -1;
860 } while (p[0] >= '0' && p[0] <= '9');
861 }
862
863nosec:
864 if (p[0] == 'Z') {
865 if (end - p != 1) return -1;
866 return epoch;
867 }
868 else if (p[0] == '+') {
869 if (end - p != 5) return -1;
870 /* Apply timezone offset */
Frederik Deweerdt953917a2017-10-16 07:37:31 -0700871 return epoch - ((10 * (p[1] - '0') + p[2] - '0') * 60 * 60 + (10 * (p[3] - '0') + p[4] - '0')) * 60;
Emeric Brun4f3c87a2014-06-20 15:46:13 +0200872 }
873 else if (p[0] == '-') {
874 if (end - p != 5) return -1;
875 /* Apply timezone offset */
Frederik Deweerdt953917a2017-10-16 07:37:31 -0700876 return epoch + ((10 * (p[1] - '0') + p[2] - '0') * 60 * 60 + (10 * (p[3] - '0') + p[4] - '0')) * 60;
Emeric Brun4f3c87a2014-06-20 15:46:13 +0200877 }
878
879 return -1;
880}
881
William Lallemand104a7a62019-10-14 14:14:59 +0200882/*
883 * struct alignment works here such that the key.key is the same as key_data
884 * Do not change the placement of key_data
885 */
886struct certificate_ocsp {
887 struct ebmb_node key;
888 unsigned char key_data[OCSP_MAX_CERTID_ASN1_LENGTH];
889 struct buffer response;
890 long expire;
891};
892
893struct ocsp_cbk_arg {
894 int is_single;
895 int single_kt;
896 union {
897 struct certificate_ocsp *s_ocsp;
898 /*
899 * m_ocsp will have multiple entries dependent on key type
900 * Entry 0 - DSA
901 * Entry 1 - ECDSA
902 * Entry 2 - RSA
903 */
904 struct certificate_ocsp *m_ocsp[SSL_SOCK_NUM_KEYTYPES];
905 };
906};
907
Emeric Brun1d3865b2014-06-20 15:37:32 +0200908static struct eb_root cert_ocsp_tree = EB_ROOT_UNIQUE;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200909
910/* This function starts to check if the OCSP response (in DER format) contained
911 * in chunk 'ocsp_response' is valid (else exits on error).
912 * If 'cid' is not NULL, it will be compared to the OCSP certificate ID
913 * contained in the OCSP Response and exits on error if no match.
914 * If it's a valid OCSP Response:
915 * If 'ocsp' is not NULL, the chunk is copied in the OCSP response's container
916 * pointed by 'ocsp'.
917 * If 'ocsp' is NULL, the function looks up into the OCSP response's
918 * containers tree (using as index the ASN1 form of the OCSP Certificate ID extracted
919 * from the response) and exits on error if not found. Finally, If an OCSP response is
920 * already present in the container, it will be overwritten.
921 *
922 * Note: OCSP response containing more than one OCSP Single response is not
923 * considered valid.
924 *
925 * Returns 0 on success, 1 in error case.
926 */
Willy Tarreau83061a82018-07-13 11:56:34 +0200927static int ssl_sock_load_ocsp_response(struct buffer *ocsp_response,
928 struct certificate_ocsp *ocsp,
929 OCSP_CERTID *cid, char **err)
Emeric Brun4147b2e2014-06-16 18:36:30 +0200930{
931 OCSP_RESPONSE *resp;
932 OCSP_BASICRESP *bs = NULL;
933 OCSP_SINGLERESP *sr;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200934 OCSP_CERTID *id;
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200935 unsigned char *p = (unsigned char *) ocsp_response->area;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200936 int rc , count_sr;
Emeric Brun13a6b482014-06-20 15:44:34 +0200937 ASN1_GENERALIZEDTIME *revtime, *thisupd, *nextupd = NULL;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200938 int reason;
939 int ret = 1;
940
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200941 resp = d2i_OCSP_RESPONSE(NULL, (const unsigned char **)&p,
942 ocsp_response->data);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200943 if (!resp) {
944 memprintf(err, "Unable to parse OCSP response");
945 goto out;
946 }
947
948 rc = OCSP_response_status(resp);
949 if (rc != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
950 memprintf(err, "OCSP response status not successful");
951 goto out;
952 }
953
954 bs = OCSP_response_get1_basic(resp);
955 if (!bs) {
956 memprintf(err, "Failed to get basic response from OCSP Response");
957 goto out;
958 }
959
960 count_sr = OCSP_resp_count(bs);
961 if (count_sr > 1) {
962 memprintf(err, "OCSP response ignored because contains multiple single responses (%d)", count_sr);
963 goto out;
964 }
965
966 sr = OCSP_resp_get0(bs, 0);
967 if (!sr) {
968 memprintf(err, "Failed to get OCSP single response");
969 goto out;
970 }
971
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200972 id = (OCSP_CERTID*)OCSP_SINGLERESP_get0_id(sr);
973
Emeric Brun4147b2e2014-06-16 18:36:30 +0200974 rc = OCSP_single_get0_status(sr, &reason, &revtime, &thisupd, &nextupd);
Emmanuel Hocdetef607052017-10-24 14:57:16 +0200975 if (rc != V_OCSP_CERTSTATUS_GOOD && rc != V_OCSP_CERTSTATUS_REVOKED) {
Emmanuel Hocdet872085c2017-10-10 15:18:52 +0200976 memprintf(err, "OCSP single response: certificate status is unknown");
Emeric Brun4147b2e2014-06-16 18:36:30 +0200977 goto out;
978 }
979
Emeric Brun13a6b482014-06-20 15:44:34 +0200980 if (!nextupd) {
981 memprintf(err, "OCSP single response: missing nextupdate");
982 goto out;
983 }
984
Emeric Brunc8b27b62014-06-19 14:16:17 +0200985 rc = OCSP_check_validity(thisupd, nextupd, OCSP_MAX_RESPONSE_TIME_SKEW, -1);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200986 if (!rc) {
987 memprintf(err, "OCSP single response: no longer valid.");
988 goto out;
989 }
990
991 if (cid) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200992 if (OCSP_id_cmp(id, cid)) {
Emeric Brun4147b2e2014-06-16 18:36:30 +0200993 memprintf(err, "OCSP single response: Certificate ID does not match certificate and issuer");
994 goto out;
995 }
996 }
997
998 if (!ocsp) {
999 unsigned char key[OCSP_MAX_CERTID_ASN1_LENGTH];
1000 unsigned char *p;
1001
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001002 rc = i2d_OCSP_CERTID(id, NULL);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001003 if (!rc) {
1004 memprintf(err, "OCSP single response: Unable to encode Certificate ID");
1005 goto out;
1006 }
1007
1008 if (rc > OCSP_MAX_CERTID_ASN1_LENGTH) {
1009 memprintf(err, "OCSP single response: Certificate ID too long");
1010 goto out;
1011 }
1012
1013 p = key;
1014 memset(key, 0, OCSP_MAX_CERTID_ASN1_LENGTH);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001015 i2d_OCSP_CERTID(id, &p);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001016 ocsp = (struct certificate_ocsp *)ebmb_lookup(&cert_ocsp_tree, key, OCSP_MAX_CERTID_ASN1_LENGTH);
1017 if (!ocsp) {
1018 memprintf(err, "OCSP single response: Certificate ID does not match any certificate or issuer");
1019 goto out;
1020 }
1021 }
1022
1023 /* According to comments on "chunk_dup", the
1024 previous chunk buffer will be freed */
1025 if (!chunk_dup(&ocsp->response, ocsp_response)) {
1026 memprintf(err, "OCSP response: Memory allocation error");
1027 goto out;
1028 }
1029
Emeric Brun4f3c87a2014-06-20 15:46:13 +02001030 ocsp->expire = asn1_generalizedtime_to_epoch(nextupd) - OCSP_MAX_RESPONSE_TIME_SKEW;
1031
Emeric Brun4147b2e2014-06-16 18:36:30 +02001032 ret = 0;
1033out:
Janusz Dziemidowicz8d710492017-03-08 16:59:41 +01001034 ERR_clear_error();
1035
Emeric Brun4147b2e2014-06-16 18:36:30 +02001036 if (bs)
1037 OCSP_BASICRESP_free(bs);
1038
1039 if (resp)
1040 OCSP_RESPONSE_free(resp);
1041
1042 return ret;
1043}
1044/*
1045 * External function use to update the OCSP response in the OCSP response's
1046 * containers tree. The chunk 'ocsp_response' must contain the OCSP response
1047 * to update in DER format.
1048 *
1049 * Returns 0 on success, 1 in error case.
1050 */
Willy Tarreau83061a82018-07-13 11:56:34 +02001051int ssl_sock_update_ocsp_response(struct buffer *ocsp_response, char **err)
Emeric Brun4147b2e2014-06-16 18:36:30 +02001052{
1053 return ssl_sock_load_ocsp_response(ocsp_response, NULL, NULL, err);
1054}
1055
William Lallemand4a660132019-10-14 14:51:41 +02001056#endif
1057
1058#if ((defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP) || defined OPENSSL_IS_BORINGSSL)
Emeric Brun4147b2e2014-06-16 18:36:30 +02001059/*
1060 * This function load the OCSP Resonse in DER format contained in file at
William Lallemand3b5f3602019-10-16 18:05:05 +02001061 * path 'ocsp_path' or base64 in a buffer <buf>
Emeric Brun4147b2e2014-06-16 18:36:30 +02001062 *
1063 * Returns 0 on success, 1 in error case.
1064 */
William Lallemand3b5f3602019-10-16 18:05:05 +02001065static int ssl_sock_load_ocsp_response_from_file(const char *ocsp_path, char *buf, struct cert_key_and_chain *ckch, char **err)
Emeric Brun4147b2e2014-06-16 18:36:30 +02001066{
1067 int fd = -1;
1068 int r = 0;
1069 int ret = 1;
William Lallemand3b5f3602019-10-16 18:05:05 +02001070 struct buffer *ocsp_response;
1071 struct buffer *src = NULL;
Emeric Brun4147b2e2014-06-16 18:36:30 +02001072
William Lallemand3b5f3602019-10-16 18:05:05 +02001073 if (buf) {
1074 int i, j;
1075 /* if it's from a buffer it will be base64 */
Emeric Brun4147b2e2014-06-16 18:36:30 +02001076
William Lallemand3b5f3602019-10-16 18:05:05 +02001077 /* remove \r and \n from the payload */
1078 for (i = 0, j = 0; buf[i]; i++) {
1079 if (buf[i] == '\r' || buf[i] == '\n')
Emeric Brun4147b2e2014-06-16 18:36:30 +02001080 continue;
William Lallemand3b5f3602019-10-16 18:05:05 +02001081 buf[j++] = buf[i];
1082 }
1083 buf[j] = 0;
Emeric Brun4147b2e2014-06-16 18:36:30 +02001084
William Lallemand3b5f3602019-10-16 18:05:05 +02001085 ret = base64dec(buf, j, trash.area, trash.size);
1086 if (ret < 0) {
1087 memprintf(err, "Error reading OCSP response in base64 format");
Emeric Brun4147b2e2014-06-16 18:36:30 +02001088 goto end;
1089 }
William Lallemand3b5f3602019-10-16 18:05:05 +02001090 trash.data = ret;
1091 src = &trash;
1092 } else {
1093 fd = open(ocsp_path, O_RDONLY);
1094 if (fd == -1) {
1095 memprintf(err, "Error opening OCSP response file");
1096 goto end;
Emeric Brun4147b2e2014-06-16 18:36:30 +02001097 }
William Lallemand3b5f3602019-10-16 18:05:05 +02001098
1099 trash.data = 0;
1100 while (trash.data < trash.size) {
1101 r = read(fd, trash.area + trash.data, trash.size - trash.data);
1102 if (r < 0) {
1103 if (errno == EINTR)
1104 continue;
1105
1106 memprintf(err, "Error reading OCSP response from file");
1107 goto end;
1108 }
1109 else if (r == 0) {
1110 break;
1111 }
1112 trash.data += r;
1113 }
1114 close(fd);
1115 fd = -1;
1116 src = &trash;
Emeric Brun4147b2e2014-06-16 18:36:30 +02001117 }
1118
William Lallemand3b5f3602019-10-16 18:05:05 +02001119 ocsp_response = calloc(1, sizeof(*ocsp_response));
1120 if (!chunk_dup(ocsp_response, src)) {
1121 free(ocsp_response);
1122 ocsp_response = NULL;
William Lallemand246c0242019-10-11 08:59:13 +02001123 goto end;
1124 }
Emmanuel Hocdet0667fae2020-01-16 14:41:36 +01001125 /* no error, fill ckch with new context, old context must be free */
1126 if (ckch->ocsp_response) {
1127 free(ckch->ocsp_response->area);
1128 ckch->ocsp_response->area = NULL;
1129 free(ckch->ocsp_response);
1130 }
William Lallemand3b5f3602019-10-16 18:05:05 +02001131 ckch->ocsp_response = ocsp_response;
William Lallemande0f48ae2019-10-15 13:44:57 +02001132 ret = 0;
Emeric Brun4147b2e2014-06-16 18:36:30 +02001133end:
1134 if (fd != -1)
1135 close(fd);
1136
1137 return ret;
1138}
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01001139#endif
Emeric Brun4147b2e2014-06-16 18:36:30 +02001140
Nenad Merdanovic05552d42015-02-27 19:56:49 +01001141#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
1142static int ssl_tlsext_ticket_key_cb(SSL *s, unsigned char key_name[16], unsigned char *iv, EVP_CIPHER_CTX *ectx, HMAC_CTX *hctx, int enc)
1143{
Christopher Faulet16f45c82018-02-16 11:23:49 +01001144 struct tls_keys_ref *ref;
Emeric Brun9e754772019-01-10 17:51:55 +01001145 union tls_sess_key *keys;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01001146 struct connection *conn;
1147 int head;
1148 int i;
Christopher Faulet16f45c82018-02-16 11:23:49 +01001149 int ret = -1; /* error by default */
Nenad Merdanovic05552d42015-02-27 19:56:49 +01001150
Thierry FOURNIER28962c92018-06-17 21:37:05 +02001151 conn = SSL_get_ex_data(s, ssl_app_data_index);
Willy Tarreau07d94e42018-09-20 10:57:52 +02001152 ref = __objt_listener(conn->target)->bind_conf->keys_ref;
Christopher Faulet16f45c82018-02-16 11:23:49 +01001153 HA_RWLOCK_RDLOCK(TLSKEYS_REF_LOCK, &ref->lock);
1154
1155 keys = ref->tlskeys;
1156 head = ref->tls_ticket_enc_index;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01001157
1158 if (enc) {
1159 memcpy(key_name, keys[head].name, 16);
1160
1161 if(!RAND_pseudo_bytes(iv, EVP_MAX_IV_LENGTH))
Christopher Faulet16f45c82018-02-16 11:23:49 +01001162 goto end;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01001163
Emeric Brun9e754772019-01-10 17:51:55 +01001164 if (ref->key_size_bits == 128) {
Nenad Merdanovic05552d42015-02-27 19:56:49 +01001165
Emeric Brun9e754772019-01-10 17:51:55 +01001166 if(!EVP_EncryptInit_ex(ectx, EVP_aes_128_cbc(), NULL, keys[head].key_128.aes_key, iv))
1167 goto end;
1168
Willy Tarreau9356dac2019-05-10 09:22:53 +02001169 HMAC_Init_ex(hctx, keys[head].key_128.hmac_key, 16, TLS_TICKET_HASH_FUNCT(), NULL);
Emeric Brun9e754772019-01-10 17:51:55 +01001170 ret = 1;
1171 }
1172 else if (ref->key_size_bits == 256 ) {
1173
1174 if(!EVP_EncryptInit_ex(ectx, EVP_aes_256_cbc(), NULL, keys[head].key_256.aes_key, iv))
1175 goto end;
1176
Willy Tarreau9356dac2019-05-10 09:22:53 +02001177 HMAC_Init_ex(hctx, keys[head].key_256.hmac_key, 32, TLS_TICKET_HASH_FUNCT(), NULL);
Emeric Brun9e754772019-01-10 17:51:55 +01001178 ret = 1;
1179 }
Nenad Merdanovic05552d42015-02-27 19:56:49 +01001180 } else {
1181 for (i = 0; i < TLS_TICKETS_NO; i++) {
1182 if (!memcmp(key_name, keys[(head + i) % TLS_TICKETS_NO].name, 16))
1183 goto found;
1184 }
Christopher Faulet16f45c82018-02-16 11:23:49 +01001185 ret = 0;
1186 goto end;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01001187
Christopher Faulet16f45c82018-02-16 11:23:49 +01001188 found:
Emeric Brun9e754772019-01-10 17:51:55 +01001189 if (ref->key_size_bits == 128) {
Willy Tarreau9356dac2019-05-10 09:22:53 +02001190 HMAC_Init_ex(hctx, keys[(head + i) % TLS_TICKETS_NO].key_128.hmac_key, 16, TLS_TICKET_HASH_FUNCT(), NULL);
Emeric Brun9e754772019-01-10 17:51:55 +01001191 if(!EVP_DecryptInit_ex(ectx, EVP_aes_128_cbc(), NULL, keys[(head + i) % TLS_TICKETS_NO].key_128.aes_key, iv))
1192 goto end;
1193 /* 2 for key renewal, 1 if current key is still valid */
1194 ret = i ? 2 : 1;
1195 }
1196 else if (ref->key_size_bits == 256) {
Willy Tarreau9356dac2019-05-10 09:22:53 +02001197 HMAC_Init_ex(hctx, keys[(head + i) % TLS_TICKETS_NO].key_256.hmac_key, 32, TLS_TICKET_HASH_FUNCT(), NULL);
Emeric Brun9e754772019-01-10 17:51:55 +01001198 if(!EVP_DecryptInit_ex(ectx, EVP_aes_256_cbc(), NULL, keys[(head + i) % TLS_TICKETS_NO].key_256.aes_key, iv))
1199 goto end;
1200 /* 2 for key renewal, 1 if current key is still valid */
1201 ret = i ? 2 : 1;
1202 }
Nenad Merdanovic05552d42015-02-27 19:56:49 +01001203 }
Emeric Brun9e754772019-01-10 17:51:55 +01001204
Christopher Faulet16f45c82018-02-16 11:23:49 +01001205 end:
1206 HA_RWLOCK_RDUNLOCK(TLSKEYS_REF_LOCK, &ref->lock);
1207 return ret;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02001208}
1209
1210struct tls_keys_ref *tlskeys_ref_lookup(const char *filename)
1211{
1212 struct tls_keys_ref *ref;
1213
1214 list_for_each_entry(ref, &tlskeys_reference, list)
1215 if (ref->filename && strcmp(filename, ref->filename) == 0)
1216 return ref;
1217 return NULL;
1218}
1219
1220struct tls_keys_ref *tlskeys_ref_lookupid(int unique_id)
1221{
1222 struct tls_keys_ref *ref;
1223
1224 list_for_each_entry(ref, &tlskeys_reference, list)
1225 if (ref->unique_id == unique_id)
1226 return ref;
1227 return NULL;
1228}
1229
Emeric Brun9e754772019-01-10 17:51:55 +01001230/* Update the key into ref: if keysize doesnt
1231 * match existing ones, this function returns -1
1232 * else it returns 0 on success.
1233 */
1234int ssl_sock_update_tlskey_ref(struct tls_keys_ref *ref,
Willy Tarreau83061a82018-07-13 11:56:34 +02001235 struct buffer *tlskey)
Christopher Faulet16f45c82018-02-16 11:23:49 +01001236{
Emeric Brun9e754772019-01-10 17:51:55 +01001237 if (ref->key_size_bits == 128) {
1238 if (tlskey->data != sizeof(struct tls_sess_key_128))
1239 return -1;
1240 }
1241 else if (ref->key_size_bits == 256) {
1242 if (tlskey->data != sizeof(struct tls_sess_key_256))
1243 return -1;
1244 }
1245 else
1246 return -1;
1247
Christopher Faulet16f45c82018-02-16 11:23:49 +01001248 HA_RWLOCK_WRLOCK(TLSKEYS_REF_LOCK, &ref->lock);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001249 memcpy((char *) (ref->tlskeys + ((ref->tls_ticket_enc_index + 2) % TLS_TICKETS_NO)),
1250 tlskey->area, tlskey->data);
Christopher Faulet16f45c82018-02-16 11:23:49 +01001251 ref->tls_ticket_enc_index = (ref->tls_ticket_enc_index + 1) % TLS_TICKETS_NO;
1252 HA_RWLOCK_WRUNLOCK(TLSKEYS_REF_LOCK, &ref->lock);
Emeric Brun9e754772019-01-10 17:51:55 +01001253
1254 return 0;
Christopher Faulet16f45c82018-02-16 11:23:49 +01001255}
1256
Willy Tarreau83061a82018-07-13 11:56:34 +02001257int ssl_sock_update_tlskey(char *filename, struct buffer *tlskey, char **err)
Christopher Faulet16f45c82018-02-16 11:23:49 +01001258{
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02001259 struct tls_keys_ref *ref = tlskeys_ref_lookup(filename);
1260
1261 if(!ref) {
1262 memprintf(err, "Unable to locate the referenced filename: %s", filename);
1263 return 1;
1264 }
Emeric Brun9e754772019-01-10 17:51:55 +01001265 if (ssl_sock_update_tlskey_ref(ref, tlskey) < 0) {
1266 memprintf(err, "Invalid key size");
1267 return 1;
1268 }
1269
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02001270 return 0;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01001271}
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02001272
1273/* This function finalize the configuration parsing. Its set all the
Willy Tarreaud1c57502016-12-22 22:46:15 +01001274 * automatic ids. It's called just after the basic checks. It returns
1275 * 0 on success otherwise ERR_*.
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02001276 */
Willy Tarreaud1c57502016-12-22 22:46:15 +01001277static int tlskeys_finalize_config(void)
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02001278{
1279 int i = 0;
1280 struct tls_keys_ref *ref, *ref2, *ref3;
1281 struct list tkr = LIST_HEAD_INIT(tkr);
1282
1283 list_for_each_entry(ref, &tlskeys_reference, list) {
1284 if (ref->unique_id == -1) {
1285 /* Look for the first free id. */
1286 while (1) {
1287 list_for_each_entry(ref2, &tlskeys_reference, list) {
1288 if (ref2->unique_id == i) {
1289 i++;
1290 break;
1291 }
1292 }
1293 if (&ref2->list == &tlskeys_reference)
1294 break;
1295 }
1296
1297 /* Uses the unique id and increment it for the next entry. */
1298 ref->unique_id = i;
1299 i++;
1300 }
1301 }
1302
1303 /* This sort the reference list by id. */
1304 list_for_each_entry_safe(ref, ref2, &tlskeys_reference, list) {
1305 LIST_DEL(&ref->list);
1306 list_for_each_entry(ref3, &tkr, list) {
1307 if (ref->unique_id < ref3->unique_id) {
1308 LIST_ADDQ(&ref3->list, &ref->list);
1309 break;
1310 }
1311 }
1312 if (&ref3->list == &tkr)
1313 LIST_ADDQ(&tkr, &ref->list);
1314 }
1315
1316 /* swap root */
1317 LIST_ADD(&tkr, &tlskeys_reference);
1318 LIST_DEL(&tkr);
Willy Tarreaud1c57502016-12-22 22:46:15 +01001319 return 0;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02001320}
Nenad Merdanovic05552d42015-02-27 19:56:49 +01001321#endif /* SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB */
1322
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01001323#ifndef OPENSSL_NO_OCSP
yanbzhube2774d2015-12-10 15:07:30 -05001324int ssl_sock_get_ocsp_arg_kt_index(int evp_keytype)
1325{
1326 switch (evp_keytype) {
1327 case EVP_PKEY_RSA:
1328 return 2;
1329 case EVP_PKEY_DSA:
1330 return 0;
1331 case EVP_PKEY_EC:
1332 return 1;
1333 }
1334
1335 return -1;
1336}
1337
Emeric Brun4147b2e2014-06-16 18:36:30 +02001338/*
1339 * Callback used to set OCSP status extension content in server hello.
1340 */
1341int ssl_sock_ocsp_stapling_cbk(SSL *ssl, void *arg)
1342{
yanbzhube2774d2015-12-10 15:07:30 -05001343 struct certificate_ocsp *ocsp;
1344 struct ocsp_cbk_arg *ocsp_arg;
1345 char *ssl_buf;
1346 EVP_PKEY *ssl_pkey;
1347 int key_type;
1348 int index;
1349
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02001350 ocsp_arg = arg;
yanbzhube2774d2015-12-10 15:07:30 -05001351
1352 ssl_pkey = SSL_get_privatekey(ssl);
1353 if (!ssl_pkey)
1354 return SSL_TLSEXT_ERR_NOACK;
1355
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001356 key_type = EVP_PKEY_base_id(ssl_pkey);
yanbzhube2774d2015-12-10 15:07:30 -05001357
1358 if (ocsp_arg->is_single && ocsp_arg->single_kt == key_type)
1359 ocsp = ocsp_arg->s_ocsp;
1360 else {
1361 /* For multiple certs per context, we have to find the correct OCSP response based on
1362 * the certificate type
1363 */
1364 index = ssl_sock_get_ocsp_arg_kt_index(key_type);
1365
1366 if (index < 0)
1367 return SSL_TLSEXT_ERR_NOACK;
1368
1369 ocsp = ocsp_arg->m_ocsp[index];
1370
1371 }
Emeric Brun4147b2e2014-06-16 18:36:30 +02001372
1373 if (!ocsp ||
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001374 !ocsp->response.area ||
1375 !ocsp->response.data ||
Emeric Brun4f3c87a2014-06-20 15:46:13 +02001376 (ocsp->expire < now.tv_sec))
Emeric Brun4147b2e2014-06-16 18:36:30 +02001377 return SSL_TLSEXT_ERR_NOACK;
1378
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001379 ssl_buf = OPENSSL_malloc(ocsp->response.data);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001380 if (!ssl_buf)
1381 return SSL_TLSEXT_ERR_NOACK;
1382
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001383 memcpy(ssl_buf, ocsp->response.area, ocsp->response.data);
1384 SSL_set_tlsext_status_ocsp_resp(ssl, ssl_buf, ocsp->response.data);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001385
1386 return SSL_TLSEXT_ERR_OK;
1387}
1388
William Lallemand4a660132019-10-14 14:51:41 +02001389#endif
1390
1391#if ((defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP) || defined OPENSSL_IS_BORINGSSL)
Emeric Brun4147b2e2014-06-16 18:36:30 +02001392/*
1393 * This function enables the handling of OCSP status extension on 'ctx' if a
William Lallemand246c0242019-10-11 08:59:13 +02001394 * ocsp_response buffer was found in the cert_key_and_chain. To enable OCSP
1395 * status extension, the issuer's certificate is mandatory. It should be
1396 * present in ckch->ocsp_issuer.
Emeric Brun4147b2e2014-06-16 18:36:30 +02001397 *
William Lallemand246c0242019-10-11 08:59:13 +02001398 * In addition, the ckch->ocsp_reponse buffer is loaded as a DER format of an
1399 * OCSP response. If file is empty or content is not a valid OCSP response,
1400 * OCSP status extension is enabled but OCSP response is ignored (a warning is
1401 * displayed).
Emeric Brun4147b2e2014-06-16 18:36:30 +02001402 *
1403 * Returns 1 if no ".ocsp" file found, 0 if OCSP status extension is
Joseph Herlant017b3da2018-11-15 09:07:59 -08001404 * successfully enabled, or -1 in other error case.
Emeric Brun4147b2e2014-06-16 18:36:30 +02001405 */
William Lallemand4a660132019-10-14 14:51:41 +02001406#ifndef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet6f507c72020-02-18 15:56:39 +01001407static int ssl_sock_load_ocsp(SSL_CTX *ctx, const struct cert_key_and_chain *ckch, STACK_OF(X509) *chain)
Emeric Brun4147b2e2014-06-16 18:36:30 +02001408{
Emmanuel Hocdet6f507c72020-02-18 15:56:39 +01001409 X509 *x, *issuer;
Emeric Brun4147b2e2014-06-16 18:36:30 +02001410 OCSP_CERTID *cid = NULL;
Emeric Brun4147b2e2014-06-16 18:36:30 +02001411 int i, ret = -1;
Emeric Brun4147b2e2014-06-16 18:36:30 +02001412 struct certificate_ocsp *ocsp = NULL, *iocsp;
1413 char *warn = NULL;
1414 unsigned char *p;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001415 void (*callback) (void);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001416
Emeric Brun4147b2e2014-06-16 18:36:30 +02001417
William Lallemand246c0242019-10-11 08:59:13 +02001418 x = ckch->cert;
Emeric Brun4147b2e2014-06-16 18:36:30 +02001419 if (!x)
1420 goto out;
1421
William Lallemand246c0242019-10-11 08:59:13 +02001422 issuer = ckch->ocsp_issuer;
Emmanuel Hocdet6f507c72020-02-18 15:56:39 +01001423 /* take issuer from chain over ocsp_issuer, is what is done historicaly */
1424 if (chain) {
1425 /* check if one of the certificate of the chain is the issuer */
1426 for (i = 0; i < sk_X509_num(chain); i++) {
1427 X509 *ti = sk_X509_value(chain, i);
1428 if (X509_check_issued(ti, x) == X509_V_OK) {
1429 issuer = ti;
1430 break;
1431 }
1432 }
1433 }
William Lallemand246c0242019-10-11 08:59:13 +02001434 if (!issuer)
1435 goto out;
Emeric Brun4147b2e2014-06-16 18:36:30 +02001436
1437 cid = OCSP_cert_to_id(0, x, issuer);
1438 if (!cid)
1439 goto out;
1440
1441 i = i2d_OCSP_CERTID(cid, NULL);
1442 if (!i || (i > OCSP_MAX_CERTID_ASN1_LENGTH))
1443 goto out;
1444
Vincent Bernat02779b62016-04-03 13:48:43 +02001445 ocsp = calloc(1, sizeof(*ocsp));
Emeric Brun4147b2e2014-06-16 18:36:30 +02001446 if (!ocsp)
1447 goto out;
1448
1449 p = ocsp->key_data;
1450 i2d_OCSP_CERTID(cid, &p);
1451
1452 iocsp = (struct certificate_ocsp *)ebmb_insert(&cert_ocsp_tree, &ocsp->key, OCSP_MAX_CERTID_ASN1_LENGTH);
1453 if (iocsp == ocsp)
1454 ocsp = NULL;
1455
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001456#ifndef SSL_CTX_get_tlsext_status_cb
1457# define SSL_CTX_get_tlsext_status_cb(ctx, cb) \
1458 *cb = (void (*) (void))ctx->tlsext_status_cb;
1459#endif
1460 SSL_CTX_get_tlsext_status_cb(ctx, &callback);
1461
1462 if (!callback) {
Vincent Bernat02779b62016-04-03 13:48:43 +02001463 struct ocsp_cbk_arg *cb_arg = calloc(1, sizeof(*cb_arg));
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001464 EVP_PKEY *pkey;
yanbzhube2774d2015-12-10 15:07:30 -05001465
1466 cb_arg->is_single = 1;
1467 cb_arg->s_ocsp = iocsp;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001468
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001469 pkey = X509_get_pubkey(x);
1470 cb_arg->single_kt = EVP_PKEY_base_id(pkey);
1471 EVP_PKEY_free(pkey);
yanbzhube2774d2015-12-10 15:07:30 -05001472
1473 SSL_CTX_set_tlsext_status_cb(ctx, ssl_sock_ocsp_stapling_cbk);
1474 SSL_CTX_set_tlsext_status_arg(ctx, cb_arg);
1475 } else {
1476 /*
1477 * If the ctx has a status CB, then we have previously set an OCSP staple for this ctx
1478 * Update that cb_arg with the new cert's staple
1479 */
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001480 struct ocsp_cbk_arg *cb_arg;
yanbzhube2774d2015-12-10 15:07:30 -05001481 struct certificate_ocsp *tmp_ocsp;
1482 int index;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001483 int key_type;
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001484 EVP_PKEY *pkey;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001485
1486#ifdef SSL_CTX_get_tlsext_status_arg
1487 SSL_CTX_ctrl(ctx, SSL_CTRL_GET_TLSEXT_STATUS_REQ_CB_ARG, 0, &cb_arg);
1488#else
1489 cb_arg = ctx->tlsext_status_arg;
1490#endif
yanbzhube2774d2015-12-10 15:07:30 -05001491
1492 /*
1493 * The following few lines will convert cb_arg from a single ocsp to multi ocsp
1494 * the order of operations below matter, take care when changing it
1495 */
1496 tmp_ocsp = cb_arg->s_ocsp;
1497 index = ssl_sock_get_ocsp_arg_kt_index(cb_arg->single_kt);
1498 cb_arg->s_ocsp = NULL;
1499 cb_arg->m_ocsp[index] = tmp_ocsp;
1500 cb_arg->is_single = 0;
1501 cb_arg->single_kt = 0;
1502
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001503 pkey = X509_get_pubkey(x);
1504 key_type = EVP_PKEY_base_id(pkey);
1505 EVP_PKEY_free(pkey);
1506
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001507 index = ssl_sock_get_ocsp_arg_kt_index(key_type);
yanbzhube2774d2015-12-10 15:07:30 -05001508 if (index >= 0 && !cb_arg->m_ocsp[index])
1509 cb_arg->m_ocsp[index] = iocsp;
1510
1511 }
Emeric Brun4147b2e2014-06-16 18:36:30 +02001512
1513 ret = 0;
1514
1515 warn = NULL;
William Lallemand246c0242019-10-11 08:59:13 +02001516 if (ssl_sock_load_ocsp_response(ckch->ocsp_response, ocsp, cid, &warn)) {
William Lallemand3b5f3602019-10-16 18:05:05 +02001517 memprintf(&warn, "Loading: %s. Content will be ignored", warn ? warn : "failure");
Christopher Faulet767a84b2017-11-24 16:50:31 +01001518 ha_warning("%s.\n", warn);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001519 }
1520
1521out:
Emeric Brun4147b2e2014-06-16 18:36:30 +02001522 if (cid)
1523 OCSP_CERTID_free(cid);
1524
1525 if (ocsp)
1526 free(ocsp);
1527
1528 if (warn)
1529 free(warn);
1530
Emeric Brun4147b2e2014-06-16 18:36:30 +02001531 return ret;
1532}
William Lallemand4a660132019-10-14 14:51:41 +02001533#else /* OPENSSL_IS_BORINGSSL */
Emmanuel Hocdet6f507c72020-02-18 15:56:39 +01001534static int ssl_sock_load_ocsp(SSL_CTX *ctx, const struct cert_key_and_chain *ckch, STACK_OF(X509) *chain)
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02001535{
William Lallemand4a660132019-10-14 14:51:41 +02001536 return SSL_CTX_set_ocsp_response(ctx, (const uint8_t *)ckch->ocsp_response->area, ckch->ocsp_response->data);
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02001537}
1538#endif
1539
William Lallemand4a660132019-10-14 14:51:41 +02001540#endif
1541
1542
Willy Tarreau5db847a2019-05-09 14:13:35 +02001543#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001544
1545#define CT_EXTENSION_TYPE 18
1546
1547static int sctl_ex_index = -1;
1548
1549/*
1550 * Try to parse Signed Certificate Timestamp List structure. This function
1551 * makes only basic test if the data seems like SCTL. No signature validation
1552 * is performed.
1553 */
Willy Tarreau83061a82018-07-13 11:56:34 +02001554static int ssl_sock_parse_sctl(struct buffer *sctl)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001555{
1556 int ret = 1;
1557 int len, pos, sct_len;
1558 unsigned char *data;
1559
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001560 if (sctl->data < 2)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001561 goto out;
1562
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001563 data = (unsigned char *) sctl->area;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001564 len = (data[0] << 8) | data[1];
1565
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001566 if (len + 2 != sctl->data)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001567 goto out;
1568
1569 data = data + 2;
1570 pos = 0;
1571 while (pos < len) {
1572 if (len - pos < 2)
1573 goto out;
1574
1575 sct_len = (data[pos] << 8) | data[pos + 1];
1576 if (pos + sct_len + 2 > len)
1577 goto out;
1578
1579 pos += sct_len + 2;
1580 }
1581
1582 ret = 0;
1583
1584out:
1585 return ret;
1586}
1587
William Lallemand0dfae6c2019-10-16 18:06:58 +02001588/* Try to load a sctl from a buffer <buf> if not NULL, or read the file <sctl_path>
1589 * It fills the ckch->sctl buffer
1590 * return 0 on success or != 0 on failure */
1591static int ssl_sock_load_sctl_from_file(const char *sctl_path, char *buf, struct cert_key_and_chain *ckch, char **err)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001592{
1593 int fd = -1;
1594 int r = 0;
1595 int ret = 1;
William Lallemand0dfae6c2019-10-16 18:06:58 +02001596 struct buffer tmp;
1597 struct buffer *src;
1598 struct buffer *sctl;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001599
William Lallemand0dfae6c2019-10-16 18:06:58 +02001600 if (buf) {
1601 tmp.area = buf;
1602 tmp.data = strlen(buf);
1603 tmp.size = tmp.data + 1;
1604 src = &tmp;
1605 } else {
1606 fd = open(sctl_path, O_RDONLY);
1607 if (fd == -1)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001608 goto end;
William Lallemand0dfae6c2019-10-16 18:06:58 +02001609
1610 trash.data = 0;
1611 while (trash.data < trash.size) {
1612 r = read(fd, trash.area + trash.data, trash.size - trash.data);
1613 if (r < 0) {
1614 if (errno == EINTR)
1615 continue;
1616 goto end;
1617 }
1618 else if (r == 0) {
1619 break;
1620 }
1621 trash.data += r;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001622 }
William Lallemand0dfae6c2019-10-16 18:06:58 +02001623 src = &trash;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001624 }
1625
William Lallemand0dfae6c2019-10-16 18:06:58 +02001626 ret = ssl_sock_parse_sctl(src);
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001627 if (ret)
1628 goto end;
1629
William Lallemand0dfae6c2019-10-16 18:06:58 +02001630 sctl = calloc(1, sizeof(*sctl));
1631 if (!chunk_dup(sctl, src)) {
1632 free(sctl);
1633 sctl = NULL;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001634 goto end;
1635 }
Emmanuel Hocdet224a0872020-01-16 15:15:49 +01001636 /* no error, fill ckch with new context, old context must be free */
1637 if (ckch->sctl) {
1638 free(ckch->sctl->area);
1639 ckch->sctl->area = NULL;
1640 free(ckch->sctl);
1641 }
William Lallemand0dfae6c2019-10-16 18:06:58 +02001642 ckch->sctl = sctl;
Emmanuel Hocdet224a0872020-01-16 15:15:49 +01001643 ret = 0;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001644end:
1645 if (fd != -1)
1646 close(fd);
1647
1648 return ret;
1649}
1650
1651int ssl_sock_sctl_add_cbk(SSL *ssl, unsigned ext_type, const unsigned char **out, size_t *outlen, int *al, void *add_arg)
1652{
Willy Tarreau83061a82018-07-13 11:56:34 +02001653 struct buffer *sctl = add_arg;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001654
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001655 *out = (unsigned char *) sctl->area;
1656 *outlen = sctl->data;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001657
1658 return 1;
1659}
1660
1661int ssl_sock_sctl_parse_cbk(SSL *s, unsigned int ext_type, const unsigned char *in, size_t inlen, int *al, void *parse_arg)
1662{
1663 return 1;
1664}
1665
William Lallemanda17f4112019-10-10 15:16:44 +02001666static int ssl_sock_load_sctl(SSL_CTX *ctx, struct buffer *sctl)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001667{
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001668 int ret = -1;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001669
William Lallemanda17f4112019-10-10 15:16:44 +02001670 if (!SSL_CTX_add_server_custom_ext(ctx, CT_EXTENSION_TYPE, ssl_sock_sctl_add_cbk, NULL, sctl, ssl_sock_sctl_parse_cbk, NULL))
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001671 goto out;
1672
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001673 SSL_CTX_set_ex_data(ctx, sctl_ex_index, sctl);
1674
1675 ret = 0;
1676
1677out:
1678 return ret;
1679}
1680
1681#endif
1682
Emeric Brune1f38db2012-09-03 20:36:47 +02001683void ssl_sock_infocbk(const SSL *ssl, int where, int ret)
1684{
Thierry FOURNIER28962c92018-06-17 21:37:05 +02001685 struct connection *conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001686 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
Emeric Brund8b2bb52014-01-28 15:43:53 +01001687 BIO *write_bio;
Willy Tarreau622317d2015-02-27 16:36:16 +01001688 (void)ret; /* shut gcc stupid warning */
Emeric Brune1f38db2012-09-03 20:36:47 +02001689
Dirkjan Bussink526894f2019-01-21 09:35:03 -08001690#ifndef SSL_OP_NO_RENEGOTIATION
1691 /* Please note that BoringSSL defines this macro to zero so don't
1692 * change this to #if and do not assign a default value to this macro!
1693 */
Emeric Brune1f38db2012-09-03 20:36:47 +02001694 if (where & SSL_CB_HANDSHAKE_START) {
1695 /* Disable renegotiation (CVE-2009-3555) */
Willy Tarreauc192b0a2020-01-23 09:11:58 +01001696 if ((conn->flags & (CO_FL_WAIT_L6_CONN | CO_FL_EARLY_SSL_HS | CO_FL_EARLY_DATA)) == 0) {
Emeric Brune1f38db2012-09-03 20:36:47 +02001697 conn->flags |= CO_FL_ERROR;
Willy Tarreau20879a02012-12-03 16:32:10 +01001698 conn->err_code = CO_ER_SSL_RENEG;
1699 }
Emeric Brune1f38db2012-09-03 20:36:47 +02001700 }
Dirkjan Bussink526894f2019-01-21 09:35:03 -08001701#endif
Emeric Brund8b2bb52014-01-28 15:43:53 +01001702
1703 if ((where & SSL_CB_ACCEPT_LOOP) == SSL_CB_ACCEPT_LOOP) {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001704 if (!(ctx->xprt_st & SSL_SOCK_ST_FL_16K_WBFSIZE)) {
Emeric Brund8b2bb52014-01-28 15:43:53 +01001705 /* Long certificate chains optimz
1706 If write and read bios are differents, we
1707 consider that the buffering was activated,
1708 so we rise the output buffer size from 4k
1709 to 16k */
1710 write_bio = SSL_get_wbio(ssl);
1711 if (write_bio != SSL_get_rbio(ssl)) {
1712 BIO_set_write_buffer_size(write_bio, 16384);
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001713 ctx->xprt_st |= SSL_SOCK_ST_FL_16K_WBFSIZE;
Emeric Brund8b2bb52014-01-28 15:43:53 +01001714 }
1715 }
1716 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02001717}
1718
Emeric Brune64aef12012-09-21 13:15:06 +02001719/* Callback is called for each certificate of the chain during a verify
1720 ok is set to 1 if preverify detect no error on current certificate.
1721 Returns 0 to break the handshake, 1 otherwise. */
Evan Broderbe554312013-06-27 00:05:25 -07001722int ssl_sock_bind_verifycbk(int ok, X509_STORE_CTX *x_store)
Emeric Brune64aef12012-09-21 13:15:06 +02001723{
1724 SSL *ssl;
1725 struct connection *conn;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001726 struct ssl_sock_ctx *ctx;
Emeric Brun81c00f02012-09-21 14:31:21 +02001727 int err, depth;
Emeric Brune64aef12012-09-21 13:15:06 +02001728
1729 ssl = X509_STORE_CTX_get_ex_data(x_store, SSL_get_ex_data_X509_STORE_CTX_idx());
Thierry FOURNIER28962c92018-06-17 21:37:05 +02001730 conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Emeric Brune64aef12012-09-21 13:15:06 +02001731
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001732 ctx = conn->xprt_ctx;
1733
1734 ctx->xprt_st |= SSL_SOCK_ST_FL_VERIFY_DONE;
Emeric Brune64aef12012-09-21 13:15:06 +02001735
Emeric Brun81c00f02012-09-21 14:31:21 +02001736 if (ok) /* no errors */
1737 return ok;
1738
1739 depth = X509_STORE_CTX_get_error_depth(x_store);
1740 err = X509_STORE_CTX_get_error(x_store);
1741
1742 /* check if CA error needs to be ignored */
1743 if (depth > 0) {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001744 if (!SSL_SOCK_ST_TO_CA_ERROR(ctx->xprt_st)) {
1745 ctx->xprt_st |= SSL_SOCK_CA_ERROR_TO_ST(err);
1746 ctx->xprt_st |= SSL_SOCK_CAEDEPTH_TO_ST(depth);
Emeric Brunf282a812012-09-21 15:27:54 +02001747 }
1748
Willy Tarreau731248f2020-02-04 14:02:02 +01001749 if (err < 64 && __objt_listener(conn->target)->bind_conf->ca_ignerr & (1ULL << err)) {
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02001750 ssl_sock_dump_errors(conn);
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001751 ERR_clear_error();
Emeric Brun81c00f02012-09-21 14:31:21 +02001752 return 1;
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001753 }
Emeric Brun81c00f02012-09-21 14:31:21 +02001754
Willy Tarreau20879a02012-12-03 16:32:10 +01001755 conn->err_code = CO_ER_SSL_CA_FAIL;
Emeric Brun81c00f02012-09-21 14:31:21 +02001756 return 0;
1757 }
1758
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001759 if (!SSL_SOCK_ST_TO_CRTERROR(ctx->xprt_st))
1760 ctx->xprt_st |= SSL_SOCK_CRTERROR_TO_ST(err);
Emeric Brunf282a812012-09-21 15:27:54 +02001761
Emeric Brun81c00f02012-09-21 14:31:21 +02001762 /* check if certificate error needs to be ignored */
Willy Tarreau731248f2020-02-04 14:02:02 +01001763 if (err < 64 && __objt_listener(conn->target)->bind_conf->crt_ignerr & (1ULL << err)) {
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02001764 ssl_sock_dump_errors(conn);
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001765 ERR_clear_error();
Emeric Brun81c00f02012-09-21 14:31:21 +02001766 return 1;
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001767 }
Emeric Brun81c00f02012-09-21 14:31:21 +02001768
Willy Tarreau20879a02012-12-03 16:32:10 +01001769 conn->err_code = CO_ER_SSL_CRT_FAIL;
Emeric Brun81c00f02012-09-21 14:31:21 +02001770 return 0;
Emeric Brune64aef12012-09-21 13:15:06 +02001771}
1772
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001773static inline
1774void ssl_sock_parse_clienthello(int write_p, int version, int content_type,
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001775 const void *buf, size_t len, SSL *ssl)
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001776{
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001777 struct ssl_capture *capture;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001778 unsigned char *msg;
1779 unsigned char *end;
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001780 size_t rec_len;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001781
1782 /* This function is called for "from client" and "to server"
1783 * connections. The combination of write_p == 0 and content_type == 22
Joseph Herlant017b3da2018-11-15 09:07:59 -08001784 * is only available during "from client" connection.
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001785 */
1786
1787 /* "write_p" is set to 0 is the bytes are received messages,
1788 * otherwise it is set to 1.
1789 */
1790 if (write_p != 0)
1791 return;
1792
1793 /* content_type contains the type of message received or sent
1794 * according with the SSL/TLS protocol spec. This message is
1795 * encoded with one byte. The value 256 (two bytes) is used
1796 * for designing the SSL/TLS record layer. According with the
1797 * rfc6101, the expected message (other than 256) are:
1798 * - change_cipher_spec(20)
1799 * - alert(21)
1800 * - handshake(22)
1801 * - application_data(23)
1802 * - (255)
1803 * We are interessed by the handshake and specially the client
1804 * hello.
1805 */
1806 if (content_type != 22)
1807 return;
1808
1809 /* The message length is at least 4 bytes, containing the
1810 * message type and the message length.
1811 */
1812 if (len < 4)
1813 return;
1814
1815 /* First byte of the handshake message id the type of
1816 * message. The konwn types are:
1817 * - hello_request(0)
1818 * - client_hello(1)
1819 * - server_hello(2)
1820 * - certificate(11)
1821 * - server_key_exchange (12)
1822 * - certificate_request(13)
1823 * - server_hello_done(14)
1824 * We are interested by the client hello.
1825 */
1826 msg = (unsigned char *)buf;
1827 if (msg[0] != 1)
1828 return;
1829
1830 /* Next three bytes are the length of the message. The total length
1831 * must be this decoded length + 4. If the length given as argument
1832 * is not the same, we abort the protocol dissector.
1833 */
1834 rec_len = (msg[1] << 16) + (msg[2] << 8) + msg[3];
1835 if (len < rec_len + 4)
1836 return;
1837 msg += 4;
1838 end = msg + rec_len;
1839 if (end < msg)
1840 return;
1841
1842 /* Expect 2 bytes for protocol version (1 byte for major and 1 byte
1843 * for minor, the random, composed by 4 bytes for the unix time and
Baptiste Assmann6be139f2018-11-28 15:20:25 +01001844 * 28 bytes for unix payload. So we jump 1 + 1 + 4 + 28.
1845 */
1846 msg += 1 + 1 + 4 + 28;
1847 if (msg > end)
1848 return;
1849
1850 /* Next, is session id:
1851 * if present, we have to jump by length + 1 for the size information
1852 * if not present, we have to jump by 1 only
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001853 */
Baptiste Assmann6be139f2018-11-28 15:20:25 +01001854 if (msg[0] > 0)
1855 msg += msg[0];
1856 msg += 1;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001857 if (msg > end)
1858 return;
1859
1860 /* Next two bytes are the ciphersuite length. */
1861 if (msg + 2 > end)
1862 return;
1863 rec_len = (msg[0] << 8) + msg[1];
1864 msg += 2;
1865 if (msg + rec_len > end || msg + rec_len < msg)
1866 return;
1867
Willy Tarreaubafbe012017-11-24 17:34:44 +01001868 capture = pool_alloc_dirty(pool_head_ssl_capture);
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001869 if (!capture)
1870 return;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001871 /* Compute the xxh64 of the ciphersuite. */
1872 capture->xxh64 = XXH64(msg, rec_len, 0);
1873
1874 /* Capture the ciphersuite. */
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001875 capture->ciphersuite_len = (global_ssl.capture_cipherlist < rec_len) ?
1876 global_ssl.capture_cipherlist : rec_len;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001877 memcpy(capture->ciphersuite, msg, capture->ciphersuite_len);
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001878
1879 SSL_set_ex_data(ssl, ssl_capture_ptr_index, capture);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001880}
1881
Emeric Brun29f037d2014-04-25 19:05:36 +02001882/* Callback is called for ssl protocol analyse */
1883void ssl_sock_msgcbk(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg)
1884{
Emeric Brun29f037d2014-04-25 19:05:36 +02001885#ifdef TLS1_RT_HEARTBEAT
1886 /* test heartbeat received (write_p is set to 0
1887 for a received record) */
Willy Tarreauf51c6982014-04-25 20:02:39 +02001888 if ((content_type == TLS1_RT_HEARTBEAT) && (write_p == 0)) {
Thierry FOURNIER28962c92018-06-17 21:37:05 +02001889 struct connection *conn = SSL_get_ex_data(ssl, ssl_app_data_index);
William Lallemand7e1770b2019-05-13 14:31:34 +02001890 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
Willy Tarreauf51c6982014-04-25 20:02:39 +02001891 const unsigned char *p = buf;
1892 unsigned int payload;
1893
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001894 ctx->xprt_st |= SSL_SOCK_RECV_HEARTBEAT;
Willy Tarreauf51c6982014-04-25 20:02:39 +02001895
1896 /* Check if this is a CVE-2014-0160 exploitation attempt. */
1897 if (*p != TLS1_HB_REQUEST)
1898 return;
1899
Willy Tarreauaeed6722014-04-25 23:59:58 +02001900 if (len < 1 + 2 + 16) /* 1 type + 2 size + 0 payload + 16 padding */
Willy Tarreauf51c6982014-04-25 20:02:39 +02001901 goto kill_it;
1902
1903 payload = (p[1] * 256) + p[2];
Willy Tarreau3b2fdb62014-04-25 23:44:22 +02001904 if (3 + payload + 16 <= len)
Willy Tarreauf51c6982014-04-25 20:02:39 +02001905 return; /* OK no problem */
Willy Tarreauaeed6722014-04-25 23:59:58 +02001906 kill_it:
Willy Tarreau3b2fdb62014-04-25 23:44:22 +02001907 /* We have a clear heartbleed attack (CVE-2014-0160), the
1908 * advertised payload is larger than the advertised packet
1909 * length, so we have garbage in the buffer between the
1910 * payload and the end of the buffer (p+len). We can't know
1911 * if the SSL stack is patched, and we don't know if we can
1912 * safely wipe out the area between p+3+len and payload.
1913 * So instead, we prevent the response from being sent by
1914 * setting the max_send_fragment to 0 and we report an SSL
1915 * error, which will kill this connection. It will be reported
1916 * above as SSL_ERROR_SSL while an other handshake failure with
Willy Tarreauf51c6982014-04-25 20:02:39 +02001917 * a heartbeat message will be reported as SSL_ERROR_SYSCALL.
1918 */
Willy Tarreau3b2fdb62014-04-25 23:44:22 +02001919 ssl->max_send_fragment = 0;
Willy Tarreauf51c6982014-04-25 20:02:39 +02001920 SSLerr(SSL_F_TLS1_HEARTBEAT, SSL_R_SSL_HANDSHAKE_FAILURE);
1921 return;
1922 }
Emeric Brun29f037d2014-04-25 19:05:36 +02001923#endif
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001924 if (global_ssl.capture_cipherlist > 0)
1925 ssl_sock_parse_clienthello(write_p, version, content_type, buf, len, ssl);
Emeric Brun29f037d2014-04-25 19:05:36 +02001926}
1927
Bernard Spil13c53f82018-02-15 13:34:58 +01001928#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Olivier Houchardc7566002018-11-20 23:33:50 +01001929static int ssl_sock_srv_select_protos(SSL *s, unsigned char **out, unsigned char *outlen,
1930 const unsigned char *in, unsigned int inlen,
1931 void *arg)
1932{
1933 struct server *srv = arg;
1934
1935 if (SSL_select_next_proto(out, outlen, in, inlen, (unsigned char *)srv->ssl_ctx.npn_str,
1936 srv->ssl_ctx.npn_len) == OPENSSL_NPN_NEGOTIATED)
1937 return SSL_TLSEXT_ERR_OK;
1938 return SSL_TLSEXT_ERR_NOACK;
1939}
1940#endif
1941
1942#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02001943/* This callback is used so that the server advertises the list of
1944 * negociable protocols for NPN.
1945 */
1946static int ssl_sock_advertise_npn_protos(SSL *s, const unsigned char **data,
1947 unsigned int *len, void *arg)
1948{
Emmanuel Hocdet98263292016-12-29 18:26:15 +01001949 struct ssl_bind_conf *conf = arg;
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02001950
1951 *data = (const unsigned char *)conf->npn_str;
1952 *len = conf->npn_len;
1953 return SSL_TLSEXT_ERR_OK;
1954}
1955#endif
1956
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01001957#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02001958/* This callback is used so that the server advertises the list of
1959 * negociable protocols for ALPN.
1960 */
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01001961static int ssl_sock_advertise_alpn_protos(SSL *s, const unsigned char **out,
1962 unsigned char *outlen,
1963 const unsigned char *server,
1964 unsigned int server_len, void *arg)
Willy Tarreauab861d32013-04-02 02:30:41 +02001965{
Emmanuel Hocdet98263292016-12-29 18:26:15 +01001966 struct ssl_bind_conf *conf = arg;
Willy Tarreauab861d32013-04-02 02:30:41 +02001967
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01001968 if (SSL_select_next_proto((unsigned char**) out, outlen, (const unsigned char *)conf->alpn_str,
1969 conf->alpn_len, server, server_len) != OPENSSL_NPN_NEGOTIATED) {
1970 return SSL_TLSEXT_ERR_NOACK;
1971 }
Willy Tarreauab861d32013-04-02 02:30:41 +02001972 return SSL_TLSEXT_ERR_OK;
1973}
1974#endif
1975
Willy Tarreauc8ad3be2015-06-17 15:48:26 +02001976#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01001977#ifndef SSL_NO_GENERATE_CERTIFICATES
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001978
Christopher Faulet30548802015-06-11 13:39:32 +02001979/* Create a X509 certificate with the specified servername and serial. This
1980 * function returns a SSL_CTX object or NULL if an error occurs. */
Christopher Faulet7969a332015-10-09 11:15:03 +02001981static SSL_CTX *
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001982ssl_sock_do_create_cert(const char *servername, struct bind_conf *bind_conf, SSL *ssl)
Christopher Faulet31af49d2015-06-09 17:29:50 +02001983{
Christopher Faulet7969a332015-10-09 11:15:03 +02001984 X509 *cacert = bind_conf->ca_sign_cert;
1985 EVP_PKEY *capkey = bind_conf->ca_sign_pkey;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001986 SSL_CTX *ssl_ctx = NULL;
1987 X509 *newcrt = NULL;
1988 EVP_PKEY *pkey = NULL;
Emmanuel Hocdet15969292017-08-11 10:56:00 +02001989 SSL *tmp_ssl = NULL;
Emmanuel Hocdeta9b84022018-10-01 18:41:36 +02001990 CONF *ctmp = NULL;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001991 X509_NAME *name;
1992 const EVP_MD *digest;
1993 X509V3_CTX ctx;
1994 unsigned int i;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001995 int key_type;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001996
Christopher Faulet48a83322017-07-28 16:56:09 +02001997 /* Get the private key of the default certificate and use it */
Willy Tarreau5db847a2019-05-09 14:13:35 +02001998#if (HA_OPENSSL_VERSION_NUMBER >= 0x10002000L)
Emmanuel Hocdet15969292017-08-11 10:56:00 +02001999 pkey = SSL_CTX_get0_privatekey(bind_conf->default_ctx);
2000#else
2001 tmp_ssl = SSL_new(bind_conf->default_ctx);
2002 if (tmp_ssl)
2003 pkey = SSL_get_privatekey(tmp_ssl);
2004#endif
2005 if (!pkey)
Christopher Faulet31af49d2015-06-09 17:29:50 +02002006 goto mkcert_error;
2007
2008 /* Create the certificate */
2009 if (!(newcrt = X509_new()))
2010 goto mkcert_error;
2011
2012 /* Set version number for the certificate (X509v3) and the serial
2013 * number */
2014 if (X509_set_version(newcrt, 2L) != 1)
2015 goto mkcert_error;
Olivier Houchard2be5a4c2019-03-08 18:54:43 +01002016 ASN1_INTEGER_set(X509_get_serialNumber(newcrt), _HA_ATOMIC_ADD(&ssl_ctx_serial, 1));
Christopher Faulet31af49d2015-06-09 17:29:50 +02002017
2018 /* Set duration for the certificate */
Rosen Penev68185952018-12-14 08:47:02 -08002019 if (!X509_gmtime_adj(X509_getm_notBefore(newcrt), (long)-60*60*24) ||
2020 !X509_gmtime_adj(X509_getm_notAfter(newcrt),(long)60*60*24*365))
Christopher Faulet31af49d2015-06-09 17:29:50 +02002021 goto mkcert_error;
2022
2023 /* set public key in the certificate */
2024 if (X509_set_pubkey(newcrt, pkey) != 1)
2025 goto mkcert_error;
2026
2027 /* Set issuer name from the CA */
2028 if (!(name = X509_get_subject_name(cacert)))
2029 goto mkcert_error;
2030 if (X509_set_issuer_name(newcrt, name) != 1)
2031 goto mkcert_error;
2032
2033 /* Set the subject name using the same, but the CN */
2034 name = X509_NAME_dup(name);
2035 if (X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC,
2036 (const unsigned char *)servername,
2037 -1, -1, 0) != 1) {
2038 X509_NAME_free(name);
2039 goto mkcert_error;
2040 }
2041 if (X509_set_subject_name(newcrt, name) != 1) {
2042 X509_NAME_free(name);
2043 goto mkcert_error;
2044 }
2045 X509_NAME_free(name);
2046
2047 /* Add x509v3 extensions as specified */
Emmanuel Hocdeta9b84022018-10-01 18:41:36 +02002048 ctmp = NCONF_new(NULL);
Christopher Faulet31af49d2015-06-09 17:29:50 +02002049 X509V3_set_ctx(&ctx, cacert, newcrt, NULL, NULL, 0);
2050 for (i = 0; i < X509V3_EXT_SIZE; i++) {
2051 X509_EXTENSION *ext;
2052
Emmanuel Hocdeta9b84022018-10-01 18:41:36 +02002053 if (!(ext = X509V3_EXT_nconf(ctmp, &ctx, x509v3_ext_names[i], x509v3_ext_values[i])))
Christopher Faulet31af49d2015-06-09 17:29:50 +02002054 goto mkcert_error;
2055 if (!X509_add_ext(newcrt, ext, -1)) {
2056 X509_EXTENSION_free(ext);
2057 goto mkcert_error;
2058 }
2059 X509_EXTENSION_free(ext);
2060 }
2061
2062 /* Sign the certificate with the CA private key */
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002063
2064 key_type = EVP_PKEY_base_id(capkey);
2065
2066 if (key_type == EVP_PKEY_DSA)
2067 digest = EVP_sha1();
2068 else if (key_type == EVP_PKEY_RSA)
Christopher Faulet31af49d2015-06-09 17:29:50 +02002069 digest = EVP_sha256();
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002070 else if (key_type == EVP_PKEY_EC)
Christopher Faulet7969a332015-10-09 11:15:03 +02002071 digest = EVP_sha256();
2072 else {
Willy Tarreau9a1ab082019-05-09 13:26:41 +02002073#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000000fL) && !defined(OPENSSL_IS_BORINGSSL)
Christopher Faulet7969a332015-10-09 11:15:03 +02002074 int nid;
2075
2076 if (EVP_PKEY_get_default_digest_nid(capkey, &nid) <= 0)
2077 goto mkcert_error;
2078 if (!(digest = EVP_get_digestbynid(nid)))
2079 goto mkcert_error;
Christopher Faulete7db2162015-10-19 13:59:24 +02002080#else
2081 goto mkcert_error;
2082#endif
Christopher Faulet7969a332015-10-09 11:15:03 +02002083 }
2084
Christopher Faulet31af49d2015-06-09 17:29:50 +02002085 if (!(X509_sign(newcrt, capkey, digest)))
2086 goto mkcert_error;
2087
2088 /* Create and set the new SSL_CTX */
2089 if (!(ssl_ctx = SSL_CTX_new(SSLv23_server_method())))
2090 goto mkcert_error;
2091 if (!SSL_CTX_use_PrivateKey(ssl_ctx, pkey))
2092 goto mkcert_error;
2093 if (!SSL_CTX_use_certificate(ssl_ctx, newcrt))
2094 goto mkcert_error;
2095 if (!SSL_CTX_check_private_key(ssl_ctx))
2096 goto mkcert_error;
2097
2098 if (newcrt) X509_free(newcrt);
Christopher Faulet7969a332015-10-09 11:15:03 +02002099
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01002100#ifndef OPENSSL_NO_DH
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02002101 SSL_CTX_set_tmp_dh_callback(ssl_ctx, ssl_get_tmp_dh);
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01002102#endif
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02002103#if defined(SSL_CTX_set_tmp_ecdh) && !defined(OPENSSL_NO_ECDH)
2104 {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01002105 const char *ecdhe = (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe : ECDHE_DEFAULT_CURVE);
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02002106 EC_KEY *ecc;
2107 int nid;
2108
2109 if ((nid = OBJ_sn2nid(ecdhe)) == NID_undef)
2110 goto end;
2111 if (!(ecc = EC_KEY_new_by_curve_name(nid)))
2112 goto end;
2113 SSL_CTX_set_tmp_ecdh(ssl_ctx, ecc);
2114 EC_KEY_free(ecc);
2115 }
2116#endif
2117 end:
Christopher Faulet31af49d2015-06-09 17:29:50 +02002118 return ssl_ctx;
2119
2120 mkcert_error:
Emmanuel Hocdeta9b84022018-10-01 18:41:36 +02002121 if (ctmp) NCONF_free(ctmp);
Emmanuel Hocdet15969292017-08-11 10:56:00 +02002122 if (tmp_ssl) SSL_free(tmp_ssl);
Christopher Faulet31af49d2015-06-09 17:29:50 +02002123 if (ssl_ctx) SSL_CTX_free(ssl_ctx);
2124 if (newcrt) X509_free(newcrt);
Christopher Faulet31af49d2015-06-09 17:29:50 +02002125 return NULL;
2126}
2127
Christopher Faulet7969a332015-10-09 11:15:03 +02002128SSL_CTX *
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002129ssl_sock_create_cert(struct connection *conn, const char *servername, unsigned int key)
Christopher Faulet7969a332015-10-09 11:15:03 +02002130{
Willy Tarreau07d94e42018-09-20 10:57:52 +02002131 struct bind_conf *bind_conf = __objt_listener(conn->target)->bind_conf;
Olivier Houchard66ab4982019-02-26 18:37:15 +01002132 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002133
Olivier Houchard66ab4982019-02-26 18:37:15 +01002134 return ssl_sock_do_create_cert(servername, bind_conf, ctx->ssl);
Christopher Faulet7969a332015-10-09 11:15:03 +02002135}
2136
Christopher Faulet30548802015-06-11 13:39:32 +02002137/* Do a lookup for a certificate in the LRU cache used to store generated
Emeric Brun821bb9b2017-06-15 16:37:39 +02002138 * certificates and immediately assign it to the SSL session if not null. */
Christopher Faulet30548802015-06-11 13:39:32 +02002139SSL_CTX *
Emeric Brun821bb9b2017-06-15 16:37:39 +02002140ssl_sock_assign_generated_cert(unsigned int key, struct bind_conf *bind_conf, SSL *ssl)
Christopher Faulet30548802015-06-11 13:39:32 +02002141{
2142 struct lru64 *lru = NULL;
2143
2144 if (ssl_ctx_lru_tree) {
Willy Tarreau03f4ec42018-05-17 10:56:47 +02002145 HA_RWLOCK_WRLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002146 lru = lru64_lookup(key, ssl_ctx_lru_tree, bind_conf->ca_sign_cert, 0);
Emeric Brun821bb9b2017-06-15 16:37:39 +02002147 if (lru && lru->domain) {
2148 if (ssl)
2149 SSL_set_SSL_CTX(ssl, (SSL_CTX *)lru->data);
Willy Tarreau03f4ec42018-05-17 10:56:47 +02002150 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet30548802015-06-11 13:39:32 +02002151 return (SSL_CTX *)lru->data;
Emeric Brun821bb9b2017-06-15 16:37:39 +02002152 }
Willy Tarreau03f4ec42018-05-17 10:56:47 +02002153 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet30548802015-06-11 13:39:32 +02002154 }
2155 return NULL;
2156}
2157
Emeric Brun821bb9b2017-06-15 16:37:39 +02002158/* Same as <ssl_sock_assign_generated_cert> but without SSL session. This
2159 * function is not thread-safe, it should only be used to check if a certificate
2160 * exists in the lru cache (with no warranty it will not be removed by another
2161 * thread). It is kept for backward compatibility. */
2162SSL_CTX *
2163ssl_sock_get_generated_cert(unsigned int key, struct bind_conf *bind_conf)
2164{
2165 return ssl_sock_assign_generated_cert(key, bind_conf, NULL);
2166}
2167
Christopher Fauletd2cab922015-07-28 16:03:47 +02002168/* Set a certificate int the LRU cache used to store generated
2169 * certificate. Return 0 on success, otherwise -1 */
2170int
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002171ssl_sock_set_generated_cert(SSL_CTX *ssl_ctx, unsigned int key, struct bind_conf *bind_conf)
Christopher Faulet30548802015-06-11 13:39:32 +02002172{
2173 struct lru64 *lru = NULL;
2174
2175 if (ssl_ctx_lru_tree) {
Christopher Faulet2a944ee2017-11-07 10:42:54 +01002176 HA_RWLOCK_WRLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002177 lru = lru64_get(key, ssl_ctx_lru_tree, bind_conf->ca_sign_cert, 0);
Emeric Brun821bb9b2017-06-15 16:37:39 +02002178 if (!lru) {
Christopher Faulet2a944ee2017-11-07 10:42:54 +01002179 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Fauletd2cab922015-07-28 16:03:47 +02002180 return -1;
Emeric Brun821bb9b2017-06-15 16:37:39 +02002181 }
Christopher Faulet30548802015-06-11 13:39:32 +02002182 if (lru->domain && lru->data)
2183 lru->free((SSL_CTX *)lru->data);
Christopher Faulet7969a332015-10-09 11:15:03 +02002184 lru64_commit(lru, ssl_ctx, bind_conf->ca_sign_cert, 0, (void (*)(void *))SSL_CTX_free);
Christopher Faulet2a944ee2017-11-07 10:42:54 +01002185 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Fauletd2cab922015-07-28 16:03:47 +02002186 return 0;
Christopher Faulet30548802015-06-11 13:39:32 +02002187 }
Christopher Fauletd2cab922015-07-28 16:03:47 +02002188 return -1;
Christopher Faulet30548802015-06-11 13:39:32 +02002189}
2190
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002191/* Compute the key of the certificate. */
Christopher Faulet30548802015-06-11 13:39:32 +02002192unsigned int
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002193ssl_sock_generated_cert_key(const void *data, size_t len)
Christopher Faulet30548802015-06-11 13:39:32 +02002194{
2195 return XXH32(data, len, ssl_ctx_lru_seed);
2196}
2197
Willy Tarreau2f63ef42015-10-20 15:16:01 +02002198/* Generate a cert and immediately assign it to the SSL session so that the cert's
2199 * refcount is maintained regardless of the cert's presence in the LRU cache.
2200 */
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002201static int
Christopher Faulet7969a332015-10-09 11:15:03 +02002202ssl_sock_generate_certificate(const char *servername, struct bind_conf *bind_conf, SSL *ssl)
Christopher Faulet31af49d2015-06-09 17:29:50 +02002203{
2204 X509 *cacert = bind_conf->ca_sign_cert;
Christopher Faulet31af49d2015-06-09 17:29:50 +02002205 SSL_CTX *ssl_ctx = NULL;
2206 struct lru64 *lru = NULL;
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002207 unsigned int key;
Christopher Faulet31af49d2015-06-09 17:29:50 +02002208
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002209 key = ssl_sock_generated_cert_key(servername, strlen(servername));
Christopher Faulet31af49d2015-06-09 17:29:50 +02002210 if (ssl_ctx_lru_tree) {
Christopher Faulet2a944ee2017-11-07 10:42:54 +01002211 HA_RWLOCK_WRLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002212 lru = lru64_get(key, ssl_ctx_lru_tree, cacert, 0);
Christopher Faulet31af49d2015-06-09 17:29:50 +02002213 if (lru && lru->domain)
2214 ssl_ctx = (SSL_CTX *)lru->data;
Christopher Fauletd2cab922015-07-28 16:03:47 +02002215 if (!ssl_ctx && lru) {
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002216 ssl_ctx = ssl_sock_do_create_cert(servername, bind_conf, ssl);
Christopher Faulet31af49d2015-06-09 17:29:50 +02002217 lru64_commit(lru, ssl_ctx, cacert, 0, (void (*)(void *))SSL_CTX_free);
Christopher Fauletd2cab922015-07-28 16:03:47 +02002218 }
Willy Tarreau2f63ef42015-10-20 15:16:01 +02002219 SSL_set_SSL_CTX(ssl, ssl_ctx);
Christopher Faulet2a944ee2017-11-07 10:42:54 +01002220 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002221 return 1;
Christopher Faulet31af49d2015-06-09 17:29:50 +02002222 }
Willy Tarreau2f63ef42015-10-20 15:16:01 +02002223 else {
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002224 ssl_ctx = ssl_sock_do_create_cert(servername, bind_conf, ssl);
Willy Tarreau2f63ef42015-10-20 15:16:01 +02002225 SSL_set_SSL_CTX(ssl, ssl_ctx);
2226 /* No LRU cache, this CTX will be released as soon as the session dies */
2227 SSL_CTX_free(ssl_ctx);
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002228 return 1;
Willy Tarreau2f63ef42015-10-20 15:16:01 +02002229 }
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002230 return 0;
2231}
2232static int
2233ssl_sock_generate_certificate_from_conn(struct bind_conf *bind_conf, SSL *ssl)
2234{
2235 unsigned int key;
Thierry FOURNIER28962c92018-06-17 21:37:05 +02002236 struct connection *conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002237
Willy Tarreauf5bdb642019-07-17 11:29:32 +02002238 if (conn_get_dst(conn)) {
Willy Tarreau085a1512019-07-17 14:47:35 +02002239 key = ssl_sock_generated_cert_key(conn->dst, get_addr_len(conn->dst));
Emeric Brun821bb9b2017-06-15 16:37:39 +02002240 if (ssl_sock_assign_generated_cert(key, bind_conf, ssl))
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002241 return 1;
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002242 }
2243 return 0;
Christopher Faulet31af49d2015-06-09 17:29:50 +02002244}
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002245#endif /* !defined SSL_NO_GENERATE_CERTIFICATES */
Christopher Faulet31af49d2015-06-09 17:29:50 +02002246
Willy Tarreau9a1ab082019-05-09 13:26:41 +02002247#if (HA_OPENSSL_VERSION_NUMBER < 0x1010000fL)
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002248typedef enum { SET_CLIENT, SET_SERVER } set_context_func;
2249
2250static void ctx_set_SSLv3_func(SSL_CTX *ctx, set_context_func c)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002251{
Emmanuel Hocdet23877ab2017-07-12 12:53:02 +02002252#if SSL_OP_NO_SSLv3
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002253 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, SSLv3_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002254 : SSL_CTX_set_ssl_version(ctx, SSLv3_client_method());
2255#endif
2256}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002257static void ctx_set_TLSv10_func(SSL_CTX *ctx, set_context_func c) {
2258 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, TLSv1_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002259 : SSL_CTX_set_ssl_version(ctx, TLSv1_client_method());
2260}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002261static void ctx_set_TLSv11_func(SSL_CTX *ctx, set_context_func c) {
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002262#if SSL_OP_NO_TLSv1_1
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002263 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, TLSv1_1_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002264 : SSL_CTX_set_ssl_version(ctx, TLSv1_1_client_method());
2265#endif
2266}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002267static void ctx_set_TLSv12_func(SSL_CTX *ctx, set_context_func c) {
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002268#if SSL_OP_NO_TLSv1_2
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002269 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, TLSv1_2_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002270 : SSL_CTX_set_ssl_version(ctx, TLSv1_2_client_method());
2271#endif
2272}
Bertrand Jacquina25282b2018-08-14 00:56:13 +01002273/* TLSv1.2 is the last supported version in this context. */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002274static void ctx_set_TLSv13_func(SSL_CTX *ctx, set_context_func c) {}
2275/* Unusable in this context. */
2276static void ssl_set_SSLv3_func(SSL *ssl, set_context_func c) {}
2277static void ssl_set_TLSv10_func(SSL *ssl, set_context_func c) {}
2278static void ssl_set_TLSv11_func(SSL *ssl, set_context_func c) {}
2279static void ssl_set_TLSv12_func(SSL *ssl, set_context_func c) {}
2280static void ssl_set_TLSv13_func(SSL *ssl, set_context_func c) {}
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002281#else /* openssl >= 1.1.0 */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002282typedef enum { SET_MIN, SET_MAX } set_context_func;
2283
2284static void ctx_set_SSLv3_func(SSL_CTX *ctx, set_context_func c) {
2285 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, SSL3_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002286 : SSL_CTX_set_min_proto_version(ctx, SSL3_VERSION);
2287}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002288static void ssl_set_SSLv3_func(SSL *ssl, set_context_func c) {
2289 c == SET_MAX ? SSL_set_max_proto_version(ssl, SSL3_VERSION)
2290 : SSL_set_min_proto_version(ssl, SSL3_VERSION);
2291}
2292static void ctx_set_TLSv10_func(SSL_CTX *ctx, set_context_func c) {
2293 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002294 : SSL_CTX_set_min_proto_version(ctx, TLS1_VERSION);
2295}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002296static void ssl_set_TLSv10_func(SSL *ssl, set_context_func c) {
2297 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_VERSION)
2298 : SSL_set_min_proto_version(ssl, TLS1_VERSION);
2299}
2300static void ctx_set_TLSv11_func(SSL_CTX *ctx, set_context_func c) {
2301 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_1_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002302 : SSL_CTX_set_min_proto_version(ctx, TLS1_1_VERSION);
2303}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002304static void ssl_set_TLSv11_func(SSL *ssl, set_context_func c) {
2305 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_1_VERSION)
2306 : SSL_set_min_proto_version(ssl, TLS1_1_VERSION);
2307}
2308static void ctx_set_TLSv12_func(SSL_CTX *ctx, set_context_func c) {
2309 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_2_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002310 : SSL_CTX_set_min_proto_version(ctx, TLS1_2_VERSION);
2311}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002312static void ssl_set_TLSv12_func(SSL *ssl, set_context_func c) {
2313 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_2_VERSION)
2314 : SSL_set_min_proto_version(ssl, TLS1_2_VERSION);
2315}
2316static void ctx_set_TLSv13_func(SSL_CTX *ctx, set_context_func c) {
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002317#if SSL_OP_NO_TLSv1_3
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002318 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_3_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002319 : SSL_CTX_set_min_proto_version(ctx, TLS1_3_VERSION);
2320#endif
2321}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002322static void ssl_set_TLSv13_func(SSL *ssl, set_context_func c) {
2323#if SSL_OP_NO_TLSv1_3
2324 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_3_VERSION)
2325 : SSL_set_min_proto_version(ssl, TLS1_3_VERSION);
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002326#endif
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002327}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002328#endif
2329static void ctx_set_None_func(SSL_CTX *ctx, set_context_func c) { }
2330static void ssl_set_None_func(SSL *ssl, set_context_func c) { }
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002331
2332static struct {
2333 int option;
2334 uint16_t flag;
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002335 void (*ctx_set_version)(SSL_CTX *, set_context_func);
2336 void (*ssl_set_version)(SSL *, set_context_func);
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002337 const char *name;
2338} methodVersions[] = {
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002339 {0, 0, ctx_set_None_func, ssl_set_None_func, "NONE"}, /* CONF_TLSV_NONE */
2340 {SSL_OP_NO_SSLv3, MC_SSL_O_NO_SSLV3, ctx_set_SSLv3_func, ssl_set_SSLv3_func, "SSLv3"}, /* CONF_SSLV3 */
2341 {SSL_OP_NO_TLSv1, MC_SSL_O_NO_TLSV10, ctx_set_TLSv10_func, ssl_set_TLSv10_func, "TLSv1.0"}, /* CONF_TLSV10 */
2342 {SSL_OP_NO_TLSv1_1, MC_SSL_O_NO_TLSV11, ctx_set_TLSv11_func, ssl_set_TLSv11_func, "TLSv1.1"}, /* CONF_TLSV11 */
2343 {SSL_OP_NO_TLSv1_2, MC_SSL_O_NO_TLSV12, ctx_set_TLSv12_func, ssl_set_TLSv12_func, "TLSv1.2"}, /* CONF_TLSV12 */
2344 {SSL_OP_NO_TLSv1_3, MC_SSL_O_NO_TLSV13, ctx_set_TLSv13_func, ssl_set_TLSv13_func, "TLSv1.3"}, /* CONF_TLSV13 */
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002345};
2346
Emmanuel Hocdet530141f2017-03-01 18:54:56 +01002347static void ssl_sock_switchctx_set(SSL *ssl, SSL_CTX *ctx)
2348{
2349 SSL_set_verify(ssl, SSL_CTX_get_verify_mode(ctx), ssl_sock_bind_verifycbk);
2350 SSL_set_client_CA_list(ssl, SSL_dup_CA_list(SSL_CTX_get_client_CA_list(ctx)));
2351 SSL_set_SSL_CTX(ssl, ctx);
2352}
2353
Willy Tarreau5db847a2019-05-09 14:13:35 +02002354#if ((HA_OPENSSL_VERSION_NUMBER >= 0x10101000L) || defined(OPENSSL_IS_BORINGSSL))
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002355
2356static int ssl_sock_switchctx_err_cbk(SSL *ssl, int *al, void *priv)
2357{
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002358 struct bind_conf *s = priv;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002359 (void)al; /* shut gcc stupid warning */
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002360
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002361 if (SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name) || s->generate_certs)
2362 return SSL_TLSEXT_ERR_OK;
2363 return SSL_TLSEXT_ERR_NOACK;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002364}
2365
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002366#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002367static int ssl_sock_switchctx_cbk(const struct ssl_early_callback_ctx *ctx)
2368{
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002369 SSL *ssl = ctx->ssl;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002370#else
2371static int ssl_sock_switchctx_cbk(SSL *ssl, int *al, void *arg)
2372{
2373#endif
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002374 struct connection *conn;
2375 struct bind_conf *s;
2376 const uint8_t *extension_data;
2377 size_t extension_len;
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002378 int has_rsa_sig = 0, has_ecdsa_sig = 0;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002379
2380 char *wildp = NULL;
2381 const uint8_t *servername;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002382 size_t servername_len;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002383 struct ebmb_node *node, *n, *node_ecdsa = NULL, *node_rsa = NULL, *node_anonymous = NULL;
Olivier Houchardc2aae742017-09-22 18:26:28 +02002384 int allow_early = 0;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002385 int i;
2386
Thierry FOURNIER28962c92018-06-17 21:37:05 +02002387 conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Willy Tarreaua8825522018-10-15 13:20:07 +02002388 s = __objt_listener(conn->target)->bind_conf;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002389
Olivier Houchard9679ac92017-10-27 14:58:08 +02002390 if (s->ssl_conf.early_data)
Olivier Houchardc2aae742017-09-22 18:26:28 +02002391 allow_early = 1;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002392#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002393 if (SSL_early_callback_ctx_extension_get(ctx, TLSEXT_TYPE_server_name,
2394 &extension_data, &extension_len)) {
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002395#else
2396 if (SSL_client_hello_get0_ext(ssl, TLSEXT_TYPE_server_name, &extension_data, &extension_len)) {
2397#endif
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002398 /*
2399 * The server_name extension was given too much extensibility when it
2400 * was written, so parsing the normal case is a bit complex.
2401 */
2402 size_t len;
2403 if (extension_len <= 2)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002404 goto abort;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002405 /* Extract the length of the supplied list of names. */
2406 len = (*extension_data++) << 8;
2407 len |= *extension_data++;
2408 if (len + 2 != extension_len)
2409 goto abort;
2410 /*
2411 * The list in practice only has a single element, so we only consider
2412 * the first one.
2413 */
2414 if (len == 0 || *extension_data++ != TLSEXT_NAMETYPE_host_name)
2415 goto abort;
2416 extension_len = len - 1;
2417 /* Now we can finally pull out the byte array with the actual hostname. */
2418 if (extension_len <= 2)
2419 goto abort;
2420 len = (*extension_data++) << 8;
2421 len |= *extension_data++;
2422 if (len == 0 || len + 2 > extension_len || len > TLSEXT_MAXLEN_host_name
2423 || memchr(extension_data, 0, len) != NULL)
2424 goto abort;
2425 servername = extension_data;
2426 servername_len = len;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002427 } else {
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002428#if (!defined SSL_NO_GENERATE_CERTIFICATES)
2429 if (s->generate_certs && ssl_sock_generate_certificate_from_conn(s, ssl)) {
Olivier Houchardc2aae742017-09-22 18:26:28 +02002430 goto allow_early;
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002431 }
2432#endif
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002433 /* without SNI extension, is the default_ctx (need SSL_TLSEXT_ERR_NOACK) */
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002434 if (!s->strict_sni) {
William Lallemand21724f02019-11-04 17:56:13 +01002435 HA_RWLOCK_RDLOCK(SNI_LOCK, &s->sni_lock);
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002436 ssl_sock_switchctx_set(ssl, s->default_ctx);
William Lallemand21724f02019-11-04 17:56:13 +01002437 HA_RWLOCK_RDUNLOCK(SNI_LOCK, &s->sni_lock);
Olivier Houchardc2aae742017-09-22 18:26:28 +02002438 goto allow_early;
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002439 }
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002440 goto abort;
2441 }
2442
2443 /* extract/check clientHello informations */
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002444#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002445 if (SSL_early_callback_ctx_extension_get(ctx, TLSEXT_TYPE_signature_algorithms, &extension_data, &extension_len)) {
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002446#else
2447 if (SSL_client_hello_get0_ext(ssl, TLSEXT_TYPE_signature_algorithms, &extension_data, &extension_len)) {
2448#endif
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002449 uint8_t sign;
2450 size_t len;
2451 if (extension_len < 2)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002452 goto abort;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002453 len = (*extension_data++) << 8;
2454 len |= *extension_data++;
2455 if (len + 2 != extension_len)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002456 goto abort;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002457 if (len % 2 != 0)
2458 goto abort;
2459 for (; len > 0; len -= 2) {
2460 extension_data++; /* hash */
2461 sign = *extension_data++;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002462 switch (sign) {
2463 case TLSEXT_signature_rsa:
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002464 has_rsa_sig = 1;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002465 break;
2466 case TLSEXT_signature_ecdsa:
2467 has_ecdsa_sig = 1;
2468 break;
2469 default:
2470 continue;
2471 }
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002472 if (has_ecdsa_sig && has_rsa_sig)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002473 break;
2474 }
2475 } else {
Bertrand Jacquina25282b2018-08-14 00:56:13 +01002476 /* without TLSEXT_TYPE_signature_algorithms extension (< TLSv1.2) */
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002477 has_rsa_sig = 1;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002478 }
2479 if (has_ecdsa_sig) { /* in very rare case: has ecdsa sign but not a ECDSA cipher */
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002480 const SSL_CIPHER *cipher;
2481 size_t len;
2482 const uint8_t *cipher_suites;
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002483 has_ecdsa_sig = 0;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002484#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002485 len = ctx->cipher_suites_len;
2486 cipher_suites = ctx->cipher_suites;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002487#else
2488 len = SSL_client_hello_get0_ciphers(ssl, &cipher_suites);
2489#endif
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002490 if (len % 2 != 0)
2491 goto abort;
2492 for (; len != 0; len -= 2, cipher_suites += 2) {
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002493#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002494 uint16_t cipher_suite = (cipher_suites[0] << 8) | cipher_suites[1];
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002495 cipher = SSL_get_cipher_by_value(cipher_suite);
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002496#else
2497 cipher = SSL_CIPHER_find(ssl, cipher_suites);
2498#endif
Emmanuel Hocdet019f9b12017-10-02 17:12:06 +02002499 if (cipher && SSL_CIPHER_get_auth_nid(cipher) == NID_auth_ecdsa) {
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002500 has_ecdsa_sig = 1;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002501 break;
2502 }
2503 }
2504 }
2505
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002506 for (i = 0; i < trash.size && i < servername_len; i++) {
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002507 trash.area[i] = tolower(servername[i]);
2508 if (!wildp && (trash.area[i] == '.'))
2509 wildp = &trash.area[i];
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002510 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002511 trash.area[i] = 0;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002512
William Lallemand150bfa82019-09-19 17:12:49 +02002513 HA_RWLOCK_RDLOCK(SNI_LOCK, &s->sni_lock);
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002514
Emmanuel Hocdet3777e3a2019-11-06 16:05:34 +01002515 for (i = 0; i < 2; i++) {
2516 if (i == 0) /* lookup in full qualified names */
2517 node = ebst_lookup(&s->sni_ctx, trash.area);
2518 else if (i == 1 && wildp) /* lookup in wildcards names */
2519 node = ebst_lookup(&s->sni_w_ctx, wildp);
2520 else
2521 break;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002522 for (n = node; n; n = ebmb_next_dup(n)) {
Emmanuel Hocdet3777e3a2019-11-06 16:05:34 +01002523 /* lookup a not neg filter */
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002524 if (!container_of(n, struct sni_ctx, name)->neg) {
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002525 switch(container_of(n, struct sni_ctx, name)->kinfo.sig) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002526 case TLSEXT_signature_ecdsa:
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002527 if (!node_ecdsa)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002528 node_ecdsa = n;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002529 break;
2530 case TLSEXT_signature_rsa:
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002531 if (!node_rsa)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002532 node_rsa = n;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002533 break;
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002534 default: /* TLSEXT_signature_anonymous|dsa */
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002535 if (!node_anonymous)
2536 node_anonymous = n;
2537 break;
2538 }
2539 }
2540 }
Emmanuel Hocdet3777e3a2019-11-06 16:05:34 +01002541 /* select by key_signature priority order */
2542 node = (has_ecdsa_sig && node_ecdsa) ? node_ecdsa
2543 : ((has_rsa_sig && node_rsa) ? node_rsa
2544 : (node_anonymous ? node_anonymous
2545 : (node_ecdsa ? node_ecdsa /* no ecdsa signature case (< TLSv1.2) */
2546 : node_rsa /* no rsa signature case (far far away) */
2547 )));
2548 if (node) {
2549 /* switch ctx */
2550 struct ssl_bind_conf *conf = container_of(node, struct sni_ctx, name)->conf;
2551 ssl_sock_switchctx_set(ssl, container_of(node, struct sni_ctx, name)->ctx);
Olivier Houchard35a63cc2017-11-02 19:04:38 +01002552 if (conf) {
2553 methodVersions[conf->ssl_methods.min].ssl_set_version(ssl, SET_MIN);
2554 methodVersions[conf->ssl_methods.max].ssl_set_version(ssl, SET_MAX);
2555 if (conf->early_data)
2556 allow_early = 1;
2557 }
William Lallemand02010472019-10-18 11:02:19 +02002558 HA_RWLOCK_RDUNLOCK(SNI_LOCK, &s->sni_lock);
Olivier Houchard35a63cc2017-11-02 19:04:38 +01002559 goto allow_early;
Emmanuel Hocdet3777e3a2019-11-06 16:05:34 +01002560 }
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002561 }
William Lallemand150bfa82019-09-19 17:12:49 +02002562
William Lallemand02010472019-10-18 11:02:19 +02002563 HA_RWLOCK_RDUNLOCK(SNI_LOCK, &s->sni_lock);
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002564#if (!defined SSL_NO_GENERATE_CERTIFICATES)
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002565 if (s->generate_certs && ssl_sock_generate_certificate(trash.area, s, ssl)) {
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002566 /* switch ctx done in ssl_sock_generate_certificate */
Olivier Houchardc2aae742017-09-22 18:26:28 +02002567 goto allow_early;
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002568 }
2569#endif
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002570 if (!s->strict_sni) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002571 /* no certificate match, is the default_ctx */
William Lallemand21724f02019-11-04 17:56:13 +01002572 HA_RWLOCK_RDLOCK(SNI_LOCK, &s->sni_lock);
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002573 ssl_sock_switchctx_set(ssl, s->default_ctx);
William Lallemand21724f02019-11-04 17:56:13 +01002574 HA_RWLOCK_RDUNLOCK(SNI_LOCK, &s->sni_lock);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002575 }
Olivier Houchardc2aae742017-09-22 18:26:28 +02002576allow_early:
2577#ifdef OPENSSL_IS_BORINGSSL
2578 if (allow_early)
2579 SSL_set_early_data_enabled(ssl, 1);
2580#else
2581 if (!allow_early)
2582 SSL_set_max_early_data(ssl, 0);
2583#endif
2584 return 1;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002585 abort:
2586 /* abort handshake (was SSL_TLSEXT_ERR_ALERT_FATAL) */
2587 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002588#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002589 return ssl_select_cert_error;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002590#else
2591 *al = SSL_AD_UNRECOGNIZED_NAME;
2592 return 0;
2593#endif
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002594}
2595
2596#else /* OPENSSL_IS_BORINGSSL */
2597
Emeric Brunfc0421f2012-09-07 17:30:07 +02002598/* Sets the SSL ctx of <ssl> to match the advertised server name. Returns a
2599 * warning when no match is found, which implies the default (first) cert
2600 * will keep being used.
2601 */
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002602static int ssl_sock_switchctx_cbk(SSL *ssl, int *al, void *priv)
Emeric Brunfc0421f2012-09-07 17:30:07 +02002603{
2604 const char *servername;
2605 const char *wildp = NULL;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002606 struct ebmb_node *node, *n;
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002607 struct bind_conf *s = priv;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002608 int i;
2609 (void)al; /* shut gcc stupid warning */
2610
2611 servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
Emmanuel Hocdet65623372013-01-24 17:17:15 +01002612 if (!servername) {
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002613#if (!defined SSL_NO_GENERATE_CERTIFICATES)
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002614 if (s->generate_certs && ssl_sock_generate_certificate_from_conn(s, ssl))
2615 return SSL_TLSEXT_ERR_OK;
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002616#endif
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002617 if (s->strict_sni)
2618 return SSL_TLSEXT_ERR_ALERT_FATAL;
William Lallemand21724f02019-11-04 17:56:13 +01002619 HA_RWLOCK_RDLOCK(SNI_LOCK, &s->sni_lock);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002620 ssl_sock_switchctx_set(ssl, s->default_ctx);
William Lallemand21724f02019-11-04 17:56:13 +01002621 HA_RWLOCK_RDUNLOCK(SNI_LOCK, &s->sni_lock);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002622 return SSL_TLSEXT_ERR_NOACK;
Emmanuel Hocdet65623372013-01-24 17:17:15 +01002623 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02002624
Willy Tarreau19d14ef2012-10-29 16:51:55 +01002625 for (i = 0; i < trash.size; i++) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02002626 if (!servername[i])
2627 break;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002628 trash.area[i] = tolower(servername[i]);
2629 if (!wildp && (trash.area[i] == '.'))
2630 wildp = &trash.area[i];
Emeric Brunfc0421f2012-09-07 17:30:07 +02002631 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002632 trash.area[i] = 0;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002633
William Lallemand150bfa82019-09-19 17:12:49 +02002634 HA_RWLOCK_RDLOCK(SNI_LOCK, &s->sni_lock);
Emmanuel Hocdetc5fdf0f2019-11-04 15:49:46 +01002635 node = NULL;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002636 /* lookup in full qualified names */
Emmanuel Hocdetc5fdf0f2019-11-04 15:49:46 +01002637 for (n = ebst_lookup(&s->sni_ctx, trash.area); n; n = ebmb_next_dup(n)) {
2638 /* lookup a not neg filter */
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002639 if (!container_of(n, struct sni_ctx, name)->neg) {
2640 node = n;
2641 break;
Emmanuel Hocdet65623372013-01-24 17:17:15 +01002642 }
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002643 }
2644 if (!node && wildp) {
2645 /* lookup in wildcards names */
Emmanuel Hocdetc5fdf0f2019-11-04 15:49:46 +01002646 for (n = ebst_lookup(&s->sni_w_ctx, wildp); n; n = ebmb_next_dup(n)) {
2647 /* lookup a not neg filter */
2648 if (!container_of(n, struct sni_ctx, name)->neg) {
2649 node = n;
2650 break;
2651 }
2652 }
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002653 }
Emmanuel Hocdetc5fdf0f2019-11-04 15:49:46 +01002654 if (!node) {
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002655#if (!defined SSL_NO_GENERATE_CERTIFICATES)
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002656 if (s->generate_certs && ssl_sock_generate_certificate(servername, s, ssl)) {
2657 /* switch ctx done in ssl_sock_generate_certificate */
William Lallemand150bfa82019-09-19 17:12:49 +02002658 HA_RWLOCK_RDUNLOCK(SNI_LOCK, &s->sni_lock);
Christopher Faulet31af49d2015-06-09 17:29:50 +02002659 return SSL_TLSEXT_ERR_OK;
2660 }
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002661#endif
William Lallemand21724f02019-11-04 17:56:13 +01002662 if (s->strict_sni) {
2663 HA_RWLOCK_RDUNLOCK(SNI_LOCK, &s->sni_lock);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002664 return SSL_TLSEXT_ERR_ALERT_FATAL;
William Lallemand21724f02019-11-04 17:56:13 +01002665 }
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002666 ssl_sock_switchctx_set(ssl, s->default_ctx);
William Lallemand21724f02019-11-04 17:56:13 +01002667 HA_RWLOCK_RDUNLOCK(SNI_LOCK, &s->sni_lock);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002668 return SSL_TLSEXT_ERR_OK;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002669 }
2670
2671 /* switch ctx */
Emmanuel Hocdet530141f2017-03-01 18:54:56 +01002672 ssl_sock_switchctx_set(ssl, container_of(node, struct sni_ctx, name)->ctx);
William Lallemand150bfa82019-09-19 17:12:49 +02002673 HA_RWLOCK_RDUNLOCK(SNI_LOCK, &s->sni_lock);
Emeric Brunfc0421f2012-09-07 17:30:07 +02002674 return SSL_TLSEXT_ERR_OK;
2675}
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002676#endif /* (!) OPENSSL_IS_BORINGSSL */
Emeric Brunfc0421f2012-09-07 17:30:07 +02002677#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
2678
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002679#ifndef OPENSSL_NO_DH
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002680
2681static DH * ssl_get_dh_1024(void)
2682{
Remi Gacogned3a341a2015-05-29 16:26:17 +02002683 static unsigned char dh1024_p[]={
2684 0xFA,0xF9,0x2A,0x22,0x2A,0xA7,0x7F,0xE1,0x67,0x4E,0x53,0xF7,
2685 0x56,0x13,0xC3,0xB1,0xE3,0x29,0x6B,0x66,0x31,0x6A,0x7F,0xB3,
2686 0xC2,0x68,0x6B,0xCB,0x1D,0x57,0x39,0x1D,0x1F,0xFF,0x1C,0xC9,
2687 0xA6,0xA4,0x98,0x82,0x31,0x5D,0x25,0xFF,0x8A,0xE0,0x73,0x96,
2688 0x81,0xC8,0x83,0x79,0xC1,0x5A,0x04,0xF8,0x37,0x0D,0xA8,0x3D,
2689 0xAE,0x74,0xBC,0xDB,0xB6,0xA4,0x75,0xD9,0x71,0x8A,0xA0,0x17,
2690 0x9E,0x2D,0xC8,0xA8,0xDF,0x2C,0x5F,0x82,0x95,0xF8,0x92,0x9B,
2691 0xA7,0x33,0x5F,0x89,0x71,0xC8,0x2D,0x6B,0x18,0x86,0xC4,0x94,
2692 0x22,0xA5,0x52,0x8D,0xF6,0xF6,0xD2,0x37,0x92,0x0F,0xA5,0xCC,
2693 0xDB,0x7B,0x1D,0x3D,0xA1,0x31,0xB7,0x80,0x8F,0x0B,0x67,0x5E,
2694 0x36,0xA5,0x60,0x0C,0xF1,0x95,0x33,0x8B,
2695 };
2696 static unsigned char dh1024_g[]={
2697 0x02,
2698 };
2699
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002700 BIGNUM *p;
2701 BIGNUM *g;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002702 DH *dh = DH_new();
2703 if (dh) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002704 p = BN_bin2bn(dh1024_p, sizeof dh1024_p, NULL);
2705 g = BN_bin2bn(dh1024_g, sizeof dh1024_g, NULL);
Remi Gacogned3a341a2015-05-29 16:26:17 +02002706
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002707 if (!p || !g) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002708 DH_free(dh);
2709 dh = NULL;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002710 } else {
2711 DH_set0_pqg(dh, p, NULL, g);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002712 }
2713 }
2714 return dh;
2715}
2716
2717static DH *ssl_get_dh_2048(void)
2718{
Remi Gacogned3a341a2015-05-29 16:26:17 +02002719 static unsigned char dh2048_p[]={
2720 0xEC,0x86,0xF8,0x70,0xA0,0x33,0x16,0xEC,0x05,0x1A,0x73,0x59,
2721 0xCD,0x1F,0x8B,0xF8,0x29,0xE4,0xD2,0xCF,0x52,0xDD,0xC2,0x24,
2722 0x8D,0xB5,0x38,0x9A,0xFB,0x5C,0xA4,0xE4,0xB2,0xDA,0xCE,0x66,
2723 0x50,0x74,0xA6,0x85,0x4D,0x4B,0x1D,0x30,0xB8,0x2B,0xF3,0x10,
2724 0xE9,0xA7,0x2D,0x05,0x71,0xE7,0x81,0xDF,0x8B,0x59,0x52,0x3B,
2725 0x5F,0x43,0x0B,0x68,0xF1,0xDB,0x07,0xBE,0x08,0x6B,0x1B,0x23,
2726 0xEE,0x4D,0xCC,0x9E,0x0E,0x43,0xA0,0x1E,0xDF,0x43,0x8C,0xEC,
2727 0xBE,0xBE,0x90,0xB4,0x51,0x54,0xB9,0x2F,0x7B,0x64,0x76,0x4E,
2728 0x5D,0xD4,0x2E,0xAE,0xC2,0x9E,0xAE,0x51,0x43,0x59,0xC7,0x77,
2729 0x9C,0x50,0x3C,0x0E,0xED,0x73,0x04,0x5F,0xF1,0x4C,0x76,0x2A,
2730 0xD8,0xF8,0xCF,0xFC,0x34,0x40,0xD1,0xB4,0x42,0x61,0x84,0x66,
2731 0x42,0x39,0x04,0xF8,0x68,0xB2,0x62,0xD7,0x55,0xED,0x1B,0x74,
2732 0x75,0x91,0xE0,0xC5,0x69,0xC1,0x31,0x5C,0xDB,0x7B,0x44,0x2E,
2733 0xCE,0x84,0x58,0x0D,0x1E,0x66,0x0C,0xC8,0x44,0x9E,0xFD,0x40,
2734 0x08,0x67,0x5D,0xFB,0xA7,0x76,0x8F,0x00,0x11,0x87,0xE9,0x93,
2735 0xF9,0x7D,0xC4,0xBC,0x74,0x55,0x20,0xD4,0x4A,0x41,0x2F,0x43,
2736 0x42,0x1A,0xC1,0xF2,0x97,0x17,0x49,0x27,0x37,0x6B,0x2F,0x88,
2737 0x7E,0x1C,0xA0,0xA1,0x89,0x92,0x27,0xD9,0x56,0x5A,0x71,0xC1,
2738 0x56,0x37,0x7E,0x3A,0x9D,0x05,0xE7,0xEE,0x5D,0x8F,0x82,0x17,
2739 0xBC,0xE9,0xC2,0x93,0x30,0x82,0xF9,0xF4,0xC9,0xAE,0x49,0xDB,
2740 0xD0,0x54,0xB4,0xD9,0x75,0x4D,0xFA,0x06,0xB8,0xD6,0x38,0x41,
2741 0xB7,0x1F,0x77,0xF3,
2742 };
2743 static unsigned char dh2048_g[]={
2744 0x02,
2745 };
2746
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002747 BIGNUM *p;
2748 BIGNUM *g;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002749 DH *dh = DH_new();
2750 if (dh) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002751 p = BN_bin2bn(dh2048_p, sizeof dh2048_p, NULL);
2752 g = BN_bin2bn(dh2048_g, sizeof dh2048_g, NULL);
Remi Gacogned3a341a2015-05-29 16:26:17 +02002753
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002754 if (!p || !g) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002755 DH_free(dh);
2756 dh = NULL;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002757 } else {
2758 DH_set0_pqg(dh, p, NULL, g);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002759 }
2760 }
2761 return dh;
2762}
2763
2764static DH *ssl_get_dh_4096(void)
2765{
Remi Gacogned3a341a2015-05-29 16:26:17 +02002766 static unsigned char dh4096_p[]={
2767 0xDE,0x16,0x94,0xCD,0x99,0x58,0x07,0xF1,0xF7,0x32,0x96,0x11,
2768 0x04,0x82,0xD4,0x84,0x72,0x80,0x99,0x06,0xCA,0xF0,0xA3,0x68,
2769 0x07,0xCE,0x64,0x50,0xE7,0x74,0x45,0x20,0x80,0x5E,0x4D,0xAD,
2770 0xA5,0xB6,0xED,0xFA,0x80,0x6C,0x3B,0x35,0xC4,0x9A,0x14,0x6B,
2771 0x32,0xBB,0xFD,0x1F,0x17,0x8E,0xB7,0x1F,0xD6,0xFA,0x3F,0x7B,
2772 0xEE,0x16,0xA5,0x62,0x33,0x0D,0xED,0xBC,0x4E,0x58,0xE5,0x47,
2773 0x4D,0xE9,0xAB,0x8E,0x38,0xD3,0x6E,0x90,0x57,0xE3,0x22,0x15,
2774 0x33,0xBD,0xF6,0x43,0x45,0xB5,0x10,0x0A,0xBE,0x2C,0xB4,0x35,
2775 0xB8,0x53,0x8D,0xAD,0xFB,0xA7,0x1F,0x85,0x58,0x41,0x7A,0x79,
2776 0x20,0x68,0xB3,0xE1,0x3D,0x08,0x76,0xBF,0x86,0x0D,0x49,0xE3,
2777 0x82,0x71,0x8C,0xB4,0x8D,0x81,0x84,0xD4,0xE7,0xBE,0x91,0xDC,
2778 0x26,0x39,0x48,0x0F,0x35,0xC4,0xCA,0x65,0xE3,0x40,0x93,0x52,
2779 0x76,0x58,0x7D,0xDD,0x51,0x75,0xDC,0x69,0x61,0xBF,0x47,0x2C,
2780 0x16,0x68,0x2D,0xC9,0x29,0xD3,0xE6,0xC0,0x99,0x48,0xA0,0x9A,
2781 0xC8,0x78,0xC0,0x6D,0x81,0x67,0x12,0x61,0x3F,0x71,0xBA,0x41,
2782 0x1F,0x6C,0x89,0x44,0x03,0xBA,0x3B,0x39,0x60,0xAA,0x28,0x55,
2783 0x59,0xAE,0xB8,0xFA,0xCB,0x6F,0xA5,0x1A,0xF7,0x2B,0xDD,0x52,
2784 0x8A,0x8B,0xE2,0x71,0xA6,0x5E,0x7E,0xD8,0x2E,0x18,0xE0,0x66,
2785 0xDF,0xDD,0x22,0x21,0x99,0x52,0x73,0xA6,0x33,0x20,0x65,0x0E,
2786 0x53,0xE7,0x6B,0x9B,0xC5,0xA3,0x2F,0x97,0x65,0x76,0xD3,0x47,
2787 0x23,0x77,0x12,0xB6,0x11,0x7B,0x24,0xED,0xF1,0xEF,0xC0,0xE2,
2788 0xA3,0x7E,0x67,0x05,0x3E,0x96,0x4D,0x45,0xC2,0x18,0xD1,0x73,
2789 0x9E,0x07,0xF3,0x81,0x6E,0x52,0x63,0xF6,0x20,0x76,0xB9,0x13,
2790 0xD2,0x65,0x30,0x18,0x16,0x09,0x16,0x9E,0x8F,0xF1,0xD2,0x10,
2791 0x5A,0xD3,0xD4,0xAF,0x16,0x61,0xDA,0x55,0x2E,0x18,0x5E,0x14,
2792 0x08,0x54,0x2E,0x2A,0x25,0xA2,0x1A,0x9B,0x8B,0x32,0xA9,0xFD,
2793 0xC2,0x48,0x96,0xE1,0x80,0xCA,0xE9,0x22,0x17,0xBB,0xCE,0x3E,
2794 0x9E,0xED,0xC7,0xF1,0x1F,0xEC,0x17,0x21,0xDC,0x7B,0x82,0x48,
2795 0x8E,0xBB,0x4B,0x9D,0x5B,0x04,0x04,0xDA,0xDB,0x39,0xDF,0x01,
2796 0x40,0xC3,0xAA,0x26,0x23,0x89,0x75,0xC6,0x0B,0xD0,0xA2,0x60,
2797 0x6A,0xF1,0xCC,0x65,0x18,0x98,0x1B,0x52,0xD2,0x74,0x61,0xCC,
2798 0xBD,0x60,0xAE,0xA3,0xA0,0x66,0x6A,0x16,0x34,0x92,0x3F,0x41,
2799 0x40,0x31,0x29,0xC0,0x2C,0x63,0xB2,0x07,0x8D,0xEB,0x94,0xB8,
2800 0xE8,0x47,0x92,0x52,0x93,0x6A,0x1B,0x7E,0x1A,0x61,0xB3,0x1B,
2801 0xF0,0xD6,0x72,0x9B,0xF1,0xB0,0xAF,0xBF,0x3E,0x65,0xEF,0x23,
2802 0x1D,0x6F,0xFF,0x70,0xCD,0x8A,0x4C,0x8A,0xA0,0x72,0x9D,0xBE,
2803 0xD4,0xBB,0x24,0x47,0x4A,0x68,0xB5,0xF5,0xC6,0xD5,0x7A,0xCD,
2804 0xCA,0x06,0x41,0x07,0xAD,0xC2,0x1E,0xE6,0x54,0xA7,0xAD,0x03,
2805 0xD9,0x12,0xC1,0x9C,0x13,0xB1,0xC9,0x0A,0x43,0x8E,0x1E,0x08,
2806 0xCE,0x50,0x82,0x73,0x5F,0xA7,0x55,0x1D,0xD9,0x59,0xAC,0xB5,
2807 0xEA,0x02,0x7F,0x6C,0x5B,0x74,0x96,0x98,0x67,0x24,0xA3,0x0F,
2808 0x15,0xFC,0xA9,0x7D,0x3E,0x67,0xD1,0x70,0xF8,0x97,0xF3,0x67,
2809 0xC5,0x8C,0x88,0x44,0x08,0x02,0xC7,0x2B,
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002810 };
Remi Gacogned3a341a2015-05-29 16:26:17 +02002811 static unsigned char dh4096_g[]={
2812 0x02,
2813 };
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002814
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002815 BIGNUM *p;
2816 BIGNUM *g;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002817 DH *dh = DH_new();
2818 if (dh) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002819 p = BN_bin2bn(dh4096_p, sizeof dh4096_p, NULL);
2820 g = BN_bin2bn(dh4096_g, sizeof dh4096_g, NULL);
Remi Gacogned3a341a2015-05-29 16:26:17 +02002821
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002822 if (!p || !g) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002823 DH_free(dh);
2824 dh = NULL;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002825 } else {
2826 DH_set0_pqg(dh, p, NULL, g);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002827 }
2828 }
2829 return dh;
2830}
2831
2832/* Returns Diffie-Hellman parameters matching the private key length
Willy Tarreauef934602016-12-22 23:12:01 +01002833 but not exceeding global_ssl.default_dh_param */
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002834static DH *ssl_get_tmp_dh(SSL *ssl, int export, int keylen)
2835{
2836 DH *dh = NULL;
2837 EVP_PKEY *pkey = SSL_get_privatekey(ssl);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002838 int type;
2839
2840 type = pkey ? EVP_PKEY_base_id(pkey) : EVP_PKEY_NONE;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002841
2842 /* The keylen supplied by OpenSSL can only be 512 or 1024.
2843 See ssl3_send_server_key_exchange() in ssl/s3_srvr.c
2844 */
2845 if (type == EVP_PKEY_RSA || type == EVP_PKEY_DSA) {
2846 keylen = EVP_PKEY_bits(pkey);
2847 }
2848
Willy Tarreauef934602016-12-22 23:12:01 +01002849 if (keylen > global_ssl.default_dh_param) {
2850 keylen = global_ssl.default_dh_param;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002851 }
2852
Remi Gacogned3a341a2015-05-29 16:26:17 +02002853 if (keylen >= 4096) {
Remi Gacogne8de54152014-07-15 11:36:40 +02002854 dh = local_dh_4096;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002855 }
2856 else if (keylen >= 2048) {
Remi Gacogne8de54152014-07-15 11:36:40 +02002857 dh = local_dh_2048;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002858 }
2859 else {
Remi Gacogne8de54152014-07-15 11:36:40 +02002860 dh = local_dh_1024;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002861 }
2862
2863 return dh;
2864}
2865
Remi Gacogne47783ef2015-05-29 15:53:22 +02002866static DH * ssl_sock_get_dh_from_file(const char *filename)
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002867{
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002868 DH *dh = NULL;
Remi Gacogne47783ef2015-05-29 15:53:22 +02002869 BIO *in = BIO_new(BIO_s_file());
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002870
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002871 if (in == NULL)
2872 goto end;
2873
Remi Gacogne47783ef2015-05-29 15:53:22 +02002874 if (BIO_read_filename(in, filename) <= 0)
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002875 goto end;
2876
Remi Gacogne47783ef2015-05-29 15:53:22 +02002877 dh = PEM_read_bio_DHparams(in, NULL, NULL, NULL);
2878
2879end:
2880 if (in)
2881 BIO_free(in);
2882
Emeric Brune1b4ed42018-08-16 15:14:12 +02002883 ERR_clear_error();
2884
Remi Gacogne47783ef2015-05-29 15:53:22 +02002885 return dh;
2886}
2887
2888int ssl_sock_load_global_dh_param_from_file(const char *filename)
2889{
2890 global_dh = ssl_sock_get_dh_from_file(filename);
2891
2892 if (global_dh) {
2893 return 0;
2894 }
2895
2896 return -1;
2897}
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002898#endif
2899
William Lallemand9117de92019-10-04 00:29:42 +02002900/* Alloc and init a ckch_inst */
2901static struct ckch_inst *ckch_inst_new()
2902{
2903 struct ckch_inst *ckch_inst;
2904
2905 ckch_inst = calloc(1, sizeof *ckch_inst);
2906 if (ckch_inst)
2907 LIST_INIT(&ckch_inst->sni_ctx);
2908
2909 return ckch_inst;
2910}
2911
2912
2913/* This function allocates a sni_ctx and adds it to the ckch_inst */
William Lallemand1d29c742019-10-04 00:53:29 +02002914static int ckch_inst_add_cert_sni(SSL_CTX *ctx, struct ckch_inst *ckch_inst,
William Lallemand9117de92019-10-04 00:29:42 +02002915 struct bind_conf *s, struct ssl_bind_conf *conf,
2916 struct pkey_info kinfo, char *name, int order)
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002917{
2918 struct sni_ctx *sc;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002919 int wild = 0, neg = 0;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002920
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002921 if (*name == '!') {
2922 neg = 1;
2923 name++;
2924 }
2925 if (*name == '*') {
2926 wild = 1;
2927 name++;
2928 }
2929 /* !* filter is a nop */
2930 if (neg && wild)
2931 return order;
2932 if (*name) {
2933 int j, len;
2934 len = strlen(name);
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002935 for (j = 0; j < len && j < trash.size; j++)
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002936 trash.area[j] = tolower(name[j]);
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002937 if (j >= trash.size)
William Lallemandfe49bb32019-10-03 23:46:33 +02002938 return -1;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002939 trash.area[j] = 0;
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002940
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002941 sc = malloc(sizeof(struct sni_ctx) + len + 1);
Thierry FOURNIER / OZON.IO7a3bd3b2016-10-06 10:35:29 +02002942 if (!sc)
William Lallemandfe49bb32019-10-03 23:46:33 +02002943 return -1;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002944 memcpy(sc->name.key, trash.area, len + 1);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002945 sc->ctx = ctx;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01002946 sc->conf = conf;
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002947 sc->kinfo = kinfo;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002948 sc->order = order++;
2949 sc->neg = neg;
William Lallemand1d29c742019-10-04 00:53:29 +02002950 sc->wild = wild;
2951 sc->name.node.leaf_p = NULL;
William Lallemand1d29c742019-10-04 00:53:29 +02002952 LIST_ADDQ(&ckch_inst->sni_ctx, &sc->by_ckch_inst);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002953 }
2954 return order;
2955}
2956
William Lallemand6af03992019-07-23 15:00:54 +02002957/*
William Lallemand1d29c742019-10-04 00:53:29 +02002958 * Insert the sni_ctxs that are listed in the ckch_inst, in the bind_conf's sni_ctx tree
2959 * This function can't return an error.
2960 *
2961 * *CAUTION*: The caller must lock the sni tree if called in multithreading mode
2962 */
2963static void ssl_sock_load_cert_sni(struct ckch_inst *ckch_inst, struct bind_conf *bind_conf)
2964{
2965
2966 struct sni_ctx *sc0, *sc0b, *sc1;
2967 struct ebmb_node *node;
William Lallemand21724f02019-11-04 17:56:13 +01002968 int def = 0;
William Lallemand1d29c742019-10-04 00:53:29 +02002969
2970 list_for_each_entry_safe(sc0, sc0b, &ckch_inst->sni_ctx, by_ckch_inst) {
2971
2972 /* ignore if sc0 was already inserted in a tree */
2973 if (sc0->name.node.leaf_p)
2974 continue;
2975
2976 /* Check for duplicates. */
2977 if (sc0->wild)
2978 node = ebst_lookup(&bind_conf->sni_w_ctx, (char *)sc0->name.key);
2979 else
2980 node = ebst_lookup(&bind_conf->sni_ctx, (char *)sc0->name.key);
2981
2982 for (; node; node = ebmb_next_dup(node)) {
2983 sc1 = ebmb_entry(node, struct sni_ctx, name);
2984 if (sc1->ctx == sc0->ctx && sc1->conf == sc0->conf
2985 && sc1->neg == sc0->neg && sc1->wild == sc0->wild) {
2986 /* it's a duplicate, we should remove and free it */
2987 LIST_DEL(&sc0->by_ckch_inst);
2988 free(sc0);
2989 sc0 = NULL;
William Lallemande15029b2019-10-14 10:46:58 +02002990 break;
William Lallemand1d29c742019-10-04 00:53:29 +02002991 }
2992 }
2993
2994 /* if duplicate, ignore the insertion */
2995 if (!sc0)
2996 continue;
2997
2998 if (sc0->wild)
2999 ebst_insert(&bind_conf->sni_w_ctx, &sc0->name);
3000 else
3001 ebst_insert(&bind_conf->sni_ctx, &sc0->name);
William Lallemand21724f02019-11-04 17:56:13 +01003002
3003 /* replace the default_ctx if required with the first ctx */
3004 if (ckch_inst->is_default && !def) {
3005 /* we don't need to free the default_ctx because the refcount was not incremented */
3006 bind_conf->default_ctx = sc0->ctx;
3007 def = 1;
3008 }
William Lallemand1d29c742019-10-04 00:53:29 +02003009 }
3010}
3011
3012/*
William Lallemande3af8fb2019-10-08 11:36:53 +02003013 * tree used to store the ckchs ordered by filename/bundle name
William Lallemand6af03992019-07-23 15:00:54 +02003014 */
William Lallemande3af8fb2019-10-08 11:36:53 +02003015struct eb_root ckchs_tree = EB_ROOT_UNIQUE;
William Lallemand6af03992019-07-23 15:00:54 +02003016
William Lallemandfa892222019-07-23 16:06:08 +02003017
Emeric Brun7a883362019-10-17 13:27:40 +02003018/* Loads Diffie-Hellman parameter from a ckchs to an SSL_CTX.
3019 * If there is no DH paramater availaible in the ckchs, the global
3020 * DH parameter is loaded into the SSL_CTX and if there is no
3021 * DH parameter available in ckchs nor in global, the default
3022 * DH parameters are applied on the SSL_CTX.
3023 * Returns a bitfield containing the flags:
3024 * ERR_FATAL in any fatal error case
3025 * ERR_ALERT if a reason of the error is availabine in err
3026 * ERR_WARN if a warning is available into err
3027 * The value 0 means there is no error nor warning and
3028 * the operation succeed.
3029 */
William Lallemandfa892222019-07-23 16:06:08 +02003030#ifndef OPENSSL_NO_DH
Emeric Brun7a883362019-10-17 13:27:40 +02003031static int ssl_sock_load_dh_params(SSL_CTX *ctx, const struct cert_key_and_chain *ckch,
3032 const char *path, char **err)
William Lallemandfa892222019-07-23 16:06:08 +02003033{
Emeric Brun7a883362019-10-17 13:27:40 +02003034 int ret = 0;
William Lallemandfa892222019-07-23 16:06:08 +02003035 DH *dh = NULL;
3036
William Lallemanda8c73742019-07-31 18:31:34 +02003037 if (ckch && ckch->dh) {
William Lallemandfa892222019-07-23 16:06:08 +02003038 dh = ckch->dh;
Emeric Bruna9363eb2019-10-17 14:53:03 +02003039 if (!SSL_CTX_set_tmp_dh(ctx, dh)) {
3040 memprintf(err, "%sunable to load the DH parameter specified in '%s'",
3041 err && *err ? *err : "", path);
3042#if defined(SSL_CTX_set_dh_auto)
3043 SSL_CTX_set_dh_auto(ctx, 1);
3044 memprintf(err, "%s, SSL library will use an automatically generated DH parameter.\n",
3045 err && *err ? *err : "");
3046#else
3047 memprintf(err, "%s, DH ciphers won't be available.\n",
3048 err && *err ? *err : "");
3049#endif
3050 ret |= ERR_WARN;
3051 goto end;
3052 }
William Lallemandfa892222019-07-23 16:06:08 +02003053
3054 if (ssl_dh_ptr_index >= 0) {
3055 /* store a pointer to the DH params to avoid complaining about
3056 ssl-default-dh-param not being set for this SSL_CTX */
3057 SSL_CTX_set_ex_data(ctx, ssl_dh_ptr_index, dh);
3058 }
3059 }
3060 else if (global_dh) {
Emeric Bruna9363eb2019-10-17 14:53:03 +02003061 if (!SSL_CTX_set_tmp_dh(ctx, global_dh)) {
3062 memprintf(err, "%sunable to use the global DH parameter for certificate '%s'",
3063 err && *err ? *err : "", path);
3064#if defined(SSL_CTX_set_dh_auto)
3065 SSL_CTX_set_dh_auto(ctx, 1);
3066 memprintf(err, "%s, SSL library will use an automatically generated DH parameter.\n",
3067 err && *err ? *err : "");
3068#else
3069 memprintf(err, "%s, DH ciphers won't be available.\n",
3070 err && *err ? *err : "");
3071#endif
3072 ret |= ERR_WARN;
3073 goto end;
3074 }
William Lallemandfa892222019-07-23 16:06:08 +02003075 }
3076 else {
3077 /* Clear openssl global errors stack */
3078 ERR_clear_error();
3079
3080 if (global_ssl.default_dh_param <= 1024) {
3081 /* we are limited to DH parameter of 1024 bits anyway */
3082 if (local_dh_1024 == NULL)
3083 local_dh_1024 = ssl_get_dh_1024();
3084
Emeric Brun7a883362019-10-17 13:27:40 +02003085 if (local_dh_1024 == NULL) {
3086 memprintf(err, "%sunable to load default 1024 bits DH parameter for certificate '%s'.\n",
3087 err && *err ? *err : "", path);
3088 ret |= ERR_ALERT | ERR_FATAL;
William Lallemandfa892222019-07-23 16:06:08 +02003089 goto end;
Emeric Brun7a883362019-10-17 13:27:40 +02003090 }
William Lallemandfa892222019-07-23 16:06:08 +02003091
Emeric Bruna9363eb2019-10-17 14:53:03 +02003092 if (!SSL_CTX_set_tmp_dh(ctx, local_dh_1024)) {
3093 memprintf(err, "%sunable to load default 1024 bits DH parameter for certificate '%s'.\n",
3094 err && *err ? *err : "", path);
3095#if defined(SSL_CTX_set_dh_auto)
3096 SSL_CTX_set_dh_auto(ctx, 1);
3097 memprintf(err, "%s, SSL library will use an automatically generated DH parameter.\n",
3098 err && *err ? *err : "");
3099#else
3100 memprintf(err, "%s, DH ciphers won't be available.\n",
3101 err && *err ? *err : "");
3102#endif
3103 ret |= ERR_WARN;
3104 goto end;
3105 }
William Lallemandfa892222019-07-23 16:06:08 +02003106 }
3107 else {
3108 SSL_CTX_set_tmp_dh_callback(ctx, ssl_get_tmp_dh);
3109 }
William Lallemandfa892222019-07-23 16:06:08 +02003110 }
3111
3112end:
William Lallemand4dd145a2020-02-05 11:46:33 +01003113 ERR_clear_error();
William Lallemandfa892222019-07-23 16:06:08 +02003114 return ret;
3115}
3116#endif
yanbzhu08ce6ab2015-12-02 13:01:29 -05003117
yanbzhu488a4d22015-12-01 15:16:07 -05003118/* Frees the contents of a cert_key_and_chain
3119 */
3120static void ssl_sock_free_cert_key_and_chain_contents(struct cert_key_and_chain *ckch)
3121{
yanbzhu488a4d22015-12-01 15:16:07 -05003122 if (!ckch)
3123 return;
3124
3125 /* Free the certificate and set pointer to NULL */
3126 if (ckch->cert)
3127 X509_free(ckch->cert);
3128 ckch->cert = NULL;
3129
3130 /* Free the key and set pointer to NULL */
3131 if (ckch->key)
3132 EVP_PKEY_free(ckch->key);
3133 ckch->key = NULL;
3134
3135 /* Free each certificate in the chain */
Emmanuel Hocdet9246f8b2018-11-30 16:00:21 +01003136 if (ckch->chain)
3137 sk_X509_pop_free(ckch->chain, X509_free);
3138 ckch->chain = NULL;
yanbzhu488a4d22015-12-01 15:16:07 -05003139
William Lallemand455af502019-10-17 18:04:45 +02003140 if (ckch->dh)
3141 DH_free(ckch->dh);
3142 ckch->dh = NULL;
3143
3144 if (ckch->sctl) {
3145 free(ckch->sctl->area);
3146 ckch->sctl->area = NULL;
3147 free(ckch->sctl);
3148 ckch->sctl = NULL;
3149 }
3150
3151 if (ckch->ocsp_response) {
3152 free(ckch->ocsp_response->area);
3153 ckch->ocsp_response->area = NULL;
3154 free(ckch->ocsp_response);
3155 ckch->ocsp_response = NULL;
3156 }
William Lallemand5c3c96f2020-01-23 11:53:13 +01003157
3158 if (ckch->ocsp_issuer)
William Lallemanddad239d2020-01-23 11:59:02 +01003159 X509_free(ckch->ocsp_issuer);
William Lallemand5c3c96f2020-01-23 11:53:13 +01003160 ckch->ocsp_issuer = NULL;
yanbzhu488a4d22015-12-01 15:16:07 -05003161}
3162
William Lallemand8d0f8932019-10-17 18:03:58 +02003163/*
3164 *
3165 * This function copy a cert_key_and_chain in memory
3166 *
3167 * It's used to try to apply changes on a ckch before committing them, because
3168 * most of the time it's not possible to revert those changes
3169 *
3170 * Return a the dst or NULL
3171 */
3172static struct cert_key_and_chain *ssl_sock_copy_cert_key_and_chain(struct cert_key_and_chain *src,
3173 struct cert_key_and_chain *dst)
3174{
3175 if (src->cert) {
3176 dst->cert = src->cert;
3177 X509_up_ref(src->cert);
3178 }
3179
3180 if (src->key) {
3181 dst->key = src->key;
3182 EVP_PKEY_up_ref(src->key);
3183 }
3184
3185 if (src->chain) {
3186 dst->chain = X509_chain_up_ref(src->chain);
3187 }
3188
3189 if (src->dh) {
3190 DH_up_ref(src->dh);
3191 dst->dh = src->dh;
3192 }
3193
3194 if (src->sctl) {
3195 struct buffer *sctl;
3196
3197 sctl = calloc(1, sizeof(*sctl));
3198 if (!chunk_dup(sctl, src->sctl)) {
3199 free(sctl);
3200 sctl = NULL;
3201 goto error;
3202 }
3203 dst->sctl = sctl;
3204 }
3205
3206 if (src->ocsp_response) {
3207 struct buffer *ocsp_response;
3208
3209 ocsp_response = calloc(1, sizeof(*ocsp_response));
3210 if (!chunk_dup(ocsp_response, src->ocsp_response)) {
3211 free(ocsp_response);
3212 ocsp_response = NULL;
3213 goto error;
3214 }
3215 dst->ocsp_response = ocsp_response;
3216 }
3217
3218 if (src->ocsp_issuer) {
3219 X509_up_ref(src->ocsp_issuer);
3220 dst->ocsp_issuer = src->ocsp_issuer;
3221 }
3222
3223 return dst;
3224
3225error:
3226
3227 /* free everything */
3228 ssl_sock_free_cert_key_and_chain_contents(dst);
3229
3230 return NULL;
3231}
3232
3233
yanbzhu488a4d22015-12-01 15:16:07 -05003234/* checks if a key and cert exists in the ckch
3235 */
William Lallemand1633e392019-09-30 12:58:13 +02003236#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
yanbzhu488a4d22015-12-01 15:16:07 -05003237static int ssl_sock_is_ckch_valid(struct cert_key_and_chain *ckch)
3238{
3239 return (ckch->cert != NULL && ckch->key != NULL);
3240}
William Lallemand1633e392019-09-30 12:58:13 +02003241#endif
yanbzhu488a4d22015-12-01 15:16:07 -05003242
William Lallemandf9568fc2019-10-16 18:27:58 +02003243/*
3244 * return 0 on success or != 0 on failure
3245 */
3246static int ssl_sock_load_issuer_file_into_ckch(const char *path, char *buf, struct cert_key_and_chain *ckch, char **err)
3247{
3248 int ret = 1;
3249 BIO *in = NULL;
3250 X509 *issuer;
3251
3252 if (buf) {
3253 /* reading from a buffer */
3254 in = BIO_new_mem_buf(buf, -1);
3255 if (in == NULL) {
3256 memprintf(err, "%sCan't allocate memory\n", err && *err ? *err : "");
3257 goto end;
3258 }
3259
3260 } else {
3261 /* reading from a file */
3262 in = BIO_new(BIO_s_file());
3263 if (in == NULL)
3264 goto end;
3265
3266 if (BIO_read_filename(in, path) <= 0)
3267 goto end;
3268 }
3269
3270 issuer = PEM_read_bio_X509_AUX(in, NULL, NULL, NULL);
3271 if (!issuer) {
3272 memprintf(err, "%s'%s' cannot be read or parsed'.\n",
Tim Duesterhus93128532019-11-23 23:45:10 +01003273 err && *err ? *err : "", path);
William Lallemandf9568fc2019-10-16 18:27:58 +02003274 goto end;
3275 }
Emmanuel Hocdeteb73dc32020-01-16 14:45:00 +01003276 /* no error, fill ckch with new context, old context must be free */
3277 if (ckch->ocsp_issuer)
3278 X509_free(ckch->ocsp_issuer);
William Lallemandf9568fc2019-10-16 18:27:58 +02003279 ckch->ocsp_issuer = issuer;
Emmanuel Hocdeteb73dc32020-01-16 14:45:00 +01003280 ret = 0;
William Lallemandf9568fc2019-10-16 18:27:58 +02003281
3282end:
3283
3284 ERR_clear_error();
3285 if (in)
3286 BIO_free(in);
3287
3288 return ret;
3289}
3290
William Lallemand96a9c972019-10-17 11:56:17 +02003291
3292/*
3293 * Try to load a PEM file from a <path> or a buffer <buf>
William Lallemand4c5adbf2020-02-24 14:23:22 +01003294 * The PEM must contain at least a Certificate,
3295 * It could contain a DH, a certificate chain and a PrivateKey.
yanbzhu488a4d22015-12-01 15:16:07 -05003296 *
William Lallemand96a9c972019-10-17 11:56:17 +02003297 * If it failed you should not attempt to use the ckch but free it.
3298 *
3299 * Return 0 on success or != 0 on failure
yanbzhu488a4d22015-12-01 15:16:07 -05003300 */
William Lallemand96a9c972019-10-17 11:56:17 +02003301static int ssl_sock_load_pem_into_ckch(const char *path, char *buf, struct cert_key_and_chain *ckch , char **err)
yanbzhu488a4d22015-12-01 15:16:07 -05003302{
William Lallemandf11365b2019-09-19 14:25:58 +02003303 BIO *in = NULL;
yanbzhu488a4d22015-12-01 15:16:07 -05003304 int ret = 1;
Emmanuel Hocdet83cbd3c2019-10-25 11:55:03 +02003305 X509 *ca;
William Lallemand96a9c972019-10-17 11:56:17 +02003306 X509 *cert = NULL;
3307 EVP_PKEY *key = NULL;
Emmanuel Hocdet6b5b44e2019-12-20 17:47:12 +01003308 DH *dh = NULL;
3309 STACK_OF(X509) *chain = NULL;
William Lallemand96a9c972019-10-17 11:56:17 +02003310
3311 if (buf) {
3312 /* reading from a buffer */
3313 in = BIO_new_mem_buf(buf, -1);
3314 if (in == NULL) {
3315 memprintf(err, "%sCan't allocate memory\n", err && *err ? *err : "");
3316 goto end;
3317 }
yanbzhu488a4d22015-12-01 15:16:07 -05003318
William Lallemand96a9c972019-10-17 11:56:17 +02003319 } else {
3320 /* reading from a file */
William Lallemandf11365b2019-09-19 14:25:58 +02003321 in = BIO_new(BIO_s_file());
3322 if (in == NULL)
3323 goto end;
yanbzhu488a4d22015-12-01 15:16:07 -05003324
William Lallemandf11365b2019-09-19 14:25:58 +02003325 if (BIO_read_filename(in, path) <= 0)
3326 goto end;
William Lallemandf11365b2019-09-19 14:25:58 +02003327 }
yanbzhu488a4d22015-12-01 15:16:07 -05003328
yanbzhu488a4d22015-12-01 15:16:07 -05003329 /* Read Private Key */
William Lallemand96a9c972019-10-17 11:56:17 +02003330 key = PEM_read_bio_PrivateKey(in, NULL, NULL, NULL);
William Lallemand4c5adbf2020-02-24 14:23:22 +01003331 /* no need to check for errors here, because the private key could be loaded later */
yanbzhu488a4d22015-12-01 15:16:07 -05003332
Emmanuel Hocdet54227d82019-07-30 17:04:01 +02003333#ifndef OPENSSL_NO_DH
William Lallemandfa892222019-07-23 16:06:08 +02003334 /* Seek back to beginning of file */
3335 if (BIO_reset(in) == -1) {
3336 memprintf(err, "%san error occurred while reading the file '%s'.\n",
3337 err && *err ? *err : "", path);
3338 goto end;
3339 }
3340
William Lallemand96a9c972019-10-17 11:56:17 +02003341 dh = PEM_read_bio_DHparams(in, NULL, NULL, NULL);
3342 /* no need to return an error there, dh is not mandatory */
Emmanuel Hocdet54227d82019-07-30 17:04:01 +02003343#endif
William Lallemandfa892222019-07-23 16:06:08 +02003344
Willy Tarreaubb137a82016-04-06 19:02:38 +02003345 /* Seek back to beginning of file */
Thierry FOURNIER / OZON.IOd44ea3f2016-10-14 00:49:21 +02003346 if (BIO_reset(in) == -1) {
3347 memprintf(err, "%san error occurred while reading the file '%s'.\n",
3348 err && *err ? *err : "", path);
3349 goto end;
3350 }
Willy Tarreaubb137a82016-04-06 19:02:38 +02003351
3352 /* Read Certificate */
William Lallemand96a9c972019-10-17 11:56:17 +02003353 cert = PEM_read_bio_X509_AUX(in, NULL, NULL, NULL);
3354 if (cert == NULL) {
Willy Tarreaubb137a82016-04-06 19:02:38 +02003355 memprintf(err, "%sunable to load certificate from file '%s'.\n",
William Lallemand96a9c972019-10-17 11:56:17 +02003356 err && *err ? *err : "", path);
Willy Tarreaubb137a82016-04-06 19:02:38 +02003357 goto end;
3358 }
3359
William Lallemand96a9c972019-10-17 11:56:17 +02003360 /* Look for a Certificate Chain */
Emmanuel Hocdet6b5b44e2019-12-20 17:47:12 +01003361 while ((ca = PEM_read_bio_X509(in, NULL, NULL, NULL))) {
3362 if (chain == NULL)
3363 chain = sk_X509_new_null();
3364 if (!sk_X509_push(chain, ca)) {
William Lallemand96a9c972019-10-17 11:56:17 +02003365 X509_free(ca);
3366 goto end;
3367 }
3368 }
Emmanuel Hocdeted17f472019-10-24 18:28:33 +02003369
yanbzhu488a4d22015-12-01 15:16:07 -05003370 ret = ERR_get_error();
3371 if (ret && (ERR_GET_LIB(ret) != ERR_LIB_PEM && ERR_GET_REASON(ret) != PEM_R_NO_START_LINE)) {
3372 memprintf(err, "%sunable to load certificate chain from file '%s'.\n",
William Lallemand96a9c972019-10-17 11:56:17 +02003373 err && *err ? *err : "", path);
yanbzhu488a4d22015-12-01 15:16:07 -05003374 goto end;
William Lallemand246c0242019-10-11 08:59:13 +02003375 }
3376
William Lallemand75b15f72020-01-23 10:56:05 +01003377 /* once it loaded the PEM, it should remove everything else in the ckch */
3378 if (ckch->ocsp_response) {
3379 free(ckch->ocsp_response->area);
3380 ckch->ocsp_response->area = NULL;
3381 free(ckch->ocsp_response);
3382 ckch->ocsp_response = NULL;
3383 }
3384
3385 if (ckch->sctl) {
3386 free(ckch->sctl->area);
3387 ckch->sctl->area = NULL;
3388 free(ckch->sctl);
3389 ckch->sctl = NULL;
3390 }
3391
3392 if (ckch->ocsp_issuer) {
3393 X509_free(ckch->ocsp_issuer);
3394 ckch->ocsp_issuer = NULL;
3395 }
3396
Emmanuel Hocdet6b5b44e2019-12-20 17:47:12 +01003397 /* no error, fill ckch with new context, old context will be free at end: */
3398 SWAP(ckch->key, key);
3399 SWAP(ckch->dh, dh);
3400 SWAP(ckch->cert, cert);
3401 SWAP(ckch->chain, chain);
3402
William Lallemand246c0242019-10-11 08:59:13 +02003403 ret = 0;
3404
William Lallemand96a9c972019-10-17 11:56:17 +02003405end:
William Lallemand246c0242019-10-11 08:59:13 +02003406
3407 ERR_clear_error();
William Lallemand96a9c972019-10-17 11:56:17 +02003408 if (in)
William Lallemand246c0242019-10-11 08:59:13 +02003409 BIO_free(in);
Emmanuel Hocdet83cbd3c2019-10-25 11:55:03 +02003410 if (key)
3411 EVP_PKEY_free(key);
Emmanuel Hocdet6b5b44e2019-12-20 17:47:12 +01003412 if (dh)
3413 DH_free(dh);
Emmanuel Hocdet83cbd3c2019-10-25 11:55:03 +02003414 if (cert)
3415 X509_free(cert);
Emmanuel Hocdet6b5b44e2019-12-20 17:47:12 +01003416 if (chain)
3417 sk_X509_pop_free(chain, X509_free);
William Lallemanda17f4112019-10-10 15:16:44 +02003418
William Lallemand96a9c972019-10-17 11:56:17 +02003419 return ret;
3420}
3421
3422/*
William Lallemand4c5adbf2020-02-24 14:23:22 +01003423 * Try to load a private key file from a <path> or a buffer <buf>
3424 *
3425 * If it failed you should not attempt to use the ckch but free it.
3426 *
3427 * Return 0 on success or != 0 on failure
3428 */
3429static int ssl_sock_load_key_into_ckch(const char *path, char *buf, struct cert_key_and_chain *ckch , char **err)
3430{
3431 BIO *in = NULL;
3432 int ret = 1;
3433 EVP_PKEY *key = NULL;
3434
3435 if (buf) {
3436 /* reading from a buffer */
3437 in = BIO_new_mem_buf(buf, -1);
3438 if (in == NULL) {
3439 memprintf(err, "%sCan't allocate memory\n", err && *err ? *err : "");
3440 goto end;
3441 }
3442
3443 } else {
3444 /* reading from a file */
3445 in = BIO_new(BIO_s_file());
3446 if (in == NULL)
3447 goto end;
3448
3449 if (BIO_read_filename(in, path) <= 0)
3450 goto end;
3451 }
3452
3453 /* Read Private Key */
3454 key = PEM_read_bio_PrivateKey(in, NULL, NULL, NULL);
3455 if (key == NULL) {
3456 memprintf(err, "%sunable to load private key from file '%s'.\n",
3457 err && *err ? *err : "", path);
3458 goto end;
3459 }
3460
3461 ret = 0;
3462
3463 SWAP(ckch->key, key);
3464
3465end:
3466
3467 ERR_clear_error();
3468 if (in)
3469 BIO_free(in);
3470 if (key)
3471 EVP_PKEY_free(key);
3472
3473 return ret;
3474}
3475
3476/*
William Lallemand96a9c972019-10-17 11:56:17 +02003477 * Try to load in a ckch every files related to a ckch.
3478 * (PEM, sctl, ocsp, issuer etc.)
3479 *
3480 * This function is only used to load files during the configuration parsing,
3481 * it is not used with the CLI.
3482 *
3483 * This allows us to carry the contents of the file without having to read the
3484 * file multiple times. The caller must call
3485 * ssl_sock_free_cert_key_and_chain_contents.
3486 *
3487 * returns:
3488 * 0 on Success
3489 * 1 on SSL Failure
3490 */
3491static int ssl_sock_load_files_into_ckch(const char *path, struct cert_key_and_chain *ckch, char **err)
3492{
3493 int ret = 1;
3494
3495 /* try to load the PEM */
3496 if (ssl_sock_load_pem_into_ckch(path, NULL, ckch , err) != 0) {
3497 goto end;
3498 }
3499
William Lallemand4c5adbf2020-02-24 14:23:22 +01003500 /* try to load an external private key if it wasn't in the PEM */
3501 if ((ckch->key == NULL) && (global_ssl.extra_files & SSL_GF_KEY)) {
3502 char fp[MAXPATHLEN+1];
3503 struct stat st;
3504
3505 snprintf(fp, MAXPATHLEN+1, "%s.key", path);
3506 if (stat(fp, &st) == 0) {
3507 if (ssl_sock_load_key_into_ckch(fp, NULL, ckch, err)) {
3508 memprintf(err, "%s '%s' is present but cannot be read or parsed'.\n",
3509 err && *err ? *err : "", fp);
3510 goto end;
3511 }
3512 }
3513 }
3514
3515 if (ckch->key == NULL) {
3516 memprintf(err, "%sNo Private Key found in '%s' or '%s.key'.\n", err && *err ? *err : "", path, path);
3517 goto end;
3518 }
3519
3520 if (!X509_check_private_key(ckch->cert, ckch->key)) {
3521 memprintf(err, "%sinconsistencies between private key and certificate loaded '%s'.\n",
3522 err && *err ? *err : "", path);
3523 goto end;
3524 }
3525
William Lallemanda17f4112019-10-10 15:16:44 +02003526#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
3527 /* try to load the sctl file */
William Lallemand3af48e72020-02-03 17:15:52 +01003528 if (global_ssl.extra_files & SSL_GF_SCTL) {
William Lallemanda17f4112019-10-10 15:16:44 +02003529 char fp[MAXPATHLEN+1];
3530 struct stat st;
3531
3532 snprintf(fp, MAXPATHLEN+1, "%s.sctl", path);
3533 if (stat(fp, &st) == 0) {
William Lallemand0dfae6c2019-10-16 18:06:58 +02003534 if (ssl_sock_load_sctl_from_file(fp, NULL, ckch, err)) {
William Lallemanda17f4112019-10-10 15:16:44 +02003535 memprintf(err, "%s '%s.sctl' is present but cannot be read or parsed'.\n",
Tim Duesterhus93128532019-11-23 23:45:10 +01003536 err && *err ? *err : "", fp);
William Lallemanda17f4112019-10-10 15:16:44 +02003537 ret = 1;
3538 goto end;
3539 }
3540 }
3541 }
3542#endif
yanbzhu488a4d22015-12-01 15:16:07 -05003543
William Lallemand246c0242019-10-11 08:59:13 +02003544 /* try to load an ocsp response file */
William Lallemand3af48e72020-02-03 17:15:52 +01003545 if (global_ssl.extra_files & SSL_GF_OCSP) {
William Lallemand246c0242019-10-11 08:59:13 +02003546 char fp[MAXPATHLEN+1];
3547 struct stat st;
3548
3549 snprintf(fp, MAXPATHLEN+1, "%s.ocsp", path);
3550 if (stat(fp, &st) == 0) {
William Lallemand3b5f3602019-10-16 18:05:05 +02003551 if (ssl_sock_load_ocsp_response_from_file(fp, NULL, ckch, err)) {
William Lallemand246c0242019-10-11 08:59:13 +02003552 ret = 1;
3553 goto end;
3554 }
3555 }
3556 }
3557
Emmanuel Hocdeteaad5cc2019-10-25 12:19:00 +02003558#ifndef OPENSSL_IS_BORINGSSL /* Useless for BoringSSL */
William Lallemand3af48e72020-02-03 17:15:52 +01003559 if (ckch->ocsp_response && (global_ssl.extra_files & SSL_GF_OCSP_ISSUER)) {
William Lallemand246c0242019-10-11 08:59:13 +02003560 /* if no issuer was found, try to load an issuer from the .issuer */
Emmanuel Hocdet078156d2020-01-22 17:02:53 +01003561 if (!ckch->ocsp_issuer) {
William Lallemand246c0242019-10-11 08:59:13 +02003562 struct stat st;
3563 char fp[MAXPATHLEN+1];
3564
3565 snprintf(fp, MAXPATHLEN+1, "%s.issuer", path);
3566 if (stat(fp, &st) == 0) {
William Lallemandf9568fc2019-10-16 18:27:58 +02003567 if (ssl_sock_load_issuer_file_into_ckch(fp, NULL, ckch, err)) {
William Lallemand246c0242019-10-11 08:59:13 +02003568 ret = 1;
3569 goto end;
3570 }
3571
3572 if (X509_check_issued(ckch->ocsp_issuer, ckch->cert) != X509_V_OK) {
William Lallemand786188f2019-10-15 10:05:37 +02003573 memprintf(err, "%s '%s' is not an issuer'.\n",
Tim Duesterhus93128532019-11-23 23:45:10 +01003574 err && *err ? *err : "", fp);
William Lallemand246c0242019-10-11 08:59:13 +02003575 ret = 1;
3576 goto end;
3577 }
William Lallemand246c0242019-10-11 08:59:13 +02003578 }
3579 }
3580 }
Emmanuel Hocdeteaad5cc2019-10-25 12:19:00 +02003581#endif
William Lallemand246c0242019-10-11 08:59:13 +02003582
yanbzhu488a4d22015-12-01 15:16:07 -05003583 ret = 0;
3584
3585end:
3586
3587 ERR_clear_error();
yanbzhu488a4d22015-12-01 15:16:07 -05003588
3589 /* Something went wrong in one of the reads */
3590 if (ret != 0)
3591 ssl_sock_free_cert_key_and_chain_contents(ckch);
3592
3593 return ret;
3594}
3595
3596/* Loads the info in ckch into ctx
Emeric Bruna96b5822019-10-17 13:25:14 +02003597 * Returns a bitfield containing the flags:
3598 * ERR_FATAL in any fatal error case
3599 * ERR_ALERT if the reason of the error is available in err
3600 * ERR_WARN if a warning is available into err
3601 * The value 0 means there is no error nor warning and
3602 * the operation succeed.
yanbzhu488a4d22015-12-01 15:16:07 -05003603 */
3604static int ssl_sock_put_ckch_into_ctx(const char *path, const struct cert_key_and_chain *ckch, SSL_CTX *ctx, char **err)
3605{
Emeric Bruna96b5822019-10-17 13:25:14 +02003606 int errcode = 0;
Emmanuel Hocdetb90d2cb2020-02-18 15:27:32 +01003607 STACK_OF(X509) *find_chain = NULL;
Emeric Bruna96b5822019-10-17 13:25:14 +02003608
yanbzhu488a4d22015-12-01 15:16:07 -05003609 if (SSL_CTX_use_PrivateKey(ctx, ckch->key) <= 0) {
3610 memprintf(err, "%sunable to load SSL private key into SSL Context '%s'.\n",
3611 err && *err ? *err : "", path);
Emeric Bruna96b5822019-10-17 13:25:14 +02003612 errcode |= ERR_ALERT | ERR_FATAL;
3613 return errcode;
yanbzhu488a4d22015-12-01 15:16:07 -05003614 }
3615
3616 if (!SSL_CTX_use_certificate(ctx, ckch->cert)) {
3617 memprintf(err, "%sunable to load SSL certificate into SSL Context '%s'.\n",
3618 err && *err ? *err : "", path);
Emeric Bruna96b5822019-10-17 13:25:14 +02003619 errcode |= ERR_ALERT | ERR_FATAL;
3620 goto end;
yanbzhu488a4d22015-12-01 15:16:07 -05003621 }
3622
Emmanuel Hocdetb90d2cb2020-02-18 15:27:32 +01003623 if (ckch->chain) {
3624 find_chain = ckch->chain;
3625 } else {
3626 /* Find Certificate Chain in global */
3627 struct issuer_chain *issuer;
3628 issuer = ssl_get_issuer_chain(ckch->cert);
3629 if (issuer)
3630 find_chain = issuer->chain;
3631 }
William Lallemand85888572020-02-27 14:48:35 +01003632
3633 /* If we didn't find a chain we *MUST* use an empty X509 structure */
3634 if (find_chain == NULL)
3635 find_chain = sk_X509_new_null();
3636
yanbzhu488a4d22015-12-01 15:16:07 -05003637 /* Load all certs in the ckch into the ctx_chain for the ssl_ctx */
Emmanuel Hocdet1c65fdd2018-12-03 18:07:44 +01003638#ifdef SSL_CTX_set1_chain
Emmanuel Hocdetb90d2cb2020-02-18 15:27:32 +01003639 if (!SSL_CTX_set1_chain(ctx, find_chain)) {
Emmanuel Hocdet9246f8b2018-11-30 16:00:21 +01003640 memprintf(err, "%sunable to load chain certificate into SSL Context '%s'. Make sure you are linking against Openssl >= 1.0.2.\n",
3641 err && *err ? *err : "", path);
Emeric Bruna96b5822019-10-17 13:25:14 +02003642 errcode |= ERR_ALERT | ERR_FATAL;
3643 goto end;
yanbzhu488a4d22015-12-01 15:16:07 -05003644 }
Emmanuel Hocdet1c65fdd2018-12-03 18:07:44 +01003645#else
3646 { /* legacy compat (< openssl 1.0.2) */
3647 X509 *ca;
Emmanuel Hocdet140b64f2019-10-24 18:33:10 +02003648 STACK_OF(X509) *chain;
Emmanuel Hocdetb90d2cb2020-02-18 15:27:32 +01003649 chain = X509_chain_up_ref(find_chain);
Emmanuel Hocdet140b64f2019-10-24 18:33:10 +02003650 while ((ca = sk_X509_shift(chain)))
Emmanuel Hocdet1c65fdd2018-12-03 18:07:44 +01003651 if (!SSL_CTX_add_extra_chain_cert(ctx, ca)) {
3652 memprintf(err, "%sunable to load chain certificate into SSL Context '%s'.\n",
3653 err && *err ? *err : "", path);
3654 X509_free(ca);
Emmanuel Hocdet140b64f2019-10-24 18:33:10 +02003655 sk_X509_pop_free(chain, X509_free);
Emeric Bruna96b5822019-10-17 13:25:14 +02003656 errcode |= ERR_ALERT | ERR_FATAL;
3657 goto end;
Emmanuel Hocdet1c65fdd2018-12-03 18:07:44 +01003658 }
3659 }
3660#endif
yanbzhu488a4d22015-12-01 15:16:07 -05003661
William Lallemandfa892222019-07-23 16:06:08 +02003662#ifndef OPENSSL_NO_DH
3663 /* store a NULL pointer to indicate we have not yet loaded
3664 a custom DH param file */
3665 if (ssl_dh_ptr_index >= 0) {
3666 SSL_CTX_set_ex_data(ctx, ssl_dh_ptr_index, NULL);
3667 }
3668
Emeric Brun7a883362019-10-17 13:27:40 +02003669 errcode |= ssl_sock_load_dh_params(ctx, ckch, path, err);
3670 if (errcode & ERR_CODE) {
William Lallemandfa892222019-07-23 16:06:08 +02003671 memprintf(err, "%sunable to load DH parameters from file '%s'.\n",
3672 err && *err ? *err : "", path);
Emeric Bruna96b5822019-10-17 13:25:14 +02003673 goto end;
William Lallemandfa892222019-07-23 16:06:08 +02003674 }
3675#endif
3676
William Lallemanda17f4112019-10-10 15:16:44 +02003677#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
3678 if (sctl_ex_index >= 0 && ckch->sctl) {
3679 if (ssl_sock_load_sctl(ctx, ckch->sctl) < 0) {
3680 memprintf(err, "%s '%s.sctl' is present but cannot be read or parsed'.\n",
Tim Duesterhus93128532019-11-23 23:45:10 +01003681 err && *err ? *err : "", path);
Emeric Bruna96b5822019-10-17 13:25:14 +02003682 errcode |= ERR_ALERT | ERR_FATAL;
3683 goto end;
William Lallemanda17f4112019-10-10 15:16:44 +02003684 }
3685 }
3686#endif
3687
William Lallemand4a660132019-10-14 14:51:41 +02003688#if ((defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP) || defined OPENSSL_IS_BORINGSSL)
William Lallemand246c0242019-10-11 08:59:13 +02003689 /* Load OCSP Info into context */
3690 if (ckch->ocsp_response) {
Emmanuel Hocdet6f507c72020-02-18 15:56:39 +01003691 if (ssl_sock_load_ocsp(ctx, ckch, find_chain) < 0) {
Tim Duesterhus93128532019-11-23 23:45:10 +01003692 memprintf(err, "%s '%s.ocsp' is present and activates OCSP but it is impossible to compute the OCSP certificate ID (maybe the issuer could not be found)'.\n",
3693 err && *err ? *err : "", path);
Emeric Bruna96b5822019-10-17 13:25:14 +02003694 errcode |= ERR_ALERT | ERR_FATAL;
3695 goto end;
William Lallemand246c0242019-10-11 08:59:13 +02003696 }
3697 }
William Lallemand246c0242019-10-11 08:59:13 +02003698#endif
3699
Emeric Bruna96b5822019-10-17 13:25:14 +02003700 end:
3701 return errcode;
yanbzhu488a4d22015-12-01 15:16:07 -05003702}
3703
William Lallemandc4ecddf2019-07-31 16:50:08 +02003704#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
yanbzhu08ce6ab2015-12-02 13:01:29 -05003705
William Lallemand28a8fce2019-10-04 17:36:55 +02003706static int ssl_sock_populate_sni_keytypes_hplr(const char *str, struct eb_root *sni_keytypes, int key_index)
yanbzhu08ce6ab2015-12-02 13:01:29 -05003707{
3708 struct sni_keytype *s_kt = NULL;
3709 struct ebmb_node *node;
3710 int i;
3711
3712 for (i = 0; i < trash.size; i++) {
3713 if (!str[i])
3714 break;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02003715 trash.area[i] = tolower(str[i]);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003716 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +02003717 trash.area[i] = 0;
3718 node = ebst_lookup(sni_keytypes, trash.area);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003719 if (!node) {
3720 /* CN not found in tree */
3721 s_kt = malloc(sizeof(struct sni_keytype) + i + 1);
3722 /* Using memcpy here instead of strncpy.
3723 * strncpy will cause sig_abrt errors under certain versions of gcc with -O2
3724 * See: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=60792
3725 */
William Lallemand28a8fce2019-10-04 17:36:55 +02003726 if (!s_kt)
3727 return -1;
3728
Willy Tarreau843b7cb2018-07-13 10:54:26 +02003729 memcpy(s_kt->name.key, trash.area, i+1);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003730 s_kt->keytypes = 0;
3731 ebst_insert(sni_keytypes, &s_kt->name);
3732 } else {
3733 /* CN found in tree */
3734 s_kt = container_of(node, struct sni_keytype, name);
3735 }
3736
3737 /* Mark that this CN has the keytype of key_index via keytypes mask */
3738 s_kt->keytypes |= 1<<key_index;
3739
William Lallemand28a8fce2019-10-04 17:36:55 +02003740 return 0;
3741
yanbzhu08ce6ab2015-12-02 13:01:29 -05003742}
3743
William Lallemandc4ecddf2019-07-31 16:50:08 +02003744#endif
William Lallemand8c1cdde2019-10-18 10:58:14 +02003745/*
3746 * Free a ckch_store and its ckch(s)
3747 * The linked ckch_inst are not free'd
3748 */
3749void ckchs_free(struct ckch_store *ckchs)
3750{
3751 if (!ckchs)
3752 return;
3753
3754#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
3755 if (ckchs->multi) {
3756 int n;
3757
3758 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++)
3759 ssl_sock_free_cert_key_and_chain_contents(&ckchs->ckch[n]);
3760 } else
3761#endif
3762 {
3763 ssl_sock_free_cert_key_and_chain_contents(ckchs->ckch);
3764 ckchs->ckch = NULL;
3765 }
3766
3767 free(ckchs);
3768}
3769
3770/* allocate and duplicate a ckch_store
3771 * Return a new ckch_store or NULL */
3772static struct ckch_store *ckchs_dup(const struct ckch_store *src)
3773{
3774 struct ckch_store *dst;
3775 int pathlen;
3776
3777 pathlen = strlen(src->path);
3778 dst = calloc(1, sizeof(*dst) + pathlen + 1);
3779 if (!dst)
3780 return NULL;
3781 /* copy previous key */
3782 memcpy(dst->path, src->path, pathlen + 1);
3783 dst->multi = src->multi;
3784 LIST_INIT(&dst->ckch_inst);
3785
3786 dst->ckch = calloc((src->multi ? SSL_SOCK_NUM_KEYTYPES : 1), sizeof(*dst->ckch));
3787 if (!dst->ckch)
3788 goto error;
3789
3790#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
3791 if (src->multi) {
3792 int n;
3793
3794 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
3795 if (&src->ckch[n]) {
3796 if (!ssl_sock_copy_cert_key_and_chain(&src->ckch[n], &dst->ckch[n]))
3797 goto error;
3798 }
3799 }
3800 } else
3801#endif
3802 {
3803 if (!ssl_sock_copy_cert_key_and_chain(src->ckch, dst->ckch))
3804 goto error;
3805 }
3806
3807 return dst;
3808
3809error:
3810 ckchs_free(dst);
3811
3812 return NULL;
3813}
William Lallemandc4ecddf2019-07-31 16:50:08 +02003814
William Lallemand36b84632019-07-18 19:28:17 +02003815/*
William Lallemande3af8fb2019-10-08 11:36:53 +02003816 * lookup a path into the ckchs tree.
William Lallemand6af03992019-07-23 15:00:54 +02003817 */
William Lallemande3af8fb2019-10-08 11:36:53 +02003818static inline struct ckch_store *ckchs_lookup(char *path)
William Lallemand6af03992019-07-23 15:00:54 +02003819{
3820 struct ebmb_node *eb;
3821
William Lallemande3af8fb2019-10-08 11:36:53 +02003822 eb = ebst_lookup(&ckchs_tree, path);
William Lallemand6af03992019-07-23 15:00:54 +02003823 if (!eb)
3824 return NULL;
3825
William Lallemande3af8fb2019-10-08 11:36:53 +02003826 return ebmb_entry(eb, struct ckch_store, node);
William Lallemand6af03992019-07-23 15:00:54 +02003827}
3828
3829/*
William Lallemande3af8fb2019-10-08 11:36:53 +02003830 * This function allocate a ckch_store and populate it with certificates from files.
William Lallemand36b84632019-07-18 19:28:17 +02003831 */
William Lallemande3af8fb2019-10-08 11:36:53 +02003832static struct ckch_store *ckchs_load_cert_file(char *path, int multi, char **err)
William Lallemand36b84632019-07-18 19:28:17 +02003833{
William Lallemande3af8fb2019-10-08 11:36:53 +02003834 struct ckch_store *ckchs;
William Lallemand36b84632019-07-18 19:28:17 +02003835
William Lallemande3af8fb2019-10-08 11:36:53 +02003836 ckchs = calloc(1, sizeof(*ckchs) + strlen(path) + 1);
3837 if (!ckchs) {
William Lallemand36b84632019-07-18 19:28:17 +02003838 memprintf(err, "%sunable to allocate memory.\n", err && *err ? *err : "");
3839 goto end;
3840 }
William Lallemande3af8fb2019-10-08 11:36:53 +02003841 ckchs->ckch = calloc(1, sizeof(*ckchs->ckch) * (multi ? SSL_SOCK_NUM_KEYTYPES : 1));
William Lallemand36b84632019-07-18 19:28:17 +02003842
William Lallemande3af8fb2019-10-08 11:36:53 +02003843 if (!ckchs->ckch) {
William Lallemand36b84632019-07-18 19:28:17 +02003844 memprintf(err, "%sunable to allocate memory.\n", err && *err ? *err : "");
3845 goto end;
3846 }
3847
William Lallemand9117de92019-10-04 00:29:42 +02003848 LIST_INIT(&ckchs->ckch_inst);
3849
William Lallemand36b84632019-07-18 19:28:17 +02003850 if (!multi) {
3851
William Lallemand96a9c972019-10-17 11:56:17 +02003852 if (ssl_sock_load_files_into_ckch(path, ckchs->ckch, err) == 1)
William Lallemand36b84632019-07-18 19:28:17 +02003853 goto end;
3854
William Lallemande3af8fb2019-10-08 11:36:53 +02003855 /* insert into the ckchs tree */
3856 memcpy(ckchs->path, path, strlen(path) + 1);
3857 ebst_insert(&ckchs_tree, &ckchs->node);
William Lallemand36b84632019-07-18 19:28:17 +02003858 } else {
3859 int found = 0;
William Lallemandc4ecddf2019-07-31 16:50:08 +02003860#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
3861 char fp[MAXPATHLEN+1] = {0};
3862 int n = 0;
William Lallemand36b84632019-07-18 19:28:17 +02003863
3864 /* Load all possible certs and keys */
3865 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
3866 struct stat buf;
3867 snprintf(fp, sizeof(fp), "%s.%s", path, SSL_SOCK_KEYTYPE_NAMES[n]);
3868 if (stat(fp, &buf) == 0) {
William Lallemand96a9c972019-10-17 11:56:17 +02003869 if (ssl_sock_load_files_into_ckch(fp, &ckchs->ckch[n], err) == 1)
William Lallemand36b84632019-07-18 19:28:17 +02003870 goto end;
3871 found = 1;
William Lallemande3af8fb2019-10-08 11:36:53 +02003872 ckchs->multi = 1;
William Lallemand36b84632019-07-18 19:28:17 +02003873 }
3874 }
William Lallemandc4ecddf2019-07-31 16:50:08 +02003875#endif
William Lallemand36b84632019-07-18 19:28:17 +02003876
3877 if (!found) {
William Lallemand6e5f2ce2019-08-01 14:43:20 +02003878 memprintf(err, "%sDidn't find any certificate for bundle '%s'.\n", err && *err ? *err : "", path);
William Lallemand36b84632019-07-18 19:28:17 +02003879 goto end;
3880 }
William Lallemande3af8fb2019-10-08 11:36:53 +02003881 /* insert into the ckchs tree */
3882 memcpy(ckchs->path, path, strlen(path) + 1);
3883 ebst_insert(&ckchs_tree, &ckchs->node);
William Lallemand36b84632019-07-18 19:28:17 +02003884 }
William Lallemande3af8fb2019-10-08 11:36:53 +02003885 return ckchs;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003886
William Lallemand36b84632019-07-18 19:28:17 +02003887end:
William Lallemande3af8fb2019-10-08 11:36:53 +02003888 if (ckchs) {
3889 free(ckchs->ckch);
3890 ebmb_delete(&ckchs->node);
William Lallemand6af03992019-07-23 15:00:54 +02003891 }
3892
William Lallemande3af8fb2019-10-08 11:36:53 +02003893 free(ckchs);
William Lallemand36b84632019-07-18 19:28:17 +02003894
3895 return NULL;
3896}
3897
William Lallemandc4ecddf2019-07-31 16:50:08 +02003898#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
3899
William Lallemand36b84632019-07-18 19:28:17 +02003900/*
William Lallemande3af8fb2019-10-08 11:36:53 +02003901 * Take a ckch_store which contains a multi-certificate bundle.
William Lallemand36b84632019-07-18 19:28:17 +02003902 * Group these certificates into a set of SSL_CTX*
yanbzhu08ce6ab2015-12-02 13:01:29 -05003903 * based on shared and unique CN and SAN entries. Add these SSL_CTX* to the SNI tree.
3904 *
Joseph Herlant017b3da2018-11-15 09:07:59 -08003905 * This will allow the user to explicitly group multiple cert/keys for a single purpose
yanbzhu08ce6ab2015-12-02 13:01:29 -05003906 *
Emeric Brun054563d2019-10-17 13:16:58 +02003907 * Returns a bitfield containing the flags:
3908 * ERR_FATAL in any fatal error case
3909 * ERR_ALERT if the reason of the error is available in err
3910 * ERR_WARN if a warning is available into err
William Lallemand36b84632019-07-18 19:28:17 +02003911 *
yanbzhu08ce6ab2015-12-02 13:01:29 -05003912 */
Emeric Brun054563d2019-10-17 13:16:58 +02003913static int ckch_inst_new_load_multi_store(const char *path, struct ckch_store *ckchs,
3914 struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
3915 char **sni_filter, int fcount, struct ckch_inst **ckchi, char **err)
yanbzhu08ce6ab2015-12-02 13:01:29 -05003916{
William Lallemand36b84632019-07-18 19:28:17 +02003917 int i = 0, n = 0;
3918 struct cert_key_and_chain *certs_and_keys;
William Lallemand4b989f22019-10-04 18:36:55 +02003919 struct eb_root sni_keytypes_map = EB_ROOT;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003920 struct ebmb_node *node;
3921 struct ebmb_node *next;
3922 /* Array of SSL_CTX pointers corresponding to each possible combo
3923 * of keytypes
3924 */
3925 struct key_combo_ctx key_combos[SSL_SOCK_POSSIBLE_KT_COMBOS] = { {0} };
Emeric Brun054563d2019-10-17 13:16:58 +02003926 int errcode = 0;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003927 X509_NAME *xname = NULL;
3928 char *str = NULL;
3929#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
3930 STACK_OF(GENERAL_NAME) *names = NULL;
3931#endif
William Lallemand614ca0d2019-10-07 13:52:11 +02003932 struct ckch_inst *ckch_inst;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003933
Emeric Brun054563d2019-10-17 13:16:58 +02003934 *ckchi = NULL;
3935
William Lallemande3af8fb2019-10-08 11:36:53 +02003936 if (!ckchs || !ckchs->ckch || !ckchs->multi) {
William Lallemand36b84632019-07-18 19:28:17 +02003937 memprintf(err, "%sunable to load SSL certificate file '%s' file does not exist.\n",
3938 err && *err ? *err : "", path);
Emeric Brun054563d2019-10-17 13:16:58 +02003939 return ERR_ALERT | ERR_FATAL;
William Lallemand614ca0d2019-10-07 13:52:11 +02003940 }
3941
3942 ckch_inst = ckch_inst_new();
3943 if (!ckch_inst) {
3944 memprintf(err, "%sunable to allocate SSL context for cert '%s'.\n",
3945 err && *err ? *err : "", path);
Emeric Brun054563d2019-10-17 13:16:58 +02003946 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemand614ca0d2019-10-07 13:52:11 +02003947 goto end;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003948 }
3949
William Lallemande3af8fb2019-10-08 11:36:53 +02003950 certs_and_keys = ckchs->ckch;
William Lallemand36b84632019-07-18 19:28:17 +02003951
William Lallemand150bfa82019-09-19 17:12:49 +02003952 /* at least one of the instances is using filters during the config
3953 * parsing, that's ok to inherit this during loading on CLI */
William Lallemand920b0352019-12-04 15:33:01 +01003954 ckchs->filters |= !!fcount;
William Lallemand150bfa82019-09-19 17:12:49 +02003955
yanbzhu08ce6ab2015-12-02 13:01:29 -05003956 /* Process each ckch and update keytypes for each CN/SAN
3957 * for example, if CN/SAN www.a.com is associated with
3958 * certs with keytype 0 and 2, then at the end of the loop,
3959 * www.a.com will have:
3960 * keyindex = 0 | 1 | 4 = 5
3961 */
3962 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
William Lallemand28a8fce2019-10-04 17:36:55 +02003963 int ret;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003964
3965 if (!ssl_sock_is_ckch_valid(&certs_and_keys[n]))
3966 continue;
3967
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003968 if (fcount) {
William Lallemand28a8fce2019-10-04 17:36:55 +02003969 for (i = 0; i < fcount; i++) {
3970 ret = ssl_sock_populate_sni_keytypes_hplr(sni_filter[i], &sni_keytypes_map, n);
3971 if (ret < 0) {
3972 memprintf(err, "%sunable to allocate SSL context.\n",
3973 err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02003974 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemand28a8fce2019-10-04 17:36:55 +02003975 goto end;
3976 }
3977 }
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003978 } else {
3979 /* A lot of the following code is OpenSSL boilerplate for processing CN's and SAN's,
3980 * so the line that contains logic is marked via comments
3981 */
3982 xname = X509_get_subject_name(certs_and_keys[n].cert);
3983 i = -1;
3984 while ((i = X509_NAME_get_index_by_NID(xname, NID_commonName, i)) != -1) {
3985 X509_NAME_ENTRY *entry = X509_NAME_get_entry(xname, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003986 ASN1_STRING *value;
3987 value = X509_NAME_ENTRY_get_data(entry);
3988 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003989 /* Important line is here */
William Lallemand28a8fce2019-10-04 17:36:55 +02003990 ret = ssl_sock_populate_sni_keytypes_hplr(str, &sni_keytypes_map, n);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003991
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003992 OPENSSL_free(str);
3993 str = NULL;
William Lallemand28a8fce2019-10-04 17:36:55 +02003994 if (ret < 0) {
3995 memprintf(err, "%sunable to allocate SSL context.\n",
3996 err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02003997 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemand28a8fce2019-10-04 17:36:55 +02003998 goto end;
3999 }
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02004000 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05004001 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05004002
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02004003 /* Do the above logic for each SAN */
yanbzhu08ce6ab2015-12-02 13:01:29 -05004004#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02004005 names = X509_get_ext_d2i(certs_and_keys[n].cert, NID_subject_alt_name, NULL, NULL);
4006 if (names) {
4007 for (i = 0; i < sk_GENERAL_NAME_num(names); i++) {
4008 GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i);
yanbzhu08ce6ab2015-12-02 13:01:29 -05004009
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02004010 if (name->type == GEN_DNS) {
4011 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
4012 /* Important line is here */
William Lallemand28a8fce2019-10-04 17:36:55 +02004013 ret = ssl_sock_populate_sni_keytypes_hplr(str, &sni_keytypes_map, n);
yanbzhu08ce6ab2015-12-02 13:01:29 -05004014
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02004015 OPENSSL_free(str);
4016 str = NULL;
William Lallemand28a8fce2019-10-04 17:36:55 +02004017 if (ret < 0) {
4018 memprintf(err, "%sunable to allocate SSL context.\n",
4019 err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02004020 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemand28a8fce2019-10-04 17:36:55 +02004021 goto end;
4022 }
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02004023 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05004024 }
4025 }
4026 }
4027 }
4028#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
4029 }
4030
4031 /* If no files found, return error */
4032 if (eb_is_empty(&sni_keytypes_map)) {
4033 memprintf(err, "%sunable to load SSL certificate file '%s' file does not exist.\n",
4034 err && *err ? *err : "", path);
Emeric Brun054563d2019-10-17 13:16:58 +02004035 errcode |= ERR_ALERT | ERR_FATAL;
yanbzhu08ce6ab2015-12-02 13:01:29 -05004036 goto end;
4037 }
4038
4039 /* We now have a map of CN/SAN to keytypes that are loaded in
4040 * Iterate through the map to create the SSL_CTX's (if needed)
4041 * and add each CTX to the SNI tree
4042 *
4043 * Some math here:
Joseph Herlant017b3da2018-11-15 09:07:59 -08004044 * There are 2^n - 1 possible combinations, each unique
yanbzhu08ce6ab2015-12-02 13:01:29 -05004045 * combination is denoted by the key in the map. Each key
4046 * has a value between 1 and 2^n - 1. Conveniently, the array
4047 * of SSL_CTX* is sized 2^n. So, we can simply use the i'th
4048 * entry in the array to correspond to the unique combo (key)
4049 * associated with i. This unique key combo (i) will be associated
4050 * with combos[i-1]
4051 */
4052
4053 node = ebmb_first(&sni_keytypes_map);
4054 while (node) {
4055 SSL_CTX *cur_ctx;
Bertrand Jacquin33423092016-11-13 16:37:13 +00004056 char cur_file[MAXPATHLEN+1];
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02004057 const struct pkey_info kinfo = { .sig = TLSEXT_signature_anonymous, .bits = 0 };
yanbzhu08ce6ab2015-12-02 13:01:29 -05004058
4059 str = (char *)container_of(node, struct sni_keytype, name)->name.key;
4060 i = container_of(node, struct sni_keytype, name)->keytypes;
4061 cur_ctx = key_combos[i-1].ctx;
4062
4063 if (cur_ctx == NULL) {
4064 /* need to create SSL_CTX */
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004065 cur_ctx = SSL_CTX_new(SSLv23_server_method());
yanbzhu08ce6ab2015-12-02 13:01:29 -05004066 if (cur_ctx == NULL) {
4067 memprintf(err, "%sunable to allocate SSL context.\n",
4068 err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02004069 errcode |= ERR_ALERT | ERR_FATAL;
yanbzhu08ce6ab2015-12-02 13:01:29 -05004070 goto end;
4071 }
4072
yanbzhube2774d2015-12-10 15:07:30 -05004073 /* Load all required certs/keys/chains/OCSPs info into SSL_CTX */
yanbzhu08ce6ab2015-12-02 13:01:29 -05004074 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
4075 if (i & (1<<n)) {
4076 /* Key combo contains ckch[n] */
Bertrand Jacquin33423092016-11-13 16:37:13 +00004077 snprintf(cur_file, MAXPATHLEN+1, "%s.%s", path, SSL_SOCK_KEYTYPE_NAMES[n]);
Emeric Bruna96b5822019-10-17 13:25:14 +02004078 errcode |= ssl_sock_put_ckch_into_ctx(cur_file, &certs_and_keys[n], cur_ctx, err);
4079 if (errcode & ERR_CODE)
yanbzhu08ce6ab2015-12-02 13:01:29 -05004080 goto end;
yanbzhu08ce6ab2015-12-02 13:01:29 -05004081 }
4082 }
4083
yanbzhu08ce6ab2015-12-02 13:01:29 -05004084 /* Update key_combos */
4085 key_combos[i-1].ctx = cur_ctx;
4086 }
4087
4088 /* Update SNI Tree */
William Lallemand9117de92019-10-04 00:29:42 +02004089
William Lallemand1d29c742019-10-04 00:53:29 +02004090 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 +02004091 kinfo, str, key_combos[i-1].order);
4092 if (key_combos[i-1].order < 0) {
4093 memprintf(err, "%sunable to create a sni context.\n", err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02004094 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemandfe49bb32019-10-03 23:46:33 +02004095 goto end;
4096 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05004097 node = ebmb_next(node);
4098 }
4099
4100
4101 /* Mark a default context if none exists, using the ctx that has the most shared keys */
4102 if (!bind_conf->default_ctx) {
4103 for (i = SSL_SOCK_POSSIBLE_KT_COMBOS - 1; i >= 0; i--) {
4104 if (key_combos[i].ctx) {
4105 bind_conf->default_ctx = key_combos[i].ctx;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004106 bind_conf->default_ssl_conf = ssl_conf;
William Lallemand21724f02019-11-04 17:56:13 +01004107 ckch_inst->is_default = 1;
yanbzhu08ce6ab2015-12-02 13:01:29 -05004108 break;
4109 }
4110 }
4111 }
4112
William Lallemand614ca0d2019-10-07 13:52:11 +02004113 ckch_inst->bind_conf = bind_conf;
William Lallemand150bfa82019-09-19 17:12:49 +02004114 ckch_inst->ssl_conf = ssl_conf;
yanbzhu08ce6ab2015-12-02 13:01:29 -05004115end:
4116
4117 if (names)
4118 sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
4119
yanbzhu08ce6ab2015-12-02 13:01:29 -05004120 node = ebmb_first(&sni_keytypes_map);
4121 while (node) {
4122 next = ebmb_next(node);
4123 ebmb_delete(node);
William Lallemand8ed5b962019-10-04 17:24:39 +02004124 free(ebmb_entry(node, struct sni_keytype, name));
yanbzhu08ce6ab2015-12-02 13:01:29 -05004125 node = next;
4126 }
4127
Emeric Brun054563d2019-10-17 13:16:58 +02004128 if (errcode & ERR_CODE && ckch_inst) {
William Lallemand0c6d12f2019-10-04 18:38:51 +02004129 struct sni_ctx *sc0, *sc0b;
4130
4131 /* free the SSL_CTX in case of error */
4132 for (i = 0; i < SSL_SOCK_POSSIBLE_KT_COMBOS; i++) {
4133 if (key_combos[i].ctx)
4134 SSL_CTX_free(key_combos[i].ctx);
4135 }
4136
4137 /* free the sni_ctx in case of error */
4138 list_for_each_entry_safe(sc0, sc0b, &ckch_inst->sni_ctx, by_ckch_inst) {
4139
4140 ebmb_delete(&sc0->name);
4141 LIST_DEL(&sc0->by_ckch_inst);
4142 free(sc0);
4143 }
William Lallemand614ca0d2019-10-07 13:52:11 +02004144 free(ckch_inst);
4145 ckch_inst = NULL;
William Lallemand0c6d12f2019-10-04 18:38:51 +02004146 }
4147
Emeric Brun054563d2019-10-17 13:16:58 +02004148 *ckchi = ckch_inst;
4149 return errcode;
yanbzhu08ce6ab2015-12-02 13:01:29 -05004150}
4151#else
4152/* This is a dummy, that just logs an error and returns error */
Emeric Brun054563d2019-10-17 13:16:58 +02004153static int ckch_inst_new_load_multi_store(const char *path, struct ckch_store *ckchs,
4154 struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
4155 char **sni_filter, int fcount, struct ckch_inst **ckchi, char **err)
yanbzhu08ce6ab2015-12-02 13:01:29 -05004156{
4157 memprintf(err, "%sunable to stat SSL certificate from file '%s' : %s.\n",
4158 err && *err ? *err : "", path, strerror(errno));
Emeric Brun054563d2019-10-17 13:16:58 +02004159 return ERR_ALERT | ERR_FATAL;
yanbzhu08ce6ab2015-12-02 13:01:29 -05004160}
4161
Willy Tarreau9a1ab082019-05-09 13:26:41 +02004162#endif /* #if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL: Support for loading multiple certs into a single SSL_CTX */
yanbzhu488a4d22015-12-01 15:16:07 -05004163
William Lallemand614ca0d2019-10-07 13:52:11 +02004164/*
4165 * This function allocate a ckch_inst and create its snis
Emeric Brun054563d2019-10-17 13:16:58 +02004166 *
4167 * Returns a bitfield containing the flags:
4168 * ERR_FATAL in any fatal error case
4169 * ERR_ALERT if the reason of the error is available in err
4170 * ERR_WARN if a warning is available into err
William Lallemand614ca0d2019-10-07 13:52:11 +02004171 */
Emeric Brun054563d2019-10-17 13:16:58 +02004172static int ckch_inst_new_load_store(const char *path, struct ckch_store *ckchs, struct bind_conf *bind_conf,
4173 struct ssl_bind_conf *ssl_conf, char **sni_filter, int fcount, struct ckch_inst **ckchi, char **err)
Emeric Brunfc0421f2012-09-07 17:30:07 +02004174{
William Lallemandc9402072019-05-15 15:33:54 +02004175 SSL_CTX *ctx;
William Lallemandc9402072019-05-15 15:33:54 +02004176 int i;
Emeric Brunfc0421f2012-09-07 17:30:07 +02004177 int order = 0;
4178 X509_NAME *xname;
4179 char *str;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01004180 EVP_PKEY *pkey;
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02004181 struct pkey_info kinfo = { .sig = TLSEXT_signature_anonymous, .bits = 0 };
Emeric Brunfc0421f2012-09-07 17:30:07 +02004182#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
4183 STACK_OF(GENERAL_NAME) *names;
4184#endif
William Lallemand36b84632019-07-18 19:28:17 +02004185 struct cert_key_and_chain *ckch;
William Lallemand614ca0d2019-10-07 13:52:11 +02004186 struct ckch_inst *ckch_inst = NULL;
Emeric Brun054563d2019-10-17 13:16:58 +02004187 int errcode = 0;
4188
4189 *ckchi = NULL;
William Lallemanda59191b2019-05-15 16:08:56 +02004190
William Lallemande3af8fb2019-10-08 11:36:53 +02004191 if (!ckchs || !ckchs->ckch)
Emeric Brun054563d2019-10-17 13:16:58 +02004192 return ERR_FATAL;
Emeric Brunfc0421f2012-09-07 17:30:07 +02004193
William Lallemande3af8fb2019-10-08 11:36:53 +02004194 ckch = ckchs->ckch;
William Lallemand36b84632019-07-18 19:28:17 +02004195
William Lallemand150bfa82019-09-19 17:12:49 +02004196 /* at least one of the instances is using filters during the config
4197 * parsing, that's ok to inherit this during loading on CLI */
William Lallemand920b0352019-12-04 15:33:01 +01004198 ckchs->filters |= !!fcount;
William Lallemand150bfa82019-09-19 17:12:49 +02004199
William Lallemandc9402072019-05-15 15:33:54 +02004200 ctx = SSL_CTX_new(SSLv23_server_method());
4201 if (!ctx) {
4202 memprintf(err, "%sunable to allocate SSL context for cert '%s'.\n",
4203 err && *err ? *err : "", path);
Emeric Brun054563d2019-10-17 13:16:58 +02004204 errcode |= ERR_ALERT | ERR_FATAL;
4205 goto error;
William Lallemandc9402072019-05-15 15:33:54 +02004206 }
4207
Emeric Bruna96b5822019-10-17 13:25:14 +02004208 errcode |= ssl_sock_put_ckch_into_ctx(path, ckch, ctx, err);
4209 if (errcode & ERR_CODE)
William Lallemand614ca0d2019-10-07 13:52:11 +02004210 goto error;
William Lallemand614ca0d2019-10-07 13:52:11 +02004211
4212 ckch_inst = ckch_inst_new();
4213 if (!ckch_inst) {
4214 memprintf(err, "%sunable to allocate SSL context for cert '%s'.\n",
4215 err && *err ? *err : "", path);
Emeric Brun054563d2019-10-17 13:16:58 +02004216 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemandd9199372019-10-04 15:37:05 +02004217 goto error;
William Lallemandc9402072019-05-15 15:33:54 +02004218 }
4219
William Lallemand36b84632019-07-18 19:28:17 +02004220 pkey = X509_get_pubkey(ckch->cert);
Emmanuel Hocdet05942112017-02-20 16:11:50 +01004221 if (pkey) {
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02004222 kinfo.bits = EVP_PKEY_bits(pkey);
Emmanuel Hocdet05942112017-02-20 16:11:50 +01004223 switch(EVP_PKEY_base_id(pkey)) {
4224 case EVP_PKEY_RSA:
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02004225 kinfo.sig = TLSEXT_signature_rsa;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01004226 break;
4227 case EVP_PKEY_EC:
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02004228 kinfo.sig = TLSEXT_signature_ecdsa;
4229 break;
4230 case EVP_PKEY_DSA:
4231 kinfo.sig = TLSEXT_signature_dsa;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01004232 break;
4233 }
4234 EVP_PKEY_free(pkey);
4235 }
4236
Emeric Brun50bcecc2013-04-22 13:05:23 +02004237 if (fcount) {
William Lallemandfe49bb32019-10-03 23:46:33 +02004238 while (fcount--) {
William Lallemand1d29c742019-10-04 00:53:29 +02004239 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 +02004240 if (order < 0) {
4241 memprintf(err, "%sunable to create a sni context.\n", err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02004242 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemandd9199372019-10-04 15:37:05 +02004243 goto error;
William Lallemandfe49bb32019-10-03 23:46:33 +02004244 }
4245 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004246 }
4247 else {
Emeric Brunfc0421f2012-09-07 17:30:07 +02004248#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
William Lallemand36b84632019-07-18 19:28:17 +02004249 names = X509_get_ext_d2i(ckch->cert, NID_subject_alt_name, NULL, NULL);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004250 if (names) {
4251 for (i = 0; i < sk_GENERAL_NAME_num(names); i++) {
4252 GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i);
4253 if (name->type == GEN_DNS) {
4254 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
William Lallemand1d29c742019-10-04 00:53:29 +02004255 order = ckch_inst_add_cert_sni(ctx, ckch_inst, bind_conf, ssl_conf, kinfo, str, order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004256 OPENSSL_free(str);
William Lallemandfe49bb32019-10-03 23:46:33 +02004257 if (order < 0) {
4258 memprintf(err, "%sunable to create a sni context.\n", err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02004259 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemandd9199372019-10-04 15:37:05 +02004260 goto error;
William Lallemandfe49bb32019-10-03 23:46:33 +02004261 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004262 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004263 }
4264 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004265 sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004266 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004267#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
William Lallemand36b84632019-07-18 19:28:17 +02004268 xname = X509_get_subject_name(ckch->cert);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004269 i = -1;
4270 while ((i = X509_NAME_get_index_by_NID(xname, NID_commonName, i)) != -1) {
4271 X509_NAME_ENTRY *entry = X509_NAME_get_entry(xname, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02004272 ASN1_STRING *value;
4273
4274 value = X509_NAME_ENTRY_get_data(entry);
4275 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
William Lallemand1d29c742019-10-04 00:53:29 +02004276 order = ckch_inst_add_cert_sni(ctx, ckch_inst, bind_conf, ssl_conf, kinfo, str, order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004277 OPENSSL_free(str);
William Lallemandfe49bb32019-10-03 23:46:33 +02004278 if (order < 0) {
4279 memprintf(err, "%sunable to create a sni context.\n", err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02004280 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemandd9199372019-10-04 15:37:05 +02004281 goto error;
William Lallemandfe49bb32019-10-03 23:46:33 +02004282 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004283 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004284 }
4285 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004286 /* we must not free the SSL_CTX anymore below, since it's already in
4287 * the tree, so it will be discovered and cleaned in time.
4288 */
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02004289
Emeric Brunfc0421f2012-09-07 17:30:07 +02004290#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004291 if (bind_conf->default_ctx) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02004292 memprintf(err, "%sthis version of openssl cannot load multiple SSL certificates.\n",
4293 err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02004294 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemandd9199372019-10-04 15:37:05 +02004295 goto error;
Emeric Brunfc0421f2012-09-07 17:30:07 +02004296 }
4297#endif
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004298 if (!bind_conf->default_ctx) {
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004299 bind_conf->default_ctx = ctx;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004300 bind_conf->default_ssl_conf = ssl_conf;
William Lallemand21724f02019-11-04 17:56:13 +01004301 ckch_inst->is_default = 1;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004302 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004303
William Lallemand9117de92019-10-04 00:29:42 +02004304 /* everything succeed, the ckch instance can be used */
4305 ckch_inst->bind_conf = bind_conf;
William Lallemand150bfa82019-09-19 17:12:49 +02004306 ckch_inst->ssl_conf = ssl_conf;
William Lallemand9117de92019-10-04 00:29:42 +02004307
Emeric Brun054563d2019-10-17 13:16:58 +02004308 *ckchi = ckch_inst;
4309 return errcode;
William Lallemandd9199372019-10-04 15:37:05 +02004310
4311error:
4312 /* free the allocated sni_ctxs */
William Lallemand614ca0d2019-10-07 13:52:11 +02004313 if (ckch_inst) {
William Lallemandd9199372019-10-04 15:37:05 +02004314 struct sni_ctx *sc0, *sc0b;
4315
4316 list_for_each_entry_safe(sc0, sc0b, &ckch_inst->sni_ctx, by_ckch_inst) {
4317
4318 ebmb_delete(&sc0->name);
4319 LIST_DEL(&sc0->by_ckch_inst);
4320 free(sc0);
4321 }
William Lallemand614ca0d2019-10-07 13:52:11 +02004322 free(ckch_inst);
4323 ckch_inst = NULL;
William Lallemandd9199372019-10-04 15:37:05 +02004324 }
4325 /* We only created 1 SSL_CTX so we can free it there */
4326 SSL_CTX_free(ctx);
4327
Emeric Brun054563d2019-10-17 13:16:58 +02004328 return errcode;
Emeric Brunfc0421f2012-09-07 17:30:07 +02004329}
4330
Willy Tarreau8c5414a2019-10-16 17:06:25 +02004331/* Returns a set of ERR_* flags possibly with an error in <err>. */
William Lallemand614ca0d2019-10-07 13:52:11 +02004332static int ssl_sock_load_ckchs(const char *path, struct ckch_store *ckchs,
4333 struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
4334 char **sni_filter, int fcount, char **err)
4335{
4336 struct ckch_inst *ckch_inst = NULL;
Emeric Brun054563d2019-10-17 13:16:58 +02004337 int errcode = 0;
William Lallemand614ca0d2019-10-07 13:52:11 +02004338
4339 /* we found the ckchs in the tree, we can use it directly */
4340 if (ckchs->multi)
Emeric Brun054563d2019-10-17 13:16:58 +02004341 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 +02004342 else
Emeric Brun054563d2019-10-17 13:16:58 +02004343 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 +02004344
Emeric Brun054563d2019-10-17 13:16:58 +02004345 if (errcode & ERR_CODE)
4346 return errcode;
William Lallemand614ca0d2019-10-07 13:52:11 +02004347
4348 ssl_sock_load_cert_sni(ckch_inst, bind_conf);
4349
4350 /* succeed, add the instance to the ckch_store's list of instance */
4351 LIST_ADDQ(&ckchs->ckch_inst, &ckch_inst->by_ckchs);
Emeric Brun054563d2019-10-17 13:16:58 +02004352 return errcode;
William Lallemand614ca0d2019-10-07 13:52:11 +02004353}
4354
4355
Willy Tarreaubbc91962019-10-16 16:42:19 +02004356/* Returns a set of ERR_* flags possibly with an error in <err>. */
Willy Tarreau03209342016-12-22 17:08:28 +01004357int ssl_sock_load_cert(char *path, struct bind_conf *bind_conf, char **err)
Emeric Brunfc0421f2012-09-07 17:30:07 +02004358{
Cyril Bonté3180f7b2015-01-25 00:16:08 +01004359 struct dirent **de_list;
4360 int i, n;
Emeric Brunfc0421f2012-09-07 17:30:07 +02004361 struct stat buf;
Willy Tarreauee2663b2012-12-06 11:36:59 +01004362 char *end;
4363 char fp[MAXPATHLEN+1];
Emeric Brunfc0421f2012-09-07 17:30:07 +02004364 int cfgerr = 0;
William Lallemande3af8fb2019-10-08 11:36:53 +02004365 struct ckch_store *ckchs;
Willy Tarreau9a1ab082019-05-09 13:26:41 +02004366#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
yanbzhu63ea8462015-12-09 13:35:14 -05004367 int is_bundle;
4368 int j;
4369#endif
William Lallemande3af8fb2019-10-08 11:36:53 +02004370 if ((ckchs = ckchs_lookup(path))) {
William Lallemande3af8fb2019-10-08 11:36:53 +02004371 /* we found the ckchs in the tree, we can use it directly */
Willy Tarreau8c5414a2019-10-16 17:06:25 +02004372 return ssl_sock_load_ckchs(path, ckchs, bind_conf, NULL, NULL, 0, err);
William Lallemand6af03992019-07-23 15:00:54 +02004373 }
4374
yanbzhu08ce6ab2015-12-02 13:01:29 -05004375 if (stat(path, &buf) == 0) {
William Dauchy9a8ef7f2020-01-13 17:52:49 +01004376 if (S_ISDIR(buf.st_mode) == 0) {
William Lallemande3af8fb2019-10-08 11:36:53 +02004377 ckchs = ckchs_load_cert_file(path, 0, err);
4378 if (!ckchs)
Willy Tarreaubbc91962019-10-16 16:42:19 +02004379 return ERR_ALERT | ERR_FATAL;
4380
Willy Tarreau8c5414a2019-10-16 17:06:25 +02004381 return ssl_sock_load_ckchs(path, ckchs, bind_conf, NULL, NULL, 0, err);
William Lallemand36b84632019-07-18 19:28:17 +02004382 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004383
yanbzhu08ce6ab2015-12-02 13:01:29 -05004384 /* strip trailing slashes, including first one */
4385 for (end = path + strlen(path) - 1; end >= path && *end == '/'; end--)
4386 *end = 0;
Emeric Brunfc0421f2012-09-07 17:30:07 +02004387
yanbzhu08ce6ab2015-12-02 13:01:29 -05004388 n = scandir(path, &de_list, 0, alphasort);
4389 if (n < 0) {
4390 memprintf(err, "%sunable to scan directory '%s' : %s.\n",
4391 err && *err ? *err : "", path, strerror(errno));
Willy Tarreaubbc91962019-10-16 16:42:19 +02004392 cfgerr |= ERR_ALERT | ERR_FATAL;
yanbzhu08ce6ab2015-12-02 13:01:29 -05004393 }
4394 else {
4395 for (i = 0; i < n; i++) {
4396 struct dirent *de = de_list[i];
Emeric Brun2aab7222014-06-18 18:15:09 +02004397
yanbzhu08ce6ab2015-12-02 13:01:29 -05004398 end = strrchr(de->d_name, '.');
William Lallemand3f25ae32020-02-24 16:30:12 +01004399 if (end && (!strcmp(end, ".issuer") || !strcmp(end, ".ocsp") || !strcmp(end, ".sctl") || !strcmp(end, ".key")))
yanbzhu08ce6ab2015-12-02 13:01:29 -05004400 goto ignore_entry;
Cyril Bonté3180f7b2015-01-25 00:16:08 +01004401
yanbzhu08ce6ab2015-12-02 13:01:29 -05004402 snprintf(fp, sizeof(fp), "%s/%s", path, de->d_name);
4403 if (stat(fp, &buf) != 0) {
4404 memprintf(err, "%sunable to stat SSL certificate from file '%s' : %s.\n",
4405 err && *err ? *err : "", fp, strerror(errno));
Willy Tarreaubbc91962019-10-16 16:42:19 +02004406 cfgerr |= ERR_ALERT | ERR_FATAL;
yanbzhu08ce6ab2015-12-02 13:01:29 -05004407 goto ignore_entry;
4408 }
4409 if (!S_ISREG(buf.st_mode))
4410 goto ignore_entry;
yanbzhu63ea8462015-12-09 13:35:14 -05004411
Willy Tarreau9a1ab082019-05-09 13:26:41 +02004412#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
yanbzhu63ea8462015-12-09 13:35:14 -05004413 is_bundle = 0;
4414 /* Check if current entry in directory is part of a multi-cert bundle */
4415
William Lallemand3af48e72020-02-03 17:15:52 +01004416 if ((global_ssl.extra_files & SSL_GF_BUNDLE) && end) {
yanbzhu63ea8462015-12-09 13:35:14 -05004417 for (j = 0; j < SSL_SOCK_NUM_KEYTYPES; j++) {
4418 if (!strcmp(end + 1, SSL_SOCK_KEYTYPE_NAMES[j])) {
4419 is_bundle = 1;
4420 break;
4421 }
4422 }
4423
4424 if (is_bundle) {
yanbzhu63ea8462015-12-09 13:35:14 -05004425 int dp_len;
4426
4427 dp_len = end - de->d_name;
yanbzhu63ea8462015-12-09 13:35:14 -05004428
4429 /* increment i and free de until we get to a non-bundle cert
4430 * Note here that we look at de_list[i + 1] before freeing de
Willy Tarreau05800522019-10-29 10:48:50 +01004431 * this is important since ignore_entry will free de. This also
4432 * guarantees that de->d_name continues to hold the same prefix.
yanbzhu63ea8462015-12-09 13:35:14 -05004433 */
Willy Tarreau05800522019-10-29 10:48:50 +01004434 while (i + 1 < n && !strncmp(de_list[i + 1]->d_name, de->d_name, dp_len)) {
yanbzhu63ea8462015-12-09 13:35:14 -05004435 free(de);
4436 i++;
4437 de = de_list[i];
4438 }
4439
Willy Tarreau05800522019-10-29 10:48:50 +01004440 snprintf(fp, sizeof(fp), "%s/%.*s", path, dp_len, de->d_name);
William Lallemande3af8fb2019-10-08 11:36:53 +02004441 if ((ckchs = ckchs_lookup(fp)) == NULL)
4442 ckchs = ckchs_load_cert_file(fp, 1, err);
4443 if (!ckchs)
Willy Tarreaubbc91962019-10-16 16:42:19 +02004444 cfgerr |= ERR_ALERT | ERR_FATAL;
Willy Tarreau8c5414a2019-10-16 17:06:25 +02004445 else
4446 cfgerr |= ssl_sock_load_ckchs(path, ckchs, bind_conf, NULL, NULL, 0, err);
yanbzhu63ea8462015-12-09 13:35:14 -05004447 /* Successfully processed the bundle */
4448 goto ignore_entry;
4449 }
4450 }
4451
4452#endif
William Lallemande3af8fb2019-10-08 11:36:53 +02004453 if ((ckchs = ckchs_lookup(fp)) == NULL)
4454 ckchs = ckchs_load_cert_file(fp, 0, err);
4455 if (!ckchs)
Willy Tarreaubbc91962019-10-16 16:42:19 +02004456 cfgerr |= ERR_ALERT | ERR_FATAL;
William Lallemand614ca0d2019-10-07 13:52:11 +02004457 else
Willy Tarreau8c5414a2019-10-16 17:06:25 +02004458 cfgerr |= ssl_sock_load_ckchs(path, ckchs, bind_conf, NULL, NULL, 0, err);
William Lallemand36b84632019-07-18 19:28:17 +02004459
yanbzhu08ce6ab2015-12-02 13:01:29 -05004460ignore_entry:
4461 free(de);
Cyril Bonté3180f7b2015-01-25 00:16:08 +01004462 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05004463 free(de_list);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004464 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05004465 return cfgerr;
yanbzhu08ce6ab2015-12-02 13:01:29 -05004466
William Lallemand3af48e72020-02-03 17:15:52 +01004467 } else {
4468 /* stat failed */
Willy Tarreaubbc91962019-10-16 16:42:19 +02004469
William Lallemand3af48e72020-02-03 17:15:52 +01004470 if (global_ssl.extra_files & SSL_GF_BUNDLE) {
4471 /* try to load a bundle if it is permitted */
4472 ckchs = ckchs_load_cert_file(path, 1, err);
4473 if (!ckchs)
4474 return ERR_ALERT | ERR_FATAL;
4475 cfgerr |= ssl_sock_load_ckchs(path, ckchs, bind_conf, NULL, NULL, 0, err);
4476 } else {
4477 memprintf(err, "%sunable to stat SSL certificate from file '%s' : %s.\n",
4478 err && *err ? *err : "", fp, strerror(errno));
4479 cfgerr |= ERR_ALERT | ERR_FATAL;
4480 }
4481 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05004482
Emeric Brunfc0421f2012-09-07 17:30:07 +02004483 return cfgerr;
4484}
4485
Thierry Fournier383085f2013-01-24 14:15:43 +01004486/* Make sure openssl opens /dev/urandom before the chroot. The work is only
4487 * done once. Zero is returned if the operation fails. No error is returned
4488 * if the random is said as not implemented, because we expect that openssl
4489 * will use another method once needed.
4490 */
4491static int ssl_initialize_random()
4492{
4493 unsigned char random;
4494 static int random_initialized = 0;
4495
4496 if (!random_initialized && RAND_bytes(&random, 1) != 0)
4497 random_initialized = 1;
4498
4499 return random_initialized;
4500}
4501
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004502/* release ssl bind conf */
4503void ssl_sock_free_ssl_conf(struct ssl_bind_conf *conf)
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004504{
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004505 if (conf) {
Bernard Spil13c53f82018-02-15 13:34:58 +01004506#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004507 free(conf->npn_str);
4508 conf->npn_str = NULL;
4509#endif
4510#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
4511 free(conf->alpn_str);
4512 conf->alpn_str = NULL;
4513#endif
4514 free(conf->ca_file);
4515 conf->ca_file = NULL;
4516 free(conf->crl_file);
4517 conf->crl_file = NULL;
4518 free(conf->ciphers);
4519 conf->ciphers = NULL;
Emmanuel Hocdet839af572019-05-14 16:27:35 +02004520#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02004521 free(conf->ciphersuites);
4522 conf->ciphersuites = NULL;
4523#endif
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004524 free(conf->curves);
4525 conf->curves = NULL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004526 free(conf->ecdhe);
4527 conf->ecdhe = NULL;
4528 }
4529}
4530
Willy Tarreaubbc91962019-10-16 16:42:19 +02004531/* Returns a set of ERR_* flags possibly with an error in <err>. */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004532int ssl_sock_load_cert_list_file(char *file, struct bind_conf *bind_conf, struct proxy *curproxy, char **err)
4533{
4534 char thisline[CRT_LINESIZE];
4535 char path[MAXPATHLEN+1];
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004536 FILE *f;
yanbzhu1b04e5b2015-12-02 13:54:14 -05004537 struct stat buf;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004538 int linenum = 0;
4539 int cfgerr = 0;
William Lallemande3af8fb2019-10-08 11:36:53 +02004540 struct ckch_store *ckchs;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004541
Willy Tarreauad1731d2013-04-02 17:35:58 +02004542 if ((f = fopen(file, "r")) == NULL) {
4543 memprintf(err, "cannot open file '%s' : %s", file, strerror(errno));
Willy Tarreaubbc91962019-10-16 16:42:19 +02004544 return ERR_ALERT | ERR_FATAL;
Willy Tarreauad1731d2013-04-02 17:35:58 +02004545 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004546
4547 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004548 int arg, newarg, cur_arg, i, ssl_b = 0, ssl_e = 0;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004549 char *end;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004550 char *args[MAX_CRT_ARGS + 1];
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004551 char *line = thisline;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004552 char *crt_path;
4553 struct ssl_bind_conf *ssl_conf = NULL;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004554
4555 linenum++;
4556 end = line + strlen(line);
4557 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
4558 /* Check if we reached the limit and the last char is not \n.
4559 * Watch out for the last line without the terminating '\n'!
4560 */
Willy Tarreauad1731d2013-04-02 17:35:58 +02004561 memprintf(err, "line %d too long in file '%s', limit is %d characters",
4562 linenum, file, (int)sizeof(thisline)-1);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004563 cfgerr |= ERR_ALERT | ERR_FATAL;
Willy Tarreauad1731d2013-04-02 17:35:58 +02004564 break;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004565 }
4566
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004567 arg = 0;
Emeric Brun50bcecc2013-04-22 13:05:23 +02004568 newarg = 1;
4569 while (*line) {
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004570 if (*line == '#' || *line == '\n' || *line == '\r') {
4571 /* end of string, end of loop */
4572 *line = 0;
4573 break;
Willy Tarreauded15b72020-02-25 07:51:59 +01004574 } else if (isspace((unsigned char)*line)) {
Emeric Brun50bcecc2013-04-22 13:05:23 +02004575 newarg = 1;
4576 *line = 0;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004577 } else if (*line == '[') {
4578 if (ssl_b) {
4579 memprintf(err, "too many '[' on line %d in file '%s'.", linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004580 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004581 break;
4582 }
4583 if (!arg) {
4584 memprintf(err, "file must start with a cert on line %d in file '%s'", linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004585 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004586 break;
4587 }
4588 ssl_b = arg;
4589 newarg = 1;
4590 *line = 0;
4591 } else if (*line == ']') {
4592 if (ssl_e) {
4593 memprintf(err, "too many ']' on line %d in file '%s'.", linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004594 cfgerr |= ERR_ALERT | ERR_FATAL;
Emeric Brun50bcecc2013-04-22 13:05:23 +02004595 break;
4596 }
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004597 if (!ssl_b) {
4598 memprintf(err, "missing '[' in line %d in file '%s'.", linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004599 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004600 break;
4601 }
4602 ssl_e = arg;
4603 newarg = 1;
4604 *line = 0;
4605 } else if (newarg) {
4606 if (arg == MAX_CRT_ARGS) {
4607 memprintf(err, "too many args on line %d in file '%s'.", linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004608 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004609 break;
4610 }
Emeric Brun50bcecc2013-04-22 13:05:23 +02004611 newarg = 0;
4612 args[arg++] = line;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004613 }
Emeric Brun50bcecc2013-04-22 13:05:23 +02004614 line++;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004615 }
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02004616 if (cfgerr)
4617 break;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004618 args[arg++] = line;
Willy Tarreauad1731d2013-04-02 17:35:58 +02004619
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004620 /* empty line */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004621 if (!*args[0])
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004622 continue;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004623
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004624 crt_path = args[0];
4625 if (*crt_path != '/' && global_ssl.crt_base) {
4626 if ((strlen(global_ssl.crt_base) + 1 + strlen(crt_path)) > MAXPATHLEN) {
4627 memprintf(err, "'%s' : path too long on line %d in file '%s'",
4628 crt_path, linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004629 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004630 break;
4631 }
4632 snprintf(path, sizeof(path), "%s/%s", global_ssl.crt_base, crt_path);
4633 crt_path = path;
4634 }
4635
4636 ssl_conf = calloc(1, sizeof *ssl_conf);
4637 cur_arg = ssl_b ? ssl_b : 1;
4638 while (cur_arg < ssl_e) {
4639 newarg = 0;
4640 for (i = 0; ssl_bind_kws[i].kw != NULL; i++) {
4641 if (strcmp(ssl_bind_kws[i].kw, args[cur_arg]) == 0) {
4642 newarg = 1;
Willy Tarreaubbc91962019-10-16 16:42:19 +02004643 cfgerr |= ssl_bind_kws[i].parse(args, cur_arg, curproxy, ssl_conf, err);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004644 if (cur_arg + 1 + ssl_bind_kws[i].skip > ssl_e) {
4645 memprintf(err, "ssl args out of '[]' for %s on line %d in file '%s'",
4646 args[cur_arg], linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004647 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004648 }
4649 cur_arg += 1 + ssl_bind_kws[i].skip;
4650 break;
4651 }
4652 }
4653 if (!cfgerr && !newarg) {
4654 memprintf(err, "unknown ssl keyword %s on line %d in file '%s'.",
4655 args[cur_arg], linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004656 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004657 break;
4658 }
4659 }
Willy Tarreaubbc91962019-10-16 16:42:19 +02004660
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004661 if (cfgerr) {
4662 ssl_sock_free_ssl_conf(ssl_conf);
4663 free(ssl_conf);
4664 ssl_conf = NULL;
4665 break;
4666 }
4667
William Lallemande3af8fb2019-10-08 11:36:53 +02004668 if ((ckchs = ckchs_lookup(crt_path)) == NULL) {
William Lallemandeed4bf22019-10-10 11:38:13 +02004669 if (stat(crt_path, &buf) == 0)
William Lallemande3af8fb2019-10-08 11:36:53 +02004670 ckchs = ckchs_load_cert_file(crt_path, 0, err);
Emmanuel Hocdet1503e052019-07-31 18:30:33 +02004671 else
William Lallemande3af8fb2019-10-08 11:36:53 +02004672 ckchs = ckchs_load_cert_file(crt_path, 1, err);
yanbzhu1b04e5b2015-12-02 13:54:14 -05004673 }
4674
Willy Tarreau8c5414a2019-10-16 17:06:25 +02004675 if (!ckchs)
Willy Tarreaubbc91962019-10-16 16:42:19 +02004676 cfgerr |= ERR_ALERT | ERR_FATAL;
Willy Tarreau8c5414a2019-10-16 17:06:25 +02004677 else
4678 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 +02004679
Willy Tarreauad1731d2013-04-02 17:35:58 +02004680 if (cfgerr) {
4681 memprintf(err, "error processing line %d in file '%s' : %s", linenum, file, *err);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004682 break;
Willy Tarreauad1731d2013-04-02 17:35:58 +02004683 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004684 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004685 fclose(f);
4686 return cfgerr;
4687}
4688
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004689/* Create an initial CTX used to start the SSL connection before switchctx */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004690static int
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004691ssl_sock_initial_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02004692{
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004693 SSL_CTX *ctx = NULL;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004694 long options =
Emeric Brunfc0421f2012-09-07 17:30:07 +02004695 SSL_OP_ALL | /* all known workarounds for bugs */
4696 SSL_OP_NO_SSLv2 |
4697 SSL_OP_NO_COMPRESSION |
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02004698 SSL_OP_SINGLE_DH_USE |
Emeric Brun2b58d042012-09-20 17:10:03 +02004699 SSL_OP_SINGLE_ECDH_USE |
Emeric Brun3c4bc6e2012-10-04 18:44:19 +02004700 SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION |
Lukas Tribus926594f2018-05-18 17:55:57 +02004701 SSL_OP_PRIORITIZE_CHACHA |
Emeric Brun3c4bc6e2012-10-04 18:44:19 +02004702 SSL_OP_CIPHER_SERVER_PREFERENCE;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004703 long mode =
Emeric Brunfc0421f2012-09-07 17:30:07 +02004704 SSL_MODE_ENABLE_PARTIAL_WRITE |
4705 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
Willy Tarreau396a1862014-11-13 14:06:52 +01004706 SSL_MODE_RELEASE_BUFFERS |
4707 SSL_MODE_SMALL_BUFFERS;
Emmanuel Hocdet43664762017-08-09 18:26:20 +02004708 struct tls_version_filter *conf_ssl_methods = &bind_conf->ssl_conf.ssl_methods;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004709 int i, min, max, hole;
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004710 int flags = MC_SSL_O_ALL;
4711 int cfgerr = 0;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004712
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004713 ctx = SSL_CTX_new(SSLv23_server_method());
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004714 bind_conf->initial_ctx = ctx;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004715
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004716 if (conf_ssl_methods->flags && (conf_ssl_methods->min || conf_ssl_methods->max))
Christopher Faulet767a84b2017-11-24 16:50:31 +01004717 ha_warning("Proxy '%s': no-sslv3/no-tlsv1x are ignored for bind '%s' at [%s:%d]. "
4718 "Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
4719 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004720 else
4721 flags = conf_ssl_methods->flags;
4722
Emmanuel Hocdetbd695fe2017-05-15 15:53:41 +02004723 min = conf_ssl_methods->min;
4724 max = conf_ssl_methods->max;
4725 /* start with TLSv10 to remove SSLv3 per default */
4726 if (!min && (!max || max >= CONF_TLSV10))
4727 min = CONF_TLSV10;
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004728 /* Real min and max should be determinate with configuration and openssl's capabilities */
Emmanuel Hocdetbd695fe2017-05-15 15:53:41 +02004729 if (min)
4730 flags |= (methodVersions[min].flag - 1);
4731 if (max)
4732 flags |= ~((methodVersions[max].flag << 1) - 1);
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004733 /* find min, max and holes */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004734 min = max = CONF_TLSV_NONE;
4735 hole = 0;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004736 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004737 /* version is in openssl && version not disable in configuration */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004738 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004739 if (min) {
4740 if (hole) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004741 ha_warning("Proxy '%s': SSL/TLS versions range not contiguous for bind '%s' at [%s:%d]. "
4742 "Hole find for %s. Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
4743 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line,
4744 methodVersions[hole].name);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004745 hole = 0;
4746 }
4747 max = i;
4748 }
4749 else {
4750 min = max = i;
4751 }
4752 }
4753 else {
4754 if (min)
4755 hole = i;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004756 }
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004757 if (!min) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004758 ha_alert("Proxy '%s': all SSL/TLS versions are disabled for bind '%s' at [%s:%d].\n",
4759 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004760 cfgerr += 1;
4761 }
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02004762 /* save real min/max in bind_conf */
4763 conf_ssl_methods->min = min;
4764 conf_ssl_methods->max = max;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004765
Willy Tarreau9a1ab082019-05-09 13:26:41 +02004766#if (HA_OPENSSL_VERSION_NUMBER < 0x1010000fL)
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004767 /* Keep force-xxx implementation as it is in older haproxy. It's a
Joseph Herlant017b3da2018-11-15 09:07:59 -08004768 precautionary measure to avoid any surprise with older openssl version. */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004769 if (min == max)
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004770 methodVersions[min].ctx_set_version(ctx, SET_SERVER);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004771 else
4772 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
4773 if (flags & methodVersions[i].flag)
4774 options |= methodVersions[i].option;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004775#else /* openssl >= 1.1.0 */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004776 /* set the max_version is required to cap TLS version or activate new TLS (v1.3) */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004777 methodVersions[min].ctx_set_version(ctx, SET_MIN);
4778 methodVersions[max].ctx_set_version(ctx, SET_MAX);
Emeric Brunfa5c5c82017-04-28 16:19:51 +02004779#endif
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004780
4781 if (bind_conf->ssl_options & BC_SSL_O_NO_TLS_TICKETS)
4782 options |= SSL_OP_NO_TICKET;
4783 if (bind_conf->ssl_options & BC_SSL_O_PREF_CLIE_CIPH)
4784 options &= ~SSL_OP_CIPHER_SERVER_PREFERENCE;
Dirkjan Bussink526894f2019-01-21 09:35:03 -08004785
4786#ifdef SSL_OP_NO_RENEGOTIATION
4787 options |= SSL_OP_NO_RENEGOTIATION;
4788#endif
4789
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004790 SSL_CTX_set_options(ctx, options);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004791
Willy Tarreau5db847a2019-05-09 14:13:35 +02004792#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004793 if (global_ssl.async)
4794 mode |= SSL_MODE_ASYNC;
4795#endif
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004796 SSL_CTX_set_mode(ctx, mode);
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004797 if (global_ssl.life_time)
4798 SSL_CTX_set_timeout(ctx, global_ssl.life_time);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004799
4800#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
4801#ifdef OPENSSL_IS_BORINGSSL
4802 SSL_CTX_set_select_certificate_cb(ctx, ssl_sock_switchctx_cbk);
4803 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_err_cbk);
Ilya Shipitsine9ff8992020-01-19 12:20:14 +05004804#elif defined(SSL_OP_NO_ANTI_REPLAY)
Olivier Houchard545989f2019-12-17 15:39:54 +01004805 if (bind_conf->ssl_conf.early_data)
Olivier Houchard51088ce2019-01-02 18:46:41 +01004806 SSL_CTX_set_options(ctx, SSL_OP_NO_ANTI_REPLAY);
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02004807 SSL_CTX_set_client_hello_cb(ctx, ssl_sock_switchctx_cbk, NULL);
4808 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_err_cbk);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004809#else
4810 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_cbk);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004811#endif
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02004812 SSL_CTX_set_tlsext_servername_arg(ctx, bind_conf);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004813#endif
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004814 return cfgerr;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004815}
4816
William Lallemand4f45bb92017-10-30 20:08:51 +01004817
4818static inline void sh_ssl_sess_free_blocks(struct shared_block *first, struct shared_block *block)
4819{
4820 if (first == block) {
4821 struct sh_ssl_sess_hdr *sh_ssl_sess = (struct sh_ssl_sess_hdr *)first->data;
4822 if (first->len > 0)
4823 sh_ssl_sess_tree_delete(sh_ssl_sess);
4824 }
4825}
4826
4827/* return first block from sh_ssl_sess */
4828static inline struct shared_block *sh_ssl_sess_first_block(struct sh_ssl_sess_hdr *sh_ssl_sess)
4829{
4830 return (struct shared_block *)((unsigned char *)sh_ssl_sess - ((struct shared_block *)NULL)->data);
4831
4832}
4833
4834/* store a session into the cache
4835 * s_id : session id padded with zero to SSL_MAX_SSL_SESSION_ID_LENGTH
4836 * data: asn1 encoded session
4837 * data_len: asn1 encoded session length
4838 * Returns 1 id session was stored (else 0)
4839 */
4840static int sh_ssl_sess_store(unsigned char *s_id, unsigned char *data, int data_len)
4841{
4842 struct shared_block *first;
4843 struct sh_ssl_sess_hdr *sh_ssl_sess, *oldsh_ssl_sess;
4844
Frédéric Lécaille0bec8072018-10-22 17:55:57 +02004845 first = shctx_row_reserve_hot(ssl_shctx, NULL, data_len + sizeof(struct sh_ssl_sess_hdr));
William Lallemand4f45bb92017-10-30 20:08:51 +01004846 if (!first) {
4847 /* Could not retrieve enough free blocks to store that session */
4848 return 0;
4849 }
4850
4851 /* STORE the key in the first elem */
4852 sh_ssl_sess = (struct sh_ssl_sess_hdr *)first->data;
4853 memcpy(sh_ssl_sess->key_data, s_id, SSL_MAX_SSL_SESSION_ID_LENGTH);
4854 first->len = sizeof(struct sh_ssl_sess_hdr);
4855
4856 /* it returns the already existing node
4857 or current node if none, never returns null */
4858 oldsh_ssl_sess = sh_ssl_sess_tree_insert(sh_ssl_sess);
4859 if (oldsh_ssl_sess != sh_ssl_sess) {
4860 /* NOTE: Row couldn't be in use because we lock read & write function */
4861 /* release the reserved row */
4862 shctx_row_dec_hot(ssl_shctx, first);
4863 /* replace the previous session already in the tree */
4864 sh_ssl_sess = oldsh_ssl_sess;
4865 /* ignore the previous session data, only use the header */
4866 first = sh_ssl_sess_first_block(sh_ssl_sess);
4867 shctx_row_inc_hot(ssl_shctx, first);
4868 first->len = sizeof(struct sh_ssl_sess_hdr);
4869 }
4870
Frédéric Lécaille0bec8072018-10-22 17:55:57 +02004871 if (shctx_row_data_append(ssl_shctx, first, NULL, data, data_len) < 0) {
William Lallemand99b90af2018-01-03 19:15:51 +01004872 shctx_row_dec_hot(ssl_shctx, first);
William Lallemand4f45bb92017-10-30 20:08:51 +01004873 return 0;
William Lallemand99b90af2018-01-03 19:15:51 +01004874 }
4875
4876 shctx_row_dec_hot(ssl_shctx, first);
William Lallemand4f45bb92017-10-30 20:08:51 +01004877
4878 return 1;
4879}
William Lallemanded0b5ad2017-10-30 19:36:36 +01004880
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004881/* SSL callback used when a new session is created while connecting to a server */
4882static int ssl_sess_new_srv_cb(SSL *ssl, SSL_SESSION *sess)
4883{
Thierry FOURNIER28962c92018-06-17 21:37:05 +02004884 struct connection *conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Olivier Houcharde6060c52017-11-16 17:42:52 +01004885 struct server *s;
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004886
Willy Tarreau07d94e42018-09-20 10:57:52 +02004887 s = __objt_server(conn->target);
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004888
Olivier Houcharde6060c52017-11-16 17:42:52 +01004889 if (!(s->ssl_ctx.options & SRV_SSL_O_NO_REUSE)) {
4890 int len;
4891 unsigned char *ptr;
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004892
Olivier Houcharde6060c52017-11-16 17:42:52 +01004893 len = i2d_SSL_SESSION(sess, NULL);
4894 if (s->ssl_ctx.reused_sess[tid].ptr && s->ssl_ctx.reused_sess[tid].allocated_size >= len) {
4895 ptr = s->ssl_ctx.reused_sess[tid].ptr;
4896 } else {
4897 free(s->ssl_ctx.reused_sess[tid].ptr);
4898 ptr = s->ssl_ctx.reused_sess[tid].ptr = malloc(len);
4899 s->ssl_ctx.reused_sess[tid].allocated_size = len;
4900 }
4901 if (s->ssl_ctx.reused_sess[tid].ptr) {
4902 s->ssl_ctx.reused_sess[tid].size = i2d_SSL_SESSION(sess,
4903 &ptr);
4904 }
4905 } else {
4906 free(s->ssl_ctx.reused_sess[tid].ptr);
4907 s->ssl_ctx.reused_sess[tid].ptr = NULL;
4908 }
4909
4910 return 0;
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004911}
4912
Olivier Houcharde6060c52017-11-16 17:42:52 +01004913
William Lallemanded0b5ad2017-10-30 19:36:36 +01004914/* SSL callback used on new session creation */
William Lallemand4f45bb92017-10-30 20:08:51 +01004915int sh_ssl_sess_new_cb(SSL *ssl, SSL_SESSION *sess)
William Lallemanded0b5ad2017-10-30 19:36:36 +01004916{
4917 unsigned char encsess[SHSESS_MAX_DATA_LEN]; /* encoded session */
4918 unsigned char encid[SSL_MAX_SSL_SESSION_ID_LENGTH]; /* encoded id */
4919 unsigned char *p;
4920 int data_len;
Emeric Bruneb469652019-10-08 18:27:37 +02004921 unsigned int sid_length;
William Lallemanded0b5ad2017-10-30 19:36:36 +01004922 const unsigned char *sid_data;
William Lallemanded0b5ad2017-10-30 19:36:36 +01004923
4924 /* Session id is already stored in to key and session id is known
4925 * so we dont store it to keep size.
Emeric Bruneb469652019-10-08 18:27:37 +02004926 * note: SSL_SESSION_set1_id is using
4927 * a memcpy so we need to use a different pointer
4928 * than sid_data or sid_ctx_data to avoid valgrind
4929 * complaining.
William Lallemanded0b5ad2017-10-30 19:36:36 +01004930 */
4931
4932 sid_data = SSL_SESSION_get_id(sess, &sid_length);
Emeric Bruneb469652019-10-08 18:27:37 +02004933
4934 /* copy value in an other buffer */
4935 memcpy(encid, sid_data, sid_length);
4936
4937 /* pad with 0 */
4938 if (sid_length < SSL_MAX_SSL_SESSION_ID_LENGTH)
4939 memset(encid + sid_length, 0, SSL_MAX_SSL_SESSION_ID_LENGTH-sid_length);
4940
4941 /* force length to zero to avoid ASN1 encoding */
4942 SSL_SESSION_set1_id(sess, encid, 0);
4943
4944 /* force length to zero to avoid ASN1 encoding */
4945 SSL_SESSION_set1_id_context(sess, (const unsigned char *)SHCTX_APPNAME, 0);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004946
4947 /* check if buffer is large enough for the ASN1 encoded session */
4948 data_len = i2d_SSL_SESSION(sess, NULL);
4949 if (data_len > SHSESS_MAX_DATA_LEN)
4950 goto err;
4951
4952 p = encsess;
4953
4954 /* process ASN1 session encoding before the lock */
4955 i2d_SSL_SESSION(sess, &p);
4956
William Lallemanded0b5ad2017-10-30 19:36:36 +01004957
William Lallemanda3c77cf2017-10-30 23:44:40 +01004958 shctx_lock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004959 /* store to cache */
William Lallemand4f45bb92017-10-30 20:08:51 +01004960 sh_ssl_sess_store(encid, encsess, data_len);
William Lallemanda3c77cf2017-10-30 23:44:40 +01004961 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004962err:
4963 /* reset original length values */
Emeric Bruneb469652019-10-08 18:27:37 +02004964 SSL_SESSION_set1_id(sess, encid, sid_length);
4965 SSL_SESSION_set1_id_context(sess, (const unsigned char *)SHCTX_APPNAME, strlen(SHCTX_APPNAME));
William Lallemanded0b5ad2017-10-30 19:36:36 +01004966
4967 return 0; /* do not increment session reference count */
4968}
4969
4970/* SSL callback used on lookup an existing session cause none found in internal cache */
William Lallemand4f45bb92017-10-30 20:08:51 +01004971SSL_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 +01004972{
William Lallemand4f45bb92017-10-30 20:08:51 +01004973 struct sh_ssl_sess_hdr *sh_ssl_sess;
William Lallemanded0b5ad2017-10-30 19:36:36 +01004974 unsigned char data[SHSESS_MAX_DATA_LEN], *p;
4975 unsigned char tmpkey[SSL_MAX_SSL_SESSION_ID_LENGTH];
William Lallemanded0b5ad2017-10-30 19:36:36 +01004976 SSL_SESSION *sess;
William Lallemand4f45bb92017-10-30 20:08:51 +01004977 struct shared_block *first;
William Lallemanded0b5ad2017-10-30 19:36:36 +01004978
4979 global.shctx_lookups++;
4980
4981 /* allow the session to be freed automatically by openssl */
4982 *do_copy = 0;
4983
4984 /* tree key is zeros padded sessionid */
4985 if (key_len < SSL_MAX_SSL_SESSION_ID_LENGTH) {
4986 memcpy(tmpkey, key, key_len);
4987 memset(tmpkey + key_len, 0, SSL_MAX_SSL_SESSION_ID_LENGTH - key_len);
4988 key = tmpkey;
4989 }
4990
4991 /* lock cache */
William Lallemanda3c77cf2017-10-30 23:44:40 +01004992 shctx_lock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004993
4994 /* lookup for session */
William Lallemand4f45bb92017-10-30 20:08:51 +01004995 sh_ssl_sess = sh_ssl_sess_tree_lookup(key);
4996 if (!sh_ssl_sess) {
William Lallemanded0b5ad2017-10-30 19:36:36 +01004997 /* no session found: unlock cache and exit */
William Lallemanda3c77cf2017-10-30 23:44:40 +01004998 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004999 global.shctx_misses++;
5000 return NULL;
5001 }
5002
William Lallemand4f45bb92017-10-30 20:08:51 +01005003 /* sh_ssl_sess (shared_block->data) is at the end of shared_block */
5004 first = sh_ssl_sess_first_block(sh_ssl_sess);
William Lallemanded0b5ad2017-10-30 19:36:36 +01005005
William Lallemand4f45bb92017-10-30 20:08:51 +01005006 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 +01005007
William Lallemanda3c77cf2017-10-30 23:44:40 +01005008 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01005009
5010 /* decode ASN1 session */
5011 p = data;
William Lallemand4f45bb92017-10-30 20:08:51 +01005012 sess = d2i_SSL_SESSION(NULL, (const unsigned char **)&p, first->len-sizeof(struct sh_ssl_sess_hdr));
William Lallemanded0b5ad2017-10-30 19:36:36 +01005013 /* Reset session id and session id contenxt */
5014 if (sess) {
5015 SSL_SESSION_set1_id(sess, key, key_len);
5016 SSL_SESSION_set1_id_context(sess, (const unsigned char *)SHCTX_APPNAME, strlen(SHCTX_APPNAME));
5017 }
5018
5019 return sess;
5020}
5021
William Lallemand4f45bb92017-10-30 20:08:51 +01005022
William Lallemanded0b5ad2017-10-30 19:36:36 +01005023/* SSL callback used to signal session is no more used in internal cache */
William Lallemand4f45bb92017-10-30 20:08:51 +01005024void sh_ssl_sess_remove_cb(SSL_CTX *ctx, SSL_SESSION *sess)
William Lallemanded0b5ad2017-10-30 19:36:36 +01005025{
William Lallemand4f45bb92017-10-30 20:08:51 +01005026 struct sh_ssl_sess_hdr *sh_ssl_sess;
William Lallemanded0b5ad2017-10-30 19:36:36 +01005027 unsigned char tmpkey[SSL_MAX_SSL_SESSION_ID_LENGTH];
5028 unsigned int sid_length;
5029 const unsigned char *sid_data;
5030 (void)ctx;
5031
5032 sid_data = SSL_SESSION_get_id(sess, &sid_length);
5033 /* tree key is zeros padded sessionid */
5034 if (sid_length < SSL_MAX_SSL_SESSION_ID_LENGTH) {
5035 memcpy(tmpkey, sid_data, sid_length);
5036 memset(tmpkey+sid_length, 0, SSL_MAX_SSL_SESSION_ID_LENGTH - sid_length);
5037 sid_data = tmpkey;
5038 }
5039
William Lallemanda3c77cf2017-10-30 23:44:40 +01005040 shctx_lock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01005041
5042 /* lookup for session */
William Lallemand4f45bb92017-10-30 20:08:51 +01005043 sh_ssl_sess = sh_ssl_sess_tree_lookup(sid_data);
5044 if (sh_ssl_sess) {
William Lallemanded0b5ad2017-10-30 19:36:36 +01005045 /* free session */
William Lallemand4f45bb92017-10-30 20:08:51 +01005046 sh_ssl_sess_tree_delete(sh_ssl_sess);
William Lallemanded0b5ad2017-10-30 19:36:36 +01005047 }
5048
5049 /* unlock cache */
William Lallemanda3c77cf2017-10-30 23:44:40 +01005050 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01005051}
5052
5053/* Set session cache mode to server and disable openssl internal cache.
5054 * Set shared cache callbacks on an ssl context.
5055 * Shared context MUST be firstly initialized */
William Lallemand4f45bb92017-10-30 20:08:51 +01005056void ssl_set_shctx(SSL_CTX *ctx)
William Lallemanded0b5ad2017-10-30 19:36:36 +01005057{
5058 SSL_CTX_set_session_id_context(ctx, (const unsigned char *)SHCTX_APPNAME, strlen(SHCTX_APPNAME));
5059
5060 if (!ssl_shctx) {
5061 SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF);
5062 return;
5063 }
5064
5065 SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_SERVER |
5066 SSL_SESS_CACHE_NO_INTERNAL |
5067 SSL_SESS_CACHE_NO_AUTO_CLEAR);
5068
5069 /* Set callbacks */
William Lallemand4f45bb92017-10-30 20:08:51 +01005070 SSL_CTX_sess_set_new_cb(ctx, sh_ssl_sess_new_cb);
5071 SSL_CTX_sess_set_get_cb(ctx, sh_ssl_sess_get_cb);
5072 SSL_CTX_sess_set_remove_cb(ctx, sh_ssl_sess_remove_cb);
William Lallemanded0b5ad2017-10-30 19:36:36 +01005073}
5074
William Lallemand8b453912019-11-21 15:48:10 +01005075/*
5076 * This function applies the SSL configuration on a SSL_CTX
5077 * It returns an error code and fills the <err> buffer
5078 */
5079int 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 +01005080{
5081 struct proxy *curproxy = bind_conf->frontend;
5082 int cfgerr = 0;
5083 int verify = SSL_VERIFY_NONE;
Willy Tarreau5d4cafb2018-01-04 18:55:19 +01005084 struct ssl_bind_conf __maybe_unused *ssl_conf_cur;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005085 const char *conf_ciphers;
Emmanuel Hocdet839af572019-05-14 16:27:35 +02005086#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02005087 const char *conf_ciphersuites;
5088#endif
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01005089 const char *conf_curves = NULL;
Emeric Brunfc0421f2012-09-07 17:30:07 +02005090
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02005091 if (ssl_conf) {
5092 struct tls_version_filter *conf_ssl_methods = &ssl_conf->ssl_methods;
5093 int i, min, max;
5094 int flags = MC_SSL_O_ALL;
5095
5096 /* Real min and max should be determinate with configuration and openssl's capabilities */
Emmanuel Hocdet43664762017-08-09 18:26:20 +02005097 min = conf_ssl_methods->min ? conf_ssl_methods->min : bind_conf->ssl_conf.ssl_methods.min;
5098 max = conf_ssl_methods->max ? conf_ssl_methods->max : bind_conf->ssl_conf.ssl_methods.max;
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02005099 if (min)
5100 flags |= (methodVersions[min].flag - 1);
5101 if (max)
5102 flags |= ~((methodVersions[max].flag << 1) - 1);
5103 min = max = CONF_TLSV_NONE;
5104 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
5105 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
5106 if (min)
5107 max = i;
5108 else
5109 min = max = i;
5110 }
5111 /* save real min/max */
5112 conf_ssl_methods->min = min;
5113 conf_ssl_methods->max = max;
5114 if (!min) {
Tim Duesterhus93128532019-11-23 23:45:10 +01005115 memprintf(err, "%sProxy '%s': all SSL/TLS versions are disabled for bind '%s' at [%s:%d].\n",
5116 err && *err ? *err : "", bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
William Lallemand8b453912019-11-21 15:48:10 +01005117 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02005118 }
5119 }
5120
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005121 switch ((ssl_conf && ssl_conf->verify) ? ssl_conf->verify : bind_conf->ssl_conf.verify) {
Emeric Brun850efd52014-01-29 12:24:34 +01005122 case SSL_SOCK_VERIFY_NONE:
5123 verify = SSL_VERIFY_NONE;
5124 break;
5125 case SSL_SOCK_VERIFY_OPTIONAL:
5126 verify = SSL_VERIFY_PEER;
5127 break;
5128 case SSL_SOCK_VERIFY_REQUIRED:
5129 verify = SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
5130 break;
5131 }
5132 SSL_CTX_set_verify(ctx, verify, ssl_sock_bind_verifycbk);
5133 if (verify & SSL_VERIFY_PEER) {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005134 char *ca_file = (ssl_conf && ssl_conf->ca_file) ? ssl_conf->ca_file : bind_conf->ssl_conf.ca_file;
5135 char *crl_file = (ssl_conf && ssl_conf->crl_file) ? ssl_conf->crl_file : bind_conf->ssl_conf.crl_file;
5136 if (ca_file) {
Emmanuel Hocdetd4f9a602019-10-24 11:32:47 +02005137 /* set CAfile to verify */
5138 if (!ssl_set_verify_locations_file(ctx, ca_file)) {
5139 memprintf(err, "%sProxy '%s': unable to set CA file '%s' for bind '%s' at [%s:%d].\n",
Tim Duesterhus93128532019-11-23 23:45:10 +01005140 err && *err ? *err : "", curproxy->id, ca_file, bind_conf->arg, bind_conf->file, bind_conf->line);
William Lallemand8b453912019-11-21 15:48:10 +01005141 cfgerr |= ERR_ALERT | ERR_FATAL;
Emeric Brund94b3fe2012-09-20 18:23:56 +02005142 }
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02005143 if (!((ssl_conf && ssl_conf->no_ca_names) || bind_conf->ssl_conf.no_ca_names)) {
5144 /* set CA names for client cert request, function returns void */
Emmanuel Hocdet129d3282019-10-24 18:08:51 +02005145 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 +02005146 }
Emeric Brund94b3fe2012-09-20 18:23:56 +02005147 }
Emeric Brun850efd52014-01-29 12:24:34 +01005148 else {
Tim Duesterhus93128532019-11-23 23:45:10 +01005149 memprintf(err, "%sProxy '%s': verify is enabled but no CA file specified for bind '%s' at [%s:%d].\n",
5150 err && *err ? *err : "", curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
William Lallemand8b453912019-11-21 15:48:10 +01005151 cfgerr |= ERR_ALERT | ERR_FATAL;
Emeric Brun850efd52014-01-29 12:24:34 +01005152 }
Emeric Brun051cdab2012-10-02 19:25:50 +02005153#ifdef X509_V_FLAG_CRL_CHECK
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005154 if (crl_file) {
Emeric Brund94b3fe2012-09-20 18:23:56 +02005155 X509_STORE *store = SSL_CTX_get_cert_store(ctx);
5156
Emmanuel Hocdetb270e812019-11-21 19:09:31 +01005157 if (!ssl_set_cert_crl_file(store, crl_file)) {
Tim Duesterhus93128532019-11-23 23:45:10 +01005158 memprintf(err, "%sProxy '%s': unable to configure CRL file '%s' for bind '%s' at [%s:%d].\n",
5159 err && *err ? *err : "", curproxy->id, crl_file, bind_conf->arg, bind_conf->file, bind_conf->line);
William Lallemand8b453912019-11-21 15:48:10 +01005160 cfgerr |= ERR_ALERT | ERR_FATAL;
Emeric Brund94b3fe2012-09-20 18:23:56 +02005161 }
Emeric Brun561e5742012-10-02 15:20:55 +02005162 else {
5163 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
5164 }
Emeric Brund94b3fe2012-09-20 18:23:56 +02005165 }
Emeric Brun051cdab2012-10-02 19:25:50 +02005166#endif
Emeric Brun644cde02012-12-14 11:21:13 +01005167 ERR_clear_error();
Emeric Brund94b3fe2012-09-20 18:23:56 +02005168 }
Nenad Merdanovic05552d42015-02-27 19:56:49 +01005169#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
Nenad Merdanovic146defa2015-05-09 08:46:00 +02005170 if(bind_conf->keys_ref) {
Nenad Merdanovic05552d42015-02-27 19:56:49 +01005171 if (!SSL_CTX_set_tlsext_ticket_key_cb(ctx, ssl_tlsext_ticket_key_cb)) {
Tim Duesterhus93128532019-11-23 23:45:10 +01005172 memprintf(err, "%sProxy '%s': unable to set callback for TLS ticket validation for bind '%s' at [%s:%d].\n",
5173 err && *err ? *err : "", curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
William Lallemand8b453912019-11-21 15:48:10 +01005174 cfgerr |= ERR_ALERT | ERR_FATAL;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01005175 }
5176 }
5177#endif
5178
William Lallemand4f45bb92017-10-30 20:08:51 +01005179 ssl_set_shctx(ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005180 conf_ciphers = (ssl_conf && ssl_conf->ciphers) ? ssl_conf->ciphers : bind_conf->ssl_conf.ciphers;
5181 if (conf_ciphers &&
5182 !SSL_CTX_set_cipher_list(ctx, conf_ciphers)) {
Tim Duesterhus93128532019-11-23 23:45:10 +01005183 memprintf(err, "%sProxy '%s': unable to set SSL cipher list to '%s' for bind '%s' at [%s:%d].\n",
5184 err && *err ? *err : "", curproxy->id, conf_ciphers, bind_conf->arg, bind_conf->file, bind_conf->line);
William Lallemand8b453912019-11-21 15:48:10 +01005185 cfgerr |= ERR_ALERT | ERR_FATAL;
Emeric Brunfc0421f2012-09-07 17:30:07 +02005186 }
5187
Emmanuel Hocdet839af572019-05-14 16:27:35 +02005188#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02005189 conf_ciphersuites = (ssl_conf && ssl_conf->ciphersuites) ? ssl_conf->ciphersuites : bind_conf->ssl_conf.ciphersuites;
5190 if (conf_ciphersuites &&
5191 !SSL_CTX_set_ciphersuites(ctx, conf_ciphersuites)) {
Tim Duesterhus93128532019-11-23 23:45:10 +01005192 memprintf(err, "%sProxy '%s': unable to set TLS 1.3 cipher suites to '%s' for bind '%s' at [%s:%d].\n",
5193 err && *err ? *err : "", curproxy->id, conf_ciphersuites, bind_conf->arg, bind_conf->file, bind_conf->line);
William Lallemand8b453912019-11-21 15:48:10 +01005194 cfgerr |= ERR_ALERT | ERR_FATAL;
Dirkjan Bussink415150f2018-09-14 11:14:21 +02005195 }
5196#endif
5197
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01005198#ifndef OPENSSL_NO_DH
Remi Gacogne47783ef2015-05-29 15:53:22 +02005199 /* If tune.ssl.default-dh-param has not been set,
5200 neither has ssl-default-dh-file and no static DH
5201 params were in the certificate file. */
Willy Tarreauef934602016-12-22 23:12:01 +01005202 if (global_ssl.default_dh_param == 0 &&
Remi Gacogne47783ef2015-05-29 15:53:22 +02005203 global_dh == NULL &&
Remi Gacogne4f902b82015-05-28 16:23:00 +02005204 (ssl_dh_ptr_index == -1 ||
5205 SSL_CTX_get_ex_data(ctx, ssl_dh_ptr_index) == NULL)) {
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01005206 STACK_OF(SSL_CIPHER) * ciphers = NULL;
5207 const SSL_CIPHER * cipher = NULL;
5208 char cipher_description[128];
5209 /* The description of ciphers using an Ephemeral Diffie Hellman key exchange
5210 contains " Kx=DH " or " Kx=DH(". Beware of " Kx=DH/",
5211 which is not ephemeral DH. */
5212 const char dhe_description[] = " Kx=DH ";
5213 const char dhe_export_description[] = " Kx=DH(";
5214 int idx = 0;
5215 int dhe_found = 0;
5216 SSL *ssl = NULL;
Lukas Tribus90132722014-08-18 00:56:33 +02005217
Remi Gacogne23d5d372014-10-10 17:04:26 +02005218 ssl = SSL_new(ctx);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02005219
Remi Gacogne23d5d372014-10-10 17:04:26 +02005220 if (ssl) {
5221 ciphers = SSL_get_ciphers(ssl);
5222
5223 if (ciphers) {
5224 for (idx = 0; idx < sk_SSL_CIPHER_num(ciphers); idx++) {
5225 cipher = sk_SSL_CIPHER_value(ciphers, idx);
5226 if (SSL_CIPHER_description(cipher, cipher_description, sizeof (cipher_description)) == cipher_description) {
5227 if (strstr(cipher_description, dhe_description) != NULL ||
5228 strstr(cipher_description, dhe_export_description) != NULL) {
5229 dhe_found = 1;
5230 break;
5231 }
Remi Gacognec1eab8c2014-06-12 18:20:11 +02005232 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02005233 }
5234 }
Remi Gacogne23d5d372014-10-10 17:04:26 +02005235 SSL_free(ssl);
5236 ssl = NULL;
Lukas Tribus90132722014-08-18 00:56:33 +02005237 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02005238
Lukas Tribus90132722014-08-18 00:56:33 +02005239 if (dhe_found) {
Tim Duesterhus93128532019-11-23 23:45:10 +01005240 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",
5241 err && *err ? *err : "");
William Lallemand8b453912019-11-21 15:48:10 +01005242 cfgerr |= ERR_WARN;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02005243 }
5244
Willy Tarreauef934602016-12-22 23:12:01 +01005245 global_ssl.default_dh_param = 1024;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02005246 }
Remi Gacogne8de54152014-07-15 11:36:40 +02005247
Willy Tarreauef934602016-12-22 23:12:01 +01005248 if (global_ssl.default_dh_param >= 1024) {
Remi Gacogne8de54152014-07-15 11:36:40 +02005249 if (local_dh_1024 == NULL) {
5250 local_dh_1024 = ssl_get_dh_1024();
5251 }
Willy Tarreauef934602016-12-22 23:12:01 +01005252 if (global_ssl.default_dh_param >= 2048) {
Remi Gacogne8de54152014-07-15 11:36:40 +02005253 if (local_dh_2048 == NULL) {
5254 local_dh_2048 = ssl_get_dh_2048();
5255 }
Willy Tarreauef934602016-12-22 23:12:01 +01005256 if (global_ssl.default_dh_param >= 4096) {
Remi Gacogne8de54152014-07-15 11:36:40 +02005257 if (local_dh_4096 == NULL) {
5258 local_dh_4096 = ssl_get_dh_4096();
5259 }
Remi Gacogne8de54152014-07-15 11:36:40 +02005260 }
5261 }
5262 }
5263#endif /* OPENSSL_NO_DH */
Remi Gacognef46cd6e2014-06-12 14:58:40 +02005264
Emeric Brunfc0421f2012-09-07 17:30:07 +02005265 SSL_CTX_set_info_callback(ctx, ssl_sock_infocbk);
Willy Tarreau9a1ab082019-05-09 13:26:41 +02005266#if HA_OPENSSL_VERSION_NUMBER >= 0x00907000L
Emeric Brun29f037d2014-04-25 19:05:36 +02005267 SSL_CTX_set_msg_callback(ctx, ssl_sock_msgcbk);
Willy Tarreau5cbe4ef2014-05-08 22:45:11 +02005268#endif
Emeric Brun29f037d2014-04-25 19:05:36 +02005269
Bernard Spil13c53f82018-02-15 13:34:58 +01005270#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005271 ssl_conf_cur = NULL;
5272 if (ssl_conf && ssl_conf->npn_str)
5273 ssl_conf_cur = ssl_conf;
5274 else if (bind_conf->ssl_conf.npn_str)
5275 ssl_conf_cur = &bind_conf->ssl_conf;
5276 if (ssl_conf_cur)
5277 SSL_CTX_set_next_protos_advertised_cb(ctx, ssl_sock_advertise_npn_protos, ssl_conf_cur);
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02005278#endif
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01005279#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005280 ssl_conf_cur = NULL;
5281 if (ssl_conf && ssl_conf->alpn_str)
5282 ssl_conf_cur = ssl_conf;
5283 else if (bind_conf->ssl_conf.alpn_str)
5284 ssl_conf_cur = &bind_conf->ssl_conf;
5285 if (ssl_conf_cur)
5286 SSL_CTX_set_alpn_select_cb(ctx, ssl_sock_advertise_alpn_protos, ssl_conf_cur);
Willy Tarreauab861d32013-04-02 02:30:41 +02005287#endif
Lukas Tribusd14b49c2019-11-24 18:20:40 +01005288#if ((HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL) || defined(LIBRESSL_VERSION_NUMBER))
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01005289 conf_curves = (ssl_conf && ssl_conf->curves) ? ssl_conf->curves : bind_conf->ssl_conf.curves;
5290 if (conf_curves) {
5291 if (!SSL_CTX_set1_curves_list(ctx, conf_curves)) {
Tim Duesterhus93128532019-11-23 23:45:10 +01005292 memprintf(err, "%sProxy '%s': unable to set SSL curves list to '%s' for bind '%s' at [%s:%d].\n",
5293 err && *err ? *err : "", curproxy->id, conf_curves, bind_conf->arg, bind_conf->file, bind_conf->line);
William Lallemand8b453912019-11-21 15:48:10 +01005294 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01005295 }
Emmanuel Hocdeta52bb152017-03-20 11:11:49 +01005296 (void)SSL_CTX_set_ecdh_auto(ctx, 1);
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01005297 }
5298#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02005299#if defined(SSL_CTX_set_tmp_ecdh) && !defined(OPENSSL_NO_ECDH)
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01005300 if (!conf_curves) {
Emeric Brun2b58d042012-09-20 17:10:03 +02005301 int i;
5302 EC_KEY *ecdh;
Willy Tarreau9a1ab082019-05-09 13:26:41 +02005303#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005304 const char *ecdhe = (ssl_conf && ssl_conf->ecdhe) ? ssl_conf->ecdhe :
Olivier Houchardc2aae742017-09-22 18:26:28 +02005305 (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe :
5306 NULL);
5307
5308 if (ecdhe == NULL) {
Eric Salama3c8bde82019-11-20 11:33:40 +01005309 (void)SSL_CTX_set_ecdh_auto(ctx, 1);
Olivier Houchardc2aae742017-09-22 18:26:28 +02005310 return cfgerr;
5311 }
5312#else
5313 const char *ecdhe = (ssl_conf && ssl_conf->ecdhe) ? ssl_conf->ecdhe :
5314 (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe :
5315 ECDHE_DEFAULT_CURVE);
5316#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02005317
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005318 i = OBJ_sn2nid(ecdhe);
Emeric Brun2b58d042012-09-20 17:10:03 +02005319 if (!i || ((ecdh = EC_KEY_new_by_curve_name(i)) == NULL)) {
Tim Duesterhus93128532019-11-23 23:45:10 +01005320 memprintf(err, "%sProxy '%s': unable to set elliptic named curve to '%s' for bind '%s' at [%s:%d].\n",
5321 err && *err ? *err : "", curproxy->id, ecdhe, bind_conf->arg, bind_conf->file, bind_conf->line);
William Lallemand8b453912019-11-21 15:48:10 +01005322 cfgerr |= ERR_ALERT | ERR_FATAL;
Emeric Brun2b58d042012-09-20 17:10:03 +02005323 }
5324 else {
5325 SSL_CTX_set_tmp_ecdh(ctx, ecdh);
5326 EC_KEY_free(ecdh);
5327 }
5328 }
5329#endif
5330
Emeric Brunfc0421f2012-09-07 17:30:07 +02005331 return cfgerr;
5332}
5333
Evan Broderbe554312013-06-27 00:05:25 -07005334static int ssl_sock_srv_hostcheck(const char *pattern, const char *hostname)
5335{
5336 const char *pattern_wildcard, *pattern_left_label_end, *hostname_left_label_end;
5337 size_t prefixlen, suffixlen;
5338
5339 /* Trivial case */
5340 if (strcmp(pattern, hostname) == 0)
5341 return 1;
5342
Evan Broderbe554312013-06-27 00:05:25 -07005343 /* The rest of this logic is based on RFC 6125, section 6.4.3
5344 * (http://tools.ietf.org/html/rfc6125#section-6.4.3) */
5345
Emeric Bruna848dae2013-10-08 11:27:28 +02005346 pattern_wildcard = NULL;
5347 pattern_left_label_end = pattern;
5348 while (*pattern_left_label_end != '.') {
5349 switch (*pattern_left_label_end) {
5350 case 0:
5351 /* End of label not found */
5352 return 0;
5353 case '*':
5354 /* If there is more than one wildcards */
5355 if (pattern_wildcard)
5356 return 0;
5357 pattern_wildcard = pattern_left_label_end;
5358 break;
5359 }
5360 pattern_left_label_end++;
5361 }
5362
5363 /* If it's not trivial and there is no wildcard, it can't
5364 * match */
5365 if (!pattern_wildcard)
Evan Broderbe554312013-06-27 00:05:25 -07005366 return 0;
5367
5368 /* Make sure all labels match except the leftmost */
5369 hostname_left_label_end = strchr(hostname, '.');
5370 if (!hostname_left_label_end
5371 || strcmp(pattern_left_label_end, hostname_left_label_end) != 0)
5372 return 0;
5373
5374 /* Make sure the leftmost label of the hostname is long enough
5375 * that the wildcard can match */
Emeric Brun369da852013-10-08 11:39:35 +02005376 if (hostname_left_label_end - hostname < (pattern_left_label_end - pattern) - 1)
Evan Broderbe554312013-06-27 00:05:25 -07005377 return 0;
5378
5379 /* Finally compare the string on either side of the
5380 * wildcard */
5381 prefixlen = pattern_wildcard - pattern;
5382 suffixlen = pattern_left_label_end - (pattern_wildcard + 1);
Emeric Bruna848dae2013-10-08 11:27:28 +02005383 if ((prefixlen && (memcmp(pattern, hostname, prefixlen) != 0))
5384 || (suffixlen && (memcmp(pattern_wildcard + 1, hostname_left_label_end - suffixlen, suffixlen) != 0)))
Evan Broderbe554312013-06-27 00:05:25 -07005385 return 0;
5386
5387 return 1;
5388}
5389
5390static int ssl_sock_srv_verifycbk(int ok, X509_STORE_CTX *ctx)
5391{
5392 SSL *ssl;
5393 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01005394 struct ssl_sock_ctx *ssl_ctx;
Willy Tarreau2ab88672017-07-05 18:23:03 +02005395 const char *servername;
Willy Tarreau71d058c2017-07-26 20:09:56 +02005396 const char *sni;
Evan Broderbe554312013-06-27 00:05:25 -07005397
5398 int depth;
5399 X509 *cert;
5400 STACK_OF(GENERAL_NAME) *alt_names;
5401 int i;
5402 X509_NAME *cert_subject;
5403 char *str;
5404
5405 if (ok == 0)
5406 return ok;
5407
5408 ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
Thierry FOURNIER28962c92018-06-17 21:37:05 +02005409 conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Olivier Houchard66ab4982019-02-26 18:37:15 +01005410 ssl_ctx = conn->xprt_ctx;
Evan Broderbe554312013-06-27 00:05:25 -07005411
Willy Tarreauad92a9a2017-07-28 11:38:41 +02005412 /* We're checking if the provided hostnames match the desired one. The
5413 * desired hostname comes from the SNI we presented if any, or if not
5414 * provided then it may have been explicitly stated using a "verifyhost"
5415 * directive. If neither is set, we don't care about the name so the
5416 * verification is OK.
Willy Tarreau2ab88672017-07-05 18:23:03 +02005417 */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005418 servername = SSL_get_servername(ssl_ctx->ssl, TLSEXT_NAMETYPE_host_name);
Willy Tarreau71d058c2017-07-26 20:09:56 +02005419 sni = servername;
Willy Tarreau2ab88672017-07-05 18:23:03 +02005420 if (!servername) {
Willy Tarreau07d94e42018-09-20 10:57:52 +02005421 servername = __objt_server(conn->target)->ssl_ctx.verify_host;
Willy Tarreau2ab88672017-07-05 18:23:03 +02005422 if (!servername)
5423 return ok;
5424 }
Evan Broderbe554312013-06-27 00:05:25 -07005425
5426 /* We only need to verify the CN on the actual server cert,
5427 * not the indirect CAs */
5428 depth = X509_STORE_CTX_get_error_depth(ctx);
5429 if (depth != 0)
5430 return ok;
5431
5432 /* At this point, the cert is *not* OK unless we can find a
5433 * hostname match */
5434 ok = 0;
5435
5436 cert = X509_STORE_CTX_get_current_cert(ctx);
5437 /* It seems like this might happen if verify peer isn't set */
5438 if (!cert)
5439 return ok;
5440
5441 alt_names = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
5442 if (alt_names) {
5443 for (i = 0; !ok && i < sk_GENERAL_NAME_num(alt_names); i++) {
5444 GENERAL_NAME *name = sk_GENERAL_NAME_value(alt_names, i);
5445 if (name->type == GEN_DNS) {
Willy Tarreau9a1ab082019-05-09 13:26:41 +02005446#if HA_OPENSSL_VERSION_NUMBER < 0x00907000L
Emeric Bruna33410c2013-09-17 15:47:48 +02005447 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.ia5) >= 0) {
5448#else
Evan Broderbe554312013-06-27 00:05:25 -07005449 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
Emeric Bruna33410c2013-09-17 15:47:48 +02005450#endif
Evan Broderbe554312013-06-27 00:05:25 -07005451 ok = ssl_sock_srv_hostcheck(str, servername);
5452 OPENSSL_free(str);
5453 }
5454 }
5455 }
Emeric Brun4ad50a42013-09-17 15:19:54 +02005456 sk_GENERAL_NAME_pop_free(alt_names, GENERAL_NAME_free);
Evan Broderbe554312013-06-27 00:05:25 -07005457 }
5458
5459 cert_subject = X509_get_subject_name(cert);
5460 i = -1;
5461 while (!ok && (i = X509_NAME_get_index_by_NID(cert_subject, NID_commonName, i)) != -1) {
5462 X509_NAME_ENTRY *entry = X509_NAME_get_entry(cert_subject, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005463 ASN1_STRING *value;
5464 value = X509_NAME_ENTRY_get_data(entry);
5465 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
Evan Broderbe554312013-06-27 00:05:25 -07005466 ok = ssl_sock_srv_hostcheck(str, servername);
5467 OPENSSL_free(str);
5468 }
5469 }
5470
Willy Tarreau71d058c2017-07-26 20:09:56 +02005471 /* report the mismatch and indicate if SNI was used or not */
5472 if (!ok && !conn->err_code)
5473 conn->err_code = sni ? CO_ER_SSL_MISMATCH_SNI : CO_ER_SSL_MISMATCH;
Evan Broderbe554312013-06-27 00:05:25 -07005474 return ok;
5475}
5476
Emeric Brun94324a42012-10-11 14:00:19 +02005477/* prepare ssl context from servers options. Returns an error count */
Willy Tarreau03209342016-12-22 17:08:28 +01005478int ssl_sock_prepare_srv_ctx(struct server *srv)
Emeric Brun94324a42012-10-11 14:00:19 +02005479{
Willy Tarreau03209342016-12-22 17:08:28 +01005480 struct proxy *curproxy = srv->proxy;
Emeric Brun94324a42012-10-11 14:00:19 +02005481 int cfgerr = 0;
Remi Gacogneaf5c3da2014-05-19 10:29:58 +02005482 long options =
Emeric Brun94324a42012-10-11 14:00:19 +02005483 SSL_OP_ALL | /* all known workarounds for bugs */
5484 SSL_OP_NO_SSLv2 |
5485 SSL_OP_NO_COMPRESSION;
Remi Gacogneaf5c3da2014-05-19 10:29:58 +02005486 long mode =
Emeric Brun94324a42012-10-11 14:00:19 +02005487 SSL_MODE_ENABLE_PARTIAL_WRITE |
5488 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
Willy Tarreau396a1862014-11-13 14:06:52 +01005489 SSL_MODE_RELEASE_BUFFERS |
5490 SSL_MODE_SMALL_BUFFERS;
Emeric Brun850efd52014-01-29 12:24:34 +01005491 int verify = SSL_VERIFY_NONE;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01005492 SSL_CTX *ctx = NULL;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005493 struct tls_version_filter *conf_ssl_methods = &srv->ssl_ctx.methods;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005494 int i, min, max, hole;
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005495 int flags = MC_SSL_O_ALL;
Emeric Brun94324a42012-10-11 14:00:19 +02005496
Thierry Fournier383085f2013-01-24 14:15:43 +01005497 /* Make sure openssl opens /dev/urandom before the chroot */
5498 if (!ssl_initialize_random()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005499 ha_alert("OpenSSL random data generator initialization failed.\n");
Thierry Fournier383085f2013-01-24 14:15:43 +01005500 cfgerr++;
5501 }
5502
Willy Tarreaufce03112015-01-15 21:32:40 +01005503 /* Automatic memory computations need to know we use SSL there */
5504 global.ssl_used_backend = 1;
5505
5506 /* Initiate SSL context for current server */
Emeric Brun821bb9b2017-06-15 16:37:39 +02005507 if (!srv->ssl_ctx.reused_sess) {
Olivier Houcharde6060c52017-11-16 17:42:52 +01005508 if ((srv->ssl_ctx.reused_sess = calloc(1, global.nbthread*sizeof(*srv->ssl_ctx.reused_sess))) == NULL) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005509 ha_alert("Proxy '%s', server '%s' [%s:%d] out of memory.\n",
5510 curproxy->id, srv->id,
5511 srv->conf.file, srv->conf.line);
Emeric Brun821bb9b2017-06-15 16:37:39 +02005512 cfgerr++;
5513 return cfgerr;
5514 }
5515 }
Emeric Brun94324a42012-10-11 14:00:19 +02005516 if (srv->use_ssl)
5517 srv->xprt = &ssl_sock;
5518 if (srv->check.use_ssl)
Cyril Bonté9ce13112014-11-15 22:41:27 +01005519 srv->check.xprt = &ssl_sock;
Emeric Brun94324a42012-10-11 14:00:19 +02005520
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005521 ctx = SSL_CTX_new(SSLv23_client_method());
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01005522 if (!ctx) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005523 ha_alert("config : %s '%s', server '%s': unable to allocate ssl context.\n",
5524 proxy_type_str(curproxy), curproxy->id,
5525 srv->id);
Emeric Brun94324a42012-10-11 14:00:19 +02005526 cfgerr++;
5527 return cfgerr;
5528 }
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005529
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005530 if (conf_ssl_methods->flags && (conf_ssl_methods->min || conf_ssl_methods->max))
Christopher Faulet767a84b2017-11-24 16:50:31 +01005531 ha_warning("config : %s '%s': no-sslv3/no-tlsv1x are ignored for server '%s'. "
5532 "Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
5533 proxy_type_str(curproxy), curproxy->id, srv->id);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005534 else
5535 flags = conf_ssl_methods->flags;
5536
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005537 /* Real min and max should be determinate with configuration and openssl's capabilities */
5538 if (conf_ssl_methods->min)
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005539 flags |= (methodVersions[conf_ssl_methods->min].flag - 1);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005540 if (conf_ssl_methods->max)
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005541 flags |= ~((methodVersions[conf_ssl_methods->max].flag << 1) - 1);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005542
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02005543 /* find min, max and holes */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005544 min = max = CONF_TLSV_NONE;
5545 hole = 0;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005546 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005547 /* version is in openssl && version not disable in configuration */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005548 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005549 if (min) {
5550 if (hole) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005551 ha_warning("config : %s '%s': SSL/TLS versions range not contiguous for server '%s'. "
5552 "Hole find for %s. Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
5553 proxy_type_str(curproxy), curproxy->id, srv->id,
5554 methodVersions[hole].name);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005555 hole = 0;
5556 }
5557 max = i;
5558 }
5559 else {
5560 min = max = i;
5561 }
5562 }
5563 else {
5564 if (min)
5565 hole = i;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005566 }
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005567 if (!min) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005568 ha_alert("config : %s '%s': all SSL/TLS versions are disabled for server '%s'.\n",
5569 proxy_type_str(curproxy), curproxy->id, srv->id);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005570 cfgerr += 1;
5571 }
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005572
Willy Tarreau9a1ab082019-05-09 13:26:41 +02005573#if (HA_OPENSSL_VERSION_NUMBER < 0x1010000fL)
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005574 /* Keep force-xxx implementation as it is in older haproxy. It's a
Joseph Herlant017b3da2018-11-15 09:07:59 -08005575 precautionary measure to avoid any surprise with older openssl version. */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005576 if (min == max)
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02005577 methodVersions[min].ctx_set_version(ctx, SET_CLIENT);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005578 else
5579 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
5580 if (flags & methodVersions[i].flag)
5581 options |= methodVersions[i].option;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005582#else /* openssl >= 1.1.0 */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005583 /* set the max_version is required to cap TLS version or activate new TLS (v1.3) */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02005584 methodVersions[min].ctx_set_version(ctx, SET_MIN);
5585 methodVersions[max].ctx_set_version(ctx, SET_MAX);
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005586#endif
5587
5588 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLS_TICKETS)
5589 options |= SSL_OP_NO_TICKET;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01005590 SSL_CTX_set_options(ctx, options);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005591
Willy Tarreau5db847a2019-05-09 14:13:35 +02005592#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005593 if (global_ssl.async)
5594 mode |= SSL_MODE_ASYNC;
5595#endif
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01005596 SSL_CTX_set_mode(ctx, mode);
5597 srv->ssl_ctx.ctx = ctx;
5598
Emeric Bruna7aa3092012-10-26 12:58:00 +02005599 if (srv->ssl_ctx.client_crt) {
5600 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 +01005601 ha_alert("config : %s '%s', server '%s': unable to load SSL private key from PEM file '%s'.\n",
5602 proxy_type_str(curproxy), curproxy->id,
5603 srv->id, srv->ssl_ctx.client_crt);
Emeric Bruna7aa3092012-10-26 12:58:00 +02005604 cfgerr++;
5605 }
5606 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 +01005607 ha_alert("config : %s '%s', server '%s': unable to load ssl certificate from PEM file '%s'.\n",
5608 proxy_type_str(curproxy), curproxy->id,
5609 srv->id, srv->ssl_ctx.client_crt);
Emeric Bruna7aa3092012-10-26 12:58:00 +02005610 cfgerr++;
5611 }
5612 else if (SSL_CTX_check_private_key(srv->ssl_ctx.ctx) <= 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005613 ha_alert("config : %s '%s', server '%s': inconsistencies between private key and certificate loaded from PEM file '%s'.\n",
5614 proxy_type_str(curproxy), curproxy->id,
5615 srv->id, srv->ssl_ctx.client_crt);
Emeric Bruna7aa3092012-10-26 12:58:00 +02005616 cfgerr++;
5617 }
5618 }
Emeric Brun94324a42012-10-11 14:00:19 +02005619
Emeric Brun850efd52014-01-29 12:24:34 +01005620 if (global.ssl_server_verify == SSL_SERVER_VERIFY_REQUIRED)
5621 verify = SSL_VERIFY_PEER;
Emeric Brun850efd52014-01-29 12:24:34 +01005622 switch (srv->ssl_ctx.verify) {
5623 case SSL_SOCK_VERIFY_NONE:
5624 verify = SSL_VERIFY_NONE;
5625 break;
5626 case SSL_SOCK_VERIFY_REQUIRED:
5627 verify = SSL_VERIFY_PEER;
5628 break;
5629 }
Evan Broderbe554312013-06-27 00:05:25 -07005630 SSL_CTX_set_verify(srv->ssl_ctx.ctx,
Emeric Brun850efd52014-01-29 12:24:34 +01005631 verify,
Willy Tarreau2ab88672017-07-05 18:23:03 +02005632 (srv->ssl_ctx.verify_host || (verify & SSL_VERIFY_PEER)) ? ssl_sock_srv_verifycbk : NULL);
Emeric Brun850efd52014-01-29 12:24:34 +01005633 if (verify & SSL_VERIFY_PEER) {
Emeric Brunef42d922012-10-11 16:11:36 +02005634 if (srv->ssl_ctx.ca_file) {
Emmanuel Hocdetd4f9a602019-10-24 11:32:47 +02005635 /* set CAfile to verify */
5636 if (!ssl_set_verify_locations_file(srv->ssl_ctx.ctx, srv->ssl_ctx.ca_file)) {
5637 ha_alert("Proxy '%s', server '%s' [%s:%d] unable to set CA file '%s'.\n",
Christopher Faulet767a84b2017-11-24 16:50:31 +01005638 curproxy->id, srv->id,
5639 srv->conf.file, srv->conf.line, srv->ssl_ctx.ca_file);
Emeric Brunef42d922012-10-11 16:11:36 +02005640 cfgerr++;
5641 }
5642 }
Emeric Brun850efd52014-01-29 12:24:34 +01005643 else {
5644 if (global.ssl_server_verify == SSL_SERVER_VERIFY_REQUIRED)
Christopher Faulet767a84b2017-11-24 16:50:31 +01005645 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",
5646 curproxy->id, srv->id,
5647 srv->conf.file, srv->conf.line);
Emeric Brun850efd52014-01-29 12:24:34 +01005648 else
Christopher Faulet767a84b2017-11-24 16:50:31 +01005649 ha_alert("Proxy '%s', server '%s' [%s:%d] verify is enabled but no CA file specified.\n",
5650 curproxy->id, srv->id,
5651 srv->conf.file, srv->conf.line);
Emeric Brun850efd52014-01-29 12:24:34 +01005652 cfgerr++;
5653 }
Emeric Brunef42d922012-10-11 16:11:36 +02005654#ifdef X509_V_FLAG_CRL_CHECK
5655 if (srv->ssl_ctx.crl_file) {
5656 X509_STORE *store = SSL_CTX_get_cert_store(srv->ssl_ctx.ctx);
5657
Emmanuel Hocdetb270e812019-11-21 19:09:31 +01005658 if (!ssl_set_cert_crl_file(store, srv->ssl_ctx.crl_file)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005659 ha_alert("Proxy '%s', server '%s' [%s:%d] unable to configure CRL file '%s'.\n",
5660 curproxy->id, srv->id,
5661 srv->conf.file, srv->conf.line, srv->ssl_ctx.crl_file);
Emeric Brunef42d922012-10-11 16:11:36 +02005662 cfgerr++;
5663 }
5664 else {
5665 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
5666 }
5667 }
5668#endif
5669 }
5670
Olivier Houchardbd84ac82017-11-03 13:43:35 +01005671 SSL_CTX_set_session_cache_mode(srv->ssl_ctx.ctx, SSL_SESS_CACHE_CLIENT |
5672 SSL_SESS_CACHE_NO_INTERNAL_STORE);
5673 SSL_CTX_sess_set_new_cb(srv->ssl_ctx.ctx, ssl_sess_new_srv_cb);
Emeric Brun94324a42012-10-11 14:00:19 +02005674 if (srv->ssl_ctx.ciphers &&
5675 !SSL_CTX_set_cipher_list(srv->ssl_ctx.ctx, srv->ssl_ctx.ciphers)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005676 ha_alert("Proxy '%s', server '%s' [%s:%d] : unable to set SSL cipher list to '%s'.\n",
5677 curproxy->id, srv->id,
5678 srv->conf.file, srv->conf.line, srv->ssl_ctx.ciphers);
Emeric Brun94324a42012-10-11 14:00:19 +02005679 cfgerr++;
5680 }
Dirkjan Bussink415150f2018-09-14 11:14:21 +02005681
Emmanuel Hocdet839af572019-05-14 16:27:35 +02005682#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02005683 if (srv->ssl_ctx.ciphersuites &&
Pierre Cheynierbc34cd12019-03-21 16:15:47 +00005684 !SSL_CTX_set_ciphersuites(srv->ssl_ctx.ctx, srv->ssl_ctx.ciphersuites)) {
Dirkjan Bussink415150f2018-09-14 11:14:21 +02005685 ha_alert("Proxy '%s', server '%s' [%s:%d] : unable to set TLS 1.3 cipher suites to '%s'.\n",
5686 curproxy->id, srv->id,
5687 srv->conf.file, srv->conf.line, srv->ssl_ctx.ciphersuites);
5688 cfgerr++;
5689 }
5690#endif
Olivier Houchardc7566002018-11-20 23:33:50 +01005691#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
5692 if (srv->ssl_ctx.npn_str)
5693 SSL_CTX_set_next_proto_select_cb(ctx, ssl_sock_srv_select_protos, srv);
5694#endif
5695#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
5696 if (srv->ssl_ctx.alpn_str)
5697 SSL_CTX_set_alpn_protos(ctx, (unsigned char *)srv->ssl_ctx.alpn_str, srv->ssl_ctx.alpn_len);
5698#endif
5699
Emeric Brun94324a42012-10-11 14:00:19 +02005700
5701 return cfgerr;
5702}
5703
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005704/* Walks down the two trees in bind_conf and prepares all certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +02005705 * be NULL, in which case nothing is done. Returns the number of errors
5706 * encountered.
5707 */
Willy Tarreau03209342016-12-22 17:08:28 +01005708int ssl_sock_prepare_all_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02005709{
5710 struct ebmb_node *node;
5711 struct sni_ctx *sni;
5712 int err = 0;
William Lallemand8b453912019-11-21 15:48:10 +01005713 int errcode = 0;
5714 char *errmsg = NULL;
Emeric Brunfc0421f2012-09-07 17:30:07 +02005715
Willy Tarreaufce03112015-01-15 21:32:40 +01005716 /* Automatic memory computations need to know we use SSL there */
5717 global.ssl_used_frontend = 1;
5718
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01005719 /* Make sure openssl opens /dev/urandom before the chroot */
5720 if (!ssl_initialize_random()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005721 ha_alert("OpenSSL random data generator initialization failed.\n");
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01005722 err++;
5723 }
5724 /* Create initial_ctx used to start the ssl connection before do switchctx */
5725 if (!bind_conf->initial_ctx) {
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005726 err += ssl_sock_initial_ctx(bind_conf);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01005727 /* It should not be necessary to call this function, but it's
5728 necessary first to check and move all initialisation related
5729 to initial_ctx in ssl_sock_initial_ctx. */
William Lallemand8b453912019-11-21 15:48:10 +01005730 errcode |= ssl_sock_prepare_ctx(bind_conf, NULL, bind_conf->initial_ctx, &errmsg);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01005731 }
Emeric Brun0bed9942014-10-30 19:25:24 +01005732 if (bind_conf->default_ctx)
William Lallemand8b453912019-11-21 15:48:10 +01005733 errcode |= ssl_sock_prepare_ctx(bind_conf, bind_conf->default_ssl_conf, bind_conf->default_ctx, &errmsg);
Emeric Brun0bed9942014-10-30 19:25:24 +01005734
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005735 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02005736 while (node) {
5737 sni = ebmb_entry(node, struct sni_ctx, name);
Emeric Brun0bed9942014-10-30 19:25:24 +01005738 if (!sni->order && sni->ctx != bind_conf->default_ctx)
5739 /* only initialize the CTX on its first occurrence and
5740 if it is not the default_ctx */
William Lallemand8b453912019-11-21 15:48:10 +01005741 errcode |= ssl_sock_prepare_ctx(bind_conf, sni->conf, sni->ctx, &errmsg);
Emeric Brunfc0421f2012-09-07 17:30:07 +02005742 node = ebmb_next(node);
5743 }
5744
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005745 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02005746 while (node) {
5747 sni = ebmb_entry(node, struct sni_ctx, name);
William Lallemand8b453912019-11-21 15:48:10 +01005748 if (!sni->order && sni->ctx != bind_conf->default_ctx) {
Emeric Brun0bed9942014-10-30 19:25:24 +01005749 /* only initialize the CTX on its first occurrence and
5750 if it is not the default_ctx */
William Lallemand8b453912019-11-21 15:48:10 +01005751 errcode |= ssl_sock_prepare_ctx(bind_conf, sni->conf, sni->ctx, &errmsg);
5752 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02005753 node = ebmb_next(node);
5754 }
William Lallemand8b453912019-11-21 15:48:10 +01005755
5756 if (errcode & ERR_WARN) {
Tim Duesterhusc0e820c2019-11-23 23:52:30 +01005757 ha_warning("%s", errmsg);
William Lallemand8b453912019-11-21 15:48:10 +01005758 } else if (errcode & ERR_CODE) {
Tim Duesterhusc0e820c2019-11-23 23:52:30 +01005759 ha_alert("%s", errmsg);
William Lallemand8b453912019-11-21 15:48:10 +01005760 err++;
5761 }
5762
5763 free(errmsg);
Emeric Brunfc0421f2012-09-07 17:30:07 +02005764 return err;
5765}
5766
Willy Tarreau55d37912016-12-21 23:38:39 +01005767/* Prepares all the contexts for a bind_conf and allocates the shared SSL
5768 * context if needed. Returns < 0 on error, 0 on success. The warnings and
5769 * alerts are directly emitted since the rest of the stack does it below.
5770 */
5771int ssl_sock_prepare_bind_conf(struct bind_conf *bind_conf)
5772{
5773 struct proxy *px = bind_conf->frontend;
5774 int alloc_ctx;
5775 int err;
5776
5777 if (!bind_conf->is_ssl) {
5778 if (bind_conf->default_ctx) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005779 ha_warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
5780 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreau55d37912016-12-21 23:38:39 +01005781 }
5782 return 0;
5783 }
5784 if (!bind_conf->default_ctx) {
Emmanuel Hocdetaa0d6372017-08-09 11:24:25 +02005785 if (bind_conf->strict_sni && !bind_conf->generate_certs) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005786 ha_warning("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d], ssl connections will fail (use 'crt').\n",
5787 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetaa0d6372017-08-09 11:24:25 +02005788 }
5789 else {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005790 ha_alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
5791 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetaa0d6372017-08-09 11:24:25 +02005792 return -1;
5793 }
Willy Tarreau55d37912016-12-21 23:38:39 +01005794 }
William Lallemandc61c0b32017-12-04 18:46:39 +01005795 if (!ssl_shctx && global.tune.sslcachesize) {
William Lallemandc3cd35f2017-11-28 11:04:43 +01005796 alloc_ctx = shctx_init(&ssl_shctx, global.tune.sslcachesize,
Frédéric Lécailleb7838af2018-10-22 16:21:39 +02005797 sizeof(struct sh_ssl_sess_hdr) + SHSESS_BLOCK_MIN_SIZE, -1,
William Lallemandc3cd35f2017-11-28 11:04:43 +01005798 sizeof(*sh_ssl_sess_tree),
5799 ((global.nbthread > 1) || (!global_ssl.private_cache && (global.nbproc > 1))) ? 1 : 0);
Frédéric Lécaille4c8aa112018-10-25 20:22:46 +02005800 if (alloc_ctx <= 0) {
William Lallemandc3cd35f2017-11-28 11:04:43 +01005801 if (alloc_ctx == SHCTX_E_INIT_LOCK)
5802 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");
5803 else
5804 ha_alert("Unable to allocate SSL session cache.\n");
5805 return -1;
5806 }
5807 /* free block callback */
5808 ssl_shctx->free_block = sh_ssl_sess_free_blocks;
5809 /* init the root tree within the extra space */
5810 sh_ssl_sess_tree = (void *)ssl_shctx + sizeof(struct shared_context);
5811 *sh_ssl_sess_tree = EB_ROOT_UNIQUE;
Willy Tarreau55d37912016-12-21 23:38:39 +01005812 }
Willy Tarreau55d37912016-12-21 23:38:39 +01005813 err = 0;
5814 /* initialize all certificate contexts */
5815 err += ssl_sock_prepare_all_ctx(bind_conf);
5816
5817 /* initialize CA variables if the certificates generation is enabled */
5818 err += ssl_sock_load_ca(bind_conf);
5819
5820 return -err;
5821}
Christopher Faulet77fe80c2015-07-29 13:02:40 +02005822
5823/* release ssl context allocated for servers. */
5824void ssl_sock_free_srv_ctx(struct server *srv)
5825{
Olivier Houchardc7566002018-11-20 23:33:50 +01005826#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
5827 if (srv->ssl_ctx.alpn_str)
5828 free(srv->ssl_ctx.alpn_str);
5829#endif
Lukas Tribusda95fd92018-11-25 13:21:27 +01005830#ifdef OPENSSL_NPN_NEGOTIATED
Olivier Houchardc7566002018-11-20 23:33:50 +01005831 if (srv->ssl_ctx.npn_str)
5832 free(srv->ssl_ctx.npn_str);
Lukas Tribus7706b852018-11-26 22:57:17 +01005833#endif
Christopher Faulet77fe80c2015-07-29 13:02:40 +02005834 if (srv->ssl_ctx.ctx)
5835 SSL_CTX_free(srv->ssl_ctx.ctx);
5836}
5837
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005838/* Walks down the two trees in bind_conf and frees all the certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +02005839 * be NULL, in which case nothing is done. The default_ctx is nullified too.
5840 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005841void ssl_sock_free_all_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02005842{
5843 struct ebmb_node *node, *back;
5844 struct sni_ctx *sni;
5845
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005846 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02005847 while (node) {
5848 sni = ebmb_entry(node, struct sni_ctx, name);
5849 back = ebmb_next(node);
5850 ebmb_delete(node);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005851 if (!sni->order) { /* only free the CTX on its first occurrence */
Emeric Brunfc0421f2012-09-07 17:30:07 +02005852 SSL_CTX_free(sni->ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005853 ssl_sock_free_ssl_conf(sni->conf);
5854 free(sni->conf);
5855 sni->conf = NULL;
5856 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02005857 free(sni);
5858 node = back;
5859 }
5860
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005861 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02005862 while (node) {
5863 sni = ebmb_entry(node, struct sni_ctx, name);
5864 back = ebmb_next(node);
5865 ebmb_delete(node);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005866 if (!sni->order) { /* only free the CTX on its first occurrence */
Emeric Brunfc0421f2012-09-07 17:30:07 +02005867 SSL_CTX_free(sni->ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005868 ssl_sock_free_ssl_conf(sni->conf);
5869 free(sni->conf);
5870 sni->conf = NULL;
5871 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02005872 free(sni);
5873 node = back;
5874 }
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01005875 SSL_CTX_free(bind_conf->initial_ctx);
5876 bind_conf->initial_ctx = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005877 bind_conf->default_ctx = NULL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005878 bind_conf->default_ssl_conf = NULL;
Emeric Brune1f38db2012-09-03 20:36:47 +02005879}
5880
Willy Tarreau795cdab2016-12-22 17:30:54 +01005881/* Destroys all the contexts for a bind_conf. This is used during deinit(). */
5882void ssl_sock_destroy_bind_conf(struct bind_conf *bind_conf)
5883{
5884 ssl_sock_free_ca(bind_conf);
5885 ssl_sock_free_all_ctx(bind_conf);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005886 ssl_sock_free_ssl_conf(&bind_conf->ssl_conf);
Willy Tarreau795cdab2016-12-22 17:30:54 +01005887 free(bind_conf->ca_sign_file);
5888 free(bind_conf->ca_sign_pass);
Willy Tarreau17b4aa12018-07-17 10:05:32 +02005889 if (bind_conf->keys_ref && !--bind_conf->keys_ref->refcount) {
Willy Tarreau795cdab2016-12-22 17:30:54 +01005890 free(bind_conf->keys_ref->filename);
5891 free(bind_conf->keys_ref->tlskeys);
5892 LIST_DEL(&bind_conf->keys_ref->list);
5893 free(bind_conf->keys_ref);
5894 }
5895 bind_conf->keys_ref = NULL;
Willy Tarreau795cdab2016-12-22 17:30:54 +01005896 bind_conf->ca_sign_pass = NULL;
5897 bind_conf->ca_sign_file = NULL;
Willy Tarreau795cdab2016-12-22 17:30:54 +01005898}
5899
Christopher Faulet31af49d2015-06-09 17:29:50 +02005900/* Load CA cert file and private key used to generate certificates */
5901int
Willy Tarreau03209342016-12-22 17:08:28 +01005902ssl_sock_load_ca(struct bind_conf *bind_conf)
Christopher Faulet31af49d2015-06-09 17:29:50 +02005903{
Willy Tarreau03209342016-12-22 17:08:28 +01005904 struct proxy *px = bind_conf->frontend;
Christopher Faulet31af49d2015-06-09 17:29:50 +02005905 FILE *fp;
5906 X509 *cacert = NULL;
5907 EVP_PKEY *capkey = NULL;
5908 int err = 0;
5909
Christopher Fauletf8bb0ce2017-09-15 09:52:49 +02005910 if (!bind_conf->generate_certs)
Christopher Faulet31af49d2015-06-09 17:29:50 +02005911 return err;
5912
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005913#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Emeric Brun821bb9b2017-06-15 16:37:39 +02005914 if (global_ssl.ctx_cache) {
Willy Tarreauef934602016-12-22 23:12:01 +01005915 ssl_ctx_lru_tree = lru64_new(global_ssl.ctx_cache);
Emeric Brun821bb9b2017-06-15 16:37:39 +02005916 }
Christopher Fauletd2cab922015-07-28 16:03:47 +02005917 ssl_ctx_lru_seed = (unsigned int)time(NULL);
Emeric Brun821bb9b2017-06-15 16:37:39 +02005918 ssl_ctx_serial = now_ms;
Willy Tarreaua84c2672015-10-09 12:10:13 +02005919#endif
Christopher Fauletd2cab922015-07-28 16:03:47 +02005920
Christopher Faulet31af49d2015-06-09 17:29:50 +02005921 if (!bind_conf->ca_sign_file) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005922 ha_alert("Proxy '%s': cannot enable certificate generation, "
5923 "no CA certificate File configured at [%s:%d].\n",
5924 px->id, bind_conf->file, bind_conf->line);
Christopher Faulet31af49d2015-06-09 17:29:50 +02005925 goto load_error;
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005926 }
Christopher Faulet31af49d2015-06-09 17:29:50 +02005927
5928 /* read in the CA certificate */
5929 if (!(fp = fopen(bind_conf->ca_sign_file, "r"))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005930 ha_alert("Proxy '%s': Failed to read CA certificate file '%s' at [%s:%d].\n",
5931 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Faulet31af49d2015-06-09 17:29:50 +02005932 goto load_error;
5933 }
5934 if (!(cacert = PEM_read_X509(fp, NULL, NULL, NULL))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005935 ha_alert("Proxy '%s': Failed to read CA certificate file '%s' at [%s:%d].\n",
5936 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005937 goto read_error;
Christopher Faulet31af49d2015-06-09 17:29:50 +02005938 }
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005939 rewind(fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02005940 if (!(capkey = PEM_read_PrivateKey(fp, NULL, NULL, bind_conf->ca_sign_pass))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005941 ha_alert("Proxy '%s': Failed to read CA private key file '%s' at [%s:%d].\n",
5942 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005943 goto read_error;
Christopher Faulet31af49d2015-06-09 17:29:50 +02005944 }
Christopher Faulet31af49d2015-06-09 17:29:50 +02005945
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005946 fclose (fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02005947 bind_conf->ca_sign_cert = cacert;
5948 bind_conf->ca_sign_pkey = capkey;
5949 return err;
5950
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005951 read_error:
5952 fclose (fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02005953 if (capkey) EVP_PKEY_free(capkey);
5954 if (cacert) X509_free(cacert);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005955 load_error:
5956 bind_conf->generate_certs = 0;
5957 err++;
Christopher Faulet31af49d2015-06-09 17:29:50 +02005958 return err;
5959}
5960
5961/* Release CA cert and private key used to generate certificated */
5962void
5963ssl_sock_free_ca(struct bind_conf *bind_conf)
5964{
Christopher Faulet31af49d2015-06-09 17:29:50 +02005965 if (bind_conf->ca_sign_pkey)
5966 EVP_PKEY_free(bind_conf->ca_sign_pkey);
5967 if (bind_conf->ca_sign_cert)
5968 X509_free(bind_conf->ca_sign_cert);
Willy Tarreau94ff03a2016-12-22 17:57:46 +01005969 bind_conf->ca_sign_pkey = NULL;
5970 bind_conf->ca_sign_cert = NULL;
Christopher Faulet31af49d2015-06-09 17:29:50 +02005971}
5972
Emeric Brun46591952012-05-18 15:47:34 +02005973/*
5974 * This function is called if SSL * context is not yet allocated. The function
5975 * is designed to be called before any other data-layer operation and sets the
5976 * handshake flag on the connection. It is safe to call it multiple times.
5977 * It returns 0 on success and -1 in error case.
5978 */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005979static int ssl_sock_init(struct connection *conn, void **xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02005980{
Olivier Houchard66ab4982019-02-26 18:37:15 +01005981 struct ssl_sock_ctx *ctx;
Emeric Brun46591952012-05-18 15:47:34 +02005982 /* already initialized */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005983 if (*xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02005984 return 0;
5985
Willy Tarreau3c728722014-01-23 13:50:42 +01005986 if (!conn_ctrl_ready(conn))
Willy Tarreauf79c8172013-10-21 16:30:56 +02005987 return 0;
5988
Olivier Houchard66ab4982019-02-26 18:37:15 +01005989 ctx = pool_alloc(ssl_sock_ctx_pool);
5990 if (!ctx) {
5991 conn->err_code = CO_ER_SSL_NO_MEM;
5992 return -1;
5993 }
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02005994 ctx->wait_event.tasklet = tasklet_new();
5995 if (!ctx->wait_event.tasklet) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02005996 conn->err_code = CO_ER_SSL_NO_MEM;
5997 pool_free(ssl_sock_ctx_pool, ctx);
5998 return -1;
5999 }
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02006000 ctx->wait_event.tasklet->process = ssl_sock_io_cb;
6001 ctx->wait_event.tasklet->context = ctx;
Olivier Houchardea8dd942019-05-20 14:02:16 +02006002 ctx->wait_event.events = 0;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006003 ctx->sent_early_data = 0;
Olivier Houchard54907bb2019-12-19 15:02:39 +01006004 ctx->early_buf = BUF_NULL;
Olivier Houcharda8955d52019-04-07 22:00:38 +02006005 ctx->conn = conn;
Willy Tarreau113d52b2020-01-10 09:20:26 +01006006 ctx->subs = NULL;
Emeric Brun5762a0d2019-09-06 15:36:02 +02006007 ctx->xprt_st = 0;
6008 ctx->xprt_ctx = NULL;
Olivier Houcharda8955d52019-04-07 22:00:38 +02006009
6010 /* Only work with sockets for now, this should be adapted when we'll
6011 * add QUIC support.
6012 */
6013 ctx->xprt = xprt_get(XPRT_RAW);
Olivier Houchard19afb272019-05-23 18:24:07 +02006014 if (ctx->xprt->init) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02006015 if (ctx->xprt->init(conn, &ctx->xprt_ctx) != 0)
6016 goto err;
Olivier Houchard19afb272019-05-23 18:24:07 +02006017 }
Olivier Houchard66ab4982019-02-26 18:37:15 +01006018
Willy Tarreau20879a02012-12-03 16:32:10 +01006019 if (global.maxsslconn && sslconns >= global.maxsslconn) {
6020 conn->err_code = CO_ER_SSL_TOO_MANY;
Olivier Houchardea8dd942019-05-20 14:02:16 +02006021 goto err;
Willy Tarreau20879a02012-12-03 16:32:10 +01006022 }
Willy Tarreau403edff2012-09-06 11:58:37 +02006023
Emeric Brun46591952012-05-18 15:47:34 +02006024 /* If it is in client mode initiate SSL session
6025 in connect state otherwise accept state */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01006026 if (objt_server(conn->target)) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01006027 int may_retry = 1;
6028
6029 retry_connect:
Emeric Brun46591952012-05-18 15:47:34 +02006030 /* Alloc a new SSL session ctx */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006031 ctx->ssl = SSL_new(__objt_server(conn->target)->ssl_ctx.ctx);
6032 if (!ctx->ssl) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01006033 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01006034 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01006035 goto retry_connect;
6036 }
Willy Tarreau20879a02012-12-03 16:32:10 +01006037 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006038 goto err;
Willy Tarreau20879a02012-12-03 16:32:10 +01006039 }
Olivier Houcharda8955d52019-04-07 22:00:38 +02006040 ctx->bio = BIO_new(ha_meth);
6041 if (!ctx->bio) {
Olivier Houchardefe5e8e2020-01-24 15:17:38 +01006042 SSL_free(ctx->ssl);
6043 ctx->ssl = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01006044 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01006045 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01006046 goto retry_connect;
6047 }
Emeric Brun55476152014-11-12 17:35:37 +01006048 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006049 goto err;
Emeric Brun55476152014-11-12 17:35:37 +01006050 }
Olivier Houcharda8955d52019-04-07 22:00:38 +02006051 BIO_set_data(ctx->bio, ctx);
Olivier Houcharda8955d52019-04-07 22:00:38 +02006052 SSL_set_bio(ctx->ssl, ctx->bio, ctx->bio);
Emeric Brun46591952012-05-18 15:47:34 +02006053
Evan Broderbe554312013-06-27 00:05:25 -07006054 /* set connection pointer */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006055 if (!SSL_set_ex_data(ctx->ssl, ssl_app_data_index, conn)) {
6056 SSL_free(ctx->ssl);
6057 ctx->ssl = NULL;
Emeric Brun55476152014-11-12 17:35:37 +01006058 conn->xprt_ctx = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01006059 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01006060 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01006061 goto retry_connect;
6062 }
Emeric Brun55476152014-11-12 17:35:37 +01006063 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006064 goto err;
Emeric Brun55476152014-11-12 17:35:37 +01006065 }
6066
Olivier Houchard66ab4982019-02-26 18:37:15 +01006067 SSL_set_connect_state(ctx->ssl);
Willy Tarreau07d94e42018-09-20 10:57:52 +02006068 if (__objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr) {
6069 const unsigned char *ptr = __objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr;
6070 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 +01006071 if (sess && !SSL_set_session(ctx->ssl, sess)) {
Olivier Houcharde6060c52017-11-16 17:42:52 +01006072 SSL_SESSION_free(sess);
Willy Tarreau07d94e42018-09-20 10:57:52 +02006073 free(__objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr);
6074 __objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr = NULL;
Olivier Houcharde6060c52017-11-16 17:42:52 +01006075 } else if (sess) {
6076 SSL_SESSION_free(sess);
Emeric Brun55476152014-11-12 17:35:37 +01006077 }
6078 }
Evan Broderbe554312013-06-27 00:05:25 -07006079
Emeric Brun46591952012-05-18 15:47:34 +02006080 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +02006081 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Willy Tarreau403edff2012-09-06 11:58:37 +02006082
Olivier Houchard2be5a4c2019-03-08 18:54:43 +01006083 _HA_ATOMIC_ADD(&sslconns, 1);
6084 _HA_ATOMIC_ADD(&totalsslconns, 1);
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006085 *xprt_ctx = ctx;
Olivier Houchardea8dd942019-05-20 14:02:16 +02006086 /* Start the handshake */
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02006087 tasklet_wakeup(ctx->wait_event.tasklet);
Emeric Brun46591952012-05-18 15:47:34 +02006088 return 0;
6089 }
Willy Tarreau3fdb3662012-11-12 00:42:33 +01006090 else if (objt_listener(conn->target)) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01006091 int may_retry = 1;
6092
6093 retry_accept:
Emeric Brun46591952012-05-18 15:47:34 +02006094 /* Alloc a new SSL session ctx */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006095 ctx->ssl = SSL_new(__objt_listener(conn->target)->bind_conf->initial_ctx);
6096 if (!ctx->ssl) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01006097 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01006098 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01006099 goto retry_accept;
6100 }
Willy Tarreau20879a02012-12-03 16:32:10 +01006101 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006102 goto err;
Willy Tarreau20879a02012-12-03 16:32:10 +01006103 }
Olivier Houcharda8955d52019-04-07 22:00:38 +02006104 ctx->bio = BIO_new(ha_meth);
6105 if (!ctx->bio) {
Olivier Houchardefe5e8e2020-01-24 15:17:38 +01006106 SSL_free(ctx->ssl);
6107 ctx->ssl = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01006108 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01006109 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01006110 goto retry_accept;
6111 }
Emeric Brun55476152014-11-12 17:35:37 +01006112 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006113 goto err;
Emeric Brun55476152014-11-12 17:35:37 +01006114 }
Olivier Houcharda8955d52019-04-07 22:00:38 +02006115 BIO_set_data(ctx->bio, ctx);
Olivier Houcharda8955d52019-04-07 22:00:38 +02006116 SSL_set_bio(ctx->ssl, ctx->bio, ctx->bio);
Emeric Brun46591952012-05-18 15:47:34 +02006117
Emeric Brune1f38db2012-09-03 20:36:47 +02006118 /* set connection pointer */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006119 if (!SSL_set_ex_data(ctx->ssl, ssl_app_data_index, conn)) {
6120 SSL_free(ctx->ssl);
6121 ctx->ssl = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01006122 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01006123 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01006124 goto retry_accept;
6125 }
Emeric Brun55476152014-11-12 17:35:37 +01006126 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006127 goto err;
Emeric Brun55476152014-11-12 17:35:37 +01006128 }
6129
Frédéric Lécaille3139c1b2020-01-24 14:56:18 +01006130#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
6131 if (__objt_listener(conn->target)->bind_conf->ssl_conf.early_data) {
6132 b_alloc(&ctx->early_buf);
6133 SSL_set_max_early_data(ctx->ssl,
6134 /* Only allow early data if we managed to allocate
6135 * a buffer.
6136 */
6137 (!b_is_null(&ctx->early_buf)) ?
6138 global.tune.bufsize - global.tune.maxrewrite : 0);
6139 }
6140#endif
6141
Olivier Houchard66ab4982019-02-26 18:37:15 +01006142 SSL_set_accept_state(ctx->ssl);
Emeric Brune1f38db2012-09-03 20:36:47 +02006143
Emeric Brun46591952012-05-18 15:47:34 +02006144 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +02006145 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Emmanuel Hocdetf967c312019-08-05 18:04:16 +02006146#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Olivier Houchardc2aae742017-09-22 18:26:28 +02006147 conn->flags |= CO_FL_EARLY_SSL_HS;
6148#endif
Willy Tarreau403edff2012-09-06 11:58:37 +02006149
Olivier Houchard2be5a4c2019-03-08 18:54:43 +01006150 _HA_ATOMIC_ADD(&sslconns, 1);
6151 _HA_ATOMIC_ADD(&totalsslconns, 1);
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006152 *xprt_ctx = ctx;
Olivier Houchardea8dd942019-05-20 14:02:16 +02006153 /* Start the handshake */
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02006154 tasklet_wakeup(ctx->wait_event.tasklet);
Emeric Brun46591952012-05-18 15:47:34 +02006155 return 0;
6156 }
6157 /* don't know how to handle such a target */
Willy Tarreau20879a02012-12-03 16:32:10 +01006158 conn->err_code = CO_ER_SSL_NO_TARGET;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006159err:
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02006160 if (ctx && ctx->wait_event.tasklet)
6161 tasklet_free(ctx->wait_event.tasklet);
Olivier Houchard66ab4982019-02-26 18:37:15 +01006162 pool_free(ssl_sock_ctx_pool, ctx);
Emeric Brun46591952012-05-18 15:47:34 +02006163 return -1;
6164}
6165
6166
6167/* This is the callback which is used when an SSL handshake is pending. It
6168 * updates the FD status if it wants some polling before being called again.
6169 * It returns 0 if it fails in a fatal way or needs to poll to go further,
6170 * otherwise it returns non-zero and removes itself from the connection's
6171 * flags (the bit is provided in <flag> by the caller).
6172 */
Olivier Houchard000694c2019-05-23 14:45:12 +02006173static int ssl_sock_handshake(struct connection *conn, unsigned int flag)
Emeric Brun46591952012-05-18 15:47:34 +02006174{
Olivier Houchard66ab4982019-02-26 18:37:15 +01006175 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
Emeric Brun46591952012-05-18 15:47:34 +02006176 int ret;
6177
Willy Tarreau3c728722014-01-23 13:50:42 +01006178 if (!conn_ctrl_ready(conn))
Willy Tarreauf79c8172013-10-21 16:30:56 +02006179 return 0;
6180
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02006181 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02006182 goto out_error;
6183
Willy Tarreau5db847a2019-05-09 14:13:35 +02006184#if HA_OPENSSL_VERSION_NUMBER >= 0x10101000L
Olivier Houchardc2aae742017-09-22 18:26:28 +02006185 /*
6186 * Check if we have early data. If we do, we have to read them
6187 * before SSL_do_handshake() is called, And there's no way to
6188 * detect early data, except to try to read them
6189 */
6190 if (conn->flags & CO_FL_EARLY_SSL_HS) {
Olivier Houchard54907bb2019-12-19 15:02:39 +01006191 size_t read_data = 0;
Olivier Houchardc2aae742017-09-22 18:26:28 +02006192
Olivier Houchard54907bb2019-12-19 15:02:39 +01006193 while (1) {
6194 ret = SSL_read_early_data(ctx->ssl,
6195 b_tail(&ctx->early_buf), b_room(&ctx->early_buf),
6196 &read_data);
6197 if (ret == SSL_READ_EARLY_DATA_ERROR)
6198 goto check_error;
6199 if (read_data > 0) {
6200 conn->flags |= CO_FL_EARLY_DATA;
6201 b_add(&ctx->early_buf, read_data);
6202 }
6203 if (ret == SSL_READ_EARLY_DATA_FINISH) {
6204 conn->flags &= ~CO_FL_EARLY_SSL_HS;
6205 if (!b_data(&ctx->early_buf))
6206 b_free(&ctx->early_buf);
6207 break;
6208 }
6209 }
Olivier Houchardc2aae742017-09-22 18:26:28 +02006210 }
6211#endif
Emeric Brun674b7432012-11-08 19:21:55 +01006212 /* If we use SSL_do_handshake to process a reneg initiated by
6213 * the remote peer, it sometimes returns SSL_ERROR_SSL.
6214 * Usually SSL_write and SSL_read are used and process implicitly
6215 * the reneg handshake.
6216 * Here we use SSL_peek as a workaround for reneg.
6217 */
Willy Tarreauc192b0a2020-01-23 09:11:58 +01006218 if (!(conn->flags & CO_FL_WAIT_L6_CONN) && SSL_renegotiate_pending(ctx->ssl)) {
Emeric Brun674b7432012-11-08 19:21:55 +01006219 char c;
6220
Olivier Houchard66ab4982019-02-26 18:37:15 +01006221 ret = SSL_peek(ctx->ssl, &c, 1);
Emeric Brun674b7432012-11-08 19:21:55 +01006222 if (ret <= 0) {
6223 /* handshake may have not been completed, let's find why */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006224 ret = SSL_get_error(ctx->ssl, ret);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006225
Emeric Brun674b7432012-11-08 19:21:55 +01006226 if (ret == SSL_ERROR_WANT_WRITE) {
6227 /* SSL handshake needs to write, L4 connection may not be ready */
Olivier Houchard03abf2d2019-05-28 10:12:02 +02006228 if (!(ctx->wait_event.events & SUB_RETRY_SEND))
Olivier Houchardea8dd942019-05-20 14:02:16 +02006229 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_SEND, &ctx->wait_event);
Emeric Brun674b7432012-11-08 19:21:55 +01006230 return 0;
6231 }
6232 else if (ret == SSL_ERROR_WANT_READ) {
6233 /* handshake may have been completed but we have
6234 * no more data to read.
6235 */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006236 if (!SSL_renegotiate_pending(ctx->ssl)) {
Emeric Brun674b7432012-11-08 19:21:55 +01006237 ret = 1;
6238 goto reneg_ok;
6239 }
6240 /* SSL handshake needs to read, L4 connection is ready */
Olivier Houchard03abf2d2019-05-28 10:12:02 +02006241 if (!(ctx->wait_event.events & SUB_RETRY_RECV))
Olivier Houchardea8dd942019-05-20 14:02:16 +02006242 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_RECV, &ctx->wait_event);
Emeric Brun674b7432012-11-08 19:21:55 +01006243 return 0;
6244 }
Willy Tarreau5db847a2019-05-09 14:13:35 +02006245#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006246 else if (ret == SSL_ERROR_WANT_ASYNC) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02006247 ssl_async_process_fds(ctx);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006248 return 0;
6249 }
6250#endif
Emeric Brun674b7432012-11-08 19:21:55 +01006251 else if (ret == SSL_ERROR_SYSCALL) {
6252 /* if errno is null, then connection was successfully established */
6253 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
6254 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Willy Tarreau20879a02012-12-03 16:32:10 +01006255 if (!conn->err_code) {
Lukas Tribus49799162019-07-08 14:29:15 +02006256#if defined(OPENSSL_IS_BORINGSSL) || defined(LIBRESSL_VERSION_NUMBER)
6257 /* do not handle empty handshakes in BoringSSL or LibreSSL */
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01006258 conn->err_code = CO_ER_SSL_HANDSHAKE;
6259#else
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006260 int empty_handshake;
Willy Tarreau5db847a2019-05-09 14:13:35 +02006261#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL)
Lukas Tribus49799162019-07-08 14:29:15 +02006262 /* use SSL_get_state() in OpenSSL >= 1.1.0; SSL_state() is broken */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006263 OSSL_HANDSHAKE_STATE state = SSL_get_state((SSL *)ctx->ssl);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006264 empty_handshake = state == TLS_ST_BEFORE;
6265#else
Lukas Tribus49799162019-07-08 14:29:15 +02006266 /* access packet_length directly in OpenSSL <= 1.0.2; SSL_state() is broken */
6267 empty_handshake = !ctx->ssl->packet_length;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006268#endif
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006269 if (empty_handshake) {
Emeric Brun29f037d2014-04-25 19:05:36 +02006270 if (!errno) {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006271 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emeric Brun29f037d2014-04-25 19:05:36 +02006272 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
6273 else
6274 conn->err_code = CO_ER_SSL_EMPTY;
6275 }
6276 else {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006277 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emeric Brun29f037d2014-04-25 19:05:36 +02006278 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
6279 else
6280 conn->err_code = CO_ER_SSL_ABORT;
6281 }
6282 }
6283 else {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006284 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emeric Brun29f037d2014-04-25 19:05:36 +02006285 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
Willy Tarreau20879a02012-12-03 16:32:10 +01006286 else
Emeric Brun29f037d2014-04-25 19:05:36 +02006287 conn->err_code = CO_ER_SSL_HANDSHAKE;
6288 }
Lukas Tribus49799162019-07-08 14:29:15 +02006289#endif /* BoringSSL or LibreSSL */
Willy Tarreau20879a02012-12-03 16:32:10 +01006290 }
Emeric Brun674b7432012-11-08 19:21:55 +01006291 goto out_error;
6292 }
6293 else {
6294 /* Fail on all other handshake errors */
6295 /* Note: OpenSSL may leave unread bytes in the socket's
6296 * buffer, causing an RST to be emitted upon close() on
6297 * TCP sockets. We first try to drain possibly pending
6298 * data to avoid this as much as possible.
6299 */
Willy Tarreaud85c4852015-03-13 00:40:28 +01006300 conn_sock_drain(conn);
Willy Tarreau20879a02012-12-03 16:32:10 +01006301 if (!conn->err_code)
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006302 conn->err_code = (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT) ?
Willy Tarreauf51c6982014-04-25 20:02:39 +02006303 CO_ER_SSL_KILLED_HB : CO_ER_SSL_HANDSHAKE;
Emeric Brun674b7432012-11-08 19:21:55 +01006304 goto out_error;
6305 }
6306 }
6307 /* read some data: consider handshake completed */
6308 goto reneg_ok;
6309 }
Olivier Houchard66ab4982019-02-26 18:37:15 +01006310 ret = SSL_do_handshake(ctx->ssl);
Olivier Houchardc2aae742017-09-22 18:26:28 +02006311check_error:
Emeric Brun46591952012-05-18 15:47:34 +02006312 if (ret != 1) {
6313 /* handshake did not complete, let's find why */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006314 ret = SSL_get_error(ctx->ssl, ret);
Emeric Brun46591952012-05-18 15:47:34 +02006315
6316 if (ret == SSL_ERROR_WANT_WRITE) {
6317 /* SSL handshake needs to write, L4 connection may not be ready */
Olivier Houchard03abf2d2019-05-28 10:12:02 +02006318 if (!(ctx->wait_event.events & SUB_RETRY_SEND))
Olivier Houchardea8dd942019-05-20 14:02:16 +02006319 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_SEND, &ctx->wait_event);
Emeric Brun46591952012-05-18 15:47:34 +02006320 return 0;
6321 }
6322 else if (ret == SSL_ERROR_WANT_READ) {
6323 /* SSL handshake needs to read, L4 connection is ready */
Olivier Houchardea8dd942019-05-20 14:02:16 +02006324 if (!(ctx->wait_event.events & SUB_RETRY_RECV))
Olivier Houchardea8dd942019-05-20 14:02:16 +02006325 ctx->xprt->subscribe(conn, ctx->xprt_ctx,
6326 SUB_RETRY_RECV, &ctx->wait_event);
Emeric Brun46591952012-05-18 15:47:34 +02006327 return 0;
6328 }
Willy Tarreau5db847a2019-05-09 14:13:35 +02006329#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006330 else if (ret == SSL_ERROR_WANT_ASYNC) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02006331 ssl_async_process_fds(ctx);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006332 return 0;
6333 }
6334#endif
Willy Tarreau89230192012-09-28 20:22:13 +02006335 else if (ret == SSL_ERROR_SYSCALL) {
6336 /* if errno is null, then connection was successfully established */
6337 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
6338 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01006339 if (!conn->err_code) {
Lukas Tribus49799162019-07-08 14:29:15 +02006340#if defined(OPENSSL_IS_BORINGSSL) || defined(LIBRESSL_VERSION_NUMBER)
6341 /* do not handle empty handshakes in BoringSSL or LibreSSL */
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01006342 conn->err_code = CO_ER_SSL_HANDSHAKE;
6343#else
6344 int empty_handshake;
Willy Tarreau5db847a2019-05-09 14:13:35 +02006345#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL)
Lukas Tribus49799162019-07-08 14:29:15 +02006346 /* use SSL_get_state() in OpenSSL >= 1.1.0; SSL_state() is broken */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006347 OSSL_HANDSHAKE_STATE state = SSL_get_state(ctx->ssl);
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01006348 empty_handshake = state == TLS_ST_BEFORE;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006349#else
Lukas Tribus49799162019-07-08 14:29:15 +02006350 /* access packet_length directly in OpenSSL <= 1.0.2; SSL_state() is broken */
6351 empty_handshake = !ctx->ssl->packet_length;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006352#endif
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01006353 if (empty_handshake) {
6354 if (!errno) {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006355 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01006356 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
6357 else
6358 conn->err_code = CO_ER_SSL_EMPTY;
6359 }
6360 else {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006361 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01006362 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
6363 else
6364 conn->err_code = CO_ER_SSL_ABORT;
6365 }
Emeric Brun29f037d2014-04-25 19:05:36 +02006366 }
6367 else {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006368 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emeric Brun29f037d2014-04-25 19:05:36 +02006369 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
6370 else
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01006371 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun29f037d2014-04-25 19:05:36 +02006372 }
Lukas Tribus49799162019-07-08 14:29:15 +02006373#endif /* BoringSSL or LibreSSL */
Emeric Brun29f037d2014-04-25 19:05:36 +02006374 }
Willy Tarreau89230192012-09-28 20:22:13 +02006375 goto out_error;
6376 }
Emeric Brun46591952012-05-18 15:47:34 +02006377 else {
6378 /* Fail on all other handshake errors */
Willy Tarreau566dc552012-10-19 20:52:18 +02006379 /* Note: OpenSSL may leave unread bytes in the socket's
6380 * buffer, causing an RST to be emitted upon close() on
6381 * TCP sockets. We first try to drain possibly pending
6382 * data to avoid this as much as possible.
6383 */
Willy Tarreaud85c4852015-03-13 00:40:28 +01006384 conn_sock_drain(conn);
Willy Tarreau20879a02012-12-03 16:32:10 +01006385 if (!conn->err_code)
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006386 conn->err_code = (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT) ?
Willy Tarreauf51c6982014-04-25 20:02:39 +02006387 CO_ER_SSL_KILLED_HB : CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02006388 goto out_error;
6389 }
6390 }
Willy Tarreau5db847a2019-05-09 14:13:35 +02006391#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Olivier Houchard522eea72017-11-03 16:27:47 +01006392 else {
6393 /*
6394 * If the server refused the early data, we have to send a
6395 * 425 to the client, as we no longer have the data to sent
6396 * them again.
6397 */
6398 if ((conn->flags & CO_FL_EARLY_DATA) && (objt_server(conn->target))) {
Olivier Houchard66ab4982019-02-26 18:37:15 +01006399 if (SSL_get_early_data_status(ctx->ssl) == SSL_EARLY_DATA_REJECTED) {
Olivier Houchard522eea72017-11-03 16:27:47 +01006400 conn->err_code = CO_ER_SSL_EARLY_FAILED;
6401 goto out_error;
6402 }
6403 }
6404 }
6405#endif
6406
Emeric Brun46591952012-05-18 15:47:34 +02006407
Emeric Brun674b7432012-11-08 19:21:55 +01006408reneg_ok:
Emeric Brunb5e42a82017-06-06 12:35:14 +00006409
Willy Tarreau5db847a2019-05-09 14:13:35 +02006410#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00006411 /* ASYNC engine API doesn't support moving read/write
6412 * buffers. So we disable ASYNC mode right after
6413 * the handshake to avoid buffer oveflows.
6414 */
6415 if (global_ssl.async)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006416 SSL_clear_mode(ctx->ssl, SSL_MODE_ASYNC);
Emeric Brunb5e42a82017-06-06 12:35:14 +00006417#endif
Emeric Brun46591952012-05-18 15:47:34 +02006418 /* Handshake succeeded */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006419 if (!SSL_session_reused(ctx->ssl)) {
Willy Tarreau0c9c2722014-05-28 12:28:58 +02006420 if (objt_server(conn->target)) {
6421 update_freq_ctr(&global.ssl_be_keys_per_sec, 1);
6422 if (global.ssl_be_keys_per_sec.curr_ctr > global.ssl_be_keys_max)
6423 global.ssl_be_keys_max = global.ssl_be_keys_per_sec.curr_ctr;
Emeric Brun46591952012-05-18 15:47:34 +02006424 }
Willy Tarreau0c9c2722014-05-28 12:28:58 +02006425 else {
6426 update_freq_ctr(&global.ssl_fe_keys_per_sec, 1);
6427 if (global.ssl_fe_keys_per_sec.curr_ctr > global.ssl_fe_keys_max)
6428 global.ssl_fe_keys_max = global.ssl_fe_keys_per_sec.curr_ctr;
6429 }
Emeric Brun46591952012-05-18 15:47:34 +02006430 }
6431
6432 /* The connection is now established at both layers, it's time to leave */
6433 conn->flags &= ~(flag | CO_FL_WAIT_L4_CONN | CO_FL_WAIT_L6_CONN);
6434 return 1;
6435
6436 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01006437 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02006438 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01006439 ERR_clear_error();
6440
Emeric Brun9fa89732012-10-04 17:09:56 +02006441 /* free resumed session if exists */
Willy Tarreau07d94e42018-09-20 10:57:52 +02006442 if (objt_server(conn->target) && __objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr) {
6443 free(__objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr);
6444 __objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr = NULL;
Emeric Brun9fa89732012-10-04 17:09:56 +02006445 }
6446
Emeric Brun46591952012-05-18 15:47:34 +02006447 /* Fail on all other handshake errors */
6448 conn->flags |= CO_FL_ERROR;
Willy Tarreau20879a02012-12-03 16:32:10 +01006449 if (!conn->err_code)
6450 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02006451 return 0;
6452}
6453
Willy Tarreauee1a6fc2020-01-17 07:52:13 +01006454/* Called from the upper layer, to subscribe <es> to events <event_type>. The
6455 * event subscriber <es> is not allowed to change from a previous call as long
6456 * as at least one event is still subscribed. The <event_type> must only be a
6457 * combination of SUB_RETRY_RECV and SUB_RETRY_SEND. It always returns 0,
6458 * unless the transport layer was already released.
6459 */
6460static int ssl_subscribe(struct connection *conn, void *xprt_ctx, int event_type, struct wait_event *es)
Olivier Houcharddf357842019-03-21 16:30:07 +01006461{
Olivier Houchardea8dd942019-05-20 14:02:16 +02006462 struct ssl_sock_ctx *ctx = xprt_ctx;
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006463
Olivier Houchard0ff28652019-06-24 18:57:39 +02006464 if (!ctx)
6465 return -1;
6466
Willy Tarreau113d52b2020-01-10 09:20:26 +01006467 BUG_ON(event_type & ~(SUB_RETRY_SEND|SUB_RETRY_RECV));
6468 BUG_ON(ctx->subs && ctx->subs->events & event_type);
Willy Tarreauee1a6fc2020-01-17 07:52:13 +01006469 BUG_ON(ctx->subs && ctx->subs != es);
Olivier Houchardea8dd942019-05-20 14:02:16 +02006470
Willy Tarreauee1a6fc2020-01-17 07:52:13 +01006471 ctx->subs = es;
6472 es->events |= event_type;
Willy Tarreau113d52b2020-01-10 09:20:26 +01006473
6474 /* we may have to subscribe to lower layers for new events */
6475 event_type &= ~ctx->wait_event.events;
6476 if (event_type && !(conn->flags & CO_FL_SSL_WAIT_HS))
6477 ctx->xprt->subscribe(conn, ctx->xprt_ctx, event_type, &ctx->wait_event);
Olivier Houchardea8dd942019-05-20 14:02:16 +02006478 return 0;
Olivier Houcharddf357842019-03-21 16:30:07 +01006479}
6480
Willy Tarreauee1a6fc2020-01-17 07:52:13 +01006481/* Called from the upper layer, to unsubscribe <es> from events <event_type>.
6482 * The <es> pointer is not allowed to differ from the one passed to the
6483 * subscribe() call. It always returns zero.
6484 */
6485static int ssl_unsubscribe(struct connection *conn, void *xprt_ctx, int event_type, struct wait_event *es)
Olivier Houcharddf357842019-03-21 16:30:07 +01006486{
Olivier Houchardea8dd942019-05-20 14:02:16 +02006487 struct ssl_sock_ctx *ctx = xprt_ctx;
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006488
Willy Tarreau113d52b2020-01-10 09:20:26 +01006489 BUG_ON(event_type & ~(SUB_RETRY_SEND|SUB_RETRY_RECV));
Willy Tarreauee1a6fc2020-01-17 07:52:13 +01006490 BUG_ON(ctx->subs && ctx->subs != es);
Olivier Houchardea8dd942019-05-20 14:02:16 +02006491
Willy Tarreauee1a6fc2020-01-17 07:52:13 +01006492 es->events &= ~event_type;
6493 if (!es->events)
Willy Tarreau113d52b2020-01-10 09:20:26 +01006494 ctx->subs = NULL;
6495
6496 /* If we subscribed, and we're not doing the handshake,
6497 * then we subscribed because the upper layer asked for it,
6498 * as the upper layer is no longer interested, we can
6499 * unsubscribe too.
6500 */
6501 event_type &= ctx->wait_event.events;
6502 if (event_type && !(ctx->conn->flags & CO_FL_SSL_WAIT_HS))
6503 conn_unsubscribe(conn, ctx->xprt_ctx, event_type, &ctx->wait_event);
Olivier Houchardea8dd942019-05-20 14:02:16 +02006504
6505 return 0;
Olivier Houcharddf357842019-03-21 16:30:07 +01006506}
6507
Olivier Houchard2e055482019-05-27 19:50:12 +02006508/* Use the provided XPRT as an underlying XPRT, and provide the old one.
6509 * Returns 0 on success, and non-zero on failure.
6510 */
6511static 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)
6512{
6513 struct ssl_sock_ctx *ctx = xprt_ctx;
6514
6515 if (oldxprt_ops != NULL)
6516 *oldxprt_ops = ctx->xprt;
6517 if (oldxprt_ctx != NULL)
6518 *oldxprt_ctx = ctx->xprt_ctx;
6519 ctx->xprt = toadd_ops;
6520 ctx->xprt_ctx = toadd_ctx;
6521 return 0;
6522}
6523
Olivier Houchard5149b592019-05-23 17:47:36 +02006524/* Remove the specified xprt. If if it our underlying XPRT, remove it and
6525 * return 0, otherwise just call the remove_xprt method from the underlying
6526 * XPRT.
6527 */
6528static int ssl_remove_xprt(struct connection *conn, void *xprt_ctx, void *toremove_ctx, const struct xprt_ops *newops, void *newctx)
6529{
6530 struct ssl_sock_ctx *ctx = xprt_ctx;
6531
6532 if (ctx->xprt_ctx == toremove_ctx) {
6533 ctx->xprt_ctx = newctx;
6534 ctx->xprt = newops;
6535 return 0;
6536 }
6537 return (ctx->xprt->remove_xprt(conn, ctx->xprt_ctx, toremove_ctx, newops, newctx));
6538}
6539
Olivier Houchardea8dd942019-05-20 14:02:16 +02006540static struct task *ssl_sock_io_cb(struct task *t, void *context, unsigned short state)
6541{
6542 struct ssl_sock_ctx *ctx = context;
6543
6544 /* First if we're doing an handshake, try that */
6545 if (ctx->conn->flags & CO_FL_SSL_WAIT_HS)
6546 ssl_sock_handshake(ctx->conn, CO_FL_SSL_WAIT_HS);
6547 /* If we had an error, or the handshake is done and I/O is available,
6548 * let the upper layer know.
Olivier Houchard477902b2020-01-22 18:08:48 +01006549 * If no mux was set up yet, then call conn_create_mux()
Olivier Houchardea8dd942019-05-20 14:02:16 +02006550 * we can't be sure conn_fd_handler() will be called again.
6551 */
6552 if ((ctx->conn->flags & CO_FL_ERROR) ||
6553 !(ctx->conn->flags & CO_FL_SSL_WAIT_HS)) {
6554 int ret = 0;
6555 int woke = 0;
6556
6557 /* On error, wake any waiter */
Willy Tarreau113d52b2020-01-10 09:20:26 +01006558 if (ctx->subs) {
6559 tasklet_wakeup(ctx->subs->tasklet);
6560 ctx->subs->events = 0;
Olivier Houchardea8dd942019-05-20 14:02:16 +02006561 woke = 1;
Willy Tarreau113d52b2020-01-10 09:20:26 +01006562 ctx->subs = NULL;
Olivier Houchardea8dd942019-05-20 14:02:16 +02006563 }
Willy Tarreau113d52b2020-01-10 09:20:26 +01006564
Olivier Houchardea8dd942019-05-20 14:02:16 +02006565 /* If we're the first xprt for the connection, let the
Olivier Houchard477902b2020-01-22 18:08:48 +01006566 * upper layers know. If we have no mux, create it,
6567 * and once we have a mux, call its wake method if we didn't
6568 * woke a tasklet already.
Olivier Houchardea8dd942019-05-20 14:02:16 +02006569 */
6570 if (ctx->conn->xprt_ctx == ctx) {
Olivier Houchard477902b2020-01-22 18:08:48 +01006571 if (!ctx->conn->mux)
6572 ret = conn_create_mux(ctx->conn);
Olivier Houchardea8dd942019-05-20 14:02:16 +02006573 if (ret >= 0 && !woke && ctx->conn->mux && ctx->conn->mux->wake)
6574 ctx->conn->mux->wake(ctx->conn);
6575 return NULL;
6576 }
6577 }
Olivier Houchard54907bb2019-12-19 15:02:39 +01006578#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
6579 /* If we have early data and somebody wants to receive, let them */
Willy Tarreau113d52b2020-01-10 09:20:26 +01006580 else if (b_data(&ctx->early_buf) && ctx->subs &&
6581 ctx->subs->events & SUB_RETRY_RECV) {
6582 tasklet_wakeup(ctx->subs->tasklet);
6583 ctx->subs->events &= ~SUB_RETRY_RECV;
6584 if (!ctx->subs->events)
6585 ctx->subs = NULL;
Olivier Houchard54907bb2019-12-19 15:02:39 +01006586 }
6587#endif
Olivier Houchardea8dd942019-05-20 14:02:16 +02006588 return NULL;
6589}
6590
Emeric Brun46591952012-05-18 15:47:34 +02006591/* Receive up to <count> bytes from connection <conn>'s socket and store them
Willy Tarreauabf08d92014-01-14 11:31:27 +01006592 * into buffer <buf>. Only one call to recv() is performed, unless the
Emeric Brun46591952012-05-18 15:47:34 +02006593 * buffer wraps, in which case a second call may be performed. The connection's
6594 * flags are updated with whatever special event is detected (error, read0,
6595 * empty). The caller is responsible for taking care of those events and
6596 * avoiding the call if inappropriate. The function does not call the
6597 * connection's polling update function, so the caller is responsible for this.
6598 */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006599static 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 +02006600{
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006601 struct ssl_sock_ctx *ctx = xprt_ctx;
Willy Tarreaubfc4d772018-07-18 11:22:03 +02006602 ssize_t ret;
6603 size_t try, done = 0;
Emeric Brun46591952012-05-18 15:47:34 +02006604
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006605 if (!ctx)
Emeric Brun46591952012-05-18 15:47:34 +02006606 goto out_error;
6607
Olivier Houchard54907bb2019-12-19 15:02:39 +01006608#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
6609 if (b_data(&ctx->early_buf)) {
6610 try = b_contig_space(buf);
6611 if (try > b_data(&ctx->early_buf))
6612 try = b_data(&ctx->early_buf);
6613 memcpy(b_tail(buf), b_head(&ctx->early_buf), try);
6614 b_add(buf, try);
6615 b_del(&ctx->early_buf, try);
6616 if (b_data(&ctx->early_buf) == 0)
6617 b_free(&ctx->early_buf);
6618 return try;
6619 }
6620#endif
6621
Willy Tarreau911db9b2020-01-23 16:27:54 +01006622 if (conn->flags & (CO_FL_WAIT_XPRT | CO_FL_SSL_WAIT_HS))
Emeric Brun46591952012-05-18 15:47:34 +02006623 /* a handshake was requested */
6624 return 0;
6625
Emeric Brun46591952012-05-18 15:47:34 +02006626 /* read the largest possible block. For this, we perform only one call
6627 * to recv() unless the buffer wraps and we exactly fill the first hunk,
6628 * in which case we accept to do it once again. A new attempt is made on
6629 * EINTR too.
6630 */
Willy Tarreau00b0fb92014-01-17 11:09:40 +01006631 while (count > 0) {
Olivier Houchardc2aae742017-09-22 18:26:28 +02006632
Willy Tarreau591d4452018-06-15 17:21:00 +02006633 try = b_contig_space(buf);
6634 if (!try)
6635 break;
6636
Willy Tarreauabf08d92014-01-14 11:31:27 +01006637 if (try > count)
6638 try = count;
Willy Tarreau591d4452018-06-15 17:21:00 +02006639
Olivier Houchard66ab4982019-02-26 18:37:15 +01006640 ret = SSL_read(ctx->ssl, b_tail(buf), try);
Emmanuel Hocdetf967c312019-08-05 18:04:16 +02006641
Emeric Brune1f38db2012-09-03 20:36:47 +02006642 if (conn->flags & CO_FL_ERROR) {
6643 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01006644 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02006645 }
Emeric Brun46591952012-05-18 15:47:34 +02006646 if (ret > 0) {
Olivier Houchardacd14032018-06-28 18:17:23 +02006647 b_add(buf, ret);
Emeric Brun46591952012-05-18 15:47:34 +02006648 done += ret;
Emeric Brun46591952012-05-18 15:47:34 +02006649 count -= ret;
Emeric Brun46591952012-05-18 15:47:34 +02006650 }
Emeric Brun46591952012-05-18 15:47:34 +02006651 else {
Olivier Houchard66ab4982019-02-26 18:37:15 +01006652 ret = SSL_get_error(ctx->ssl, ret);
Emeric Brun46591952012-05-18 15:47:34 +02006653 if (ret == SSL_ERROR_WANT_WRITE) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01006654 /* handshake is running, and it needs to enable write */
Emeric Brun46591952012-05-18 15:47:34 +02006655 conn->flags |= CO_FL_SSL_WAIT_HS;
Olivier Houchardea8dd942019-05-20 14:02:16 +02006656 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_SEND, &ctx->wait_event);
Willy Tarreau5db847a2019-05-09 14:13:35 +02006657#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00006658 /* Async mode can be re-enabled, because we're leaving data state.*/
6659 if (global_ssl.async)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006660 SSL_set_mode(ctx->ssl, SSL_MODE_ASYNC);
Emeric Brunb5e42a82017-06-06 12:35:14 +00006661#endif
Emeric Brun46591952012-05-18 15:47:34 +02006662 break;
6663 }
6664 else if (ret == SSL_ERROR_WANT_READ) {
Olivier Houchard66ab4982019-02-26 18:37:15 +01006665 if (SSL_renegotiate_pending(ctx->ssl)) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02006666 ctx->xprt->subscribe(conn, ctx->xprt_ctx,
6667 SUB_RETRY_RECV,
6668 &ctx->wait_event);
Emeric Brun282a76a2012-11-08 18:02:56 +01006669 /* handshake is running, and it may need to re-enable read */
6670 conn->flags |= CO_FL_SSL_WAIT_HS;
Willy Tarreau5db847a2019-05-09 14:13:35 +02006671#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00006672 /* Async mode can be re-enabled, because we're leaving data state.*/
6673 if (global_ssl.async)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006674 SSL_set_mode(ctx->ssl, SSL_MODE_ASYNC);
Emeric Brunb5e42a82017-06-06 12:35:14 +00006675#endif
Emeric Brun282a76a2012-11-08 18:02:56 +01006676 break;
6677 }
Emeric Brun46591952012-05-18 15:47:34 +02006678 break;
Olivier Houchardc2aae742017-09-22 18:26:28 +02006679 } else if (ret == SSL_ERROR_ZERO_RETURN)
6680 goto read0;
Christopher Faulet4ac77a92018-02-19 14:25:15 +01006681 /* For SSL_ERROR_SYSCALL, make sure to clear the error
6682 * stack before shutting down the connection for
6683 * reading. */
Olivier Houchard7e2e5052018-02-13 15:17:23 +01006684 if (ret == SSL_ERROR_SYSCALL && (!errno || errno == EAGAIN))
6685 goto clear_ssl_error;
Emeric Brun46591952012-05-18 15:47:34 +02006686 /* otherwise it's a real error */
6687 goto out_error;
6688 }
6689 }
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02006690 leave:
Emeric Brun46591952012-05-18 15:47:34 +02006691 return done;
6692
Christopher Faulet4ac77a92018-02-19 14:25:15 +01006693 clear_ssl_error:
6694 /* Clear openssl global errors stack */
6695 ssl_sock_dump_errors(conn);
6696 ERR_clear_error();
Emeric Brun46591952012-05-18 15:47:34 +02006697 read0:
6698 conn_sock_read0(conn);
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02006699 goto leave;
Christopher Faulet4ac77a92018-02-19 14:25:15 +01006700
Emeric Brun46591952012-05-18 15:47:34 +02006701 out_error:
Olivier Houchard7e2e5052018-02-13 15:17:23 +01006702 conn->flags |= CO_FL_ERROR;
Emeric Brun644cde02012-12-14 11:21:13 +01006703 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02006704 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01006705 ERR_clear_error();
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02006706 goto leave;
Emeric Brun46591952012-05-18 15:47:34 +02006707}
6708
6709
Willy Tarreau787db9a2018-06-14 18:31:46 +02006710/* Send up to <count> pending bytes from buffer <buf> to connection <conn>'s
6711 * socket. <flags> may contain some CO_SFL_* flags to hint the system about
6712 * other pending data for example, but this flag is ignored at the moment.
Emeric Brun46591952012-05-18 15:47:34 +02006713 * Only one call to send() is performed, unless the buffer wraps, in which case
6714 * a second call may be performed. The connection's flags are updated with
6715 * whatever special event is detected (error, empty). The caller is responsible
6716 * for taking care of those events and avoiding the call if inappropriate. The
6717 * function does not call the connection's polling update function, so the caller
Willy Tarreau787db9a2018-06-14 18:31:46 +02006718 * is responsible for this. The buffer's output is not adjusted, it's up to the
6719 * caller to take care of this. It's up to the caller to update the buffer's
6720 * contents based on the return value.
Emeric Brun46591952012-05-18 15:47:34 +02006721 */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006722static 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 +02006723{
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006724 struct ssl_sock_ctx *ctx = xprt_ctx;
Willy Tarreau787db9a2018-06-14 18:31:46 +02006725 ssize_t ret;
6726 size_t try, done;
Emeric Brun46591952012-05-18 15:47:34 +02006727
6728 done = 0;
6729
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006730 if (!ctx)
Emeric Brun46591952012-05-18 15:47:34 +02006731 goto out_error;
6732
Willy Tarreau911db9b2020-01-23 16:27:54 +01006733 if (conn->flags & (CO_FL_WAIT_XPRT | CO_FL_SSL_WAIT_HS | CO_FL_EARLY_SSL_HS))
Emeric Brun46591952012-05-18 15:47:34 +02006734 /* a handshake was requested */
6735 return 0;
6736
6737 /* send the largest possible block. For this we perform only one call
6738 * to send() unless the buffer wraps and we exactly fill the first hunk,
6739 * in which case we accept to do it once again.
6740 */
Willy Tarreau787db9a2018-06-14 18:31:46 +02006741 while (count) {
Willy Tarreau5db847a2019-05-09 14:13:35 +02006742#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Olivier Houchardc2aae742017-09-22 18:26:28 +02006743 size_t written_data;
6744#endif
6745
Willy Tarreau787db9a2018-06-14 18:31:46 +02006746 try = b_contig_data(buf, done);
6747 if (try > count)
6748 try = count;
Willy Tarreaubfd59462013-02-21 07:46:09 +01006749
Willy Tarreau7bed9452014-02-02 02:00:24 +01006750 if (!(flags & CO_SFL_STREAMER) &&
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006751 !(ctx->xprt_st & SSL_SOCK_SEND_UNLIMITED) &&
Willy Tarreauef934602016-12-22 23:12:01 +01006752 global_ssl.max_record && try > global_ssl.max_record) {
6753 try = global_ssl.max_record;
Willy Tarreau518cedd2014-02-17 15:43:01 +01006754 }
6755 else {
6756 /* we need to keep the information about the fact that
6757 * we're not limiting the upcoming send(), because if it
6758 * fails, we'll have to retry with at least as many data.
6759 */
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006760 ctx->xprt_st |= SSL_SOCK_SEND_UNLIMITED;
Willy Tarreau518cedd2014-02-17 15:43:01 +01006761 }
Willy Tarreaubfd59462013-02-21 07:46:09 +01006762
Willy Tarreau5db847a2019-05-09 14:13:35 +02006763#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Olivier Houchard010941f2019-05-03 20:56:19 +02006764 if (!SSL_is_init_finished(ctx->ssl) && conn_is_back(conn)) {
Olivier Houchardc2aae742017-09-22 18:26:28 +02006765 unsigned int max_early;
6766
Olivier Houchard522eea72017-11-03 16:27:47 +01006767 if (objt_listener(conn->target))
Olivier Houchard66ab4982019-02-26 18:37:15 +01006768 max_early = SSL_get_max_early_data(ctx->ssl);
Olivier Houchard522eea72017-11-03 16:27:47 +01006769 else {
Olivier Houchard66ab4982019-02-26 18:37:15 +01006770 if (SSL_get0_session(ctx->ssl))
6771 max_early = SSL_SESSION_get_max_early_data(SSL_get0_session(ctx->ssl));
Olivier Houchard522eea72017-11-03 16:27:47 +01006772 else
6773 max_early = 0;
6774 }
6775
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006776 if (try + ctx->sent_early_data > max_early) {
6777 try -= (try + ctx->sent_early_data) - max_early;
Olivier Houchard522eea72017-11-03 16:27:47 +01006778 if (try <= 0) {
Olivier Houchard010941f2019-05-03 20:56:19 +02006779 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Olivier Houchard965e84e2019-06-15 20:59:30 +02006780 tasklet_wakeup(ctx->wait_event.tasklet);
Olivier Houchardc2aae742017-09-22 18:26:28 +02006781 break;
Olivier Houchard522eea72017-11-03 16:27:47 +01006782 }
Olivier Houchardc2aae742017-09-22 18:26:28 +02006783 }
Olivier Houchard66ab4982019-02-26 18:37:15 +01006784 ret = SSL_write_early_data(ctx->ssl, b_peek(buf, done), try, &written_data);
Olivier Houchardc2aae742017-09-22 18:26:28 +02006785 if (ret == 1) {
6786 ret = written_data;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006787 ctx->sent_early_data += ret;
Olivier Houchard965e84e2019-06-15 20:59:30 +02006788 if (objt_server(conn->target)) {
Olivier Houchard522eea72017-11-03 16:27:47 +01006789 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN | CO_FL_EARLY_DATA;
Olivier Houchard965e84e2019-06-15 20:59:30 +02006790 /* Initiate the handshake, now */
6791 tasklet_wakeup(ctx->wait_event.tasklet);
6792 }
Olivier Houchard522eea72017-11-03 16:27:47 +01006793
Olivier Houchardc2aae742017-09-22 18:26:28 +02006794 }
6795
6796 } else
6797#endif
Olivier Houchard66ab4982019-02-26 18:37:15 +01006798 ret = SSL_write(ctx->ssl, b_peek(buf, done), try);
Willy Tarreau518cedd2014-02-17 15:43:01 +01006799
Emeric Brune1f38db2012-09-03 20:36:47 +02006800 if (conn->flags & CO_FL_ERROR) {
6801 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01006802 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02006803 }
Emeric Brun46591952012-05-18 15:47:34 +02006804 if (ret > 0) {
Willy Tarreauc192b0a2020-01-23 09:11:58 +01006805 /* A send succeeded, so we can consider ourself connected */
6806 conn->flags &= ~CO_FL_WAIT_L4L6;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006807 ctx->xprt_st &= ~SSL_SOCK_SEND_UNLIMITED;
Willy Tarreau787db9a2018-06-14 18:31:46 +02006808 count -= ret;
Emeric Brun46591952012-05-18 15:47:34 +02006809 done += ret;
Emeric Brun46591952012-05-18 15:47:34 +02006810 }
6811 else {
Olivier Houchard66ab4982019-02-26 18:37:15 +01006812 ret = SSL_get_error(ctx->ssl, ret);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006813
Emeric Brun46591952012-05-18 15:47:34 +02006814 if (ret == SSL_ERROR_WANT_WRITE) {
Olivier Houchard66ab4982019-02-26 18:37:15 +01006815 if (SSL_renegotiate_pending(ctx->ssl)) {
Emeric Brun282a76a2012-11-08 18:02:56 +01006816 /* handshake is running, and it may need to re-enable write */
6817 conn->flags |= CO_FL_SSL_WAIT_HS;
Olivier Houchardea8dd942019-05-20 14:02:16 +02006818 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_SEND, &ctx->wait_event);
Willy Tarreau5db847a2019-05-09 14:13:35 +02006819#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00006820 /* Async mode can be re-enabled, because we're leaving data state.*/
6821 if (global_ssl.async)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006822 SSL_set_mode(ctx->ssl, SSL_MODE_ASYNC);
Emeric Brunb5e42a82017-06-06 12:35:14 +00006823#endif
Emeric Brun282a76a2012-11-08 18:02:56 +01006824 break;
6825 }
Olivier Houchardea8dd942019-05-20 14:02:16 +02006826
Emeric Brun46591952012-05-18 15:47:34 +02006827 break;
6828 }
6829 else if (ret == SSL_ERROR_WANT_READ) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01006830 /* handshake is running, and it needs to enable read */
Emeric Brun46591952012-05-18 15:47:34 +02006831 conn->flags |= CO_FL_SSL_WAIT_HS;
Olivier Houchardea8dd942019-05-20 14:02:16 +02006832 ctx->xprt->subscribe(conn, ctx->xprt_ctx,
6833 SUB_RETRY_RECV,
6834 &ctx->wait_event);
Willy Tarreau5db847a2019-05-09 14:13:35 +02006835#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00006836 /* Async mode can be re-enabled, because we're leaving data state.*/
6837 if (global_ssl.async)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006838 SSL_set_mode(ctx->ssl, SSL_MODE_ASYNC);
Emeric Brunb5e42a82017-06-06 12:35:14 +00006839#endif
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006840 break;
6841 }
Emeric Brun46591952012-05-18 15:47:34 +02006842 goto out_error;
6843 }
6844 }
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02006845 leave:
Emeric Brun46591952012-05-18 15:47:34 +02006846 return done;
6847
6848 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01006849 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02006850 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01006851 ERR_clear_error();
6852
Emeric Brun46591952012-05-18 15:47:34 +02006853 conn->flags |= CO_FL_ERROR;
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02006854 goto leave;
Emeric Brun46591952012-05-18 15:47:34 +02006855}
6856
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006857static void ssl_sock_close(struct connection *conn, void *xprt_ctx) {
Emeric Brun46591952012-05-18 15:47:34 +02006858
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006859 struct ssl_sock_ctx *ctx = xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006860
Olivier Houchardea8dd942019-05-20 14:02:16 +02006861
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006862 if (ctx) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02006863 if (ctx->wait_event.events != 0)
6864 ctx->xprt->unsubscribe(ctx->conn, ctx->xprt_ctx,
6865 ctx->wait_event.events,
6866 &ctx->wait_event);
Willy Tarreau113d52b2020-01-10 09:20:26 +01006867 if (ctx->subs) {
6868 ctx->subs->events = 0;
6869 tasklet_wakeup(ctx->subs->tasklet);
Olivier Houchardea8dd942019-05-20 14:02:16 +02006870 }
Willy Tarreau113d52b2020-01-10 09:20:26 +01006871
Olivier Houchard692c1d02019-05-23 18:41:47 +02006872 if (ctx->xprt->close)
6873 ctx->xprt->close(conn, ctx->xprt_ctx);
Willy Tarreau5db847a2019-05-09 14:13:35 +02006874#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brun3854e012017-05-17 20:42:48 +02006875 if (global_ssl.async) {
6876 OSSL_ASYNC_FD all_fd[32], afd;
6877 size_t num_all_fds = 0;
6878 int i;
6879
Olivier Houchard66ab4982019-02-26 18:37:15 +01006880 SSL_get_all_async_fds(ctx->ssl, NULL, &num_all_fds);
Emeric Brun3854e012017-05-17 20:42:48 +02006881 if (num_all_fds > 32) {
6882 send_log(NULL, LOG_EMERG, "haproxy: openssl returns too many async fds. It seems a bug. Process may crash\n");
6883 return;
6884 }
6885
Olivier Houchard66ab4982019-02-26 18:37:15 +01006886 SSL_get_all_async_fds(ctx->ssl, all_fd, &num_all_fds);
Emeric Brun3854e012017-05-17 20:42:48 +02006887
6888 /* If an async job is pending, we must try to
6889 to catch the end using polling before calling
6890 SSL_free */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006891 if (num_all_fds && SSL_waiting_for_async(ctx->ssl)) {
Emeric Brun3854e012017-05-17 20:42:48 +02006892 for (i=0 ; i < num_all_fds ; i++) {
6893 /* switch on an handler designed to
6894 * handle the SSL_free
6895 */
6896 afd = all_fd[i];
6897 fdtab[afd].iocb = ssl_async_fd_free;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006898 fdtab[afd].owner = ctx->ssl;
Emeric Brun3854e012017-05-17 20:42:48 +02006899 fd_want_recv(afd);
Emeric Brunce9e01c2017-05-31 10:02:53 +00006900 /* To ensure that the fd cache won't be used
6901 * and we'll catch a real RD event.
6902 */
6903 fd_cant_recv(afd);
Emeric Brun3854e012017-05-17 20:42:48 +02006904 }
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02006905 tasklet_free(ctx->wait_event.tasklet);
Olivier Houchard66ab4982019-02-26 18:37:15 +01006906 pool_free(ssl_sock_ctx_pool, ctx);
Olivier Houchard2be5a4c2019-03-08 18:54:43 +01006907 _HA_ATOMIC_ADD(&jobs, 1);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006908 return;
6909 }
Emeric Brun3854e012017-05-17 20:42:48 +02006910 /* Else we can remove the fds from the fdtab
6911 * and call SSL_free.
6912 * note: we do a fd_remove and not a delete
6913 * because the fd is owned by the engine.
6914 * the engine is responsible to close
6915 */
6916 for (i=0 ; i < num_all_fds ; i++)
6917 fd_remove(all_fd[i]);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006918 }
6919#endif
Olivier Houchard66ab4982019-02-26 18:37:15 +01006920 SSL_free(ctx->ssl);
Olivier Houchard54907bb2019-12-19 15:02:39 +01006921 b_free(&ctx->early_buf);
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02006922 tasklet_free(ctx->wait_event.tasklet);
Olivier Houchard66ab4982019-02-26 18:37:15 +01006923 pool_free(ssl_sock_ctx_pool, ctx);
Olivier Houchard2be5a4c2019-03-08 18:54:43 +01006924 _HA_ATOMIC_SUB(&sslconns, 1);
Emeric Brun46591952012-05-18 15:47:34 +02006925 }
Emeric Brun46591952012-05-18 15:47:34 +02006926}
6927
6928/* This function tries to perform a clean shutdown on an SSL connection, and in
6929 * any case, flags the connection as reusable if no handshake was in progress.
6930 */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006931static void ssl_sock_shutw(struct connection *conn, void *xprt_ctx, int clean)
Emeric Brun46591952012-05-18 15:47:34 +02006932{
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006933 struct ssl_sock_ctx *ctx = xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006934
Willy Tarreau911db9b2020-01-23 16:27:54 +01006935 if (conn->flags & (CO_FL_WAIT_XPRT | CO_FL_SSL_WAIT_HS))
Emeric Brun46591952012-05-18 15:47:34 +02006936 return;
Emmanuel Hocdet405ff312017-01-08 14:07:39 +01006937 if (!clean)
6938 /* don't sent notify on SSL_shutdown */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006939 SSL_set_quiet_shutdown(ctx->ssl, 1);
Emeric Brun46591952012-05-18 15:47:34 +02006940 /* no handshake was in progress, try a clean ssl shutdown */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006941 if (SSL_shutdown(ctx->ssl) <= 0) {
Emeric Brun644cde02012-12-14 11:21:13 +01006942 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02006943 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01006944 ERR_clear_error();
6945 }
Emeric Brun46591952012-05-18 15:47:34 +02006946}
6947
William Lallemandd4f946c2019-12-05 10:26:40 +01006948/* fill a buffer with the algorithm and size of a public key */
6949static int cert_get_pkey_algo(X509 *crt, struct buffer *out)
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01006950{
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01006951 int bits = 0;
6952 int sig = TLSEXT_signature_anonymous;
6953 int len = -1;
Emmanuel Hocdetc3775d22019-11-04 18:19:32 +01006954 EVP_PKEY *pkey;
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01006955
Emmanuel Hocdetc3775d22019-11-04 18:19:32 +01006956 pkey = X509_get_pubkey(crt);
6957 if (pkey) {
6958 bits = EVP_PKEY_bits(pkey);
6959 switch(EVP_PKEY_base_id(pkey)) {
6960 case EVP_PKEY_RSA:
6961 sig = TLSEXT_signature_rsa;
6962 break;
6963 case EVP_PKEY_EC:
6964 sig = TLSEXT_signature_ecdsa;
6965 break;
6966 case EVP_PKEY_DSA:
6967 sig = TLSEXT_signature_dsa;
6968 break;
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01006969 }
Emmanuel Hocdetc3775d22019-11-04 18:19:32 +01006970 EVP_PKEY_free(pkey);
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01006971 }
6972
6973 switch(sig) {
6974 case TLSEXT_signature_rsa:
6975 len = chunk_printf(out, "RSA%d", bits);
6976 break;
6977 case TLSEXT_signature_ecdsa:
6978 len = chunk_printf(out, "EC%d", bits);
6979 break;
6980 case TLSEXT_signature_dsa:
6981 len = chunk_printf(out, "DSA%d", bits);
6982 break;
6983 default:
6984 return 0;
6985 }
6986 if (len < 0)
6987 return 0;
6988 return 1;
6989}
6990
William Lallemandd4f946c2019-12-05 10:26:40 +01006991/* used for ppv2 pkey alog (can be used for logging) */
6992int ssl_sock_get_pkey_algo(struct connection *conn, struct buffer *out)
6993{
6994 struct ssl_sock_ctx *ctx;
6995 X509 *crt;
6996
6997 if (!ssl_sock_is_ssl(conn))
6998 return 0;
6999
7000 ctx = conn->xprt_ctx;
7001
7002 crt = SSL_get_certificate(ctx->ssl);
7003 if (!crt)
7004 return 0;
7005
7006 return cert_get_pkey_algo(crt, out);
7007}
7008
Emmanuel Hocdet283e0042017-11-02 14:05:23 +01007009/* used for ppv2 cert signature (can be used for logging) */
7010const char *ssl_sock_get_cert_sig(struct connection *conn)
7011{
Christopher Faulet82004142019-09-10 10:12:03 +02007012 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007013
Emmanuel Hocdet283e0042017-11-02 14:05:23 +01007014 __OPENSSL_110_CONST__ ASN1_OBJECT *algorithm;
7015 X509 *crt;
7016
7017 if (!ssl_sock_is_ssl(conn))
7018 return NULL;
Christopher Faulet82004142019-09-10 10:12:03 +02007019 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007020 crt = SSL_get_certificate(ctx->ssl);
Emmanuel Hocdet283e0042017-11-02 14:05:23 +01007021 if (!crt)
7022 return NULL;
7023 X509_ALGOR_get0(&algorithm, NULL, NULL, X509_get0_tbs_sigalg(crt));
7024 return OBJ_nid2sn(OBJ_obj2nid(algorithm));
7025}
7026
Emmanuel Hocdet253c3b72018-02-01 18:29:59 +01007027/* used for ppv2 authority */
7028const char *ssl_sock_get_sni(struct connection *conn)
7029{
7030#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Christopher Faulet82004142019-09-10 10:12:03 +02007031 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007032
Emmanuel Hocdet253c3b72018-02-01 18:29:59 +01007033 if (!ssl_sock_is_ssl(conn))
7034 return NULL;
Christopher Faulet82004142019-09-10 10:12:03 +02007035 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007036 return SSL_get_servername(ctx->ssl, TLSEXT_NAMETYPE_host_name);
Emmanuel Hocdet253c3b72018-02-01 18:29:59 +01007037#else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007038 return NULL;
Emmanuel Hocdet253c3b72018-02-01 18:29:59 +01007039#endif
7040}
7041
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02007042/* used for logging/ppv2, may be changed for a sample fetch later */
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02007043const char *ssl_sock_get_cipher_name(struct connection *conn)
7044{
Christopher Faulet82004142019-09-10 10:12:03 +02007045 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007046
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02007047 if (!ssl_sock_is_ssl(conn))
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02007048 return NULL;
Christopher Faulet82004142019-09-10 10:12:03 +02007049 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007050 return SSL_get_cipher_name(ctx->ssl);
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02007051}
7052
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02007053/* used for logging/ppv2, may be changed for a sample fetch later */
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02007054const char *ssl_sock_get_proto_version(struct connection *conn)
7055{
Christopher Faulet82004142019-09-10 10:12:03 +02007056 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007057
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02007058 if (!ssl_sock_is_ssl(conn))
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02007059 return NULL;
Christopher Faulet82004142019-09-10 10:12:03 +02007060 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007061 return SSL_get_version(ctx->ssl);
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02007062}
7063
Willy Tarreau8d598402012-10-22 17:58:39 +02007064/* Extract a serial from a cert, and copy it to a chunk.
7065 * Returns 1 if serial is found and copied, 0 if no serial found and
7066 * -1 if output is not large enough.
7067 */
7068static int
Willy Tarreau83061a82018-07-13 11:56:34 +02007069ssl_sock_get_serial(X509 *crt, struct buffer *out)
Willy Tarreau8d598402012-10-22 17:58:39 +02007070{
7071 ASN1_INTEGER *serial;
7072
7073 serial = X509_get_serialNumber(crt);
7074 if (!serial)
7075 return 0;
7076
7077 if (out->size < serial->length)
7078 return -1;
7079
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007080 memcpy(out->area, serial->data, serial->length);
7081 out->data = serial->length;
Willy Tarreau8d598402012-10-22 17:58:39 +02007082 return 1;
7083}
7084
Emeric Brun43e79582014-10-29 19:03:26 +01007085/* Extract a cert to der, and copy it to a chunk.
Joseph Herlant017b3da2018-11-15 09:07:59 -08007086 * Returns 1 if the cert is found and copied, 0 on der conversion failure
7087 * and -1 if the output is not large enough.
Emeric Brun43e79582014-10-29 19:03:26 +01007088 */
7089static int
Willy Tarreau83061a82018-07-13 11:56:34 +02007090ssl_sock_crt2der(X509 *crt, struct buffer *out)
Emeric Brun43e79582014-10-29 19:03:26 +01007091{
7092 int len;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007093 unsigned char *p = (unsigned char *) out->area;;
Emeric Brun43e79582014-10-29 19:03:26 +01007094
7095 len =i2d_X509(crt, NULL);
7096 if (len <= 0)
7097 return 1;
7098
7099 if (out->size < len)
7100 return -1;
7101
7102 i2d_X509(crt,&p);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007103 out->data = len;
Emeric Brun43e79582014-10-29 19:03:26 +01007104 return 1;
7105}
7106
Emeric Brunce5ad802012-10-22 14:11:22 +02007107
Willy Tarreau83061a82018-07-13 11:56:34 +02007108/* Copy Date in ASN1_UTCTIME format in struct buffer out.
Emeric Brunce5ad802012-10-22 14:11:22 +02007109 * Returns 1 if serial is found and copied, 0 if no valid time found
7110 * and -1 if output is not large enough.
7111 */
7112static int
Willy Tarreau83061a82018-07-13 11:56:34 +02007113ssl_sock_get_time(ASN1_TIME *tm, struct buffer *out)
Emeric Brunce5ad802012-10-22 14:11:22 +02007114{
7115 if (tm->type == V_ASN1_GENERALIZEDTIME) {
7116 ASN1_GENERALIZEDTIME *gentm = (ASN1_GENERALIZEDTIME *)tm;
7117
7118 if (gentm->length < 12)
7119 return 0;
7120 if (gentm->data[0] != 0x32 || gentm->data[1] != 0x30)
7121 return 0;
7122 if (out->size < gentm->length-2)
7123 return -1;
7124
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007125 memcpy(out->area, gentm->data+2, gentm->length-2);
7126 out->data = gentm->length-2;
Emeric Brunce5ad802012-10-22 14:11:22 +02007127 return 1;
7128 }
7129 else if (tm->type == V_ASN1_UTCTIME) {
7130 ASN1_UTCTIME *utctm = (ASN1_UTCTIME *)tm;
7131
7132 if (utctm->length < 10)
7133 return 0;
7134 if (utctm->data[0] >= 0x35)
7135 return 0;
7136 if (out->size < utctm->length)
7137 return -1;
7138
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007139 memcpy(out->area, utctm->data, utctm->length);
7140 out->data = utctm->length;
Emeric Brunce5ad802012-10-22 14:11:22 +02007141 return 1;
7142 }
7143
7144 return 0;
7145}
7146
Emeric Brun87855892012-10-17 17:39:35 +02007147/* Extract an entry from a X509_NAME and copy its value to an output chunk.
7148 * Returns 1 if entry found, 0 if entry not found, or -1 if output not large enough.
7149 */
7150static int
Willy Tarreau83061a82018-07-13 11:56:34 +02007151ssl_sock_get_dn_entry(X509_NAME *a, const struct buffer *entry, int pos,
7152 struct buffer *out)
Emeric Brun87855892012-10-17 17:39:35 +02007153{
7154 X509_NAME_ENTRY *ne;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007155 ASN1_OBJECT *obj;
7156 ASN1_STRING *data;
7157 const unsigned char *data_ptr;
7158 int data_len;
Emeric Brun87855892012-10-17 17:39:35 +02007159 int i, j, n;
7160 int cur = 0;
7161 const char *s;
7162 char tmp[128];
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007163 int name_count;
7164
7165 name_count = X509_NAME_entry_count(a);
Emeric Brun87855892012-10-17 17:39:35 +02007166
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007167 out->data = 0;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007168 for (i = 0; i < name_count; i++) {
Emeric Brun87855892012-10-17 17:39:35 +02007169 if (pos < 0)
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007170 j = (name_count-1) - i;
Emeric Brun87855892012-10-17 17:39:35 +02007171 else
7172 j = i;
7173
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007174 ne = X509_NAME_get_entry(a, j);
7175 obj = X509_NAME_ENTRY_get_object(ne);
7176 data = X509_NAME_ENTRY_get_data(ne);
7177 data_ptr = ASN1_STRING_get0_data(data);
7178 data_len = ASN1_STRING_length(data);
7179 n = OBJ_obj2nid(obj);
Emeric Brun87855892012-10-17 17:39:35 +02007180 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007181 i2t_ASN1_OBJECT(tmp, sizeof(tmp), obj);
Emeric Brun87855892012-10-17 17:39:35 +02007182 s = tmp;
7183 }
7184
7185 if (chunk_strcasecmp(entry, s) != 0)
7186 continue;
7187
7188 if (pos < 0)
7189 cur--;
7190 else
7191 cur++;
7192
7193 if (cur != pos)
7194 continue;
7195
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007196 if (data_len > out->size)
Emeric Brun87855892012-10-17 17:39:35 +02007197 return -1;
7198
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007199 memcpy(out->area, data_ptr, data_len);
7200 out->data = data_len;
Emeric Brun87855892012-10-17 17:39:35 +02007201 return 1;
7202 }
7203
7204 return 0;
7205
William Lallemandd4f946c2019-12-05 10:26:40 +01007206}
7207
7208/*
7209 * Extract and format the DNS SAN extensions and copy result into a chuink
7210 * Return 0;
7211 */
7212#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
7213static int ssl_sock_get_san_oneline(X509 *cert, struct buffer *out)
7214{
7215 int i;
7216 char *str;
7217 STACK_OF(GENERAL_NAME) *names = NULL;
7218
7219 names = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
7220 if (names) {
7221 for (i = 0; i < sk_GENERAL_NAME_num(names); i++) {
7222 GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i);
7223 if (i > 0)
7224 chunk_appendf(out, ", ");
7225 if (name->type == GEN_DNS) {
7226 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
7227 chunk_appendf(out, "DNS:%s", str);
7228 OPENSSL_free(str);
7229 }
7230 }
7231 }
7232 sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
7233 }
7234 return 0;
Emeric Brun87855892012-10-17 17:39:35 +02007235}
William Lallemandd4f946c2019-12-05 10:26:40 +01007236#endif
Emeric Brun87855892012-10-17 17:39:35 +02007237
Elliot Otchet71f82972020-01-15 08:12:14 -05007238/*
7239 * Extract the DN in the specified format from the X509_NAME and copy result to a chunk.
7240 * Currently supports rfc2253 for returning LDAP V3 DNs.
7241 * Returns 1 if dn entries exist, 0 if no dn entry was found.
7242 */
7243static int
7244ssl_sock_get_dn_formatted(X509_NAME *a, const struct buffer *format, struct buffer *out)
7245{
7246 BIO *bio = NULL;
7247 int ret = 0;
7248 int data_len = 0;
7249
7250 if (chunk_strcmp(format, "rfc2253") == 0) {
7251 bio = BIO_new(BIO_s_mem());
7252 if (bio == NULL)
7253 goto out;
7254
7255 if (X509_NAME_print_ex(bio, a, 0, XN_FLAG_RFC2253) < 0)
7256 goto out;
7257
7258 if ((data_len = BIO_read(bio, out->area, out->size)) <= 0)
7259 goto out;
7260
7261 out->data = data_len;
7262
7263 ret = 1;
7264 }
7265out:
7266 if (bio)
7267 BIO_free(bio);
7268 return ret;
7269}
7270
Emeric Brun87855892012-10-17 17:39:35 +02007271/* Extract and format full DN from a X509_NAME and copy result into a chunk
7272 * Returns 1 if dn entries exits, 0 if no dn entry found or -1 if output is not large enough.
7273 */
7274static int
Willy Tarreau83061a82018-07-13 11:56:34 +02007275ssl_sock_get_dn_oneline(X509_NAME *a, struct buffer *out)
Emeric Brun87855892012-10-17 17:39:35 +02007276{
7277 X509_NAME_ENTRY *ne;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007278 ASN1_OBJECT *obj;
7279 ASN1_STRING *data;
7280 const unsigned char *data_ptr;
7281 int data_len;
Emeric Brun87855892012-10-17 17:39:35 +02007282 int i, n, ln;
7283 int l = 0;
7284 const char *s;
7285 char *p;
7286 char tmp[128];
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007287 int name_count;
7288
7289
7290 name_count = X509_NAME_entry_count(a);
Emeric Brun87855892012-10-17 17:39:35 +02007291
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007292 out->data = 0;
7293 p = out->area;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007294 for (i = 0; i < name_count; i++) {
7295 ne = X509_NAME_get_entry(a, i);
7296 obj = X509_NAME_ENTRY_get_object(ne);
7297 data = X509_NAME_ENTRY_get_data(ne);
7298 data_ptr = ASN1_STRING_get0_data(data);
7299 data_len = ASN1_STRING_length(data);
7300 n = OBJ_obj2nid(obj);
Emeric Brun87855892012-10-17 17:39:35 +02007301 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007302 i2t_ASN1_OBJECT(tmp, sizeof(tmp), obj);
Emeric Brun87855892012-10-17 17:39:35 +02007303 s = tmp;
7304 }
7305 ln = strlen(s);
7306
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007307 l += 1 + ln + 1 + data_len;
Emeric Brun87855892012-10-17 17:39:35 +02007308 if (l > out->size)
7309 return -1;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007310 out->data = l;
Emeric Brun87855892012-10-17 17:39:35 +02007311
7312 *(p++)='/';
7313 memcpy(p, s, ln);
7314 p += ln;
7315 *(p++)='=';
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007316 memcpy(p, data_ptr, data_len);
7317 p += data_len;
Emeric Brun87855892012-10-17 17:39:35 +02007318 }
7319
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007320 if (!out->data)
Emeric Brun87855892012-10-17 17:39:35 +02007321 return 0;
7322
7323 return 1;
7324}
7325
Olivier Houchardab28a322018-12-21 19:45:40 +01007326void ssl_sock_set_alpn(struct connection *conn, const unsigned char *alpn, int len)
7327{
7328#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Christopher Faulet82004142019-09-10 10:12:03 +02007329 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007330
Olivier Houcharde488ea82019-06-28 14:10:33 +02007331 if (!ssl_sock_is_ssl(conn))
7332 return;
Christopher Faulet82004142019-09-10 10:12:03 +02007333 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007334 SSL_set_alpn_protos(ctx->ssl, alpn, len);
Olivier Houchardab28a322018-12-21 19:45:40 +01007335#endif
7336}
7337
Willy Tarreau119a4082016-12-22 21:58:38 +01007338/* Sets advertised SNI for outgoing connections. Please set <hostname> to NULL
7339 * to disable SNI.
7340 */
Willy Tarreau63076412015-07-10 11:33:32 +02007341void ssl_sock_set_servername(struct connection *conn, const char *hostname)
7342{
7343#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Christopher Faulet82004142019-09-10 10:12:03 +02007344 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007345
Willy Tarreau119a4082016-12-22 21:58:38 +01007346 char *prev_name;
7347
Willy Tarreau63076412015-07-10 11:33:32 +02007348 if (!ssl_sock_is_ssl(conn))
7349 return;
Christopher Faulet82004142019-09-10 10:12:03 +02007350 ctx = conn->xprt_ctx;
Willy Tarreau63076412015-07-10 11:33:32 +02007351
Willy Tarreau119a4082016-12-22 21:58:38 +01007352 /* if the SNI changes, we must destroy the reusable context so that a
7353 * new connection will present a new SNI. As an optimization we could
7354 * later imagine having a small cache of ssl_ctx to hold a few SNI per
7355 * server.
7356 */
Olivier Houchard66ab4982019-02-26 18:37:15 +01007357 prev_name = (char *)SSL_get_servername(ctx->ssl, TLSEXT_NAMETYPE_host_name);
Willy Tarreau119a4082016-12-22 21:58:38 +01007358 if ((!prev_name && hostname) ||
7359 (prev_name && (!hostname || strcmp(hostname, prev_name) != 0)))
Olivier Houchard66ab4982019-02-26 18:37:15 +01007360 SSL_set_session(ctx->ssl, NULL);
Willy Tarreau119a4082016-12-22 21:58:38 +01007361
Olivier Houchard66ab4982019-02-26 18:37:15 +01007362 SSL_set_tlsext_host_name(ctx->ssl, hostname);
Willy Tarreau63076412015-07-10 11:33:32 +02007363#endif
7364}
7365
Emeric Brun0abf8362014-06-24 18:26:41 +02007366/* Extract peer certificate's common name into the chunk dest
7367 * Returns
7368 * the len of the extracted common name
7369 * or 0 if no CN found in DN
7370 * or -1 on error case (i.e. no peer certificate)
7371 */
Willy Tarreau83061a82018-07-13 11:56:34 +02007372int ssl_sock_get_remote_common_name(struct connection *conn,
7373 struct buffer *dest)
David Safb76832014-05-08 23:42:08 -04007374{
Christopher Faulet82004142019-09-10 10:12:03 +02007375 struct ssl_sock_ctx *ctx;
David Safb76832014-05-08 23:42:08 -04007376 X509 *crt = NULL;
7377 X509_NAME *name;
David Safb76832014-05-08 23:42:08 -04007378 const char find_cn[] = "CN";
Willy Tarreau83061a82018-07-13 11:56:34 +02007379 const struct buffer find_cn_chunk = {
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007380 .area = (char *)&find_cn,
7381 .data = sizeof(find_cn)-1
David Safb76832014-05-08 23:42:08 -04007382 };
Emeric Brun0abf8362014-06-24 18:26:41 +02007383 int result = -1;
David Safb76832014-05-08 23:42:08 -04007384
7385 if (!ssl_sock_is_ssl(conn))
Emeric Brun0abf8362014-06-24 18:26:41 +02007386 goto out;
Christopher Faulet82004142019-09-10 10:12:03 +02007387 ctx = conn->xprt_ctx;
David Safb76832014-05-08 23:42:08 -04007388
7389 /* SSL_get_peer_certificate, it increase X509 * ref count */
Olivier Houchard66ab4982019-02-26 18:37:15 +01007390 crt = SSL_get_peer_certificate(ctx->ssl);
David Safb76832014-05-08 23:42:08 -04007391 if (!crt)
7392 goto out;
7393
7394 name = X509_get_subject_name(crt);
7395 if (!name)
7396 goto out;
David Safb76832014-05-08 23:42:08 -04007397
Emeric Brun0abf8362014-06-24 18:26:41 +02007398 result = ssl_sock_get_dn_entry(name, &find_cn_chunk, 1, dest);
7399out:
David Safb76832014-05-08 23:42:08 -04007400 if (crt)
7401 X509_free(crt);
7402
7403 return result;
7404}
7405
Dave McCowan328fb582014-07-30 10:39:13 -04007406/* returns 1 if client passed a certificate for this session, 0 if not */
7407int ssl_sock_get_cert_used_sess(struct connection *conn)
7408{
Christopher Faulet82004142019-09-10 10:12:03 +02007409 struct ssl_sock_ctx *ctx;
Dave McCowan328fb582014-07-30 10:39:13 -04007410 X509 *crt = NULL;
7411
7412 if (!ssl_sock_is_ssl(conn))
7413 return 0;
Christopher Faulet82004142019-09-10 10:12:03 +02007414 ctx = conn->xprt_ctx;
Dave McCowan328fb582014-07-30 10:39:13 -04007415
7416 /* SSL_get_peer_certificate, it increase X509 * ref count */
Olivier Houchard66ab4982019-02-26 18:37:15 +01007417 crt = SSL_get_peer_certificate(ctx->ssl);
Dave McCowan328fb582014-07-30 10:39:13 -04007418 if (!crt)
7419 return 0;
7420
7421 X509_free(crt);
7422 return 1;
7423}
7424
7425/* returns 1 if client passed a certificate for this connection, 0 if not */
7426int ssl_sock_get_cert_used_conn(struct connection *conn)
David Safb76832014-05-08 23:42:08 -04007427{
Christopher Faulet82004142019-09-10 10:12:03 +02007428 struct ssl_sock_ctx *ctx;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007429
David Safb76832014-05-08 23:42:08 -04007430 if (!ssl_sock_is_ssl(conn))
7431 return 0;
Christopher Faulet82004142019-09-10 10:12:03 +02007432 ctx = conn->xprt_ctx;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007433 return SSL_SOCK_ST_FL_VERIFY_DONE & ctx->xprt_st ? 1 : 0;
David Safb76832014-05-08 23:42:08 -04007434}
7435
7436/* returns result from SSL verify */
7437unsigned int ssl_sock_get_verify_result(struct connection *conn)
7438{
Christopher Faulet82004142019-09-10 10:12:03 +02007439 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007440
David Safb76832014-05-08 23:42:08 -04007441 if (!ssl_sock_is_ssl(conn))
7442 return (unsigned int)X509_V_ERR_APPLICATION_VERIFICATION;
Christopher Faulet82004142019-09-10 10:12:03 +02007443 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007444 return (unsigned int)SSL_get_verify_result(ctx->ssl);
David Safb76832014-05-08 23:42:08 -04007445}
7446
Willy Tarreau8743f7e2016-12-04 18:44:29 +01007447/* Returns the application layer protocol name in <str> and <len> when known.
7448 * Zero is returned if the protocol name was not found, otherwise non-zero is
7449 * returned. The string is allocated in the SSL context and doesn't have to be
7450 * freed by the caller. NPN is also checked if available since older versions
7451 * of openssl (1.0.1) which are more common in field only support this one.
7452 */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01007453static int ssl_sock_get_alpn(const struct connection *conn, void *xprt_ctx, const char **str, int *len)
Willy Tarreau8743f7e2016-12-04 18:44:29 +01007454{
Olivier Houchard66ab4982019-02-26 18:37:15 +01007455#if defined(TLSEXT_TYPE_application_layer_protocol_negotiation) || \
7456 defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Olivier Houcharde179d0e2019-03-21 18:27:17 +01007457 struct ssl_sock_ctx *ctx = xprt_ctx;
7458 if (!ctx)
Willy Tarreau8743f7e2016-12-04 18:44:29 +01007459 return 0;
7460
7461 *str = NULL;
7462
7463#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Olivier Houchard66ab4982019-02-26 18:37:15 +01007464 SSL_get0_alpn_selected(ctx->ssl, (const unsigned char **)str, (unsigned *)len);
Willy Tarreau8743f7e2016-12-04 18:44:29 +01007465 if (*str)
7466 return 1;
7467#endif
Bernard Spil13c53f82018-02-15 13:34:58 +01007468#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007469 SSL_get0_next_proto_negotiated(ctx->ssl, (const unsigned char **)str, (unsigned *)len);
Willy Tarreau8743f7e2016-12-04 18:44:29 +01007470 if (*str)
7471 return 1;
7472#endif
Olivier Houcharde179d0e2019-03-21 18:27:17 +01007473#endif
Willy Tarreau8743f7e2016-12-04 18:44:29 +01007474 return 0;
7475}
7476
Willy Tarreau7875d092012-09-10 08:20:03 +02007477/***** Below are some sample fetching functions for ACL/patterns *****/
7478
Olivier Houchardccaa7de2017-10-02 11:51:03 +02007479static int
7480smp_fetch_ssl_fc_has_early(const struct arg *args, struct sample *smp, const char *kw, void *private)
7481{
7482 struct connection *conn;
7483
7484 conn = objt_conn(smp->sess->origin);
7485 if (!conn || conn->xprt != &ssl_sock)
7486 return 0;
7487
7488 smp->flags = 0;
7489 smp->data.type = SMP_T_BOOL;
Emmanuel Hocdetc9858012019-08-07 14:44:49 +02007490#ifdef OPENSSL_IS_BORINGSSL
7491 {
7492 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
7493 smp->data.u.sint = (SSL_in_early_data(ctx->ssl) &&
7494 SSL_early_data_accepted(ctx->ssl));
7495 }
7496#else
Olivier Houchard25ae45a2017-11-29 19:51:19 +01007497 smp->data.u.sint = ((conn->flags & CO_FL_EARLY_DATA) &&
Olivier Houchard220a26c2020-01-23 14:57:36 +01007498 (conn->flags & (CO_FL_EARLY_SSL_HS | CO_FL_SSL_WAIT_HS))) ? 1 : 0;
Emmanuel Hocdetc9858012019-08-07 14:44:49 +02007499#endif
Olivier Houchardccaa7de2017-10-02 11:51:03 +02007500 return 1;
7501}
7502
Emeric Brune64aef12012-09-21 13:15:06 +02007503/* boolean, returns true if client cert was present */
7504static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007505smp_fetch_ssl_fc_has_crt(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brune64aef12012-09-21 13:15:06 +02007506{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007507 struct connection *conn;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007508 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007509
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007510 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007511 if (!conn || conn->xprt != &ssl_sock)
Emeric Brune64aef12012-09-21 13:15:06 +02007512 return 0;
7513
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007514 ctx = conn->xprt_ctx;
7515
Willy Tarreau911db9b2020-01-23 16:27:54 +01007516 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Brune64aef12012-09-21 13:15:06 +02007517 smp->flags |= SMP_F_MAY_CHANGE;
7518 return 0;
7519 }
7520
7521 smp->flags = 0;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007522 smp->data.type = SMP_T_BOOL;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007523 smp->data.u.sint = SSL_SOCK_ST_FL_VERIFY_DONE & ctx->xprt_st ? 1 : 0;
Emeric Brune64aef12012-09-21 13:15:06 +02007524
7525 return 1;
7526}
7527
Emeric Brun43e79582014-10-29 19:03:26 +01007528/* binary, returns a certificate in a binary chunk (der/raw).
7529 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7530 * should be use.
7531 */
7532static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007533smp_fetch_ssl_x_der(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun43e79582014-10-29 19:03:26 +01007534{
7535 int cert_peer = (kw[4] == 'c') ? 1 : 0;
7536 X509 *crt = NULL;
7537 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02007538 struct buffer *smp_trash;
Emeric Brun43e79582014-10-29 19:03:26 +01007539 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007540 struct ssl_sock_ctx *ctx;
Emeric Brun43e79582014-10-29 19:03:26 +01007541
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007542 conn = objt_conn(smp->sess->origin);
Emeric Brun43e79582014-10-29 19:03:26 +01007543 if (!conn || conn->xprt != &ssl_sock)
7544 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007545 ctx = conn->xprt_ctx;
Emeric Brun43e79582014-10-29 19:03:26 +01007546
Willy Tarreau911db9b2020-01-23 16:27:54 +01007547 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Brun43e79582014-10-29 19:03:26 +01007548 smp->flags |= SMP_F_MAY_CHANGE;
7549 return 0;
7550 }
7551
7552 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007553 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brun43e79582014-10-29 19:03:26 +01007554 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007555 crt = SSL_get_certificate(ctx->ssl);
Emeric Brun43e79582014-10-29 19:03:26 +01007556
7557 if (!crt)
7558 goto out;
7559
7560 smp_trash = get_trash_chunk();
7561 if (ssl_sock_crt2der(crt, smp_trash) <= 0)
7562 goto out;
7563
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007564 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007565 smp->data.type = SMP_T_BIN;
Emeric Brun43e79582014-10-29 19:03:26 +01007566 ret = 1;
7567out:
7568 /* SSL_get_peer_certificate, it increase X509 * ref count */
7569 if (cert_peer && crt)
7570 X509_free(crt);
7571 return ret;
7572}
7573
Emeric Brunba841a12014-04-30 17:05:08 +02007574/* binary, returns serial of certificate in a binary chunk.
7575 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7576 * should be use.
7577 */
Willy Tarreau8d598402012-10-22 17:58:39 +02007578static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007579smp_fetch_ssl_x_serial(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau8d598402012-10-22 17:58:39 +02007580{
Emeric Brunba841a12014-04-30 17:05:08 +02007581 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Willy Tarreau8d598402012-10-22 17:58:39 +02007582 X509 *crt = NULL;
7583 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02007584 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007585 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007586 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007587
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007588 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007589 if (!conn || conn->xprt != &ssl_sock)
Willy Tarreau8d598402012-10-22 17:58:39 +02007590 return 0;
7591
Olivier Houchard66ab4982019-02-26 18:37:15 +01007592 ctx = conn->xprt_ctx;
7593
Willy Tarreau911db9b2020-01-23 16:27:54 +01007594 if (conn->flags & CO_FL_WAIT_XPRT) {
Willy Tarreau8d598402012-10-22 17:58:39 +02007595 smp->flags |= SMP_F_MAY_CHANGE;
7596 return 0;
7597 }
7598
Emeric Brunba841a12014-04-30 17:05:08 +02007599 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007600 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007601 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007602 crt = SSL_get_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007603
Willy Tarreau8d598402012-10-22 17:58:39 +02007604 if (!crt)
7605 goto out;
7606
Willy Tarreau47ca5452012-12-23 20:22:19 +01007607 smp_trash = get_trash_chunk();
Willy Tarreau8d598402012-10-22 17:58:39 +02007608 if (ssl_sock_get_serial(crt, smp_trash) <= 0)
7609 goto out;
7610
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007611 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007612 smp->data.type = SMP_T_BIN;
Willy Tarreau8d598402012-10-22 17:58:39 +02007613 ret = 1;
7614out:
Emeric Brunba841a12014-04-30 17:05:08 +02007615 /* SSL_get_peer_certificate, it increase X509 * ref count */
7616 if (cert_peer && crt)
Willy Tarreau8d598402012-10-22 17:58:39 +02007617 X509_free(crt);
7618 return ret;
7619}
Emeric Brune64aef12012-09-21 13:15:06 +02007620
Emeric Brunba841a12014-04-30 17:05:08 +02007621/* binary, returns the client certificate's SHA-1 fingerprint (SHA-1 hash of DER-encoded certificate) in a binary chunk.
7622 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7623 * should be use.
7624 */
James Votha051b4a2013-05-14 20:37:59 +02007625static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007626smp_fetch_ssl_x_sha1(const struct arg *args, struct sample *smp, const char *kw, void *private)
James Votha051b4a2013-05-14 20:37:59 +02007627{
Emeric Brunba841a12014-04-30 17:05:08 +02007628 int cert_peer = (kw[4] == 'c') ? 1 : 0;
James Votha051b4a2013-05-14 20:37:59 +02007629 X509 *crt = NULL;
7630 const EVP_MD *digest;
7631 int ret = 0;
Willy Tarreau105599c2020-02-25 08:59:23 +01007632 unsigned int len = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02007633 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007634 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007635 struct ssl_sock_ctx *ctx;
James Votha051b4a2013-05-14 20:37:59 +02007636
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007637 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007638 if (!conn || conn->xprt != &ssl_sock)
7639 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007640 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007641
Willy Tarreau911db9b2020-01-23 16:27:54 +01007642 if (conn->flags & CO_FL_WAIT_XPRT) {
James Votha051b4a2013-05-14 20:37:59 +02007643 smp->flags |= SMP_F_MAY_CHANGE;
7644 return 0;
7645 }
7646
Emeric Brunba841a12014-04-30 17:05:08 +02007647 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007648 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007649 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007650 crt = SSL_get_certificate(ctx->ssl);
James Votha051b4a2013-05-14 20:37:59 +02007651 if (!crt)
7652 goto out;
7653
7654 smp_trash = get_trash_chunk();
7655 digest = EVP_sha1();
Willy Tarreau105599c2020-02-25 08:59:23 +01007656 X509_digest(crt, digest, (unsigned char *) smp_trash->area, &len);
7657 smp_trash->data = len;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007658 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007659 smp->data.type = SMP_T_BIN;
James Votha051b4a2013-05-14 20:37:59 +02007660 ret = 1;
7661out:
Emeric Brunba841a12014-04-30 17:05:08 +02007662 /* SSL_get_peer_certificate, it increase X509 * ref count */
7663 if (cert_peer && crt)
James Votha051b4a2013-05-14 20:37:59 +02007664 X509_free(crt);
7665 return ret;
7666}
7667
Emeric Brunba841a12014-04-30 17:05:08 +02007668/* string, returns certificate's notafter date in ASN1_UTCTIME format.
7669 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7670 * should be use.
7671 */
Emeric Brunce5ad802012-10-22 14:11:22 +02007672static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007673smp_fetch_ssl_x_notafter(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunce5ad802012-10-22 14:11:22 +02007674{
Emeric Brunba841a12014-04-30 17:05:08 +02007675 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brunce5ad802012-10-22 14:11:22 +02007676 X509 *crt = NULL;
7677 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02007678 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007679 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007680 struct ssl_sock_ctx *ctx;
Emeric Brunce5ad802012-10-22 14:11:22 +02007681
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007682 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007683 if (!conn || conn->xprt != &ssl_sock)
7684 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007685 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007686
Willy Tarreau911db9b2020-01-23 16:27:54 +01007687 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Brunce5ad802012-10-22 14:11:22 +02007688 smp->flags |= SMP_F_MAY_CHANGE;
7689 return 0;
7690 }
7691
Emeric Brunba841a12014-04-30 17:05:08 +02007692 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007693 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007694 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007695 crt = SSL_get_certificate(ctx->ssl);
Emeric Brunce5ad802012-10-22 14:11:22 +02007696 if (!crt)
7697 goto out;
7698
Willy Tarreau47ca5452012-12-23 20:22:19 +01007699 smp_trash = get_trash_chunk();
Rosen Penev68185952018-12-14 08:47:02 -08007700 if (ssl_sock_get_time(X509_getm_notAfter(crt), smp_trash) <= 0)
Emeric Brunce5ad802012-10-22 14:11:22 +02007701 goto out;
7702
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007703 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007704 smp->data.type = SMP_T_STR;
Emeric Brunce5ad802012-10-22 14:11:22 +02007705 ret = 1;
7706out:
Emeric Brunba841a12014-04-30 17:05:08 +02007707 /* SSL_get_peer_certificate, it increase X509 * ref count */
7708 if (cert_peer && crt)
Emeric Brunce5ad802012-10-22 14:11:22 +02007709 X509_free(crt);
7710 return ret;
7711}
7712
Emeric Brunba841a12014-04-30 17:05:08 +02007713/* string, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. of certificate's issuer
7714 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7715 * should be use.
7716 */
Emeric Brun87855892012-10-17 17:39:35 +02007717static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007718smp_fetch_ssl_x_i_dn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun87855892012-10-17 17:39:35 +02007719{
Emeric Brunba841a12014-04-30 17:05:08 +02007720 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun87855892012-10-17 17:39:35 +02007721 X509 *crt = NULL;
7722 X509_NAME *name;
7723 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02007724 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007725 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007726 struct ssl_sock_ctx *ctx;
Emeric Brun87855892012-10-17 17:39:35 +02007727
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007728 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007729 if (!conn || conn->xprt != &ssl_sock)
7730 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007731 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007732
Willy Tarreau911db9b2020-01-23 16:27:54 +01007733 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Brun87855892012-10-17 17:39:35 +02007734 smp->flags |= SMP_F_MAY_CHANGE;
7735 return 0;
7736 }
7737
Emeric Brunba841a12014-04-30 17:05:08 +02007738 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007739 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007740 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007741 crt = SSL_get_certificate(ctx->ssl);
Emeric Brun87855892012-10-17 17:39:35 +02007742 if (!crt)
7743 goto out;
7744
7745 name = X509_get_issuer_name(crt);
7746 if (!name)
7747 goto out;
7748
Willy Tarreau47ca5452012-12-23 20:22:19 +01007749 smp_trash = get_trash_chunk();
Elliot Otchet71f82972020-01-15 08:12:14 -05007750 if (args && args[0].type == ARGT_STR && args[0].data.str.data > 0) {
Emeric Brun87855892012-10-17 17:39:35 +02007751 int pos = 1;
7752
7753 if (args[1].type == ARGT_SINT)
7754 pos = args[1].data.sint;
Emeric Brun87855892012-10-17 17:39:35 +02007755
7756 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
7757 goto out;
7758 }
Elliot Otchet71f82972020-01-15 08:12:14 -05007759 else if (args && args[2].type == ARGT_STR && args[2].data.str.data > 0) {
7760 if (ssl_sock_get_dn_formatted(name, &args[2].data.str, smp_trash) <= 0)
7761 goto out;
7762 }
Emeric Brun87855892012-10-17 17:39:35 +02007763 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
7764 goto out;
7765
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007766 smp->data.type = SMP_T_STR;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007767 smp->data.u.str = *smp_trash;
Emeric Brun87855892012-10-17 17:39:35 +02007768 ret = 1;
7769out:
Emeric Brunba841a12014-04-30 17:05:08 +02007770 /* SSL_get_peer_certificate, it increase X509 * ref count */
7771 if (cert_peer && crt)
Emeric Brun87855892012-10-17 17:39:35 +02007772 X509_free(crt);
7773 return ret;
7774}
7775
Emeric Brunba841a12014-04-30 17:05:08 +02007776/* string, returns notbefore date in ASN1_UTCTIME format.
7777 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7778 * should be use.
7779 */
Emeric Brunce5ad802012-10-22 14:11:22 +02007780static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007781smp_fetch_ssl_x_notbefore(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunce5ad802012-10-22 14:11:22 +02007782{
Emeric Brunba841a12014-04-30 17:05:08 +02007783 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brunce5ad802012-10-22 14:11:22 +02007784 X509 *crt = NULL;
7785 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02007786 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007787 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007788 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007789
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007790 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007791 if (!conn || conn->xprt != &ssl_sock)
Emeric Brunce5ad802012-10-22 14:11:22 +02007792 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007793 ctx = conn->xprt_ctx;
Emeric Brunce5ad802012-10-22 14:11:22 +02007794
Willy Tarreau911db9b2020-01-23 16:27:54 +01007795 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Brunce5ad802012-10-22 14:11:22 +02007796 smp->flags |= SMP_F_MAY_CHANGE;
7797 return 0;
7798 }
7799
Emeric Brunba841a12014-04-30 17:05:08 +02007800 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007801 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007802 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007803 crt = SSL_get_certificate(ctx->ssl);
Emeric Brunce5ad802012-10-22 14:11:22 +02007804 if (!crt)
7805 goto out;
7806
Willy Tarreau47ca5452012-12-23 20:22:19 +01007807 smp_trash = get_trash_chunk();
Rosen Penev68185952018-12-14 08:47:02 -08007808 if (ssl_sock_get_time(X509_getm_notBefore(crt), smp_trash) <= 0)
Emeric Brunce5ad802012-10-22 14:11:22 +02007809 goto out;
7810
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007811 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007812 smp->data.type = SMP_T_STR;
Emeric Brunce5ad802012-10-22 14:11:22 +02007813 ret = 1;
7814out:
Emeric Brunba841a12014-04-30 17:05:08 +02007815 /* SSL_get_peer_certificate, it increase X509 * ref count */
7816 if (cert_peer && crt)
Emeric Brunce5ad802012-10-22 14:11:22 +02007817 X509_free(crt);
7818 return ret;
7819}
7820
Emeric Brunba841a12014-04-30 17:05:08 +02007821/* string, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. of certificate's subject
7822 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7823 * should be use.
7824 */
Emeric Brun87855892012-10-17 17:39:35 +02007825static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007826smp_fetch_ssl_x_s_dn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun87855892012-10-17 17:39:35 +02007827{
Emeric Brunba841a12014-04-30 17:05:08 +02007828 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun87855892012-10-17 17:39:35 +02007829 X509 *crt = NULL;
7830 X509_NAME *name;
7831 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02007832 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007833 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007834 struct ssl_sock_ctx *ctx;
Emeric Brun87855892012-10-17 17:39:35 +02007835
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007836 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007837 if (!conn || conn->xprt != &ssl_sock)
7838 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007839 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007840
Willy Tarreau911db9b2020-01-23 16:27:54 +01007841 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Brun87855892012-10-17 17:39:35 +02007842 smp->flags |= SMP_F_MAY_CHANGE;
7843 return 0;
7844 }
7845
Emeric Brunba841a12014-04-30 17:05:08 +02007846 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007847 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007848 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007849 crt = SSL_get_certificate(ctx->ssl);
Emeric Brun87855892012-10-17 17:39:35 +02007850 if (!crt)
7851 goto out;
7852
7853 name = X509_get_subject_name(crt);
7854 if (!name)
7855 goto out;
7856
Willy Tarreau47ca5452012-12-23 20:22:19 +01007857 smp_trash = get_trash_chunk();
Elliot Otchet71f82972020-01-15 08:12:14 -05007858 if (args && args[0].type == ARGT_STR && args[0].data.str.data > 0) {
Emeric Brun87855892012-10-17 17:39:35 +02007859 int pos = 1;
7860
7861 if (args[1].type == ARGT_SINT)
7862 pos = args[1].data.sint;
Emeric Brun87855892012-10-17 17:39:35 +02007863
7864 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
7865 goto out;
7866 }
Elliot Otchet71f82972020-01-15 08:12:14 -05007867 else if (args && args[2].type == ARGT_STR && args[2].data.str.data > 0) {
7868 if (ssl_sock_get_dn_formatted(name, &args[2].data.str, smp_trash) <= 0)
7869 goto out;
7870 }
Emeric Brun87855892012-10-17 17:39:35 +02007871 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
7872 goto out;
7873
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007874 smp->data.type = SMP_T_STR;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007875 smp->data.u.str = *smp_trash;
Emeric Brun87855892012-10-17 17:39:35 +02007876 ret = 1;
7877out:
Emeric Brunba841a12014-04-30 17:05:08 +02007878 /* SSL_get_peer_certificate, it increase X509 * ref count */
7879 if (cert_peer && crt)
Emeric Brun87855892012-10-17 17:39:35 +02007880 X509_free(crt);
7881 return ret;
7882}
Emeric Brun9143d372012-12-20 15:44:16 +01007883
7884/* integer, returns true if current session use a client certificate */
7885static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007886smp_fetch_ssl_c_used(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun9143d372012-12-20 15:44:16 +01007887{
7888 X509 *crt;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007889 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007890 struct ssl_sock_ctx *ctx;
Emeric Brun9143d372012-12-20 15:44:16 +01007891
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007892 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007893 if (!conn || conn->xprt != &ssl_sock)
7894 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007895 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007896
Willy Tarreau911db9b2020-01-23 16:27:54 +01007897 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Brun9143d372012-12-20 15:44:16 +01007898 smp->flags |= SMP_F_MAY_CHANGE;
7899 return 0;
7900 }
7901
7902 /* SSL_get_peer_certificate returns a ptr on allocated X509 struct */
Olivier Houchard66ab4982019-02-26 18:37:15 +01007903 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brun9143d372012-12-20 15:44:16 +01007904 if (crt) {
7905 X509_free(crt);
7906 }
7907
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007908 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007909 smp->data.u.sint = (crt != NULL);
Emeric Brun9143d372012-12-20 15:44:16 +01007910 return 1;
7911}
7912
Emeric Brunba841a12014-04-30 17:05:08 +02007913/* integer, returns the certificate version
7914 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7915 * should be use.
7916 */
Emeric Bruna7359fd2012-10-17 15:03:11 +02007917static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007918smp_fetch_ssl_x_version(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Bruna7359fd2012-10-17 15:03:11 +02007919{
Emeric Brunba841a12014-04-30 17:05:08 +02007920 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Bruna7359fd2012-10-17 15:03:11 +02007921 X509 *crt;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007922 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007923 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007924
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007925 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007926 if (!conn || conn->xprt != &ssl_sock)
Emeric Bruna7359fd2012-10-17 15:03:11 +02007927 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007928 ctx = conn->xprt_ctx;
Emeric Bruna7359fd2012-10-17 15:03:11 +02007929
Willy Tarreau911db9b2020-01-23 16:27:54 +01007930 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Bruna7359fd2012-10-17 15:03:11 +02007931 smp->flags |= SMP_F_MAY_CHANGE;
7932 return 0;
7933 }
7934
Emeric Brunba841a12014-04-30 17:05:08 +02007935 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007936 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007937 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007938 crt = SSL_get_certificate(ctx->ssl);
Emeric Bruna7359fd2012-10-17 15:03:11 +02007939 if (!crt)
7940 return 0;
7941
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007942 smp->data.u.sint = (unsigned int)(1 + X509_get_version(crt));
Emeric Brunba841a12014-04-30 17:05:08 +02007943 /* SSL_get_peer_certificate increase X509 * ref count */
7944 if (cert_peer)
7945 X509_free(crt);
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007946 smp->data.type = SMP_T_SINT;
Emeric Bruna7359fd2012-10-17 15:03:11 +02007947
7948 return 1;
7949}
7950
Emeric Brunba841a12014-04-30 17:05:08 +02007951/* string, returns the certificate's signature algorithm.
7952 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7953 * should be use.
7954 */
Emeric Brun7f56e742012-10-19 18:15:40 +02007955static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007956smp_fetch_ssl_x_sig_alg(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun7f56e742012-10-19 18:15:40 +02007957{
Emeric Brunba841a12014-04-30 17:05:08 +02007958 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun7f56e742012-10-19 18:15:40 +02007959 X509 *crt;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007960 __OPENSSL_110_CONST__ ASN1_OBJECT *algorithm;
Emeric Brun7f56e742012-10-19 18:15:40 +02007961 int nid;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007962 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007963 struct ssl_sock_ctx *ctx;
Emeric Brun7f56e742012-10-19 18:15:40 +02007964
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007965 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007966 if (!conn || conn->xprt != &ssl_sock)
7967 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007968 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007969
Willy Tarreau911db9b2020-01-23 16:27:54 +01007970 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Brun7f56e742012-10-19 18:15:40 +02007971 smp->flags |= SMP_F_MAY_CHANGE;
7972 return 0;
7973 }
7974
Emeric Brunba841a12014-04-30 17:05:08 +02007975 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007976 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007977 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007978 crt = SSL_get_certificate(ctx->ssl);
Emeric Brun7f56e742012-10-19 18:15:40 +02007979 if (!crt)
7980 return 0;
7981
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007982 X509_ALGOR_get0(&algorithm, NULL, NULL, X509_get0_tbs_sigalg(crt));
7983 nid = OBJ_obj2nid(algorithm);
Emeric Brun7f56e742012-10-19 18:15:40 +02007984
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007985 smp->data.u.str.area = (char *)OBJ_nid2sn(nid);
7986 if (!smp->data.u.str.area) {
Emeric Brunba841a12014-04-30 17:05:08 +02007987 /* SSL_get_peer_certificate increase X509 * ref count */
7988 if (cert_peer)
7989 X509_free(crt);
Emeric Brun7f56e742012-10-19 18:15:40 +02007990 return 0;
Emeric Brun9bf3ba22013-10-07 14:31:44 +02007991 }
Emeric Brun7f56e742012-10-19 18:15:40 +02007992
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007993 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01007994 smp->flags |= SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007995 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brunba841a12014-04-30 17:05:08 +02007996 /* SSL_get_peer_certificate increase X509 * ref count */
7997 if (cert_peer)
7998 X509_free(crt);
Emeric Brun7f56e742012-10-19 18:15:40 +02007999
8000 return 1;
8001}
8002
Emeric Brunba841a12014-04-30 17:05:08 +02008003/* string, returns the certificate's key algorithm.
8004 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
8005 * should be use.
8006 */
Emeric Brun521a0112012-10-22 12:22:55 +02008007static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008008smp_fetch_ssl_x_key_alg(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun521a0112012-10-22 12:22:55 +02008009{
Emeric Brunba841a12014-04-30 17:05:08 +02008010 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun521a0112012-10-22 12:22:55 +02008011 X509 *crt;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02008012 ASN1_OBJECT *algorithm;
Emeric Brun521a0112012-10-22 12:22:55 +02008013 int nid;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008014 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008015 struct ssl_sock_ctx *ctx;
Emeric Brun521a0112012-10-22 12:22:55 +02008016
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02008017 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008018 if (!conn || conn->xprt != &ssl_sock)
8019 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008020 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008021
Willy Tarreau911db9b2020-01-23 16:27:54 +01008022 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Brun521a0112012-10-22 12:22:55 +02008023 smp->flags |= SMP_F_MAY_CHANGE;
8024 return 0;
8025 }
8026
Emeric Brunba841a12014-04-30 17:05:08 +02008027 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01008028 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02008029 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01008030 crt = SSL_get_certificate(ctx->ssl);
Emeric Brun521a0112012-10-22 12:22:55 +02008031 if (!crt)
8032 return 0;
8033
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02008034 X509_PUBKEY_get0_param(&algorithm, NULL, NULL, NULL, X509_get_X509_PUBKEY(crt));
8035 nid = OBJ_obj2nid(algorithm);
Emeric Brun521a0112012-10-22 12:22:55 +02008036
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008037 smp->data.u.str.area = (char *)OBJ_nid2sn(nid);
8038 if (!smp->data.u.str.area) {
Emeric Brunba841a12014-04-30 17:05:08 +02008039 /* SSL_get_peer_certificate increase X509 * ref count */
8040 if (cert_peer)
8041 X509_free(crt);
Emeric Brun521a0112012-10-22 12:22:55 +02008042 return 0;
Emeric Brun9bf3ba22013-10-07 14:31:44 +02008043 }
Emeric Brun521a0112012-10-22 12:22:55 +02008044
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008045 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008046 smp->flags |= SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008047 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brunba841a12014-04-30 17:05:08 +02008048 if (cert_peer)
8049 X509_free(crt);
Emeric Brun521a0112012-10-22 12:22:55 +02008050
8051 return 1;
8052}
8053
Emeric Brun645ae792014-04-30 14:21:06 +02008054/* boolean, returns true if front conn. transport layer is SSL.
8055 * This function is also usable on backend conn if the fetch keyword 5th
8056 * char is 'b'.
8057 */
Willy Tarreau7875d092012-09-10 08:20:03 +02008058static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008059smp_fetch_ssl_fc(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02008060{
Emeric Bruneb8def92018-02-19 15:59:48 +01008061 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
8062 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008063
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008064 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02008065 smp->data.u.sint = (conn && conn->xprt == &ssl_sock);
Willy Tarreau7875d092012-09-10 08:20:03 +02008066 return 1;
8067}
8068
Emeric Brun2525b6b2012-10-18 15:59:43 +02008069/* boolean, returns true if client present a SNI */
Willy Tarreau7875d092012-09-10 08:20:03 +02008070static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008071smp_fetch_ssl_fc_has_sni(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02008072{
8073#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02008074 struct connection *conn = objt_conn(smp->sess->origin);
Olivier Houchard66ab4982019-02-26 18:37:15 +01008075 struct ssl_sock_ctx *ctx = conn ? conn->xprt_ctx : NULL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008076
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008077 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02008078 smp->data.u.sint = (conn && conn->xprt == &ssl_sock) &&
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008079 conn->xprt_ctx &&
Olivier Houchard66ab4982019-02-26 18:37:15 +01008080 SSL_get_servername(ctx->ssl, TLSEXT_NAMETYPE_host_name) != NULL;
Willy Tarreau7875d092012-09-10 08:20:03 +02008081 return 1;
8082#else
8083 return 0;
8084#endif
8085}
8086
Emeric Brun74f7ffa2018-02-19 16:14:12 +01008087/* boolean, returns true if client session has been resumed.
8088 * This function is also usable on backend conn if the fetch keyword 5th
8089 * char is 'b'.
8090 */
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02008091static int
8092smp_fetch_ssl_fc_is_resumed(const struct arg *args, struct sample *smp, const char *kw, void *private)
8093{
Emeric Brun74f7ffa2018-02-19 16:14:12 +01008094 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
8095 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008096 struct ssl_sock_ctx *ctx = conn ? conn->xprt_ctx : NULL;
Emeric Brun74f7ffa2018-02-19 16:14:12 +01008097
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02008098
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008099 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02008100 smp->data.u.sint = (conn && conn->xprt == &ssl_sock) &&
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02008101 conn->xprt_ctx &&
Olivier Houchard66ab4982019-02-26 18:37:15 +01008102 SSL_session_reused(ctx->ssl);
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02008103 return 1;
8104}
8105
Emeric Brun645ae792014-04-30 14:21:06 +02008106/* string, returns the used cipher if front conn. transport layer is SSL.
8107 * This function is also usable on backend conn if the fetch keyword 5th
8108 * char is 'b'.
8109 */
Emeric Brun589fcad2012-10-16 14:13:26 +02008110static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008111smp_fetch_ssl_fc_cipher(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02008112{
Emeric Bruneb8def92018-02-19 15:59:48 +01008113 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
8114 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008115 struct ssl_sock_ctx *ctx;
Emeric Brun589fcad2012-10-16 14:13:26 +02008116
Willy Tarreaube508f12016-03-10 11:47:01 +01008117 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008118 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02008119 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008120 ctx = conn->xprt_ctx;
Emeric Brun589fcad2012-10-16 14:13:26 +02008121
Olivier Houchard66ab4982019-02-26 18:37:15 +01008122 smp->data.u.str.area = (char *)SSL_get_cipher_name(ctx->ssl);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008123 if (!smp->data.u.str.area)
Emeric Brun589fcad2012-10-16 14:13:26 +02008124 return 0;
8125
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008126 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008127 smp->flags |= SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008128 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brun589fcad2012-10-16 14:13:26 +02008129
8130 return 1;
8131}
8132
Emeric Brun645ae792014-04-30 14:21:06 +02008133/* integer, returns the algoritm's keysize if front conn. transport layer
8134 * is SSL.
8135 * This function is also usable on backend conn if the fetch keyword 5th
8136 * char is 'b'.
8137 */
Emeric Brun589fcad2012-10-16 14:13:26 +02008138static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008139smp_fetch_ssl_fc_alg_keysize(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +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;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008143 struct ssl_sock_ctx *ctx;
Willy Tarreaue237fe12016-03-10 17:05:28 +01008144 int sint;
Willy Tarreaube508f12016-03-10 11:47:01 +01008145
Emeric Brun589fcad2012-10-16 14:13:26 +02008146 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008147 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02008148 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008149 ctx = conn->xprt_ctx;
Emeric Brun589fcad2012-10-16 14:13:26 +02008150
Olivier Houchard66ab4982019-02-26 18:37:15 +01008151 if (!SSL_get_cipher_bits(ctx->ssl, &sint))
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008152 return 0;
8153
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02008154 smp->data.u.sint = sint;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008155 smp->data.type = SMP_T_SINT;
Emeric Brun589fcad2012-10-16 14:13:26 +02008156
8157 return 1;
8158}
8159
Emeric Brun645ae792014-04-30 14:21:06 +02008160/* integer, returns the used keysize if front conn. transport layer is SSL.
8161 * This function is also usable on backend conn if the fetch keyword 5th
8162 * char is 'b'.
8163 */
Emeric Brun589fcad2012-10-16 14:13:26 +02008164static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008165smp_fetch_ssl_fc_use_keysize(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02008166{
Emeric Bruneb8def92018-02-19 15:59:48 +01008167 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
8168 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008169 struct ssl_sock_ctx *ctx;
Willy Tarreaube508f12016-03-10 11:47:01 +01008170
Emeric Brun589fcad2012-10-16 14:13:26 +02008171 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008172 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8173 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008174 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008175
Olivier Houchard66ab4982019-02-26 18:37:15 +01008176 smp->data.u.sint = (unsigned int)SSL_get_cipher_bits(ctx->ssl, NULL);
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02008177 if (!smp->data.u.sint)
Emeric Brun589fcad2012-10-16 14:13:26 +02008178 return 0;
8179
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008180 smp->data.type = SMP_T_SINT;
Emeric Brun589fcad2012-10-16 14:13:26 +02008181
8182 return 1;
8183}
8184
Bernard Spil13c53f82018-02-15 13:34:58 +01008185#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Willy Tarreau7875d092012-09-10 08:20:03 +02008186static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008187smp_fetch_ssl_fc_npn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreaua33c6542012-10-15 13:19:06 +02008188{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008189 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008190 struct ssl_sock_ctx *ctx;
Willy Tarreau105599c2020-02-25 08:59:23 +01008191 unsigned int len = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008192
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008193 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008194 smp->data.type = SMP_T_STR;
Willy Tarreaua33c6542012-10-15 13:19:06 +02008195
Olivier Houchard6b77f492018-11-22 18:18:29 +01008196 conn = (kw[4] != 'b' ) ? objt_conn(smp->sess->origin) :
8197 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008198 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8199 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008200 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008201
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008202 smp->data.u.str.area = NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008203 SSL_get0_next_proto_negotiated(ctx->ssl,
Willy Tarreau105599c2020-02-25 08:59:23 +01008204 (const unsigned char **)&smp->data.u.str.area,
8205 &len);
Willy Tarreaua33c6542012-10-15 13:19:06 +02008206
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008207 if (!smp->data.u.str.area)
Willy Tarreaua33c6542012-10-15 13:19:06 +02008208 return 0;
8209
Willy Tarreau105599c2020-02-25 08:59:23 +01008210 smp->data.u.str.data = len;
Willy Tarreaua33c6542012-10-15 13:19:06 +02008211 return 1;
Willy Tarreaua33c6542012-10-15 13:19:06 +02008212}
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02008213#endif
Willy Tarreaua33c6542012-10-15 13:19:06 +02008214
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01008215#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02008216static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008217smp_fetch_ssl_fc_alpn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreauab861d32013-04-02 02:30:41 +02008218{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008219 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008220 struct ssl_sock_ctx *ctx;
Willy Tarreau105599c2020-02-25 08:59:23 +01008221 unsigned int len = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008222
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008223 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008224 smp->data.type = SMP_T_STR;
Willy Tarreauab861d32013-04-02 02:30:41 +02008225
Olivier Houchard6b77f492018-11-22 18:18:29 +01008226 conn = (kw[4] != 'b' ) ? objt_conn(smp->sess->origin) :
8227 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
8228
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008229 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Willy Tarreauab861d32013-04-02 02:30:41 +02008230 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008231 ctx = conn->xprt_ctx;
Willy Tarreauab861d32013-04-02 02:30:41 +02008232
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008233 smp->data.u.str.area = NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008234 SSL_get0_alpn_selected(ctx->ssl,
Willy Tarreau105599c2020-02-25 08:59:23 +01008235 (const unsigned char **)&smp->data.u.str.area,
8236 &len);
Willy Tarreauab861d32013-04-02 02:30:41 +02008237
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008238 if (!smp->data.u.str.area)
Willy Tarreauab861d32013-04-02 02:30:41 +02008239 return 0;
8240
Willy Tarreau105599c2020-02-25 08:59:23 +01008241 smp->data.u.str.data = len;
Willy Tarreauab861d32013-04-02 02:30:41 +02008242 return 1;
8243}
8244#endif
8245
Emeric Brun645ae792014-04-30 14:21:06 +02008246/* string, returns the used protocol if front conn. transport layer is SSL.
8247 * This function is also usable on backend conn if the fetch keyword 5th
8248 * char is 'b'.
8249 */
Willy Tarreaua33c6542012-10-15 13:19:06 +02008250static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008251smp_fetch_ssl_fc_protocol(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02008252{
Emeric Bruneb8def92018-02-19 15:59:48 +01008253 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
8254 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008255 struct ssl_sock_ctx *ctx;
Willy Tarreaube508f12016-03-10 11:47:01 +01008256
Emeric Brun589fcad2012-10-16 14:13:26 +02008257 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008258 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8259 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008260 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008261
Olivier Houchard66ab4982019-02-26 18:37:15 +01008262 smp->data.u.str.area = (char *)SSL_get_version(ctx->ssl);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008263 if (!smp->data.u.str.area)
Emeric Brun589fcad2012-10-16 14:13:26 +02008264 return 0;
8265
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008266 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008267 smp->flags = SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008268 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brun589fcad2012-10-16 14:13:26 +02008269
8270 return 1;
8271}
8272
Willy Tarreau87b09662015-04-03 00:22:06 +02008273/* binary, returns the SSL stream id if front conn. transport layer is SSL.
Emeric Brun645ae792014-04-30 14:21:06 +02008274 * This function is also usable on backend conn if the fetch keyword 5th
8275 * char is 'b'.
8276 */
Willy Tarreau9a1ab082019-05-09 13:26:41 +02008277#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
Emeric Brun589fcad2012-10-16 14:13:26 +02008278static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008279smp_fetch_ssl_fc_session_id(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunfe68f682012-10-16 14:59:28 +02008280{
Emeric Bruneb8def92018-02-19 15:59:48 +01008281 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
8282 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaue237fe12016-03-10 17:05:28 +01008283 SSL_SESSION *ssl_sess;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008284 struct ssl_sock_ctx *ctx;
Willy Tarreau105599c2020-02-25 08:59:23 +01008285 unsigned int len = 0;
Willy Tarreaube508f12016-03-10 11:47:01 +01008286
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008287 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008288 smp->data.type = SMP_T_BIN;
Emeric Brunfe68f682012-10-16 14:59:28 +02008289
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008290 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8291 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008292 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008293
Olivier Houchard66ab4982019-02-26 18:37:15 +01008294 ssl_sess = SSL_get_session(ctx->ssl);
Willy Tarreau192252e2015-04-04 01:47:55 +02008295 if (!ssl_sess)
Emeric Brunfe68f682012-10-16 14:59:28 +02008296 return 0;
8297
Willy Tarreau105599c2020-02-25 08:59:23 +01008298 smp->data.u.str.area = (char *)SSL_SESSION_get_id(ssl_sess, &len);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008299 if (!smp->data.u.str.area || !smp->data.u.str.data)
Emeric Brunfe68f682012-10-16 14:59:28 +02008300 return 0;
8301
Willy Tarreau105599c2020-02-25 08:59:23 +01008302 smp->data.u.str.data = len;
Emeric Brunfe68f682012-10-16 14:59:28 +02008303 return 1;
Emeric Brunfe68f682012-10-16 14:59:28 +02008304}
Patrick Hemmer41966772018-04-28 19:15:48 -04008305#endif
8306
Emeric Brunfe68f682012-10-16 14:59:28 +02008307
Emmanuel Hocdet839af572019-05-14 16:27:35 +02008308#if HA_OPENSSL_VERSION_NUMBER >= 0x10100000L
Patrick Hemmere0275472018-04-28 19:15:51 -04008309static int
Patrick Hemmer65674662019-06-04 08:13:03 -04008310smp_fetch_ssl_fc_random(const struct arg *args, struct sample *smp, const char *kw, void *private)
8311{
8312 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
8313 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
8314 struct buffer *data;
8315 struct ssl_sock_ctx *ctx;
8316
8317 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8318 return 0;
8319 ctx = conn->xprt_ctx;
8320
8321 data = get_trash_chunk();
8322 if (kw[7] == 'c')
8323 data->data = SSL_get_client_random(ctx->ssl,
8324 (unsigned char *) data->area,
8325 data->size);
8326 else
8327 data->data = SSL_get_server_random(ctx->ssl,
8328 (unsigned char *) data->area,
8329 data->size);
8330 if (!data->data)
8331 return 0;
8332
8333 smp->flags = 0;
8334 smp->data.type = SMP_T_BIN;
8335 smp->data.u.str = *data;
8336
8337 return 1;
8338}
8339
8340static int
Patrick Hemmere0275472018-04-28 19:15:51 -04008341smp_fetch_ssl_fc_session_key(const struct arg *args, struct sample *smp, const char *kw, void *private)
8342{
8343 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
8344 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
8345 SSL_SESSION *ssl_sess;
Willy Tarreau83061a82018-07-13 11:56:34 +02008346 struct buffer *data;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008347 struct ssl_sock_ctx *ctx;
Patrick Hemmere0275472018-04-28 19:15:51 -04008348
8349 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8350 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008351 ctx = conn->xprt_ctx;
Patrick Hemmere0275472018-04-28 19:15:51 -04008352
Olivier Houchard66ab4982019-02-26 18:37:15 +01008353 ssl_sess = SSL_get_session(ctx->ssl);
Patrick Hemmere0275472018-04-28 19:15:51 -04008354 if (!ssl_sess)
8355 return 0;
8356
8357 data = get_trash_chunk();
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008358 data->data = SSL_SESSION_get_master_key(ssl_sess,
8359 (unsigned char *) data->area,
8360 data->size);
8361 if (!data->data)
Patrick Hemmere0275472018-04-28 19:15:51 -04008362 return 0;
8363
8364 smp->flags = 0;
8365 smp->data.type = SMP_T_BIN;
8366 smp->data.u.str = *data;
8367
8368 return 1;
8369}
8370#endif
8371
Patrick Hemmer41966772018-04-28 19:15:48 -04008372#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emeric Brunfe68f682012-10-16 14:59:28 +02008373static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008374smp_fetch_ssl_fc_sni(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02008375{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008376 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008377 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008378
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008379 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008380 smp->data.type = SMP_T_STR;
Willy Tarreau7875d092012-09-10 08:20:03 +02008381
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02008382 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008383 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8384 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008385 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008386
Olivier Houchard66ab4982019-02-26 18:37:15 +01008387 smp->data.u.str.area = (char *)SSL_get_servername(ctx->ssl, TLSEXT_NAMETYPE_host_name);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008388 if (!smp->data.u.str.area)
Willy Tarreau3e394c92012-09-14 23:56:58 +02008389 return 0;
8390
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008391 smp->data.u.str.data = strlen(smp->data.u.str.area);
Willy Tarreau7875d092012-09-10 08:20:03 +02008392 return 1;
Willy Tarreau7875d092012-09-10 08:20:03 +02008393}
Patrick Hemmer41966772018-04-28 19:15:48 -04008394#endif
Willy Tarreau7875d092012-09-10 08:20:03 +02008395
David Sc1ad52e2014-04-08 18:48:47 -04008396static int
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008397smp_fetch_ssl_fc_cl_bin(const struct arg *args, struct sample *smp, const char *kw, void *private)
8398{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008399 struct connection *conn;
8400 struct ssl_capture *capture;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008401 struct ssl_sock_ctx *ctx;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008402
8403 conn = objt_conn(smp->sess->origin);
8404 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8405 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008406 ctx = conn->xprt_ctx;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008407
Olivier Houchard66ab4982019-02-26 18:37:15 +01008408 capture = SSL_get_ex_data(ctx->ssl, ssl_capture_ptr_index);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008409 if (!capture)
8410 return 0;
8411
8412 smp->flags = SMP_F_CONST;
8413 smp->data.type = SMP_T_BIN;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008414 smp->data.u.str.area = capture->ciphersuite;
8415 smp->data.u.str.data = capture->ciphersuite_len;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008416 return 1;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008417}
8418
8419static int
8420smp_fetch_ssl_fc_cl_hex(const struct arg *args, struct sample *smp, const char *kw, void *private)
8421{
Willy Tarreau83061a82018-07-13 11:56:34 +02008422 struct buffer *data;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008423
8424 if (!smp_fetch_ssl_fc_cl_bin(args, smp, kw, private))
8425 return 0;
8426
8427 data = get_trash_chunk();
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008428 dump_binary(data, smp->data.u.str.area, smp->data.u.str.data);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008429 smp->data.type = SMP_T_BIN;
8430 smp->data.u.str = *data;
8431 return 1;
8432}
8433
8434static int
8435smp_fetch_ssl_fc_cl_xxh64(const struct arg *args, struct sample *smp, const char *kw, void *private)
8436{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008437 struct connection *conn;
8438 struct ssl_capture *capture;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008439 struct ssl_sock_ctx *ctx;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008440
8441 conn = objt_conn(smp->sess->origin);
8442 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8443 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008444 ctx = conn->xprt_ctx;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008445
Olivier Houchard66ab4982019-02-26 18:37:15 +01008446 capture = SSL_get_ex_data(ctx->ssl, ssl_capture_ptr_index);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008447 if (!capture)
8448 return 0;
8449
8450 smp->data.type = SMP_T_SINT;
8451 smp->data.u.sint = capture->xxh64;
8452 return 1;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008453}
8454
8455static int
8456smp_fetch_ssl_fc_cl_str(const struct arg *args, struct sample *smp, const char *kw, void *private)
8457{
Willy Tarreau5db847a2019-05-09 14:13:35 +02008458#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL)
Willy Tarreau83061a82018-07-13 11:56:34 +02008459 struct buffer *data;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008460 int i;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008461
8462 if (!smp_fetch_ssl_fc_cl_bin(args, smp, kw, private))
8463 return 0;
8464
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008465 data = get_trash_chunk();
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008466 for (i = 0; i + 1 < smp->data.u.str.data; i += 2) {
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02008467 const char *str;
8468 const SSL_CIPHER *cipher;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008469 const unsigned char *bin = (const unsigned char *) smp->data.u.str.area + i;
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02008470 uint16_t id = (bin[0] << 8) | bin[1];
8471#if defined(OPENSSL_IS_BORINGSSL)
8472 cipher = SSL_get_cipher_by_value(id);
8473#else
Willy Tarreaub7290772018-10-15 11:01:59 +02008474 struct connection *conn = __objt_conn(smp->sess->origin);
Olivier Houchard66ab4982019-02-26 18:37:15 +01008475 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
8476 cipher = SSL_CIPHER_find(ctx->ssl, bin);
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02008477#endif
8478 str = SSL_CIPHER_get_name(cipher);
8479 if (!str || strcmp(str, "(NONE)") == 0)
8480 chunk_appendf(data, "%sUNKNOWN(%04x)", i == 0 ? "" : ",", id);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008481 else
8482 chunk_appendf(data, "%s%s", i == 0 ? "" : ",", str);
8483 }
8484 smp->data.type = SMP_T_STR;
8485 smp->data.u.str = *data;
8486 return 1;
8487#else
8488 return smp_fetch_ssl_fc_cl_xxh64(args, smp, kw, private);
8489#endif
8490}
8491
Willy Tarreau9a1ab082019-05-09 13:26:41 +02008492#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008493static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008494smp_fetch_ssl_fc_unique_id(const struct arg *args, struct sample *smp, const char *kw, void *private)
David Sc1ad52e2014-04-08 18:48:47 -04008495{
Emeric Bruneb8def92018-02-19 15:59:48 +01008496 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
8497 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
David Sc1ad52e2014-04-08 18:48:47 -04008498 int finished_len;
Willy Tarreau83061a82018-07-13 11:56:34 +02008499 struct buffer *finished_trash;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008500 struct ssl_sock_ctx *ctx;
David Sc1ad52e2014-04-08 18:48:47 -04008501
8502 smp->flags = 0;
David Sc1ad52e2014-04-08 18:48:47 -04008503 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8504 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008505 ctx = conn->xprt_ctx;
David Sc1ad52e2014-04-08 18:48:47 -04008506
Willy Tarreau911db9b2020-01-23 16:27:54 +01008507 if (conn->flags & CO_FL_WAIT_XPRT) {
David Sc1ad52e2014-04-08 18:48:47 -04008508 smp->flags |= SMP_F_MAY_CHANGE;
8509 return 0;
8510 }
8511
8512 finished_trash = get_trash_chunk();
Olivier Houchard66ab4982019-02-26 18:37:15 +01008513 if (!SSL_session_reused(ctx->ssl))
8514 finished_len = SSL_get_peer_finished(ctx->ssl,
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008515 finished_trash->area,
8516 finished_trash->size);
David Sc1ad52e2014-04-08 18:48:47 -04008517 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01008518 finished_len = SSL_get_finished(ctx->ssl,
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008519 finished_trash->area,
8520 finished_trash->size);
David Sc1ad52e2014-04-08 18:48:47 -04008521
8522 if (!finished_len)
8523 return 0;
8524
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008525 finished_trash->data = finished_len;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02008526 smp->data.u.str = *finished_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008527 smp->data.type = SMP_T_BIN;
David Sc1ad52e2014-04-08 18:48:47 -04008528
8529 return 1;
David Sc1ad52e2014-04-08 18:48:47 -04008530}
Patrick Hemmer41966772018-04-28 19:15:48 -04008531#endif
David Sc1ad52e2014-04-08 18:48:47 -04008532
Emeric Brun2525b6b2012-10-18 15:59:43 +02008533/* integer, returns the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02008534static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008535smp_fetch_ssl_c_ca_err(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunf282a812012-09-21 15:27:54 +02008536{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008537 struct connection *conn;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008538 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008539
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02008540 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008541 if (!conn || conn->xprt != &ssl_sock)
8542 return 0;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008543 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008544
Willy Tarreau911db9b2020-01-23 16:27:54 +01008545 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Brunf282a812012-09-21 15:27:54 +02008546 smp->flags = SMP_F_MAY_CHANGE;
8547 return 0;
8548 }
8549
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008550 smp->data.type = SMP_T_SINT;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008551 smp->data.u.sint = (unsigned long long int)SSL_SOCK_ST_TO_CA_ERROR(ctx->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02008552 smp->flags = 0;
8553
8554 return 1;
8555}
8556
Emeric Brun2525b6b2012-10-18 15:59:43 +02008557/* integer, returns the depth of the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02008558static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008559smp_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 +02008560{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008561 struct connection *conn;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008562 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008563
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02008564 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008565 if (!conn || conn->xprt != &ssl_sock)
Emeric Brunf282a812012-09-21 15:27:54 +02008566 return 0;
8567
Willy Tarreau911db9b2020-01-23 16:27:54 +01008568 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Brunf282a812012-09-21 15:27:54 +02008569 smp->flags = SMP_F_MAY_CHANGE;
8570 return 0;
8571 }
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008572 ctx = conn->xprt_ctx;
Emeric Brunf282a812012-09-21 15:27:54 +02008573
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008574 smp->data.type = SMP_T_SINT;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008575 smp->data.u.sint = (long long int)SSL_SOCK_ST_TO_CAEDEPTH(ctx->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02008576 smp->flags = 0;
8577
8578 return 1;
8579}
8580
Emeric Brun2525b6b2012-10-18 15:59:43 +02008581/* integer, returns the first verify error on client certificate */
Emeric Brunf282a812012-09-21 15:27:54 +02008582static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008583smp_fetch_ssl_c_err(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunf282a812012-09-21 15:27:54 +02008584{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008585 struct connection *conn;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008586 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008587
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02008588 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008589 if (!conn || conn->xprt != &ssl_sock)
8590 return 0;
8591
Willy Tarreau911db9b2020-01-23 16:27:54 +01008592 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Brunf282a812012-09-21 15:27:54 +02008593 smp->flags = SMP_F_MAY_CHANGE;
8594 return 0;
8595 }
8596
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008597 ctx = conn->xprt_ctx;
8598
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008599 smp->data.type = SMP_T_SINT;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008600 smp->data.u.sint = (long long int)SSL_SOCK_ST_TO_CRTERROR(ctx->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02008601 smp->flags = 0;
8602
8603 return 1;
8604}
8605
Emeric Brun2525b6b2012-10-18 15:59:43 +02008606/* integer, returns the verify result on client cert */
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02008607static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008608smp_fetch_ssl_c_verify(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02008609{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008610 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008611 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008612
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02008613 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008614 if (!conn || conn->xprt != &ssl_sock)
8615 return 0;
8616
Willy Tarreau911db9b2020-01-23 16:27:54 +01008617 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02008618 smp->flags = SMP_F_MAY_CHANGE;
8619 return 0;
8620 }
8621
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008622 if (!conn->xprt_ctx)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02008623 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008624 ctx = conn->xprt_ctx;
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02008625
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008626 smp->data.type = SMP_T_SINT;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008627 smp->data.u.sint = (long long int)SSL_get_verify_result(ctx->ssl);
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02008628 smp->flags = 0;
8629
8630 return 1;
8631}
8632
Emeric Brunfb510ea2012-10-05 12:00:26 +02008633/* parse the "ca-file" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008634static int ssl_bind_parse_ca_file(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
Emeric Brund94b3fe2012-09-20 18:23:56 +02008635{
8636 if (!*args[cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01008637 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
Emeric Brund94b3fe2012-09-20 18:23:56 +02008638 return ERR_ALERT | ERR_FATAL;
8639 }
8640
Willy Tarreauef934602016-12-22 23:12:01 +01008641 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
8642 memprintf(&conf->ca_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02008643 else
8644 memprintf(&conf->ca_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02008645
Emmanuel Hocdetd4f9a602019-10-24 11:32:47 +02008646 if (!ssl_store_load_locations_file(conf->ca_file)) {
8647 memprintf(err, "'%s' : unable to load %s", args[cur_arg], conf->ca_file);
8648 return ERR_ALERT | ERR_FATAL;
8649 }
Emeric Brund94b3fe2012-09-20 18:23:56 +02008650 return 0;
8651}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008652static int bind_parse_ca_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8653{
8654 return ssl_bind_parse_ca_file(args, cur_arg, px, &conf->ssl_conf, err);
8655}
Emeric Brund94b3fe2012-09-20 18:23:56 +02008656
Christopher Faulet31af49d2015-06-09 17:29:50 +02008657/* parse the "ca-sign-file" bind keyword */
8658static int bind_parse_ca_sign_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8659{
8660 if (!*args[cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01008661 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
Christopher Faulet31af49d2015-06-09 17:29:50 +02008662 return ERR_ALERT | ERR_FATAL;
8663 }
8664
Willy Tarreauef934602016-12-22 23:12:01 +01008665 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
8666 memprintf(&conf->ca_sign_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Christopher Faulet31af49d2015-06-09 17:29:50 +02008667 else
8668 memprintf(&conf->ca_sign_file, "%s", args[cur_arg + 1]);
8669
8670 return 0;
8671}
8672
Bertrand Jacquinff13c062016-11-13 16:37:11 +00008673/* parse the "ca-sign-pass" bind keyword */
Christopher Faulet31af49d2015-06-09 17:29:50 +02008674static int bind_parse_ca_sign_pass(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8675{
8676 if (!*args[cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01008677 memprintf(err, "'%s' : missing CAkey password", args[cur_arg]);
Christopher Faulet31af49d2015-06-09 17:29:50 +02008678 return ERR_ALERT | ERR_FATAL;
8679 }
8680 memprintf(&conf->ca_sign_pass, "%s", args[cur_arg + 1]);
8681 return 0;
8682}
8683
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008684/* parse the "ciphers" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008685static 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 +02008686{
8687 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02008688 memprintf(err, "'%s' : missing cipher suite", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008689 return ERR_ALERT | ERR_FATAL;
8690 }
8691
Emeric Brun76d88952012-10-05 15:47:31 +02008692 free(conf->ciphers);
Willy Tarreau4348fad2012-09-20 16:48:07 +02008693 conf->ciphers = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008694 return 0;
8695}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008696static int bind_parse_ciphers(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8697{
8698 return ssl_bind_parse_ciphers(args, cur_arg, px, &conf->ssl_conf, err);
8699}
Dirkjan Bussink415150f2018-09-14 11:14:21 +02008700
Emmanuel Hocdet839af572019-05-14 16:27:35 +02008701#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02008702/* parse the "ciphersuites" bind keyword */
8703static int ssl_bind_parse_ciphersuites(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
8704{
8705 if (!*args[cur_arg + 1]) {
8706 memprintf(err, "'%s' : missing cipher suite", args[cur_arg]);
8707 return ERR_ALERT | ERR_FATAL;
8708 }
8709
8710 free(conf->ciphersuites);
8711 conf->ciphersuites = strdup(args[cur_arg + 1]);
8712 return 0;
8713}
8714static int bind_parse_ciphersuites(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8715{
8716 return ssl_bind_parse_ciphersuites(args, cur_arg, px, &conf->ssl_conf, err);
8717}
8718#endif
8719
Willy Tarreaubbc91962019-10-16 16:42:19 +02008720/* parse the "crt" bind keyword. Returns a set of ERR_* flags possibly with an error in <err>. */
Willy Tarreau4348fad2012-09-20 16:48:07 +02008721static 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 +02008722{
Willy Tarreau38011032013-08-13 16:59:39 +02008723 char path[MAXPATHLEN];
Willy Tarreaub75d6922014-04-14 18:05:41 +02008724
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008725 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02008726 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008727 return ERR_ALERT | ERR_FATAL;
8728 }
8729
Willy Tarreauef934602016-12-22 23:12:01 +01008730 if ((*args[cur_arg + 1] != '/' ) && global_ssl.crt_base) {
8731 if ((strlen(global_ssl.crt_base) + 1 + strlen(args[cur_arg + 1]) + 1) > MAXPATHLEN) {
Emeric Brunc8e8d122012-10-02 18:42:10 +02008732 memprintf(err, "'%s' : path too long", args[cur_arg]);
8733 return ERR_ALERT | ERR_FATAL;
8734 }
Willy Tarreauef934602016-12-22 23:12:01 +01008735 snprintf(path, sizeof(path), "%s/%s", global_ssl.crt_base, args[cur_arg + 1]);
Willy Tarreaubbc91962019-10-16 16:42:19 +02008736 return ssl_sock_load_cert(path, conf, err);
Emeric Brunc8e8d122012-10-02 18:42:10 +02008737 }
8738
Willy Tarreaubbc91962019-10-16 16:42:19 +02008739 return ssl_sock_load_cert(args[cur_arg + 1], conf, err);
Emeric Brund94b3fe2012-09-20 18:23:56 +02008740}
8741
Willy Tarreaubbc91962019-10-16 16:42:19 +02008742/* 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 +01008743static int bind_parse_crt_list(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8744{
Willy Tarreaubbc91962019-10-16 16:42:19 +02008745 int err_code;
8746
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01008747 if (!*args[cur_arg + 1]) {
8748 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
8749 return ERR_ALERT | ERR_FATAL;
8750 }
8751
Willy Tarreaubbc91962019-10-16 16:42:19 +02008752 err_code = ssl_sock_load_cert_list_file(args[cur_arg + 1], conf, px, err);
8753 if (err_code)
Willy Tarreauad1731d2013-04-02 17:35:58 +02008754 memprintf(err, "'%s' : %s", args[cur_arg], *err);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01008755
Willy Tarreaubbc91962019-10-16 16:42:19 +02008756 return err_code;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01008757}
8758
Emeric Brunfb510ea2012-10-05 12:00:26 +02008759/* parse the "crl-file" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008760static 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 +02008761{
Emeric Brun051cdab2012-10-02 19:25:50 +02008762#ifndef X509_V_FLAG_CRL_CHECK
Tim Duesterhus93128532019-11-23 23:45:10 +01008763 memprintf(err, "'%s' : library does not support CRL verify", args[cur_arg]);
Emeric Brun051cdab2012-10-02 19:25:50 +02008764 return ERR_ALERT | ERR_FATAL;
8765#else
Emeric Brund94b3fe2012-09-20 18:23:56 +02008766 if (!*args[cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01008767 memprintf(err, "'%s' : missing CRLfile path", args[cur_arg]);
Emeric Brund94b3fe2012-09-20 18:23:56 +02008768 return ERR_ALERT | ERR_FATAL;
8769 }
Emeric Brun2b58d042012-09-20 17:10:03 +02008770
Willy Tarreauef934602016-12-22 23:12:01 +01008771 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
8772 memprintf(&conf->crl_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02008773 else
8774 memprintf(&conf->crl_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02008775
Emmanuel Hocdetb270e812019-11-21 19:09:31 +01008776 if (!ssl_store_load_locations_file(conf->crl_file)) {
8777 memprintf(err, "'%s' : unable to load %s", args[cur_arg], conf->crl_file);
8778 return ERR_ALERT | ERR_FATAL;
8779 }
Emeric Brun2b58d042012-09-20 17:10:03 +02008780 return 0;
Emeric Brun051cdab2012-10-02 19:25:50 +02008781#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02008782}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008783static int bind_parse_crl_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8784{
8785 return ssl_bind_parse_crl_file(args, cur_arg, px, &conf->ssl_conf, err);
8786}
Emeric Brun2b58d042012-09-20 17:10:03 +02008787
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01008788/* parse the "curves" bind keyword keyword */
8789static int ssl_bind_parse_curves(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
8790{
Lukas Tribusd14b49c2019-11-24 18:20:40 +01008791#if ((HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL) || defined(LIBRESSL_VERSION_NUMBER))
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01008792 if (!*args[cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01008793 memprintf(err, "'%s' : missing curve suite", args[cur_arg]);
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01008794 return ERR_ALERT | ERR_FATAL;
8795 }
8796 conf->curves = strdup(args[cur_arg + 1]);
8797 return 0;
8798#else
Tim Duesterhus93128532019-11-23 23:45:10 +01008799 memprintf(err, "'%s' : library does not support curve suite", args[cur_arg]);
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01008800 return ERR_ALERT | ERR_FATAL;
8801#endif
8802}
8803static int bind_parse_curves(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8804{
8805 return ssl_bind_parse_curves(args, cur_arg, px, &conf->ssl_conf, err);
8806}
8807
Bertrand Jacquinff13c062016-11-13 16:37:11 +00008808/* parse the "ecdhe" bind keyword keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008809static 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 +02008810{
Willy Tarreau9a1ab082019-05-09 13:26:41 +02008811#if HA_OPENSSL_VERSION_NUMBER < 0x0090800fL
Tim Duesterhus93128532019-11-23 23:45:10 +01008812 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (too old)", args[cur_arg]);
Emeric Brun2b58d042012-09-20 17:10:03 +02008813 return ERR_ALERT | ERR_FATAL;
8814#elif defined(OPENSSL_NO_ECDH)
Tim Duesterhus93128532019-11-23 23:45:10 +01008815 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 +02008816 return ERR_ALERT | ERR_FATAL;
8817#else
8818 if (!*args[cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01008819 memprintf(err, "'%s' : missing named curve", args[cur_arg]);
Emeric Brun2b58d042012-09-20 17:10:03 +02008820 return ERR_ALERT | ERR_FATAL;
8821 }
8822
8823 conf->ecdhe = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008824
8825 return 0;
Emeric Brun2b58d042012-09-20 17:10:03 +02008826#endif
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008827}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008828static int bind_parse_ecdhe(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8829{
8830 return ssl_bind_parse_ecdhe(args, cur_arg, px, &conf->ssl_conf, err);
8831}
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008832
Bertrand Jacquinff13c062016-11-13 16:37:11 +00008833/* parse the "crt-ignore-err" and "ca-ignore-err" bind keywords */
Emeric Brun81c00f02012-09-21 14:31:21 +02008834static int bind_parse_ignore_err(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8835{
8836 int code;
8837 char *p = args[cur_arg + 1];
8838 unsigned long long *ignerr = &conf->crt_ignerr;
8839
8840 if (!*p) {
Tim Duesterhus93128532019-11-23 23:45:10 +01008841 memprintf(err, "'%s' : missing error IDs list", args[cur_arg]);
Emeric Brun81c00f02012-09-21 14:31:21 +02008842 return ERR_ALERT | ERR_FATAL;
8843 }
8844
8845 if (strcmp(args[cur_arg], "ca-ignore-err") == 0)
8846 ignerr = &conf->ca_ignerr;
8847
8848 if (strcmp(p, "all") == 0) {
8849 *ignerr = ~0ULL;
8850 return 0;
8851 }
8852
8853 while (p) {
8854 code = atoi(p);
8855 if ((code <= 0) || (code > 63)) {
Tim Duesterhus93128532019-11-23 23:45:10 +01008856 memprintf(err, "'%s' : ID '%d' out of range (1..63) in error IDs list '%s'",
8857 args[cur_arg], code, args[cur_arg + 1]);
Emeric Brun81c00f02012-09-21 14:31:21 +02008858 return ERR_ALERT | ERR_FATAL;
8859 }
8860 *ignerr |= 1ULL << code;
8861 p = strchr(p, ',');
8862 if (p)
8863 p++;
8864 }
8865
Emeric Brun2cb7ae52012-10-05 14:14:21 +02008866 return 0;
8867}
8868
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008869/* parse tls_method_options "no-xxx" and "force-xxx" */
8870static int parse_tls_method_options(char *arg, struct tls_version_filter *methods, char **err)
Emeric Brun2cb7ae52012-10-05 14:14:21 +02008871{
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008872 uint16_t v;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008873 char *p;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008874 p = strchr(arg, '-');
8875 if (!p)
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008876 goto fail;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008877 p++;
8878 if (!strcmp(p, "sslv3"))
8879 v = CONF_SSLV3;
8880 else if (!strcmp(p, "tlsv10"))
8881 v = CONF_TLSV10;
8882 else if (!strcmp(p, "tlsv11"))
8883 v = CONF_TLSV11;
8884 else if (!strcmp(p, "tlsv12"))
8885 v = CONF_TLSV12;
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +02008886 else if (!strcmp(p, "tlsv13"))
8887 v = CONF_TLSV13;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008888 else
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008889 goto fail;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008890 if (!strncmp(arg, "no-", 3))
8891 methods->flags |= methodVersions[v].flag;
8892 else if (!strncmp(arg, "force-", 6))
8893 methods->min = methods->max = v;
8894 else
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008895 goto fail;
Emeric Brun2d0c4822012-10-02 13:45:20 +02008896 return 0;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008897 fail:
Tim Duesterhus93128532019-11-23 23:45:10 +01008898 memprintf(err, "'%s' : option not implemented", arg);
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008899 return ERR_ALERT | ERR_FATAL;
Emeric Brun2d0c4822012-10-02 13:45:20 +02008900}
8901
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008902static 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 +02008903{
Emmanuel Hocdet43664762017-08-09 18:26:20 +02008904 return parse_tls_method_options(args[cur_arg], &conf->ssl_conf.ssl_methods, err);
Emeric Brun2cb7ae52012-10-05 14:14:21 +02008905}
8906
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008907static 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 +02008908{
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008909 return parse_tls_method_options(args[*cur_arg], &newsrv->ssl_ctx.methods, err);
8910}
8911
8912/* parse tls_method min/max: "ssl-min-ver" and "ssl-max-ver" */
8913static int parse_tls_method_minmax(char **args, int cur_arg, struct tls_version_filter *methods, char **err)
8914{
8915 uint16_t i, v = 0;
8916 char *argv = args[cur_arg + 1];
8917 if (!*argv) {
Tim Duesterhus93128532019-11-23 23:45:10 +01008918 memprintf(err, "'%s' : missing the ssl/tls version", args[cur_arg]);
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008919 return ERR_ALERT | ERR_FATAL;
8920 }
8921 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
8922 if (!strcmp(argv, methodVersions[i].name))
8923 v = i;
8924 if (!v) {
Tim Duesterhus93128532019-11-23 23:45:10 +01008925 memprintf(err, "'%s' : unknown ssl/tls version", args[cur_arg + 1]);
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008926 return ERR_ALERT | ERR_FATAL;
8927 }
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008928 if (!strcmp("ssl-min-ver", args[cur_arg]))
8929 methods->min = v;
8930 else if (!strcmp("ssl-max-ver", args[cur_arg]))
8931 methods->max = v;
8932 else {
Tim Duesterhus93128532019-11-23 23:45:10 +01008933 memprintf(err, "'%s' : option not implemented", args[cur_arg]);
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008934 return ERR_ALERT | ERR_FATAL;
8935 }
Emeric Brun2cb7ae52012-10-05 14:14:21 +02008936 return 0;
Emeric Brun2cb7ae52012-10-05 14:14:21 +02008937}
Emeric Brun2cb7ae52012-10-05 14:14:21 +02008938
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02008939static int ssl_bind_parse_tls_method_minmax(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
8940{
Willy Tarreau9a1ab082019-05-09 13:26:41 +02008941#if (HA_OPENSSL_VERSION_NUMBER < 0x10101000L) && !defined(OPENSSL_IS_BORINGSSL)
Christopher Faulet767a84b2017-11-24 16:50:31 +01008942 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 +02008943#endif
8944 return parse_tls_method_minmax(args, cur_arg, &conf->ssl_methods, err);
8945}
8946
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008947static int bind_parse_tls_method_minmax(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8948{
Emmanuel Hocdet43664762017-08-09 18:26:20 +02008949 return parse_tls_method_minmax(args, cur_arg, &conf->ssl_conf.ssl_methods, err);
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008950}
8951
8952static int srv_parse_tls_method_minmax(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8953{
8954 return parse_tls_method_minmax(args, *cur_arg, &newsrv->ssl_ctx.methods, err);
8955}
8956
Emeric Brun2d0c4822012-10-02 13:45:20 +02008957/* parse the "no-tls-tickets" bind keyword */
Emmanuel Hocdet4608ed92017-01-20 13:06:27 +01008958static 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 +02008959{
Emeric Brun89675492012-10-05 13:48:26 +02008960 conf->ssl_options |= BC_SSL_O_NO_TLS_TICKETS;
Emeric Brun81c00f02012-09-21 14:31:21 +02008961 return 0;
8962}
Emeric Brun2d0c4822012-10-02 13:45:20 +02008963
Olivier Houchardc2aae742017-09-22 18:26:28 +02008964/* parse the "allow-0rtt" bind keyword */
8965static int ssl_bind_parse_allow_0rtt(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
8966{
8967 conf->early_data = 1;
8968 return 0;
8969}
8970
8971static int bind_parse_allow_0rtt(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8972{
Olivier Houchard9679ac92017-10-27 14:58:08 +02008973 conf->ssl_conf.early_data = 1;
Olivier Houchardc2aae742017-09-22 18:26:28 +02008974 return 0;
8975}
8976
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02008977/* parse the "npn" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008978static 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 +02008979{
Bernard Spil13c53f82018-02-15 13:34:58 +01008980#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02008981 char *p1, *p2;
8982
8983 if (!*args[cur_arg + 1]) {
8984 memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[cur_arg]);
8985 return ERR_ALERT | ERR_FATAL;
8986 }
8987
8988 free(conf->npn_str);
8989
Willy Tarreau3724da12016-02-12 17:11:12 +01008990 /* the NPN string is built as a suite of (<len> <name>)*,
8991 * so we reuse each comma to store the next <len> and need
8992 * one more for the end of the string.
8993 */
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02008994 conf->npn_len = strlen(args[cur_arg + 1]) + 1;
Willy Tarreau3724da12016-02-12 17:11:12 +01008995 conf->npn_str = calloc(1, conf->npn_len + 1);
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02008996 memcpy(conf->npn_str + 1, args[cur_arg + 1], conf->npn_len);
8997
8998 /* replace commas with the name length */
8999 p1 = conf->npn_str;
9000 p2 = p1 + 1;
9001 while (1) {
9002 p2 = memchr(p1 + 1, ',', conf->npn_str + conf->npn_len - (p1 + 1));
9003 if (!p2)
9004 p2 = p1 + 1 + strlen(p1 + 1);
9005
9006 if (p2 - (p1 + 1) > 255) {
9007 *p2 = '\0';
9008 memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
9009 return ERR_ALERT | ERR_FATAL;
9010 }
9011
9012 *p1 = p2 - (p1 + 1);
9013 p1 = p2;
9014
9015 if (!*p2)
9016 break;
9017
9018 *(p2++) = '\0';
9019 }
9020 return 0;
9021#else
Tim Duesterhus93128532019-11-23 23:45:10 +01009022 memprintf(err, "'%s' : library does not support TLS NPN extension", args[cur_arg]);
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02009023 return ERR_ALERT | ERR_FATAL;
9024#endif
9025}
9026
Emmanuel Hocdet98263292016-12-29 18:26:15 +01009027static int bind_parse_npn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
9028{
9029 return ssl_bind_parse_npn(args, cur_arg, px, &conf->ssl_conf, err);
9030}
9031
Willy Tarreauab861d32013-04-02 02:30:41 +02009032/* parse the "alpn" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01009033static 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 +02009034{
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01009035#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02009036 char *p1, *p2;
9037
9038 if (!*args[cur_arg + 1]) {
9039 memprintf(err, "'%s' : missing the comma-delimited ALPN protocol suite", args[cur_arg]);
9040 return ERR_ALERT | ERR_FATAL;
9041 }
9042
9043 free(conf->alpn_str);
9044
Marcoen Hirschbergbef60912016-02-12 17:05:24 +01009045 /* the ALPN string is built as a suite of (<len> <name>)*,
9046 * so we reuse each comma to store the next <len> and need
9047 * one more for the end of the string.
9048 */
Willy Tarreauab861d32013-04-02 02:30:41 +02009049 conf->alpn_len = strlen(args[cur_arg + 1]) + 1;
Marcoen Hirschbergbef60912016-02-12 17:05:24 +01009050 conf->alpn_str = calloc(1, conf->alpn_len + 1);
Willy Tarreauab861d32013-04-02 02:30:41 +02009051 memcpy(conf->alpn_str + 1, args[cur_arg + 1], conf->alpn_len);
9052
9053 /* replace commas with the name length */
9054 p1 = conf->alpn_str;
9055 p2 = p1 + 1;
9056 while (1) {
9057 p2 = memchr(p1 + 1, ',', conf->alpn_str + conf->alpn_len - (p1 + 1));
9058 if (!p2)
9059 p2 = p1 + 1 + strlen(p1 + 1);
9060
9061 if (p2 - (p1 + 1) > 255) {
9062 *p2 = '\0';
9063 memprintf(err, "'%s' : ALPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
9064 return ERR_ALERT | ERR_FATAL;
9065 }
9066
9067 *p1 = p2 - (p1 + 1);
9068 p1 = p2;
9069
9070 if (!*p2)
9071 break;
9072
9073 *(p2++) = '\0';
9074 }
9075 return 0;
9076#else
Tim Duesterhus93128532019-11-23 23:45:10 +01009077 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[cur_arg]);
Willy Tarreauab861d32013-04-02 02:30:41 +02009078 return ERR_ALERT | ERR_FATAL;
9079#endif
9080}
9081
Emmanuel Hocdet98263292016-12-29 18:26:15 +01009082static int bind_parse_alpn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
9083{
9084 return ssl_bind_parse_alpn(args, cur_arg, px, &conf->ssl_conf, err);
9085}
9086
Willy Tarreau79eeafa2012-09-14 07:53:05 +02009087/* parse the "ssl" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02009088static 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 +02009089{
Willy Tarreau71a8c7c2016-12-21 22:04:54 +01009090 conf->xprt = &ssl_sock;
Willy Tarreau4348fad2012-09-20 16:48:07 +02009091 conf->is_ssl = 1;
Emeric Brun76d88952012-10-05 15:47:31 +02009092
Emmanuel Hocdet98263292016-12-29 18:26:15 +01009093 if (global_ssl.listen_default_ciphers && !conf->ssl_conf.ciphers)
9094 conf->ssl_conf.ciphers = strdup(global_ssl.listen_default_ciphers);
Emmanuel Hocdet839af572019-05-14 16:27:35 +02009095#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009096 if (global_ssl.listen_default_ciphersuites && !conf->ssl_conf.ciphersuites)
9097 conf->ssl_conf.ciphersuites = strdup(global_ssl.listen_default_ciphersuites);
9098#endif
Emmanuel Hocdet4608ed92017-01-20 13:06:27 +01009099 conf->ssl_options |= global_ssl.listen_default_ssloptions;
Emmanuel Hocdet43664762017-08-09 18:26:20 +02009100 conf->ssl_conf.ssl_methods.flags |= global_ssl.listen_default_sslmethods.flags;
9101 if (!conf->ssl_conf.ssl_methods.min)
9102 conf->ssl_conf.ssl_methods.min = global_ssl.listen_default_sslmethods.min;
9103 if (!conf->ssl_conf.ssl_methods.max)
9104 conf->ssl_conf.ssl_methods.max = global_ssl.listen_default_sslmethods.max;
Emeric Brun76d88952012-10-05 15:47:31 +02009105
Willy Tarreau79eeafa2012-09-14 07:53:05 +02009106 return 0;
9107}
9108
Lukas Tribus53ae85c2017-05-04 15:45:40 +00009109/* parse the "prefer-client-ciphers" bind keyword */
9110static int bind_parse_pcc(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
9111{
9112 conf->ssl_options |= BC_SSL_O_PREF_CLIE_CIPH;
9113 return 0;
9114}
9115
Christopher Faulet31af49d2015-06-09 17:29:50 +02009116/* parse the "generate-certificates" bind keyword */
9117static int bind_parse_generate_certs(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
9118{
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01009119#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Christopher Faulet31af49d2015-06-09 17:29:50 +02009120 conf->generate_certs = 1;
9121#else
9122 memprintf(err, "%sthis version of openssl cannot generate SSL certificates.\n",
9123 err && *err ? *err : "");
9124#endif
9125 return 0;
9126}
9127
Emmanuel Hocdet65623372013-01-24 17:17:15 +01009128/* parse the "strict-sni" bind keyword */
9129static int bind_parse_strict_sni(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
9130{
9131 conf->strict_sni = 1;
9132 return 0;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009133}
9134
9135/* parse the "tls-ticket-keys" bind keyword */
9136static int bind_parse_tls_ticket_keys(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
9137{
9138#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
Christopher Faulete566f3d2019-10-21 09:55:49 +02009139 FILE *f = NULL;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009140 int i = 0;
9141 char thisline[LINESIZE];
Christopher Faulete566f3d2019-10-21 09:55:49 +02009142 struct tls_keys_ref *keys_ref = NULL;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009143
9144 if (!*args[cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009145 memprintf(err, "'%s' : missing TLS ticket keys file path", args[cur_arg]);
Christopher Faulete566f3d2019-10-21 09:55:49 +02009146 goto fail;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009147 }
9148
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02009149 keys_ref = tlskeys_ref_lookup(args[cur_arg + 1]);
Willy Tarreau17b4aa12018-07-17 10:05:32 +02009150 if (keys_ref) {
9151 keys_ref->refcount++;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02009152 conf->keys_ref = keys_ref;
9153 return 0;
9154 }
9155
Christopher Faulete566f3d2019-10-21 09:55:49 +02009156 keys_ref = calloc(1, sizeof(*keys_ref));
Emeric Brun09852f72019-01-10 10:51:13 +01009157 if (!keys_ref) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009158 memprintf(err, "'%s' : allocation error", args[cur_arg+1]);
Christopher Faulete566f3d2019-10-21 09:55:49 +02009159 goto fail;
Emeric Brun09852f72019-01-10 10:51:13 +01009160 }
9161
Emeric Brun9e754772019-01-10 17:51:55 +01009162 keys_ref->tlskeys = malloc(TLS_TICKETS_NO * sizeof(union tls_sess_key));
Emeric Brun09852f72019-01-10 10:51:13 +01009163 if (!keys_ref->tlskeys) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009164 memprintf(err, "'%s' : allocation error", args[cur_arg+1]);
Christopher Faulete566f3d2019-10-21 09:55:49 +02009165 goto fail;
Emeric Brun09852f72019-01-10 10:51:13 +01009166 }
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009167
9168 if ((f = fopen(args[cur_arg + 1], "r")) == NULL) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009169 memprintf(err, "'%s' : unable to load ssl tickets keys file", args[cur_arg+1]);
Christopher Faulete566f3d2019-10-21 09:55:49 +02009170 goto fail;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009171 }
9172
Nenad Merdanovic146defa2015-05-09 08:46:00 +02009173 keys_ref->filename = strdup(args[cur_arg + 1]);
Emeric Brun09852f72019-01-10 10:51:13 +01009174 if (!keys_ref->filename) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009175 memprintf(err, "'%s' : allocation error", args[cur_arg+1]);
Christopher Faulete566f3d2019-10-21 09:55:49 +02009176 goto fail;
Emeric Brun09852f72019-01-10 10:51:13 +01009177 }
Nenad Merdanovic146defa2015-05-09 08:46:00 +02009178
Emeric Brun9e754772019-01-10 17:51:55 +01009179 keys_ref->key_size_bits = 0;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009180 while (fgets(thisline, sizeof(thisline), f) != NULL) {
9181 int len = strlen(thisline);
Emeric Brun9e754772019-01-10 17:51:55 +01009182 int dec_size;
9183
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009184 /* Strip newline characters from the end */
9185 if(thisline[len - 1] == '\n')
9186 thisline[--len] = 0;
9187
9188 if(thisline[len - 1] == '\r')
9189 thisline[--len] = 0;
9190
Emeric Brun9e754772019-01-10 17:51:55 +01009191 dec_size = base64dec(thisline, len, (char *) (keys_ref->tlskeys + i % TLS_TICKETS_NO), sizeof(union tls_sess_key));
9192 if (dec_size < 0) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009193 memprintf(err, "'%s' : unable to decode base64 key on line %d", args[cur_arg+1], i + 1);
Christopher Faulete566f3d2019-10-21 09:55:49 +02009194 goto fail;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009195 }
Emeric Brun9e754772019-01-10 17:51:55 +01009196 else if (!keys_ref->key_size_bits && (dec_size == sizeof(struct tls_sess_key_128))) {
9197 keys_ref->key_size_bits = 128;
9198 }
9199 else if (!keys_ref->key_size_bits && (dec_size == sizeof(struct tls_sess_key_256))) {
9200 keys_ref->key_size_bits = 256;
9201 }
9202 else if (((dec_size != sizeof(struct tls_sess_key_128)) && (dec_size != sizeof(struct tls_sess_key_256)))
9203 || ((dec_size == sizeof(struct tls_sess_key_128) && (keys_ref->key_size_bits != 128)))
9204 || ((dec_size == sizeof(struct tls_sess_key_256) && (keys_ref->key_size_bits != 256)))) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009205 memprintf(err, "'%s' : wrong sized key on line %d", args[cur_arg+1], i + 1);
Christopher Faulete566f3d2019-10-21 09:55:49 +02009206 goto fail;
Emeric Brun9e754772019-01-10 17:51:55 +01009207 }
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009208 i++;
9209 }
9210
9211 if (i < TLS_TICKETS_NO) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009212 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 +02009213 goto fail;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009214 }
9215
9216 fclose(f);
9217
9218 /* Use penultimate key for encryption, handle when TLS_TICKETS_NO = 1 */
Nenad Merdanovic17891152016-03-25 22:16:57 +01009219 i -= 2;
9220 keys_ref->tls_ticket_enc_index = i < 0 ? 0 : i % TLS_TICKETS_NO;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02009221 keys_ref->unique_id = -1;
Willy Tarreau17b4aa12018-07-17 10:05:32 +02009222 keys_ref->refcount = 1;
Christopher Faulet16f45c82018-02-16 11:23:49 +01009223 HA_RWLOCK_INIT(&keys_ref->lock);
Nenad Merdanovic146defa2015-05-09 08:46:00 +02009224 conf->keys_ref = keys_ref;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009225
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02009226 LIST_ADD(&tlskeys_reference, &keys_ref->list);
9227
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009228 return 0;
Christopher Faulete566f3d2019-10-21 09:55:49 +02009229
9230 fail:
9231 if (f)
9232 fclose(f);
9233 if (keys_ref) {
9234 free(keys_ref->filename);
9235 free(keys_ref->tlskeys);
9236 free(keys_ref);
9237 }
9238 return ERR_ALERT | ERR_FATAL;
9239
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009240#else
Tim Duesterhus93128532019-11-23 23:45:10 +01009241 memprintf(err, "'%s' : TLS ticket callback extension not supported", args[cur_arg]);
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009242 return ERR_ALERT | ERR_FATAL;
9243#endif /* SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB */
Emmanuel Hocdet65623372013-01-24 17:17:15 +01009244}
9245
Emeric Brund94b3fe2012-09-20 18:23:56 +02009246/* parse the "verify" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01009247static 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 +02009248{
9249 if (!*args[cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009250 memprintf(err, "'%s' : missing verify method", args[cur_arg]);
Emeric Brund94b3fe2012-09-20 18:23:56 +02009251 return ERR_ALERT | ERR_FATAL;
9252 }
9253
9254 if (strcmp(args[cur_arg + 1], "none") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01009255 conf->verify = SSL_SOCK_VERIFY_NONE;
Emeric Brund94b3fe2012-09-20 18:23:56 +02009256 else if (strcmp(args[cur_arg + 1], "optional") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01009257 conf->verify = SSL_SOCK_VERIFY_OPTIONAL;
Emeric Brund94b3fe2012-09-20 18:23:56 +02009258 else if (strcmp(args[cur_arg + 1], "required") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01009259 conf->verify = SSL_SOCK_VERIFY_REQUIRED;
Emeric Brund94b3fe2012-09-20 18:23:56 +02009260 else {
Tim Duesterhus93128532019-11-23 23:45:10 +01009261 memprintf(err, "'%s' : unknown verify method '%s', only 'none', 'optional', and 'required' are supported\n",
9262 args[cur_arg], args[cur_arg + 1]);
Emeric Brund94b3fe2012-09-20 18:23:56 +02009263 return ERR_ALERT | ERR_FATAL;
9264 }
9265
9266 return 0;
9267}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01009268static int bind_parse_verify(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
9269{
9270 return ssl_bind_parse_verify(args, cur_arg, px, &conf->ssl_conf, err);
9271}
Emeric Brund94b3fe2012-09-20 18:23:56 +02009272
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02009273/* parse the "no-ca-names" bind keyword */
9274static int ssl_bind_parse_no_ca_names(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
9275{
9276 conf->no_ca_names = 1;
9277 return 0;
9278}
9279static int bind_parse_no_ca_names(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
9280{
9281 return ssl_bind_parse_no_ca_names(args, cur_arg, px, &conf->ssl_conf, err);
9282}
9283
Willy Tarreau92faadf2012-10-10 23:04:25 +02009284/************** "server" keywords ****************/
9285
Olivier Houchardc7566002018-11-20 23:33:50 +01009286/* parse the "npn" bind keyword */
9287static int srv_parse_npn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9288{
9289#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
9290 char *p1, *p2;
9291
9292 if (!*args[*cur_arg + 1]) {
9293 memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[*cur_arg]);
9294 return ERR_ALERT | ERR_FATAL;
9295 }
9296
9297 free(newsrv->ssl_ctx.npn_str);
9298
9299 /* the NPN string is built as a suite of (<len> <name>)*,
9300 * so we reuse each comma to store the next <len> and need
9301 * one more for the end of the string.
9302 */
9303 newsrv->ssl_ctx.npn_len = strlen(args[*cur_arg + 1]) + 1;
9304 newsrv->ssl_ctx.npn_str = calloc(1, newsrv->ssl_ctx.npn_len + 1);
9305 memcpy(newsrv->ssl_ctx.npn_str + 1, args[*cur_arg + 1],
9306 newsrv->ssl_ctx.npn_len);
9307
9308 /* replace commas with the name length */
9309 p1 = newsrv->ssl_ctx.npn_str;
9310 p2 = p1 + 1;
9311 while (1) {
9312 p2 = memchr(p1 + 1, ',', newsrv->ssl_ctx.npn_str +
9313 newsrv->ssl_ctx.npn_len - (p1 + 1));
9314 if (!p2)
9315 p2 = p1 + 1 + strlen(p1 + 1);
9316
9317 if (p2 - (p1 + 1) > 255) {
9318 *p2 = '\0';
9319 memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[*cur_arg], p1 + 1);
9320 return ERR_ALERT | ERR_FATAL;
9321 }
9322
9323 *p1 = p2 - (p1 + 1);
9324 p1 = p2;
9325
9326 if (!*p2)
9327 break;
9328
9329 *(p2++) = '\0';
9330 }
9331 return 0;
9332#else
Tim Duesterhus93128532019-11-23 23:45:10 +01009333 memprintf(err, "'%s' : library does not support TLS NPN extension", args[*cur_arg]);
Olivier Houchardc7566002018-11-20 23:33:50 +01009334 return ERR_ALERT | ERR_FATAL;
9335#endif
9336}
9337
Olivier Houchard92150142018-12-21 19:47:01 +01009338/* parse the "alpn" or the "check-alpn" server keyword */
Olivier Houchardc7566002018-11-20 23:33:50 +01009339static int srv_parse_alpn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9340{
9341#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
9342 char *p1, *p2;
Olivier Houchard92150142018-12-21 19:47:01 +01009343 char **alpn_str;
9344 int *alpn_len;
Olivier Houchardc7566002018-11-20 23:33:50 +01009345
Olivier Houchard92150142018-12-21 19:47:01 +01009346 if (*args[*cur_arg] == 'c') {
9347 alpn_str = &newsrv->check.alpn_str;
9348 alpn_len = &newsrv->check.alpn_len;
9349 } else {
9350 alpn_str = &newsrv->ssl_ctx.alpn_str;
9351 alpn_len = &newsrv->ssl_ctx.alpn_len;
9352
9353 }
Olivier Houchardc7566002018-11-20 23:33:50 +01009354 if (!*args[*cur_arg + 1]) {
9355 memprintf(err, "'%s' : missing the comma-delimited ALPN protocol suite", args[*cur_arg]);
9356 return ERR_ALERT | ERR_FATAL;
9357 }
9358
Olivier Houchard92150142018-12-21 19:47:01 +01009359 free(*alpn_str);
Olivier Houchardc7566002018-11-20 23:33:50 +01009360
9361 /* the ALPN string is built as a suite of (<len> <name>)*,
9362 * so we reuse each comma to store the next <len> and need
9363 * one more for the end of the string.
9364 */
Olivier Houchard92150142018-12-21 19:47:01 +01009365 *alpn_len = strlen(args[*cur_arg + 1]) + 1;
9366 *alpn_str = calloc(1, *alpn_len + 1);
9367 memcpy(*alpn_str + 1, args[*cur_arg + 1], *alpn_len);
Olivier Houchardc7566002018-11-20 23:33:50 +01009368
9369 /* replace commas with the name length */
Olivier Houchard92150142018-12-21 19:47:01 +01009370 p1 = *alpn_str;
Olivier Houchardc7566002018-11-20 23:33:50 +01009371 p2 = p1 + 1;
9372 while (1) {
Olivier Houchard92150142018-12-21 19:47:01 +01009373 p2 = memchr(p1 + 1, ',', *alpn_str + *alpn_len - (p1 + 1));
Olivier Houchardc7566002018-11-20 23:33:50 +01009374 if (!p2)
9375 p2 = p1 + 1 + strlen(p1 + 1);
9376
9377 if (p2 - (p1 + 1) > 255) {
9378 *p2 = '\0';
9379 memprintf(err, "'%s' : ALPN protocol name too long : '%s'", args[*cur_arg], p1 + 1);
9380 return ERR_ALERT | ERR_FATAL;
9381 }
9382
9383 *p1 = p2 - (p1 + 1);
9384 p1 = p2;
9385
9386 if (!*p2)
9387 break;
9388
9389 *(p2++) = '\0';
9390 }
9391 return 0;
9392#else
Tim Duesterhus93128532019-11-23 23:45:10 +01009393 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[*cur_arg]);
Olivier Houchardc7566002018-11-20 23:33:50 +01009394 return ERR_ALERT | ERR_FATAL;
9395#endif
9396}
9397
Emeric Brunef42d922012-10-11 16:11:36 +02009398/* parse the "ca-file" server keyword */
9399static int srv_parse_ca_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9400{
9401 if (!*args[*cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009402 memprintf(err, "'%s' : missing CAfile path", args[*cur_arg]);
Emeric Brunef42d922012-10-11 16:11:36 +02009403 return ERR_ALERT | ERR_FATAL;
9404 }
9405
Willy Tarreauef934602016-12-22 23:12:01 +01009406 if ((*args[*cur_arg + 1] != '/') && global_ssl.ca_base)
9407 memprintf(&newsrv->ssl_ctx.ca_file, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02009408 else
9409 memprintf(&newsrv->ssl_ctx.ca_file, "%s", args[*cur_arg + 1]);
9410
Emmanuel Hocdetd4f9a602019-10-24 11:32:47 +02009411 if (!ssl_store_load_locations_file(newsrv->ssl_ctx.ca_file)) {
9412 memprintf(err, "'%s' : unable to load %s", args[*cur_arg], newsrv->ssl_ctx.ca_file);
9413 return ERR_ALERT | ERR_FATAL;
9414 }
Emeric Brunef42d922012-10-11 16:11:36 +02009415 return 0;
9416}
9417
Olivier Houchard9130a962017-10-17 17:33:43 +02009418/* parse the "check-sni" server keyword */
9419static int srv_parse_check_sni(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9420{
9421 if (!*args[*cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009422 memprintf(err, "'%s' : missing SNI", args[*cur_arg]);
Olivier Houchard9130a962017-10-17 17:33:43 +02009423 return ERR_ALERT | ERR_FATAL;
9424 }
9425
9426 newsrv->check.sni = strdup(args[*cur_arg + 1]);
9427 if (!newsrv->check.sni) {
9428 memprintf(err, "'%s' : failed to allocate memory", args[*cur_arg]);
9429 return ERR_ALERT | ERR_FATAL;
9430 }
9431 return 0;
9432
9433}
9434
Willy Tarreau92faadf2012-10-10 23:04:25 +02009435/* parse the "check-ssl" server keyword */
9436static int srv_parse_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9437{
9438 newsrv->check.use_ssl = 1;
Willy Tarreauef934602016-12-22 23:12:01 +01009439 if (global_ssl.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
9440 newsrv->ssl_ctx.ciphers = strdup(global_ssl.connect_default_ciphers);
Emmanuel Hocdet839af572019-05-14 16:27:35 +02009441#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009442 if (global_ssl.connect_default_ciphersuites && !newsrv->ssl_ctx.ciphersuites)
9443 newsrv->ssl_ctx.ciphersuites = strdup(global_ssl.connect_default_ciphersuites);
9444#endif
Willy Tarreauef934602016-12-22 23:12:01 +01009445 newsrv->ssl_ctx.options |= global_ssl.connect_default_ssloptions;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02009446 newsrv->ssl_ctx.methods.flags |= global_ssl.connect_default_sslmethods.flags;
9447 if (!newsrv->ssl_ctx.methods.min)
9448 newsrv->ssl_ctx.methods.min = global_ssl.connect_default_sslmethods.min;
9449 if (!newsrv->ssl_ctx.methods.max)
9450 newsrv->ssl_ctx.methods.max = global_ssl.connect_default_sslmethods.max;
9451
Willy Tarreau92faadf2012-10-10 23:04:25 +02009452 return 0;
9453}
9454
9455/* parse the "ciphers" server keyword */
9456static int srv_parse_ciphers(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9457{
9458 if (!*args[*cur_arg + 1]) {
9459 memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
9460 return ERR_ALERT | ERR_FATAL;
9461 }
9462
9463 free(newsrv->ssl_ctx.ciphers);
9464 newsrv->ssl_ctx.ciphers = strdup(args[*cur_arg + 1]);
9465 return 0;
9466}
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009467
Emmanuel Hocdet839af572019-05-14 16:27:35 +02009468#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009469/* parse the "ciphersuites" server keyword */
9470static int srv_parse_ciphersuites(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9471{
9472 if (!*args[*cur_arg + 1]) {
9473 memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
9474 return ERR_ALERT | ERR_FATAL;
9475 }
9476
9477 free(newsrv->ssl_ctx.ciphersuites);
9478 newsrv->ssl_ctx.ciphersuites = strdup(args[*cur_arg + 1]);
9479 return 0;
9480}
9481#endif
Willy Tarreau92faadf2012-10-10 23:04:25 +02009482
Emeric Brunef42d922012-10-11 16:11:36 +02009483/* parse the "crl-file" server keyword */
9484static int srv_parse_crl_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9485{
9486#ifndef X509_V_FLAG_CRL_CHECK
Tim Duesterhus93128532019-11-23 23:45:10 +01009487 memprintf(err, "'%s' : library does not support CRL verify", args[*cur_arg]);
Emeric Brunef42d922012-10-11 16:11:36 +02009488 return ERR_ALERT | ERR_FATAL;
9489#else
9490 if (!*args[*cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009491 memprintf(err, "'%s' : missing CRLfile path", args[*cur_arg]);
Emeric Brunef42d922012-10-11 16:11:36 +02009492 return ERR_ALERT | ERR_FATAL;
9493 }
9494
Willy Tarreauef934602016-12-22 23:12:01 +01009495 if ((*args[*cur_arg + 1] != '/') && global_ssl.ca_base)
9496 memprintf(&newsrv->ssl_ctx.crl_file, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02009497 else
9498 memprintf(&newsrv->ssl_ctx.crl_file, "%s", args[*cur_arg + 1]);
9499
Emmanuel Hocdetb270e812019-11-21 19:09:31 +01009500 if (!ssl_store_load_locations_file(newsrv->ssl_ctx.crl_file)) {
9501 memprintf(err, "'%s' : unable to load %s", args[*cur_arg], newsrv->ssl_ctx.crl_file);
9502 return ERR_ALERT | ERR_FATAL;
9503 }
Emeric Brunef42d922012-10-11 16:11:36 +02009504 return 0;
9505#endif
9506}
9507
Emeric Bruna7aa3092012-10-26 12:58:00 +02009508/* parse the "crt" server keyword */
9509static int srv_parse_crt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9510{
9511 if (!*args[*cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009512 memprintf(err, "'%s' : missing certificate file path", args[*cur_arg]);
Emeric Bruna7aa3092012-10-26 12:58:00 +02009513 return ERR_ALERT | ERR_FATAL;
9514 }
9515
Willy Tarreauef934602016-12-22 23:12:01 +01009516 if ((*args[*cur_arg + 1] != '/') && global_ssl.crt_base)
Christopher Fauletff3a41e2017-11-23 09:13:32 +01009517 memprintf(&newsrv->ssl_ctx.client_crt, "%s/%s", global_ssl.crt_base, args[*cur_arg + 1]);
Emeric Bruna7aa3092012-10-26 12:58:00 +02009518 else
9519 memprintf(&newsrv->ssl_ctx.client_crt, "%s", args[*cur_arg + 1]);
9520
9521 return 0;
9522}
Emeric Brunef42d922012-10-11 16:11:36 +02009523
Frédéric Lécaille340ae602017-03-13 10:38:04 +01009524/* parse the "no-check-ssl" server keyword */
9525static int srv_parse_no_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9526{
9527 newsrv->check.use_ssl = 0;
9528 free(newsrv->ssl_ctx.ciphers);
9529 newsrv->ssl_ctx.ciphers = NULL;
9530 newsrv->ssl_ctx.options &= ~global_ssl.connect_default_ssloptions;
9531 return 0;
9532}
9533
Frédéric Lécaillee892c4c2017-03-13 12:08:01 +01009534/* parse the "no-send-proxy-v2-ssl" server keyword */
9535static int srv_parse_no_send_proxy_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9536{
9537 newsrv->pp_opts &= ~SRV_PP_V2;
9538 newsrv->pp_opts &= ~SRV_PP_V2_SSL;
9539 return 0;
9540}
9541
9542/* parse the "no-send-proxy-v2-ssl-cn" server keyword */
9543static int srv_parse_no_send_proxy_cn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9544{
9545 newsrv->pp_opts &= ~SRV_PP_V2;
9546 newsrv->pp_opts &= ~SRV_PP_V2_SSL;
9547 newsrv->pp_opts &= ~SRV_PP_V2_SSL_CN;
9548 return 0;
9549}
9550
Frédéric Lécaillee381d762017-03-13 11:54:17 +01009551/* parse the "no-ssl" server keyword */
9552static int srv_parse_no_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9553{
9554 newsrv->use_ssl = 0;
9555 free(newsrv->ssl_ctx.ciphers);
9556 newsrv->ssl_ctx.ciphers = NULL;
9557 return 0;
9558}
9559
Olivier Houchard522eea72017-11-03 16:27:47 +01009560/* parse the "allow-0rtt" server keyword */
9561static int srv_parse_allow_0rtt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9562{
9563 newsrv->ssl_ctx.options |= SRV_SSL_O_EARLY_DATA;
9564 return 0;
9565}
9566
Willy Tarreau2a3fb1c2015-02-05 16:47:07 +01009567/* parse the "no-ssl-reuse" server keyword */
9568static int srv_parse_no_ssl_reuse(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9569{
9570 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_REUSE;
9571 return 0;
9572}
9573
Emeric Brunf9c5c472012-10-11 15:28:34 +02009574/* parse the "no-tls-tickets" server keyword */
9575static int srv_parse_no_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9576{
9577 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLS_TICKETS;
9578 return 0;
9579}
David Safb76832014-05-08 23:42:08 -04009580/* parse the "send-proxy-v2-ssl" server keyword */
9581static int srv_parse_send_proxy_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9582{
9583 newsrv->pp_opts |= SRV_PP_V2;
9584 newsrv->pp_opts |= SRV_PP_V2_SSL;
9585 return 0;
9586}
9587
9588/* parse the "send-proxy-v2-ssl-cn" server keyword */
9589static int srv_parse_send_proxy_cn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9590{
9591 newsrv->pp_opts |= SRV_PP_V2;
9592 newsrv->pp_opts |= SRV_PP_V2_SSL;
9593 newsrv->pp_opts |= SRV_PP_V2_SSL_CN;
9594 return 0;
9595}
Emeric Brunf9c5c472012-10-11 15:28:34 +02009596
Willy Tarreau732eac42015-07-09 11:40:25 +02009597/* parse the "sni" server keyword */
9598static int srv_parse_sni(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9599{
9600#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
9601 memprintf(err, "'%s' : the current SSL library doesn't support the SNI TLS extension", args[*cur_arg]);
9602 return ERR_ALERT | ERR_FATAL;
9603#else
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01009604 char *arg;
Willy Tarreau732eac42015-07-09 11:40:25 +02009605
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01009606 arg = args[*cur_arg + 1];
9607 if (!*arg) {
Willy Tarreau732eac42015-07-09 11:40:25 +02009608 memprintf(err, "'%s' : missing sni expression", args[*cur_arg]);
9609 return ERR_ALERT | ERR_FATAL;
9610 }
9611
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01009612 free(newsrv->sni_expr);
9613 newsrv->sni_expr = strdup(arg);
Willy Tarreau732eac42015-07-09 11:40:25 +02009614
Willy Tarreau732eac42015-07-09 11:40:25 +02009615 return 0;
9616#endif
9617}
9618
Willy Tarreau92faadf2012-10-10 23:04:25 +02009619/* parse the "ssl" server keyword */
9620static int srv_parse_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9621{
9622 newsrv->use_ssl = 1;
Willy Tarreauef934602016-12-22 23:12:01 +01009623 if (global_ssl.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
9624 newsrv->ssl_ctx.ciphers = strdup(global_ssl.connect_default_ciphers);
Emmanuel Hocdet839af572019-05-14 16:27:35 +02009625#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009626 if (global_ssl.connect_default_ciphersuites && !newsrv->ssl_ctx.ciphersuites)
9627 newsrv->ssl_ctx.ciphersuites = strdup(global_ssl.connect_default_ciphersuites);
9628#endif
Willy Tarreau92faadf2012-10-10 23:04:25 +02009629 return 0;
9630}
9631
Frédéric Lécaille2cfcdbe2017-03-13 11:32:20 +01009632/* parse the "ssl-reuse" server keyword */
9633static int srv_parse_ssl_reuse(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9634{
9635 newsrv->ssl_ctx.options &= ~SRV_SSL_O_NO_REUSE;
9636 return 0;
9637}
9638
Frédéric Lécaille2cfcdbe2017-03-13 11:32:20 +01009639/* parse the "tls-tickets" server keyword */
9640static int srv_parse_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9641{
9642 newsrv->ssl_ctx.options &= ~SRV_SSL_O_NO_TLS_TICKETS;
9643 return 0;
9644}
9645
Emeric Brunef42d922012-10-11 16:11:36 +02009646/* parse the "verify" server keyword */
9647static int srv_parse_verify(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9648{
9649 if (!*args[*cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009650 memprintf(err, "'%s' : missing verify method", args[*cur_arg]);
Emeric Brunef42d922012-10-11 16:11:36 +02009651 return ERR_ALERT | ERR_FATAL;
9652 }
9653
9654 if (strcmp(args[*cur_arg + 1], "none") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01009655 newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_NONE;
Emeric Brunef42d922012-10-11 16:11:36 +02009656 else if (strcmp(args[*cur_arg + 1], "required") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01009657 newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_REQUIRED;
Emeric Brunef42d922012-10-11 16:11:36 +02009658 else {
Tim Duesterhus93128532019-11-23 23:45:10 +01009659 memprintf(err, "'%s' : unknown verify method '%s', only 'none' and 'required' are supported\n",
9660 args[*cur_arg], args[*cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02009661 return ERR_ALERT | ERR_FATAL;
9662 }
9663
Evan Broderbe554312013-06-27 00:05:25 -07009664 return 0;
9665}
9666
9667/* parse the "verifyhost" server keyword */
9668static int srv_parse_verifyhost(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9669{
9670 if (!*args[*cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009671 memprintf(err, "'%s' : missing hostname to verify against", args[*cur_arg]);
Evan Broderbe554312013-06-27 00:05:25 -07009672 return ERR_ALERT | ERR_FATAL;
9673 }
9674
Frédéric Lécaille273f3212017-03-13 15:52:01 +01009675 free(newsrv->ssl_ctx.verify_host);
Evan Broderbe554312013-06-27 00:05:25 -07009676 newsrv->ssl_ctx.verify_host = strdup(args[*cur_arg + 1]);
9677
Emeric Brunef42d922012-10-11 16:11:36 +02009678 return 0;
9679}
9680
Emeric Brun2c86cbf2014-10-30 15:56:50 +01009681/* parse the "ssl-default-bind-options" keyword in global section */
9682static int ssl_parse_default_bind_options(char **args, int section_type, struct proxy *curpx,
9683 struct proxy *defpx, const char *file, int line,
9684 char **err) {
9685 int i = 1;
9686
9687 if (*(args[i]) == 0) {
9688 memprintf(err, "global statement '%s' expects an option as an argument.", args[0]);
9689 return -1;
9690 }
9691 while (*(args[i])) {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02009692 if (!strcmp(args[i], "no-tls-tickets"))
Willy Tarreauef934602016-12-22 23:12:01 +01009693 global_ssl.listen_default_ssloptions |= BC_SSL_O_NO_TLS_TICKETS;
Lukas Tribus53ae85c2017-05-04 15:45:40 +00009694 else if (!strcmp(args[i], "prefer-client-ciphers"))
9695 global_ssl.listen_default_ssloptions |= BC_SSL_O_PREF_CLIE_CIPH;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02009696 else if (!strcmp(args[i], "ssl-min-ver") || !strcmp(args[i], "ssl-max-ver")) {
9697 if (!parse_tls_method_minmax(args, i, &global_ssl.listen_default_sslmethods, err))
9698 i++;
9699 else {
9700 memprintf(err, "%s on global statement '%s'.", *err, args[0]);
9701 return -1;
9702 }
9703 }
9704 else if (parse_tls_method_options(args[i], &global_ssl.listen_default_sslmethods, err)) {
Emeric Brun2c86cbf2014-10-30 15:56:50 +01009705 memprintf(err, "unknown option '%s' on global statement '%s'.", args[i], args[0]);
9706 return -1;
9707 }
9708 i++;
9709 }
9710 return 0;
9711}
9712
9713/* parse the "ssl-default-server-options" keyword in global section */
9714static int ssl_parse_default_server_options(char **args, int section_type, struct proxy *curpx,
9715 struct proxy *defpx, const char *file, int line,
9716 char **err) {
9717 int i = 1;
9718
9719 if (*(args[i]) == 0) {
9720 memprintf(err, "global statement '%s' expects an option as an argument.", args[0]);
9721 return -1;
9722 }
9723 while (*(args[i])) {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02009724 if (!strcmp(args[i], "no-tls-tickets"))
Willy Tarreauef934602016-12-22 23:12:01 +01009725 global_ssl.connect_default_ssloptions |= SRV_SSL_O_NO_TLS_TICKETS;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02009726 else if (!strcmp(args[i], "ssl-min-ver") || !strcmp(args[i], "ssl-max-ver")) {
9727 if (!parse_tls_method_minmax(args, i, &global_ssl.connect_default_sslmethods, err))
9728 i++;
9729 else {
9730 memprintf(err, "%s on global statement '%s'.", *err, args[0]);
9731 return -1;
9732 }
9733 }
9734 else if (parse_tls_method_options(args[i], &global_ssl.connect_default_sslmethods, err)) {
Emeric Brun2c86cbf2014-10-30 15:56:50 +01009735 memprintf(err, "unknown option '%s' on global statement '%s'.", args[i], args[0]);
9736 return -1;
9737 }
9738 i++;
9739 }
9740 return 0;
9741}
9742
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01009743/* parse the "ca-base" / "crt-base" keywords in global section.
9744 * Returns <0 on alert, >0 on warning, 0 on success.
9745 */
9746static int ssl_parse_global_ca_crt_base(char **args, int section_type, struct proxy *curpx,
9747 struct proxy *defpx, const char *file, int line,
9748 char **err)
9749{
9750 char **target;
9751
Willy Tarreauef934602016-12-22 23:12:01 +01009752 target = (args[0][1] == 'a') ? &global_ssl.ca_base : &global_ssl.crt_base;
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01009753
9754 if (too_many_args(1, args, err, NULL))
9755 return -1;
9756
9757 if (*target) {
9758 memprintf(err, "'%s' already specified.", args[0]);
9759 return -1;
9760 }
9761
9762 if (*(args[1]) == 0) {
9763 memprintf(err, "global statement '%s' expects a directory path as an argument.", args[0]);
9764 return -1;
9765 }
9766 *target = strdup(args[1]);
9767 return 0;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00009768}
9769
Emmanuel Hocdet70df7bf2019-01-04 11:08:20 +01009770/* "issuers-chain-path" load chain certificate in global */
9771static int ssl_load_global_issuer_from_BIO(BIO *in, char *fp, char **err)
9772{
9773 X509 *ca;
9774 X509_NAME *name = NULL;
9775 ASN1_OCTET_STRING *skid = NULL;
9776 STACK_OF(X509) *chain = NULL;
9777 struct issuer_chain *issuer;
9778 struct eb64_node *node;
9779 char *path;
9780 u64 key;
9781 int ret = 0;
9782
9783 while ((ca = PEM_read_bio_X509(in, NULL, NULL, NULL))) {
9784 if (chain == NULL) {
9785 chain = sk_X509_new_null();
9786 skid = X509_get_ext_d2i(ca, NID_subject_key_identifier, NULL, NULL);
9787 name = X509_get_subject_name(ca);
9788 }
9789 if (!sk_X509_push(chain, ca)) {
9790 X509_free(ca);
9791 goto end;
9792 }
9793 }
9794 if (!chain) {
9795 memprintf(err, "unable to load issuers-chain %s : pem certificate not found.\n", fp);
9796 goto end;
9797 }
9798 if (!skid) {
9799 memprintf(err, "unable to load issuers-chain %s : SubjectKeyIdentifier not found.\n", fp);
9800 goto end;
9801 }
9802 if (!name) {
9803 memprintf(err, "unable to load issuers-chain %s : SubjectName not found.\n", fp);
9804 goto end;
9805 }
9806 key = XXH64(ASN1_STRING_get0_data(skid), ASN1_STRING_length(skid), 0);
William Lallemande0f3fd52020-02-25 14:53:06 +01009807 for (node = eb64_lookup(&cert_issuer_tree, key); node; node = eb64_next(node)) {
Emmanuel Hocdet70df7bf2019-01-04 11:08:20 +01009808 issuer = container_of(node, typeof(*issuer), node);
9809 if (!X509_NAME_cmp(name, X509_get_subject_name(sk_X509_value(issuer->chain, 0)))) {
9810 memprintf(err, "duplicate issuers-chain %s: %s already in store\n", fp, issuer->path);
9811 goto end;
9812 }
9813 }
9814 issuer = calloc(1, sizeof *issuer);
9815 path = strdup(fp);
9816 if (!issuer || !path) {
9817 free(issuer);
9818 free(path);
9819 goto end;
9820 }
9821 issuer->node.key = key;
9822 issuer->path = path;
9823 issuer->chain = chain;
9824 chain = NULL;
William Lallemande0f3fd52020-02-25 14:53:06 +01009825 eb64_insert(&cert_issuer_tree, &issuer->node);
Emmanuel Hocdet70df7bf2019-01-04 11:08:20 +01009826 ret = 1;
9827 end:
9828 if (skid)
9829 ASN1_OCTET_STRING_free(skid);
9830 if (chain)
9831 sk_X509_pop_free(chain, X509_free);
9832 return ret;
9833}
9834
Emmanuel Hocdet75a7aa12020-02-18 15:19:24 +01009835static struct issuer_chain* ssl_get_issuer_chain(X509 *cert)
9836{
9837 AUTHORITY_KEYID *akid;
9838 struct issuer_chain *issuer = NULL;
9839
9840 akid = X509_get_ext_d2i(cert, NID_authority_key_identifier, NULL, NULL);
9841 if (akid) {
9842 struct eb64_node *node;
9843 u64 hk;
9844 hk = XXH64(ASN1_STRING_get0_data(akid->keyid), ASN1_STRING_length(akid->keyid), 0);
9845 for (node = eb64_lookup(&cert_issuer_tree, hk); node; node = eb64_next(node)) {
9846 struct issuer_chain *ti = container_of(node, typeof(*issuer), node);
9847 if (X509_check_issued(sk_X509_value(ti->chain, 0), cert) == X509_V_OK) {
9848 issuer = ti;
9849 break;
9850 }
9851 }
9852 AUTHORITY_KEYID_free(akid);
9853 }
9854 return issuer;
9855}
9856
Emmanuel Hocdet70df7bf2019-01-04 11:08:20 +01009857static void ssl_free_global_issuers(void)
9858{
9859 struct eb64_node *node, *back;
9860 struct issuer_chain *issuer;
9861
William Lallemande0f3fd52020-02-25 14:53:06 +01009862 node = eb64_first(&cert_issuer_tree);
Emmanuel Hocdet70df7bf2019-01-04 11:08:20 +01009863 while (node) {
9864 issuer = container_of(node, typeof(*issuer), node);
9865 back = eb64_next(node);
9866 eb64_delete(node);
9867 free(issuer->path);
9868 sk_X509_pop_free(issuer->chain, X509_free);
9869 free(issuer);
9870 node = back;
9871 }
9872}
9873
9874static int ssl_load_global_issuers_from_path(char **args, int section_type, struct proxy *curpx,
9875 struct proxy *defpx, const char *file, int line,
9876 char **err)
9877{
9878 char *path;
9879 struct dirent **de_list;
9880 int i, n;
9881 struct stat buf;
9882 char *end;
9883 char fp[MAXPATHLEN+1];
9884
9885 if (too_many_args(1, args, err, NULL))
9886 return -1;
9887
9888 path = args[1];
9889 if (*path == 0 || stat(path, &buf)) {
9890 memprintf(err, "%sglobal statement '%s' expects a directory path as an argument.\n",
9891 err && *err ? *err : "", args[0]);
9892 return -1;
9893 }
9894 if (S_ISDIR(buf.st_mode) == 0) {
9895 memprintf(err, "%sglobal statement '%s': %s is not a directory.\n",
9896 err && *err ? *err : "", args[0], path);
9897 return -1;
9898 }
9899
9900 /* strip trailing slashes, including first one */
9901 for (end = path + strlen(path) - 1; end >= path && *end == '/'; end--)
9902 *end = 0;
9903 /* path already parsed? */
9904 if (global_ssl.issuers_chain_path && strcmp(global_ssl.issuers_chain_path, path) == 0)
9905 return 0;
9906 /* overwrite old issuers_chain_path */
9907 free(global_ssl.issuers_chain_path);
9908 global_ssl.issuers_chain_path = strdup(path);
9909 ssl_free_global_issuers();
9910
9911 n = scandir(path, &de_list, 0, alphasort);
9912 if (n < 0) {
9913 memprintf(err, "%sglobal statement '%s': unable to scan directory '%s' : %s.\n",
9914 err && *err ? *err : "", args[0], path, strerror(errno));
9915 return -1;
9916 }
9917 for (i = 0; i < n; i++) {
9918 struct dirent *de = de_list[i];
9919 BIO *in = NULL;
9920 char *warn = NULL;
9921
9922 snprintf(fp, sizeof(fp), "%s/%s", path, de->d_name);
9923 free(de);
9924 if (stat(fp, &buf) != 0) {
9925 ha_warning("unable to stat certificate from file '%s' : %s.\n", fp, strerror(errno));
9926 goto next;
9927 }
9928 if (!S_ISREG(buf.st_mode))
9929 goto next;
9930
9931 in = BIO_new(BIO_s_file());
9932 if (in == NULL)
9933 goto next;
9934 if (BIO_read_filename(in, fp) <= 0)
9935 goto next;
9936 ssl_load_global_issuer_from_BIO(in, fp, &warn);
9937 if (warn) {
Tim Duesterhuse8aa5f22020-02-19 11:41:13 +01009938 ha_warning("%s", warn);
Emmanuel Hocdet70df7bf2019-01-04 11:08:20 +01009939 free(warn);
9940 warn = NULL;
9941 }
9942 next:
9943 if (in)
9944 BIO_free(in);
9945 }
9946 free(de_list);
9947
9948 return 0;
9949}
9950
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00009951/* parse the "ssl-mode-async" keyword in global section.
9952 * Returns <0 on alert, >0 on warning, 0 on success.
9953 */
9954static int ssl_parse_global_ssl_async(char **args, int section_type, struct proxy *curpx,
9955 struct proxy *defpx, const char *file, int line,
9956 char **err)
9957{
Willy Tarreau5db847a2019-05-09 14:13:35 +02009958#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00009959 global_ssl.async = 1;
Emeric Brunece0c332017-12-06 13:51:49 +01009960 global.ssl_used_async_engines = nb_engines;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00009961 return 0;
9962#else
9963 memprintf(err, "'%s': openssl library does not support async mode", args[0]);
9964 return -1;
9965#endif
9966}
9967
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02009968#ifndef OPENSSL_NO_ENGINE
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00009969static int ssl_check_async_engine_count(void) {
9970 int err_code = 0;
9971
Emeric Brun3854e012017-05-17 20:42:48 +02009972 if (global_ssl.async && (openssl_engines_initialized > 32)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01009973 ha_alert("ssl-mode-async only supports a maximum of 32 engines.\n");
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00009974 err_code = ERR_ABORT;
9975 }
9976 return err_code;
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01009977}
9978
Grant Zhang872f9c22017-01-21 01:10:18 +00009979/* parse the "ssl-engine" keyword in global section.
9980 * Returns <0 on alert, >0 on warning, 0 on success.
9981 */
9982static int ssl_parse_global_ssl_engine(char **args, int section_type, struct proxy *curpx,
9983 struct proxy *defpx, const char *file, int line,
9984 char **err)
9985{
9986 char *algo;
9987 int ret = -1;
9988
9989 if (*(args[1]) == 0) {
9990 memprintf(err, "global statement '%s' expects a valid engine name as an argument.", args[0]);
9991 return ret;
9992 }
9993
9994 if (*(args[2]) == 0) {
9995 /* if no list of algorithms is given, it defaults to ALL */
9996 algo = strdup("ALL");
9997 goto add_engine;
9998 }
9999
10000 /* otherwise the expected format is ssl-engine <engine_name> algo <list of algo> */
10001 if (strcmp(args[2], "algo") != 0) {
10002 memprintf(err, "global statement '%s' expects to have algo keyword.", args[0]);
10003 return ret;
10004 }
10005
10006 if (*(args[3]) == 0) {
10007 memprintf(err, "global statement '%s' expects algorithm names as an argument.", args[0]);
10008 return ret;
10009 }
10010 algo = strdup(args[3]);
10011
10012add_engine:
10013 if (ssl_init_single_engine(args[1], algo)==0) {
10014 openssl_engines_initialized++;
10015 ret = 0;
10016 }
10017 free(algo);
10018 return ret;
10019}
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020010020#endif
Grant Zhang872f9c22017-01-21 01:10:18 +000010021
Willy Tarreauf22e9682016-12-21 23:23:19 +010010022/* parse the "ssl-default-bind-ciphers" / "ssl-default-server-ciphers" keywords
10023 * in global section. Returns <0 on alert, >0 on warning, 0 on success.
10024 */
10025static int ssl_parse_global_ciphers(char **args, int section_type, struct proxy *curpx,
10026 struct proxy *defpx, const char *file, int line,
10027 char **err)
10028{
10029 char **target;
10030
Willy Tarreauef934602016-12-22 23:12:01 +010010031 target = (args[0][12] == 'b') ? &global_ssl.listen_default_ciphers : &global_ssl.connect_default_ciphers;
Willy Tarreauf22e9682016-12-21 23:23:19 +010010032
10033 if (too_many_args(1, args, err, NULL))
10034 return -1;
10035
10036 if (*(args[1]) == 0) {
10037 memprintf(err, "global statement '%s' expects a cipher suite as an argument.", args[0]);
10038 return -1;
10039 }
10040
10041 free(*target);
10042 *target = strdup(args[1]);
10043 return 0;
10044}
Dirkjan Bussink415150f2018-09-14 11:14:21 +020010045
Emmanuel Hocdet839af572019-05-14 16:27:35 +020010046#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +020010047/* parse the "ssl-default-bind-ciphersuites" / "ssl-default-server-ciphersuites" keywords
10048 * in global section. Returns <0 on alert, >0 on warning, 0 on success.
10049 */
10050static int ssl_parse_global_ciphersuites(char **args, int section_type, struct proxy *curpx,
10051 struct proxy *defpx, const char *file, int line,
10052 char **err)
10053{
10054 char **target;
10055
10056 target = (args[0][12] == 'b') ? &global_ssl.listen_default_ciphersuites : &global_ssl.connect_default_ciphersuites;
10057
10058 if (too_many_args(1, args, err, NULL))
10059 return -1;
10060
10061 if (*(args[1]) == 0) {
10062 memprintf(err, "global statement '%s' expects a cipher suite as an argument.", args[0]);
10063 return -1;
10064 }
10065
10066 free(*target);
10067 *target = strdup(args[1]);
10068 return 0;
10069}
10070#endif
Willy Tarreauf22e9682016-12-21 23:23:19 +010010071
Willy Tarreau9ceda382016-12-21 23:13:03 +010010072/* parse various global tune.ssl settings consisting in positive integers.
10073 * Returns <0 on alert, >0 on warning, 0 on success.
10074 */
10075static int ssl_parse_global_int(char **args, int section_type, struct proxy *curpx,
10076 struct proxy *defpx, const char *file, int line,
10077 char **err)
10078{
10079 int *target;
10080
10081 if (strcmp(args[0], "tune.ssl.cachesize") == 0)
10082 target = &global.tune.sslcachesize;
10083 else if (strcmp(args[0], "tune.ssl.maxrecord") == 0)
Willy Tarreauef934602016-12-22 23:12:01 +010010084 target = (int *)&global_ssl.max_record;
Willy Tarreau9ceda382016-12-21 23:13:03 +010010085 else if (strcmp(args[0], "tune.ssl.ssl-ctx-cache-size") == 0)
Willy Tarreauef934602016-12-22 23:12:01 +010010086 target = &global_ssl.ctx_cache;
Willy Tarreau0bea58d2016-12-21 23:17:25 +010010087 else if (strcmp(args[0], "maxsslconn") == 0)
10088 target = &global.maxsslconn;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +010010089 else if (strcmp(args[0], "tune.ssl.capture-cipherlist-size") == 0)
10090 target = &global_ssl.capture_cipherlist;
Willy Tarreau9ceda382016-12-21 23:13:03 +010010091 else {
10092 memprintf(err, "'%s' keyword not unhandled (please report this bug).", args[0]);
10093 return -1;
10094 }
10095
10096 if (too_many_args(1, args, err, NULL))
10097 return -1;
10098
10099 if (*(args[1]) == 0) {
10100 memprintf(err, "'%s' expects an integer argument.", args[0]);
10101 return -1;
10102 }
10103
10104 *target = atoi(args[1]);
10105 if (*target < 0) {
10106 memprintf(err, "'%s' expects a positive numeric value.", args[0]);
10107 return -1;
10108 }
10109 return 0;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +010010110}
10111
10112static int ssl_parse_global_capture_cipherlist(char **args, int section_type, struct proxy *curpx,
10113 struct proxy *defpx, const char *file, int line,
10114 char **err)
10115{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +010010116 int ret;
10117
10118 ret = ssl_parse_global_int(args, section_type, curpx, defpx, file, line, err);
10119 if (ret != 0)
10120 return ret;
10121
Willy Tarreaubafbe012017-11-24 17:34:44 +010010122 if (pool_head_ssl_capture) {
Thierry FOURNIER5bf77322017-02-25 12:45:22 +010010123 memprintf(err, "'%s' is already configured.", args[0]);
10124 return -1;
10125 }
10126
Willy Tarreaubafbe012017-11-24 17:34:44 +010010127 pool_head_ssl_capture = create_pool("ssl-capture", sizeof(struct ssl_capture) + global_ssl.capture_cipherlist, MEM_F_SHARED);
10128 if (!pool_head_ssl_capture) {
Thierry FOURNIER5bf77322017-02-25 12:45:22 +010010129 memprintf(err, "Out of memory error.");
10130 return -1;
10131 }
10132 return 0;
Willy Tarreau9ceda382016-12-21 23:13:03 +010010133}
10134
10135/* parse "ssl.force-private-cache".
10136 * Returns <0 on alert, >0 on warning, 0 on success.
10137 */
10138static int ssl_parse_global_private_cache(char **args, int section_type, struct proxy *curpx,
10139 struct proxy *defpx, const char *file, int line,
10140 char **err)
10141{
10142 if (too_many_args(0, args, err, NULL))
10143 return -1;
10144
Willy Tarreauef934602016-12-22 23:12:01 +010010145 global_ssl.private_cache = 1;
Willy Tarreau9ceda382016-12-21 23:13:03 +010010146 return 0;
10147}
10148
10149/* parse "ssl.lifetime".
10150 * Returns <0 on alert, >0 on warning, 0 on success.
10151 */
10152static int ssl_parse_global_lifetime(char **args, int section_type, struct proxy *curpx,
10153 struct proxy *defpx, const char *file, int line,
10154 char **err)
10155{
10156 const char *res;
10157
10158 if (too_many_args(1, args, err, NULL))
10159 return -1;
10160
10161 if (*(args[1]) == 0) {
10162 memprintf(err, "'%s' expects ssl sessions <lifetime> in seconds as argument.", args[0]);
10163 return -1;
10164 }
10165
Willy Tarreauef934602016-12-22 23:12:01 +010010166 res = parse_time_err(args[1], &global_ssl.life_time, TIME_UNIT_S);
Willy Tarreau9faebe32019-06-07 19:00:37 +020010167 if (res == PARSE_TIME_OVER) {
10168 memprintf(err, "timer overflow in argument '%s' to <%s> (maximum value is 2147483647 s or ~68 years).",
10169 args[1], args[0]);
10170 return -1;
10171 }
10172 else if (res == PARSE_TIME_UNDER) {
10173 memprintf(err, "timer underflow in argument '%s' to <%s> (minimum non-null value is 1 s).",
10174 args[1], args[0]);
10175 return -1;
10176 }
10177 else if (res) {
Willy Tarreau9ceda382016-12-21 23:13:03 +010010178 memprintf(err, "unexpected character '%c' in argument to <%s>.", *res, args[0]);
10179 return -1;
10180 }
10181 return 0;
10182}
10183
10184#ifndef OPENSSL_NO_DH
Willy Tarreau14e36a12016-12-21 23:28:13 +010010185/* parse "ssl-dh-param-file".
10186 * Returns <0 on alert, >0 on warning, 0 on success.
10187 */
10188static int ssl_parse_global_dh_param_file(char **args, int section_type, struct proxy *curpx,
10189 struct proxy *defpx, const char *file, int line,
10190 char **err)
10191{
10192 if (too_many_args(1, args, err, NULL))
10193 return -1;
10194
10195 if (*(args[1]) == 0) {
10196 memprintf(err, "'%s' expects a file path as an argument.", args[0]);
10197 return -1;
10198 }
10199
10200 if (ssl_sock_load_global_dh_param_from_file(args[1])) {
10201 memprintf(err, "'%s': unable to load DH parameters from file <%s>.", args[0], args[1]);
10202 return -1;
10203 }
10204 return 0;
10205}
10206
Willy Tarreau9ceda382016-12-21 23:13:03 +010010207/* parse "ssl.default-dh-param".
10208 * Returns <0 on alert, >0 on warning, 0 on success.
10209 */
10210static int ssl_parse_global_default_dh(char **args, int section_type, struct proxy *curpx,
10211 struct proxy *defpx, const char *file, int line,
10212 char **err)
10213{
10214 if (too_many_args(1, args, err, NULL))
10215 return -1;
10216
10217 if (*(args[1]) == 0) {
10218 memprintf(err, "'%s' expects an integer argument.", args[0]);
10219 return -1;
10220 }
10221
Willy Tarreauef934602016-12-22 23:12:01 +010010222 global_ssl.default_dh_param = atoi(args[1]);
10223 if (global_ssl.default_dh_param < 1024) {
Willy Tarreau9ceda382016-12-21 23:13:03 +010010224 memprintf(err, "'%s' expects a value >= 1024.", args[0]);
10225 return -1;
10226 }
10227 return 0;
10228}
10229#endif
10230
William Lallemand3af48e72020-02-03 17:15:52 +010010231
10232/*
10233 * parse "ssl-load-extra-files".
10234 * multiple arguments are allowed: "bundle", "sctl", "ocsp", "issuer", "all", "none"
10235 */
10236static int ssl_parse_global_extra_files(char **args, int section_type, struct proxy *curpx,
10237 struct proxy *defpx, const char *file, int line,
10238 char **err)
10239{
10240 int i;
10241 int gf = SSL_GF_NONE;
10242
10243 if (*(args[1]) == 0)
10244 goto err_arg;
10245
10246 for (i = 1; *args[i]; i++) {
10247
10248 if (!strcmp("bundle", args[i])) {
10249 gf |= SSL_GF_BUNDLE;
10250
10251 } else if (!strcmp("sctl", args[i])) {
10252 gf |= SSL_GF_SCTL;
10253
10254 } else if (!strcmp("ocsp", args[i])){
10255 gf |= SSL_GF_OCSP;
10256
10257 } else if (!strcmp("issuer", args[i])){
10258 gf |= SSL_GF_OCSP_ISSUER;
10259
William Lallemand4c5adbf2020-02-24 14:23:22 +010010260 } else if (!strcmp("key", args[i])) {
10261 gf |= SSL_GF_KEY;
10262
William Lallemand3af48e72020-02-03 17:15:52 +010010263 } else if (!strcmp("none", args[i])) {
10264 if (gf != SSL_GF_NONE)
10265 goto err_alone;
10266 gf = SSL_GF_NONE;
10267 i++;
10268 break;
10269
10270 } else if (!strcmp("all", args[i])) {
10271 if (gf != SSL_GF_NONE)
10272 goto err_alone;
10273 gf = SSL_GF_ALL;
10274 i++;
10275 break;
10276 } else {
10277 goto err_arg;
10278 }
10279 }
10280 /* break from loop but there are still arguments */
10281 if (*args[i])
10282 goto err_alone;
10283
10284 global_ssl.extra_files = gf;
10285
10286 return 0;
10287
10288err_alone:
10289 memprintf(err, "'%s' 'none' and 'all' can be only used alone", args[0]);
10290 return -1;
10291
10292err_arg:
10293 memprintf(err, "'%s' expects one or multiple arguments (none, all, bundle, sctl, ocsp, issuer).", args[0]);
10294 return -1;
10295}
10296
Willy Tarreau9ceda382016-12-21 23:13:03 +010010297
William Lallemand32af2032016-10-29 18:09:35 +020010298/* This function is used with TLS ticket keys management. It permits to browse
10299 * each reference. The variable <getnext> must contain the current node,
10300 * <end> point to the root node.
10301 */
10302#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
10303static inline
10304struct tls_keys_ref *tlskeys_list_get_next(struct tls_keys_ref *getnext, struct list *end)
10305{
10306 struct tls_keys_ref *ref = getnext;
10307
10308 while (1) {
10309
10310 /* Get next list entry. */
10311 ref = LIST_NEXT(&ref->list, struct tls_keys_ref *, list);
10312
10313 /* If the entry is the last of the list, return NULL. */
10314 if (&ref->list == end)
10315 return NULL;
10316
10317 return ref;
10318 }
10319}
10320
10321static inline
10322struct tls_keys_ref *tlskeys_ref_lookup_ref(const char *reference)
10323{
10324 int id;
10325 char *error;
10326
10327 /* If the reference starts by a '#', this is numeric id. */
10328 if (reference[0] == '#') {
10329 /* Try to convert the numeric id. If the conversion fails, the lookup fails. */
10330 id = strtol(reference + 1, &error, 10);
10331 if (*error != '\0')
10332 return NULL;
10333
10334 /* Perform the unique id lookup. */
10335 return tlskeys_ref_lookupid(id);
10336 }
10337
10338 /* Perform the string lookup. */
10339 return tlskeys_ref_lookup(reference);
10340}
10341#endif
10342
10343
10344#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
10345
10346static int cli_io_handler_tlskeys_files(struct appctx *appctx);
10347
10348static inline int cli_io_handler_tlskeys_entries(struct appctx *appctx) {
10349 return cli_io_handler_tlskeys_files(appctx);
10350}
10351
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010352/* dumps all tls keys. Relies on cli.i0 (non-null = only list file names), cli.i1
10353 * (next index to be dumped), and cli.p0 (next key reference).
10354 */
William Lallemand32af2032016-10-29 18:09:35 +020010355static int cli_io_handler_tlskeys_files(struct appctx *appctx) {
10356
10357 struct stream_interface *si = appctx->owner;
10358
10359 switch (appctx->st2) {
10360 case STAT_ST_INIT:
10361 /* Display the column headers. If the message cannot be sent,
Joseph Herlant017b3da2018-11-15 09:07:59 -080010362 * quit the function with returning 0. The function is called
William Lallemand32af2032016-10-29 18:09:35 +020010363 * later and restart at the state "STAT_ST_INIT".
10364 */
10365 chunk_reset(&trash);
10366
10367 if (appctx->io_handler == cli_io_handler_tlskeys_entries)
10368 chunk_appendf(&trash, "# id secret\n");
10369 else
10370 chunk_appendf(&trash, "# id (file)\n");
10371
Willy Tarreau06d80a92017-10-19 14:32:15 +020010372 if (ci_putchk(si_ic(si), &trash) == -1) {
Willy Tarreaudb398432018-11-15 11:08:52 +010010373 si_rx_room_blk(si);
William Lallemand32af2032016-10-29 18:09:35 +020010374 return 0;
10375 }
10376
William Lallemand32af2032016-10-29 18:09:35 +020010377 /* Now, we start the browsing of the references lists.
10378 * Note that the following call to LIST_ELEM return bad pointer. The only
10379 * available field of this pointer is <list>. It is used with the function
10380 * tlskeys_list_get_next() for retruning the first available entry
10381 */
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010382 if (appctx->ctx.cli.p0 == NULL) {
10383 appctx->ctx.cli.p0 = LIST_ELEM(&tlskeys_reference, struct tls_keys_ref *, list);
10384 appctx->ctx.cli.p0 = tlskeys_list_get_next(appctx->ctx.cli.p0, &tlskeys_reference);
William Lallemand32af2032016-10-29 18:09:35 +020010385 }
10386
10387 appctx->st2 = STAT_ST_LIST;
10388 /* fall through */
10389
10390 case STAT_ST_LIST:
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010391 while (appctx->ctx.cli.p0) {
10392 struct tls_keys_ref *ref = appctx->ctx.cli.p0;
William Lallemand32af2032016-10-29 18:09:35 +020010393
10394 chunk_reset(&trash);
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010395 if (appctx->io_handler == cli_io_handler_tlskeys_entries && appctx->ctx.cli.i1 == 0)
William Lallemand32af2032016-10-29 18:09:35 +020010396 chunk_appendf(&trash, "# ");
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010397
10398 if (appctx->ctx.cli.i1 == 0)
10399 chunk_appendf(&trash, "%d (%s)\n", ref->unique_id, ref->filename);
10400
William Lallemand32af2032016-10-29 18:09:35 +020010401 if (appctx->io_handler == cli_io_handler_tlskeys_entries) {
Christopher Faulet16f45c82018-02-16 11:23:49 +010010402 int head;
10403
10404 HA_RWLOCK_RDLOCK(TLSKEYS_REF_LOCK, &ref->lock);
10405 head = ref->tls_ticket_enc_index;
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010406 while (appctx->ctx.cli.i1 < TLS_TICKETS_NO) {
Willy Tarreau83061a82018-07-13 11:56:34 +020010407 struct buffer *t2 = get_trash_chunk();
William Lallemand32af2032016-10-29 18:09:35 +020010408
10409 chunk_reset(t2);
10410 /* should never fail here because we dump only a key in the t2 buffer */
Emeric Brun9e754772019-01-10 17:51:55 +010010411 if (ref->key_size_bits == 128) {
10412 t2->data = a2base64((char *)(ref->tlskeys + (head + 2 + appctx->ctx.cli.i1) % TLS_TICKETS_NO),
10413 sizeof(struct tls_sess_key_128),
10414 t2->area, t2->size);
10415 chunk_appendf(&trash, "%d.%d %s\n", ref->unique_id, appctx->ctx.cli.i1,
10416 t2->area);
10417 }
10418 else if (ref->key_size_bits == 256) {
10419 t2->data = a2base64((char *)(ref->tlskeys + (head + 2 + appctx->ctx.cli.i1) % TLS_TICKETS_NO),
10420 sizeof(struct tls_sess_key_256),
10421 t2->area, t2->size);
10422 chunk_appendf(&trash, "%d.%d %s\n", ref->unique_id, appctx->ctx.cli.i1,
10423 t2->area);
10424 }
10425 else {
10426 /* This case should never happen */
10427 chunk_appendf(&trash, "%d.%d <unknown>\n", ref->unique_id, appctx->ctx.cli.i1);
10428 }
William Lallemand32af2032016-10-29 18:09:35 +020010429
Willy Tarreau06d80a92017-10-19 14:32:15 +020010430 if (ci_putchk(si_ic(si), &trash) == -1) {
William Lallemand32af2032016-10-29 18:09:35 +020010431 /* let's try again later from this stream. We add ourselves into
10432 * this stream's users so that it can remove us upon termination.
10433 */
Christopher Faulet16f45c82018-02-16 11:23:49 +010010434 HA_RWLOCK_RDUNLOCK(TLSKEYS_REF_LOCK, &ref->lock);
Willy Tarreaudb398432018-11-15 11:08:52 +010010435 si_rx_room_blk(si);
William Lallemand32af2032016-10-29 18:09:35 +020010436 return 0;
10437 }
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010438 appctx->ctx.cli.i1++;
William Lallemand32af2032016-10-29 18:09:35 +020010439 }
Christopher Faulet16f45c82018-02-16 11:23:49 +010010440 HA_RWLOCK_RDUNLOCK(TLSKEYS_REF_LOCK, &ref->lock);
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010441 appctx->ctx.cli.i1 = 0;
William Lallemand32af2032016-10-29 18:09:35 +020010442 }
Willy Tarreau06d80a92017-10-19 14:32:15 +020010443 if (ci_putchk(si_ic(si), &trash) == -1) {
William Lallemand32af2032016-10-29 18:09:35 +020010444 /* let's try again later from this stream. We add ourselves into
10445 * this stream's users so that it can remove us upon termination.
10446 */
Willy Tarreaudb398432018-11-15 11:08:52 +010010447 si_rx_room_blk(si);
William Lallemand32af2032016-10-29 18:09:35 +020010448 return 0;
10449 }
10450
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010451 if (appctx->ctx.cli.i0 == 0) /* don't display everything if not necessary */
William Lallemand32af2032016-10-29 18:09:35 +020010452 break;
10453
10454 /* get next list entry and check the end of the list */
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010455 appctx->ctx.cli.p0 = tlskeys_list_get_next(appctx->ctx.cli.p0, &tlskeys_reference);
William Lallemand32af2032016-10-29 18:09:35 +020010456 }
10457
10458 appctx->st2 = STAT_ST_FIN;
10459 /* fall through */
10460
10461 default:
10462 appctx->st2 = STAT_ST_FIN;
10463 return 1;
10464 }
10465 return 0;
10466}
10467
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010468/* sets cli.i0 to non-zero if only file lists should be dumped */
Aurélien Nephtaliabbf6072018-04-18 13:26:46 +020010469static int cli_parse_show_tlskeys(char **args, char *payload, struct appctx *appctx, void *private)
William Lallemand32af2032016-10-29 18:09:35 +020010470{
William Lallemand32af2032016-10-29 18:09:35 +020010471 /* no parameter, shows only file list */
10472 if (!*args[2]) {
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010473 appctx->ctx.cli.i0 = 1;
William Lallemand32af2032016-10-29 18:09:35 +020010474 appctx->io_handler = cli_io_handler_tlskeys_files;
Willy Tarreau3067bfa2016-12-05 14:50:15 +010010475 return 0;
William Lallemand32af2032016-10-29 18:09:35 +020010476 }
10477
10478 if (args[2][0] == '*') {
10479 /* list every TLS ticket keys */
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010480 appctx->ctx.cli.i0 = 1;
William Lallemand32af2032016-10-29 18:09:35 +020010481 } else {
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010482 appctx->ctx.cli.p0 = tlskeys_ref_lookup_ref(args[2]);
Willy Tarreau9d008692019-08-09 11:21:01 +020010483 if (!appctx->ctx.cli.p0)
10484 return cli_err(appctx, "'show tls-keys' unable to locate referenced filename\n");
William Lallemand32af2032016-10-29 18:09:35 +020010485 }
William Lallemand32af2032016-10-29 18:09:35 +020010486 appctx->io_handler = cli_io_handler_tlskeys_entries;
Willy Tarreau3067bfa2016-12-05 14:50:15 +010010487 return 0;
William Lallemand32af2032016-10-29 18:09:35 +020010488}
10489
Aurélien Nephtaliabbf6072018-04-18 13:26:46 +020010490static int cli_parse_set_tlskeys(char **args, char *payload, struct appctx *appctx, void *private)
William Lallemand32af2032016-10-29 18:09:35 +020010491{
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010492 struct tls_keys_ref *ref;
Willy Tarreau1c913e42018-08-22 05:26:57 +020010493 int ret;
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010494
William Lallemand32af2032016-10-29 18:09:35 +020010495 /* Expect two parameters: the filename and the new new TLS key in encoding */
Willy Tarreau9d008692019-08-09 11:21:01 +020010496 if (!*args[3] || !*args[4])
10497 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 +020010498
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010499 ref = tlskeys_ref_lookup_ref(args[3]);
Willy Tarreau9d008692019-08-09 11:21:01 +020010500 if (!ref)
10501 return cli_err(appctx, "'set ssl tls-key' unable to locate referenced filename\n");
William Lallemand32af2032016-10-29 18:09:35 +020010502
Willy Tarreau1c913e42018-08-22 05:26:57 +020010503 ret = base64dec(args[4], strlen(args[4]), trash.area, trash.size);
Willy Tarreau9d008692019-08-09 11:21:01 +020010504 if (ret < 0)
10505 return cli_err(appctx, "'set ssl tls-key' received invalid base64 encoded TLS key.\n");
Emeric Brun9e754772019-01-10 17:51:55 +010010506
Willy Tarreau1c913e42018-08-22 05:26:57 +020010507 trash.data = ret;
Willy Tarreau9d008692019-08-09 11:21:01 +020010508 if (ssl_sock_update_tlskey_ref(ref, &trash) < 0)
10509 return cli_err(appctx, "'set ssl tls-key' received a key of wrong size.\n");
William Lallemand32af2032016-10-29 18:09:35 +020010510
Willy Tarreau9d008692019-08-09 11:21:01 +020010511 return cli_msg(appctx, LOG_INFO, "TLS ticket key updated!\n");
William Lallemand32af2032016-10-29 18:09:35 +020010512}
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +010010513#endif
William Lallemand32af2032016-10-29 18:09:35 +020010514
William Lallemand44b35322019-10-17 16:28:40 +020010515
10516/* Type of SSL payloads that can be updated over the CLI */
10517
10518enum {
10519 CERT_TYPE_PEM = 0,
William Lallemand4c5adbf2020-02-24 14:23:22 +010010520 CERT_TYPE_KEY,
Emmanuel Hocdetf6ac4fa2019-10-30 17:41:27 +010010521#if ((defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP) || defined OPENSSL_IS_BORINGSSL)
William Lallemand44b35322019-10-17 16:28:40 +020010522 CERT_TYPE_OCSP,
Emmanuel Hocdetf6ac4fa2019-10-30 17:41:27 +010010523#endif
William Lallemand44b35322019-10-17 16:28:40 +020010524 CERT_TYPE_ISSUER,
Emmanuel Hocdetf6ac4fa2019-10-30 17:41:27 +010010525#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
William Lallemand44b35322019-10-17 16:28:40 +020010526 CERT_TYPE_SCTL,
Emmanuel Hocdetf6ac4fa2019-10-30 17:41:27 +010010527#endif
William Lallemand44b35322019-10-17 16:28:40 +020010528 CERT_TYPE_MAX,
10529};
10530
10531struct {
10532 const char *ext;
10533 int type;
10534 int (*load)(const char *path, char *payload, struct cert_key_and_chain *ckch, char **err);
10535 /* add a parsing callback */
William Lallemandf29cdef2019-10-23 15:00:52 +020010536} cert_exts[CERT_TYPE_MAX+1] = {
William Lallemand44b35322019-10-17 16:28:40 +020010537 [CERT_TYPE_PEM] = { "", CERT_TYPE_PEM, &ssl_sock_load_pem_into_ckch }, /* default mode, no extensions */
William Lallemand4c5adbf2020-02-24 14:23:22 +010010538 [CERT_TYPE_KEY] = { "key", CERT_TYPE_KEY, &ssl_sock_load_key_into_ckch },
William Lallemand541a5342019-10-23 14:11:54 +020010539#if ((defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP) || defined OPENSSL_IS_BORINGSSL)
William Lallemand44b35322019-10-17 16:28:40 +020010540 [CERT_TYPE_OCSP] = { "ocsp", CERT_TYPE_OCSP, &ssl_sock_load_ocsp_response_from_file },
William Lallemand541a5342019-10-23 14:11:54 +020010541#endif
10542#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
William Lallemand44b35322019-10-17 16:28:40 +020010543 [CERT_TYPE_SCTL] = { "sctl", CERT_TYPE_SCTL, &ssl_sock_load_sctl_from_file },
William Lallemand541a5342019-10-23 14:11:54 +020010544#endif
William Lallemand44b35322019-10-17 16:28:40 +020010545 [CERT_TYPE_ISSUER] = { "issuer", CERT_TYPE_ISSUER, &ssl_sock_load_issuer_file_into_ckch },
William Lallemandf29cdef2019-10-23 15:00:52 +020010546 [CERT_TYPE_MAX] = { NULL, CERT_TYPE_MAX, NULL },
William Lallemand44b35322019-10-17 16:28:40 +020010547};
10548
William Lallemand430413e2019-10-28 14:30:47 +010010549/* states of the CLI IO handler for 'set ssl cert' */
10550enum {
10551 SETCERT_ST_INIT = 0,
10552 SETCERT_ST_GEN,
10553 SETCERT_ST_INSERT,
10554 SETCERT_ST_FIN,
10555};
William Lallemand8f840d72019-10-23 10:53:05 +020010556
William Lallemandd4f946c2019-12-05 10:26:40 +010010557/* release function of the `show ssl cert' command */
10558static void cli_release_show_cert(struct appctx *appctx)
10559{
10560 HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
10561}
10562
10563/* IO handler of "show ssl cert <filename>" */
10564static int cli_io_handler_show_cert(struct appctx *appctx)
10565{
10566 struct buffer *trash = alloc_trash_chunk();
10567 struct ebmb_node *node;
10568 struct stream_interface *si = appctx->owner;
10569 struct ckch_store *ckchs;
William Lallemandd4f946c2019-12-05 10:26:40 +010010570
10571 if (trash == NULL)
10572 return 1;
10573
10574 if (!appctx->ctx.ssl.old_ckchs) {
10575 if (ckchs_transaction.old_ckchs) {
10576 ckchs = ckchs_transaction.old_ckchs;
10577 chunk_appendf(trash, "# transaction\n");
10578 if (!ckchs->multi) {
10579 chunk_appendf(trash, "*%s\n", ckchs->path);
William Lallemandba22e902019-12-18 20:36:01 +010010580#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
William Lallemandd4f946c2019-12-05 10:26:40 +010010581 } else {
William Lallemanda25a19f2020-01-29 00:04:24 +010010582 int n;
10583
William Lallemandd4f946c2019-12-05 10:26:40 +010010584 chunk_appendf(trash, "*%s:", ckchs->path);
10585 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
10586 if (ckchs->ckch[n].cert)
10587 chunk_appendf(trash, " %s.%s\n", ckchs->path, SSL_SOCK_KEYTYPE_NAMES[n]);
10588 }
10589 chunk_appendf(trash, "\n");
William Lallemandba22e902019-12-18 20:36:01 +010010590#endif
William Lallemandd4f946c2019-12-05 10:26:40 +010010591 }
10592 }
10593 }
10594
10595 if (!appctx->ctx.cli.p0) {
10596 chunk_appendf(trash, "# filename\n");
10597 node = ebmb_first(&ckchs_tree);
10598 } else {
10599 node = &((struct ckch_store *)appctx->ctx.cli.p0)->node;
10600 }
10601 while (node) {
10602 ckchs = ebmb_entry(node, struct ckch_store, node);
10603 if (!ckchs->multi) {
10604 chunk_appendf(trash, "%s\n", ckchs->path);
William Lallemandba22e902019-12-18 20:36:01 +010010605#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
William Lallemandd4f946c2019-12-05 10:26:40 +010010606 } else {
William Lallemanda25a19f2020-01-29 00:04:24 +010010607 int n;
10608
William Lallemandd4f946c2019-12-05 10:26:40 +010010609 chunk_appendf(trash, "%s:", ckchs->path);
10610 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
10611 if (ckchs->ckch[n].cert)
10612 chunk_appendf(trash, " %s.%s", ckchs->path, SSL_SOCK_KEYTYPE_NAMES[n]);
10613 }
10614 chunk_appendf(trash, "\n");
William Lallemandba22e902019-12-18 20:36:01 +010010615#endif
William Lallemandd4f946c2019-12-05 10:26:40 +010010616 }
10617
10618 node = ebmb_next(node);
10619 if (ci_putchk(si_ic(si), trash) == -1) {
10620 si_rx_room_blk(si);
10621 goto yield;
10622 }
10623 }
10624
10625 appctx->ctx.cli.p0 = NULL;
10626 free_trash_chunk(trash);
10627 return 1;
10628yield:
10629
10630 free_trash_chunk(trash);
10631 appctx->ctx.cli.p0 = ckchs;
10632 return 0; /* should come back */
10633}
10634
10635/* IO handler of the details "show ssl cert <filename>" */
10636static int cli_io_handler_show_cert_detail(struct appctx *appctx)
10637{
10638 struct stream_interface *si = appctx->owner;
10639 struct ckch_store *ckchs = appctx->ctx.cli.p0;
10640 struct buffer *out = alloc_trash_chunk();
10641 struct buffer *tmp = alloc_trash_chunk();
10642 X509_NAME *name = NULL;
Emmanuel Hocdetcf8cf6c2020-02-18 16:06:14 +010010643 STACK_OF(X509) *chain;
Willy Tarreau105599c2020-02-25 08:59:23 +010010644 unsigned int len = 0;
William Lallemandd4f946c2019-12-05 10:26:40 +010010645 int write = -1;
10646 BIO *bio = NULL;
William Lallemand35f4a9d2020-02-25 11:56:32 +010010647 int i;
William Lallemandd4f946c2019-12-05 10:26:40 +010010648
10649 if (!tmp || !out)
10650 goto end;
10651
10652 if (!ckchs->multi) {
10653 chunk_appendf(out, "Filename: ");
10654 if (ckchs == ckchs_transaction.new_ckchs)
10655 chunk_appendf(out, "*");
10656 chunk_appendf(out, "%s\n", ckchs->path);
Emmanuel Hocdetcf8cf6c2020-02-18 16:06:14 +010010657
10658 chain = ckchs->ckch->chain;
10659 if (chain == NULL) {
10660 struct issuer_chain *issuer;
10661 issuer = ssl_get_issuer_chain(ckchs->ckch->cert);
10662 if (issuer) {
10663 chain = issuer->chain;
10664 chunk_appendf(out, "Chain Filename: ");
10665 chunk_appendf(out, "%s\n", issuer->path);
10666 }
10667 }
William Lallemandd4f946c2019-12-05 10:26:40 +010010668 chunk_appendf(out, "Serial: ");
10669 if (ssl_sock_get_serial(ckchs->ckch->cert, tmp) == -1)
10670 goto end;
10671 dump_binary(out, tmp->area, tmp->data);
10672 chunk_appendf(out, "\n");
10673
10674 chunk_appendf(out, "notBefore: ");
10675 chunk_reset(tmp);
10676 if ((bio = BIO_new(BIO_s_mem())) == NULL)
10677 goto end;
10678 if (ASN1_TIME_print(bio, X509_getm_notBefore(ckchs->ckch->cert)) == 0)
10679 goto end;
10680 write = BIO_read(bio, tmp->area, tmp->size-1);
10681 tmp->area[write] = '\0';
10682 BIO_free(bio);
10683 chunk_appendf(out, "%s\n", tmp->area);
10684
10685 chunk_appendf(out, "notAfter: ");
10686 chunk_reset(tmp);
10687 if ((bio = BIO_new(BIO_s_mem())) == NULL)
10688 goto end;
10689 if (ASN1_TIME_print(bio, X509_getm_notAfter(ckchs->ckch->cert)) == 0)
10690 goto end;
10691 if ((write = BIO_read(bio, tmp->area, tmp->size-1)) <= 0)
10692 goto end;
10693 tmp->area[write] = '\0';
10694 BIO_free(bio);
10695 chunk_appendf(out, "%s\n", tmp->area);
10696
William Lallemandd4f946c2019-12-05 10:26:40 +010010697#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
10698 chunk_appendf(out, "Subject Alternative Name: ");
10699 if (ssl_sock_get_san_oneline(ckchs->ckch->cert, out) == -1)
10700 goto end;
10701 *(out->area + out->data) = '\0';
10702 chunk_appendf(out, "\n");
10703#endif
10704 chunk_reset(tmp);
10705 chunk_appendf(out, "Algorithm: ");
10706 if (cert_get_pkey_algo(ckchs->ckch->cert, tmp) == 0)
10707 goto end;
10708 chunk_appendf(out, "%s\n", tmp->area);
10709
10710 chunk_reset(tmp);
10711 chunk_appendf(out, "SHA1 FingerPrint: ");
Willy Tarreau105599c2020-02-25 08:59:23 +010010712 if (X509_digest(ckchs->ckch->cert, EVP_sha1(), (unsigned char *) tmp->area, &len) == 0)
William Lallemandd4f946c2019-12-05 10:26:40 +010010713 goto end;
Willy Tarreau105599c2020-02-25 08:59:23 +010010714 tmp->data = len;
William Lallemandd4f946c2019-12-05 10:26:40 +010010715 dump_binary(out, tmp->area, tmp->data);
10716 chunk_appendf(out, "\n");
William Lallemand35f4a9d2020-02-25 11:56:32 +010010717
William Lallemanda90e5932020-02-25 14:07:58 +010010718 chunk_appendf(out, "Subject: ");
10719 if ((name = X509_get_subject_name(ckchs->ckch->cert)) == NULL)
10720 goto end;
10721 if ((ssl_sock_get_dn_oneline(name, tmp)) == -1)
10722 goto end;
10723 *(tmp->area + tmp->data) = '\0';
10724 chunk_appendf(out, "%s\n", tmp->area);
10725
10726 chunk_appendf(out, "Issuer: ");
10727 if ((name = X509_get_issuer_name(ckchs->ckch->cert)) == NULL)
10728 goto end;
10729 if ((ssl_sock_get_dn_oneline(name, tmp)) == -1)
10730 goto end;
10731 *(tmp->area + tmp->data) = '\0';
10732 chunk_appendf(out, "%s\n", tmp->area);
10733
William Lallemand35f4a9d2020-02-25 11:56:32 +010010734 /* Displays subject of each certificate in the chain */
Emmanuel Hocdetcf8cf6c2020-02-18 16:06:14 +010010735 for (i = 0; i < sk_X509_num(chain); i++) {
10736 X509 *ca = sk_X509_value(chain, i);
William Lallemand35f4a9d2020-02-25 11:56:32 +010010737
William Lallemandbb7288a2020-02-25 14:04:33 +010010738 chunk_appendf(out, "Chain Subject: ");
William Lallemand35f4a9d2020-02-25 11:56:32 +010010739 if ((name = X509_get_subject_name(ca)) == NULL)
10740 goto end;
10741 if ((ssl_sock_get_dn_oneline(name, tmp)) == -1)
10742 goto end;
10743 *(tmp->area + tmp->data) = '\0';
10744 chunk_appendf(out, "%s\n", tmp->area);
10745
William Lallemandbb7288a2020-02-25 14:04:33 +010010746 chunk_appendf(out, "Chain Issuer: ");
10747 if ((name = X509_get_issuer_name(ca)) == NULL)
10748 goto end;
10749 if ((ssl_sock_get_dn_oneline(name, tmp)) == -1)
10750 goto end;
10751 *(tmp->area + tmp->data) = '\0';
10752 chunk_appendf(out, "%s\n", tmp->area);
William Lallemand35f4a9d2020-02-25 11:56:32 +010010753 }
William Lallemandd4f946c2019-12-05 10:26:40 +010010754 }
10755
10756 if (ci_putchk(si_ic(si), out) == -1) {
10757 si_rx_room_blk(si);
10758 goto yield;
10759 }
10760
10761end:
10762 free_trash_chunk(tmp);
10763 free_trash_chunk(out);
10764 return 1;
10765yield:
10766 free_trash_chunk(tmp);
10767 free_trash_chunk(out);
10768 return 0; /* should come back */
10769}
10770
10771/* parsing function for 'show ssl cert [certfile]' */
10772static int cli_parse_show_cert(char **args, char *payload, struct appctx *appctx, void *private)
10773{
10774 struct ckch_store *ckchs;
10775
10776 if (!cli_has_level(appctx, ACCESS_LVL_OPER))
10777 return cli_err(appctx, "Can't allocate memory!\n");
10778
10779 /* The operations on the CKCH architecture are locked so we can
10780 * manipulate ckch_store and ckch_inst */
10781 if (HA_SPIN_TRYLOCK(CKCH_LOCK, &ckch_lock))
10782 return cli_err(appctx, "Can't show!\nOperations on certificates are currently locked!\n");
10783
10784 /* check if there is a certificate to lookup */
10785 if (*args[3]) {
10786 if (*args[3] == '*') {
10787 if (!ckchs_transaction.new_ckchs)
10788 goto error;
10789
10790 ckchs = ckchs_transaction.new_ckchs;
10791
10792 if (strcmp(args[3] + 1, ckchs->path))
10793 goto error;
10794
10795 } else {
10796 if ((ckchs = ckchs_lookup(args[3])) == NULL)
10797 goto error;
10798
10799 }
10800
10801 if (ckchs->multi)
10802 goto error;
10803
10804 appctx->ctx.cli.p0 = ckchs;
10805 /* use the IO handler that shows details */
10806 appctx->io_handler = cli_io_handler_show_cert_detail;
10807 }
10808
10809 return 0;
10810
10811error:
10812 HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
10813 return cli_err(appctx, "Can't display the certificate: Not found or the certificate is a bundle!\n");
10814}
10815
William Lallemand430413e2019-10-28 14:30:47 +010010816/* release function of the `set ssl cert' command, free things and unlock the spinlock */
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010817static void cli_release_commit_cert(struct appctx *appctx)
William Lallemand8f840d72019-10-23 10:53:05 +020010818{
10819 struct ckch_store *new_ckchs;
10820 struct ckch_inst *ckchi, *ckchis;
William Lallemand8f840d72019-10-23 10:53:05 +020010821
William Lallemand430413e2019-10-28 14:30:47 +010010822 HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
William Lallemand8f840d72019-10-23 10:53:05 +020010823
William Lallemand430413e2019-10-28 14:30:47 +010010824 if (appctx->st2 != SETCERT_ST_FIN) {
William Lallemand8f840d72019-10-23 10:53:05 +020010825 /* 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 +010010826 new_ckchs = appctx->ctx.ssl.new_ckchs;
William Lallemand8f840d72019-10-23 10:53:05 +020010827
William Lallemandbeea2a42019-10-30 17:45:33 +010010828 if (!new_ckchs)
10829 return;
William Lallemand8f840d72019-10-23 10:53:05 +020010830
William Lallemandbeea2a42019-10-30 17:45:33 +010010831 /* if the allocation failed, we need to free everything from the temporary list */
10832 list_for_each_entry_safe(ckchi, ckchis, &new_ckchs->ckch_inst, by_ckchs) {
10833 struct sni_ctx *sc0, *sc0s;
William Lallemand8f840d72019-10-23 10:53:05 +020010834
William Lallemandbeea2a42019-10-30 17:45:33 +010010835 list_for_each_entry_safe(sc0, sc0s, &ckchi->sni_ctx, by_ckch_inst) {
10836 if (sc0->order == 0) /* we only free if it's the first inserted */
10837 SSL_CTX_free(sc0->ctx);
10838 LIST_DEL(&sc0->by_ckch_inst);
10839 free(sc0);
William Lallemand8f840d72019-10-23 10:53:05 +020010840 }
William Lallemandbeea2a42019-10-30 17:45:33 +010010841 LIST_DEL(&ckchi->by_ckchs);
10842 free(ckchi);
William Lallemand8f840d72019-10-23 10:53:05 +020010843 }
William Lallemandbeea2a42019-10-30 17:45:33 +010010844 ckchs_free(new_ckchs);
William Lallemand8f840d72019-10-23 10:53:05 +020010845 }
10846}
10847
10848
10849/*
10850 * This function tries to create the new ckch_inst and their SNIs
10851 */
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010852static int cli_io_handler_commit_cert(struct appctx *appctx)
William Lallemand8f840d72019-10-23 10:53:05 +020010853{
10854 struct stream_interface *si = appctx->owner;
10855 int y = 0;
10856 char *err = NULL;
10857 int errcode = 0;
10858 struct ckch_store *old_ckchs, *new_ckchs = NULL;
10859 struct ckch_inst *ckchi, *ckchis;
William Lallemand8f840d72019-10-23 10:53:05 +020010860 struct buffer *trash = alloc_trash_chunk();
William Lallemand8ef0c2a2019-11-21 16:30:34 +010010861 struct sni_ctx *sc0, *sc0s;
William Lallemand8f840d72019-10-23 10:53:05 +020010862
William Lallemand33cc76f2019-10-31 11:43:45 +010010863 if (trash == NULL)
10864 goto error;
10865
William Lallemand8f840d72019-10-23 10:53:05 +020010866 if (unlikely(si_ic(si)->flags & (CF_WRITE_ERROR|CF_SHUTW)))
10867 goto error;
10868
William Lallemand430413e2019-10-28 14:30:47 +010010869 while (1) {
10870 switch (appctx->st2) {
10871 case SETCERT_ST_INIT:
10872 /* This state just print the update message */
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010873 chunk_printf(trash, "Committing %s", ckchs_transaction.path);
William Lallemand430413e2019-10-28 14:30:47 +010010874 if (ci_putchk(si_ic(si), trash) == -1) {
10875 si_rx_room_blk(si);
William Lallemand8f840d72019-10-23 10:53:05 +020010876 goto yield;
William Lallemand430413e2019-10-28 14:30:47 +010010877 }
10878 appctx->st2 = SETCERT_ST_GEN;
10879 /* fallthrough */
10880 case SETCERT_ST_GEN:
10881 /*
10882 * This state generates the ckch instances with their
10883 * sni_ctxs and SSL_CTX.
10884 *
William Lallemand430413e2019-10-28 14:30:47 +010010885 * Since the SSL_CTX generation can be CPU consumer, we
10886 * yield every 10 instances.
10887 */
William Lallemand8f840d72019-10-23 10:53:05 +020010888
William Lallemandbeea2a42019-10-30 17:45:33 +010010889 old_ckchs = appctx->ctx.ssl.old_ckchs;
10890 new_ckchs = appctx->ctx.ssl.new_ckchs;
William Lallemand8f840d72019-10-23 10:53:05 +020010891
William Lallemandbeea2a42019-10-30 17:45:33 +010010892 if (!new_ckchs)
10893 continue;
William Lallemand8f840d72019-10-23 10:53:05 +020010894
William Lallemandbeea2a42019-10-30 17:45:33 +010010895 /* get the next ckchi to regenerate */
10896 ckchi = appctx->ctx.ssl.next_ckchi;
10897 /* we didn't start yet, set it to the first elem */
10898 if (ckchi == NULL)
10899 ckchi = LIST_ELEM(old_ckchs->ckch_inst.n, typeof(ckchi), by_ckchs);
William Lallemand8f840d72019-10-23 10:53:05 +020010900
William Lallemandbeea2a42019-10-30 17:45:33 +010010901 /* walk through the old ckch_inst and creates new ckch_inst using the updated ckchs */
10902 list_for_each_entry_from(ckchi, &old_ckchs->ckch_inst, by_ckchs) {
10903 struct ckch_inst *new_inst;
William Lallemand8f840d72019-10-23 10:53:05 +020010904
William Lallemandbeea2a42019-10-30 17:45:33 +010010905 /* it takes a lot of CPU to creates SSL_CTXs, so we yield every 10 CKCH instances */
10906 if (y >= 10) {
10907 /* save the next ckchi to compute */
10908 appctx->ctx.ssl.next_ckchi = ckchi;
10909 goto yield;
10910 }
William Lallemand8f840d72019-10-23 10:53:05 +020010911
William Lallemandbeea2a42019-10-30 17:45:33 +010010912 if (new_ckchs->multi)
10913 errcode |= ckch_inst_new_load_multi_store(new_ckchs->path, new_ckchs, ckchi->bind_conf, ckchi->ssl_conf, NULL, 0, &new_inst, &err);
10914 else
10915 errcode |= ckch_inst_new_load_store(new_ckchs->path, new_ckchs, ckchi->bind_conf, ckchi->ssl_conf, NULL, 0, &new_inst, &err);
William Lallemand8f840d72019-10-23 10:53:05 +020010916
William Lallemandbeea2a42019-10-30 17:45:33 +010010917 if (errcode & ERR_CODE)
10918 goto error;
William Lallemand8f840d72019-10-23 10:53:05 +020010919
William Lallemand21724f02019-11-04 17:56:13 +010010920 /* if the previous ckchi was used as the default */
10921 if (ckchi->is_default)
10922 new_inst->is_default = 1;
10923
William Lallemand8ef0c2a2019-11-21 16:30:34 +010010924 /* we need to initialize the SSL_CTX generated */
William Lallemand696f3172020-02-07 20:45:24 +010010925 /* this iterate on the newly generated SNIs in the new instance to prepare their SSL_CTX */
10926 list_for_each_entry_safe(sc0, sc0s, &new_inst->sni_ctx, by_ckch_inst) {
William Lallemand8ef0c2a2019-11-21 16:30:34 +010010927 if (!sc0->order) { /* we initiliazed only the first SSL_CTX because it's the same in the other sni_ctx's */
10928 errcode |= ssl_sock_prepare_ctx(ckchi->bind_conf, ckchi->ssl_conf, sc0->ctx, &err);
10929 if (errcode & ERR_CODE)
10930 goto error;
10931 }
10932 }
10933
10934
William Lallemandbeea2a42019-10-30 17:45:33 +010010935 /* display one dot per new instance */
10936 chunk_appendf(trash, ".");
10937 /* link the new ckch_inst to the duplicate */
10938 LIST_ADDQ(&new_ckchs->ckch_inst, &new_inst->by_ckchs);
10939 y++;
10940 }
William Lallemand430413e2019-10-28 14:30:47 +010010941 appctx->st2 = SETCERT_ST_INSERT;
10942 /* fallthrough */
10943 case SETCERT_ST_INSERT:
10944 /* The generation is finished, we can insert everything */
William Lallemand8f840d72019-10-23 10:53:05 +020010945
William Lallemandbeea2a42019-10-30 17:45:33 +010010946 old_ckchs = appctx->ctx.ssl.old_ckchs;
10947 new_ckchs = appctx->ctx.ssl.new_ckchs;
William Lallemand8f840d72019-10-23 10:53:05 +020010948
William Lallemandbeea2a42019-10-30 17:45:33 +010010949 if (!new_ckchs)
10950 continue;
William Lallemand430413e2019-10-28 14:30:47 +010010951
William Lallemand21724f02019-11-04 17:56:13 +010010952 /* First, we insert every new SNIs in the trees, also replace the default_ctx */
William Lallemandbeea2a42019-10-30 17:45:33 +010010953 list_for_each_entry_safe(ckchi, ckchis, &new_ckchs->ckch_inst, by_ckchs) {
10954 HA_RWLOCK_WRLOCK(SNI_LOCK, &ckchi->bind_conf->sni_lock);
10955 ssl_sock_load_cert_sni(ckchi, ckchi->bind_conf);
10956 HA_RWLOCK_WRUNLOCK(SNI_LOCK, &ckchi->bind_conf->sni_lock);
10957 }
William Lallemand8f840d72019-10-23 10:53:05 +020010958
William Lallemandbeea2a42019-10-30 17:45:33 +010010959 /* delete the old sni_ctx, the old ckch_insts and the ckch_store */
10960 list_for_each_entry_safe(ckchi, ckchis, &old_ckchs->ckch_inst, by_ckchs) {
William Lallemand430413e2019-10-28 14:30:47 +010010961
William Lallemandbeea2a42019-10-30 17:45:33 +010010962 HA_RWLOCK_WRLOCK(SNI_LOCK, &ckchi->bind_conf->sni_lock);
10963 list_for_each_entry_safe(sc0, sc0s, &ckchi->sni_ctx, by_ckch_inst) {
10964 ebmb_delete(&sc0->name);
10965 LIST_DEL(&sc0->by_ckch_inst);
10966 free(sc0);
William Lallemand430413e2019-10-28 14:30:47 +010010967 }
William Lallemandbeea2a42019-10-30 17:45:33 +010010968 HA_RWLOCK_WRUNLOCK(SNI_LOCK, &ckchi->bind_conf->sni_lock);
10969 LIST_DEL(&ckchi->by_ckchs);
10970 free(ckchi);
10971 }
William Lallemand8f840d72019-10-23 10:53:05 +020010972
William Lallemandbeea2a42019-10-30 17:45:33 +010010973 /* Replace the old ckchs by the new one */
10974 ebmb_delete(&old_ckchs->node);
10975 ckchs_free(old_ckchs);
10976 ebst_insert(&ckchs_tree, &new_ckchs->node);
William Lallemand430413e2019-10-28 14:30:47 +010010977 appctx->st2 = SETCERT_ST_FIN;
10978 /* fallthrough */
10979 case SETCERT_ST_FIN:
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010980 /* we achieved the transaction, we can set everything to NULL */
10981 free(ckchs_transaction.path);
10982 ckchs_transaction.path = NULL;
10983 ckchs_transaction.new_ckchs = NULL;
10984 ckchs_transaction.old_ckchs = NULL;
William Lallemand430413e2019-10-28 14:30:47 +010010985 goto end;
10986 }
William Lallemand8f840d72019-10-23 10:53:05 +020010987 }
William Lallemand430413e2019-10-28 14:30:47 +010010988end:
William Lallemand8f840d72019-10-23 10:53:05 +020010989
William Lallemanded442432019-11-21 16:41:07 +010010990 chunk_appendf(trash, "\n");
10991 if (errcode & ERR_WARN)
Tim Duesterhusc0e820c2019-11-23 23:52:30 +010010992 chunk_appendf(trash, "%s", err);
William Lallemanded442432019-11-21 16:41:07 +010010993 chunk_appendf(trash, "Success!\n");
William Lallemand430413e2019-10-28 14:30:47 +010010994 if (ci_putchk(si_ic(si), trash) == -1)
10995 si_rx_room_blk(si);
10996 free_trash_chunk(trash);
10997 /* success: call the release function and don't come back */
10998 return 1;
William Lallemand8f840d72019-10-23 10:53:05 +020010999yield:
11000 /* store the state */
11001 if (ci_putchk(si_ic(si), trash) == -1)
11002 si_rx_room_blk(si);
11003 free_trash_chunk(trash);
11004 si_rx_endp_more(si); /* let's come back later */
William Lallemand8f840d72019-10-23 10:53:05 +020011005 return 0; /* should come back */
11006
11007error:
11008 /* spin unlock and free are done in the release function */
William Lallemand33cc76f2019-10-31 11:43:45 +010011009 if (trash) {
11010 chunk_appendf(trash, "\n%sFailed!\n", err);
11011 if (ci_putchk(si_ic(si), trash) == -1)
11012 si_rx_room_blk(si);
11013 free_trash_chunk(trash);
11014 }
William Lallemand430413e2019-10-28 14:30:47 +010011015 /* error: call the release function and don't come back */
11016 return 1;
William Lallemand8f840d72019-10-23 10:53:05 +020011017}
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011018
11019/*
11020 * Parsing function of 'commit ssl cert'
11021 */
11022static int cli_parse_commit_cert(char **args, char *payload, struct appctx *appctx, void *private)
11023{
11024 char *err = NULL;
11025
William Lallemand230662a2019-12-03 13:32:54 +010011026 if (!cli_has_level(appctx, ACCESS_LVL_ADMIN))
11027 return 1;
11028
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011029 if (!*args[3])
11030 return cli_err(appctx, "'commit ssl cert expects a filename\n");
11031
11032 /* The operations on the CKCH architecture are locked so we can
11033 * manipulate ckch_store and ckch_inst */
11034 if (HA_SPIN_TRYLOCK(CKCH_LOCK, &ckch_lock))
11035 return cli_err(appctx, "Can't commit the certificate!\nOperations on certificates are currently locked!\n");
11036
11037 if (!ckchs_transaction.path) {
11038 memprintf(&err, "No ongoing transaction! !\n");
11039 goto error;
11040 }
11041
11042 if (strcmp(ckchs_transaction.path, args[3]) != 0) {
11043 memprintf(&err, "The ongoing transaction is about '%s' but you are trying to set '%s'\n", ckchs_transaction.path, args[3]);
11044 goto error;
11045 }
11046
William Lallemand4c5adbf2020-02-24 14:23:22 +010011047#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
11048 if (ckchs_transaction.new_ckchs->multi) {
11049 int n;
11050
11051 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
11052 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)) {
11053 memprintf(&err, "inconsistencies between private key and certificate loaded '%s'.\n", ckchs_transaction.path);
11054 goto error;
11055 }
11056 }
11057 } else
11058#endif
11059 {
11060 if (!X509_check_private_key(ckchs_transaction.new_ckchs->ckch->cert, ckchs_transaction.new_ckchs->ckch->key)) {
11061 memprintf(&err, "inconsistencies between private key and certificate loaded '%s'.\n", ckchs_transaction.path);
11062 goto error;
11063 }
11064 }
11065
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011066 /* init the appctx structure */
11067 appctx->st2 = SETCERT_ST_INIT;
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011068 appctx->ctx.ssl.next_ckchi = NULL;
11069 appctx->ctx.ssl.new_ckchs = ckchs_transaction.new_ckchs;
11070 appctx->ctx.ssl.old_ckchs = ckchs_transaction.old_ckchs;
11071
11072 /* we don't unlock there, it will be unlock after the IO handler, in the release handler */
11073 return 0;
11074
11075error:
11076
11077 HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
11078 err = memprintf(&err, "%sCan't commit %s!\n", err ? err : "", args[3]);
11079
11080 return cli_dynerr(appctx, err);
11081}
11082
11083
William Lallemand8f840d72019-10-23 10:53:05 +020011084/*
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011085 * Parsing function of `set ssl cert`, it updates or creates a temporary ckch.
William Lallemand8f840d72019-10-23 10:53:05 +020011086 */
William Lallemand150bfa82019-09-19 17:12:49 +020011087static int cli_parse_set_cert(char **args, char *payload, struct appctx *appctx, void *private)
11088{
William Lallemand0c3b7d92019-10-18 11:27:07 +020011089 struct ckch_store *new_ckchs = NULL;
William Lallemand8f840d72019-10-23 10:53:05 +020011090 struct ckch_store *old_ckchs = NULL;
William Lallemand150bfa82019-09-19 17:12:49 +020011091 char *err = NULL;
William Lallemand963b2e72019-10-14 11:38:36 +020011092 int i;
William Lallemand849eed62019-10-17 16:23:50 +020011093 int bundle = -1; /* TRUE if >= 0 (ckch index) */
Emeric Brunf69ed1d2019-10-17 11:56:56 +020011094 int errcode = 0;
William Lallemand44b35322019-10-17 16:28:40 +020011095 char *end;
11096 int type = CERT_TYPE_PEM;
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011097 struct cert_key_and_chain *ckch;
11098 struct buffer *buf;
William Lallemand8f840d72019-10-23 10:53:05 +020011099
William Lallemand230662a2019-12-03 13:32:54 +010011100 if (!cli_has_level(appctx, ACCESS_LVL_ADMIN))
11101 return 1;
11102
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011103 if ((buf = alloc_trash_chunk()) == NULL)
11104 return cli_err(appctx, "Can't allocate memory\n");
William Lallemand150bfa82019-09-19 17:12:49 +020011105
11106 if (!*args[3] || !payload)
11107 return cli_err(appctx, "'set ssl cert expects a filename and a certificat as a payload\n");
11108
11109 /* The operations on the CKCH architecture are locked so we can
11110 * manipulate ckch_store and ckch_inst */
11111 if (HA_SPIN_TRYLOCK(CKCH_LOCK, &ckch_lock))
11112 return cli_err(appctx, "Can't update the certificate!\nOperations on certificates are currently locked!\n");
11113
William Lallemand8f840d72019-10-23 10:53:05 +020011114 if (!chunk_strcpy(buf, args[3])) {
11115 memprintf(&err, "%sCan't allocate memory\n", err ? err : "");
11116 errcode |= ERR_ALERT | ERR_FATAL;
11117 goto end;
11118 }
11119
William Lallemand44b35322019-10-17 16:28:40 +020011120 /* check which type of file we want to update */
William Lallemandf29cdef2019-10-23 15:00:52 +020011121 for (i = 0; cert_exts[i].type < CERT_TYPE_MAX; i++) {
William Lallemand8f840d72019-10-23 10:53:05 +020011122 end = strrchr(buf->area, '.');
William Lallemand44b35322019-10-17 16:28:40 +020011123 if (end && *cert_exts[i].ext && (!strcmp(end + 1, cert_exts[i].ext))) {
11124 *end = '\0';
11125 type = cert_exts[i].type;
11126 break;
11127 }
11128 }
11129
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011130 appctx->ctx.ssl.old_ckchs = NULL;
11131 appctx->ctx.ssl.new_ckchs = NULL;
William Lallemand849eed62019-10-17 16:23:50 +020011132
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011133 /* if there is an ongoing transaction */
11134 if (ckchs_transaction.path) {
11135 /* 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 +020011136#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011137 if (ckchs_transaction.new_ckchs->multi) {
Emmanuel Hocdet40f2f1e2019-10-30 17:31:28 +010011138 char *end;
William Lallemand963b2e72019-10-14 11:38:36 +020011139 int j;
William Lallemand150bfa82019-09-19 17:12:49 +020011140
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011141 /* check if it was used in a bundle by removing the
William Lallemand963b2e72019-10-14 11:38:36 +020011142 * .dsa/.rsa/.ecdsa at the end of the filename */
William Lallemand8f840d72019-10-23 10:53:05 +020011143 end = strrchr(buf->area, '.');
Emmanuel Hocdet40f2f1e2019-10-30 17:31:28 +010011144 for (j = 0; end && j < SSL_SOCK_NUM_KEYTYPES; j++) {
William Lallemand963b2e72019-10-14 11:38:36 +020011145 if (!strcmp(end + 1, SSL_SOCK_KEYTYPE_NAMES[j])) {
11146 bundle = j; /* keep the type of certificate so we insert it at the right place */
11147 *end = '\0'; /* it's a bundle let's end the string*/
11148 break;
11149 }
William Lallemand150bfa82019-09-19 17:12:49 +020011150 }
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011151 if (bundle < 0) {
11152 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);
11153 errcode |= ERR_ALERT | ERR_FATAL;
11154 goto end;
11155 }
11156 }
11157#endif
11158
11159 /* if there is an ongoing transaction, check if this is the same file */
11160 if (strcmp(ckchs_transaction.path, buf->area) != 0) {
11161 memprintf(&err, "The ongoing transaction is about '%s' but you are trying to set '%s'\n", ckchs_transaction.path, buf->area);
11162 errcode |= ERR_ALERT | ERR_FATAL;
11163 goto end;
William Lallemand150bfa82019-09-19 17:12:49 +020011164 }
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011165
11166 appctx->ctx.ssl.old_ckchs = ckchs_transaction.new_ckchs;
11167
11168 } else {
11169 struct ckch_store *find_ckchs[2] = { NULL, NULL };
11170
11171 /* lookup for the certificate in the tree:
11172 * check if this is used as a bundle AND as a unique certificate */
11173 for (i = 0; i < 2; i++) {
11174
11175 if ((find_ckchs[i] = ckchs_lookup(buf->area)) != NULL) {
11176 /* only the bundle name is in the tree and you should
11177 * never update a bundle name, only a filename */
11178 if (bundle < 0 && find_ckchs[i]->multi) {
11179 /* we tried to look for a non-bundle and we found a bundle */
11180 memprintf(&err, "%s%s is a multi-cert bundle. Try updating %s.{dsa,rsa,ecdsa}\n",
11181 err ? err : "", args[3], args[3]);
11182 errcode |= ERR_ALERT | ERR_FATAL;
11183 goto end;
11184 }
William Lallemand3246d942019-11-04 14:02:11 +010011185 /* If we want a bundle but this is not a bundle
11186 * example: When you try to update <file>.rsa, but
11187 * <file> is a regular file */
11188 if (bundle >= 0 && find_ckchs[i]->multi == 0) {
11189 find_ckchs[i] = NULL;
11190 break;
11191 }
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011192 }
11193#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
11194 {
Emmanuel Hocdet40f2f1e2019-10-30 17:31:28 +010011195 char *end;
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011196 int j;
11197
11198 /* check if it was used in a bundle by removing the
11199 * .dsa/.rsa/.ecdsa at the end of the filename */
11200 end = strrchr(buf->area, '.');
Emmanuel Hocdet40f2f1e2019-10-30 17:31:28 +010011201 for (j = 0; end && j < SSL_SOCK_NUM_KEYTYPES; j++) {
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011202 if (!strcmp(end + 1, SSL_SOCK_KEYTYPE_NAMES[j])) {
11203 bundle = j; /* keep the type of certificate so we insert it at the right place */
11204 *end = '\0'; /* it's a bundle let's end the string*/
11205 break;
11206 }
11207 }
William Lallemand37031b82019-11-04 13:38:53 +010011208 if (bundle < 0) /* we didn't find a bundle extension */
11209 break;
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011210 }
William Lallemand963b2e72019-10-14 11:38:36 +020011211#else
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011212 /* bundles are not supported here, so we don't need to lookup again */
11213 break;
William Lallemand963b2e72019-10-14 11:38:36 +020011214#endif
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011215 }
11216
11217 if (find_ckchs[0] && find_ckchs[1]) {
11218 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",
11219 err ? err : "", find_ckchs[0]->path, find_ckchs[1]->path);
11220 errcode |= ERR_ALERT | ERR_FATAL;
11221 goto end;
11222 }
11223
11224 appctx->ctx.ssl.old_ckchs = find_ckchs[0] ? find_ckchs[0] : find_ckchs[1];
William Lallemand150bfa82019-09-19 17:12:49 +020011225 }
11226
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011227 if (!appctx->ctx.ssl.old_ckchs) {
11228 memprintf(&err, "%sCan't replace a certificate which is not referenced by the configuration!\n",
William Lallemand150bfa82019-09-19 17:12:49 +020011229 err ? err : "");
Emeric Brunf69ed1d2019-10-17 11:56:56 +020011230 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemand8f840d72019-10-23 10:53:05 +020011231 goto end;
William Lallemand150bfa82019-09-19 17:12:49 +020011232 }
11233
William Lallemand8a7fdf02019-11-04 10:59:32 +010011234 if (!appctx->ctx.ssl.path) {
11235 /* this is a new transaction, set the path of the transaction */
11236 appctx->ctx.ssl.path = strdup(appctx->ctx.ssl.old_ckchs->path);
11237 if (!appctx->ctx.ssl.path) {
11238 memprintf(&err, "%sCan't allocate memory\n", err ? err : "");
11239 errcode |= ERR_ALERT | ERR_FATAL;
11240 goto end;
11241 }
11242 }
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011243
11244 old_ckchs = appctx->ctx.ssl.old_ckchs;
11245
11246 /* TODO: handle filters */
11247 if (old_ckchs->filters) {
11248 memprintf(&err, "%sCertificates used in crt-list with filters are not supported!\n",
11249 err ? err : "");
11250 errcode |= ERR_ALERT | ERR_FATAL;
11251 goto end;
11252 }
11253
11254 /* duplicate the ckch store */
11255 new_ckchs = ckchs_dup(old_ckchs);
11256 if (!new_ckchs) {
11257 memprintf(&err, "%sCannot allocate memory!\n",
11258 err ? err : "");
11259 errcode |= ERR_ALERT | ERR_FATAL;
11260 goto end;
11261 }
11262
11263 if (!new_ckchs->multi)
11264 ckch = new_ckchs->ckch;
11265 else
11266 ckch = &new_ckchs->ckch[bundle];
11267
11268 /* appply the change on the duplicate */
11269 if (cert_exts[type].load(buf->area, payload, ckch, &err) != 0) {
11270 memprintf(&err, "%sCan't load the payload\n", err ? err : "");
11271 errcode |= ERR_ALERT | ERR_FATAL;
11272 goto end;
11273 }
11274
11275 appctx->ctx.ssl.new_ckchs = new_ckchs;
11276
11277 /* we succeed, we can save the ckchs in the transaction */
11278
11279 /* if there wasn't a transaction, update the old ckchs */
William Dauchyc8bb1532019-11-24 15:04:20 +010011280 if (!ckchs_transaction.old_ckchs) {
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011281 ckchs_transaction.old_ckchs = appctx->ctx.ssl.old_ckchs;
11282 ckchs_transaction.path = appctx->ctx.ssl.path;
11283 err = memprintf(&err, "Transaction created for certificate %s!\n", ckchs_transaction.path);
11284 } else {
11285 err = memprintf(&err, "Transaction updated for certificate %s!\n", ckchs_transaction.path);
11286
11287 }
11288
11289 /* free the previous ckchs if there was a transaction */
11290 ckchs_free(ckchs_transaction.new_ckchs);
11291
11292 ckchs_transaction.new_ckchs = appctx->ctx.ssl.new_ckchs;
11293
11294
William Lallemand8f840d72019-10-23 10:53:05 +020011295 /* creates the SNI ctxs later in the IO handler */
William Lallemand150bfa82019-09-19 17:12:49 +020011296
William Lallemand8f840d72019-10-23 10:53:05 +020011297end:
11298 free_trash_chunk(buf);
William Lallemand150bfa82019-09-19 17:12:49 +020011299
Emeric Brunf69ed1d2019-10-17 11:56:56 +020011300 if (errcode & ERR_CODE) {
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011301
11302 ckchs_free(appctx->ctx.ssl.new_ckchs);
11303 appctx->ctx.ssl.new_ckchs = NULL;
11304
11305 appctx->ctx.ssl.old_ckchs = NULL;
11306
11307 free(appctx->ctx.ssl.path);
11308 appctx->ctx.ssl.path = NULL;
11309
11310 HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
William Lallemand44b35322019-10-17 16:28:40 +020011311 return cli_dynerr(appctx, memprintf(&err, "%sCan't update %s!\n", err ? err : "", args[3]));
William Lallemand430413e2019-10-28 14:30:47 +010011312 } else {
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011313
11314 HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
11315 return cli_dynmsg(appctx, LOG_NOTICE, err);
William Lallemand430413e2019-10-28 14:30:47 +010011316 }
William Lallemand8f840d72019-10-23 10:53:05 +020011317 /* TODO: handle the ERR_WARN which are not handled because of the io_handler */
William Lallemand150bfa82019-09-19 17:12:49 +020011318}
11319
William Lallemand0bc9c8a2019-11-19 15:51:51 +010011320/* parsing function of 'abort ssl cert' */
11321static int cli_parse_abort_cert(char **args, char *payload, struct appctx *appctx, void *private)
11322{
11323 char *err = NULL;
11324
William Lallemand230662a2019-12-03 13:32:54 +010011325 if (!cli_has_level(appctx, ACCESS_LVL_ADMIN))
11326 return 1;
11327
William Lallemand0bc9c8a2019-11-19 15:51:51 +010011328 if (!*args[3])
11329 return cli_err(appctx, "'abort ssl cert' expects a filename\n");
11330
11331 /* The operations on the CKCH architecture are locked so we can
11332 * manipulate ckch_store and ckch_inst */
11333 if (HA_SPIN_TRYLOCK(CKCH_LOCK, &ckch_lock))
11334 return cli_err(appctx, "Can't abort!\nOperations on certificates are currently locked!\n");
11335
11336 if (!ckchs_transaction.path) {
11337 memprintf(&err, "No ongoing transaction!\n");
11338 goto error;
11339 }
11340
11341 if (strcmp(ckchs_transaction.path, args[3]) != 0) {
11342 memprintf(&err, "The ongoing transaction is about '%s' but you are trying to abort a transaction for '%s'\n", ckchs_transaction.path, args[3]);
11343 goto error;
11344 }
11345
11346 /* Only free the ckchs there, because the SNI and instances were not generated yet */
11347 ckchs_free(ckchs_transaction.new_ckchs);
11348 ckchs_transaction.new_ckchs = NULL;
11349 ckchs_free(ckchs_transaction.old_ckchs);
11350 ckchs_transaction.old_ckchs = NULL;
11351 free(ckchs_transaction.path);
11352 ckchs_transaction.path = NULL;
11353
11354 HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
11355
11356 err = memprintf(&err, "Transaction aborted for certificate '%s'!\n", args[3]);
11357 return cli_dynmsg(appctx, LOG_NOTICE, err);
11358
11359error:
11360 HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
11361
11362 return cli_dynerr(appctx, err);
11363}
11364
Aurélien Nephtaliabbf6072018-04-18 13:26:46 +020011365static int cli_parse_set_ocspresponse(char **args, char *payload, struct appctx *appctx, void *private)
William Lallemand32af2032016-10-29 18:09:35 +020011366{
11367#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
11368 char *err = NULL;
Willy Tarreau1c913e42018-08-22 05:26:57 +020011369 int i, j, ret;
Aurélien Nephtali1e0867c2018-04-18 14:04:58 +020011370
11371 if (!payload)
11372 payload = args[3];
William Lallemand32af2032016-10-29 18:09:35 +020011373
11374 /* Expect one parameter: the new response in base64 encoding */
Willy Tarreau9d008692019-08-09 11:21:01 +020011375 if (!*payload)
11376 return cli_err(appctx, "'set ssl ocsp-response' expects response in base64 encoding.\n");
Aurélien Nephtali1e0867c2018-04-18 14:04:58 +020011377
11378 /* remove \r and \n from the payload */
11379 for (i = 0, j = 0; payload[i]; i++) {
11380 if (payload[i] == '\r' || payload[i] == '\n')
11381 continue;
11382 payload[j++] = payload[i];
11383 }
11384 payload[j] = 0;
William Lallemand32af2032016-10-29 18:09:35 +020011385
Willy Tarreau1c913e42018-08-22 05:26:57 +020011386 ret = base64dec(payload, j, trash.area, trash.size);
Willy Tarreau9d008692019-08-09 11:21:01 +020011387 if (ret < 0)
11388 return cli_err(appctx, "'set ssl ocsp-response' received invalid base64 encoded response.\n");
William Lallemand32af2032016-10-29 18:09:35 +020011389
Willy Tarreau1c913e42018-08-22 05:26:57 +020011390 trash.data = ret;
William Lallemand32af2032016-10-29 18:09:35 +020011391 if (ssl_sock_update_ocsp_response(&trash, &err)) {
Willy Tarreau9d008692019-08-09 11:21:01 +020011392 if (err)
11393 return cli_dynerr(appctx, memprintf(&err, "%s.\n", err));
11394 else
11395 return cli_err(appctx, "Failed to update OCSP response.\n");
William Lallemand32af2032016-10-29 18:09:35 +020011396 }
Willy Tarreau9d008692019-08-09 11:21:01 +020011397
11398 return cli_msg(appctx, LOG_INFO, "OCSP Response updated!\n");
William Lallemand32af2032016-10-29 18:09:35 +020011399#else
Willy Tarreau9d008692019-08-09 11:21:01 +020011400 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 +020011401#endif
11402
Nenad Merdanovicc31499d2019-03-23 11:00:32 +010011403}
11404
Willy Tarreau86a394e2019-05-09 14:15:32 +020011405#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000100fL)
Nenad Merdanovicc31499d2019-03-23 11:00:32 +010011406static inline int sample_conv_var2smp_str(const struct arg *arg, struct sample *smp)
11407{
11408 switch (arg->type) {
11409 case ARGT_STR:
11410 smp->data.type = SMP_T_STR;
11411 smp->data.u.str = arg->data.str;
11412 return 1;
11413 case ARGT_VAR:
11414 if (!vars_get_by_desc(&arg->data.var, smp))
11415 return 0;
11416 if (!sample_casts[smp->data.type][SMP_T_STR])
11417 return 0;
11418 if (!sample_casts[smp->data.type][SMP_T_STR](smp))
11419 return 0;
11420 return 1;
11421 default:
11422 return 0;
11423 }
11424}
11425
11426static int check_aes_gcm(struct arg *args, struct sample_conv *conv,
11427 const char *file, int line, char **err)
11428{
11429 switch(args[0].data.sint) {
11430 case 128:
11431 case 192:
11432 case 256:
11433 break;
11434 default:
11435 memprintf(err, "key size must be 128, 192 or 256 (bits).");
11436 return 0;
11437 }
11438 /* Try to decode a variable. */
11439 vars_check_arg(&args[1], NULL);
11440 vars_check_arg(&args[2], NULL);
11441 vars_check_arg(&args[3], NULL);
11442 return 1;
11443}
11444
11445/* Arguements: AES size in bits, nonce, key, tag. The last three arguments are base64 encoded */
11446static int sample_conv_aes_gcm_dec(const struct arg *arg_p, struct sample *smp, void *private)
11447{
11448 struct sample nonce, key, aead_tag;
11449 struct buffer *smp_trash, *smp_trash_alloc;
11450 EVP_CIPHER_CTX *ctx;
11451 int dec_size, ret;
11452
11453 smp_set_owner(&nonce, smp->px, smp->sess, smp->strm, smp->opt);
11454 if (!sample_conv_var2smp_str(&arg_p[1], &nonce))
11455 return 0;
11456
11457 smp_set_owner(&key, smp->px, smp->sess, smp->strm, smp->opt);
11458 if (!sample_conv_var2smp_str(&arg_p[2], &key))
11459 return 0;
11460
11461 smp_set_owner(&aead_tag, smp->px, smp->sess, smp->strm, smp->opt);
11462 if (!sample_conv_var2smp_str(&arg_p[3], &aead_tag))
11463 return 0;
11464
11465 smp_trash = get_trash_chunk();
11466 smp_trash_alloc = alloc_trash_chunk();
11467 if (!smp_trash_alloc)
11468 return 0;
11469
11470 ctx = EVP_CIPHER_CTX_new();
11471
11472 if (!ctx)
11473 goto err;
11474
11475 dec_size = base64dec(nonce.data.u.str.area, nonce.data.u.str.data, smp_trash->area, smp_trash->size);
11476 if (dec_size < 0)
11477 goto err;
11478 smp_trash->data = dec_size;
11479
11480 /* Set cipher type and mode */
11481 switch(arg_p[0].data.sint) {
11482 case 128:
11483 EVP_DecryptInit_ex(ctx, EVP_aes_128_gcm(), NULL, NULL, NULL);
11484 break;
11485 case 192:
11486 EVP_DecryptInit_ex(ctx, EVP_aes_192_gcm(), NULL, NULL, NULL);
11487 break;
11488 case 256:
11489 EVP_DecryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL);
11490 break;
11491 }
11492
11493 EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, smp_trash->data, NULL);
11494
11495 /* Initialise IV */
11496 if(!EVP_DecryptInit_ex(ctx, NULL, NULL, NULL, (unsigned char *) smp_trash->area))
11497 goto err;
11498
11499 dec_size = base64dec(key.data.u.str.area, key.data.u.str.data, smp_trash->area, smp_trash->size);
11500 if (dec_size < 0)
11501 goto err;
11502 smp_trash->data = dec_size;
11503
11504 /* Initialise key */
11505 if (!EVP_DecryptInit_ex(ctx, NULL, NULL, (unsigned char *) smp_trash->area, NULL))
11506 goto err;
11507
11508 if (!EVP_DecryptUpdate(ctx, (unsigned char *) smp_trash->area, (int *) &smp_trash->data,
11509 (unsigned char *) smp->data.u.str.area, (int) smp->data.u.str.data))
11510 goto err;
11511
11512 dec_size = base64dec(aead_tag.data.u.str.area, aead_tag.data.u.str.data, smp_trash_alloc->area, smp_trash_alloc->size);
11513 if (dec_size < 0)
11514 goto err;
11515 smp_trash_alloc->data = dec_size;
11516 dec_size = smp_trash->data;
11517
11518 EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, smp_trash_alloc->data, (void *) smp_trash_alloc->area);
11519 ret = EVP_DecryptFinal_ex(ctx, (unsigned char *) smp_trash->area + smp_trash->data, (int *) &smp_trash->data);
11520
11521 if (ret <= 0)
11522 goto err;
11523
11524 smp->data.u.str.data = dec_size + smp_trash->data;
11525 smp->data.u.str.area = smp_trash->area;
11526 smp->data.type = SMP_T_BIN;
11527 smp->flags &= ~SMP_F_CONST;
11528 free_trash_chunk(smp_trash_alloc);
11529 return 1;
11530
11531err:
11532 free_trash_chunk(smp_trash_alloc);
11533 return 0;
William Lallemand32af2032016-10-29 18:09:35 +020011534}
Nenad Merdanovicc31499d2019-03-23 11:00:32 +010011535# endif
William Lallemand32af2032016-10-29 18:09:35 +020011536
Elliot Otchet71f82972020-01-15 08:12:14 -050011537/* Argument validation functions */
11538
11539/* This function is used to validate the arguments passed to any "x_dn" ssl
11540 * keywords. These keywords support specifying a third parameter that must be
11541 * either empty or the value "rfc2253". Returns 0 on error, non-zero if OK.
11542 */
11543int val_dnfmt(struct arg *arg, char **err_msg)
11544{
11545 if (arg && arg[2].type == ARGT_STR && arg[2].data.str.data > 0 && (strcmp(arg[2].data.str.area, "rfc2253") != 0)) {
11546 memprintf(err_msg, "only rfc2253 or a blank value are currently supported as the format argument.");
11547 return 0;
11548 }
11549 return 1;
11550}
11551
William Lallemand32af2032016-10-29 18:09:35 +020011552/* register cli keywords */
11553static struct cli_kw_list cli_kws = {{ },{
11554#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
11555 { { "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 +020011556 { { "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 +020011557#endif
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +010011558 { { "set", "ssl", "ocsp-response", NULL }, NULL, cli_parse_set_ocspresponse, NULL },
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011559 { { "set", "ssl", "cert", NULL }, "set ssl cert <certfile> <payload> : replace a certificate file", cli_parse_set_cert, NULL, NULL },
11560 { { "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 +010011561 { { "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 +010011562 { { "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 +020011563 { { NULL }, NULL, NULL, NULL }
11564}};
11565
Willy Tarreau0108d902018-11-25 19:14:37 +010011566INITCALL1(STG_REGISTER, cli_register_kw, &cli_kws);
William Lallemand32af2032016-10-29 18:09:35 +020011567
Willy Tarreau7875d092012-09-10 08:20:03 +020011568/* Note: must not be declared <const> as its list will be overwritten.
11569 * Please take care of keeping this list alphabetically sorted.
11570 */
Willy Tarreaudc13c112013-06-21 23:16:39 +020011571static struct sample_fetch_kw_list sample_fetch_keywords = {ILH, {
Emeric Brun645ae792014-04-30 14:21:06 +020011572 { "ssl_bc", smp_fetch_ssl_fc, 0, NULL, SMP_T_BOOL, SMP_USE_L5SRV },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +020011573 { "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 +010011574#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Jérôme Magnine064a802018-12-03 22:21:04 +010011575 { "ssl_bc_alpn", smp_fetch_ssl_fc_alpn, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
Olivier Houchard6b77f492018-11-22 18:18:29 +010011576#endif
Emeric Brun645ae792014-04-30 14:21:06 +020011577 { "ssl_bc_cipher", smp_fetch_ssl_fc_cipher, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
Olivier Houchard6b77f492018-11-22 18:18:29 +010011578#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
11579 { "ssl_bc_npn", smp_fetch_ssl_fc_npn, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
11580#endif
Emeric Brun74f7ffa2018-02-19 16:14:12 +010011581 { "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 +020011582 { "ssl_bc_protocol", smp_fetch_ssl_fc_protocol, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
Emeric Brunb73a9b02014-04-30 18:49:19 +020011583 { "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 +020011584 { "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 +020011585#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
Emeric Brun645ae792014-04-30 14:21:06 +020011586 { "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 -040011587#endif
Emmanuel Hocdet839af572019-05-14 16:27:35 +020011588#if HA_OPENSSL_VERSION_NUMBER >= 0x10100000L
Patrick Hemmer65674662019-06-04 08:13:03 -040011589 { "ssl_bc_client_random", smp_fetch_ssl_fc_random, 0, NULL, SMP_T_BIN, SMP_USE_L5SRV },
11590 { "ssl_bc_server_random", smp_fetch_ssl_fc_random, 0, NULL, SMP_T_BIN, SMP_USE_L5SRV },
Patrick Hemmere0275472018-04-28 19:15:51 -040011591 { "ssl_bc_session_key", smp_fetch_ssl_fc_session_key, 0, NULL, SMP_T_BIN, SMP_USE_L5SRV },
11592#endif
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +020011593 { "ssl_c_ca_err", smp_fetch_ssl_c_ca_err, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
11594 { "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 +010011595 { "ssl_c_der", smp_fetch_ssl_x_der, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +020011596 { "ssl_c_err", smp_fetch_ssl_c_err, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Elliot Otchet71f82972020-01-15 08:12:14 -050011597 { "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 +020011598 { "ssl_c_key_alg", smp_fetch_ssl_x_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
11599 { "ssl_c_notafter", smp_fetch_ssl_x_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
11600 { "ssl_c_notbefore", smp_fetch_ssl_x_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
11601 { "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 -050011602 { "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 +020011603 { "ssl_c_serial", smp_fetch_ssl_x_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
11604 { "ssl_c_sha1", smp_fetch_ssl_x_sha1, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +010011605 { "ssl_c_used", smp_fetch_ssl_c_used, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +020011606 { "ssl_c_verify", smp_fetch_ssl_c_verify, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
11607 { "ssl_c_version", smp_fetch_ssl_x_version, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Emeric Brun43e79582014-10-29 19:03:26 +010011608 { "ssl_f_der", smp_fetch_ssl_x_der, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Elliot Otchet71f82972020-01-15 08:12:14 -050011609 { "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 +020011610 { "ssl_f_key_alg", smp_fetch_ssl_x_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
11611 { "ssl_f_notafter", smp_fetch_ssl_x_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
11612 { "ssl_f_notbefore", smp_fetch_ssl_x_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
11613 { "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 -050011614 { "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 +020011615 { "ssl_f_serial", smp_fetch_ssl_x_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Emeric Brun55f4fa82014-04-30 17:11:25 +020011616 { "ssl_f_sha1", smp_fetch_ssl_x_sha1, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +020011617 { "ssl_f_version", smp_fetch_ssl_x_version, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +010011618 { "ssl_fc", smp_fetch_ssl_fc, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +020011619 { "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 +010011620 { "ssl_fc_cipher", smp_fetch_ssl_fc_cipher, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +010011621 { "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 +020011622 { "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 +010011623 { "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 +020011624 { "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 +010011625#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +010011626 { "ssl_fc_npn", smp_fetch_ssl_fc_npn, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreaua33c6542012-10-15 13:19:06 +020011627#endif
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +010011628#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +010011629 { "ssl_fc_alpn", smp_fetch_ssl_fc_alpn, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreauab861d32013-04-02 02:30:41 +020011630#endif
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +010011631 { "ssl_fc_protocol", smp_fetch_ssl_fc_protocol, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreau9a1ab082019-05-09 13:26:41 +020011632#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
Emeric Brunb73a9b02014-04-30 18:49:19 +020011633 { "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 -040011634#endif
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +020011635 { "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 +020011636#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +010011637 { "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 -040011638#endif
Emmanuel Hocdet839af572019-05-14 16:27:35 +020011639#if HA_OPENSSL_VERSION_NUMBER >= 0x10100000L
Patrick Hemmer65674662019-06-04 08:13:03 -040011640 { "ssl_fc_client_random", smp_fetch_ssl_fc_random, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
11641 { "ssl_fc_server_random", smp_fetch_ssl_fc_random, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Patrick Hemmere0275472018-04-28 19:15:51 -040011642 { "ssl_fc_session_key", smp_fetch_ssl_fc_session_key, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
11643#endif
Patrick Hemmer41966772018-04-28 19:15:48 -040011644#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +010011645 { "ssl_fc_sni", smp_fetch_ssl_fc_sni, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Patrick Hemmer41966772018-04-28 19:15:48 -040011646#endif
Thierry FOURNIER5bf77322017-02-25 12:45:22 +010011647 { "ssl_fc_cipherlist_bin", smp_fetch_ssl_fc_cl_bin, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
11648 { "ssl_fc_cipherlist_hex", smp_fetch_ssl_fc_cl_hex, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
11649 { "ssl_fc_cipherlist_str", smp_fetch_ssl_fc_cl_str, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
11650 { "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 +020011651 { NULL, NULL, 0, 0, 0 },
11652}};
11653
Willy Tarreau0108d902018-11-25 19:14:37 +010011654INITCALL1(STG_REGISTER, sample_register_fetches, &sample_fetch_keywords);
11655
Willy Tarreau7875d092012-09-10 08:20:03 +020011656/* Note: must not be declared <const> as its list will be overwritten.
11657 * Please take care of keeping this list alphabetically sorted.
11658 */
Willy Tarreaudc13c112013-06-21 23:16:39 +020011659static struct acl_kw_list acl_kws = {ILH, {
Thierry FOURNIERc5a4e982014-03-05 16:07:08 +010011660 { "ssl_fc_sni_end", "ssl_fc_sni", PAT_MATCH_END },
11661 { "ssl_fc_sni_reg", "ssl_fc_sni", PAT_MATCH_REG },
Willy Tarreau8ed669b2013-01-11 15:49:37 +010011662 { /* END */ },
Willy Tarreau7875d092012-09-10 08:20:03 +020011663}};
11664
Willy Tarreau0108d902018-11-25 19:14:37 +010011665INITCALL1(STG_REGISTER, acl_register_keywords, &acl_kws);
11666
Willy Tarreau79eeafa2012-09-14 07:53:05 +020011667/* Note: must not be declared <const> as its list will be overwritten.
11668 * Please take care of keeping this list alphabetically sorted, doing so helps
11669 * all code contributors.
11670 * Optional keywords are also declared with a NULL ->parse() function so that
11671 * the config parser can report an appropriate error when a known keyword was
11672 * not enabled.
11673 */
Emmanuel Hocdet98263292016-12-29 18:26:15 +010011674static struct ssl_bind_kw ssl_bind_kws[] = {
Olivier Houchardc2aae742017-09-22 18:26:28 +020011675 { "allow-0rtt", ssl_bind_parse_allow_0rtt, 0 }, /* allow 0-RTT */
Emmanuel Hocdet98263292016-12-29 18:26:15 +010011676 { "alpn", ssl_bind_parse_alpn, 1 }, /* set ALPN supported protocols */
11677 { "ca-file", ssl_bind_parse_ca_file, 1 }, /* set CAfile to process verify on client cert */
11678 { "ciphers", ssl_bind_parse_ciphers, 1 }, /* set SSL cipher suite */
Emmanuel Hocdet839af572019-05-14 16:27:35 +020011679#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +020011680 { "ciphersuites", ssl_bind_parse_ciphersuites, 1 }, /* set TLS 1.3 cipher suite */
11681#endif
Emmanuel Hocdet98263292016-12-29 18:26:15 +010011682 { "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 +010011683 { "curves", ssl_bind_parse_curves, 1 }, /* set SSL curve suite */
Emmanuel Hocdet98263292016-12-29 18:26:15 +010011684 { "ecdhe", ssl_bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +020011685 { "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 +010011686 { "npn", ssl_bind_parse_npn, 1 }, /* set NPN supported protocols */
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +020011687 { "ssl-min-ver", ssl_bind_parse_tls_method_minmax,1 }, /* minimum version */
11688 { "ssl-max-ver", ssl_bind_parse_tls_method_minmax,1 }, /* maximum version */
Emmanuel Hocdet98263292016-12-29 18:26:15 +010011689 { "verify", ssl_bind_parse_verify, 1 }, /* set SSL verify method */
11690 { NULL, NULL, 0 },
11691};
11692
Willy Tarreau0108d902018-11-25 19:14:37 +010011693/* no initcall for ssl_bind_kws, these ones are parsed in the parser loop */
11694
Willy Tarreau51fb7652012-09-18 18:24:39 +020011695static struct bind_kw_list bind_kws = { "SSL", { }, {
Olivier Houchardc2aae742017-09-22 18:26:28 +020011696 { "allow-0rtt", bind_parse_allow_0rtt, 0 }, /* Allow 0RTT */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +020011697 { "alpn", bind_parse_alpn, 1 }, /* set ALPN supported protocols */
11698 { "ca-file", bind_parse_ca_file, 1 }, /* set CAfile to process verify on client cert */
11699 { "ca-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ignore on verify depth > 0 */
11700 { "ca-sign-file", bind_parse_ca_sign_file, 1 }, /* set CAFile used to generate and sign server certs */
11701 { "ca-sign-pass", bind_parse_ca_sign_pass, 1 }, /* set CAKey passphrase */
11702 { "ciphers", bind_parse_ciphers, 1 }, /* set SSL cipher suite */
Emmanuel Hocdet839af572019-05-14 16:27:35 +020011703#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +020011704 { "ciphersuites", bind_parse_ciphersuites, 1 }, /* set TLS 1.3 cipher suite */
11705#endif
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +020011706 { "crl-file", bind_parse_crl_file, 1 }, /* set certificat revocation list file use on client cert verify */
11707 { "crt", bind_parse_crt, 1 }, /* load SSL certificates from this location */
11708 { "crt-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ingore on verify depth == 0 */
11709 { "crt-list", bind_parse_crt_list, 1 }, /* load a list of crt from this location */
11710 { "curves", bind_parse_curves, 1 }, /* set SSL curve suite */
11711 { "ecdhe", bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
11712 { "force-sslv3", bind_parse_tls_method_options, 0 }, /* force SSLv3 */
11713 { "force-tlsv10", bind_parse_tls_method_options, 0 }, /* force TLSv10 */
11714 { "force-tlsv11", bind_parse_tls_method_options, 0 }, /* force TLSv11 */
11715 { "force-tlsv12", bind_parse_tls_method_options, 0 }, /* force TLSv12 */
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +020011716 { "force-tlsv13", bind_parse_tls_method_options, 0 }, /* force TLSv13 */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +020011717 { "generate-certificates", bind_parse_generate_certs, 0 }, /* enable the server certificates generation */
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +020011718 { "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 +020011719 { "no-sslv3", bind_parse_tls_method_options, 0 }, /* disable SSLv3 */
11720 { "no-tlsv10", bind_parse_tls_method_options, 0 }, /* disable TLSv10 */
11721 { "no-tlsv11", bind_parse_tls_method_options, 0 }, /* disable TLSv11 */
11722 { "no-tlsv12", bind_parse_tls_method_options, 0 }, /* disable TLSv12 */
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +020011723 { "no-tlsv13", bind_parse_tls_method_options, 0 }, /* disable TLSv13 */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +020011724 { "no-tls-tickets", bind_parse_no_tls_tickets, 0 }, /* disable session resumption tickets */
11725 { "ssl", bind_parse_ssl, 0 }, /* enable SSL processing */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +020011726 { "ssl-min-ver", bind_parse_tls_method_minmax, 1 }, /* minimum version */
11727 { "ssl-max-ver", bind_parse_tls_method_minmax, 1 }, /* maximum version */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +020011728 { "strict-sni", bind_parse_strict_sni, 0 }, /* refuse negotiation if sni doesn't match a certificate */
11729 { "tls-ticket-keys", bind_parse_tls_ticket_keys, 1 }, /* set file to load TLS ticket keys from */
11730 { "verify", bind_parse_verify, 1 }, /* set SSL verify method */
11731 { "npn", bind_parse_npn, 1 }, /* set NPN supported protocols */
11732 { "prefer-client-ciphers", bind_parse_pcc, 0 }, /* prefer client ciphers */
Willy Tarreau79eeafa2012-09-14 07:53:05 +020011733 { NULL, NULL, 0 },
11734}};
Emeric Brun46591952012-05-18 15:47:34 +020011735
Willy Tarreau0108d902018-11-25 19:14:37 +010011736INITCALL1(STG_REGISTER, bind_register_keywords, &bind_kws);
11737
Willy Tarreau92faadf2012-10-10 23:04:25 +020011738/* Note: must not be declared <const> as its list will be overwritten.
11739 * Please take care of keeping this list alphabetically sorted, doing so helps
11740 * all code contributors.
11741 * Optional keywords are also declared with a NULL ->parse() function so that
11742 * the config parser can report an appropriate error when a known keyword was
11743 * not enabled.
11744 */
11745static struct srv_kw_list srv_kws = { "SSL", { }, {
Olivier Houchard522eea72017-11-03 16:27:47 +010011746 { "allow-0rtt", srv_parse_allow_0rtt, 0, 1 }, /* Allow using early data on this server */
Olivier Houchardc7566002018-11-20 23:33:50 +010011747 { "alpn", srv_parse_alpn, 1, 1 }, /* Set ALPN supported protocols */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +020011748 { "ca-file", srv_parse_ca_file, 1, 1 }, /* set CAfile to process verify server cert */
Olivier Houchard92150142018-12-21 19:47:01 +010011749 { "check-alpn", srv_parse_alpn, 1, 1 }, /* Set ALPN used for checks */
Olivier Houchard9130a962017-10-17 17:33:43 +020011750 { "check-sni", srv_parse_check_sni, 1, 1 }, /* set SNI */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +020011751 { "check-ssl", srv_parse_check_ssl, 0, 1 }, /* enable SSL for health checks */
11752 { "ciphers", srv_parse_ciphers, 1, 1 }, /* select the cipher suite */
Emmanuel Hocdet839af572019-05-14 16:27:35 +020011753#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +020011754 { "ciphersuites", srv_parse_ciphersuites, 1, 1 }, /* select the cipher suite */
11755#endif
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +020011756 { "crl-file", srv_parse_crl_file, 1, 1 }, /* set certificate revocation list file use on server cert verify */
11757 { "crt", srv_parse_crt, 1, 1 }, /* set client certificate */
11758 { "force-sslv3", srv_parse_tls_method_options, 0, 1 }, /* force SSLv3 */
11759 { "force-tlsv10", srv_parse_tls_method_options, 0, 1 }, /* force TLSv10 */
11760 { "force-tlsv11", srv_parse_tls_method_options, 0, 1 }, /* force TLSv11 */
11761 { "force-tlsv12", srv_parse_tls_method_options, 0, 1 }, /* force TLSv12 */
11762 { "force-tlsv13", srv_parse_tls_method_options, 0, 1 }, /* force TLSv13 */
11763 { "no-check-ssl", srv_parse_no_check_ssl, 0, 1 }, /* disable SSL for health checks */
11764 { "no-send-proxy-v2-ssl", srv_parse_no_send_proxy_ssl, 0, 1 }, /* do not send PROXY protocol header v2 with SSL info */
11765 { "no-send-proxy-v2-ssl-cn", srv_parse_no_send_proxy_cn, 0, 1 }, /* do not send PROXY protocol header v2 with CN */
11766 { "no-ssl", srv_parse_no_ssl, 0, 1 }, /* disable SSL processing */
11767 { "no-ssl-reuse", srv_parse_no_ssl_reuse, 0, 1 }, /* disable session reuse */
11768 { "no-sslv3", srv_parse_tls_method_options, 0, 0 }, /* disable SSLv3 */
11769 { "no-tlsv10", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv10 */
11770 { "no-tlsv11", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv11 */
11771 { "no-tlsv12", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv12 */
11772 { "no-tlsv13", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv13 */
11773 { "no-tls-tickets", srv_parse_no_tls_tickets, 0, 1 }, /* disable session resumption tickets */
Olivier Houchardc7566002018-11-20 23:33:50 +010011774 { "npn", srv_parse_npn, 1, 1 }, /* Set NPN supported protocols */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +020011775 { "send-proxy-v2-ssl", srv_parse_send_proxy_ssl, 0, 1 }, /* send PROXY protocol header v2 with SSL info */
11776 { "send-proxy-v2-ssl-cn", srv_parse_send_proxy_cn, 0, 1 }, /* send PROXY protocol header v2 with CN */
11777 { "sni", srv_parse_sni, 1, 1 }, /* send SNI extension */
11778 { "ssl", srv_parse_ssl, 0, 1 }, /* enable SSL processing */
11779 { "ssl-min-ver", srv_parse_tls_method_minmax, 1, 1 }, /* minimum version */
11780 { "ssl-max-ver", srv_parse_tls_method_minmax, 1, 1 }, /* maximum version */
11781 { "ssl-reuse", srv_parse_ssl_reuse, 0, 1 }, /* enable session reuse */
11782 { "tls-tickets", srv_parse_tls_tickets, 0, 1 }, /* enable session resumption tickets */
11783 { "verify", srv_parse_verify, 1, 1 }, /* set SSL verify method */
11784 { "verifyhost", srv_parse_verifyhost, 1, 1 }, /* require that SSL cert verifies for hostname */
Willy Tarreau92faadf2012-10-10 23:04:25 +020011785 { NULL, NULL, 0, 0 },
11786}};
11787
Willy Tarreau0108d902018-11-25 19:14:37 +010011788INITCALL1(STG_REGISTER, srv_register_keywords, &srv_kws);
11789
Emeric Brun2c86cbf2014-10-30 15:56:50 +010011790static struct cfg_kw_list cfg_kws = {ILH, {
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +010011791 { CFG_GLOBAL, "ca-base", ssl_parse_global_ca_crt_base },
11792 { CFG_GLOBAL, "crt-base", ssl_parse_global_ca_crt_base },
Emmanuel Hocdet70df7bf2019-01-04 11:08:20 +010011793 { CFG_GLOBAL, "issuers-chain-path", ssl_load_global_issuers_from_path },
Willy Tarreau0bea58d2016-12-21 23:17:25 +010011794 { CFG_GLOBAL, "maxsslconn", ssl_parse_global_int },
Emeric Brun2c86cbf2014-10-30 15:56:50 +010011795 { CFG_GLOBAL, "ssl-default-bind-options", ssl_parse_default_bind_options },
11796 { CFG_GLOBAL, "ssl-default-server-options", ssl_parse_default_server_options },
Willy Tarreau14e36a12016-12-21 23:28:13 +010011797#ifndef OPENSSL_NO_DH
11798 { CFG_GLOBAL, "ssl-dh-param-file", ssl_parse_global_dh_param_file },
11799#endif
Grant Zhangfa6c7ee2017-01-14 01:42:15 +000011800 { CFG_GLOBAL, "ssl-mode-async", ssl_parse_global_ssl_async },
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020011801#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +000011802 { CFG_GLOBAL, "ssl-engine", ssl_parse_global_ssl_engine },
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020011803#endif
Willy Tarreau9ceda382016-12-21 23:13:03 +010011804 { CFG_GLOBAL, "tune.ssl.cachesize", ssl_parse_global_int },
11805#ifndef OPENSSL_NO_DH
11806 { CFG_GLOBAL, "tune.ssl.default-dh-param", ssl_parse_global_default_dh },
11807#endif
11808 { CFG_GLOBAL, "tune.ssl.force-private-cache", ssl_parse_global_private_cache },
11809 { CFG_GLOBAL, "tune.ssl.lifetime", ssl_parse_global_lifetime },
11810 { CFG_GLOBAL, "tune.ssl.maxrecord", ssl_parse_global_int },
11811 { CFG_GLOBAL, "tune.ssl.ssl-ctx-cache-size", ssl_parse_global_int },
Thierry FOURNIER5bf77322017-02-25 12:45:22 +010011812 { CFG_GLOBAL, "tune.ssl.capture-cipherlist-size", ssl_parse_global_capture_cipherlist },
Willy Tarreauf22e9682016-12-21 23:23:19 +010011813 { CFG_GLOBAL, "ssl-default-bind-ciphers", ssl_parse_global_ciphers },
11814 { CFG_GLOBAL, "ssl-default-server-ciphers", ssl_parse_global_ciphers },
Emmanuel Hocdet839af572019-05-14 16:27:35 +020011815#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +020011816 { CFG_GLOBAL, "ssl-default-bind-ciphersuites", ssl_parse_global_ciphersuites },
11817 { CFG_GLOBAL, "ssl-default-server-ciphersuites", ssl_parse_global_ciphersuites },
11818#endif
William Lallemand3af48e72020-02-03 17:15:52 +010011819 { CFG_GLOBAL, "ssl-load-extra-files", ssl_parse_global_extra_files },
Emeric Brun2c86cbf2014-10-30 15:56:50 +010011820 { 0, NULL, NULL },
11821}};
11822
Willy Tarreau0108d902018-11-25 19:14:37 +010011823INITCALL1(STG_REGISTER, cfg_register_keywords, &cfg_kws);
11824
Nenad Merdanovicc31499d2019-03-23 11:00:32 +010011825/* Note: must not be declared <const> as its list will be overwritten */
11826static struct sample_conv_kw_list conv_kws = {ILH, {
Willy Tarreau86a394e2019-05-09 14:15:32 +020011827#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000100fL)
Nenad Merdanovicc31499d2019-03-23 11:00:32 +010011828 { "aes_gcm_dec", sample_conv_aes_gcm_dec, ARG4(4,SINT,STR,STR,STR), check_aes_gcm, SMP_T_BIN, SMP_T_BIN },
11829#endif
11830 { NULL, NULL, 0, 0, 0 },
11831}};
11832
11833INITCALL1(STG_REGISTER, sample_register_convs, &conv_kws);
11834
Willy Tarreauf7bc57c2012-10-03 00:19:48 +020011835/* transport-layer operations for SSL sockets */
Willy Tarreaud9f5cca2016-12-22 21:08:52 +010011836static struct xprt_ops ssl_sock = {
Emeric Brun46591952012-05-18 15:47:34 +020011837 .snd_buf = ssl_sock_from_buf,
11838 .rcv_buf = ssl_sock_to_buf,
Olivier Houcharddf357842019-03-21 16:30:07 +010011839 .subscribe = ssl_subscribe,
11840 .unsubscribe = ssl_unsubscribe,
Olivier Houchard5149b592019-05-23 17:47:36 +020011841 .remove_xprt = ssl_remove_xprt,
Olivier Houchard2e055482019-05-27 19:50:12 +020011842 .add_xprt = ssl_add_xprt,
Emeric Brun46591952012-05-18 15:47:34 +020011843 .rcv_pipe = NULL,
11844 .snd_pipe = NULL,
11845 .shutr = NULL,
11846 .shutw = ssl_sock_shutw,
11847 .close = ssl_sock_close,
11848 .init = ssl_sock_init,
Willy Tarreau55d37912016-12-21 23:38:39 +010011849 .prepare_bind_conf = ssl_sock_prepare_bind_conf,
Willy Tarreau795cdab2016-12-22 17:30:54 +010011850 .destroy_bind_conf = ssl_sock_destroy_bind_conf,
Willy Tarreau17d45382016-12-22 21:16:08 +010011851 .prepare_srv = ssl_sock_prepare_srv_ctx,
11852 .destroy_srv = ssl_sock_free_srv_ctx,
Willy Tarreau8743f7e2016-12-04 18:44:29 +010011853 .get_alpn = ssl_sock_get_alpn,
Willy Tarreau8e0bb0a2016-11-24 16:58:12 +010011854 .name = "SSL",
Emeric Brun46591952012-05-18 15:47:34 +020011855};
11856
Olivier Houchardccaa7de2017-10-02 11:51:03 +020011857enum act_return ssl_action_wait_for_hs(struct act_rule *rule, struct proxy *px,
11858 struct session *sess, struct stream *s, int flags)
11859{
11860 struct connection *conn;
Olivier Houchard6fa63d92017-11-27 18:41:32 +010011861 struct conn_stream *cs;
Olivier Houchardccaa7de2017-10-02 11:51:03 +020011862
11863 conn = objt_conn(sess->origin);
Olivier Houchard6fa63d92017-11-27 18:41:32 +010011864 cs = objt_cs(s->si[0].end);
Olivier Houchardccaa7de2017-10-02 11:51:03 +020011865
Olivier Houchard6fa63d92017-11-27 18:41:32 +010011866 if (conn && cs) {
Olivier Houchardccaa7de2017-10-02 11:51:03 +020011867 if (conn->flags & (CO_FL_EARLY_SSL_HS | CO_FL_SSL_WAIT_HS)) {
Olivier Houchard6fa63d92017-11-27 18:41:32 +010011868 cs->flags |= CS_FL_WAIT_FOR_HS;
Olivier Houchardccaa7de2017-10-02 11:51:03 +020011869 s->req.flags |= CF_READ_NULL;
11870 return ACT_RET_YIELD;
11871 }
11872 }
11873 return (ACT_RET_CONT);
11874}
11875
11876static enum act_parse_ret ssl_parse_wait_for_hs(const char **args, int *orig_arg, struct proxy *px, struct act_rule *rule, char **err)
11877{
11878 rule->action_ptr = ssl_action_wait_for_hs;
11879
11880 return ACT_RET_PRS_OK;
11881}
11882
11883static struct action_kw_list http_req_actions = {ILH, {
11884 { "wait-for-handshake", ssl_parse_wait_for_hs },
11885 { /* END */ }
11886}};
11887
Willy Tarreau0108d902018-11-25 19:14:37 +010011888INITCALL1(STG_REGISTER, http_req_keywords_register, &http_req_actions);
11889
Willy Tarreau5db847a2019-05-09 14:13:35 +020011890#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +010011891
11892static void ssl_sock_sctl_free_func(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, long argl, void *argp)
11893{
11894 if (ptr) {
11895 chunk_destroy(ptr);
11896 free(ptr);
11897 }
11898}
11899
11900#endif
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +010011901static void ssl_sock_capture_free_func(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, long argl, void *argp)
11902{
Willy Tarreaubafbe012017-11-24 17:34:44 +010011903 pool_free(pool_head_ssl_capture, ptr);
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +010011904}
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +010011905
Emeric Brun46591952012-05-18 15:47:34 +020011906__attribute__((constructor))
Willy Tarreau92faadf2012-10-10 23:04:25 +020011907static void __ssl_sock_init(void)
11908{
Ilya Shipitsin0590f442019-05-25 19:30:50 +050011909#if (!defined(OPENSSL_NO_COMP) && !defined(SSL_OP_NO_COMPRESSION))
Emeric Brun46591952012-05-18 15:47:34 +020011910 STACK_OF(SSL_COMP)* cm;
Ilya Shipitsine242f3d2019-05-25 03:38:14 +050011911 int n;
Ilya Shipitsin0590f442019-05-25 19:30:50 +050011912#endif
Emeric Brun46591952012-05-18 15:47:34 +020011913
Willy Tarreauef934602016-12-22 23:12:01 +010011914 if (global_ssl.listen_default_ciphers)
11915 global_ssl.listen_default_ciphers = strdup(global_ssl.listen_default_ciphers);
11916 if (global_ssl.connect_default_ciphers)
11917 global_ssl.connect_default_ciphers = strdup(global_ssl.connect_default_ciphers);
Emmanuel Hocdet839af572019-05-14 16:27:35 +020011918#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +020011919 if (global_ssl.listen_default_ciphersuites)
11920 global_ssl.listen_default_ciphersuites = strdup(global_ssl.listen_default_ciphersuites);
11921 if (global_ssl.connect_default_ciphersuites)
11922 global_ssl.connect_default_ciphersuites = strdup(global_ssl.connect_default_ciphersuites);
11923#endif
Willy Tarreau610f04b2014-02-13 11:36:41 +010011924
Willy Tarreau13e14102016-12-22 20:25:26 +010011925 xprt_register(XPRT_SSL, &ssl_sock);
Willy Tarreau9a1ab082019-05-09 13:26:41 +020011926#if HA_OPENSSL_VERSION_NUMBER < 0x10100000L
Emeric Brun46591952012-05-18 15:47:34 +020011927 SSL_library_init();
Rosen Penev68185952018-12-14 08:47:02 -080011928#endif
Ilya Shipitsin0590f442019-05-25 19:30:50 +050011929#if (!defined(OPENSSL_NO_COMP) && !defined(SSL_OP_NO_COMPRESSION))
Emeric Brun46591952012-05-18 15:47:34 +020011930 cm = SSL_COMP_get_compression_methods();
Ilya Shipitsine242f3d2019-05-25 03:38:14 +050011931 n = sk_SSL_COMP_num(cm);
11932 while (n--) {
11933 (void) sk_SSL_COMP_pop(cm);
11934 }
Ilya Shipitsin0590f442019-05-25 19:30:50 +050011935#endif
Ilya Shipitsine242f3d2019-05-25 03:38:14 +050011936
Willy Tarreau5db847a2019-05-09 14:13:35 +020011937#if defined(USE_THREAD) && (HA_OPENSSL_VERSION_NUMBER < 0x10100000L)
Emeric Brun821bb9b2017-06-15 16:37:39 +020011938 ssl_locking_init();
11939#endif
Willy Tarreau5db847a2019-05-09 14:13:35 +020011940#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +010011941 sctl_ex_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, ssl_sock_sctl_free_func);
11942#endif
Thierry FOURNIER28962c92018-06-17 21:37:05 +020011943 ssl_app_data_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL);
Thierry FOURNIER16ff0502018-06-17 21:33:01 +020011944 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 +020011945#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +000011946 ENGINE_load_builtin_engines();
Grant Zhangfa6c7ee2017-01-14 01:42:15 +000011947 hap_register_post_check(ssl_check_async_engine_count);
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020011948#endif
Willy Tarreaud1c57502016-12-22 22:46:15 +010011949#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
11950 hap_register_post_check(tlskeys_finalize_config);
11951#endif
Willy Tarreau80713382018-11-26 10:19:54 +010011952
11953 global.ssl_session_max_cost = SSL_SESSION_MAX_COST;
11954 global.ssl_handshake_max_cost = SSL_HANDSHAKE_MAX_COST;
11955
Emmanuel Hocdet70df7bf2019-01-04 11:08:20 +010011956 hap_register_post_deinit(ssl_free_global_issuers);
11957
Willy Tarreau80713382018-11-26 10:19:54 +010011958#ifndef OPENSSL_NO_DH
11959 ssl_dh_ptr_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, NULL);
11960 hap_register_post_deinit(ssl_free_dh);
11961#endif
11962#ifndef OPENSSL_NO_ENGINE
11963 hap_register_post_deinit(ssl_free_engines);
11964#endif
11965 /* Load SSL string for the verbose & debug mode. */
11966 ERR_load_SSL_strings();
Olivier Houcharda8955d52019-04-07 22:00:38 +020011967 ha_meth = BIO_meth_new(0x666, "ha methods");
11968 BIO_meth_set_write(ha_meth, ha_ssl_write);
11969 BIO_meth_set_read(ha_meth, ha_ssl_read);
11970 BIO_meth_set_ctrl(ha_meth, ha_ssl_ctrl);
11971 BIO_meth_set_create(ha_meth, ha_ssl_new);
11972 BIO_meth_set_destroy(ha_meth, ha_ssl_free);
11973 BIO_meth_set_puts(ha_meth, ha_ssl_puts);
11974 BIO_meth_set_gets(ha_meth, ha_ssl_gets);
William Lallemand150bfa82019-09-19 17:12:49 +020011975
11976 HA_SPIN_INIT(&ckch_lock);
Willy Tarreau80713382018-11-26 10:19:54 +010011977}
Willy Tarreaud92aa5c2015-01-15 21:34:39 +010011978
Willy Tarreau80713382018-11-26 10:19:54 +010011979/* Compute and register the version string */
11980static void ssl_register_build_options()
11981{
11982 char *ptr = NULL;
11983 int i;
11984
Willy Tarreauc2c0b612016-12-21 19:23:20 +010011985 memprintf(&ptr, "Built with OpenSSL version : "
11986#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet50e25e12017-03-24 15:20:03 +010011987 "BoringSSL");
Willy Tarreauc2c0b612016-12-21 19:23:20 +010011988#else /* OPENSSL_IS_BORINGSSL */
11989 OPENSSL_VERSION_TEXT
11990 "\nRunning on OpenSSL version : %s%s",
Rosen Penev68185952018-12-14 08:47:02 -080011991 OpenSSL_version(OPENSSL_VERSION),
Willy Tarreau1d158ab2019-05-09 13:41:45 +020011992 ((OPENSSL_VERSION_NUMBER ^ OpenSSL_version_num()) >> 8) ? " (VERSIONS DIFFER!)" : "");
Willy Tarreauc2c0b612016-12-21 19:23:20 +010011993#endif
11994 memprintf(&ptr, "%s\nOpenSSL library supports TLS extensions : "
Willy Tarreau9a1ab082019-05-09 13:26:41 +020011995#if HA_OPENSSL_VERSION_NUMBER < 0x00907000L
Willy Tarreauc2c0b612016-12-21 19:23:20 +010011996 "no (library version too old)"
11997#elif defined(OPENSSL_NO_TLSEXT)
11998 "no (disabled via OPENSSL_NO_TLSEXT)"
11999#else
12000 "yes"
12001#endif
12002 "", ptr);
12003
12004 memprintf(&ptr, "%s\nOpenSSL library supports SNI : "
12005#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
12006 "yes"
12007#else
12008#ifdef OPENSSL_NO_TLSEXT
12009 "no (because of OPENSSL_NO_TLSEXT)"
12010#else
12011 "no (version might be too old, 0.9.8f min needed)"
12012#endif
12013#endif
12014 "", ptr);
12015
Emmanuel Hocdetf80bc242017-07-12 14:25:38 +020012016 memprintf(&ptr, "%s\nOpenSSL library supports :", ptr);
12017 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
12018 if (methodVersions[i].option)
12019 memprintf(&ptr, "%s %s", ptr, methodVersions[i].name);
Emmanuel Hocdet50e25e12017-03-24 15:20:03 +010012020
Willy Tarreauc2c0b612016-12-21 19:23:20 +010012021 hap_register_build_opts(ptr, 1);
Willy Tarreau80713382018-11-26 10:19:54 +010012022}
Willy Tarreauc2c0b612016-12-21 19:23:20 +010012023
Willy Tarreau80713382018-11-26 10:19:54 +010012024INITCALL0(STG_REGISTER, ssl_register_build_options);
Remi Gacogne4f902b82015-05-28 16:23:00 +020012025
Emeric Brun46591952012-05-18 15:47:34 +020012026
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020012027#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +000012028void ssl_free_engines(void) {
12029 struct ssl_engine_list *wl, *wlb;
12030 /* free up engine list */
12031 list_for_each_entry_safe(wl, wlb, &openssl_engines, list) {
12032 ENGINE_finish(wl->e);
12033 ENGINE_free(wl->e);
12034 LIST_DEL(&wl->list);
12035 free(wl);
12036 }
12037}
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020012038#endif
Christopher Faulet31af49d2015-06-09 17:29:50 +020012039
Remi Gacogned3a23c32015-05-28 16:39:47 +020012040#ifndef OPENSSL_NO_DH
Grant Zhang872f9c22017-01-21 01:10:18 +000012041void ssl_free_dh(void) {
12042 if (local_dh_1024) {
12043 DH_free(local_dh_1024);
12044 local_dh_1024 = NULL;
12045 }
12046 if (local_dh_2048) {
12047 DH_free(local_dh_2048);
12048 local_dh_2048 = NULL;
12049 }
12050 if (local_dh_4096) {
12051 DH_free(local_dh_4096);
12052 local_dh_4096 = NULL;
12053 }
Remi Gacogne47783ef2015-05-29 15:53:22 +020012054 if (global_dh) {
12055 DH_free(global_dh);
12056 global_dh = NULL;
12057 }
Grant Zhang872f9c22017-01-21 01:10:18 +000012058}
12059#endif
12060
12061__attribute__((destructor))
12062static void __ssl_sock_deinit(void)
12063{
12064#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Emeric Brun821bb9b2017-06-15 16:37:39 +020012065 if (ssl_ctx_lru_tree) {
12066 lru64_destroy(ssl_ctx_lru_tree);
Christopher Faulet2a944ee2017-11-07 10:42:54 +010012067 HA_RWLOCK_DESTROY(&ssl_ctx_lru_rwlock);
Emeric Brun821bb9b2017-06-15 16:37:39 +020012068 }
Remi Gacogned3a23c32015-05-28 16:39:47 +020012069#endif
12070
Willy Tarreau5db847a2019-05-09 14:13:35 +020012071#if (HA_OPENSSL_VERSION_NUMBER < 0x10100000L)
Remi Gacogned3a23c32015-05-28 16:39:47 +020012072 ERR_remove_state(0);
12073 ERR_free_strings();
12074
12075 EVP_cleanup();
Rosen Penev68185952018-12-14 08:47:02 -080012076#endif
Remi Gacogned3a23c32015-05-28 16:39:47 +020012077
Willy Tarreau5db847a2019-05-09 14:13:35 +020012078#if (HA_OPENSSL_VERSION_NUMBER >= 0x00907000L) && (HA_OPENSSL_VERSION_NUMBER < 0x10100000L)
Remi Gacogned3a23c32015-05-28 16:39:47 +020012079 CRYPTO_cleanup_all_ex_data();
12080#endif
Olivier Houcharda8955d52019-04-07 22:00:38 +020012081 BIO_meth_free(ha_meth);
Remi Gacogned3a23c32015-05-28 16:39:47 +020012082}
12083
12084
Emeric Brun46591952012-05-18 15:47:34 +020012085/*
12086 * Local variables:
12087 * c-indent-level: 8
12088 * c-basic-offset: 8
12089 * End:
12090 */