blob: ef3091e3c3319098ac36df341e5a2882461a9148 [file] [log] [blame]
yanbzhu08ce6ab2015-12-02 13:01:29 -05001
Emeric Brun46591952012-05-18 15:47:34 +02002/*
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02003 * SSL/TLS transport layer over SOCK_STREAM sockets
Emeric Brun46591952012-05-18 15:47:34 +02004 *
5 * Copyright (C) 2012 EXCELIANCE, Emeric Brun <ebrun@exceliance.fr>
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version
10 * 2 of the License, or (at your option) any later version.
11 *
Willy Tarreau69845df2012-09-10 09:43:09 +020012 * Acknowledgement:
13 * We'd like to specially thank the Stud project authors for a very clean
14 * and well documented code which helped us understand how the OpenSSL API
15 * ought to be used in non-blocking mode. This is one difficult part which
16 * is not easy to get from the OpenSSL doc, and reading the Stud code made
17 * it much more obvious than the examples in the OpenSSL package. Keep up
18 * the good works, guys !
19 *
20 * Stud is an extremely efficient and scalable SSL/TLS proxy which combines
21 * particularly well with haproxy. For more info about this project, visit :
22 * https://github.com/bumptech/stud
23 *
Emeric Brun46591952012-05-18 15:47:34 +020024 */
25
Willy Tarreau8d164dc2019-05-10 09:35:00 +020026/* Note: do NOT include openssl/xxx.h here, do it in openssl-compat.h */
Emeric Brun46591952012-05-18 15:47:34 +020027#define _GNU_SOURCE
Emeric Brunfc0421f2012-09-07 17:30:07 +020028#include <ctype.h>
29#include <dirent.h>
Emeric Brun46591952012-05-18 15:47:34 +020030#include <errno.h>
31#include <fcntl.h>
32#include <stdio.h>
33#include <stdlib.h>
Emeric Brunfc0421f2012-09-07 17:30:07 +020034#include <string.h>
35#include <unistd.h>
Emeric Brun46591952012-05-18 15:47:34 +020036
37#include <sys/socket.h>
38#include <sys/stat.h>
39#include <sys/types.h>
Christopher Faulet31af49d2015-06-09 17:29:50 +020040#include <netdb.h>
Emeric Brun46591952012-05-18 15:47:34 +020041#include <netinet/tcp.h>
42
Christopher Faulet31af49d2015-06-09 17:29:50 +020043#include <import/lru.h>
44#include <import/xxhash.h>
45
Emeric Brun46591952012-05-18 15:47:34 +020046#include <common/buffer.h>
Willy Tarreau843b7cb2018-07-13 10:54:26 +020047#include <common/chunk.h>
Emeric Brun46591952012-05-18 15:47:34 +020048#include <common/compat.h>
49#include <common/config.h>
50#include <common/debug.h>
Willy Tarreau79eeafa2012-09-14 07:53:05 +020051#include <common/errors.h>
Willy Tarreau0108d902018-11-25 19:14:37 +010052#include <common/initcall.h>
Willy Tarreau55994562019-05-09 14:52:44 +020053#include <common/openssl-compat.h>
Emeric Brun46591952012-05-18 15:47:34 +020054#include <common/standard.h>
55#include <common/ticks.h>
56#include <common/time.h>
Emeric Brun2c86cbf2014-10-30 15:56:50 +010057#include <common/cfgparse.h>
Nenad Merdanovic05552d42015-02-27 19:56:49 +010058#include <common/base64.h>
Emeric Brun46591952012-05-18 15:47:34 +020059
Emeric Brunfc0421f2012-09-07 17:30:07 +020060#include <ebsttree.h>
61
William Lallemand32af2032016-10-29 18:09:35 +020062#include <types/applet.h>
63#include <types/cli.h>
Emeric Brunfc0421f2012-09-07 17:30:07 +020064#include <types/global.h>
65#include <types/ssl_sock.h>
William Lallemand32af2032016-10-29 18:09:35 +020066#include <types/stats.h>
Emeric Brunfc0421f2012-09-07 17:30:07 +020067
Willy Tarreau7875d092012-09-10 08:20:03 +020068#include <proto/acl.h>
69#include <proto/arg.h>
William Lallemand32af2032016-10-29 18:09:35 +020070#include <proto/channel.h>
Emeric Brun46591952012-05-18 15:47:34 +020071#include <proto/connection.h>
William Lallemand32af2032016-10-29 18:09:35 +020072#include <proto/cli.h>
Emeric Brun46591952012-05-18 15:47:34 +020073#include <proto/fd.h>
74#include <proto/freq_ctr.h>
75#include <proto/frontend.h>
Willy Tarreau61c112a2018-10-02 16:43:32 +020076#include <proto/http_rules.h>
Willy Tarreau79eeafa2012-09-14 07:53:05 +020077#include <proto/listener.h>
Thierry FOURNIERed66c292013-11-28 11:05:19 +010078#include <proto/pattern.h>
Christopher Faulet31af49d2015-06-09 17:29:50 +020079#include <proto/proto_tcp.h>
Christopher Fauletfc9cfe42019-07-16 14:54:53 +020080#include <proto/http_ana.h>
Willy Tarreau92faadf2012-10-10 23:04:25 +020081#include <proto/server.h>
William Lallemand32af2032016-10-29 18:09:35 +020082#include <proto/stream_interface.h>
Emeric Brun46591952012-05-18 15:47:34 +020083#include <proto/log.h>
Emeric Brun94324a42012-10-11 14:00:19 +020084#include <proto/proxy.h>
Emeric Brunfc0421f2012-09-07 17:30:07 +020085#include <proto/shctx.h>
Emeric Brun46591952012-05-18 15:47:34 +020086#include <proto/ssl_sock.h>
Willy Tarreau9ad7bd42015-04-03 19:19:59 +020087#include <proto/stream.h>
Emeric Brun46591952012-05-18 15:47:34 +020088#include <proto/task.h>
Nenad Merdanovicc31499d2019-03-23 11:00:32 +010089#include <proto/vars.h>
Emeric Brun46591952012-05-18 15:47:34 +020090
Willy Tarreau9356dac2019-05-10 09:22:53 +020091/* ***** READ THIS before adding code here! *****
92 *
93 * Due to API incompatibilities between multiple OpenSSL versions and their
94 * derivatives, it's often tempting to add macros to (re-)define certain
95 * symbols. Please do not do this here, and do it in common/openssl-compat.h
96 * exclusively so that the whole code consistently uses the same macros.
97 *
98 * Whenever possible if a macro is missing in certain versions, it's better
99 * to conditionally define it in openssl-compat.h than using lots of ifdefs.
100 */
101
Willy Tarreau518cedd2014-02-17 15:43:01 +0100102/* Warning, these are bits, not integers! */
Emeric Brune64aef12012-09-21 13:15:06 +0200103#define SSL_SOCK_ST_FL_VERIFY_DONE 0x00000001
Emeric Brund8b2bb52014-01-28 15:43:53 +0100104#define SSL_SOCK_ST_FL_16K_WBFSIZE 0x00000002
Willy Tarreau518cedd2014-02-17 15:43:01 +0100105#define SSL_SOCK_SEND_UNLIMITED 0x00000004
Emeric Brun29f037d2014-04-25 19:05:36 +0200106#define SSL_SOCK_RECV_HEARTBEAT 0x00000008
107
Emeric Brunf282a812012-09-21 15:27:54 +0200108/* bits 0xFFFF0000 are reserved to store verify errors */
109
110/* Verify errors macros */
111#define SSL_SOCK_CA_ERROR_TO_ST(e) (((e > 63) ? 63 : e) << (16))
112#define SSL_SOCK_CAEDEPTH_TO_ST(d) (((d > 15) ? 15 : d) << (6+16))
113#define SSL_SOCK_CRTERROR_TO_ST(e) (((e > 63) ? 63 : e) << (4+6+16))
114
115#define SSL_SOCK_ST_TO_CA_ERROR(s) ((s >> (16)) & 63)
116#define SSL_SOCK_ST_TO_CAEDEPTH(s) ((s >> (6+16)) & 15)
117#define SSL_SOCK_ST_TO_CRTERROR(s) ((s >> (4+6+16)) & 63)
Emeric Brune64aef12012-09-21 13:15:06 +0200118
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200119/* ssl_methods flags for ssl options */
120#define MC_SSL_O_ALL 0x0000
121#define MC_SSL_O_NO_SSLV3 0x0001 /* disable SSLv3 */
122#define MC_SSL_O_NO_TLSV10 0x0002 /* disable TLSv10 */
123#define MC_SSL_O_NO_TLSV11 0x0004 /* disable TLSv11 */
124#define MC_SSL_O_NO_TLSV12 0x0008 /* disable TLSv12 */
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +0200125#define MC_SSL_O_NO_TLSV13 0x0010 /* disable TLSv13 */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200126
William Lallemand3af48e72020-02-03 17:15:52 +0100127/* file to guess during file loading */
128#define SSL_GF_NONE 0x00000000 /* Don't guess any file, only open the files specified in the configuration files */
129#define SSL_GF_BUNDLE 0x00000001 /* try to open the bundles */
130#define SSL_GF_SCTL 0x00000002 /* try to open the .sctl file */
131#define SSL_GF_OCSP 0x00000004 /* try to open the .ocsp file */
132#define SSL_GF_OCSP_ISSUER 0x00000008 /* try to open the .issuer file if an OCSP file was loaded */
William Lallemand4c5adbf2020-02-24 14:23:22 +0100133#define SSL_GF_KEY 0x00000010 /* try to open the .key file to load a private key */
William Lallemand3af48e72020-02-03 17:15:52 +0100134
William Lallemand4c5adbf2020-02-24 14:23:22 +0100135#define SSL_GF_ALL (SSL_GF_BUNDLE|SSL_GF_SCTL|SSL_GF_OCSP|SSL_GF_OCSP_ISSUER|SSL_GF_KEY)
William Lallemand3af48e72020-02-03 17:15:52 +0100136
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200137/* ssl_methods versions */
138enum {
139 CONF_TLSV_NONE = 0,
140 CONF_TLSV_MIN = 1,
141 CONF_SSLV3 = 1,
142 CONF_TLSV10 = 2,
143 CONF_TLSV11 = 3,
144 CONF_TLSV12 = 4,
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +0200145 CONF_TLSV13 = 5,
146 CONF_TLSV_MAX = 5,
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200147};
148
Emeric Brun850efd52014-01-29 12:24:34 +0100149/* server and bind verify method, it uses a global value as default */
150enum {
151 SSL_SOCK_VERIFY_DEFAULT = 0,
152 SSL_SOCK_VERIFY_REQUIRED = 1,
153 SSL_SOCK_VERIFY_OPTIONAL = 2,
154 SSL_SOCK_VERIFY_NONE = 3,
155};
156
Willy Tarreau71b734c2014-01-28 15:19:44 +0100157int sslconns = 0;
158int totalsslconns = 0;
Willy Tarreaud9f5cca2016-12-22 21:08:52 +0100159static struct xprt_ops ssl_sock;
Emeric Brunece0c332017-12-06 13:51:49 +0100160int nb_engines = 0;
Emeric Brune1f38db2012-09-03 20:36:47 +0200161
William Lallemande0f3fd52020-02-25 14:53:06 +0100162static struct eb_root cert_issuer_tree = EB_ROOT; /* issuers tree from "issuers-chain-path" */
Emmanuel Hocdet75a7aa12020-02-18 15:19:24 +0100163static struct issuer_chain* ssl_get_issuer_chain(X509 *cert);
William Lallemande0f3fd52020-02-25 14:53:06 +0100164
Willy Tarreauef934602016-12-22 23:12:01 +0100165static struct {
166 char *crt_base; /* base directory path for certificates */
167 char *ca_base; /* base directory path for CAs and CRLs */
Emmanuel Hocdet70df7bf2019-01-04 11:08:20 +0100168 char *issuers_chain_path; /* from "issuers-chain-path" */
Emmanuel Hocdet70df7bf2019-01-04 11:08:20 +0100169
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000170 int async; /* whether we use ssl async mode */
Willy Tarreauef934602016-12-22 23:12:01 +0100171
172 char *listen_default_ciphers;
173 char *connect_default_ciphers;
Emmanuel Hocdet839af572019-05-14 16:27:35 +0200174#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +0200175 char *listen_default_ciphersuites;
176 char *connect_default_ciphersuites;
177#endif
Willy Tarreauef934602016-12-22 23:12:01 +0100178 int listen_default_ssloptions;
179 int connect_default_ssloptions;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200180 struct tls_version_filter listen_default_sslmethods;
181 struct tls_version_filter connect_default_sslmethods;
Willy Tarreauef934602016-12-22 23:12:01 +0100182
183 int private_cache; /* Force to use a private session cache even if nbproc > 1 */
184 unsigned int life_time; /* SSL session lifetime in seconds */
185 unsigned int max_record; /* SSL max record size */
186 unsigned int default_dh_param; /* SSL maximum DH parameter size */
187 int ctx_cache; /* max number of entries in the ssl_ctx cache. */
Thierry FOURNIER5bf77322017-02-25 12:45:22 +0100188 int capture_cipherlist; /* Size of the cipherlist buffer. */
William Lallemand3af48e72020-02-03 17:15:52 +0100189 int extra_files; /* which files not defined in the configuration file are we looking for */
Willy Tarreauef934602016-12-22 23:12:01 +0100190} global_ssl = {
191#ifdef LISTEN_DEFAULT_CIPHERS
192 .listen_default_ciphers = LISTEN_DEFAULT_CIPHERS,
193#endif
194#ifdef CONNECT_DEFAULT_CIPHERS
195 .connect_default_ciphers = CONNECT_DEFAULT_CIPHERS,
196#endif
Emmanuel Hocdet839af572019-05-14 16:27:35 +0200197#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +0200198#ifdef LISTEN_DEFAULT_CIPHERSUITES
199 .listen_default_ciphersuites = LISTEN_DEFAULT_CIPHERSUITES,
200#endif
201#ifdef CONNECT_DEFAULT_CIPHERSUITES
202 .connect_default_ciphersuites = CONNECT_DEFAULT_CIPHERSUITES,
203#endif
204#endif
Willy Tarreauef934602016-12-22 23:12:01 +0100205 .listen_default_ssloptions = BC_SSL_O_NONE,
206 .connect_default_ssloptions = SRV_SSL_O_NONE,
207
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200208 .listen_default_sslmethods.flags = MC_SSL_O_ALL,
209 .listen_default_sslmethods.min = CONF_TLSV_NONE,
210 .listen_default_sslmethods.max = CONF_TLSV_NONE,
211 .connect_default_sslmethods.flags = MC_SSL_O_ALL,
212 .connect_default_sslmethods.min = CONF_TLSV_NONE,
213 .connect_default_sslmethods.max = CONF_TLSV_NONE,
214
Willy Tarreauef934602016-12-22 23:12:01 +0100215#ifdef DEFAULT_SSL_MAX_RECORD
216 .max_record = DEFAULT_SSL_MAX_RECORD,
217#endif
218 .default_dh_param = SSL_DEFAULT_DH_PARAM,
219 .ctx_cache = DEFAULT_SSL_CTX_CACHE,
Thierry FOURNIER5bf77322017-02-25 12:45:22 +0100220 .capture_cipherlist = 0,
William Lallemand3af48e72020-02-03 17:15:52 +0100221 .extra_files = SSL_GF_ALL,
Willy Tarreauef934602016-12-22 23:12:01 +0100222};
223
Olivier Houcharda8955d52019-04-07 22:00:38 +0200224static BIO_METHOD *ha_meth;
225
Olivier Houchard66ab4982019-02-26 18:37:15 +0100226struct ssl_sock_ctx {
Olivier Houcharda8955d52019-04-07 22:00:38 +0200227 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +0100228 SSL *ssl;
Olivier Houcharda8955d52019-04-07 22:00:38 +0200229 BIO *bio;
Olivier Houchard5149b592019-05-23 17:47:36 +0200230 const struct xprt_ops *xprt;
Olivier Houchard66ab4982019-02-26 18:37:15 +0100231 void *xprt_ctx;
Olivier Houchardea8dd942019-05-20 14:02:16 +0200232 struct wait_event wait_event;
Willy Tarreau113d52b2020-01-10 09:20:26 +0100233 struct wait_event *subs;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +0100234 int xprt_st; /* transport layer state, initialized to zero */
Olivier Houchard54907bb2019-12-19 15:02:39 +0100235 struct buffer early_buf; /* buffer to store the early data received */
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +0100236 int sent_early_data; /* Amount of early data we sent so far */
237
Olivier Houchard66ab4982019-02-26 18:37:15 +0100238};
239
240DECLARE_STATIC_POOL(ssl_sock_ctx_pool, "ssl_sock_ctx_pool", sizeof(struct ssl_sock_ctx));
241
Olivier Houchardea8dd942019-05-20 14:02:16 +0200242static struct task *ssl_sock_io_cb(struct task *, void *, unsigned short);
Olivier Houchard000694c2019-05-23 14:45:12 +0200243static int ssl_sock_handshake(struct connection *conn, unsigned int flag);
Olivier Houchardea8dd942019-05-20 14:02:16 +0200244
Olivier Houcharda8955d52019-04-07 22:00:38 +0200245/* Methods to implement OpenSSL BIO */
246static int ha_ssl_write(BIO *h, const char *buf, int num)
247{
248 struct buffer tmpbuf;
249 struct ssl_sock_ctx *ctx;
250 int ret;
251
252 ctx = BIO_get_data(h);
253 tmpbuf.size = num;
254 tmpbuf.area = (void *)(uintptr_t)buf;
255 tmpbuf.data = num;
256 tmpbuf.head = 0;
257 ret = ctx->xprt->snd_buf(ctx->conn, ctx->xprt_ctx, &tmpbuf, num, 0);
Olivier Houchardb51937e2019-05-01 17:24:36 +0200258 if (ret == 0 && !(ctx->conn->flags & (CO_FL_ERROR | CO_FL_SOCK_WR_SH))) {
Olivier Houcharda8955d52019-04-07 22:00:38 +0200259 BIO_set_retry_write(h);
Olivier Houcharda28454e2019-04-24 12:04:36 +0200260 ret = -1;
Olivier Houchardb51937e2019-05-01 17:24:36 +0200261 } else if (ret == 0)
262 BIO_clear_retry_flags(h);
Olivier Houcharda8955d52019-04-07 22:00:38 +0200263 return ret;
264}
265
266static int ha_ssl_gets(BIO *h, char *buf, int size)
267{
268
269 return 0;
270}
271
272static int ha_ssl_puts(BIO *h, const char *str)
273{
274
275 return ha_ssl_write(h, str, strlen(str));
276}
277
278static int ha_ssl_read(BIO *h, char *buf, int size)
279{
280 struct buffer tmpbuf;
281 struct ssl_sock_ctx *ctx;
282 int ret;
283
284 ctx = BIO_get_data(h);
285 tmpbuf.size = size;
286 tmpbuf.area = buf;
287 tmpbuf.data = 0;
288 tmpbuf.head = 0;
289 ret = ctx->xprt->rcv_buf(ctx->conn, ctx->xprt_ctx, &tmpbuf, size, 0);
Olivier Houchardb51937e2019-05-01 17:24:36 +0200290 if (ret == 0 && !(ctx->conn->flags & (CO_FL_ERROR | CO_FL_SOCK_RD_SH))) {
Olivier Houcharda8955d52019-04-07 22:00:38 +0200291 BIO_set_retry_read(h);
Olivier Houcharda28454e2019-04-24 12:04:36 +0200292 ret = -1;
Olivier Houchardb51937e2019-05-01 17:24:36 +0200293 } else if (ret == 0)
294 BIO_clear_retry_flags(h);
Olivier Houcharda8955d52019-04-07 22:00:38 +0200295
296 return ret;
297}
298
299static long ha_ssl_ctrl(BIO *h, int cmd, long arg1, void *arg2)
300{
301 int ret = 0;
302 switch (cmd) {
303 case BIO_CTRL_DUP:
304 case BIO_CTRL_FLUSH:
305 ret = 1;
306 break;
307 }
308 return ret;
309}
310
311static int ha_ssl_new(BIO *h)
312{
313 BIO_set_init(h, 1);
314 BIO_set_data(h, NULL);
315 BIO_clear_flags(h, ~0);
316 return 1;
317}
318
319static int ha_ssl_free(BIO *data)
320{
321
322 return 1;
323}
324
325
Willy Tarreau5db847a2019-05-09 14:13:35 +0200326#if defined(USE_THREAD) && (HA_OPENSSL_VERSION_NUMBER < 0x10100000L)
Christopher Faulet9dcf9b62017-11-13 10:34:01 +0100327
Emeric Brun821bb9b2017-06-15 16:37:39 +0200328static HA_RWLOCK_T *ssl_rwlocks;
329
330
331unsigned long ssl_id_function(void)
332{
333 return (unsigned long)tid;
334}
335
336void ssl_locking_function(int mode, int n, const char * file, int line)
337{
338 if (mode & CRYPTO_LOCK) {
339 if (mode & CRYPTO_READ)
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100340 HA_RWLOCK_RDLOCK(SSL_LOCK, &ssl_rwlocks[n]);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200341 else
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100342 HA_RWLOCK_WRLOCK(SSL_LOCK, &ssl_rwlocks[n]);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200343 }
344 else {
345 if (mode & CRYPTO_READ)
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100346 HA_RWLOCK_RDUNLOCK(SSL_LOCK, &ssl_rwlocks[n]);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200347 else
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100348 HA_RWLOCK_WRUNLOCK(SSL_LOCK, &ssl_rwlocks[n]);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200349 }
350}
351
352static int ssl_locking_init(void)
353{
354 int i;
355
356 ssl_rwlocks = malloc(sizeof(HA_RWLOCK_T)*CRYPTO_num_locks());
357 if (!ssl_rwlocks)
358 return -1;
359
360 for (i = 0 ; i < CRYPTO_num_locks() ; i++)
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100361 HA_RWLOCK_INIT(&ssl_rwlocks[i]);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200362
363 CRYPTO_set_id_callback(ssl_id_function);
364 CRYPTO_set_locking_callback(ssl_locking_function);
365
366 return 0;
367}
Christopher Faulet9dcf9b62017-11-13 10:34:01 +0100368
Emeric Brun821bb9b2017-06-15 16:37:39 +0200369#endif
370
William Lallemand150bfa82019-09-19 17:12:49 +0200371__decl_hathreads(HA_SPINLOCK_T ckch_lock);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200372
William Lallemandbc6ca7c2019-10-29 23:48:19 +0100373/* Uncommitted CKCH transaction */
374
375static struct {
376 struct ckch_store *new_ckchs;
377 struct ckch_store *old_ckchs;
378 char *path;
379} ckchs_transaction;
380
Emmanuel Hocdetd4f9a602019-10-24 11:32:47 +0200381/*
Emmanuel Hocdetb270e812019-11-21 19:09:31 +0100382 * deduplicate cafile (and crlfile)
Emmanuel Hocdetd4f9a602019-10-24 11:32:47 +0200383 */
384struct cafile_entry {
385 X509_STORE *ca_store;
Emmanuel Hocdet129d3282019-10-24 18:08:51 +0200386 STACK_OF(X509_NAME) *ca_list;
Emmanuel Hocdetd4f9a602019-10-24 11:32:47 +0200387 struct ebmb_node node;
388 char path[0];
389};
390
391static struct eb_root cafile_tree = EB_ROOT_UNIQUE;
392
393static X509_STORE* ssl_store_get0_locations_file(char *path)
394{
395 struct ebmb_node *eb;
396
397 eb = ebst_lookup(&cafile_tree, path);
398 if (eb) {
399 struct cafile_entry *ca_e;
400 ca_e = ebmb_entry(eb, struct cafile_entry, node);
401 return ca_e->ca_store;
402 }
403 return NULL;
404}
405
406static int ssl_store_load_locations_file(char *path)
407{
408 if (ssl_store_get0_locations_file(path) == NULL) {
409 struct cafile_entry *ca_e;
410 X509_STORE *store = X509_STORE_new();
411 if (X509_STORE_load_locations(store, path, NULL)) {
412 int pathlen;
413 pathlen = strlen(path);
414 ca_e = calloc(1, sizeof(*ca_e) + pathlen + 1);
415 if (ca_e) {
416 memcpy(ca_e->path, path, pathlen + 1);
417 ca_e->ca_store = store;
418 ebst_insert(&cafile_tree, &ca_e->node);
419 return 1;
420 }
421 }
422 X509_STORE_free(store);
423 return 0;
424 }
425 return 1;
426}
427
428/* mimic what X509_STORE_load_locations do with store_ctx */
429static int ssl_set_cert_crl_file(X509_STORE *store_ctx, char *path)
430{
431 X509_STORE *store;
432 store = ssl_store_get0_locations_file(path);
433 if (store_ctx && store) {
434 int i;
435 X509_OBJECT *obj;
436 STACK_OF(X509_OBJECT) *objs = X509_STORE_get0_objects(store);
437 for (i = 0; i < sk_X509_OBJECT_num(objs); i++) {
438 obj = sk_X509_OBJECT_value(objs, i);
439 switch (X509_OBJECT_get_type(obj)) {
440 case X509_LU_X509:
441 X509_STORE_add_cert(store_ctx, X509_OBJECT_get0_X509(obj));
442 break;
443 case X509_LU_CRL:
444 X509_STORE_add_crl(store_ctx, X509_OBJECT_get0_X509_CRL(obj));
445 break;
446 default:
447 break;
448 }
449 }
450 return 1;
451 }
452 return 0;
453}
454
455/* SSL_CTX_load_verify_locations substitute, internaly call X509_STORE_load_locations */
456static int ssl_set_verify_locations_file(SSL_CTX *ctx, char *path)
457{
458 X509_STORE *store_ctx = SSL_CTX_get_cert_store(ctx);
459 return ssl_set_cert_crl_file(store_ctx, path);
460}
461
Emmanuel Hocdet129d3282019-10-24 18:08:51 +0200462/*
463 Extract CA_list from CA_file already in tree.
464 Duplicate ca_name is tracking with ebtree. It's simplify openssl compatibility.
465 Return a shared ca_list: SSL_dup_CA_list must be used before set it on SSL_CTX.
466*/
467static STACK_OF(X509_NAME)* ssl_get_client_ca_file(char *path)
468{
469 struct ebmb_node *eb;
470 struct cafile_entry *ca_e;
471
472 eb = ebst_lookup(&cafile_tree, path);
473 if (!eb)
474 return NULL;
475 ca_e = ebmb_entry(eb, struct cafile_entry, node);
476
477 if (ca_e->ca_list == NULL) {
478 int i;
479 unsigned long key;
480 struct eb_root ca_name_tree = EB_ROOT;
481 struct eb64_node *node, *back;
482 struct {
483 struct eb64_node node;
484 X509_NAME *xname;
485 } *ca_name;
486 STACK_OF(X509_OBJECT) *objs;
487 STACK_OF(X509_NAME) *skn;
488 X509 *x;
489 X509_NAME *xn;
490
491 skn = sk_X509_NAME_new_null();
492 /* take x509 from cafile_tree */
493 objs = X509_STORE_get0_objects(ca_e->ca_store);
494 for (i = 0; i < sk_X509_OBJECT_num(objs); i++) {
495 x = X509_OBJECT_get0_X509(sk_X509_OBJECT_value(objs, i));
496 if (!x)
497 continue;
498 xn = X509_get_subject_name(x);
499 if (!xn)
500 continue;
501 /* Check for duplicates. */
502 key = X509_NAME_hash(xn);
503 for (node = eb64_lookup(&ca_name_tree, key), ca_name = NULL;
504 node && ca_name == NULL;
505 node = eb64_next(node)) {
506 ca_name = container_of(node, typeof(*ca_name), node);
507 if (X509_NAME_cmp(xn, ca_name->xname) != 0)
508 ca_name = NULL;
509 }
510 /* find a duplicate */
511 if (ca_name)
512 continue;
513 ca_name = calloc(1, sizeof *ca_name);
514 xn = X509_NAME_dup(xn);
515 if (!ca_name ||
516 !xn ||
517 !sk_X509_NAME_push(skn, xn)) {
518 free(ca_name);
519 X509_NAME_free(xn);
520 sk_X509_NAME_pop_free(skn, X509_NAME_free);
521 sk_X509_NAME_free(skn);
522 skn = NULL;
523 break;
524 }
525 ca_name->node.key = key;
526 ca_name->xname = xn;
527 eb64_insert(&ca_name_tree, &ca_name->node);
528 }
529 ca_e->ca_list = skn;
530 /* remove temporary ca_name tree */
531 node = eb64_first(&ca_name_tree);
532 while (node) {
533 ca_name = container_of(node, typeof(*ca_name), node);
534 back = eb64_next(node);
535 eb64_delete(node);
536 free(ca_name);
537 node = back;
538 }
539 }
540 return ca_e->ca_list;
541}
542
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +0100543/* This memory pool is used for capturing clienthello parameters. */
Thierry FOURNIER5bf77322017-02-25 12:45:22 +0100544struct ssl_capture {
Thierry FOURNIER5bf77322017-02-25 12:45:22 +0100545 unsigned long long int xxh64;
546 unsigned char ciphersuite_len;
547 char ciphersuite[0];
548};
Willy Tarreaubafbe012017-11-24 17:34:44 +0100549struct pool_head *pool_head_ssl_capture = NULL;
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +0100550static int ssl_capture_ptr_index = -1;
Thierry FOURNIER28962c92018-06-17 21:37:05 +0200551static int ssl_app_data_index = -1;
Willy Tarreauef934602016-12-22 23:12:01 +0100552
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200553#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
554struct list tlskeys_reference = LIST_HEAD_INIT(tlskeys_reference);
555#endif
556
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +0200557#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +0000558static unsigned int openssl_engines_initialized;
559struct list openssl_engines = LIST_HEAD_INIT(openssl_engines);
560struct ssl_engine_list {
561 struct list list;
562 ENGINE *e;
563};
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +0200564#endif
Grant Zhang872f9c22017-01-21 01:10:18 +0000565
Remi Gacogne8de54152014-07-15 11:36:40 +0200566#ifndef OPENSSL_NO_DH
Remi Gacogne4f902b82015-05-28 16:23:00 +0200567static int ssl_dh_ptr_index = -1;
Remi Gacogne47783ef2015-05-29 15:53:22 +0200568static DH *global_dh = NULL;
Remi Gacogne8de54152014-07-15 11:36:40 +0200569static DH *local_dh_1024 = NULL;
570static DH *local_dh_2048 = NULL;
571static DH *local_dh_4096 = NULL;
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +0100572static DH *ssl_get_tmp_dh(SSL *ssl, int export, int keylen);
Remi Gacogne8de54152014-07-15 11:36:40 +0200573#endif /* OPENSSL_NO_DH */
574
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100575#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Christopher Faulet31af49d2015-06-09 17:29:50 +0200576/* X509V3 Extensions that will be added on generated certificates */
577#define X509V3_EXT_SIZE 5
578static char *x509v3_ext_names[X509V3_EXT_SIZE] = {
579 "basicConstraints",
580 "nsComment",
581 "subjectKeyIdentifier",
582 "authorityKeyIdentifier",
583 "keyUsage",
584};
585static char *x509v3_ext_values[X509V3_EXT_SIZE] = {
586 "CA:FALSE",
587 "\"OpenSSL Generated Certificate\"",
588 "hash",
589 "keyid,issuer:always",
590 "nonRepudiation,digitalSignature,keyEncipherment"
591};
Christopher Faulet31af49d2015-06-09 17:29:50 +0200592/* LRU cache to store generated certificate */
593static struct lru64_head *ssl_ctx_lru_tree = NULL;
594static unsigned int ssl_ctx_lru_seed = 0;
Emeric Brun821bb9b2017-06-15 16:37:39 +0200595static unsigned int ssl_ctx_serial;
Willy Tarreau86abe442018-11-25 20:12:18 +0100596__decl_rwlock(ssl_ctx_lru_rwlock);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200597
Willy Tarreauc8ad3be2015-06-17 15:48:26 +0200598#endif // SSL_CTRL_SET_TLSEXT_HOSTNAME
599
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100600static struct ssl_bind_kw ssl_bind_kws[];
601
Willy Tarreau9a1ab082019-05-09 13:26:41 +0200602#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
yanbzhube2774d2015-12-10 15:07:30 -0500603/* The order here matters for picking a default context,
604 * keep the most common keytype at the bottom of the list
605 */
606const char *SSL_SOCK_KEYTYPE_NAMES[] = {
607 "dsa",
608 "ecdsa",
609 "rsa"
610};
611#define SSL_SOCK_NUM_KEYTYPES 3
Willy Tarreau30da7ad2015-12-14 11:28:33 +0100612#else
613#define SSL_SOCK_NUM_KEYTYPES 1
yanbzhube2774d2015-12-10 15:07:30 -0500614#endif
615
William Lallemandc3cd35f2017-11-28 11:04:43 +0100616static struct shared_context *ssl_shctx = NULL; /* ssl shared session cache */
William Lallemand4f45bb92017-10-30 20:08:51 +0100617static struct eb_root *sh_ssl_sess_tree; /* ssl shared session tree */
618
619#define sh_ssl_sess_tree_delete(s) ebmb_delete(&(s)->key);
620
621#define sh_ssl_sess_tree_insert(s) (struct sh_ssl_sess_hdr *)ebmb_insert(sh_ssl_sess_tree, \
622 &(s)->key, SSL_MAX_SSL_SESSION_ID_LENGTH);
623
624#define sh_ssl_sess_tree_lookup(k) (struct sh_ssl_sess_hdr *)ebmb_lookup(sh_ssl_sess_tree, \
625 (k), SSL_MAX_SSL_SESSION_ID_LENGTH);
William Lallemand3f85c9a2017-10-09 16:30:50 +0200626
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100627/*
628 * This function gives the detail of the SSL error. It is used only
629 * if the debug mode and the verbose mode are activated. It dump all
630 * the SSL error until the stack was empty.
631 */
632static forceinline void ssl_sock_dump_errors(struct connection *conn)
633{
634 unsigned long ret;
635
636 if (unlikely(global.mode & MODE_DEBUG)) {
637 while(1) {
638 ret = ERR_get_error();
639 if (ret == 0)
640 return;
641 fprintf(stderr, "fd[%04x] OpenSSL error[0x%lx] %s: %s\n",
Willy Tarreau585744b2017-08-24 14:31:19 +0200642 (unsigned short)conn->handle.fd, ret,
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100643 ERR_func_error_string(ret), ERR_reason_error_string(ret));
644 }
645 }
646}
647
yanbzhube2774d2015-12-10 15:07:30 -0500648
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +0200649#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +0000650static int ssl_init_single_engine(const char *engine_id, const char *def_algorithms)
651{
652 int err_code = ERR_ABORT;
653 ENGINE *engine;
654 struct ssl_engine_list *el;
655
656 /* grab the structural reference to the engine */
657 engine = ENGINE_by_id(engine_id);
658 if (engine == NULL) {
Christopher Faulet767a84b2017-11-24 16:50:31 +0100659 ha_alert("ssl-engine %s: failed to get structural reference\n", engine_id);
Grant Zhang872f9c22017-01-21 01:10:18 +0000660 goto fail_get;
661 }
662
663 if (!ENGINE_init(engine)) {
664 /* the engine couldn't initialise, release it */
Christopher Faulet767a84b2017-11-24 16:50:31 +0100665 ha_alert("ssl-engine %s: failed to initialize\n", engine_id);
Grant Zhang872f9c22017-01-21 01:10:18 +0000666 goto fail_init;
667 }
668
669 if (ENGINE_set_default_string(engine, def_algorithms) == 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +0100670 ha_alert("ssl-engine %s: failed on ENGINE_set_default_string\n", engine_id);
Grant Zhang872f9c22017-01-21 01:10:18 +0000671 goto fail_set_method;
672 }
673
674 el = calloc(1, sizeof(*el));
675 el->e = engine;
676 LIST_ADD(&openssl_engines, &el->list);
Emeric Brunece0c332017-12-06 13:51:49 +0100677 nb_engines++;
678 if (global_ssl.async)
679 global.ssl_used_async_engines = nb_engines;
Grant Zhang872f9c22017-01-21 01:10:18 +0000680 return 0;
681
682fail_set_method:
683 /* release the functional reference from ENGINE_init() */
684 ENGINE_finish(engine);
685
686fail_init:
687 /* release the structural reference from ENGINE_by_id() */
688 ENGINE_free(engine);
689
690fail_get:
691 return err_code;
692}
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +0200693#endif
Grant Zhang872f9c22017-01-21 01:10:18 +0000694
Willy Tarreau5db847a2019-05-09 14:13:35 +0200695#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brun3854e012017-05-17 20:42:48 +0200696/*
697 * openssl async fd handler
698 */
Emeric Brund0e095c2019-04-19 17:15:28 +0200699void ssl_async_fd_handler(int fd)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000700{
Olivier Houchardea8dd942019-05-20 14:02:16 +0200701 struct ssl_sock_ctx *ctx = fdtab[fd].owner;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000702
Emeric Brun3854e012017-05-17 20:42:48 +0200703 /* fd is an async enfine fd, we must stop
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000704 * to poll this fd until it is requested
705 */
Emeric Brunbbc16542017-06-02 15:54:06 +0000706 fd_stop_recv(fd);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000707 fd_cant_recv(fd);
708
709 /* crypto engine is available, let's notify the associated
710 * connection that it can pursue its processing.
711 */
Olivier Houchard03abf2d2019-05-28 10:12:02 +0200712 ssl_sock_io_cb(NULL, ctx, 0);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000713}
714
Emeric Brun3854e012017-05-17 20:42:48 +0200715/*
716 * openssl async delayed SSL_free handler
717 */
Emeric Brund0e095c2019-04-19 17:15:28 +0200718void ssl_async_fd_free(int fd)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000719{
720 SSL *ssl = fdtab[fd].owner;
Emeric Brun3854e012017-05-17 20:42:48 +0200721 OSSL_ASYNC_FD all_fd[32];
722 size_t num_all_fds = 0;
723 int i;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000724
Emeric Brun3854e012017-05-17 20:42:48 +0200725 /* We suppose that the async job for a same SSL *
726 * are serialized. So if we are awake it is
727 * because the running job has just finished
728 * and we can remove all async fds safely
729 */
730 SSL_get_all_async_fds(ssl, NULL, &num_all_fds);
731 if (num_all_fds > 32) {
732 send_log(NULL, LOG_EMERG, "haproxy: openssl returns too many async fds. It seems a bug. Process may crash\n");
733 return;
734 }
735
736 SSL_get_all_async_fds(ssl, all_fd, &num_all_fds);
737 for (i=0 ; i < num_all_fds ; i++)
738 fd_remove(all_fd[i]);
739
740 /* Now we can safely call SSL_free, no more pending job in engines */
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000741 SSL_free(ssl);
Olivier Houchard2be5a4c2019-03-08 18:54:43 +0100742 _HA_ATOMIC_SUB(&sslconns, 1);
743 _HA_ATOMIC_SUB(&jobs, 1);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000744}
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000745/*
Emeric Brun3854e012017-05-17 20:42:48 +0200746 * function used to manage a returned SSL_ERROR_WANT_ASYNC
747 * and enable/disable polling for async fds
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000748 */
Olivier Houchardea8dd942019-05-20 14:02:16 +0200749static inline void ssl_async_process_fds(struct ssl_sock_ctx *ctx)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000750{
Willy Tarreaua9786b62018-01-25 07:22:13 +0100751 OSSL_ASYNC_FD add_fd[32];
Emeric Brun3854e012017-05-17 20:42:48 +0200752 OSSL_ASYNC_FD del_fd[32];
Olivier Houchardea8dd942019-05-20 14:02:16 +0200753 SSL *ssl = ctx->ssl;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000754 size_t num_add_fds = 0;
755 size_t num_del_fds = 0;
Emeric Brun3854e012017-05-17 20:42:48 +0200756 int i;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000757
758 SSL_get_changed_async_fds(ssl, NULL, &num_add_fds, NULL,
759 &num_del_fds);
Emeric Brun3854e012017-05-17 20:42:48 +0200760 if (num_add_fds > 32 || num_del_fds > 32) {
761 send_log(NULL, LOG_EMERG, "haproxy: openssl returns too many async fds. It seems a bug. Process may crash\n");
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000762 return;
763 }
764
Emeric Brun3854e012017-05-17 20:42:48 +0200765 SSL_get_changed_async_fds(ssl, add_fd, &num_add_fds, del_fd, &num_del_fds);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000766
Emeric Brun3854e012017-05-17 20:42:48 +0200767 /* We remove unused fds from the fdtab */
768 for (i=0 ; i < num_del_fds ; i++)
769 fd_remove(del_fd[i]);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000770
Emeric Brun3854e012017-05-17 20:42:48 +0200771 /* We add new fds to the fdtab */
772 for (i=0 ; i < num_add_fds ; i++) {
Olivier Houchardea8dd942019-05-20 14:02:16 +0200773 fd_insert(add_fd[i], ctx, ssl_async_fd_handler, tid_bit);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000774 }
775
Emeric Brun3854e012017-05-17 20:42:48 +0200776 num_add_fds = 0;
777 SSL_get_all_async_fds(ssl, NULL, &num_add_fds);
778 if (num_add_fds > 32) {
779 send_log(NULL, LOG_EMERG, "haproxy: openssl returns too many async fds. It seems a bug. Process may crash\n");
780 return;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000781 }
Emeric Brun3854e012017-05-17 20:42:48 +0200782
783 /* We activate the polling for all known async fds */
784 SSL_get_all_async_fds(ssl, add_fd, &num_add_fds);
Emeric Brunce9e01c2017-05-31 10:02:53 +0000785 for (i=0 ; i < num_add_fds ; i++) {
Emeric Brun3854e012017-05-17 20:42:48 +0200786 fd_want_recv(add_fd[i]);
Emeric Brunce9e01c2017-05-31 10:02:53 +0000787 /* To ensure that the fd cache won't be used
788 * We'll prefer to catch a real RD event
789 * because handling an EAGAIN on this fd will
790 * result in a context switch and also
791 * some engines uses a fd in blocking mode.
792 */
793 fd_cant_recv(add_fd[i]);
794 }
Emeric Brun3854e012017-05-17 20:42:48 +0200795
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000796}
797#endif
798
William Lallemand104a7a62019-10-14 14:14:59 +0200799#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
Emeric Brun4f3c87a2014-06-20 15:46:13 +0200800/*
801 * This function returns the number of seconds elapsed
802 * since the Epoch, 1970-01-01 00:00:00 +0000 (UTC) and the
803 * date presented un ASN1_GENERALIZEDTIME.
804 *
805 * In parsing error case, it returns -1.
806 */
807static long asn1_generalizedtime_to_epoch(ASN1_GENERALIZEDTIME *d)
808{
809 long epoch;
810 char *p, *end;
811 const unsigned short month_offset[12] = {
812 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
813 };
814 int year, month;
815
816 if (!d || (d->type != V_ASN1_GENERALIZEDTIME)) return -1;
817
818 p = (char *)d->data;
819 end = p + d->length;
820
821 if (end - p < 4) return -1;
822 year = 1000 * (p[0] - '0') + 100 * (p[1] - '0') + 10 * (p[2] - '0') + p[3] - '0';
823 p += 4;
824 if (end - p < 2) return -1;
825 month = 10 * (p[0] - '0') + p[1] - '0';
826 if (month < 1 || month > 12) return -1;
827 /* Compute the number of seconds since 1 jan 1970 and the beginning of current month
828 We consider leap years and the current month (<marsh or not) */
829 epoch = ( ((year - 1970) * 365)
830 + ((year - (month < 3)) / 4 - (year - (month < 3)) / 100 + (year - (month < 3)) / 400)
831 - ((1970 - 1) / 4 - (1970 - 1) / 100 + (1970 - 1) / 400)
832 + month_offset[month-1]
833 ) * 24 * 60 * 60;
834 p += 2;
835 if (end - p < 2) return -1;
836 /* Add the number of seconds of completed days of current month */
837 epoch += (10 * (p[0] - '0') + p[1] - '0' - 1) * 24 * 60 * 60;
838 p += 2;
839 if (end - p < 2) return -1;
840 /* Add the completed hours of the current day */
841 epoch += (10 * (p[0] - '0') + p[1] - '0') * 60 * 60;
842 p += 2;
843 if (end - p < 2) return -1;
844 /* Add the completed minutes of the current hour */
845 epoch += (10 * (p[0] - '0') + p[1] - '0') * 60;
846 p += 2;
847 if (p == end) return -1;
848 /* Test if there is available seconds */
849 if (p[0] < '0' || p[0] > '9')
850 goto nosec;
851 if (end - p < 2) return -1;
852 /* Add the seconds of the current minute */
853 epoch += 10 * (p[0] - '0') + p[1] - '0';
854 p += 2;
855 if (p == end) return -1;
856 /* Ignore seconds float part if present */
857 if (p[0] == '.') {
858 do {
859 if (++p == end) return -1;
860 } while (p[0] >= '0' && p[0] <= '9');
861 }
862
863nosec:
864 if (p[0] == 'Z') {
865 if (end - p != 1) return -1;
866 return epoch;
867 }
868 else if (p[0] == '+') {
869 if (end - p != 5) return -1;
870 /* Apply timezone offset */
Frederik Deweerdt953917a2017-10-16 07:37:31 -0700871 return epoch - ((10 * (p[1] - '0') + p[2] - '0') * 60 * 60 + (10 * (p[3] - '0') + p[4] - '0')) * 60;
Emeric Brun4f3c87a2014-06-20 15:46:13 +0200872 }
873 else if (p[0] == '-') {
874 if (end - p != 5) return -1;
875 /* Apply timezone offset */
Frederik Deweerdt953917a2017-10-16 07:37:31 -0700876 return epoch + ((10 * (p[1] - '0') + p[2] - '0') * 60 * 60 + (10 * (p[3] - '0') + p[4] - '0')) * 60;
Emeric Brun4f3c87a2014-06-20 15:46:13 +0200877 }
878
879 return -1;
880}
881
William Lallemand104a7a62019-10-14 14:14:59 +0200882/*
883 * struct alignment works here such that the key.key is the same as key_data
884 * Do not change the placement of key_data
885 */
886struct certificate_ocsp {
887 struct ebmb_node key;
888 unsigned char key_data[OCSP_MAX_CERTID_ASN1_LENGTH];
889 struct buffer response;
890 long expire;
891};
892
893struct ocsp_cbk_arg {
894 int is_single;
895 int single_kt;
896 union {
897 struct certificate_ocsp *s_ocsp;
898 /*
899 * m_ocsp will have multiple entries dependent on key type
900 * Entry 0 - DSA
901 * Entry 1 - ECDSA
902 * Entry 2 - RSA
903 */
904 struct certificate_ocsp *m_ocsp[SSL_SOCK_NUM_KEYTYPES];
905 };
906};
907
Emeric Brun1d3865b2014-06-20 15:37:32 +0200908static struct eb_root cert_ocsp_tree = EB_ROOT_UNIQUE;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200909
910/* This function starts to check if the OCSP response (in DER format) contained
911 * in chunk 'ocsp_response' is valid (else exits on error).
912 * If 'cid' is not NULL, it will be compared to the OCSP certificate ID
913 * contained in the OCSP Response and exits on error if no match.
914 * If it's a valid OCSP Response:
915 * If 'ocsp' is not NULL, the chunk is copied in the OCSP response's container
916 * pointed by 'ocsp'.
917 * If 'ocsp' is NULL, the function looks up into the OCSP response's
918 * containers tree (using as index the ASN1 form of the OCSP Certificate ID extracted
919 * from the response) and exits on error if not found. Finally, If an OCSP response is
920 * already present in the container, it will be overwritten.
921 *
922 * Note: OCSP response containing more than one OCSP Single response is not
923 * considered valid.
924 *
925 * Returns 0 on success, 1 in error case.
926 */
Willy Tarreau83061a82018-07-13 11:56:34 +0200927static int ssl_sock_load_ocsp_response(struct buffer *ocsp_response,
928 struct certificate_ocsp *ocsp,
929 OCSP_CERTID *cid, char **err)
Emeric Brun4147b2e2014-06-16 18:36:30 +0200930{
931 OCSP_RESPONSE *resp;
932 OCSP_BASICRESP *bs = NULL;
933 OCSP_SINGLERESP *sr;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200934 OCSP_CERTID *id;
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200935 unsigned char *p = (unsigned char *) ocsp_response->area;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200936 int rc , count_sr;
Emeric Brun13a6b482014-06-20 15:44:34 +0200937 ASN1_GENERALIZEDTIME *revtime, *thisupd, *nextupd = NULL;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200938 int reason;
939 int ret = 1;
940
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200941 resp = d2i_OCSP_RESPONSE(NULL, (const unsigned char **)&p,
942 ocsp_response->data);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200943 if (!resp) {
944 memprintf(err, "Unable to parse OCSP response");
945 goto out;
946 }
947
948 rc = OCSP_response_status(resp);
949 if (rc != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
950 memprintf(err, "OCSP response status not successful");
951 goto out;
952 }
953
954 bs = OCSP_response_get1_basic(resp);
955 if (!bs) {
956 memprintf(err, "Failed to get basic response from OCSP Response");
957 goto out;
958 }
959
960 count_sr = OCSP_resp_count(bs);
961 if (count_sr > 1) {
962 memprintf(err, "OCSP response ignored because contains multiple single responses (%d)", count_sr);
963 goto out;
964 }
965
966 sr = OCSP_resp_get0(bs, 0);
967 if (!sr) {
968 memprintf(err, "Failed to get OCSP single response");
969 goto out;
970 }
971
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200972 id = (OCSP_CERTID*)OCSP_SINGLERESP_get0_id(sr);
973
Emeric Brun4147b2e2014-06-16 18:36:30 +0200974 rc = OCSP_single_get0_status(sr, &reason, &revtime, &thisupd, &nextupd);
Emmanuel Hocdetef607052017-10-24 14:57:16 +0200975 if (rc != V_OCSP_CERTSTATUS_GOOD && rc != V_OCSP_CERTSTATUS_REVOKED) {
Emmanuel Hocdet872085c2017-10-10 15:18:52 +0200976 memprintf(err, "OCSP single response: certificate status is unknown");
Emeric Brun4147b2e2014-06-16 18:36:30 +0200977 goto out;
978 }
979
Emeric Brun13a6b482014-06-20 15:44:34 +0200980 if (!nextupd) {
981 memprintf(err, "OCSP single response: missing nextupdate");
982 goto out;
983 }
984
Emeric Brunc8b27b62014-06-19 14:16:17 +0200985 rc = OCSP_check_validity(thisupd, nextupd, OCSP_MAX_RESPONSE_TIME_SKEW, -1);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200986 if (!rc) {
987 memprintf(err, "OCSP single response: no longer valid.");
988 goto out;
989 }
990
991 if (cid) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200992 if (OCSP_id_cmp(id, cid)) {
Emeric Brun4147b2e2014-06-16 18:36:30 +0200993 memprintf(err, "OCSP single response: Certificate ID does not match certificate and issuer");
994 goto out;
995 }
996 }
997
998 if (!ocsp) {
999 unsigned char key[OCSP_MAX_CERTID_ASN1_LENGTH];
1000 unsigned char *p;
1001
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001002 rc = i2d_OCSP_CERTID(id, NULL);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001003 if (!rc) {
1004 memprintf(err, "OCSP single response: Unable to encode Certificate ID");
1005 goto out;
1006 }
1007
1008 if (rc > OCSP_MAX_CERTID_ASN1_LENGTH) {
1009 memprintf(err, "OCSP single response: Certificate ID too long");
1010 goto out;
1011 }
1012
1013 p = key;
1014 memset(key, 0, OCSP_MAX_CERTID_ASN1_LENGTH);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001015 i2d_OCSP_CERTID(id, &p);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001016 ocsp = (struct certificate_ocsp *)ebmb_lookup(&cert_ocsp_tree, key, OCSP_MAX_CERTID_ASN1_LENGTH);
1017 if (!ocsp) {
1018 memprintf(err, "OCSP single response: Certificate ID does not match any certificate or issuer");
1019 goto out;
1020 }
1021 }
1022
1023 /* According to comments on "chunk_dup", the
1024 previous chunk buffer will be freed */
1025 if (!chunk_dup(&ocsp->response, ocsp_response)) {
1026 memprintf(err, "OCSP response: Memory allocation error");
1027 goto out;
1028 }
1029
Emeric Brun4f3c87a2014-06-20 15:46:13 +02001030 ocsp->expire = asn1_generalizedtime_to_epoch(nextupd) - OCSP_MAX_RESPONSE_TIME_SKEW;
1031
Emeric Brun4147b2e2014-06-16 18:36:30 +02001032 ret = 0;
1033out:
Janusz Dziemidowicz8d710492017-03-08 16:59:41 +01001034 ERR_clear_error();
1035
Emeric Brun4147b2e2014-06-16 18:36:30 +02001036 if (bs)
1037 OCSP_BASICRESP_free(bs);
1038
1039 if (resp)
1040 OCSP_RESPONSE_free(resp);
1041
1042 return ret;
1043}
1044/*
1045 * External function use to update the OCSP response in the OCSP response's
1046 * containers tree. The chunk 'ocsp_response' must contain the OCSP response
1047 * to update in DER format.
1048 *
1049 * Returns 0 on success, 1 in error case.
1050 */
Willy Tarreau83061a82018-07-13 11:56:34 +02001051int ssl_sock_update_ocsp_response(struct buffer *ocsp_response, char **err)
Emeric Brun4147b2e2014-06-16 18:36:30 +02001052{
1053 return ssl_sock_load_ocsp_response(ocsp_response, NULL, NULL, err);
1054}
1055
William Lallemand4a660132019-10-14 14:51:41 +02001056#endif
1057
1058#if ((defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP) || defined OPENSSL_IS_BORINGSSL)
Emeric Brun4147b2e2014-06-16 18:36:30 +02001059/*
1060 * This function load the OCSP Resonse in DER format contained in file at
William Lallemand3b5f3602019-10-16 18:05:05 +02001061 * path 'ocsp_path' or base64 in a buffer <buf>
Emeric Brun4147b2e2014-06-16 18:36:30 +02001062 *
1063 * Returns 0 on success, 1 in error case.
1064 */
William Lallemand3b5f3602019-10-16 18:05:05 +02001065static int ssl_sock_load_ocsp_response_from_file(const char *ocsp_path, char *buf, struct cert_key_and_chain *ckch, char **err)
Emeric Brun4147b2e2014-06-16 18:36:30 +02001066{
1067 int fd = -1;
1068 int r = 0;
1069 int ret = 1;
William Lallemand3b5f3602019-10-16 18:05:05 +02001070 struct buffer *ocsp_response;
1071 struct buffer *src = NULL;
Emeric Brun4147b2e2014-06-16 18:36:30 +02001072
William Lallemand3b5f3602019-10-16 18:05:05 +02001073 if (buf) {
1074 int i, j;
1075 /* if it's from a buffer it will be base64 */
Emeric Brun4147b2e2014-06-16 18:36:30 +02001076
William Lallemand3b5f3602019-10-16 18:05:05 +02001077 /* remove \r and \n from the payload */
1078 for (i = 0, j = 0; buf[i]; i++) {
1079 if (buf[i] == '\r' || buf[i] == '\n')
Emeric Brun4147b2e2014-06-16 18:36:30 +02001080 continue;
William Lallemand3b5f3602019-10-16 18:05:05 +02001081 buf[j++] = buf[i];
1082 }
1083 buf[j] = 0;
Emeric Brun4147b2e2014-06-16 18:36:30 +02001084
William Lallemand3b5f3602019-10-16 18:05:05 +02001085 ret = base64dec(buf, j, trash.area, trash.size);
1086 if (ret < 0) {
1087 memprintf(err, "Error reading OCSP response in base64 format");
Emeric Brun4147b2e2014-06-16 18:36:30 +02001088 goto end;
1089 }
William Lallemand3b5f3602019-10-16 18:05:05 +02001090 trash.data = ret;
1091 src = &trash;
1092 } else {
1093 fd = open(ocsp_path, O_RDONLY);
1094 if (fd == -1) {
1095 memprintf(err, "Error opening OCSP response file");
1096 goto end;
Emeric Brun4147b2e2014-06-16 18:36:30 +02001097 }
William Lallemand3b5f3602019-10-16 18:05:05 +02001098
1099 trash.data = 0;
1100 while (trash.data < trash.size) {
1101 r = read(fd, trash.area + trash.data, trash.size - trash.data);
1102 if (r < 0) {
1103 if (errno == EINTR)
1104 continue;
1105
1106 memprintf(err, "Error reading OCSP response from file");
1107 goto end;
1108 }
1109 else if (r == 0) {
1110 break;
1111 }
1112 trash.data += r;
1113 }
1114 close(fd);
1115 fd = -1;
1116 src = &trash;
Emeric Brun4147b2e2014-06-16 18:36:30 +02001117 }
1118
William Lallemand3b5f3602019-10-16 18:05:05 +02001119 ocsp_response = calloc(1, sizeof(*ocsp_response));
1120 if (!chunk_dup(ocsp_response, src)) {
1121 free(ocsp_response);
1122 ocsp_response = NULL;
William Lallemand246c0242019-10-11 08:59:13 +02001123 goto end;
1124 }
Emmanuel Hocdet0667fae2020-01-16 14:41:36 +01001125 /* no error, fill ckch with new context, old context must be free */
1126 if (ckch->ocsp_response) {
1127 free(ckch->ocsp_response->area);
1128 ckch->ocsp_response->area = NULL;
1129 free(ckch->ocsp_response);
1130 }
William Lallemand3b5f3602019-10-16 18:05:05 +02001131 ckch->ocsp_response = ocsp_response;
William Lallemande0f48ae2019-10-15 13:44:57 +02001132 ret = 0;
Emeric Brun4147b2e2014-06-16 18:36:30 +02001133end:
1134 if (fd != -1)
1135 close(fd);
1136
1137 return ret;
1138}
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01001139#endif
Emeric Brun4147b2e2014-06-16 18:36:30 +02001140
Nenad Merdanovic05552d42015-02-27 19:56:49 +01001141#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
1142static int ssl_tlsext_ticket_key_cb(SSL *s, unsigned char key_name[16], unsigned char *iv, EVP_CIPHER_CTX *ectx, HMAC_CTX *hctx, int enc)
1143{
Christopher Faulet16f45c82018-02-16 11:23:49 +01001144 struct tls_keys_ref *ref;
Emeric Brun9e754772019-01-10 17:51:55 +01001145 union tls_sess_key *keys;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01001146 struct connection *conn;
1147 int head;
1148 int i;
Christopher Faulet16f45c82018-02-16 11:23:49 +01001149 int ret = -1; /* error by default */
Nenad Merdanovic05552d42015-02-27 19:56:49 +01001150
Thierry FOURNIER28962c92018-06-17 21:37:05 +02001151 conn = SSL_get_ex_data(s, ssl_app_data_index);
Willy Tarreau07d94e42018-09-20 10:57:52 +02001152 ref = __objt_listener(conn->target)->bind_conf->keys_ref;
Christopher Faulet16f45c82018-02-16 11:23:49 +01001153 HA_RWLOCK_RDLOCK(TLSKEYS_REF_LOCK, &ref->lock);
1154
1155 keys = ref->tlskeys;
1156 head = ref->tls_ticket_enc_index;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01001157
1158 if (enc) {
1159 memcpy(key_name, keys[head].name, 16);
1160
1161 if(!RAND_pseudo_bytes(iv, EVP_MAX_IV_LENGTH))
Christopher Faulet16f45c82018-02-16 11:23:49 +01001162 goto end;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01001163
Emeric Brun9e754772019-01-10 17:51:55 +01001164 if (ref->key_size_bits == 128) {
Nenad Merdanovic05552d42015-02-27 19:56:49 +01001165
Emeric Brun9e754772019-01-10 17:51:55 +01001166 if(!EVP_EncryptInit_ex(ectx, EVP_aes_128_cbc(), NULL, keys[head].key_128.aes_key, iv))
1167 goto end;
1168
Willy Tarreau9356dac2019-05-10 09:22:53 +02001169 HMAC_Init_ex(hctx, keys[head].key_128.hmac_key, 16, TLS_TICKET_HASH_FUNCT(), NULL);
Emeric Brun9e754772019-01-10 17:51:55 +01001170 ret = 1;
1171 }
1172 else if (ref->key_size_bits == 256 ) {
1173
1174 if(!EVP_EncryptInit_ex(ectx, EVP_aes_256_cbc(), NULL, keys[head].key_256.aes_key, iv))
1175 goto end;
1176
Willy Tarreau9356dac2019-05-10 09:22:53 +02001177 HMAC_Init_ex(hctx, keys[head].key_256.hmac_key, 32, TLS_TICKET_HASH_FUNCT(), NULL);
Emeric Brun9e754772019-01-10 17:51:55 +01001178 ret = 1;
1179 }
Nenad Merdanovic05552d42015-02-27 19:56:49 +01001180 } else {
1181 for (i = 0; i < TLS_TICKETS_NO; i++) {
1182 if (!memcmp(key_name, keys[(head + i) % TLS_TICKETS_NO].name, 16))
1183 goto found;
1184 }
Christopher Faulet16f45c82018-02-16 11:23:49 +01001185 ret = 0;
1186 goto end;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01001187
Christopher Faulet16f45c82018-02-16 11:23:49 +01001188 found:
Emeric Brun9e754772019-01-10 17:51:55 +01001189 if (ref->key_size_bits == 128) {
Willy Tarreau9356dac2019-05-10 09:22:53 +02001190 HMAC_Init_ex(hctx, keys[(head + i) % TLS_TICKETS_NO].key_128.hmac_key, 16, TLS_TICKET_HASH_FUNCT(), NULL);
Emeric Brun9e754772019-01-10 17:51:55 +01001191 if(!EVP_DecryptInit_ex(ectx, EVP_aes_128_cbc(), NULL, keys[(head + i) % TLS_TICKETS_NO].key_128.aes_key, iv))
1192 goto end;
1193 /* 2 for key renewal, 1 if current key is still valid */
1194 ret = i ? 2 : 1;
1195 }
1196 else if (ref->key_size_bits == 256) {
Willy Tarreau9356dac2019-05-10 09:22:53 +02001197 HMAC_Init_ex(hctx, keys[(head + i) % TLS_TICKETS_NO].key_256.hmac_key, 32, TLS_TICKET_HASH_FUNCT(), NULL);
Emeric Brun9e754772019-01-10 17:51:55 +01001198 if(!EVP_DecryptInit_ex(ectx, EVP_aes_256_cbc(), NULL, keys[(head + i) % TLS_TICKETS_NO].key_256.aes_key, iv))
1199 goto end;
1200 /* 2 for key renewal, 1 if current key is still valid */
1201 ret = i ? 2 : 1;
1202 }
Nenad Merdanovic05552d42015-02-27 19:56:49 +01001203 }
Emeric Brun9e754772019-01-10 17:51:55 +01001204
Christopher Faulet16f45c82018-02-16 11:23:49 +01001205 end:
1206 HA_RWLOCK_RDUNLOCK(TLSKEYS_REF_LOCK, &ref->lock);
1207 return ret;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02001208}
1209
1210struct tls_keys_ref *tlskeys_ref_lookup(const char *filename)
1211{
1212 struct tls_keys_ref *ref;
1213
1214 list_for_each_entry(ref, &tlskeys_reference, list)
1215 if (ref->filename && strcmp(filename, ref->filename) == 0)
1216 return ref;
1217 return NULL;
1218}
1219
1220struct tls_keys_ref *tlskeys_ref_lookupid(int unique_id)
1221{
1222 struct tls_keys_ref *ref;
1223
1224 list_for_each_entry(ref, &tlskeys_reference, list)
1225 if (ref->unique_id == unique_id)
1226 return ref;
1227 return NULL;
1228}
1229
Emeric Brun9e754772019-01-10 17:51:55 +01001230/* Update the key into ref: if keysize doesnt
1231 * match existing ones, this function returns -1
1232 * else it returns 0 on success.
1233 */
1234int ssl_sock_update_tlskey_ref(struct tls_keys_ref *ref,
Willy Tarreau83061a82018-07-13 11:56:34 +02001235 struct buffer *tlskey)
Christopher Faulet16f45c82018-02-16 11:23:49 +01001236{
Emeric Brun9e754772019-01-10 17:51:55 +01001237 if (ref->key_size_bits == 128) {
1238 if (tlskey->data != sizeof(struct tls_sess_key_128))
1239 return -1;
1240 }
1241 else if (ref->key_size_bits == 256) {
1242 if (tlskey->data != sizeof(struct tls_sess_key_256))
1243 return -1;
1244 }
1245 else
1246 return -1;
1247
Christopher Faulet16f45c82018-02-16 11:23:49 +01001248 HA_RWLOCK_WRLOCK(TLSKEYS_REF_LOCK, &ref->lock);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001249 memcpy((char *) (ref->tlskeys + ((ref->tls_ticket_enc_index + 2) % TLS_TICKETS_NO)),
1250 tlskey->area, tlskey->data);
Christopher Faulet16f45c82018-02-16 11:23:49 +01001251 ref->tls_ticket_enc_index = (ref->tls_ticket_enc_index + 1) % TLS_TICKETS_NO;
1252 HA_RWLOCK_WRUNLOCK(TLSKEYS_REF_LOCK, &ref->lock);
Emeric Brun9e754772019-01-10 17:51:55 +01001253
1254 return 0;
Christopher Faulet16f45c82018-02-16 11:23:49 +01001255}
1256
Willy Tarreau83061a82018-07-13 11:56:34 +02001257int ssl_sock_update_tlskey(char *filename, struct buffer *tlskey, char **err)
Christopher Faulet16f45c82018-02-16 11:23:49 +01001258{
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02001259 struct tls_keys_ref *ref = tlskeys_ref_lookup(filename);
1260
1261 if(!ref) {
1262 memprintf(err, "Unable to locate the referenced filename: %s", filename);
1263 return 1;
1264 }
Emeric Brun9e754772019-01-10 17:51:55 +01001265 if (ssl_sock_update_tlskey_ref(ref, tlskey) < 0) {
1266 memprintf(err, "Invalid key size");
1267 return 1;
1268 }
1269
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02001270 return 0;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01001271}
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02001272
1273/* This function finalize the configuration parsing. Its set all the
Willy Tarreaud1c57502016-12-22 22:46:15 +01001274 * automatic ids. It's called just after the basic checks. It returns
1275 * 0 on success otherwise ERR_*.
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02001276 */
Willy Tarreaud1c57502016-12-22 22:46:15 +01001277static int tlskeys_finalize_config(void)
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02001278{
1279 int i = 0;
1280 struct tls_keys_ref *ref, *ref2, *ref3;
1281 struct list tkr = LIST_HEAD_INIT(tkr);
1282
1283 list_for_each_entry(ref, &tlskeys_reference, list) {
1284 if (ref->unique_id == -1) {
1285 /* Look for the first free id. */
1286 while (1) {
1287 list_for_each_entry(ref2, &tlskeys_reference, list) {
1288 if (ref2->unique_id == i) {
1289 i++;
1290 break;
1291 }
1292 }
1293 if (&ref2->list == &tlskeys_reference)
1294 break;
1295 }
1296
1297 /* Uses the unique id and increment it for the next entry. */
1298 ref->unique_id = i;
1299 i++;
1300 }
1301 }
1302
1303 /* This sort the reference list by id. */
1304 list_for_each_entry_safe(ref, ref2, &tlskeys_reference, list) {
1305 LIST_DEL(&ref->list);
1306 list_for_each_entry(ref3, &tkr, list) {
1307 if (ref->unique_id < ref3->unique_id) {
1308 LIST_ADDQ(&ref3->list, &ref->list);
1309 break;
1310 }
1311 }
1312 if (&ref3->list == &tkr)
1313 LIST_ADDQ(&tkr, &ref->list);
1314 }
1315
1316 /* swap root */
1317 LIST_ADD(&tkr, &tlskeys_reference);
1318 LIST_DEL(&tkr);
Willy Tarreaud1c57502016-12-22 22:46:15 +01001319 return 0;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02001320}
Nenad Merdanovic05552d42015-02-27 19:56:49 +01001321#endif /* SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB */
1322
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01001323#ifndef OPENSSL_NO_OCSP
yanbzhube2774d2015-12-10 15:07:30 -05001324int ssl_sock_get_ocsp_arg_kt_index(int evp_keytype)
1325{
1326 switch (evp_keytype) {
1327 case EVP_PKEY_RSA:
1328 return 2;
1329 case EVP_PKEY_DSA:
1330 return 0;
1331 case EVP_PKEY_EC:
1332 return 1;
1333 }
1334
1335 return -1;
1336}
1337
Emeric Brun4147b2e2014-06-16 18:36:30 +02001338/*
1339 * Callback used to set OCSP status extension content in server hello.
1340 */
1341int ssl_sock_ocsp_stapling_cbk(SSL *ssl, void *arg)
1342{
yanbzhube2774d2015-12-10 15:07:30 -05001343 struct certificate_ocsp *ocsp;
1344 struct ocsp_cbk_arg *ocsp_arg;
1345 char *ssl_buf;
1346 EVP_PKEY *ssl_pkey;
1347 int key_type;
1348 int index;
1349
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02001350 ocsp_arg = arg;
yanbzhube2774d2015-12-10 15:07:30 -05001351
1352 ssl_pkey = SSL_get_privatekey(ssl);
1353 if (!ssl_pkey)
1354 return SSL_TLSEXT_ERR_NOACK;
1355
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001356 key_type = EVP_PKEY_base_id(ssl_pkey);
yanbzhube2774d2015-12-10 15:07:30 -05001357
1358 if (ocsp_arg->is_single && ocsp_arg->single_kt == key_type)
1359 ocsp = ocsp_arg->s_ocsp;
1360 else {
1361 /* For multiple certs per context, we have to find the correct OCSP response based on
1362 * the certificate type
1363 */
1364 index = ssl_sock_get_ocsp_arg_kt_index(key_type);
1365
1366 if (index < 0)
1367 return SSL_TLSEXT_ERR_NOACK;
1368
1369 ocsp = ocsp_arg->m_ocsp[index];
1370
1371 }
Emeric Brun4147b2e2014-06-16 18:36:30 +02001372
1373 if (!ocsp ||
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001374 !ocsp->response.area ||
1375 !ocsp->response.data ||
Emeric Brun4f3c87a2014-06-20 15:46:13 +02001376 (ocsp->expire < now.tv_sec))
Emeric Brun4147b2e2014-06-16 18:36:30 +02001377 return SSL_TLSEXT_ERR_NOACK;
1378
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001379 ssl_buf = OPENSSL_malloc(ocsp->response.data);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001380 if (!ssl_buf)
1381 return SSL_TLSEXT_ERR_NOACK;
1382
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001383 memcpy(ssl_buf, ocsp->response.area, ocsp->response.data);
1384 SSL_set_tlsext_status_ocsp_resp(ssl, ssl_buf, ocsp->response.data);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001385
1386 return SSL_TLSEXT_ERR_OK;
1387}
1388
William Lallemand4a660132019-10-14 14:51:41 +02001389#endif
1390
1391#if ((defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP) || defined OPENSSL_IS_BORINGSSL)
Emeric Brun4147b2e2014-06-16 18:36:30 +02001392/*
1393 * This function enables the handling of OCSP status extension on 'ctx' if a
William Lallemand246c0242019-10-11 08:59:13 +02001394 * ocsp_response buffer was found in the cert_key_and_chain. To enable OCSP
1395 * status extension, the issuer's certificate is mandatory. It should be
1396 * present in ckch->ocsp_issuer.
Emeric Brun4147b2e2014-06-16 18:36:30 +02001397 *
William Lallemand246c0242019-10-11 08:59:13 +02001398 * In addition, the ckch->ocsp_reponse buffer is loaded as a DER format of an
1399 * OCSP response. If file is empty or content is not a valid OCSP response,
1400 * OCSP status extension is enabled but OCSP response is ignored (a warning is
1401 * displayed).
Emeric Brun4147b2e2014-06-16 18:36:30 +02001402 *
1403 * Returns 1 if no ".ocsp" file found, 0 if OCSP status extension is
Joseph Herlant017b3da2018-11-15 09:07:59 -08001404 * successfully enabled, or -1 in other error case.
Emeric Brun4147b2e2014-06-16 18:36:30 +02001405 */
William Lallemand4a660132019-10-14 14:51:41 +02001406#ifndef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet6f507c72020-02-18 15:56:39 +01001407static int ssl_sock_load_ocsp(SSL_CTX *ctx, const struct cert_key_and_chain *ckch, STACK_OF(X509) *chain)
Emeric Brun4147b2e2014-06-16 18:36:30 +02001408{
Emmanuel Hocdet6f507c72020-02-18 15:56:39 +01001409 X509 *x, *issuer;
Emeric Brun4147b2e2014-06-16 18:36:30 +02001410 OCSP_CERTID *cid = NULL;
Emeric Brun4147b2e2014-06-16 18:36:30 +02001411 int i, ret = -1;
Emeric Brun4147b2e2014-06-16 18:36:30 +02001412 struct certificate_ocsp *ocsp = NULL, *iocsp;
1413 char *warn = NULL;
1414 unsigned char *p;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001415 void (*callback) (void);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001416
Emeric Brun4147b2e2014-06-16 18:36:30 +02001417
William Lallemand246c0242019-10-11 08:59:13 +02001418 x = ckch->cert;
Emeric Brun4147b2e2014-06-16 18:36:30 +02001419 if (!x)
1420 goto out;
1421
William Lallemand246c0242019-10-11 08:59:13 +02001422 issuer = ckch->ocsp_issuer;
Emmanuel Hocdet6f507c72020-02-18 15:56:39 +01001423 /* take issuer from chain over ocsp_issuer, is what is done historicaly */
1424 if (chain) {
1425 /* check if one of the certificate of the chain is the issuer */
1426 for (i = 0; i < sk_X509_num(chain); i++) {
1427 X509 *ti = sk_X509_value(chain, i);
1428 if (X509_check_issued(ti, x) == X509_V_OK) {
1429 issuer = ti;
1430 break;
1431 }
1432 }
1433 }
William Lallemand246c0242019-10-11 08:59:13 +02001434 if (!issuer)
1435 goto out;
Emeric Brun4147b2e2014-06-16 18:36:30 +02001436
1437 cid = OCSP_cert_to_id(0, x, issuer);
1438 if (!cid)
1439 goto out;
1440
1441 i = i2d_OCSP_CERTID(cid, NULL);
1442 if (!i || (i > OCSP_MAX_CERTID_ASN1_LENGTH))
1443 goto out;
1444
Vincent Bernat02779b62016-04-03 13:48:43 +02001445 ocsp = calloc(1, sizeof(*ocsp));
Emeric Brun4147b2e2014-06-16 18:36:30 +02001446 if (!ocsp)
1447 goto out;
1448
1449 p = ocsp->key_data;
1450 i2d_OCSP_CERTID(cid, &p);
1451
1452 iocsp = (struct certificate_ocsp *)ebmb_insert(&cert_ocsp_tree, &ocsp->key, OCSP_MAX_CERTID_ASN1_LENGTH);
1453 if (iocsp == ocsp)
1454 ocsp = NULL;
1455
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001456#ifndef SSL_CTX_get_tlsext_status_cb
1457# define SSL_CTX_get_tlsext_status_cb(ctx, cb) \
1458 *cb = (void (*) (void))ctx->tlsext_status_cb;
1459#endif
1460 SSL_CTX_get_tlsext_status_cb(ctx, &callback);
1461
1462 if (!callback) {
Vincent Bernat02779b62016-04-03 13:48:43 +02001463 struct ocsp_cbk_arg *cb_arg = calloc(1, sizeof(*cb_arg));
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001464 EVP_PKEY *pkey;
yanbzhube2774d2015-12-10 15:07:30 -05001465
1466 cb_arg->is_single = 1;
1467 cb_arg->s_ocsp = iocsp;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001468
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001469 pkey = X509_get_pubkey(x);
1470 cb_arg->single_kt = EVP_PKEY_base_id(pkey);
1471 EVP_PKEY_free(pkey);
yanbzhube2774d2015-12-10 15:07:30 -05001472
1473 SSL_CTX_set_tlsext_status_cb(ctx, ssl_sock_ocsp_stapling_cbk);
1474 SSL_CTX_set_tlsext_status_arg(ctx, cb_arg);
1475 } else {
1476 /*
1477 * If the ctx has a status CB, then we have previously set an OCSP staple for this ctx
1478 * Update that cb_arg with the new cert's staple
1479 */
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001480 struct ocsp_cbk_arg *cb_arg;
yanbzhube2774d2015-12-10 15:07:30 -05001481 struct certificate_ocsp *tmp_ocsp;
1482 int index;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001483 int key_type;
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001484 EVP_PKEY *pkey;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001485
1486#ifdef SSL_CTX_get_tlsext_status_arg
1487 SSL_CTX_ctrl(ctx, SSL_CTRL_GET_TLSEXT_STATUS_REQ_CB_ARG, 0, &cb_arg);
1488#else
1489 cb_arg = ctx->tlsext_status_arg;
1490#endif
yanbzhube2774d2015-12-10 15:07:30 -05001491
1492 /*
1493 * The following few lines will convert cb_arg from a single ocsp to multi ocsp
1494 * the order of operations below matter, take care when changing it
1495 */
1496 tmp_ocsp = cb_arg->s_ocsp;
1497 index = ssl_sock_get_ocsp_arg_kt_index(cb_arg->single_kt);
1498 cb_arg->s_ocsp = NULL;
1499 cb_arg->m_ocsp[index] = tmp_ocsp;
1500 cb_arg->is_single = 0;
1501 cb_arg->single_kt = 0;
1502
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001503 pkey = X509_get_pubkey(x);
1504 key_type = EVP_PKEY_base_id(pkey);
1505 EVP_PKEY_free(pkey);
1506
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001507 index = ssl_sock_get_ocsp_arg_kt_index(key_type);
yanbzhube2774d2015-12-10 15:07:30 -05001508 if (index >= 0 && !cb_arg->m_ocsp[index])
1509 cb_arg->m_ocsp[index] = iocsp;
1510
1511 }
Emeric Brun4147b2e2014-06-16 18:36:30 +02001512
1513 ret = 0;
1514
1515 warn = NULL;
William Lallemand246c0242019-10-11 08:59:13 +02001516 if (ssl_sock_load_ocsp_response(ckch->ocsp_response, ocsp, cid, &warn)) {
William Lallemand3b5f3602019-10-16 18:05:05 +02001517 memprintf(&warn, "Loading: %s. Content will be ignored", warn ? warn : "failure");
Christopher Faulet767a84b2017-11-24 16:50:31 +01001518 ha_warning("%s.\n", warn);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001519 }
1520
1521out:
Emeric Brun4147b2e2014-06-16 18:36:30 +02001522 if (cid)
1523 OCSP_CERTID_free(cid);
1524
1525 if (ocsp)
1526 free(ocsp);
1527
1528 if (warn)
1529 free(warn);
1530
Emeric Brun4147b2e2014-06-16 18:36:30 +02001531 return ret;
1532}
William Lallemand4a660132019-10-14 14:51:41 +02001533#else /* OPENSSL_IS_BORINGSSL */
Emmanuel Hocdet6f507c72020-02-18 15:56:39 +01001534static int ssl_sock_load_ocsp(SSL_CTX *ctx, const struct cert_key_and_chain *ckch, STACK_OF(X509) *chain)
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02001535{
William Lallemand4a660132019-10-14 14:51:41 +02001536 return SSL_CTX_set_ocsp_response(ctx, (const uint8_t *)ckch->ocsp_response->area, ckch->ocsp_response->data);
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02001537}
1538#endif
1539
William Lallemand4a660132019-10-14 14:51:41 +02001540#endif
1541
1542
Willy Tarreau5db847a2019-05-09 14:13:35 +02001543#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001544
1545#define CT_EXTENSION_TYPE 18
1546
1547static int sctl_ex_index = -1;
1548
1549/*
1550 * Try to parse Signed Certificate Timestamp List structure. This function
1551 * makes only basic test if the data seems like SCTL. No signature validation
1552 * is performed.
1553 */
Willy Tarreau83061a82018-07-13 11:56:34 +02001554static int ssl_sock_parse_sctl(struct buffer *sctl)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001555{
1556 int ret = 1;
1557 int len, pos, sct_len;
1558 unsigned char *data;
1559
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001560 if (sctl->data < 2)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001561 goto out;
1562
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001563 data = (unsigned char *) sctl->area;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001564 len = (data[0] << 8) | data[1];
1565
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001566 if (len + 2 != sctl->data)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001567 goto out;
1568
1569 data = data + 2;
1570 pos = 0;
1571 while (pos < len) {
1572 if (len - pos < 2)
1573 goto out;
1574
1575 sct_len = (data[pos] << 8) | data[pos + 1];
1576 if (pos + sct_len + 2 > len)
1577 goto out;
1578
1579 pos += sct_len + 2;
1580 }
1581
1582 ret = 0;
1583
1584out:
1585 return ret;
1586}
1587
William Lallemand0dfae6c2019-10-16 18:06:58 +02001588/* Try to load a sctl from a buffer <buf> if not NULL, or read the file <sctl_path>
1589 * It fills the ckch->sctl buffer
1590 * return 0 on success or != 0 on failure */
1591static int ssl_sock_load_sctl_from_file(const char *sctl_path, char *buf, struct cert_key_and_chain *ckch, char **err)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001592{
1593 int fd = -1;
1594 int r = 0;
1595 int ret = 1;
William Lallemand0dfae6c2019-10-16 18:06:58 +02001596 struct buffer tmp;
1597 struct buffer *src;
1598 struct buffer *sctl;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001599
William Lallemand0dfae6c2019-10-16 18:06:58 +02001600 if (buf) {
1601 tmp.area = buf;
1602 tmp.data = strlen(buf);
1603 tmp.size = tmp.data + 1;
1604 src = &tmp;
1605 } else {
1606 fd = open(sctl_path, O_RDONLY);
1607 if (fd == -1)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001608 goto end;
William Lallemand0dfae6c2019-10-16 18:06:58 +02001609
1610 trash.data = 0;
1611 while (trash.data < trash.size) {
1612 r = read(fd, trash.area + trash.data, trash.size - trash.data);
1613 if (r < 0) {
1614 if (errno == EINTR)
1615 continue;
1616 goto end;
1617 }
1618 else if (r == 0) {
1619 break;
1620 }
1621 trash.data += r;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001622 }
William Lallemand0dfae6c2019-10-16 18:06:58 +02001623 src = &trash;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001624 }
1625
William Lallemand0dfae6c2019-10-16 18:06:58 +02001626 ret = ssl_sock_parse_sctl(src);
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001627 if (ret)
1628 goto end;
1629
William Lallemand0dfae6c2019-10-16 18:06:58 +02001630 sctl = calloc(1, sizeof(*sctl));
1631 if (!chunk_dup(sctl, src)) {
1632 free(sctl);
1633 sctl = NULL;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001634 goto end;
1635 }
Emmanuel Hocdet224a0872020-01-16 15:15:49 +01001636 /* no error, fill ckch with new context, old context must be free */
1637 if (ckch->sctl) {
1638 free(ckch->sctl->area);
1639 ckch->sctl->area = NULL;
1640 free(ckch->sctl);
1641 }
William Lallemand0dfae6c2019-10-16 18:06:58 +02001642 ckch->sctl = sctl;
Emmanuel Hocdet224a0872020-01-16 15:15:49 +01001643 ret = 0;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001644end:
1645 if (fd != -1)
1646 close(fd);
1647
1648 return ret;
1649}
1650
1651int ssl_sock_sctl_add_cbk(SSL *ssl, unsigned ext_type, const unsigned char **out, size_t *outlen, int *al, void *add_arg)
1652{
Willy Tarreau83061a82018-07-13 11:56:34 +02001653 struct buffer *sctl = add_arg;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001654
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001655 *out = (unsigned char *) sctl->area;
1656 *outlen = sctl->data;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001657
1658 return 1;
1659}
1660
1661int ssl_sock_sctl_parse_cbk(SSL *s, unsigned int ext_type, const unsigned char *in, size_t inlen, int *al, void *parse_arg)
1662{
1663 return 1;
1664}
1665
William Lallemanda17f4112019-10-10 15:16:44 +02001666static int ssl_sock_load_sctl(SSL_CTX *ctx, struct buffer *sctl)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001667{
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001668 int ret = -1;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001669
William Lallemanda17f4112019-10-10 15:16:44 +02001670 if (!SSL_CTX_add_server_custom_ext(ctx, CT_EXTENSION_TYPE, ssl_sock_sctl_add_cbk, NULL, sctl, ssl_sock_sctl_parse_cbk, NULL))
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001671 goto out;
1672
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001673 SSL_CTX_set_ex_data(ctx, sctl_ex_index, sctl);
1674
1675 ret = 0;
1676
1677out:
1678 return ret;
1679}
1680
1681#endif
1682
Emeric Brune1f38db2012-09-03 20:36:47 +02001683void ssl_sock_infocbk(const SSL *ssl, int where, int ret)
1684{
Thierry FOURNIER28962c92018-06-17 21:37:05 +02001685 struct connection *conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001686 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
Emeric Brund8b2bb52014-01-28 15:43:53 +01001687 BIO *write_bio;
Willy Tarreau622317d2015-02-27 16:36:16 +01001688 (void)ret; /* shut gcc stupid warning */
Emeric Brune1f38db2012-09-03 20:36:47 +02001689
Dirkjan Bussink526894f2019-01-21 09:35:03 -08001690#ifndef SSL_OP_NO_RENEGOTIATION
1691 /* Please note that BoringSSL defines this macro to zero so don't
1692 * change this to #if and do not assign a default value to this macro!
1693 */
Emeric Brune1f38db2012-09-03 20:36:47 +02001694 if (where & SSL_CB_HANDSHAKE_START) {
1695 /* Disable renegotiation (CVE-2009-3555) */
Willy Tarreauc192b0a2020-01-23 09:11:58 +01001696 if ((conn->flags & (CO_FL_WAIT_L6_CONN | CO_FL_EARLY_SSL_HS | CO_FL_EARLY_DATA)) == 0) {
Emeric Brune1f38db2012-09-03 20:36:47 +02001697 conn->flags |= CO_FL_ERROR;
Willy Tarreau20879a02012-12-03 16:32:10 +01001698 conn->err_code = CO_ER_SSL_RENEG;
1699 }
Emeric Brune1f38db2012-09-03 20:36:47 +02001700 }
Dirkjan Bussink526894f2019-01-21 09:35:03 -08001701#endif
Emeric Brund8b2bb52014-01-28 15:43:53 +01001702
1703 if ((where & SSL_CB_ACCEPT_LOOP) == SSL_CB_ACCEPT_LOOP) {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001704 if (!(ctx->xprt_st & SSL_SOCK_ST_FL_16K_WBFSIZE)) {
Emeric Brund8b2bb52014-01-28 15:43:53 +01001705 /* Long certificate chains optimz
1706 If write and read bios are differents, we
1707 consider that the buffering was activated,
1708 so we rise the output buffer size from 4k
1709 to 16k */
1710 write_bio = SSL_get_wbio(ssl);
1711 if (write_bio != SSL_get_rbio(ssl)) {
1712 BIO_set_write_buffer_size(write_bio, 16384);
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001713 ctx->xprt_st |= SSL_SOCK_ST_FL_16K_WBFSIZE;
Emeric Brund8b2bb52014-01-28 15:43:53 +01001714 }
1715 }
1716 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02001717}
1718
Emeric Brune64aef12012-09-21 13:15:06 +02001719/* Callback is called for each certificate of the chain during a verify
1720 ok is set to 1 if preverify detect no error on current certificate.
1721 Returns 0 to break the handshake, 1 otherwise. */
Evan Broderbe554312013-06-27 00:05:25 -07001722int ssl_sock_bind_verifycbk(int ok, X509_STORE_CTX *x_store)
Emeric Brune64aef12012-09-21 13:15:06 +02001723{
1724 SSL *ssl;
1725 struct connection *conn;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001726 struct ssl_sock_ctx *ctx;
Emeric Brun81c00f02012-09-21 14:31:21 +02001727 int err, depth;
Emeric Brune64aef12012-09-21 13:15:06 +02001728
1729 ssl = X509_STORE_CTX_get_ex_data(x_store, SSL_get_ex_data_X509_STORE_CTX_idx());
Thierry FOURNIER28962c92018-06-17 21:37:05 +02001730 conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Emeric Brune64aef12012-09-21 13:15:06 +02001731
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001732 ctx = conn->xprt_ctx;
1733
1734 ctx->xprt_st |= SSL_SOCK_ST_FL_VERIFY_DONE;
Emeric Brune64aef12012-09-21 13:15:06 +02001735
Emeric Brun81c00f02012-09-21 14:31:21 +02001736 if (ok) /* no errors */
1737 return ok;
1738
1739 depth = X509_STORE_CTX_get_error_depth(x_store);
1740 err = X509_STORE_CTX_get_error(x_store);
1741
1742 /* check if CA error needs to be ignored */
1743 if (depth > 0) {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001744 if (!SSL_SOCK_ST_TO_CA_ERROR(ctx->xprt_st)) {
1745 ctx->xprt_st |= SSL_SOCK_CA_ERROR_TO_ST(err);
1746 ctx->xprt_st |= SSL_SOCK_CAEDEPTH_TO_ST(depth);
Emeric Brunf282a812012-09-21 15:27:54 +02001747 }
1748
Willy Tarreau731248f2020-02-04 14:02:02 +01001749 if (err < 64 && __objt_listener(conn->target)->bind_conf->ca_ignerr & (1ULL << err)) {
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02001750 ssl_sock_dump_errors(conn);
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001751 ERR_clear_error();
Emeric Brun81c00f02012-09-21 14:31:21 +02001752 return 1;
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001753 }
Emeric Brun81c00f02012-09-21 14:31:21 +02001754
Willy Tarreau20879a02012-12-03 16:32:10 +01001755 conn->err_code = CO_ER_SSL_CA_FAIL;
Emeric Brun81c00f02012-09-21 14:31:21 +02001756 return 0;
1757 }
1758
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001759 if (!SSL_SOCK_ST_TO_CRTERROR(ctx->xprt_st))
1760 ctx->xprt_st |= SSL_SOCK_CRTERROR_TO_ST(err);
Emeric Brunf282a812012-09-21 15:27:54 +02001761
Emeric Brun81c00f02012-09-21 14:31:21 +02001762 /* check if certificate error needs to be ignored */
Willy Tarreau731248f2020-02-04 14:02:02 +01001763 if (err < 64 && __objt_listener(conn->target)->bind_conf->crt_ignerr & (1ULL << err)) {
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02001764 ssl_sock_dump_errors(conn);
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001765 ERR_clear_error();
Emeric Brun81c00f02012-09-21 14:31:21 +02001766 return 1;
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001767 }
Emeric Brun81c00f02012-09-21 14:31:21 +02001768
Willy Tarreau20879a02012-12-03 16:32:10 +01001769 conn->err_code = CO_ER_SSL_CRT_FAIL;
Emeric Brun81c00f02012-09-21 14:31:21 +02001770 return 0;
Emeric Brune64aef12012-09-21 13:15:06 +02001771}
1772
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001773static inline
1774void ssl_sock_parse_clienthello(int write_p, int version, int content_type,
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001775 const void *buf, size_t len, SSL *ssl)
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001776{
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001777 struct ssl_capture *capture;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001778 unsigned char *msg;
1779 unsigned char *end;
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001780 size_t rec_len;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001781
1782 /* This function is called for "from client" and "to server"
1783 * connections. The combination of write_p == 0 and content_type == 22
Joseph Herlant017b3da2018-11-15 09:07:59 -08001784 * is only available during "from client" connection.
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001785 */
1786
1787 /* "write_p" is set to 0 is the bytes are received messages,
1788 * otherwise it is set to 1.
1789 */
1790 if (write_p != 0)
1791 return;
1792
1793 /* content_type contains the type of message received or sent
1794 * according with the SSL/TLS protocol spec. This message is
1795 * encoded with one byte. The value 256 (two bytes) is used
1796 * for designing the SSL/TLS record layer. According with the
1797 * rfc6101, the expected message (other than 256) are:
1798 * - change_cipher_spec(20)
1799 * - alert(21)
1800 * - handshake(22)
1801 * - application_data(23)
1802 * - (255)
1803 * We are interessed by the handshake and specially the client
1804 * hello.
1805 */
1806 if (content_type != 22)
1807 return;
1808
1809 /* The message length is at least 4 bytes, containing the
1810 * message type and the message length.
1811 */
1812 if (len < 4)
1813 return;
1814
1815 /* First byte of the handshake message id the type of
1816 * message. The konwn types are:
1817 * - hello_request(0)
1818 * - client_hello(1)
1819 * - server_hello(2)
1820 * - certificate(11)
1821 * - server_key_exchange (12)
1822 * - certificate_request(13)
1823 * - server_hello_done(14)
1824 * We are interested by the client hello.
1825 */
1826 msg = (unsigned char *)buf;
1827 if (msg[0] != 1)
1828 return;
1829
1830 /* Next three bytes are the length of the message. The total length
1831 * must be this decoded length + 4. If the length given as argument
1832 * is not the same, we abort the protocol dissector.
1833 */
1834 rec_len = (msg[1] << 16) + (msg[2] << 8) + msg[3];
1835 if (len < rec_len + 4)
1836 return;
1837 msg += 4;
1838 end = msg + rec_len;
1839 if (end < msg)
1840 return;
1841
1842 /* Expect 2 bytes for protocol version (1 byte for major and 1 byte
1843 * for minor, the random, composed by 4 bytes for the unix time and
Baptiste Assmann6be139f2018-11-28 15:20:25 +01001844 * 28 bytes for unix payload. So we jump 1 + 1 + 4 + 28.
1845 */
1846 msg += 1 + 1 + 4 + 28;
1847 if (msg > end)
1848 return;
1849
1850 /* Next, is session id:
1851 * if present, we have to jump by length + 1 for the size information
1852 * if not present, we have to jump by 1 only
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001853 */
Baptiste Assmann6be139f2018-11-28 15:20:25 +01001854 if (msg[0] > 0)
1855 msg += msg[0];
1856 msg += 1;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001857 if (msg > end)
1858 return;
1859
1860 /* Next two bytes are the ciphersuite length. */
1861 if (msg + 2 > end)
1862 return;
1863 rec_len = (msg[0] << 8) + msg[1];
1864 msg += 2;
1865 if (msg + rec_len > end || msg + rec_len < msg)
1866 return;
1867
Willy Tarreaubafbe012017-11-24 17:34:44 +01001868 capture = pool_alloc_dirty(pool_head_ssl_capture);
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001869 if (!capture)
1870 return;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001871 /* Compute the xxh64 of the ciphersuite. */
1872 capture->xxh64 = XXH64(msg, rec_len, 0);
1873
1874 /* Capture the ciphersuite. */
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001875 capture->ciphersuite_len = (global_ssl.capture_cipherlist < rec_len) ?
1876 global_ssl.capture_cipherlist : rec_len;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001877 memcpy(capture->ciphersuite, msg, capture->ciphersuite_len);
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001878
1879 SSL_set_ex_data(ssl, ssl_capture_ptr_index, capture);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001880}
1881
Emeric Brun29f037d2014-04-25 19:05:36 +02001882/* Callback is called for ssl protocol analyse */
1883void ssl_sock_msgcbk(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg)
1884{
Emeric Brun29f037d2014-04-25 19:05:36 +02001885#ifdef TLS1_RT_HEARTBEAT
1886 /* test heartbeat received (write_p is set to 0
1887 for a received record) */
Willy Tarreauf51c6982014-04-25 20:02:39 +02001888 if ((content_type == TLS1_RT_HEARTBEAT) && (write_p == 0)) {
Thierry FOURNIER28962c92018-06-17 21:37:05 +02001889 struct connection *conn = SSL_get_ex_data(ssl, ssl_app_data_index);
William Lallemand7e1770b2019-05-13 14:31:34 +02001890 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
Willy Tarreauf51c6982014-04-25 20:02:39 +02001891 const unsigned char *p = buf;
1892 unsigned int payload;
1893
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001894 ctx->xprt_st |= SSL_SOCK_RECV_HEARTBEAT;
Willy Tarreauf51c6982014-04-25 20:02:39 +02001895
1896 /* Check if this is a CVE-2014-0160 exploitation attempt. */
1897 if (*p != TLS1_HB_REQUEST)
1898 return;
1899
Willy Tarreauaeed6722014-04-25 23:59:58 +02001900 if (len < 1 + 2 + 16) /* 1 type + 2 size + 0 payload + 16 padding */
Willy Tarreauf51c6982014-04-25 20:02:39 +02001901 goto kill_it;
1902
1903 payload = (p[1] * 256) + p[2];
Willy Tarreau3b2fdb62014-04-25 23:44:22 +02001904 if (3 + payload + 16 <= len)
Willy Tarreauf51c6982014-04-25 20:02:39 +02001905 return; /* OK no problem */
Willy Tarreauaeed6722014-04-25 23:59:58 +02001906 kill_it:
Willy Tarreau3b2fdb62014-04-25 23:44:22 +02001907 /* We have a clear heartbleed attack (CVE-2014-0160), the
1908 * advertised payload is larger than the advertised packet
1909 * length, so we have garbage in the buffer between the
1910 * payload and the end of the buffer (p+len). We can't know
1911 * if the SSL stack is patched, and we don't know if we can
1912 * safely wipe out the area between p+3+len and payload.
1913 * So instead, we prevent the response from being sent by
1914 * setting the max_send_fragment to 0 and we report an SSL
1915 * error, which will kill this connection. It will be reported
1916 * above as SSL_ERROR_SSL while an other handshake failure with
Willy Tarreauf51c6982014-04-25 20:02:39 +02001917 * a heartbeat message will be reported as SSL_ERROR_SYSCALL.
1918 */
Willy Tarreau3b2fdb62014-04-25 23:44:22 +02001919 ssl->max_send_fragment = 0;
Willy Tarreauf51c6982014-04-25 20:02:39 +02001920 SSLerr(SSL_F_TLS1_HEARTBEAT, SSL_R_SSL_HANDSHAKE_FAILURE);
1921 return;
1922 }
Emeric Brun29f037d2014-04-25 19:05:36 +02001923#endif
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001924 if (global_ssl.capture_cipherlist > 0)
1925 ssl_sock_parse_clienthello(write_p, version, content_type, buf, len, ssl);
Emeric Brun29f037d2014-04-25 19:05:36 +02001926}
1927
Bernard Spil13c53f82018-02-15 13:34:58 +01001928#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Olivier Houchardc7566002018-11-20 23:33:50 +01001929static int ssl_sock_srv_select_protos(SSL *s, unsigned char **out, unsigned char *outlen,
1930 const unsigned char *in, unsigned int inlen,
1931 void *arg)
1932{
1933 struct server *srv = arg;
1934
1935 if (SSL_select_next_proto(out, outlen, in, inlen, (unsigned char *)srv->ssl_ctx.npn_str,
1936 srv->ssl_ctx.npn_len) == OPENSSL_NPN_NEGOTIATED)
1937 return SSL_TLSEXT_ERR_OK;
1938 return SSL_TLSEXT_ERR_NOACK;
1939}
1940#endif
1941
1942#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02001943/* This callback is used so that the server advertises the list of
1944 * negociable protocols for NPN.
1945 */
1946static int ssl_sock_advertise_npn_protos(SSL *s, const unsigned char **data,
1947 unsigned int *len, void *arg)
1948{
Emmanuel Hocdet98263292016-12-29 18:26:15 +01001949 struct ssl_bind_conf *conf = arg;
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02001950
1951 *data = (const unsigned char *)conf->npn_str;
1952 *len = conf->npn_len;
1953 return SSL_TLSEXT_ERR_OK;
1954}
1955#endif
1956
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01001957#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02001958/* This callback is used so that the server advertises the list of
1959 * negociable protocols for ALPN.
1960 */
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01001961static int ssl_sock_advertise_alpn_protos(SSL *s, const unsigned char **out,
1962 unsigned char *outlen,
1963 const unsigned char *server,
1964 unsigned int server_len, void *arg)
Willy Tarreauab861d32013-04-02 02:30:41 +02001965{
Emmanuel Hocdet98263292016-12-29 18:26:15 +01001966 struct ssl_bind_conf *conf = arg;
Willy Tarreauab861d32013-04-02 02:30:41 +02001967
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01001968 if (SSL_select_next_proto((unsigned char**) out, outlen, (const unsigned char *)conf->alpn_str,
1969 conf->alpn_len, server, server_len) != OPENSSL_NPN_NEGOTIATED) {
1970 return SSL_TLSEXT_ERR_NOACK;
1971 }
Willy Tarreauab861d32013-04-02 02:30:41 +02001972 return SSL_TLSEXT_ERR_OK;
1973}
1974#endif
1975
Willy Tarreauc8ad3be2015-06-17 15:48:26 +02001976#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01001977#ifndef SSL_NO_GENERATE_CERTIFICATES
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001978
Christopher Faulet30548802015-06-11 13:39:32 +02001979/* Create a X509 certificate with the specified servername and serial. This
1980 * function returns a SSL_CTX object or NULL if an error occurs. */
Christopher Faulet7969a332015-10-09 11:15:03 +02001981static SSL_CTX *
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001982ssl_sock_do_create_cert(const char *servername, struct bind_conf *bind_conf, SSL *ssl)
Christopher Faulet31af49d2015-06-09 17:29:50 +02001983{
Christopher Faulet7969a332015-10-09 11:15:03 +02001984 X509 *cacert = bind_conf->ca_sign_cert;
1985 EVP_PKEY *capkey = bind_conf->ca_sign_pkey;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001986 SSL_CTX *ssl_ctx = NULL;
1987 X509 *newcrt = NULL;
1988 EVP_PKEY *pkey = NULL;
Emmanuel Hocdet15969292017-08-11 10:56:00 +02001989 SSL *tmp_ssl = NULL;
Emmanuel Hocdeta9b84022018-10-01 18:41:36 +02001990 CONF *ctmp = NULL;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001991 X509_NAME *name;
1992 const EVP_MD *digest;
1993 X509V3_CTX ctx;
1994 unsigned int i;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001995 int key_type;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001996
Christopher Faulet48a83322017-07-28 16:56:09 +02001997 /* Get the private key of the default certificate and use it */
Willy Tarreau5db847a2019-05-09 14:13:35 +02001998#if (HA_OPENSSL_VERSION_NUMBER >= 0x10002000L)
Emmanuel Hocdet15969292017-08-11 10:56:00 +02001999 pkey = SSL_CTX_get0_privatekey(bind_conf->default_ctx);
2000#else
2001 tmp_ssl = SSL_new(bind_conf->default_ctx);
2002 if (tmp_ssl)
2003 pkey = SSL_get_privatekey(tmp_ssl);
2004#endif
2005 if (!pkey)
Christopher Faulet31af49d2015-06-09 17:29:50 +02002006 goto mkcert_error;
2007
2008 /* Create the certificate */
2009 if (!(newcrt = X509_new()))
2010 goto mkcert_error;
2011
2012 /* Set version number for the certificate (X509v3) and the serial
2013 * number */
2014 if (X509_set_version(newcrt, 2L) != 1)
2015 goto mkcert_error;
Olivier Houchard2be5a4c2019-03-08 18:54:43 +01002016 ASN1_INTEGER_set(X509_get_serialNumber(newcrt), _HA_ATOMIC_ADD(&ssl_ctx_serial, 1));
Christopher Faulet31af49d2015-06-09 17:29:50 +02002017
2018 /* Set duration for the certificate */
Rosen Penev68185952018-12-14 08:47:02 -08002019 if (!X509_gmtime_adj(X509_getm_notBefore(newcrt), (long)-60*60*24) ||
2020 !X509_gmtime_adj(X509_getm_notAfter(newcrt),(long)60*60*24*365))
Christopher Faulet31af49d2015-06-09 17:29:50 +02002021 goto mkcert_error;
2022
2023 /* set public key in the certificate */
2024 if (X509_set_pubkey(newcrt, pkey) != 1)
2025 goto mkcert_error;
2026
2027 /* Set issuer name from the CA */
2028 if (!(name = X509_get_subject_name(cacert)))
2029 goto mkcert_error;
2030 if (X509_set_issuer_name(newcrt, name) != 1)
2031 goto mkcert_error;
2032
2033 /* Set the subject name using the same, but the CN */
2034 name = X509_NAME_dup(name);
2035 if (X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC,
2036 (const unsigned char *)servername,
2037 -1, -1, 0) != 1) {
2038 X509_NAME_free(name);
2039 goto mkcert_error;
2040 }
2041 if (X509_set_subject_name(newcrt, name) != 1) {
2042 X509_NAME_free(name);
2043 goto mkcert_error;
2044 }
2045 X509_NAME_free(name);
2046
2047 /* Add x509v3 extensions as specified */
Emmanuel Hocdeta9b84022018-10-01 18:41:36 +02002048 ctmp = NCONF_new(NULL);
Christopher Faulet31af49d2015-06-09 17:29:50 +02002049 X509V3_set_ctx(&ctx, cacert, newcrt, NULL, NULL, 0);
2050 for (i = 0; i < X509V3_EXT_SIZE; i++) {
2051 X509_EXTENSION *ext;
2052
Emmanuel Hocdeta9b84022018-10-01 18:41:36 +02002053 if (!(ext = X509V3_EXT_nconf(ctmp, &ctx, x509v3_ext_names[i], x509v3_ext_values[i])))
Christopher Faulet31af49d2015-06-09 17:29:50 +02002054 goto mkcert_error;
2055 if (!X509_add_ext(newcrt, ext, -1)) {
2056 X509_EXTENSION_free(ext);
2057 goto mkcert_error;
2058 }
2059 X509_EXTENSION_free(ext);
2060 }
2061
2062 /* Sign the certificate with the CA private key */
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002063
2064 key_type = EVP_PKEY_base_id(capkey);
2065
2066 if (key_type == EVP_PKEY_DSA)
2067 digest = EVP_sha1();
2068 else if (key_type == EVP_PKEY_RSA)
Christopher Faulet31af49d2015-06-09 17:29:50 +02002069 digest = EVP_sha256();
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002070 else if (key_type == EVP_PKEY_EC)
Christopher Faulet7969a332015-10-09 11:15:03 +02002071 digest = EVP_sha256();
2072 else {
Willy Tarreau9a1ab082019-05-09 13:26:41 +02002073#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000000fL) && !defined(OPENSSL_IS_BORINGSSL)
Christopher Faulet7969a332015-10-09 11:15:03 +02002074 int nid;
2075
2076 if (EVP_PKEY_get_default_digest_nid(capkey, &nid) <= 0)
2077 goto mkcert_error;
2078 if (!(digest = EVP_get_digestbynid(nid)))
2079 goto mkcert_error;
Christopher Faulete7db2162015-10-19 13:59:24 +02002080#else
2081 goto mkcert_error;
2082#endif
Christopher Faulet7969a332015-10-09 11:15:03 +02002083 }
2084
Christopher Faulet31af49d2015-06-09 17:29:50 +02002085 if (!(X509_sign(newcrt, capkey, digest)))
2086 goto mkcert_error;
2087
2088 /* Create and set the new SSL_CTX */
2089 if (!(ssl_ctx = SSL_CTX_new(SSLv23_server_method())))
2090 goto mkcert_error;
2091 if (!SSL_CTX_use_PrivateKey(ssl_ctx, pkey))
2092 goto mkcert_error;
2093 if (!SSL_CTX_use_certificate(ssl_ctx, newcrt))
2094 goto mkcert_error;
2095 if (!SSL_CTX_check_private_key(ssl_ctx))
2096 goto mkcert_error;
2097
2098 if (newcrt) X509_free(newcrt);
Christopher Faulet7969a332015-10-09 11:15:03 +02002099
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01002100#ifndef OPENSSL_NO_DH
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02002101 SSL_CTX_set_tmp_dh_callback(ssl_ctx, ssl_get_tmp_dh);
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01002102#endif
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02002103#if defined(SSL_CTX_set_tmp_ecdh) && !defined(OPENSSL_NO_ECDH)
2104 {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01002105 const char *ecdhe = (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe : ECDHE_DEFAULT_CURVE);
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02002106 EC_KEY *ecc;
2107 int nid;
2108
2109 if ((nid = OBJ_sn2nid(ecdhe)) == NID_undef)
2110 goto end;
2111 if (!(ecc = EC_KEY_new_by_curve_name(nid)))
2112 goto end;
2113 SSL_CTX_set_tmp_ecdh(ssl_ctx, ecc);
2114 EC_KEY_free(ecc);
2115 }
2116#endif
2117 end:
Christopher Faulet31af49d2015-06-09 17:29:50 +02002118 return ssl_ctx;
2119
2120 mkcert_error:
Emmanuel Hocdeta9b84022018-10-01 18:41:36 +02002121 if (ctmp) NCONF_free(ctmp);
Emmanuel Hocdet15969292017-08-11 10:56:00 +02002122 if (tmp_ssl) SSL_free(tmp_ssl);
Christopher Faulet31af49d2015-06-09 17:29:50 +02002123 if (ssl_ctx) SSL_CTX_free(ssl_ctx);
2124 if (newcrt) X509_free(newcrt);
Christopher Faulet31af49d2015-06-09 17:29:50 +02002125 return NULL;
2126}
2127
Christopher Faulet7969a332015-10-09 11:15:03 +02002128SSL_CTX *
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002129ssl_sock_create_cert(struct connection *conn, const char *servername, unsigned int key)
Christopher Faulet7969a332015-10-09 11:15:03 +02002130{
Willy Tarreau07d94e42018-09-20 10:57:52 +02002131 struct bind_conf *bind_conf = __objt_listener(conn->target)->bind_conf;
Olivier Houchard66ab4982019-02-26 18:37:15 +01002132 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002133
Olivier Houchard66ab4982019-02-26 18:37:15 +01002134 return ssl_sock_do_create_cert(servername, bind_conf, ctx->ssl);
Christopher Faulet7969a332015-10-09 11:15:03 +02002135}
2136
Christopher Faulet30548802015-06-11 13:39:32 +02002137/* Do a lookup for a certificate in the LRU cache used to store generated
Emeric Brun821bb9b2017-06-15 16:37:39 +02002138 * certificates and immediately assign it to the SSL session if not null. */
Christopher Faulet30548802015-06-11 13:39:32 +02002139SSL_CTX *
Emeric Brun821bb9b2017-06-15 16:37:39 +02002140ssl_sock_assign_generated_cert(unsigned int key, struct bind_conf *bind_conf, SSL *ssl)
Christopher Faulet30548802015-06-11 13:39:32 +02002141{
2142 struct lru64 *lru = NULL;
2143
2144 if (ssl_ctx_lru_tree) {
Willy Tarreau03f4ec42018-05-17 10:56:47 +02002145 HA_RWLOCK_WRLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002146 lru = lru64_lookup(key, ssl_ctx_lru_tree, bind_conf->ca_sign_cert, 0);
Emeric Brun821bb9b2017-06-15 16:37:39 +02002147 if (lru && lru->domain) {
2148 if (ssl)
2149 SSL_set_SSL_CTX(ssl, (SSL_CTX *)lru->data);
Willy Tarreau03f4ec42018-05-17 10:56:47 +02002150 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet30548802015-06-11 13:39:32 +02002151 return (SSL_CTX *)lru->data;
Emeric Brun821bb9b2017-06-15 16:37:39 +02002152 }
Willy Tarreau03f4ec42018-05-17 10:56:47 +02002153 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet30548802015-06-11 13:39:32 +02002154 }
2155 return NULL;
2156}
2157
Emeric Brun821bb9b2017-06-15 16:37:39 +02002158/* Same as <ssl_sock_assign_generated_cert> but without SSL session. This
2159 * function is not thread-safe, it should only be used to check if a certificate
2160 * exists in the lru cache (with no warranty it will not be removed by another
2161 * thread). It is kept for backward compatibility. */
2162SSL_CTX *
2163ssl_sock_get_generated_cert(unsigned int key, struct bind_conf *bind_conf)
2164{
2165 return ssl_sock_assign_generated_cert(key, bind_conf, NULL);
2166}
2167
Christopher Fauletd2cab922015-07-28 16:03:47 +02002168/* Set a certificate int the LRU cache used to store generated
2169 * certificate. Return 0 on success, otherwise -1 */
2170int
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002171ssl_sock_set_generated_cert(SSL_CTX *ssl_ctx, unsigned int key, struct bind_conf *bind_conf)
Christopher Faulet30548802015-06-11 13:39:32 +02002172{
2173 struct lru64 *lru = NULL;
2174
2175 if (ssl_ctx_lru_tree) {
Christopher Faulet2a944ee2017-11-07 10:42:54 +01002176 HA_RWLOCK_WRLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002177 lru = lru64_get(key, ssl_ctx_lru_tree, bind_conf->ca_sign_cert, 0);
Emeric Brun821bb9b2017-06-15 16:37:39 +02002178 if (!lru) {
Christopher Faulet2a944ee2017-11-07 10:42:54 +01002179 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Fauletd2cab922015-07-28 16:03:47 +02002180 return -1;
Emeric Brun821bb9b2017-06-15 16:37:39 +02002181 }
Christopher Faulet30548802015-06-11 13:39:32 +02002182 if (lru->domain && lru->data)
2183 lru->free((SSL_CTX *)lru->data);
Christopher Faulet7969a332015-10-09 11:15:03 +02002184 lru64_commit(lru, ssl_ctx, bind_conf->ca_sign_cert, 0, (void (*)(void *))SSL_CTX_free);
Christopher Faulet2a944ee2017-11-07 10:42:54 +01002185 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Fauletd2cab922015-07-28 16:03:47 +02002186 return 0;
Christopher Faulet30548802015-06-11 13:39:32 +02002187 }
Christopher Fauletd2cab922015-07-28 16:03:47 +02002188 return -1;
Christopher Faulet30548802015-06-11 13:39:32 +02002189}
2190
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002191/* Compute the key of the certificate. */
Christopher Faulet30548802015-06-11 13:39:32 +02002192unsigned int
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002193ssl_sock_generated_cert_key(const void *data, size_t len)
Christopher Faulet30548802015-06-11 13:39:32 +02002194{
2195 return XXH32(data, len, ssl_ctx_lru_seed);
2196}
2197
Willy Tarreau2f63ef42015-10-20 15:16:01 +02002198/* Generate a cert and immediately assign it to the SSL session so that the cert's
2199 * refcount is maintained regardless of the cert's presence in the LRU cache.
2200 */
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002201static int
Christopher Faulet7969a332015-10-09 11:15:03 +02002202ssl_sock_generate_certificate(const char *servername, struct bind_conf *bind_conf, SSL *ssl)
Christopher Faulet31af49d2015-06-09 17:29:50 +02002203{
2204 X509 *cacert = bind_conf->ca_sign_cert;
Christopher Faulet31af49d2015-06-09 17:29:50 +02002205 SSL_CTX *ssl_ctx = NULL;
2206 struct lru64 *lru = NULL;
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002207 unsigned int key;
Christopher Faulet31af49d2015-06-09 17:29:50 +02002208
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002209 key = ssl_sock_generated_cert_key(servername, strlen(servername));
Christopher Faulet31af49d2015-06-09 17:29:50 +02002210 if (ssl_ctx_lru_tree) {
Christopher Faulet2a944ee2017-11-07 10:42:54 +01002211 HA_RWLOCK_WRLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002212 lru = lru64_get(key, ssl_ctx_lru_tree, cacert, 0);
Christopher Faulet31af49d2015-06-09 17:29:50 +02002213 if (lru && lru->domain)
2214 ssl_ctx = (SSL_CTX *)lru->data;
Christopher Fauletd2cab922015-07-28 16:03:47 +02002215 if (!ssl_ctx && lru) {
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002216 ssl_ctx = ssl_sock_do_create_cert(servername, bind_conf, ssl);
Christopher Faulet31af49d2015-06-09 17:29:50 +02002217 lru64_commit(lru, ssl_ctx, cacert, 0, (void (*)(void *))SSL_CTX_free);
Christopher Fauletd2cab922015-07-28 16:03:47 +02002218 }
Willy Tarreau2f63ef42015-10-20 15:16:01 +02002219 SSL_set_SSL_CTX(ssl, ssl_ctx);
Christopher Faulet2a944ee2017-11-07 10:42:54 +01002220 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002221 return 1;
Christopher Faulet31af49d2015-06-09 17:29:50 +02002222 }
Willy Tarreau2f63ef42015-10-20 15:16:01 +02002223 else {
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002224 ssl_ctx = ssl_sock_do_create_cert(servername, bind_conf, ssl);
Willy Tarreau2f63ef42015-10-20 15:16:01 +02002225 SSL_set_SSL_CTX(ssl, ssl_ctx);
2226 /* No LRU cache, this CTX will be released as soon as the session dies */
2227 SSL_CTX_free(ssl_ctx);
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002228 return 1;
Willy Tarreau2f63ef42015-10-20 15:16:01 +02002229 }
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002230 return 0;
2231}
2232static int
2233ssl_sock_generate_certificate_from_conn(struct bind_conf *bind_conf, SSL *ssl)
2234{
2235 unsigned int key;
Thierry FOURNIER28962c92018-06-17 21:37:05 +02002236 struct connection *conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002237
Willy Tarreauf5bdb642019-07-17 11:29:32 +02002238 if (conn_get_dst(conn)) {
Willy Tarreau085a1512019-07-17 14:47:35 +02002239 key = ssl_sock_generated_cert_key(conn->dst, get_addr_len(conn->dst));
Emeric Brun821bb9b2017-06-15 16:37:39 +02002240 if (ssl_sock_assign_generated_cert(key, bind_conf, ssl))
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002241 return 1;
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002242 }
2243 return 0;
Christopher Faulet31af49d2015-06-09 17:29:50 +02002244}
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002245#endif /* !defined SSL_NO_GENERATE_CERTIFICATES */
Christopher Faulet31af49d2015-06-09 17:29:50 +02002246
Willy Tarreau9a1ab082019-05-09 13:26:41 +02002247#if (HA_OPENSSL_VERSION_NUMBER < 0x1010000fL)
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002248typedef enum { SET_CLIENT, SET_SERVER } set_context_func;
2249
2250static void ctx_set_SSLv3_func(SSL_CTX *ctx, set_context_func c)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002251{
Emmanuel Hocdet23877ab2017-07-12 12:53:02 +02002252#if SSL_OP_NO_SSLv3
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002253 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, SSLv3_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002254 : SSL_CTX_set_ssl_version(ctx, SSLv3_client_method());
2255#endif
2256}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002257static void ctx_set_TLSv10_func(SSL_CTX *ctx, set_context_func c) {
2258 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, TLSv1_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002259 : SSL_CTX_set_ssl_version(ctx, TLSv1_client_method());
2260}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002261static void ctx_set_TLSv11_func(SSL_CTX *ctx, set_context_func c) {
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002262#if SSL_OP_NO_TLSv1_1
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002263 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, TLSv1_1_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002264 : SSL_CTX_set_ssl_version(ctx, TLSv1_1_client_method());
2265#endif
2266}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002267static void ctx_set_TLSv12_func(SSL_CTX *ctx, set_context_func c) {
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002268#if SSL_OP_NO_TLSv1_2
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002269 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, TLSv1_2_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002270 : SSL_CTX_set_ssl_version(ctx, TLSv1_2_client_method());
2271#endif
2272}
Bertrand Jacquina25282b2018-08-14 00:56:13 +01002273/* TLSv1.2 is the last supported version in this context. */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002274static void ctx_set_TLSv13_func(SSL_CTX *ctx, set_context_func c) {}
2275/* Unusable in this context. */
2276static void ssl_set_SSLv3_func(SSL *ssl, set_context_func c) {}
2277static void ssl_set_TLSv10_func(SSL *ssl, set_context_func c) {}
2278static void ssl_set_TLSv11_func(SSL *ssl, set_context_func c) {}
2279static void ssl_set_TLSv12_func(SSL *ssl, set_context_func c) {}
2280static void ssl_set_TLSv13_func(SSL *ssl, set_context_func c) {}
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002281#else /* openssl >= 1.1.0 */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002282typedef enum { SET_MIN, SET_MAX } set_context_func;
2283
2284static void ctx_set_SSLv3_func(SSL_CTX *ctx, set_context_func c) {
2285 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, SSL3_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002286 : SSL_CTX_set_min_proto_version(ctx, SSL3_VERSION);
2287}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002288static void ssl_set_SSLv3_func(SSL *ssl, set_context_func c) {
2289 c == SET_MAX ? SSL_set_max_proto_version(ssl, SSL3_VERSION)
2290 : SSL_set_min_proto_version(ssl, SSL3_VERSION);
2291}
2292static void ctx_set_TLSv10_func(SSL_CTX *ctx, set_context_func c) {
2293 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002294 : SSL_CTX_set_min_proto_version(ctx, TLS1_VERSION);
2295}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002296static void ssl_set_TLSv10_func(SSL *ssl, set_context_func c) {
2297 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_VERSION)
2298 : SSL_set_min_proto_version(ssl, TLS1_VERSION);
2299}
2300static void ctx_set_TLSv11_func(SSL_CTX *ctx, set_context_func c) {
2301 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_1_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002302 : SSL_CTX_set_min_proto_version(ctx, TLS1_1_VERSION);
2303}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002304static void ssl_set_TLSv11_func(SSL *ssl, set_context_func c) {
2305 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_1_VERSION)
2306 : SSL_set_min_proto_version(ssl, TLS1_1_VERSION);
2307}
2308static void ctx_set_TLSv12_func(SSL_CTX *ctx, set_context_func c) {
2309 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_2_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002310 : SSL_CTX_set_min_proto_version(ctx, TLS1_2_VERSION);
2311}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002312static void ssl_set_TLSv12_func(SSL *ssl, set_context_func c) {
2313 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_2_VERSION)
2314 : SSL_set_min_proto_version(ssl, TLS1_2_VERSION);
2315}
2316static void ctx_set_TLSv13_func(SSL_CTX *ctx, set_context_func c) {
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002317#if SSL_OP_NO_TLSv1_3
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002318 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_3_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002319 : SSL_CTX_set_min_proto_version(ctx, TLS1_3_VERSION);
2320#endif
2321}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002322static void ssl_set_TLSv13_func(SSL *ssl, set_context_func c) {
2323#if SSL_OP_NO_TLSv1_3
2324 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_3_VERSION)
2325 : SSL_set_min_proto_version(ssl, TLS1_3_VERSION);
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002326#endif
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002327}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002328#endif
2329static void ctx_set_None_func(SSL_CTX *ctx, set_context_func c) { }
2330static void ssl_set_None_func(SSL *ssl, set_context_func c) { }
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002331
2332static struct {
2333 int option;
2334 uint16_t flag;
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002335 void (*ctx_set_version)(SSL_CTX *, set_context_func);
2336 void (*ssl_set_version)(SSL *, set_context_func);
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002337 const char *name;
2338} methodVersions[] = {
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002339 {0, 0, ctx_set_None_func, ssl_set_None_func, "NONE"}, /* CONF_TLSV_NONE */
2340 {SSL_OP_NO_SSLv3, MC_SSL_O_NO_SSLV3, ctx_set_SSLv3_func, ssl_set_SSLv3_func, "SSLv3"}, /* CONF_SSLV3 */
2341 {SSL_OP_NO_TLSv1, MC_SSL_O_NO_TLSV10, ctx_set_TLSv10_func, ssl_set_TLSv10_func, "TLSv1.0"}, /* CONF_TLSV10 */
2342 {SSL_OP_NO_TLSv1_1, MC_SSL_O_NO_TLSV11, ctx_set_TLSv11_func, ssl_set_TLSv11_func, "TLSv1.1"}, /* CONF_TLSV11 */
2343 {SSL_OP_NO_TLSv1_2, MC_SSL_O_NO_TLSV12, ctx_set_TLSv12_func, ssl_set_TLSv12_func, "TLSv1.2"}, /* CONF_TLSV12 */
2344 {SSL_OP_NO_TLSv1_3, MC_SSL_O_NO_TLSV13, ctx_set_TLSv13_func, ssl_set_TLSv13_func, "TLSv1.3"}, /* CONF_TLSV13 */
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002345};
2346
Emmanuel Hocdet530141f2017-03-01 18:54:56 +01002347static void ssl_sock_switchctx_set(SSL *ssl, SSL_CTX *ctx)
2348{
2349 SSL_set_verify(ssl, SSL_CTX_get_verify_mode(ctx), ssl_sock_bind_verifycbk);
2350 SSL_set_client_CA_list(ssl, SSL_dup_CA_list(SSL_CTX_get_client_CA_list(ctx)));
2351 SSL_set_SSL_CTX(ssl, ctx);
2352}
2353
Willy Tarreau5db847a2019-05-09 14:13:35 +02002354#if ((HA_OPENSSL_VERSION_NUMBER >= 0x10101000L) || defined(OPENSSL_IS_BORINGSSL))
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002355
2356static int ssl_sock_switchctx_err_cbk(SSL *ssl, int *al, void *priv)
2357{
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002358 struct bind_conf *s = priv;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002359 (void)al; /* shut gcc stupid warning */
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002360
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002361 if (SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name) || s->generate_certs)
2362 return SSL_TLSEXT_ERR_OK;
2363 return SSL_TLSEXT_ERR_NOACK;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002364}
2365
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002366#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002367static int ssl_sock_switchctx_cbk(const struct ssl_early_callback_ctx *ctx)
2368{
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002369 SSL *ssl = ctx->ssl;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002370#else
2371static int ssl_sock_switchctx_cbk(SSL *ssl, int *al, void *arg)
2372{
2373#endif
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002374 struct connection *conn;
2375 struct bind_conf *s;
2376 const uint8_t *extension_data;
2377 size_t extension_len;
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002378 int has_rsa_sig = 0, has_ecdsa_sig = 0;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002379
2380 char *wildp = NULL;
2381 const uint8_t *servername;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002382 size_t servername_len;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002383 struct ebmb_node *node, *n, *node_ecdsa = NULL, *node_rsa = NULL, *node_anonymous = NULL;
Olivier Houchardc2aae742017-09-22 18:26:28 +02002384 int allow_early = 0;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002385 int i;
2386
Thierry FOURNIER28962c92018-06-17 21:37:05 +02002387 conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Willy Tarreaua8825522018-10-15 13:20:07 +02002388 s = __objt_listener(conn->target)->bind_conf;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002389
Olivier Houchard9679ac92017-10-27 14:58:08 +02002390 if (s->ssl_conf.early_data)
Olivier Houchardc2aae742017-09-22 18:26:28 +02002391 allow_early = 1;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002392#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002393 if (SSL_early_callback_ctx_extension_get(ctx, TLSEXT_TYPE_server_name,
2394 &extension_data, &extension_len)) {
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002395#else
2396 if (SSL_client_hello_get0_ext(ssl, TLSEXT_TYPE_server_name, &extension_data, &extension_len)) {
2397#endif
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002398 /*
2399 * The server_name extension was given too much extensibility when it
2400 * was written, so parsing the normal case is a bit complex.
2401 */
2402 size_t len;
2403 if (extension_len <= 2)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002404 goto abort;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002405 /* Extract the length of the supplied list of names. */
2406 len = (*extension_data++) << 8;
2407 len |= *extension_data++;
2408 if (len + 2 != extension_len)
2409 goto abort;
2410 /*
2411 * The list in practice only has a single element, so we only consider
2412 * the first one.
2413 */
2414 if (len == 0 || *extension_data++ != TLSEXT_NAMETYPE_host_name)
2415 goto abort;
2416 extension_len = len - 1;
2417 /* Now we can finally pull out the byte array with the actual hostname. */
2418 if (extension_len <= 2)
2419 goto abort;
2420 len = (*extension_data++) << 8;
2421 len |= *extension_data++;
2422 if (len == 0 || len + 2 > extension_len || len > TLSEXT_MAXLEN_host_name
2423 || memchr(extension_data, 0, len) != NULL)
2424 goto abort;
2425 servername = extension_data;
2426 servername_len = len;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002427 } else {
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002428#if (!defined SSL_NO_GENERATE_CERTIFICATES)
2429 if (s->generate_certs && ssl_sock_generate_certificate_from_conn(s, ssl)) {
Olivier Houchardc2aae742017-09-22 18:26:28 +02002430 goto allow_early;
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002431 }
2432#endif
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002433 /* without SNI extension, is the default_ctx (need SSL_TLSEXT_ERR_NOACK) */
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002434 if (!s->strict_sni) {
William Lallemand21724f02019-11-04 17:56:13 +01002435 HA_RWLOCK_RDLOCK(SNI_LOCK, &s->sni_lock);
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002436 ssl_sock_switchctx_set(ssl, s->default_ctx);
William Lallemand21724f02019-11-04 17:56:13 +01002437 HA_RWLOCK_RDUNLOCK(SNI_LOCK, &s->sni_lock);
Olivier Houchardc2aae742017-09-22 18:26:28 +02002438 goto allow_early;
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002439 }
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002440 goto abort;
2441 }
2442
2443 /* extract/check clientHello informations */
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002444#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002445 if (SSL_early_callback_ctx_extension_get(ctx, TLSEXT_TYPE_signature_algorithms, &extension_data, &extension_len)) {
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002446#else
2447 if (SSL_client_hello_get0_ext(ssl, TLSEXT_TYPE_signature_algorithms, &extension_data, &extension_len)) {
2448#endif
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002449 uint8_t sign;
2450 size_t len;
2451 if (extension_len < 2)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002452 goto abort;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002453 len = (*extension_data++) << 8;
2454 len |= *extension_data++;
2455 if (len + 2 != extension_len)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002456 goto abort;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002457 if (len % 2 != 0)
2458 goto abort;
2459 for (; len > 0; len -= 2) {
2460 extension_data++; /* hash */
2461 sign = *extension_data++;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002462 switch (sign) {
2463 case TLSEXT_signature_rsa:
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002464 has_rsa_sig = 1;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002465 break;
2466 case TLSEXT_signature_ecdsa:
2467 has_ecdsa_sig = 1;
2468 break;
2469 default:
2470 continue;
2471 }
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002472 if (has_ecdsa_sig && has_rsa_sig)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002473 break;
2474 }
2475 } else {
Bertrand Jacquina25282b2018-08-14 00:56:13 +01002476 /* without TLSEXT_TYPE_signature_algorithms extension (< TLSv1.2) */
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002477 has_rsa_sig = 1;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002478 }
2479 if (has_ecdsa_sig) { /* in very rare case: has ecdsa sign but not a ECDSA cipher */
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002480 const SSL_CIPHER *cipher;
2481 size_t len;
2482 const uint8_t *cipher_suites;
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002483 has_ecdsa_sig = 0;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002484#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002485 len = ctx->cipher_suites_len;
2486 cipher_suites = ctx->cipher_suites;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002487#else
2488 len = SSL_client_hello_get0_ciphers(ssl, &cipher_suites);
2489#endif
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002490 if (len % 2 != 0)
2491 goto abort;
2492 for (; len != 0; len -= 2, cipher_suites += 2) {
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002493#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002494 uint16_t cipher_suite = (cipher_suites[0] << 8) | cipher_suites[1];
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002495 cipher = SSL_get_cipher_by_value(cipher_suite);
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002496#else
2497 cipher = SSL_CIPHER_find(ssl, cipher_suites);
2498#endif
Emmanuel Hocdet019f9b12017-10-02 17:12:06 +02002499 if (cipher && SSL_CIPHER_get_auth_nid(cipher) == NID_auth_ecdsa) {
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002500 has_ecdsa_sig = 1;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002501 break;
2502 }
2503 }
2504 }
2505
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002506 for (i = 0; i < trash.size && i < servername_len; i++) {
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002507 trash.area[i] = tolower(servername[i]);
2508 if (!wildp && (trash.area[i] == '.'))
2509 wildp = &trash.area[i];
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002510 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002511 trash.area[i] = 0;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002512
William Lallemand150bfa82019-09-19 17:12:49 +02002513 HA_RWLOCK_RDLOCK(SNI_LOCK, &s->sni_lock);
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002514
Emmanuel Hocdet3777e3a2019-11-06 16:05:34 +01002515 for (i = 0; i < 2; i++) {
2516 if (i == 0) /* lookup in full qualified names */
2517 node = ebst_lookup(&s->sni_ctx, trash.area);
2518 else if (i == 1 && wildp) /* lookup in wildcards names */
2519 node = ebst_lookup(&s->sni_w_ctx, wildp);
2520 else
2521 break;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002522 for (n = node; n; n = ebmb_next_dup(n)) {
Emmanuel Hocdet3777e3a2019-11-06 16:05:34 +01002523 /* lookup a not neg filter */
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002524 if (!container_of(n, struct sni_ctx, name)->neg) {
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002525 switch(container_of(n, struct sni_ctx, name)->kinfo.sig) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002526 case TLSEXT_signature_ecdsa:
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002527 if (!node_ecdsa)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002528 node_ecdsa = n;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002529 break;
2530 case TLSEXT_signature_rsa:
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002531 if (!node_rsa)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002532 node_rsa = n;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002533 break;
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002534 default: /* TLSEXT_signature_anonymous|dsa */
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002535 if (!node_anonymous)
2536 node_anonymous = n;
2537 break;
2538 }
2539 }
2540 }
Emmanuel Hocdet3777e3a2019-11-06 16:05:34 +01002541 /* select by key_signature priority order */
2542 node = (has_ecdsa_sig && node_ecdsa) ? node_ecdsa
2543 : ((has_rsa_sig && node_rsa) ? node_rsa
2544 : (node_anonymous ? node_anonymous
2545 : (node_ecdsa ? node_ecdsa /* no ecdsa signature case (< TLSv1.2) */
2546 : node_rsa /* no rsa signature case (far far away) */
2547 )));
2548 if (node) {
2549 /* switch ctx */
2550 struct ssl_bind_conf *conf = container_of(node, struct sni_ctx, name)->conf;
2551 ssl_sock_switchctx_set(ssl, container_of(node, struct sni_ctx, name)->ctx);
Olivier Houchard35a63cc2017-11-02 19:04:38 +01002552 if (conf) {
2553 methodVersions[conf->ssl_methods.min].ssl_set_version(ssl, SET_MIN);
2554 methodVersions[conf->ssl_methods.max].ssl_set_version(ssl, SET_MAX);
2555 if (conf->early_data)
2556 allow_early = 1;
2557 }
William Lallemand02010472019-10-18 11:02:19 +02002558 HA_RWLOCK_RDUNLOCK(SNI_LOCK, &s->sni_lock);
Olivier Houchard35a63cc2017-11-02 19:04:38 +01002559 goto allow_early;
Emmanuel Hocdet3777e3a2019-11-06 16:05:34 +01002560 }
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002561 }
William Lallemand150bfa82019-09-19 17:12:49 +02002562
William Lallemand02010472019-10-18 11:02:19 +02002563 HA_RWLOCK_RDUNLOCK(SNI_LOCK, &s->sni_lock);
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002564#if (!defined SSL_NO_GENERATE_CERTIFICATES)
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002565 if (s->generate_certs && ssl_sock_generate_certificate(trash.area, s, ssl)) {
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002566 /* switch ctx done in ssl_sock_generate_certificate */
Olivier Houchardc2aae742017-09-22 18:26:28 +02002567 goto allow_early;
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002568 }
2569#endif
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002570 if (!s->strict_sni) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002571 /* no certificate match, is the default_ctx */
William Lallemand21724f02019-11-04 17:56:13 +01002572 HA_RWLOCK_RDLOCK(SNI_LOCK, &s->sni_lock);
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002573 ssl_sock_switchctx_set(ssl, s->default_ctx);
William Lallemand21724f02019-11-04 17:56:13 +01002574 HA_RWLOCK_RDUNLOCK(SNI_LOCK, &s->sni_lock);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002575 }
Olivier Houchardc2aae742017-09-22 18:26:28 +02002576allow_early:
2577#ifdef OPENSSL_IS_BORINGSSL
2578 if (allow_early)
2579 SSL_set_early_data_enabled(ssl, 1);
2580#else
2581 if (!allow_early)
2582 SSL_set_max_early_data(ssl, 0);
2583#endif
2584 return 1;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002585 abort:
2586 /* abort handshake (was SSL_TLSEXT_ERR_ALERT_FATAL) */
2587 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002588#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002589 return ssl_select_cert_error;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002590#else
2591 *al = SSL_AD_UNRECOGNIZED_NAME;
2592 return 0;
2593#endif
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002594}
2595
2596#else /* OPENSSL_IS_BORINGSSL */
2597
Emeric Brunfc0421f2012-09-07 17:30:07 +02002598/* Sets the SSL ctx of <ssl> to match the advertised server name. Returns a
2599 * warning when no match is found, which implies the default (first) cert
2600 * will keep being used.
2601 */
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002602static int ssl_sock_switchctx_cbk(SSL *ssl, int *al, void *priv)
Emeric Brunfc0421f2012-09-07 17:30:07 +02002603{
2604 const char *servername;
2605 const char *wildp = NULL;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002606 struct ebmb_node *node, *n;
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002607 struct bind_conf *s = priv;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002608 int i;
2609 (void)al; /* shut gcc stupid warning */
2610
2611 servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
Emmanuel Hocdet65623372013-01-24 17:17:15 +01002612 if (!servername) {
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002613#if (!defined SSL_NO_GENERATE_CERTIFICATES)
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002614 if (s->generate_certs && ssl_sock_generate_certificate_from_conn(s, ssl))
2615 return SSL_TLSEXT_ERR_OK;
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002616#endif
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002617 if (s->strict_sni)
2618 return SSL_TLSEXT_ERR_ALERT_FATAL;
William Lallemand21724f02019-11-04 17:56:13 +01002619 HA_RWLOCK_RDLOCK(SNI_LOCK, &s->sni_lock);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002620 ssl_sock_switchctx_set(ssl, s->default_ctx);
William Lallemand21724f02019-11-04 17:56:13 +01002621 HA_RWLOCK_RDUNLOCK(SNI_LOCK, &s->sni_lock);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002622 return SSL_TLSEXT_ERR_NOACK;
Emmanuel Hocdet65623372013-01-24 17:17:15 +01002623 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02002624
Willy Tarreau19d14ef2012-10-29 16:51:55 +01002625 for (i = 0; i < trash.size; i++) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02002626 if (!servername[i])
2627 break;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002628 trash.area[i] = tolower(servername[i]);
2629 if (!wildp && (trash.area[i] == '.'))
2630 wildp = &trash.area[i];
Emeric Brunfc0421f2012-09-07 17:30:07 +02002631 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002632 trash.area[i] = 0;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002633
William Lallemand150bfa82019-09-19 17:12:49 +02002634 HA_RWLOCK_RDLOCK(SNI_LOCK, &s->sni_lock);
Emmanuel Hocdetc5fdf0f2019-11-04 15:49:46 +01002635 node = NULL;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002636 /* lookup in full qualified names */
Emmanuel Hocdetc5fdf0f2019-11-04 15:49:46 +01002637 for (n = ebst_lookup(&s->sni_ctx, trash.area); n; n = ebmb_next_dup(n)) {
2638 /* lookup a not neg filter */
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002639 if (!container_of(n, struct sni_ctx, name)->neg) {
2640 node = n;
2641 break;
Emmanuel Hocdet65623372013-01-24 17:17:15 +01002642 }
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002643 }
2644 if (!node && wildp) {
2645 /* lookup in wildcards names */
Emmanuel Hocdetc5fdf0f2019-11-04 15:49:46 +01002646 for (n = ebst_lookup(&s->sni_w_ctx, wildp); n; n = ebmb_next_dup(n)) {
2647 /* lookup a not neg filter */
2648 if (!container_of(n, struct sni_ctx, name)->neg) {
2649 node = n;
2650 break;
2651 }
2652 }
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002653 }
Emmanuel Hocdetc5fdf0f2019-11-04 15:49:46 +01002654 if (!node) {
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002655#if (!defined SSL_NO_GENERATE_CERTIFICATES)
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002656 if (s->generate_certs && ssl_sock_generate_certificate(servername, s, ssl)) {
2657 /* switch ctx done in ssl_sock_generate_certificate */
William Lallemand150bfa82019-09-19 17:12:49 +02002658 HA_RWLOCK_RDUNLOCK(SNI_LOCK, &s->sni_lock);
Christopher Faulet31af49d2015-06-09 17:29:50 +02002659 return SSL_TLSEXT_ERR_OK;
2660 }
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002661#endif
William Lallemand21724f02019-11-04 17:56:13 +01002662 if (s->strict_sni) {
2663 HA_RWLOCK_RDUNLOCK(SNI_LOCK, &s->sni_lock);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002664 return SSL_TLSEXT_ERR_ALERT_FATAL;
William Lallemand21724f02019-11-04 17:56:13 +01002665 }
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002666 ssl_sock_switchctx_set(ssl, s->default_ctx);
William Lallemand21724f02019-11-04 17:56:13 +01002667 HA_RWLOCK_RDUNLOCK(SNI_LOCK, &s->sni_lock);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002668 return SSL_TLSEXT_ERR_OK;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002669 }
2670
2671 /* switch ctx */
Emmanuel Hocdet530141f2017-03-01 18:54:56 +01002672 ssl_sock_switchctx_set(ssl, container_of(node, struct sni_ctx, name)->ctx);
William Lallemand150bfa82019-09-19 17:12:49 +02002673 HA_RWLOCK_RDUNLOCK(SNI_LOCK, &s->sni_lock);
Emeric Brunfc0421f2012-09-07 17:30:07 +02002674 return SSL_TLSEXT_ERR_OK;
2675}
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002676#endif /* (!) OPENSSL_IS_BORINGSSL */
Emeric Brunfc0421f2012-09-07 17:30:07 +02002677#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
2678
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002679#ifndef OPENSSL_NO_DH
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002680
2681static DH * ssl_get_dh_1024(void)
2682{
Remi Gacogned3a341a2015-05-29 16:26:17 +02002683 static unsigned char dh1024_p[]={
2684 0xFA,0xF9,0x2A,0x22,0x2A,0xA7,0x7F,0xE1,0x67,0x4E,0x53,0xF7,
2685 0x56,0x13,0xC3,0xB1,0xE3,0x29,0x6B,0x66,0x31,0x6A,0x7F,0xB3,
2686 0xC2,0x68,0x6B,0xCB,0x1D,0x57,0x39,0x1D,0x1F,0xFF,0x1C,0xC9,
2687 0xA6,0xA4,0x98,0x82,0x31,0x5D,0x25,0xFF,0x8A,0xE0,0x73,0x96,
2688 0x81,0xC8,0x83,0x79,0xC1,0x5A,0x04,0xF8,0x37,0x0D,0xA8,0x3D,
2689 0xAE,0x74,0xBC,0xDB,0xB6,0xA4,0x75,0xD9,0x71,0x8A,0xA0,0x17,
2690 0x9E,0x2D,0xC8,0xA8,0xDF,0x2C,0x5F,0x82,0x95,0xF8,0x92,0x9B,
2691 0xA7,0x33,0x5F,0x89,0x71,0xC8,0x2D,0x6B,0x18,0x86,0xC4,0x94,
2692 0x22,0xA5,0x52,0x8D,0xF6,0xF6,0xD2,0x37,0x92,0x0F,0xA5,0xCC,
2693 0xDB,0x7B,0x1D,0x3D,0xA1,0x31,0xB7,0x80,0x8F,0x0B,0x67,0x5E,
2694 0x36,0xA5,0x60,0x0C,0xF1,0x95,0x33,0x8B,
2695 };
2696 static unsigned char dh1024_g[]={
2697 0x02,
2698 };
2699
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002700 BIGNUM *p;
2701 BIGNUM *g;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002702 DH *dh = DH_new();
2703 if (dh) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002704 p = BN_bin2bn(dh1024_p, sizeof dh1024_p, NULL);
2705 g = BN_bin2bn(dh1024_g, sizeof dh1024_g, NULL);
Remi Gacogned3a341a2015-05-29 16:26:17 +02002706
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002707 if (!p || !g) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002708 DH_free(dh);
2709 dh = NULL;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002710 } else {
2711 DH_set0_pqg(dh, p, NULL, g);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002712 }
2713 }
2714 return dh;
2715}
2716
2717static DH *ssl_get_dh_2048(void)
2718{
Remi Gacogned3a341a2015-05-29 16:26:17 +02002719 static unsigned char dh2048_p[]={
2720 0xEC,0x86,0xF8,0x70,0xA0,0x33,0x16,0xEC,0x05,0x1A,0x73,0x59,
2721 0xCD,0x1F,0x8B,0xF8,0x29,0xE4,0xD2,0xCF,0x52,0xDD,0xC2,0x24,
2722 0x8D,0xB5,0x38,0x9A,0xFB,0x5C,0xA4,0xE4,0xB2,0xDA,0xCE,0x66,
2723 0x50,0x74,0xA6,0x85,0x4D,0x4B,0x1D,0x30,0xB8,0x2B,0xF3,0x10,
2724 0xE9,0xA7,0x2D,0x05,0x71,0xE7,0x81,0xDF,0x8B,0x59,0x52,0x3B,
2725 0x5F,0x43,0x0B,0x68,0xF1,0xDB,0x07,0xBE,0x08,0x6B,0x1B,0x23,
2726 0xEE,0x4D,0xCC,0x9E,0x0E,0x43,0xA0,0x1E,0xDF,0x43,0x8C,0xEC,
2727 0xBE,0xBE,0x90,0xB4,0x51,0x54,0xB9,0x2F,0x7B,0x64,0x76,0x4E,
2728 0x5D,0xD4,0x2E,0xAE,0xC2,0x9E,0xAE,0x51,0x43,0x59,0xC7,0x77,
2729 0x9C,0x50,0x3C,0x0E,0xED,0x73,0x04,0x5F,0xF1,0x4C,0x76,0x2A,
2730 0xD8,0xF8,0xCF,0xFC,0x34,0x40,0xD1,0xB4,0x42,0x61,0x84,0x66,
2731 0x42,0x39,0x04,0xF8,0x68,0xB2,0x62,0xD7,0x55,0xED,0x1B,0x74,
2732 0x75,0x91,0xE0,0xC5,0x69,0xC1,0x31,0x5C,0xDB,0x7B,0x44,0x2E,
2733 0xCE,0x84,0x58,0x0D,0x1E,0x66,0x0C,0xC8,0x44,0x9E,0xFD,0x40,
2734 0x08,0x67,0x5D,0xFB,0xA7,0x76,0x8F,0x00,0x11,0x87,0xE9,0x93,
2735 0xF9,0x7D,0xC4,0xBC,0x74,0x55,0x20,0xD4,0x4A,0x41,0x2F,0x43,
2736 0x42,0x1A,0xC1,0xF2,0x97,0x17,0x49,0x27,0x37,0x6B,0x2F,0x88,
2737 0x7E,0x1C,0xA0,0xA1,0x89,0x92,0x27,0xD9,0x56,0x5A,0x71,0xC1,
2738 0x56,0x37,0x7E,0x3A,0x9D,0x05,0xE7,0xEE,0x5D,0x8F,0x82,0x17,
2739 0xBC,0xE9,0xC2,0x93,0x30,0x82,0xF9,0xF4,0xC9,0xAE,0x49,0xDB,
2740 0xD0,0x54,0xB4,0xD9,0x75,0x4D,0xFA,0x06,0xB8,0xD6,0x38,0x41,
2741 0xB7,0x1F,0x77,0xF3,
2742 };
2743 static unsigned char dh2048_g[]={
2744 0x02,
2745 };
2746
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002747 BIGNUM *p;
2748 BIGNUM *g;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002749 DH *dh = DH_new();
2750 if (dh) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002751 p = BN_bin2bn(dh2048_p, sizeof dh2048_p, NULL);
2752 g = BN_bin2bn(dh2048_g, sizeof dh2048_g, NULL);
Remi Gacogned3a341a2015-05-29 16:26:17 +02002753
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002754 if (!p || !g) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002755 DH_free(dh);
2756 dh = NULL;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002757 } else {
2758 DH_set0_pqg(dh, p, NULL, g);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002759 }
2760 }
2761 return dh;
2762}
2763
2764static DH *ssl_get_dh_4096(void)
2765{
Remi Gacogned3a341a2015-05-29 16:26:17 +02002766 static unsigned char dh4096_p[]={
2767 0xDE,0x16,0x94,0xCD,0x99,0x58,0x07,0xF1,0xF7,0x32,0x96,0x11,
2768 0x04,0x82,0xD4,0x84,0x72,0x80,0x99,0x06,0xCA,0xF0,0xA3,0x68,
2769 0x07,0xCE,0x64,0x50,0xE7,0x74,0x45,0x20,0x80,0x5E,0x4D,0xAD,
2770 0xA5,0xB6,0xED,0xFA,0x80,0x6C,0x3B,0x35,0xC4,0x9A,0x14,0x6B,
2771 0x32,0xBB,0xFD,0x1F,0x17,0x8E,0xB7,0x1F,0xD6,0xFA,0x3F,0x7B,
2772 0xEE,0x16,0xA5,0x62,0x33,0x0D,0xED,0xBC,0x4E,0x58,0xE5,0x47,
2773 0x4D,0xE9,0xAB,0x8E,0x38,0xD3,0x6E,0x90,0x57,0xE3,0x22,0x15,
2774 0x33,0xBD,0xF6,0x43,0x45,0xB5,0x10,0x0A,0xBE,0x2C,0xB4,0x35,
2775 0xB8,0x53,0x8D,0xAD,0xFB,0xA7,0x1F,0x85,0x58,0x41,0x7A,0x79,
2776 0x20,0x68,0xB3,0xE1,0x3D,0x08,0x76,0xBF,0x86,0x0D,0x49,0xE3,
2777 0x82,0x71,0x8C,0xB4,0x8D,0x81,0x84,0xD4,0xE7,0xBE,0x91,0xDC,
2778 0x26,0x39,0x48,0x0F,0x35,0xC4,0xCA,0x65,0xE3,0x40,0x93,0x52,
2779 0x76,0x58,0x7D,0xDD,0x51,0x75,0xDC,0x69,0x61,0xBF,0x47,0x2C,
2780 0x16,0x68,0x2D,0xC9,0x29,0xD3,0xE6,0xC0,0x99,0x48,0xA0,0x9A,
2781 0xC8,0x78,0xC0,0x6D,0x81,0x67,0x12,0x61,0x3F,0x71,0xBA,0x41,
2782 0x1F,0x6C,0x89,0x44,0x03,0xBA,0x3B,0x39,0x60,0xAA,0x28,0x55,
2783 0x59,0xAE,0xB8,0xFA,0xCB,0x6F,0xA5,0x1A,0xF7,0x2B,0xDD,0x52,
2784 0x8A,0x8B,0xE2,0x71,0xA6,0x5E,0x7E,0xD8,0x2E,0x18,0xE0,0x66,
2785 0xDF,0xDD,0x22,0x21,0x99,0x52,0x73,0xA6,0x33,0x20,0x65,0x0E,
2786 0x53,0xE7,0x6B,0x9B,0xC5,0xA3,0x2F,0x97,0x65,0x76,0xD3,0x47,
2787 0x23,0x77,0x12,0xB6,0x11,0x7B,0x24,0xED,0xF1,0xEF,0xC0,0xE2,
2788 0xA3,0x7E,0x67,0x05,0x3E,0x96,0x4D,0x45,0xC2,0x18,0xD1,0x73,
2789 0x9E,0x07,0xF3,0x81,0x6E,0x52,0x63,0xF6,0x20,0x76,0xB9,0x13,
2790 0xD2,0x65,0x30,0x18,0x16,0x09,0x16,0x9E,0x8F,0xF1,0xD2,0x10,
2791 0x5A,0xD3,0xD4,0xAF,0x16,0x61,0xDA,0x55,0x2E,0x18,0x5E,0x14,
2792 0x08,0x54,0x2E,0x2A,0x25,0xA2,0x1A,0x9B,0x8B,0x32,0xA9,0xFD,
2793 0xC2,0x48,0x96,0xE1,0x80,0xCA,0xE9,0x22,0x17,0xBB,0xCE,0x3E,
2794 0x9E,0xED,0xC7,0xF1,0x1F,0xEC,0x17,0x21,0xDC,0x7B,0x82,0x48,
2795 0x8E,0xBB,0x4B,0x9D,0x5B,0x04,0x04,0xDA,0xDB,0x39,0xDF,0x01,
2796 0x40,0xC3,0xAA,0x26,0x23,0x89,0x75,0xC6,0x0B,0xD0,0xA2,0x60,
2797 0x6A,0xF1,0xCC,0x65,0x18,0x98,0x1B,0x52,0xD2,0x74,0x61,0xCC,
2798 0xBD,0x60,0xAE,0xA3,0xA0,0x66,0x6A,0x16,0x34,0x92,0x3F,0x41,
2799 0x40,0x31,0x29,0xC0,0x2C,0x63,0xB2,0x07,0x8D,0xEB,0x94,0xB8,
2800 0xE8,0x47,0x92,0x52,0x93,0x6A,0x1B,0x7E,0x1A,0x61,0xB3,0x1B,
2801 0xF0,0xD6,0x72,0x9B,0xF1,0xB0,0xAF,0xBF,0x3E,0x65,0xEF,0x23,
2802 0x1D,0x6F,0xFF,0x70,0xCD,0x8A,0x4C,0x8A,0xA0,0x72,0x9D,0xBE,
2803 0xD4,0xBB,0x24,0x47,0x4A,0x68,0xB5,0xF5,0xC6,0xD5,0x7A,0xCD,
2804 0xCA,0x06,0x41,0x07,0xAD,0xC2,0x1E,0xE6,0x54,0xA7,0xAD,0x03,
2805 0xD9,0x12,0xC1,0x9C,0x13,0xB1,0xC9,0x0A,0x43,0x8E,0x1E,0x08,
2806 0xCE,0x50,0x82,0x73,0x5F,0xA7,0x55,0x1D,0xD9,0x59,0xAC,0xB5,
2807 0xEA,0x02,0x7F,0x6C,0x5B,0x74,0x96,0x98,0x67,0x24,0xA3,0x0F,
2808 0x15,0xFC,0xA9,0x7D,0x3E,0x67,0xD1,0x70,0xF8,0x97,0xF3,0x67,
2809 0xC5,0x8C,0x88,0x44,0x08,0x02,0xC7,0x2B,
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002810 };
Remi Gacogned3a341a2015-05-29 16:26:17 +02002811 static unsigned char dh4096_g[]={
2812 0x02,
2813 };
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002814
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002815 BIGNUM *p;
2816 BIGNUM *g;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002817 DH *dh = DH_new();
2818 if (dh) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002819 p = BN_bin2bn(dh4096_p, sizeof dh4096_p, NULL);
2820 g = BN_bin2bn(dh4096_g, sizeof dh4096_g, NULL);
Remi Gacogned3a341a2015-05-29 16:26:17 +02002821
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002822 if (!p || !g) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002823 DH_free(dh);
2824 dh = NULL;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002825 } else {
2826 DH_set0_pqg(dh, p, NULL, g);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002827 }
2828 }
2829 return dh;
2830}
2831
2832/* Returns Diffie-Hellman parameters matching the private key length
Willy Tarreauef934602016-12-22 23:12:01 +01002833 but not exceeding global_ssl.default_dh_param */
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002834static DH *ssl_get_tmp_dh(SSL *ssl, int export, int keylen)
2835{
2836 DH *dh = NULL;
2837 EVP_PKEY *pkey = SSL_get_privatekey(ssl);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002838 int type;
2839
2840 type = pkey ? EVP_PKEY_base_id(pkey) : EVP_PKEY_NONE;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002841
2842 /* The keylen supplied by OpenSSL can only be 512 or 1024.
2843 See ssl3_send_server_key_exchange() in ssl/s3_srvr.c
2844 */
2845 if (type == EVP_PKEY_RSA || type == EVP_PKEY_DSA) {
2846 keylen = EVP_PKEY_bits(pkey);
2847 }
2848
Willy Tarreauef934602016-12-22 23:12:01 +01002849 if (keylen > global_ssl.default_dh_param) {
2850 keylen = global_ssl.default_dh_param;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002851 }
2852
Remi Gacogned3a341a2015-05-29 16:26:17 +02002853 if (keylen >= 4096) {
Remi Gacogne8de54152014-07-15 11:36:40 +02002854 dh = local_dh_4096;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002855 }
2856 else if (keylen >= 2048) {
Remi Gacogne8de54152014-07-15 11:36:40 +02002857 dh = local_dh_2048;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002858 }
2859 else {
Remi Gacogne8de54152014-07-15 11:36:40 +02002860 dh = local_dh_1024;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002861 }
2862
2863 return dh;
2864}
2865
Remi Gacogne47783ef2015-05-29 15:53:22 +02002866static DH * ssl_sock_get_dh_from_file(const char *filename)
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002867{
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002868 DH *dh = NULL;
Remi Gacogne47783ef2015-05-29 15:53:22 +02002869 BIO *in = BIO_new(BIO_s_file());
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002870
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002871 if (in == NULL)
2872 goto end;
2873
Remi Gacogne47783ef2015-05-29 15:53:22 +02002874 if (BIO_read_filename(in, filename) <= 0)
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002875 goto end;
2876
Remi Gacogne47783ef2015-05-29 15:53:22 +02002877 dh = PEM_read_bio_DHparams(in, NULL, NULL, NULL);
2878
2879end:
2880 if (in)
2881 BIO_free(in);
2882
Emeric Brune1b4ed42018-08-16 15:14:12 +02002883 ERR_clear_error();
2884
Remi Gacogne47783ef2015-05-29 15:53:22 +02002885 return dh;
2886}
2887
2888int ssl_sock_load_global_dh_param_from_file(const char *filename)
2889{
2890 global_dh = ssl_sock_get_dh_from_file(filename);
2891
2892 if (global_dh) {
2893 return 0;
2894 }
2895
2896 return -1;
2897}
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002898#endif
2899
William Lallemand9117de92019-10-04 00:29:42 +02002900/* Alloc and init a ckch_inst */
2901static struct ckch_inst *ckch_inst_new()
2902{
2903 struct ckch_inst *ckch_inst;
2904
2905 ckch_inst = calloc(1, sizeof *ckch_inst);
2906 if (ckch_inst)
2907 LIST_INIT(&ckch_inst->sni_ctx);
2908
2909 return ckch_inst;
2910}
2911
2912
2913/* This function allocates a sni_ctx and adds it to the ckch_inst */
William Lallemand1d29c742019-10-04 00:53:29 +02002914static int ckch_inst_add_cert_sni(SSL_CTX *ctx, struct ckch_inst *ckch_inst,
William Lallemand9117de92019-10-04 00:29:42 +02002915 struct bind_conf *s, struct ssl_bind_conf *conf,
2916 struct pkey_info kinfo, char *name, int order)
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002917{
2918 struct sni_ctx *sc;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002919 int wild = 0, neg = 0;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002920
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002921 if (*name == '!') {
2922 neg = 1;
2923 name++;
2924 }
2925 if (*name == '*') {
2926 wild = 1;
2927 name++;
2928 }
2929 /* !* filter is a nop */
2930 if (neg && wild)
2931 return order;
2932 if (*name) {
2933 int j, len;
2934 len = strlen(name);
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002935 for (j = 0; j < len && j < trash.size; j++)
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002936 trash.area[j] = tolower(name[j]);
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002937 if (j >= trash.size)
William Lallemandfe49bb32019-10-03 23:46:33 +02002938 return -1;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002939 trash.area[j] = 0;
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002940
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002941 sc = malloc(sizeof(struct sni_ctx) + len + 1);
Thierry FOURNIER / OZON.IO7a3bd3b2016-10-06 10:35:29 +02002942 if (!sc)
William Lallemandfe49bb32019-10-03 23:46:33 +02002943 return -1;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002944 memcpy(sc->name.key, trash.area, len + 1);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002945 sc->ctx = ctx;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01002946 sc->conf = conf;
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002947 sc->kinfo = kinfo;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002948 sc->order = order++;
2949 sc->neg = neg;
William Lallemand1d29c742019-10-04 00:53:29 +02002950 sc->wild = wild;
2951 sc->name.node.leaf_p = NULL;
William Lallemandcfca1422020-03-05 10:17:47 +01002952 sc->ckch_inst = ckch_inst;
William Lallemand1d29c742019-10-04 00:53:29 +02002953 LIST_ADDQ(&ckch_inst->sni_ctx, &sc->by_ckch_inst);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002954 }
2955 return order;
2956}
2957
William Lallemand6af03992019-07-23 15:00:54 +02002958/*
William Lallemand1d29c742019-10-04 00:53:29 +02002959 * Insert the sni_ctxs that are listed in the ckch_inst, in the bind_conf's sni_ctx tree
2960 * This function can't return an error.
2961 *
2962 * *CAUTION*: The caller must lock the sni tree if called in multithreading mode
2963 */
2964static void ssl_sock_load_cert_sni(struct ckch_inst *ckch_inst, struct bind_conf *bind_conf)
2965{
2966
2967 struct sni_ctx *sc0, *sc0b, *sc1;
2968 struct ebmb_node *node;
William Lallemand21724f02019-11-04 17:56:13 +01002969 int def = 0;
William Lallemand1d29c742019-10-04 00:53:29 +02002970
2971 list_for_each_entry_safe(sc0, sc0b, &ckch_inst->sni_ctx, by_ckch_inst) {
2972
2973 /* ignore if sc0 was already inserted in a tree */
2974 if (sc0->name.node.leaf_p)
2975 continue;
2976
2977 /* Check for duplicates. */
2978 if (sc0->wild)
2979 node = ebst_lookup(&bind_conf->sni_w_ctx, (char *)sc0->name.key);
2980 else
2981 node = ebst_lookup(&bind_conf->sni_ctx, (char *)sc0->name.key);
2982
2983 for (; node; node = ebmb_next_dup(node)) {
2984 sc1 = ebmb_entry(node, struct sni_ctx, name);
2985 if (sc1->ctx == sc0->ctx && sc1->conf == sc0->conf
2986 && sc1->neg == sc0->neg && sc1->wild == sc0->wild) {
2987 /* it's a duplicate, we should remove and free it */
2988 LIST_DEL(&sc0->by_ckch_inst);
2989 free(sc0);
2990 sc0 = NULL;
William Lallemande15029b2019-10-14 10:46:58 +02002991 break;
William Lallemand1d29c742019-10-04 00:53:29 +02002992 }
2993 }
2994
2995 /* if duplicate, ignore the insertion */
2996 if (!sc0)
2997 continue;
2998
2999 if (sc0->wild)
3000 ebst_insert(&bind_conf->sni_w_ctx, &sc0->name);
3001 else
3002 ebst_insert(&bind_conf->sni_ctx, &sc0->name);
William Lallemand21724f02019-11-04 17:56:13 +01003003
3004 /* replace the default_ctx if required with the first ctx */
3005 if (ckch_inst->is_default && !def) {
3006 /* we don't need to free the default_ctx because the refcount was not incremented */
3007 bind_conf->default_ctx = sc0->ctx;
3008 def = 1;
3009 }
William Lallemand1d29c742019-10-04 00:53:29 +02003010 }
3011}
3012
3013/*
William Lallemande3af8fb2019-10-08 11:36:53 +02003014 * tree used to store the ckchs ordered by filename/bundle name
William Lallemand6af03992019-07-23 15:00:54 +02003015 */
William Lallemande3af8fb2019-10-08 11:36:53 +02003016struct eb_root ckchs_tree = EB_ROOT_UNIQUE;
William Lallemand6af03992019-07-23 15:00:54 +02003017
William Lallemandfa892222019-07-23 16:06:08 +02003018
Emeric Brun7a883362019-10-17 13:27:40 +02003019/* Loads Diffie-Hellman parameter from a ckchs to an SSL_CTX.
3020 * If there is no DH paramater availaible in the ckchs, the global
3021 * DH parameter is loaded into the SSL_CTX and if there is no
3022 * DH parameter available in ckchs nor in global, the default
3023 * DH parameters are applied on the SSL_CTX.
3024 * Returns a bitfield containing the flags:
3025 * ERR_FATAL in any fatal error case
3026 * ERR_ALERT if a reason of the error is availabine in err
3027 * ERR_WARN if a warning is available into err
3028 * The value 0 means there is no error nor warning and
3029 * the operation succeed.
3030 */
William Lallemandfa892222019-07-23 16:06:08 +02003031#ifndef OPENSSL_NO_DH
Emeric Brun7a883362019-10-17 13:27:40 +02003032static int ssl_sock_load_dh_params(SSL_CTX *ctx, const struct cert_key_and_chain *ckch,
3033 const char *path, char **err)
William Lallemandfa892222019-07-23 16:06:08 +02003034{
Emeric Brun7a883362019-10-17 13:27:40 +02003035 int ret = 0;
William Lallemandfa892222019-07-23 16:06:08 +02003036 DH *dh = NULL;
3037
William Lallemanda8c73742019-07-31 18:31:34 +02003038 if (ckch && ckch->dh) {
William Lallemandfa892222019-07-23 16:06:08 +02003039 dh = ckch->dh;
Emeric Bruna9363eb2019-10-17 14:53:03 +02003040 if (!SSL_CTX_set_tmp_dh(ctx, dh)) {
3041 memprintf(err, "%sunable to load the DH parameter specified in '%s'",
3042 err && *err ? *err : "", path);
3043#if defined(SSL_CTX_set_dh_auto)
3044 SSL_CTX_set_dh_auto(ctx, 1);
3045 memprintf(err, "%s, SSL library will use an automatically generated DH parameter.\n",
3046 err && *err ? *err : "");
3047#else
3048 memprintf(err, "%s, DH ciphers won't be available.\n",
3049 err && *err ? *err : "");
3050#endif
3051 ret |= ERR_WARN;
3052 goto end;
3053 }
William Lallemandfa892222019-07-23 16:06:08 +02003054
3055 if (ssl_dh_ptr_index >= 0) {
3056 /* store a pointer to the DH params to avoid complaining about
3057 ssl-default-dh-param not being set for this SSL_CTX */
3058 SSL_CTX_set_ex_data(ctx, ssl_dh_ptr_index, dh);
3059 }
3060 }
3061 else if (global_dh) {
Emeric Bruna9363eb2019-10-17 14:53:03 +02003062 if (!SSL_CTX_set_tmp_dh(ctx, global_dh)) {
3063 memprintf(err, "%sunable to use the global DH parameter for certificate '%s'",
3064 err && *err ? *err : "", path);
3065#if defined(SSL_CTX_set_dh_auto)
3066 SSL_CTX_set_dh_auto(ctx, 1);
3067 memprintf(err, "%s, SSL library will use an automatically generated DH parameter.\n",
3068 err && *err ? *err : "");
3069#else
3070 memprintf(err, "%s, DH ciphers won't be available.\n",
3071 err && *err ? *err : "");
3072#endif
3073 ret |= ERR_WARN;
3074 goto end;
3075 }
William Lallemandfa892222019-07-23 16:06:08 +02003076 }
3077 else {
3078 /* Clear openssl global errors stack */
3079 ERR_clear_error();
3080
3081 if (global_ssl.default_dh_param <= 1024) {
3082 /* we are limited to DH parameter of 1024 bits anyway */
3083 if (local_dh_1024 == NULL)
3084 local_dh_1024 = ssl_get_dh_1024();
3085
Emeric Brun7a883362019-10-17 13:27:40 +02003086 if (local_dh_1024 == NULL) {
3087 memprintf(err, "%sunable to load default 1024 bits DH parameter for certificate '%s'.\n",
3088 err && *err ? *err : "", path);
3089 ret |= ERR_ALERT | ERR_FATAL;
William Lallemandfa892222019-07-23 16:06:08 +02003090 goto end;
Emeric Brun7a883362019-10-17 13:27:40 +02003091 }
William Lallemandfa892222019-07-23 16:06:08 +02003092
Emeric Bruna9363eb2019-10-17 14:53:03 +02003093 if (!SSL_CTX_set_tmp_dh(ctx, local_dh_1024)) {
3094 memprintf(err, "%sunable to load default 1024 bits DH parameter for certificate '%s'.\n",
3095 err && *err ? *err : "", path);
3096#if defined(SSL_CTX_set_dh_auto)
3097 SSL_CTX_set_dh_auto(ctx, 1);
3098 memprintf(err, "%s, SSL library will use an automatically generated DH parameter.\n",
3099 err && *err ? *err : "");
3100#else
3101 memprintf(err, "%s, DH ciphers won't be available.\n",
3102 err && *err ? *err : "");
3103#endif
3104 ret |= ERR_WARN;
3105 goto end;
3106 }
William Lallemandfa892222019-07-23 16:06:08 +02003107 }
3108 else {
3109 SSL_CTX_set_tmp_dh_callback(ctx, ssl_get_tmp_dh);
3110 }
William Lallemandfa892222019-07-23 16:06:08 +02003111 }
3112
3113end:
William Lallemand4dd145a2020-02-05 11:46:33 +01003114 ERR_clear_error();
William Lallemandfa892222019-07-23 16:06:08 +02003115 return ret;
3116}
3117#endif
yanbzhu08ce6ab2015-12-02 13:01:29 -05003118
yanbzhu488a4d22015-12-01 15:16:07 -05003119/* Frees the contents of a cert_key_and_chain
3120 */
3121static void ssl_sock_free_cert_key_and_chain_contents(struct cert_key_and_chain *ckch)
3122{
yanbzhu488a4d22015-12-01 15:16:07 -05003123 if (!ckch)
3124 return;
3125
3126 /* Free the certificate and set pointer to NULL */
3127 if (ckch->cert)
3128 X509_free(ckch->cert);
3129 ckch->cert = NULL;
3130
3131 /* Free the key and set pointer to NULL */
3132 if (ckch->key)
3133 EVP_PKEY_free(ckch->key);
3134 ckch->key = NULL;
3135
3136 /* Free each certificate in the chain */
Emmanuel Hocdet9246f8b2018-11-30 16:00:21 +01003137 if (ckch->chain)
3138 sk_X509_pop_free(ckch->chain, X509_free);
3139 ckch->chain = NULL;
yanbzhu488a4d22015-12-01 15:16:07 -05003140
William Lallemand455af502019-10-17 18:04:45 +02003141 if (ckch->dh)
3142 DH_free(ckch->dh);
3143 ckch->dh = NULL;
3144
3145 if (ckch->sctl) {
3146 free(ckch->sctl->area);
3147 ckch->sctl->area = NULL;
3148 free(ckch->sctl);
3149 ckch->sctl = NULL;
3150 }
3151
3152 if (ckch->ocsp_response) {
3153 free(ckch->ocsp_response->area);
3154 ckch->ocsp_response->area = NULL;
3155 free(ckch->ocsp_response);
3156 ckch->ocsp_response = NULL;
3157 }
William Lallemand5c3c96f2020-01-23 11:53:13 +01003158
3159 if (ckch->ocsp_issuer)
William Lallemanddad239d2020-01-23 11:59:02 +01003160 X509_free(ckch->ocsp_issuer);
William Lallemand5c3c96f2020-01-23 11:53:13 +01003161 ckch->ocsp_issuer = NULL;
yanbzhu488a4d22015-12-01 15:16:07 -05003162}
3163
William Lallemand8d0f8932019-10-17 18:03:58 +02003164/*
3165 *
3166 * This function copy a cert_key_and_chain in memory
3167 *
3168 * It's used to try to apply changes on a ckch before committing them, because
3169 * most of the time it's not possible to revert those changes
3170 *
3171 * Return a the dst or NULL
3172 */
3173static struct cert_key_and_chain *ssl_sock_copy_cert_key_and_chain(struct cert_key_and_chain *src,
3174 struct cert_key_and_chain *dst)
3175{
3176 if (src->cert) {
3177 dst->cert = src->cert;
3178 X509_up_ref(src->cert);
3179 }
3180
3181 if (src->key) {
3182 dst->key = src->key;
3183 EVP_PKEY_up_ref(src->key);
3184 }
3185
3186 if (src->chain) {
3187 dst->chain = X509_chain_up_ref(src->chain);
3188 }
3189
3190 if (src->dh) {
3191 DH_up_ref(src->dh);
3192 dst->dh = src->dh;
3193 }
3194
3195 if (src->sctl) {
3196 struct buffer *sctl;
3197
3198 sctl = calloc(1, sizeof(*sctl));
3199 if (!chunk_dup(sctl, src->sctl)) {
3200 free(sctl);
3201 sctl = NULL;
3202 goto error;
3203 }
3204 dst->sctl = sctl;
3205 }
3206
3207 if (src->ocsp_response) {
3208 struct buffer *ocsp_response;
3209
3210 ocsp_response = calloc(1, sizeof(*ocsp_response));
3211 if (!chunk_dup(ocsp_response, src->ocsp_response)) {
3212 free(ocsp_response);
3213 ocsp_response = NULL;
3214 goto error;
3215 }
3216 dst->ocsp_response = ocsp_response;
3217 }
3218
3219 if (src->ocsp_issuer) {
3220 X509_up_ref(src->ocsp_issuer);
3221 dst->ocsp_issuer = src->ocsp_issuer;
3222 }
3223
3224 return dst;
3225
3226error:
3227
3228 /* free everything */
3229 ssl_sock_free_cert_key_and_chain_contents(dst);
3230
3231 return NULL;
3232}
3233
3234
yanbzhu488a4d22015-12-01 15:16:07 -05003235/* checks if a key and cert exists in the ckch
3236 */
William Lallemand1633e392019-09-30 12:58:13 +02003237#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
yanbzhu488a4d22015-12-01 15:16:07 -05003238static int ssl_sock_is_ckch_valid(struct cert_key_and_chain *ckch)
3239{
3240 return (ckch->cert != NULL && ckch->key != NULL);
3241}
William Lallemand1633e392019-09-30 12:58:13 +02003242#endif
yanbzhu488a4d22015-12-01 15:16:07 -05003243
William Lallemandf9568fc2019-10-16 18:27:58 +02003244/*
3245 * return 0 on success or != 0 on failure
3246 */
3247static int ssl_sock_load_issuer_file_into_ckch(const char *path, char *buf, struct cert_key_and_chain *ckch, char **err)
3248{
3249 int ret = 1;
3250 BIO *in = NULL;
3251 X509 *issuer;
3252
3253 if (buf) {
3254 /* reading from a buffer */
3255 in = BIO_new_mem_buf(buf, -1);
3256 if (in == NULL) {
3257 memprintf(err, "%sCan't allocate memory\n", err && *err ? *err : "");
3258 goto end;
3259 }
3260
3261 } else {
3262 /* reading from a file */
3263 in = BIO_new(BIO_s_file());
3264 if (in == NULL)
3265 goto end;
3266
3267 if (BIO_read_filename(in, path) <= 0)
3268 goto end;
3269 }
3270
3271 issuer = PEM_read_bio_X509_AUX(in, NULL, NULL, NULL);
3272 if (!issuer) {
3273 memprintf(err, "%s'%s' cannot be read or parsed'.\n",
Tim Duesterhus93128532019-11-23 23:45:10 +01003274 err && *err ? *err : "", path);
William Lallemandf9568fc2019-10-16 18:27:58 +02003275 goto end;
3276 }
Emmanuel Hocdeteb73dc32020-01-16 14:45:00 +01003277 /* no error, fill ckch with new context, old context must be free */
3278 if (ckch->ocsp_issuer)
3279 X509_free(ckch->ocsp_issuer);
William Lallemandf9568fc2019-10-16 18:27:58 +02003280 ckch->ocsp_issuer = issuer;
Emmanuel Hocdeteb73dc32020-01-16 14:45:00 +01003281 ret = 0;
William Lallemandf9568fc2019-10-16 18:27:58 +02003282
3283end:
3284
3285 ERR_clear_error();
3286 if (in)
3287 BIO_free(in);
3288
3289 return ret;
3290}
3291
William Lallemand96a9c972019-10-17 11:56:17 +02003292
3293/*
3294 * Try to load a PEM file from a <path> or a buffer <buf>
William Lallemand4c5adbf2020-02-24 14:23:22 +01003295 * The PEM must contain at least a Certificate,
3296 * It could contain a DH, a certificate chain and a PrivateKey.
yanbzhu488a4d22015-12-01 15:16:07 -05003297 *
William Lallemand96a9c972019-10-17 11:56:17 +02003298 * If it failed you should not attempt to use the ckch but free it.
3299 *
3300 * Return 0 on success or != 0 on failure
yanbzhu488a4d22015-12-01 15:16:07 -05003301 */
William Lallemand96a9c972019-10-17 11:56:17 +02003302static int ssl_sock_load_pem_into_ckch(const char *path, char *buf, struct cert_key_and_chain *ckch , char **err)
yanbzhu488a4d22015-12-01 15:16:07 -05003303{
William Lallemandf11365b2019-09-19 14:25:58 +02003304 BIO *in = NULL;
yanbzhu488a4d22015-12-01 15:16:07 -05003305 int ret = 1;
Emmanuel Hocdet83cbd3c2019-10-25 11:55:03 +02003306 X509 *ca;
William Lallemand96a9c972019-10-17 11:56:17 +02003307 X509 *cert = NULL;
3308 EVP_PKEY *key = NULL;
Emmanuel Hocdet6b5b44e2019-12-20 17:47:12 +01003309 DH *dh = NULL;
3310 STACK_OF(X509) *chain = NULL;
William Lallemand96a9c972019-10-17 11:56:17 +02003311
3312 if (buf) {
3313 /* reading from a buffer */
3314 in = BIO_new_mem_buf(buf, -1);
3315 if (in == NULL) {
3316 memprintf(err, "%sCan't allocate memory\n", err && *err ? *err : "");
3317 goto end;
3318 }
yanbzhu488a4d22015-12-01 15:16:07 -05003319
William Lallemand96a9c972019-10-17 11:56:17 +02003320 } else {
3321 /* reading from a file */
William Lallemandf11365b2019-09-19 14:25:58 +02003322 in = BIO_new(BIO_s_file());
3323 if (in == NULL)
3324 goto end;
yanbzhu488a4d22015-12-01 15:16:07 -05003325
William Lallemandf11365b2019-09-19 14:25:58 +02003326 if (BIO_read_filename(in, path) <= 0)
3327 goto end;
William Lallemandf11365b2019-09-19 14:25:58 +02003328 }
yanbzhu488a4d22015-12-01 15:16:07 -05003329
yanbzhu488a4d22015-12-01 15:16:07 -05003330 /* Read Private Key */
William Lallemand96a9c972019-10-17 11:56:17 +02003331 key = PEM_read_bio_PrivateKey(in, NULL, NULL, NULL);
William Lallemand4c5adbf2020-02-24 14:23:22 +01003332 /* no need to check for errors here, because the private key could be loaded later */
yanbzhu488a4d22015-12-01 15:16:07 -05003333
Emmanuel Hocdet54227d82019-07-30 17:04:01 +02003334#ifndef OPENSSL_NO_DH
William Lallemandfa892222019-07-23 16:06:08 +02003335 /* Seek back to beginning of file */
3336 if (BIO_reset(in) == -1) {
3337 memprintf(err, "%san error occurred while reading the file '%s'.\n",
3338 err && *err ? *err : "", path);
3339 goto end;
3340 }
3341
William Lallemand96a9c972019-10-17 11:56:17 +02003342 dh = PEM_read_bio_DHparams(in, NULL, NULL, NULL);
3343 /* no need to return an error there, dh is not mandatory */
Emmanuel Hocdet54227d82019-07-30 17:04:01 +02003344#endif
William Lallemandfa892222019-07-23 16:06:08 +02003345
Willy Tarreaubb137a82016-04-06 19:02:38 +02003346 /* Seek back to beginning of file */
Thierry FOURNIER / OZON.IOd44ea3f2016-10-14 00:49:21 +02003347 if (BIO_reset(in) == -1) {
3348 memprintf(err, "%san error occurred while reading the file '%s'.\n",
3349 err && *err ? *err : "", path);
3350 goto end;
3351 }
Willy Tarreaubb137a82016-04-06 19:02:38 +02003352
3353 /* Read Certificate */
William Lallemand96a9c972019-10-17 11:56:17 +02003354 cert = PEM_read_bio_X509_AUX(in, NULL, NULL, NULL);
3355 if (cert == NULL) {
Willy Tarreaubb137a82016-04-06 19:02:38 +02003356 memprintf(err, "%sunable to load certificate from file '%s'.\n",
William Lallemand96a9c972019-10-17 11:56:17 +02003357 err && *err ? *err : "", path);
Willy Tarreaubb137a82016-04-06 19:02:38 +02003358 goto end;
3359 }
3360
William Lallemand96a9c972019-10-17 11:56:17 +02003361 /* Look for a Certificate Chain */
Emmanuel Hocdet6b5b44e2019-12-20 17:47:12 +01003362 while ((ca = PEM_read_bio_X509(in, NULL, NULL, NULL))) {
3363 if (chain == NULL)
3364 chain = sk_X509_new_null();
3365 if (!sk_X509_push(chain, ca)) {
William Lallemand96a9c972019-10-17 11:56:17 +02003366 X509_free(ca);
3367 goto end;
3368 }
3369 }
Emmanuel Hocdeted17f472019-10-24 18:28:33 +02003370
yanbzhu488a4d22015-12-01 15:16:07 -05003371 ret = ERR_get_error();
3372 if (ret && (ERR_GET_LIB(ret) != ERR_LIB_PEM && ERR_GET_REASON(ret) != PEM_R_NO_START_LINE)) {
3373 memprintf(err, "%sunable to load certificate chain from file '%s'.\n",
William Lallemand96a9c972019-10-17 11:56:17 +02003374 err && *err ? *err : "", path);
yanbzhu488a4d22015-12-01 15:16:07 -05003375 goto end;
William Lallemand246c0242019-10-11 08:59:13 +02003376 }
3377
William Lallemand75b15f72020-01-23 10:56:05 +01003378 /* once it loaded the PEM, it should remove everything else in the ckch */
3379 if (ckch->ocsp_response) {
3380 free(ckch->ocsp_response->area);
3381 ckch->ocsp_response->area = NULL;
3382 free(ckch->ocsp_response);
3383 ckch->ocsp_response = NULL;
3384 }
3385
3386 if (ckch->sctl) {
3387 free(ckch->sctl->area);
3388 ckch->sctl->area = NULL;
3389 free(ckch->sctl);
3390 ckch->sctl = NULL;
3391 }
3392
3393 if (ckch->ocsp_issuer) {
3394 X509_free(ckch->ocsp_issuer);
3395 ckch->ocsp_issuer = NULL;
3396 }
3397
Emmanuel Hocdet6b5b44e2019-12-20 17:47:12 +01003398 /* no error, fill ckch with new context, old context will be free at end: */
3399 SWAP(ckch->key, key);
3400 SWAP(ckch->dh, dh);
3401 SWAP(ckch->cert, cert);
3402 SWAP(ckch->chain, chain);
3403
William Lallemand246c0242019-10-11 08:59:13 +02003404 ret = 0;
3405
William Lallemand96a9c972019-10-17 11:56:17 +02003406end:
William Lallemand246c0242019-10-11 08:59:13 +02003407
3408 ERR_clear_error();
William Lallemand96a9c972019-10-17 11:56:17 +02003409 if (in)
William Lallemand246c0242019-10-11 08:59:13 +02003410 BIO_free(in);
Emmanuel Hocdet83cbd3c2019-10-25 11:55:03 +02003411 if (key)
3412 EVP_PKEY_free(key);
Emmanuel Hocdet6b5b44e2019-12-20 17:47:12 +01003413 if (dh)
3414 DH_free(dh);
Emmanuel Hocdet83cbd3c2019-10-25 11:55:03 +02003415 if (cert)
3416 X509_free(cert);
Emmanuel Hocdet6b5b44e2019-12-20 17:47:12 +01003417 if (chain)
3418 sk_X509_pop_free(chain, X509_free);
William Lallemanda17f4112019-10-10 15:16:44 +02003419
William Lallemand96a9c972019-10-17 11:56:17 +02003420 return ret;
3421}
3422
3423/*
William Lallemand4c5adbf2020-02-24 14:23:22 +01003424 * Try to load a private key file from a <path> or a buffer <buf>
3425 *
3426 * If it failed you should not attempt to use the ckch but free it.
3427 *
3428 * Return 0 on success or != 0 on failure
3429 */
3430static int ssl_sock_load_key_into_ckch(const char *path, char *buf, struct cert_key_and_chain *ckch , char **err)
3431{
3432 BIO *in = NULL;
3433 int ret = 1;
3434 EVP_PKEY *key = NULL;
3435
3436 if (buf) {
3437 /* reading from a buffer */
3438 in = BIO_new_mem_buf(buf, -1);
3439 if (in == NULL) {
3440 memprintf(err, "%sCan't allocate memory\n", err && *err ? *err : "");
3441 goto end;
3442 }
3443
3444 } else {
3445 /* reading from a file */
3446 in = BIO_new(BIO_s_file());
3447 if (in == NULL)
3448 goto end;
3449
3450 if (BIO_read_filename(in, path) <= 0)
3451 goto end;
3452 }
3453
3454 /* Read Private Key */
3455 key = PEM_read_bio_PrivateKey(in, NULL, NULL, NULL);
3456 if (key == NULL) {
3457 memprintf(err, "%sunable to load private key from file '%s'.\n",
3458 err && *err ? *err : "", path);
3459 goto end;
3460 }
3461
3462 ret = 0;
3463
3464 SWAP(ckch->key, key);
3465
3466end:
3467
3468 ERR_clear_error();
3469 if (in)
3470 BIO_free(in);
3471 if (key)
3472 EVP_PKEY_free(key);
3473
3474 return ret;
3475}
3476
3477/*
William Lallemand96a9c972019-10-17 11:56:17 +02003478 * Try to load in a ckch every files related to a ckch.
3479 * (PEM, sctl, ocsp, issuer etc.)
3480 *
3481 * This function is only used to load files during the configuration parsing,
3482 * it is not used with the CLI.
3483 *
3484 * This allows us to carry the contents of the file without having to read the
3485 * file multiple times. The caller must call
3486 * ssl_sock_free_cert_key_and_chain_contents.
3487 *
3488 * returns:
3489 * 0 on Success
3490 * 1 on SSL Failure
3491 */
3492static int ssl_sock_load_files_into_ckch(const char *path, struct cert_key_and_chain *ckch, char **err)
3493{
3494 int ret = 1;
3495
3496 /* try to load the PEM */
3497 if (ssl_sock_load_pem_into_ckch(path, NULL, ckch , err) != 0) {
3498 goto end;
3499 }
3500
William Lallemand4c5adbf2020-02-24 14:23:22 +01003501 /* try to load an external private key if it wasn't in the PEM */
3502 if ((ckch->key == NULL) && (global_ssl.extra_files & SSL_GF_KEY)) {
3503 char fp[MAXPATHLEN+1];
3504 struct stat st;
3505
3506 snprintf(fp, MAXPATHLEN+1, "%s.key", path);
3507 if (stat(fp, &st) == 0) {
3508 if (ssl_sock_load_key_into_ckch(fp, NULL, ckch, err)) {
3509 memprintf(err, "%s '%s' is present but cannot be read or parsed'.\n",
3510 err && *err ? *err : "", fp);
3511 goto end;
3512 }
3513 }
3514 }
3515
3516 if (ckch->key == NULL) {
3517 memprintf(err, "%sNo Private Key found in '%s' or '%s.key'.\n", err && *err ? *err : "", path, path);
3518 goto end;
3519 }
3520
3521 if (!X509_check_private_key(ckch->cert, ckch->key)) {
3522 memprintf(err, "%sinconsistencies between private key and certificate loaded '%s'.\n",
3523 err && *err ? *err : "", path);
3524 goto end;
3525 }
3526
William Lallemanda17f4112019-10-10 15:16:44 +02003527#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
3528 /* try to load the sctl file */
William Lallemand3af48e72020-02-03 17:15:52 +01003529 if (global_ssl.extra_files & SSL_GF_SCTL) {
William Lallemanda17f4112019-10-10 15:16:44 +02003530 char fp[MAXPATHLEN+1];
3531 struct stat st;
3532
3533 snprintf(fp, MAXPATHLEN+1, "%s.sctl", path);
3534 if (stat(fp, &st) == 0) {
William Lallemand0dfae6c2019-10-16 18:06:58 +02003535 if (ssl_sock_load_sctl_from_file(fp, NULL, ckch, err)) {
William Lallemanda17f4112019-10-10 15:16:44 +02003536 memprintf(err, "%s '%s.sctl' is present but cannot be read or parsed'.\n",
Tim Duesterhus93128532019-11-23 23:45:10 +01003537 err && *err ? *err : "", fp);
William Lallemanda17f4112019-10-10 15:16:44 +02003538 ret = 1;
3539 goto end;
3540 }
3541 }
3542 }
3543#endif
yanbzhu488a4d22015-12-01 15:16:07 -05003544
William Lallemand246c0242019-10-11 08:59:13 +02003545 /* try to load an ocsp response file */
William Lallemand3af48e72020-02-03 17:15:52 +01003546 if (global_ssl.extra_files & SSL_GF_OCSP) {
William Lallemand246c0242019-10-11 08:59:13 +02003547 char fp[MAXPATHLEN+1];
3548 struct stat st;
3549
3550 snprintf(fp, MAXPATHLEN+1, "%s.ocsp", path);
3551 if (stat(fp, &st) == 0) {
William Lallemand3b5f3602019-10-16 18:05:05 +02003552 if (ssl_sock_load_ocsp_response_from_file(fp, NULL, ckch, err)) {
William Lallemand246c0242019-10-11 08:59:13 +02003553 ret = 1;
3554 goto end;
3555 }
3556 }
3557 }
3558
Emmanuel Hocdeteaad5cc2019-10-25 12:19:00 +02003559#ifndef OPENSSL_IS_BORINGSSL /* Useless for BoringSSL */
William Lallemand3af48e72020-02-03 17:15:52 +01003560 if (ckch->ocsp_response && (global_ssl.extra_files & SSL_GF_OCSP_ISSUER)) {
William Lallemand246c0242019-10-11 08:59:13 +02003561 /* if no issuer was found, try to load an issuer from the .issuer */
Emmanuel Hocdet078156d2020-01-22 17:02:53 +01003562 if (!ckch->ocsp_issuer) {
William Lallemand246c0242019-10-11 08:59:13 +02003563 struct stat st;
3564 char fp[MAXPATHLEN+1];
3565
3566 snprintf(fp, MAXPATHLEN+1, "%s.issuer", path);
3567 if (stat(fp, &st) == 0) {
William Lallemandf9568fc2019-10-16 18:27:58 +02003568 if (ssl_sock_load_issuer_file_into_ckch(fp, NULL, ckch, err)) {
William Lallemand246c0242019-10-11 08:59:13 +02003569 ret = 1;
3570 goto end;
3571 }
3572
3573 if (X509_check_issued(ckch->ocsp_issuer, ckch->cert) != X509_V_OK) {
William Lallemand786188f2019-10-15 10:05:37 +02003574 memprintf(err, "%s '%s' is not an issuer'.\n",
Tim Duesterhus93128532019-11-23 23:45:10 +01003575 err && *err ? *err : "", fp);
William Lallemand246c0242019-10-11 08:59:13 +02003576 ret = 1;
3577 goto end;
3578 }
William Lallemand246c0242019-10-11 08:59:13 +02003579 }
3580 }
3581 }
Emmanuel Hocdeteaad5cc2019-10-25 12:19:00 +02003582#endif
William Lallemand246c0242019-10-11 08:59:13 +02003583
yanbzhu488a4d22015-12-01 15:16:07 -05003584 ret = 0;
3585
3586end:
3587
3588 ERR_clear_error();
yanbzhu488a4d22015-12-01 15:16:07 -05003589
3590 /* Something went wrong in one of the reads */
3591 if (ret != 0)
3592 ssl_sock_free_cert_key_and_chain_contents(ckch);
3593
3594 return ret;
3595}
3596
3597/* Loads the info in ckch into ctx
Emeric Bruna96b5822019-10-17 13:25:14 +02003598 * Returns a bitfield containing the flags:
3599 * ERR_FATAL in any fatal error case
3600 * ERR_ALERT if the reason of the error is available in err
3601 * ERR_WARN if a warning is available into err
3602 * The value 0 means there is no error nor warning and
3603 * the operation succeed.
yanbzhu488a4d22015-12-01 15:16:07 -05003604 */
3605static int ssl_sock_put_ckch_into_ctx(const char *path, const struct cert_key_and_chain *ckch, SSL_CTX *ctx, char **err)
3606{
Emeric Bruna96b5822019-10-17 13:25:14 +02003607 int errcode = 0;
Emmanuel Hocdetb90d2cb2020-02-18 15:27:32 +01003608 STACK_OF(X509) *find_chain = NULL;
Emeric Bruna96b5822019-10-17 13:25:14 +02003609
yanbzhu488a4d22015-12-01 15:16:07 -05003610 if (SSL_CTX_use_PrivateKey(ctx, ckch->key) <= 0) {
3611 memprintf(err, "%sunable to load SSL private key into SSL Context '%s'.\n",
3612 err && *err ? *err : "", path);
Emeric Bruna96b5822019-10-17 13:25:14 +02003613 errcode |= ERR_ALERT | ERR_FATAL;
3614 return errcode;
yanbzhu488a4d22015-12-01 15:16:07 -05003615 }
3616
3617 if (!SSL_CTX_use_certificate(ctx, ckch->cert)) {
3618 memprintf(err, "%sunable to load SSL certificate into SSL Context '%s'.\n",
3619 err && *err ? *err : "", path);
Emeric Bruna96b5822019-10-17 13:25:14 +02003620 errcode |= ERR_ALERT | ERR_FATAL;
3621 goto end;
yanbzhu488a4d22015-12-01 15:16:07 -05003622 }
3623
Emmanuel Hocdetb90d2cb2020-02-18 15:27:32 +01003624 if (ckch->chain) {
3625 find_chain = ckch->chain;
3626 } else {
3627 /* Find Certificate Chain in global */
3628 struct issuer_chain *issuer;
3629 issuer = ssl_get_issuer_chain(ckch->cert);
3630 if (issuer)
3631 find_chain = issuer->chain;
3632 }
William Lallemand85888572020-02-27 14:48:35 +01003633
3634 /* If we didn't find a chain we *MUST* use an empty X509 structure */
3635 if (find_chain == NULL)
3636 find_chain = sk_X509_new_null();
3637
yanbzhu488a4d22015-12-01 15:16:07 -05003638 /* Load all certs in the ckch into the ctx_chain for the ssl_ctx */
Emmanuel Hocdet1c65fdd2018-12-03 18:07:44 +01003639#ifdef SSL_CTX_set1_chain
Emmanuel Hocdetb90d2cb2020-02-18 15:27:32 +01003640 if (!SSL_CTX_set1_chain(ctx, find_chain)) {
Emmanuel Hocdet9246f8b2018-11-30 16:00:21 +01003641 memprintf(err, "%sunable to load chain certificate into SSL Context '%s'. Make sure you are linking against Openssl >= 1.0.2.\n",
3642 err && *err ? *err : "", path);
Emeric Bruna96b5822019-10-17 13:25:14 +02003643 errcode |= ERR_ALERT | ERR_FATAL;
3644 goto end;
yanbzhu488a4d22015-12-01 15:16:07 -05003645 }
Emmanuel Hocdet1c65fdd2018-12-03 18:07:44 +01003646#else
3647 { /* legacy compat (< openssl 1.0.2) */
3648 X509 *ca;
Emmanuel Hocdet140b64f2019-10-24 18:33:10 +02003649 STACK_OF(X509) *chain;
Emmanuel Hocdetb90d2cb2020-02-18 15:27:32 +01003650 chain = X509_chain_up_ref(find_chain);
Emmanuel Hocdet140b64f2019-10-24 18:33:10 +02003651 while ((ca = sk_X509_shift(chain)))
Emmanuel Hocdet1c65fdd2018-12-03 18:07:44 +01003652 if (!SSL_CTX_add_extra_chain_cert(ctx, ca)) {
3653 memprintf(err, "%sunable to load chain certificate into SSL Context '%s'.\n",
3654 err && *err ? *err : "", path);
3655 X509_free(ca);
Emmanuel Hocdet140b64f2019-10-24 18:33:10 +02003656 sk_X509_pop_free(chain, X509_free);
Emeric Bruna96b5822019-10-17 13:25:14 +02003657 errcode |= ERR_ALERT | ERR_FATAL;
3658 goto end;
Emmanuel Hocdet1c65fdd2018-12-03 18:07:44 +01003659 }
3660 }
3661#endif
yanbzhu488a4d22015-12-01 15:16:07 -05003662
William Lallemandfa892222019-07-23 16:06:08 +02003663#ifndef OPENSSL_NO_DH
3664 /* store a NULL pointer to indicate we have not yet loaded
3665 a custom DH param file */
3666 if (ssl_dh_ptr_index >= 0) {
3667 SSL_CTX_set_ex_data(ctx, ssl_dh_ptr_index, NULL);
3668 }
3669
Emeric Brun7a883362019-10-17 13:27:40 +02003670 errcode |= ssl_sock_load_dh_params(ctx, ckch, path, err);
3671 if (errcode & ERR_CODE) {
William Lallemandfa892222019-07-23 16:06:08 +02003672 memprintf(err, "%sunable to load DH parameters from file '%s'.\n",
3673 err && *err ? *err : "", path);
Emeric Bruna96b5822019-10-17 13:25:14 +02003674 goto end;
William Lallemandfa892222019-07-23 16:06:08 +02003675 }
3676#endif
3677
William Lallemanda17f4112019-10-10 15:16:44 +02003678#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
3679 if (sctl_ex_index >= 0 && ckch->sctl) {
3680 if (ssl_sock_load_sctl(ctx, ckch->sctl) < 0) {
3681 memprintf(err, "%s '%s.sctl' is present but cannot be read or parsed'.\n",
Tim Duesterhus93128532019-11-23 23:45:10 +01003682 err && *err ? *err : "", path);
Emeric Bruna96b5822019-10-17 13:25:14 +02003683 errcode |= ERR_ALERT | ERR_FATAL;
3684 goto end;
William Lallemanda17f4112019-10-10 15:16:44 +02003685 }
3686 }
3687#endif
3688
William Lallemand4a660132019-10-14 14:51:41 +02003689#if ((defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP) || defined OPENSSL_IS_BORINGSSL)
William Lallemand246c0242019-10-11 08:59:13 +02003690 /* Load OCSP Info into context */
3691 if (ckch->ocsp_response) {
Emmanuel Hocdet6f507c72020-02-18 15:56:39 +01003692 if (ssl_sock_load_ocsp(ctx, ckch, find_chain) < 0) {
Tim Duesterhus93128532019-11-23 23:45:10 +01003693 memprintf(err, "%s '%s.ocsp' is present and activates OCSP but it is impossible to compute the OCSP certificate ID (maybe the issuer could not be found)'.\n",
3694 err && *err ? *err : "", path);
Emeric Bruna96b5822019-10-17 13:25:14 +02003695 errcode |= ERR_ALERT | ERR_FATAL;
3696 goto end;
William Lallemand246c0242019-10-11 08:59:13 +02003697 }
3698 }
William Lallemand246c0242019-10-11 08:59:13 +02003699#endif
3700
Emeric Bruna96b5822019-10-17 13:25:14 +02003701 end:
3702 return errcode;
yanbzhu488a4d22015-12-01 15:16:07 -05003703}
3704
William Lallemandc4ecddf2019-07-31 16:50:08 +02003705#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
yanbzhu08ce6ab2015-12-02 13:01:29 -05003706
William Lallemand28a8fce2019-10-04 17:36:55 +02003707static int ssl_sock_populate_sni_keytypes_hplr(const char *str, struct eb_root *sni_keytypes, int key_index)
yanbzhu08ce6ab2015-12-02 13:01:29 -05003708{
3709 struct sni_keytype *s_kt = NULL;
3710 struct ebmb_node *node;
3711 int i;
3712
3713 for (i = 0; i < trash.size; i++) {
3714 if (!str[i])
3715 break;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02003716 trash.area[i] = tolower(str[i]);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003717 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +02003718 trash.area[i] = 0;
3719 node = ebst_lookup(sni_keytypes, trash.area);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003720 if (!node) {
3721 /* CN not found in tree */
3722 s_kt = malloc(sizeof(struct sni_keytype) + i + 1);
3723 /* Using memcpy here instead of strncpy.
3724 * strncpy will cause sig_abrt errors under certain versions of gcc with -O2
3725 * See: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=60792
3726 */
William Lallemand28a8fce2019-10-04 17:36:55 +02003727 if (!s_kt)
3728 return -1;
3729
Willy Tarreau843b7cb2018-07-13 10:54:26 +02003730 memcpy(s_kt->name.key, trash.area, i+1);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003731 s_kt->keytypes = 0;
3732 ebst_insert(sni_keytypes, &s_kt->name);
3733 } else {
3734 /* CN found in tree */
3735 s_kt = container_of(node, struct sni_keytype, name);
3736 }
3737
3738 /* Mark that this CN has the keytype of key_index via keytypes mask */
3739 s_kt->keytypes |= 1<<key_index;
3740
William Lallemand28a8fce2019-10-04 17:36:55 +02003741 return 0;
3742
yanbzhu08ce6ab2015-12-02 13:01:29 -05003743}
3744
William Lallemandc4ecddf2019-07-31 16:50:08 +02003745#endif
William Lallemand8c1cdde2019-10-18 10:58:14 +02003746/*
3747 * Free a ckch_store and its ckch(s)
3748 * The linked ckch_inst are not free'd
3749 */
3750void ckchs_free(struct ckch_store *ckchs)
3751{
3752 if (!ckchs)
3753 return;
3754
3755#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
3756 if (ckchs->multi) {
3757 int n;
3758
3759 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++)
3760 ssl_sock_free_cert_key_and_chain_contents(&ckchs->ckch[n]);
3761 } else
3762#endif
3763 {
3764 ssl_sock_free_cert_key_and_chain_contents(ckchs->ckch);
3765 ckchs->ckch = NULL;
3766 }
3767
3768 free(ckchs);
3769}
3770
3771/* allocate and duplicate a ckch_store
3772 * Return a new ckch_store or NULL */
3773static struct ckch_store *ckchs_dup(const struct ckch_store *src)
3774{
3775 struct ckch_store *dst;
3776 int pathlen;
3777
3778 pathlen = strlen(src->path);
3779 dst = calloc(1, sizeof(*dst) + pathlen + 1);
3780 if (!dst)
3781 return NULL;
3782 /* copy previous key */
3783 memcpy(dst->path, src->path, pathlen + 1);
3784 dst->multi = src->multi;
3785 LIST_INIT(&dst->ckch_inst);
3786
3787 dst->ckch = calloc((src->multi ? SSL_SOCK_NUM_KEYTYPES : 1), sizeof(*dst->ckch));
3788 if (!dst->ckch)
3789 goto error;
3790
3791#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
3792 if (src->multi) {
3793 int n;
3794
3795 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
3796 if (&src->ckch[n]) {
3797 if (!ssl_sock_copy_cert_key_and_chain(&src->ckch[n], &dst->ckch[n]))
3798 goto error;
3799 }
3800 }
3801 } else
3802#endif
3803 {
3804 if (!ssl_sock_copy_cert_key_and_chain(src->ckch, dst->ckch))
3805 goto error;
3806 }
3807
3808 return dst;
3809
3810error:
3811 ckchs_free(dst);
3812
3813 return NULL;
3814}
William Lallemandc4ecddf2019-07-31 16:50:08 +02003815
William Lallemand36b84632019-07-18 19:28:17 +02003816/*
William Lallemande3af8fb2019-10-08 11:36:53 +02003817 * lookup a path into the ckchs tree.
William Lallemand6af03992019-07-23 15:00:54 +02003818 */
William Lallemande3af8fb2019-10-08 11:36:53 +02003819static inline struct ckch_store *ckchs_lookup(char *path)
William Lallemand6af03992019-07-23 15:00:54 +02003820{
3821 struct ebmb_node *eb;
3822
William Lallemande3af8fb2019-10-08 11:36:53 +02003823 eb = ebst_lookup(&ckchs_tree, path);
William Lallemand6af03992019-07-23 15:00:54 +02003824 if (!eb)
3825 return NULL;
3826
William Lallemande3af8fb2019-10-08 11:36:53 +02003827 return ebmb_entry(eb, struct ckch_store, node);
William Lallemand6af03992019-07-23 15:00:54 +02003828}
3829
3830/*
William Lallemande3af8fb2019-10-08 11:36:53 +02003831 * This function allocate a ckch_store and populate it with certificates from files.
William Lallemand36b84632019-07-18 19:28:17 +02003832 */
William Lallemande3af8fb2019-10-08 11:36:53 +02003833static struct ckch_store *ckchs_load_cert_file(char *path, int multi, char **err)
William Lallemand36b84632019-07-18 19:28:17 +02003834{
William Lallemande3af8fb2019-10-08 11:36:53 +02003835 struct ckch_store *ckchs;
William Lallemand36b84632019-07-18 19:28:17 +02003836
William Lallemande3af8fb2019-10-08 11:36:53 +02003837 ckchs = calloc(1, sizeof(*ckchs) + strlen(path) + 1);
3838 if (!ckchs) {
William Lallemand36b84632019-07-18 19:28:17 +02003839 memprintf(err, "%sunable to allocate memory.\n", err && *err ? *err : "");
3840 goto end;
3841 }
William Lallemande3af8fb2019-10-08 11:36:53 +02003842 ckchs->ckch = calloc(1, sizeof(*ckchs->ckch) * (multi ? SSL_SOCK_NUM_KEYTYPES : 1));
William Lallemand36b84632019-07-18 19:28:17 +02003843
William Lallemande3af8fb2019-10-08 11:36:53 +02003844 if (!ckchs->ckch) {
William Lallemand36b84632019-07-18 19:28:17 +02003845 memprintf(err, "%sunable to allocate memory.\n", err && *err ? *err : "");
3846 goto end;
3847 }
3848
William Lallemand9117de92019-10-04 00:29:42 +02003849 LIST_INIT(&ckchs->ckch_inst);
3850
William Lallemand36b84632019-07-18 19:28:17 +02003851 if (!multi) {
3852
William Lallemand96a9c972019-10-17 11:56:17 +02003853 if (ssl_sock_load_files_into_ckch(path, ckchs->ckch, err) == 1)
William Lallemand36b84632019-07-18 19:28:17 +02003854 goto end;
3855
William Lallemande3af8fb2019-10-08 11:36:53 +02003856 /* insert into the ckchs tree */
3857 memcpy(ckchs->path, path, strlen(path) + 1);
3858 ebst_insert(&ckchs_tree, &ckchs->node);
William Lallemand36b84632019-07-18 19:28:17 +02003859 } else {
3860 int found = 0;
William Lallemandc4ecddf2019-07-31 16:50:08 +02003861#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
3862 char fp[MAXPATHLEN+1] = {0};
3863 int n = 0;
William Lallemand36b84632019-07-18 19:28:17 +02003864
3865 /* Load all possible certs and keys */
3866 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
3867 struct stat buf;
3868 snprintf(fp, sizeof(fp), "%s.%s", path, SSL_SOCK_KEYTYPE_NAMES[n]);
3869 if (stat(fp, &buf) == 0) {
William Lallemand96a9c972019-10-17 11:56:17 +02003870 if (ssl_sock_load_files_into_ckch(fp, &ckchs->ckch[n], err) == 1)
William Lallemand36b84632019-07-18 19:28:17 +02003871 goto end;
3872 found = 1;
William Lallemande3af8fb2019-10-08 11:36:53 +02003873 ckchs->multi = 1;
William Lallemand36b84632019-07-18 19:28:17 +02003874 }
3875 }
William Lallemandc4ecddf2019-07-31 16:50:08 +02003876#endif
William Lallemand36b84632019-07-18 19:28:17 +02003877
3878 if (!found) {
William Lallemand6e5f2ce2019-08-01 14:43:20 +02003879 memprintf(err, "%sDidn't find any certificate for bundle '%s'.\n", err && *err ? *err : "", path);
William Lallemand36b84632019-07-18 19:28:17 +02003880 goto end;
3881 }
William Lallemande3af8fb2019-10-08 11:36:53 +02003882 /* insert into the ckchs tree */
3883 memcpy(ckchs->path, path, strlen(path) + 1);
3884 ebst_insert(&ckchs_tree, &ckchs->node);
William Lallemand36b84632019-07-18 19:28:17 +02003885 }
William Lallemande3af8fb2019-10-08 11:36:53 +02003886 return ckchs;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003887
William Lallemand36b84632019-07-18 19:28:17 +02003888end:
William Lallemande3af8fb2019-10-08 11:36:53 +02003889 if (ckchs) {
3890 free(ckchs->ckch);
3891 ebmb_delete(&ckchs->node);
William Lallemand6af03992019-07-23 15:00:54 +02003892 }
3893
William Lallemande3af8fb2019-10-08 11:36:53 +02003894 free(ckchs);
William Lallemand36b84632019-07-18 19:28:17 +02003895
3896 return NULL;
3897}
3898
William Lallemand38df1c82019-12-04 15:39:35 +01003899
3900/*
3901 * Free a sni filters array generated by ckch_inst_sni_ctx_to_sni_filters()
3902 */
3903static inline void free_sni_filters(char **sni_filter, int fcount)
3904{
3905 int i;
3906
3907 if (sni_filter) {
3908 for (i = 0; i < fcount; i++) {
3909 if (sni_filter[i]) {
3910 free(sni_filter[i]);
3911 sni_filter[i] = NULL;
3912 }
3913 }
3914 free(sni_filter);
3915 }
3916}
3917
3918/*
3919 * Fill <*sni_filter> with an allocated array of ptr to the existing filters,
3920 * The caller should free <*sni_filter>.
3921 * Fill <*fcount> with the number of filters
3922 * Return an ERR_* code.
3923 */
3924static int ckch_inst_sni_ctx_to_sni_filters(const struct ckch_inst *ckchi, char ***sni_filter, int *fcount, char **err)
3925{
3926 struct sni_ctx *sc0;
3927 int errcode = 0;
3928 int i = 0;
3929 char **tmp_filter;
3930 int tmp_fcount = 0;
3931
3932 list_for_each_entry(sc0, &ckchi->sni_ctx, by_ckch_inst) {
3933 tmp_fcount++;
3934 }
3935
3936 if (!tmp_fcount)
3937 goto end;
3938
3939 tmp_filter = malloc(sizeof(*tmp_filter) * tmp_fcount);
3940 if (!tmp_filter) {
3941 errcode |= ERR_FATAL|ERR_ALERT;
3942 goto error;
3943 }
3944
3945 list_for_each_entry(sc0, &ckchi->sni_ctx, by_ckch_inst) {
3946 size_t len = strlen((char *)sc0->name.key);
3947
3948 /* we need to alloc and copy to insert a '!' or/and a '*' */
3949 tmp_filter[i] = calloc(1, len + sc0->neg + sc0->wild + 1);
3950 if (!tmp_filter[i]) {
3951 errcode |= ERR_FATAL|ERR_ALERT;
3952 goto error;
3953 }
3954
3955 if (sc0->neg)
3956 *tmp_filter[i] = '!';
3957 if (sc0->wild)
3958 *(tmp_filter[i] + sc0->neg) = '*';
3959
3960 memcpy(tmp_filter[i] + sc0->neg + sc0->wild, (char *)sc0->name.key, len + 1);
3961 i++;
3962 }
William Lallemand38df1c82019-12-04 15:39:35 +01003963 *sni_filter = tmp_filter;
Willy Tarreaud04a2a62020-03-05 16:26:12 +01003964end:
William Lallemand38df1c82019-12-04 15:39:35 +01003965 *fcount = tmp_fcount;
3966
3967 return errcode;
3968error:
3969 memprintf(err, "%sUnable to generate filters!",
3970 err && *err ? *err : "");
3971 free_sni_filters(tmp_filter, tmp_fcount);
3972
3973 return errcode;
3974}
3975
3976
William Lallemandc4ecddf2019-07-31 16:50:08 +02003977#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
3978
William Lallemand36b84632019-07-18 19:28:17 +02003979/*
William Lallemande3af8fb2019-10-08 11:36:53 +02003980 * Take a ckch_store which contains a multi-certificate bundle.
William Lallemand36b84632019-07-18 19:28:17 +02003981 * Group these certificates into a set of SSL_CTX*
yanbzhu08ce6ab2015-12-02 13:01:29 -05003982 * based on shared and unique CN and SAN entries. Add these SSL_CTX* to the SNI tree.
3983 *
Joseph Herlant017b3da2018-11-15 09:07:59 -08003984 * This will allow the user to explicitly group multiple cert/keys for a single purpose
yanbzhu08ce6ab2015-12-02 13:01:29 -05003985 *
Emeric Brun054563d2019-10-17 13:16:58 +02003986 * Returns a bitfield containing the flags:
3987 * ERR_FATAL in any fatal error case
3988 * ERR_ALERT if the reason of the error is available in err
3989 * ERR_WARN if a warning is available into err
William Lallemand36b84632019-07-18 19:28:17 +02003990 *
yanbzhu08ce6ab2015-12-02 13:01:29 -05003991 */
Emeric Brun054563d2019-10-17 13:16:58 +02003992static int ckch_inst_new_load_multi_store(const char *path, struct ckch_store *ckchs,
3993 struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
3994 char **sni_filter, int fcount, struct ckch_inst **ckchi, char **err)
yanbzhu08ce6ab2015-12-02 13:01:29 -05003995{
William Lallemand36b84632019-07-18 19:28:17 +02003996 int i = 0, n = 0;
3997 struct cert_key_and_chain *certs_and_keys;
William Lallemand4b989f22019-10-04 18:36:55 +02003998 struct eb_root sni_keytypes_map = EB_ROOT;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003999 struct ebmb_node *node;
4000 struct ebmb_node *next;
4001 /* Array of SSL_CTX pointers corresponding to each possible combo
4002 * of keytypes
4003 */
4004 struct key_combo_ctx key_combos[SSL_SOCK_POSSIBLE_KT_COMBOS] = { {0} };
Emeric Brun054563d2019-10-17 13:16:58 +02004005 int errcode = 0;
yanbzhu08ce6ab2015-12-02 13:01:29 -05004006 X509_NAME *xname = NULL;
4007 char *str = NULL;
4008#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
4009 STACK_OF(GENERAL_NAME) *names = NULL;
4010#endif
William Lallemand614ca0d2019-10-07 13:52:11 +02004011 struct ckch_inst *ckch_inst;
yanbzhu08ce6ab2015-12-02 13:01:29 -05004012
Emeric Brun054563d2019-10-17 13:16:58 +02004013 *ckchi = NULL;
4014
William Lallemande3af8fb2019-10-08 11:36:53 +02004015 if (!ckchs || !ckchs->ckch || !ckchs->multi) {
William Lallemand36b84632019-07-18 19:28:17 +02004016 memprintf(err, "%sunable to load SSL certificate file '%s' file does not exist.\n",
4017 err && *err ? *err : "", path);
Emeric Brun054563d2019-10-17 13:16:58 +02004018 return ERR_ALERT | ERR_FATAL;
William Lallemand614ca0d2019-10-07 13:52:11 +02004019 }
4020
4021 ckch_inst = ckch_inst_new();
4022 if (!ckch_inst) {
4023 memprintf(err, "%sunable to allocate SSL context for cert '%s'.\n",
4024 err && *err ? *err : "", path);
Emeric Brun054563d2019-10-17 13:16:58 +02004025 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemand614ca0d2019-10-07 13:52:11 +02004026 goto end;
yanbzhu08ce6ab2015-12-02 13:01:29 -05004027 }
4028
William Lallemande3af8fb2019-10-08 11:36:53 +02004029 certs_and_keys = ckchs->ckch;
William Lallemand36b84632019-07-18 19:28:17 +02004030
yanbzhu08ce6ab2015-12-02 13:01:29 -05004031 /* Process each ckch and update keytypes for each CN/SAN
4032 * for example, if CN/SAN www.a.com is associated with
4033 * certs with keytype 0 and 2, then at the end of the loop,
4034 * www.a.com will have:
4035 * keyindex = 0 | 1 | 4 = 5
4036 */
4037 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
William Lallemand28a8fce2019-10-04 17:36:55 +02004038 int ret;
yanbzhu08ce6ab2015-12-02 13:01:29 -05004039
4040 if (!ssl_sock_is_ckch_valid(&certs_and_keys[n]))
4041 continue;
4042
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02004043 if (fcount) {
William Lallemand28a8fce2019-10-04 17:36:55 +02004044 for (i = 0; i < fcount; i++) {
4045 ret = ssl_sock_populate_sni_keytypes_hplr(sni_filter[i], &sni_keytypes_map, n);
4046 if (ret < 0) {
4047 memprintf(err, "%sunable to allocate SSL context.\n",
4048 err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02004049 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemand28a8fce2019-10-04 17:36:55 +02004050 goto end;
4051 }
4052 }
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02004053 } else {
4054 /* A lot of the following code is OpenSSL boilerplate for processing CN's and SAN's,
4055 * so the line that contains logic is marked via comments
4056 */
4057 xname = X509_get_subject_name(certs_and_keys[n].cert);
4058 i = -1;
4059 while ((i = X509_NAME_get_index_by_NID(xname, NID_commonName, i)) != -1) {
4060 X509_NAME_ENTRY *entry = X509_NAME_get_entry(xname, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02004061 ASN1_STRING *value;
4062 value = X509_NAME_ENTRY_get_data(entry);
4063 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02004064 /* Important line is here */
William Lallemand28a8fce2019-10-04 17:36:55 +02004065 ret = ssl_sock_populate_sni_keytypes_hplr(str, &sni_keytypes_map, n);
yanbzhu08ce6ab2015-12-02 13:01:29 -05004066
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02004067 OPENSSL_free(str);
4068 str = NULL;
William Lallemand28a8fce2019-10-04 17:36:55 +02004069 if (ret < 0) {
4070 memprintf(err, "%sunable to allocate SSL context.\n",
4071 err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02004072 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemand28a8fce2019-10-04 17:36:55 +02004073 goto end;
4074 }
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02004075 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05004076 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05004077
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02004078 /* Do the above logic for each SAN */
yanbzhu08ce6ab2015-12-02 13:01:29 -05004079#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02004080 names = X509_get_ext_d2i(certs_and_keys[n].cert, NID_subject_alt_name, NULL, NULL);
4081 if (names) {
4082 for (i = 0; i < sk_GENERAL_NAME_num(names); i++) {
4083 GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i);
yanbzhu08ce6ab2015-12-02 13:01:29 -05004084
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02004085 if (name->type == GEN_DNS) {
4086 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
4087 /* Important line is here */
William Lallemand28a8fce2019-10-04 17:36:55 +02004088 ret = ssl_sock_populate_sni_keytypes_hplr(str, &sni_keytypes_map, n);
yanbzhu08ce6ab2015-12-02 13:01:29 -05004089
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02004090 OPENSSL_free(str);
4091 str = NULL;
William Lallemand28a8fce2019-10-04 17:36:55 +02004092 if (ret < 0) {
4093 memprintf(err, "%sunable to allocate SSL context.\n",
4094 err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02004095 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemand28a8fce2019-10-04 17:36:55 +02004096 goto end;
4097 }
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02004098 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05004099 }
4100 }
4101 }
4102 }
4103#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
4104 }
4105
4106 /* If no files found, return error */
4107 if (eb_is_empty(&sni_keytypes_map)) {
4108 memprintf(err, "%sunable to load SSL certificate file '%s' file does not exist.\n",
4109 err && *err ? *err : "", path);
Emeric Brun054563d2019-10-17 13:16:58 +02004110 errcode |= ERR_ALERT | ERR_FATAL;
yanbzhu08ce6ab2015-12-02 13:01:29 -05004111 goto end;
4112 }
4113
4114 /* We now have a map of CN/SAN to keytypes that are loaded in
4115 * Iterate through the map to create the SSL_CTX's (if needed)
4116 * and add each CTX to the SNI tree
4117 *
4118 * Some math here:
Joseph Herlant017b3da2018-11-15 09:07:59 -08004119 * There are 2^n - 1 possible combinations, each unique
yanbzhu08ce6ab2015-12-02 13:01:29 -05004120 * combination is denoted by the key in the map. Each key
4121 * has a value between 1 and 2^n - 1. Conveniently, the array
4122 * of SSL_CTX* is sized 2^n. So, we can simply use the i'th
4123 * entry in the array to correspond to the unique combo (key)
4124 * associated with i. This unique key combo (i) will be associated
4125 * with combos[i-1]
4126 */
4127
4128 node = ebmb_first(&sni_keytypes_map);
4129 while (node) {
4130 SSL_CTX *cur_ctx;
Bertrand Jacquin33423092016-11-13 16:37:13 +00004131 char cur_file[MAXPATHLEN+1];
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02004132 const struct pkey_info kinfo = { .sig = TLSEXT_signature_anonymous, .bits = 0 };
yanbzhu08ce6ab2015-12-02 13:01:29 -05004133
4134 str = (char *)container_of(node, struct sni_keytype, name)->name.key;
4135 i = container_of(node, struct sni_keytype, name)->keytypes;
4136 cur_ctx = key_combos[i-1].ctx;
4137
4138 if (cur_ctx == NULL) {
4139 /* need to create SSL_CTX */
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004140 cur_ctx = SSL_CTX_new(SSLv23_server_method());
yanbzhu08ce6ab2015-12-02 13:01:29 -05004141 if (cur_ctx == NULL) {
4142 memprintf(err, "%sunable to allocate SSL context.\n",
4143 err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02004144 errcode |= ERR_ALERT | ERR_FATAL;
yanbzhu08ce6ab2015-12-02 13:01:29 -05004145 goto end;
4146 }
4147
yanbzhube2774d2015-12-10 15:07:30 -05004148 /* Load all required certs/keys/chains/OCSPs info into SSL_CTX */
yanbzhu08ce6ab2015-12-02 13:01:29 -05004149 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
4150 if (i & (1<<n)) {
4151 /* Key combo contains ckch[n] */
Bertrand Jacquin33423092016-11-13 16:37:13 +00004152 snprintf(cur_file, MAXPATHLEN+1, "%s.%s", path, SSL_SOCK_KEYTYPE_NAMES[n]);
Emeric Bruna96b5822019-10-17 13:25:14 +02004153 errcode |= ssl_sock_put_ckch_into_ctx(cur_file, &certs_and_keys[n], cur_ctx, err);
4154 if (errcode & ERR_CODE)
yanbzhu08ce6ab2015-12-02 13:01:29 -05004155 goto end;
yanbzhu08ce6ab2015-12-02 13:01:29 -05004156 }
4157 }
4158
yanbzhu08ce6ab2015-12-02 13:01:29 -05004159 /* Update key_combos */
4160 key_combos[i-1].ctx = cur_ctx;
4161 }
4162
4163 /* Update SNI Tree */
William Lallemand9117de92019-10-04 00:29:42 +02004164
William Lallemand1d29c742019-10-04 00:53:29 +02004165 key_combos[i-1].order = ckch_inst_add_cert_sni(cur_ctx, ckch_inst, bind_conf, ssl_conf,
William Lallemandfe49bb32019-10-03 23:46:33 +02004166 kinfo, str, key_combos[i-1].order);
4167 if (key_combos[i-1].order < 0) {
4168 memprintf(err, "%sunable to create a sni context.\n", err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02004169 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemandfe49bb32019-10-03 23:46:33 +02004170 goto end;
4171 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05004172 node = ebmb_next(node);
4173 }
4174
4175
4176 /* Mark a default context if none exists, using the ctx that has the most shared keys */
4177 if (!bind_conf->default_ctx) {
4178 for (i = SSL_SOCK_POSSIBLE_KT_COMBOS - 1; i >= 0; i--) {
4179 if (key_combos[i].ctx) {
4180 bind_conf->default_ctx = key_combos[i].ctx;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004181 bind_conf->default_ssl_conf = ssl_conf;
William Lallemand21724f02019-11-04 17:56:13 +01004182 ckch_inst->is_default = 1;
yanbzhu08ce6ab2015-12-02 13:01:29 -05004183 break;
4184 }
4185 }
4186 }
4187
William Lallemand614ca0d2019-10-07 13:52:11 +02004188 ckch_inst->bind_conf = bind_conf;
William Lallemand150bfa82019-09-19 17:12:49 +02004189 ckch_inst->ssl_conf = ssl_conf;
William Lallemandcfca1422020-03-05 10:17:47 +01004190 ckch_inst->ckch_store = ckchs;
William Lallemand67630162020-03-09 16:56:39 +01004191 ckch_inst->filters = !!fcount;
yanbzhu08ce6ab2015-12-02 13:01:29 -05004192end:
4193
4194 if (names)
4195 sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
4196
yanbzhu08ce6ab2015-12-02 13:01:29 -05004197 node = ebmb_first(&sni_keytypes_map);
4198 while (node) {
4199 next = ebmb_next(node);
4200 ebmb_delete(node);
William Lallemand8ed5b962019-10-04 17:24:39 +02004201 free(ebmb_entry(node, struct sni_keytype, name));
yanbzhu08ce6ab2015-12-02 13:01:29 -05004202 node = next;
4203 }
4204
Emeric Brun054563d2019-10-17 13:16:58 +02004205 if (errcode & ERR_CODE && ckch_inst) {
William Lallemand0c6d12f2019-10-04 18:38:51 +02004206 struct sni_ctx *sc0, *sc0b;
4207
4208 /* free the SSL_CTX in case of error */
4209 for (i = 0; i < SSL_SOCK_POSSIBLE_KT_COMBOS; i++) {
4210 if (key_combos[i].ctx)
4211 SSL_CTX_free(key_combos[i].ctx);
4212 }
4213
4214 /* free the sni_ctx in case of error */
4215 list_for_each_entry_safe(sc0, sc0b, &ckch_inst->sni_ctx, by_ckch_inst) {
4216
4217 ebmb_delete(&sc0->name);
4218 LIST_DEL(&sc0->by_ckch_inst);
4219 free(sc0);
4220 }
William Lallemand614ca0d2019-10-07 13:52:11 +02004221 free(ckch_inst);
4222 ckch_inst = NULL;
William Lallemand0c6d12f2019-10-04 18:38:51 +02004223 }
4224
Emeric Brun054563d2019-10-17 13:16:58 +02004225 *ckchi = ckch_inst;
4226 return errcode;
yanbzhu08ce6ab2015-12-02 13:01:29 -05004227}
4228#else
4229/* This is a dummy, that just logs an error and returns error */
Emeric Brun054563d2019-10-17 13:16:58 +02004230static int ckch_inst_new_load_multi_store(const char *path, struct ckch_store *ckchs,
4231 struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
4232 char **sni_filter, int fcount, struct ckch_inst **ckchi, char **err)
yanbzhu08ce6ab2015-12-02 13:01:29 -05004233{
4234 memprintf(err, "%sunable to stat SSL certificate from file '%s' : %s.\n",
4235 err && *err ? *err : "", path, strerror(errno));
Emeric Brun054563d2019-10-17 13:16:58 +02004236 return ERR_ALERT | ERR_FATAL;
yanbzhu08ce6ab2015-12-02 13:01:29 -05004237}
4238
Willy Tarreau9a1ab082019-05-09 13:26:41 +02004239#endif /* #if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL: Support for loading multiple certs into a single SSL_CTX */
yanbzhu488a4d22015-12-01 15:16:07 -05004240
William Lallemand614ca0d2019-10-07 13:52:11 +02004241/*
4242 * This function allocate a ckch_inst and create its snis
Emeric Brun054563d2019-10-17 13:16:58 +02004243 *
4244 * Returns a bitfield containing the flags:
4245 * ERR_FATAL in any fatal error case
4246 * ERR_ALERT if the reason of the error is available in err
4247 * ERR_WARN if a warning is available into err
William Lallemand614ca0d2019-10-07 13:52:11 +02004248 */
Emeric Brun054563d2019-10-17 13:16:58 +02004249static int ckch_inst_new_load_store(const char *path, struct ckch_store *ckchs, struct bind_conf *bind_conf,
4250 struct ssl_bind_conf *ssl_conf, char **sni_filter, int fcount, struct ckch_inst **ckchi, char **err)
Emeric Brunfc0421f2012-09-07 17:30:07 +02004251{
William Lallemandc9402072019-05-15 15:33:54 +02004252 SSL_CTX *ctx;
William Lallemandc9402072019-05-15 15:33:54 +02004253 int i;
Emeric Brunfc0421f2012-09-07 17:30:07 +02004254 int order = 0;
4255 X509_NAME *xname;
4256 char *str;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01004257 EVP_PKEY *pkey;
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02004258 struct pkey_info kinfo = { .sig = TLSEXT_signature_anonymous, .bits = 0 };
Emeric Brunfc0421f2012-09-07 17:30:07 +02004259#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
4260 STACK_OF(GENERAL_NAME) *names;
4261#endif
William Lallemand36b84632019-07-18 19:28:17 +02004262 struct cert_key_and_chain *ckch;
William Lallemand614ca0d2019-10-07 13:52:11 +02004263 struct ckch_inst *ckch_inst = NULL;
Emeric Brun054563d2019-10-17 13:16:58 +02004264 int errcode = 0;
4265
4266 *ckchi = NULL;
William Lallemanda59191b2019-05-15 16:08:56 +02004267
William Lallemande3af8fb2019-10-08 11:36:53 +02004268 if (!ckchs || !ckchs->ckch)
Emeric Brun054563d2019-10-17 13:16:58 +02004269 return ERR_FATAL;
Emeric Brunfc0421f2012-09-07 17:30:07 +02004270
William Lallemande3af8fb2019-10-08 11:36:53 +02004271 ckch = ckchs->ckch;
William Lallemand36b84632019-07-18 19:28:17 +02004272
William Lallemandc9402072019-05-15 15:33:54 +02004273 ctx = SSL_CTX_new(SSLv23_server_method());
4274 if (!ctx) {
4275 memprintf(err, "%sunable to allocate SSL context for cert '%s'.\n",
4276 err && *err ? *err : "", path);
Emeric Brun054563d2019-10-17 13:16:58 +02004277 errcode |= ERR_ALERT | ERR_FATAL;
4278 goto error;
William Lallemandc9402072019-05-15 15:33:54 +02004279 }
4280
Emeric Bruna96b5822019-10-17 13:25:14 +02004281 errcode |= ssl_sock_put_ckch_into_ctx(path, ckch, ctx, err);
4282 if (errcode & ERR_CODE)
William Lallemand614ca0d2019-10-07 13:52:11 +02004283 goto error;
William Lallemand614ca0d2019-10-07 13:52:11 +02004284
4285 ckch_inst = ckch_inst_new();
4286 if (!ckch_inst) {
4287 memprintf(err, "%sunable to allocate SSL context for cert '%s'.\n",
4288 err && *err ? *err : "", path);
Emeric Brun054563d2019-10-17 13:16:58 +02004289 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemandd9199372019-10-04 15:37:05 +02004290 goto error;
William Lallemandc9402072019-05-15 15:33:54 +02004291 }
4292
William Lallemand36b84632019-07-18 19:28:17 +02004293 pkey = X509_get_pubkey(ckch->cert);
Emmanuel Hocdet05942112017-02-20 16:11:50 +01004294 if (pkey) {
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02004295 kinfo.bits = EVP_PKEY_bits(pkey);
Emmanuel Hocdet05942112017-02-20 16:11:50 +01004296 switch(EVP_PKEY_base_id(pkey)) {
4297 case EVP_PKEY_RSA:
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02004298 kinfo.sig = TLSEXT_signature_rsa;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01004299 break;
4300 case EVP_PKEY_EC:
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02004301 kinfo.sig = TLSEXT_signature_ecdsa;
4302 break;
4303 case EVP_PKEY_DSA:
4304 kinfo.sig = TLSEXT_signature_dsa;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01004305 break;
4306 }
4307 EVP_PKEY_free(pkey);
4308 }
4309
Emeric Brun50bcecc2013-04-22 13:05:23 +02004310 if (fcount) {
William Lallemandfe49bb32019-10-03 23:46:33 +02004311 while (fcount--) {
William Lallemand1d29c742019-10-04 00:53:29 +02004312 order = ckch_inst_add_cert_sni(ctx, ckch_inst, bind_conf, ssl_conf, kinfo, sni_filter[fcount], order);
William Lallemandfe49bb32019-10-03 23:46:33 +02004313 if (order < 0) {
4314 memprintf(err, "%sunable to create a sni context.\n", err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02004315 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemandd9199372019-10-04 15:37:05 +02004316 goto error;
William Lallemandfe49bb32019-10-03 23:46:33 +02004317 }
4318 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004319 }
4320 else {
Emeric Brunfc0421f2012-09-07 17:30:07 +02004321#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
William Lallemand36b84632019-07-18 19:28:17 +02004322 names = X509_get_ext_d2i(ckch->cert, NID_subject_alt_name, NULL, NULL);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004323 if (names) {
4324 for (i = 0; i < sk_GENERAL_NAME_num(names); i++) {
4325 GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i);
4326 if (name->type == GEN_DNS) {
4327 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
William Lallemand1d29c742019-10-04 00:53:29 +02004328 order = ckch_inst_add_cert_sni(ctx, ckch_inst, bind_conf, ssl_conf, kinfo, str, order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004329 OPENSSL_free(str);
William Lallemandfe49bb32019-10-03 23:46:33 +02004330 if (order < 0) {
4331 memprintf(err, "%sunable to create a sni context.\n", err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02004332 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemandd9199372019-10-04 15:37:05 +02004333 goto error;
William Lallemandfe49bb32019-10-03 23:46:33 +02004334 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004335 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004336 }
4337 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004338 sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004339 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004340#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
William Lallemand36b84632019-07-18 19:28:17 +02004341 xname = X509_get_subject_name(ckch->cert);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004342 i = -1;
4343 while ((i = X509_NAME_get_index_by_NID(xname, NID_commonName, i)) != -1) {
4344 X509_NAME_ENTRY *entry = X509_NAME_get_entry(xname, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02004345 ASN1_STRING *value;
4346
4347 value = X509_NAME_ENTRY_get_data(entry);
4348 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
William Lallemand1d29c742019-10-04 00:53:29 +02004349 order = ckch_inst_add_cert_sni(ctx, ckch_inst, bind_conf, ssl_conf, kinfo, str, order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004350 OPENSSL_free(str);
William Lallemandfe49bb32019-10-03 23:46:33 +02004351 if (order < 0) {
4352 memprintf(err, "%sunable to create a sni context.\n", err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02004353 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemandd9199372019-10-04 15:37:05 +02004354 goto error;
William Lallemandfe49bb32019-10-03 23:46:33 +02004355 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004356 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004357 }
4358 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004359 /* we must not free the SSL_CTX anymore below, since it's already in
4360 * the tree, so it will be discovered and cleaned in time.
4361 */
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02004362
Emeric Brunfc0421f2012-09-07 17:30:07 +02004363#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004364 if (bind_conf->default_ctx) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02004365 memprintf(err, "%sthis version of openssl cannot load multiple SSL certificates.\n",
4366 err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02004367 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemandd9199372019-10-04 15:37:05 +02004368 goto error;
Emeric Brunfc0421f2012-09-07 17:30:07 +02004369 }
4370#endif
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004371 if (!bind_conf->default_ctx) {
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004372 bind_conf->default_ctx = ctx;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004373 bind_conf->default_ssl_conf = ssl_conf;
William Lallemand21724f02019-11-04 17:56:13 +01004374 ckch_inst->is_default = 1;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004375 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004376
William Lallemand9117de92019-10-04 00:29:42 +02004377 /* everything succeed, the ckch instance can be used */
4378 ckch_inst->bind_conf = bind_conf;
William Lallemand150bfa82019-09-19 17:12:49 +02004379 ckch_inst->ssl_conf = ssl_conf;
William Lallemandcfca1422020-03-05 10:17:47 +01004380 ckch_inst->ckch_store = ckchs;
William Lallemand67630162020-03-09 16:56:39 +01004381 ckch_inst->filters = !!fcount;
William Lallemand9117de92019-10-04 00:29:42 +02004382
Emeric Brun054563d2019-10-17 13:16:58 +02004383 *ckchi = ckch_inst;
4384 return errcode;
William Lallemandd9199372019-10-04 15:37:05 +02004385
4386error:
4387 /* free the allocated sni_ctxs */
William Lallemand614ca0d2019-10-07 13:52:11 +02004388 if (ckch_inst) {
William Lallemandd9199372019-10-04 15:37:05 +02004389 struct sni_ctx *sc0, *sc0b;
4390
4391 list_for_each_entry_safe(sc0, sc0b, &ckch_inst->sni_ctx, by_ckch_inst) {
4392
4393 ebmb_delete(&sc0->name);
4394 LIST_DEL(&sc0->by_ckch_inst);
4395 free(sc0);
4396 }
William Lallemand614ca0d2019-10-07 13:52:11 +02004397 free(ckch_inst);
4398 ckch_inst = NULL;
William Lallemandd9199372019-10-04 15:37:05 +02004399 }
4400 /* We only created 1 SSL_CTX so we can free it there */
4401 SSL_CTX_free(ctx);
4402
Emeric Brun054563d2019-10-17 13:16:58 +02004403 return errcode;
Emeric Brunfc0421f2012-09-07 17:30:07 +02004404}
4405
Willy Tarreau8c5414a2019-10-16 17:06:25 +02004406/* Returns a set of ERR_* flags possibly with an error in <err>. */
William Lallemand614ca0d2019-10-07 13:52:11 +02004407static int ssl_sock_load_ckchs(const char *path, struct ckch_store *ckchs,
4408 struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
4409 char **sni_filter, int fcount, char **err)
4410{
4411 struct ckch_inst *ckch_inst = NULL;
Emeric Brun054563d2019-10-17 13:16:58 +02004412 int errcode = 0;
William Lallemand614ca0d2019-10-07 13:52:11 +02004413
4414 /* we found the ckchs in the tree, we can use it directly */
4415 if (ckchs->multi)
Emeric Brun054563d2019-10-17 13:16:58 +02004416 errcode |= ckch_inst_new_load_multi_store(path, ckchs, bind_conf, ssl_conf, sni_filter, fcount, &ckch_inst, err);
William Lallemand614ca0d2019-10-07 13:52:11 +02004417 else
Emeric Brun054563d2019-10-17 13:16:58 +02004418 errcode |= ckch_inst_new_load_store(path, ckchs, bind_conf, ssl_conf, sni_filter, fcount, &ckch_inst, err);
William Lallemand614ca0d2019-10-07 13:52:11 +02004419
Emeric Brun054563d2019-10-17 13:16:58 +02004420 if (errcode & ERR_CODE)
4421 return errcode;
William Lallemand614ca0d2019-10-07 13:52:11 +02004422
4423 ssl_sock_load_cert_sni(ckch_inst, bind_conf);
4424
4425 /* succeed, add the instance to the ckch_store's list of instance */
4426 LIST_ADDQ(&ckchs->ckch_inst, &ckch_inst->by_ckchs);
Emeric Brun054563d2019-10-17 13:16:58 +02004427 return errcode;
William Lallemand614ca0d2019-10-07 13:52:11 +02004428}
4429
4430
Willy Tarreaubbc91962019-10-16 16:42:19 +02004431/* Returns a set of ERR_* flags possibly with an error in <err>. */
Willy Tarreau03209342016-12-22 17:08:28 +01004432int ssl_sock_load_cert(char *path, struct bind_conf *bind_conf, char **err)
Emeric Brunfc0421f2012-09-07 17:30:07 +02004433{
Cyril Bonté3180f7b2015-01-25 00:16:08 +01004434 struct dirent **de_list;
4435 int i, n;
Emeric Brunfc0421f2012-09-07 17:30:07 +02004436 struct stat buf;
Willy Tarreauee2663b2012-12-06 11:36:59 +01004437 char *end;
4438 char fp[MAXPATHLEN+1];
Emeric Brunfc0421f2012-09-07 17:30:07 +02004439 int cfgerr = 0;
William Lallemande3af8fb2019-10-08 11:36:53 +02004440 struct ckch_store *ckchs;
Willy Tarreau9a1ab082019-05-09 13:26:41 +02004441#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
yanbzhu63ea8462015-12-09 13:35:14 -05004442 int is_bundle;
4443 int j;
4444#endif
William Lallemande3af8fb2019-10-08 11:36:53 +02004445 if ((ckchs = ckchs_lookup(path))) {
William Lallemande3af8fb2019-10-08 11:36:53 +02004446 /* we found the ckchs in the tree, we can use it directly */
Willy Tarreau8c5414a2019-10-16 17:06:25 +02004447 return ssl_sock_load_ckchs(path, ckchs, bind_conf, NULL, NULL, 0, err);
William Lallemand6af03992019-07-23 15:00:54 +02004448 }
4449
yanbzhu08ce6ab2015-12-02 13:01:29 -05004450 if (stat(path, &buf) == 0) {
William Dauchy9a8ef7f2020-01-13 17:52:49 +01004451 if (S_ISDIR(buf.st_mode) == 0) {
William Lallemande3af8fb2019-10-08 11:36:53 +02004452 ckchs = ckchs_load_cert_file(path, 0, err);
4453 if (!ckchs)
Willy Tarreaubbc91962019-10-16 16:42:19 +02004454 return ERR_ALERT | ERR_FATAL;
4455
Willy Tarreau8c5414a2019-10-16 17:06:25 +02004456 return ssl_sock_load_ckchs(path, ckchs, bind_conf, NULL, NULL, 0, err);
William Lallemand36b84632019-07-18 19:28:17 +02004457 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004458
yanbzhu08ce6ab2015-12-02 13:01:29 -05004459 /* strip trailing slashes, including first one */
4460 for (end = path + strlen(path) - 1; end >= path && *end == '/'; end--)
4461 *end = 0;
Emeric Brunfc0421f2012-09-07 17:30:07 +02004462
yanbzhu08ce6ab2015-12-02 13:01:29 -05004463 n = scandir(path, &de_list, 0, alphasort);
4464 if (n < 0) {
4465 memprintf(err, "%sunable to scan directory '%s' : %s.\n",
4466 err && *err ? *err : "", path, strerror(errno));
Willy Tarreaubbc91962019-10-16 16:42:19 +02004467 cfgerr |= ERR_ALERT | ERR_FATAL;
yanbzhu08ce6ab2015-12-02 13:01:29 -05004468 }
4469 else {
4470 for (i = 0; i < n; i++) {
4471 struct dirent *de = de_list[i];
Emeric Brun2aab7222014-06-18 18:15:09 +02004472
yanbzhu08ce6ab2015-12-02 13:01:29 -05004473 end = strrchr(de->d_name, '.');
William Lallemand3f25ae32020-02-24 16:30:12 +01004474 if (end && (!strcmp(end, ".issuer") || !strcmp(end, ".ocsp") || !strcmp(end, ".sctl") || !strcmp(end, ".key")))
yanbzhu08ce6ab2015-12-02 13:01:29 -05004475 goto ignore_entry;
Cyril Bonté3180f7b2015-01-25 00:16:08 +01004476
yanbzhu08ce6ab2015-12-02 13:01:29 -05004477 snprintf(fp, sizeof(fp), "%s/%s", path, de->d_name);
4478 if (stat(fp, &buf) != 0) {
4479 memprintf(err, "%sunable to stat SSL certificate from file '%s' : %s.\n",
4480 err && *err ? *err : "", fp, strerror(errno));
Willy Tarreaubbc91962019-10-16 16:42:19 +02004481 cfgerr |= ERR_ALERT | ERR_FATAL;
yanbzhu08ce6ab2015-12-02 13:01:29 -05004482 goto ignore_entry;
4483 }
4484 if (!S_ISREG(buf.st_mode))
4485 goto ignore_entry;
yanbzhu63ea8462015-12-09 13:35:14 -05004486
Willy Tarreau9a1ab082019-05-09 13:26:41 +02004487#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
yanbzhu63ea8462015-12-09 13:35:14 -05004488 is_bundle = 0;
4489 /* Check if current entry in directory is part of a multi-cert bundle */
4490
William Lallemand3af48e72020-02-03 17:15:52 +01004491 if ((global_ssl.extra_files & SSL_GF_BUNDLE) && end) {
yanbzhu63ea8462015-12-09 13:35:14 -05004492 for (j = 0; j < SSL_SOCK_NUM_KEYTYPES; j++) {
4493 if (!strcmp(end + 1, SSL_SOCK_KEYTYPE_NAMES[j])) {
4494 is_bundle = 1;
4495 break;
4496 }
4497 }
4498
4499 if (is_bundle) {
yanbzhu63ea8462015-12-09 13:35:14 -05004500 int dp_len;
4501
4502 dp_len = end - de->d_name;
yanbzhu63ea8462015-12-09 13:35:14 -05004503
4504 /* increment i and free de until we get to a non-bundle cert
4505 * Note here that we look at de_list[i + 1] before freeing de
Willy Tarreau05800522019-10-29 10:48:50 +01004506 * this is important since ignore_entry will free de. This also
4507 * guarantees that de->d_name continues to hold the same prefix.
yanbzhu63ea8462015-12-09 13:35:14 -05004508 */
Willy Tarreau05800522019-10-29 10:48:50 +01004509 while (i + 1 < n && !strncmp(de_list[i + 1]->d_name, de->d_name, dp_len)) {
yanbzhu63ea8462015-12-09 13:35:14 -05004510 free(de);
4511 i++;
4512 de = de_list[i];
4513 }
4514
Willy Tarreau05800522019-10-29 10:48:50 +01004515 snprintf(fp, sizeof(fp), "%s/%.*s", path, dp_len, de->d_name);
William Lallemande3af8fb2019-10-08 11:36:53 +02004516 if ((ckchs = ckchs_lookup(fp)) == NULL)
4517 ckchs = ckchs_load_cert_file(fp, 1, err);
4518 if (!ckchs)
Willy Tarreaubbc91962019-10-16 16:42:19 +02004519 cfgerr |= ERR_ALERT | ERR_FATAL;
Willy Tarreau8c5414a2019-10-16 17:06:25 +02004520 else
4521 cfgerr |= ssl_sock_load_ckchs(path, ckchs, bind_conf, NULL, NULL, 0, err);
yanbzhu63ea8462015-12-09 13:35:14 -05004522 /* Successfully processed the bundle */
4523 goto ignore_entry;
4524 }
4525 }
4526
4527#endif
William Lallemande3af8fb2019-10-08 11:36:53 +02004528 if ((ckchs = ckchs_lookup(fp)) == NULL)
4529 ckchs = ckchs_load_cert_file(fp, 0, err);
4530 if (!ckchs)
Willy Tarreaubbc91962019-10-16 16:42:19 +02004531 cfgerr |= ERR_ALERT | ERR_FATAL;
William Lallemand614ca0d2019-10-07 13:52:11 +02004532 else
Willy Tarreau8c5414a2019-10-16 17:06:25 +02004533 cfgerr |= ssl_sock_load_ckchs(path, ckchs, bind_conf, NULL, NULL, 0, err);
William Lallemand36b84632019-07-18 19:28:17 +02004534
yanbzhu08ce6ab2015-12-02 13:01:29 -05004535ignore_entry:
4536 free(de);
Cyril Bonté3180f7b2015-01-25 00:16:08 +01004537 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05004538 free(de_list);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004539 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05004540 return cfgerr;
yanbzhu08ce6ab2015-12-02 13:01:29 -05004541
William Lallemand3af48e72020-02-03 17:15:52 +01004542 } else {
4543 /* stat failed */
Willy Tarreaubbc91962019-10-16 16:42:19 +02004544
William Lallemand3af48e72020-02-03 17:15:52 +01004545 if (global_ssl.extra_files & SSL_GF_BUNDLE) {
4546 /* try to load a bundle if it is permitted */
4547 ckchs = ckchs_load_cert_file(path, 1, err);
4548 if (!ckchs)
4549 return ERR_ALERT | ERR_FATAL;
4550 cfgerr |= ssl_sock_load_ckchs(path, ckchs, bind_conf, NULL, NULL, 0, err);
4551 } else {
4552 memprintf(err, "%sunable to stat SSL certificate from file '%s' : %s.\n",
4553 err && *err ? *err : "", fp, strerror(errno));
4554 cfgerr |= ERR_ALERT | ERR_FATAL;
4555 }
4556 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05004557
Emeric Brunfc0421f2012-09-07 17:30:07 +02004558 return cfgerr;
4559}
4560
Thierry Fournier383085f2013-01-24 14:15:43 +01004561/* Make sure openssl opens /dev/urandom before the chroot. The work is only
4562 * done once. Zero is returned if the operation fails. No error is returned
4563 * if the random is said as not implemented, because we expect that openssl
4564 * will use another method once needed.
4565 */
4566static int ssl_initialize_random()
4567{
4568 unsigned char random;
4569 static int random_initialized = 0;
4570
4571 if (!random_initialized && RAND_bytes(&random, 1) != 0)
4572 random_initialized = 1;
4573
4574 return random_initialized;
4575}
4576
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004577/* release ssl bind conf */
4578void ssl_sock_free_ssl_conf(struct ssl_bind_conf *conf)
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004579{
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004580 if (conf) {
Bernard Spil13c53f82018-02-15 13:34:58 +01004581#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004582 free(conf->npn_str);
4583 conf->npn_str = NULL;
4584#endif
4585#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
4586 free(conf->alpn_str);
4587 conf->alpn_str = NULL;
4588#endif
4589 free(conf->ca_file);
4590 conf->ca_file = NULL;
Emmanuel Hocdet842e94e2019-12-16 16:39:17 +01004591 free(conf->ca_verify_file);
4592 conf->ca_verify_file = NULL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004593 free(conf->crl_file);
4594 conf->crl_file = NULL;
4595 free(conf->ciphers);
4596 conf->ciphers = NULL;
Emmanuel Hocdet839af572019-05-14 16:27:35 +02004597#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02004598 free(conf->ciphersuites);
4599 conf->ciphersuites = NULL;
4600#endif
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004601 free(conf->curves);
4602 conf->curves = NULL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004603 free(conf->ecdhe);
4604 conf->ecdhe = NULL;
4605 }
4606}
4607
Willy Tarreaubbc91962019-10-16 16:42:19 +02004608/* Returns a set of ERR_* flags possibly with an error in <err>. */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004609int ssl_sock_load_cert_list_file(char *file, struct bind_conf *bind_conf, struct proxy *curproxy, char **err)
4610{
4611 char thisline[CRT_LINESIZE];
4612 char path[MAXPATHLEN+1];
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004613 FILE *f;
yanbzhu1b04e5b2015-12-02 13:54:14 -05004614 struct stat buf;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004615 int linenum = 0;
4616 int cfgerr = 0;
William Lallemande3af8fb2019-10-08 11:36:53 +02004617 struct ckch_store *ckchs;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004618
Willy Tarreauad1731d2013-04-02 17:35:58 +02004619 if ((f = fopen(file, "r")) == NULL) {
4620 memprintf(err, "cannot open file '%s' : %s", file, strerror(errno));
Willy Tarreaubbc91962019-10-16 16:42:19 +02004621 return ERR_ALERT | ERR_FATAL;
Willy Tarreauad1731d2013-04-02 17:35:58 +02004622 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004623
4624 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004625 int arg, newarg, cur_arg, i, ssl_b = 0, ssl_e = 0;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004626 char *end;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004627 char *args[MAX_CRT_ARGS + 1];
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004628 char *line = thisline;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004629 char *crt_path;
4630 struct ssl_bind_conf *ssl_conf = NULL;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004631
4632 linenum++;
4633 end = line + strlen(line);
4634 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
4635 /* Check if we reached the limit and the last char is not \n.
4636 * Watch out for the last line without the terminating '\n'!
4637 */
Willy Tarreauad1731d2013-04-02 17:35:58 +02004638 memprintf(err, "line %d too long in file '%s', limit is %d characters",
4639 linenum, file, (int)sizeof(thisline)-1);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004640 cfgerr |= ERR_ALERT | ERR_FATAL;
Willy Tarreauad1731d2013-04-02 17:35:58 +02004641 break;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004642 }
4643
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004644 arg = 0;
Emeric Brun50bcecc2013-04-22 13:05:23 +02004645 newarg = 1;
4646 while (*line) {
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004647 if (*line == '#' || *line == '\n' || *line == '\r') {
4648 /* end of string, end of loop */
4649 *line = 0;
4650 break;
Willy Tarreauded15b72020-02-25 07:51:59 +01004651 } else if (isspace((unsigned char)*line)) {
Emeric Brun50bcecc2013-04-22 13:05:23 +02004652 newarg = 1;
4653 *line = 0;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004654 } else if (*line == '[') {
4655 if (ssl_b) {
4656 memprintf(err, "too many '[' on line %d in file '%s'.", linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004657 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004658 break;
4659 }
4660 if (!arg) {
4661 memprintf(err, "file must start with a cert on line %d in file '%s'", linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004662 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004663 break;
4664 }
4665 ssl_b = arg;
4666 newarg = 1;
4667 *line = 0;
4668 } else if (*line == ']') {
4669 if (ssl_e) {
4670 memprintf(err, "too many ']' on line %d in file '%s'.", linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004671 cfgerr |= ERR_ALERT | ERR_FATAL;
Emeric Brun50bcecc2013-04-22 13:05:23 +02004672 break;
4673 }
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004674 if (!ssl_b) {
4675 memprintf(err, "missing '[' in line %d in file '%s'.", linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004676 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004677 break;
4678 }
4679 ssl_e = arg;
4680 newarg = 1;
4681 *line = 0;
4682 } else if (newarg) {
4683 if (arg == MAX_CRT_ARGS) {
4684 memprintf(err, "too many args on line %d in file '%s'.", linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004685 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004686 break;
4687 }
Emeric Brun50bcecc2013-04-22 13:05:23 +02004688 newarg = 0;
4689 args[arg++] = line;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004690 }
Emeric Brun50bcecc2013-04-22 13:05:23 +02004691 line++;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004692 }
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02004693 if (cfgerr)
4694 break;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004695 args[arg++] = line;
Willy Tarreauad1731d2013-04-02 17:35:58 +02004696
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004697 /* empty line */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004698 if (!*args[0])
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004699 continue;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004700
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004701 crt_path = args[0];
4702 if (*crt_path != '/' && global_ssl.crt_base) {
4703 if ((strlen(global_ssl.crt_base) + 1 + strlen(crt_path)) > MAXPATHLEN) {
4704 memprintf(err, "'%s' : path too long on line %d in file '%s'",
4705 crt_path, linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004706 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004707 break;
4708 }
4709 snprintf(path, sizeof(path), "%s/%s", global_ssl.crt_base, crt_path);
4710 crt_path = path;
4711 }
4712
4713 ssl_conf = calloc(1, sizeof *ssl_conf);
4714 cur_arg = ssl_b ? ssl_b : 1;
4715 while (cur_arg < ssl_e) {
4716 newarg = 0;
4717 for (i = 0; ssl_bind_kws[i].kw != NULL; i++) {
4718 if (strcmp(ssl_bind_kws[i].kw, args[cur_arg]) == 0) {
4719 newarg = 1;
Willy Tarreaubbc91962019-10-16 16:42:19 +02004720 cfgerr |= ssl_bind_kws[i].parse(args, cur_arg, curproxy, ssl_conf, err);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004721 if (cur_arg + 1 + ssl_bind_kws[i].skip > ssl_e) {
4722 memprintf(err, "ssl args out of '[]' for %s on line %d in file '%s'",
4723 args[cur_arg], linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004724 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004725 }
4726 cur_arg += 1 + ssl_bind_kws[i].skip;
4727 break;
4728 }
4729 }
4730 if (!cfgerr && !newarg) {
4731 memprintf(err, "unknown ssl keyword %s on line %d in file '%s'.",
4732 args[cur_arg], linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004733 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004734 break;
4735 }
4736 }
Willy Tarreaubbc91962019-10-16 16:42:19 +02004737
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004738 if (cfgerr) {
4739 ssl_sock_free_ssl_conf(ssl_conf);
4740 free(ssl_conf);
4741 ssl_conf = NULL;
4742 break;
4743 }
4744
William Lallemande3af8fb2019-10-08 11:36:53 +02004745 if ((ckchs = ckchs_lookup(crt_path)) == NULL) {
William Lallemandeed4bf22019-10-10 11:38:13 +02004746 if (stat(crt_path, &buf) == 0)
William Lallemande3af8fb2019-10-08 11:36:53 +02004747 ckchs = ckchs_load_cert_file(crt_path, 0, err);
Emmanuel Hocdet1503e052019-07-31 18:30:33 +02004748 else
William Lallemande3af8fb2019-10-08 11:36:53 +02004749 ckchs = ckchs_load_cert_file(crt_path, 1, err);
yanbzhu1b04e5b2015-12-02 13:54:14 -05004750 }
4751
Willy Tarreau8c5414a2019-10-16 17:06:25 +02004752 if (!ckchs)
Willy Tarreaubbc91962019-10-16 16:42:19 +02004753 cfgerr |= ERR_ALERT | ERR_FATAL;
Willy Tarreau8c5414a2019-10-16 17:06:25 +02004754 else
4755 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 +02004756
Willy Tarreauad1731d2013-04-02 17:35:58 +02004757 if (cfgerr) {
4758 memprintf(err, "error processing line %d in file '%s' : %s", linenum, file, *err);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004759 break;
Willy Tarreauad1731d2013-04-02 17:35:58 +02004760 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004761 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004762 fclose(f);
4763 return cfgerr;
4764}
4765
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004766/* Create an initial CTX used to start the SSL connection before switchctx */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004767static int
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004768ssl_sock_initial_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02004769{
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004770 SSL_CTX *ctx = NULL;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004771 long options =
Emeric Brunfc0421f2012-09-07 17:30:07 +02004772 SSL_OP_ALL | /* all known workarounds for bugs */
4773 SSL_OP_NO_SSLv2 |
4774 SSL_OP_NO_COMPRESSION |
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02004775 SSL_OP_SINGLE_DH_USE |
Emeric Brun2b58d042012-09-20 17:10:03 +02004776 SSL_OP_SINGLE_ECDH_USE |
Emeric Brun3c4bc6e2012-10-04 18:44:19 +02004777 SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION |
Lukas Tribus926594f2018-05-18 17:55:57 +02004778 SSL_OP_PRIORITIZE_CHACHA |
Emeric Brun3c4bc6e2012-10-04 18:44:19 +02004779 SSL_OP_CIPHER_SERVER_PREFERENCE;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004780 long mode =
Emeric Brunfc0421f2012-09-07 17:30:07 +02004781 SSL_MODE_ENABLE_PARTIAL_WRITE |
4782 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
Willy Tarreau396a1862014-11-13 14:06:52 +01004783 SSL_MODE_RELEASE_BUFFERS |
4784 SSL_MODE_SMALL_BUFFERS;
Emmanuel Hocdet43664762017-08-09 18:26:20 +02004785 struct tls_version_filter *conf_ssl_methods = &bind_conf->ssl_conf.ssl_methods;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004786 int i, min, max, hole;
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004787 int flags = MC_SSL_O_ALL;
4788 int cfgerr = 0;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004789
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004790 ctx = SSL_CTX_new(SSLv23_server_method());
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004791 bind_conf->initial_ctx = ctx;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004792
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004793 if (conf_ssl_methods->flags && (conf_ssl_methods->min || conf_ssl_methods->max))
Christopher Faulet767a84b2017-11-24 16:50:31 +01004794 ha_warning("Proxy '%s': no-sslv3/no-tlsv1x are ignored for bind '%s' at [%s:%d]. "
4795 "Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
4796 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004797 else
4798 flags = conf_ssl_methods->flags;
4799
Emmanuel Hocdetbd695fe2017-05-15 15:53:41 +02004800 min = conf_ssl_methods->min;
4801 max = conf_ssl_methods->max;
4802 /* start with TLSv10 to remove SSLv3 per default */
4803 if (!min && (!max || max >= CONF_TLSV10))
4804 min = CONF_TLSV10;
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004805 /* Real min and max should be determinate with configuration and openssl's capabilities */
Emmanuel Hocdetbd695fe2017-05-15 15:53:41 +02004806 if (min)
4807 flags |= (methodVersions[min].flag - 1);
4808 if (max)
4809 flags |= ~((methodVersions[max].flag << 1) - 1);
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004810 /* find min, max and holes */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004811 min = max = CONF_TLSV_NONE;
4812 hole = 0;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004813 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004814 /* version is in openssl && version not disable in configuration */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004815 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004816 if (min) {
4817 if (hole) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004818 ha_warning("Proxy '%s': SSL/TLS versions range not contiguous for bind '%s' at [%s:%d]. "
4819 "Hole find for %s. Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
4820 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line,
4821 methodVersions[hole].name);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004822 hole = 0;
4823 }
4824 max = i;
4825 }
4826 else {
4827 min = max = i;
4828 }
4829 }
4830 else {
4831 if (min)
4832 hole = i;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004833 }
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004834 if (!min) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004835 ha_alert("Proxy '%s': all SSL/TLS versions are disabled for bind '%s' at [%s:%d].\n",
4836 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004837 cfgerr += 1;
4838 }
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02004839 /* save real min/max in bind_conf */
4840 conf_ssl_methods->min = min;
4841 conf_ssl_methods->max = max;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004842
Willy Tarreau9a1ab082019-05-09 13:26:41 +02004843#if (HA_OPENSSL_VERSION_NUMBER < 0x1010000fL)
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004844 /* Keep force-xxx implementation as it is in older haproxy. It's a
Joseph Herlant017b3da2018-11-15 09:07:59 -08004845 precautionary measure to avoid any surprise with older openssl version. */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004846 if (min == max)
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004847 methodVersions[min].ctx_set_version(ctx, SET_SERVER);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004848 else
4849 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
4850 if (flags & methodVersions[i].flag)
4851 options |= methodVersions[i].option;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004852#else /* openssl >= 1.1.0 */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004853 /* set the max_version is required to cap TLS version or activate new TLS (v1.3) */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004854 methodVersions[min].ctx_set_version(ctx, SET_MIN);
4855 methodVersions[max].ctx_set_version(ctx, SET_MAX);
Emeric Brunfa5c5c82017-04-28 16:19:51 +02004856#endif
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004857
4858 if (bind_conf->ssl_options & BC_SSL_O_NO_TLS_TICKETS)
4859 options |= SSL_OP_NO_TICKET;
4860 if (bind_conf->ssl_options & BC_SSL_O_PREF_CLIE_CIPH)
4861 options &= ~SSL_OP_CIPHER_SERVER_PREFERENCE;
Dirkjan Bussink526894f2019-01-21 09:35:03 -08004862
4863#ifdef SSL_OP_NO_RENEGOTIATION
4864 options |= SSL_OP_NO_RENEGOTIATION;
4865#endif
4866
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004867 SSL_CTX_set_options(ctx, options);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004868
Willy Tarreau5db847a2019-05-09 14:13:35 +02004869#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004870 if (global_ssl.async)
4871 mode |= SSL_MODE_ASYNC;
4872#endif
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004873 SSL_CTX_set_mode(ctx, mode);
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004874 if (global_ssl.life_time)
4875 SSL_CTX_set_timeout(ctx, global_ssl.life_time);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004876
4877#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
4878#ifdef OPENSSL_IS_BORINGSSL
4879 SSL_CTX_set_select_certificate_cb(ctx, ssl_sock_switchctx_cbk);
4880 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_err_cbk);
Ilya Shipitsine9ff8992020-01-19 12:20:14 +05004881#elif defined(SSL_OP_NO_ANTI_REPLAY)
Olivier Houchard545989f2019-12-17 15:39:54 +01004882 if (bind_conf->ssl_conf.early_data)
Olivier Houchard51088ce2019-01-02 18:46:41 +01004883 SSL_CTX_set_options(ctx, SSL_OP_NO_ANTI_REPLAY);
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02004884 SSL_CTX_set_client_hello_cb(ctx, ssl_sock_switchctx_cbk, NULL);
4885 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_err_cbk);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004886#else
4887 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_cbk);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004888#endif
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02004889 SSL_CTX_set_tlsext_servername_arg(ctx, bind_conf);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004890#endif
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004891 return cfgerr;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004892}
4893
William Lallemand4f45bb92017-10-30 20:08:51 +01004894
4895static inline void sh_ssl_sess_free_blocks(struct shared_block *first, struct shared_block *block)
4896{
4897 if (first == block) {
4898 struct sh_ssl_sess_hdr *sh_ssl_sess = (struct sh_ssl_sess_hdr *)first->data;
4899 if (first->len > 0)
4900 sh_ssl_sess_tree_delete(sh_ssl_sess);
4901 }
4902}
4903
4904/* return first block from sh_ssl_sess */
4905static inline struct shared_block *sh_ssl_sess_first_block(struct sh_ssl_sess_hdr *sh_ssl_sess)
4906{
4907 return (struct shared_block *)((unsigned char *)sh_ssl_sess - ((struct shared_block *)NULL)->data);
4908
4909}
4910
4911/* store a session into the cache
4912 * s_id : session id padded with zero to SSL_MAX_SSL_SESSION_ID_LENGTH
4913 * data: asn1 encoded session
4914 * data_len: asn1 encoded session length
4915 * Returns 1 id session was stored (else 0)
4916 */
4917static int sh_ssl_sess_store(unsigned char *s_id, unsigned char *data, int data_len)
4918{
4919 struct shared_block *first;
4920 struct sh_ssl_sess_hdr *sh_ssl_sess, *oldsh_ssl_sess;
4921
Frédéric Lécaille0bec8072018-10-22 17:55:57 +02004922 first = shctx_row_reserve_hot(ssl_shctx, NULL, data_len + sizeof(struct sh_ssl_sess_hdr));
William Lallemand4f45bb92017-10-30 20:08:51 +01004923 if (!first) {
4924 /* Could not retrieve enough free blocks to store that session */
4925 return 0;
4926 }
4927
4928 /* STORE the key in the first elem */
4929 sh_ssl_sess = (struct sh_ssl_sess_hdr *)first->data;
4930 memcpy(sh_ssl_sess->key_data, s_id, SSL_MAX_SSL_SESSION_ID_LENGTH);
4931 first->len = sizeof(struct sh_ssl_sess_hdr);
4932
4933 /* it returns the already existing node
4934 or current node if none, never returns null */
4935 oldsh_ssl_sess = sh_ssl_sess_tree_insert(sh_ssl_sess);
4936 if (oldsh_ssl_sess != sh_ssl_sess) {
4937 /* NOTE: Row couldn't be in use because we lock read & write function */
4938 /* release the reserved row */
4939 shctx_row_dec_hot(ssl_shctx, first);
4940 /* replace the previous session already in the tree */
4941 sh_ssl_sess = oldsh_ssl_sess;
4942 /* ignore the previous session data, only use the header */
4943 first = sh_ssl_sess_first_block(sh_ssl_sess);
4944 shctx_row_inc_hot(ssl_shctx, first);
4945 first->len = sizeof(struct sh_ssl_sess_hdr);
4946 }
4947
Frédéric Lécaille0bec8072018-10-22 17:55:57 +02004948 if (shctx_row_data_append(ssl_shctx, first, NULL, data, data_len) < 0) {
William Lallemand99b90af2018-01-03 19:15:51 +01004949 shctx_row_dec_hot(ssl_shctx, first);
William Lallemand4f45bb92017-10-30 20:08:51 +01004950 return 0;
William Lallemand99b90af2018-01-03 19:15:51 +01004951 }
4952
4953 shctx_row_dec_hot(ssl_shctx, first);
William Lallemand4f45bb92017-10-30 20:08:51 +01004954
4955 return 1;
4956}
William Lallemanded0b5ad2017-10-30 19:36:36 +01004957
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004958/* SSL callback used when a new session is created while connecting to a server */
4959static int ssl_sess_new_srv_cb(SSL *ssl, SSL_SESSION *sess)
4960{
Thierry FOURNIER28962c92018-06-17 21:37:05 +02004961 struct connection *conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Olivier Houcharde6060c52017-11-16 17:42:52 +01004962 struct server *s;
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004963
Willy Tarreau07d94e42018-09-20 10:57:52 +02004964 s = __objt_server(conn->target);
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004965
Olivier Houcharde6060c52017-11-16 17:42:52 +01004966 if (!(s->ssl_ctx.options & SRV_SSL_O_NO_REUSE)) {
4967 int len;
4968 unsigned char *ptr;
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004969
Olivier Houcharde6060c52017-11-16 17:42:52 +01004970 len = i2d_SSL_SESSION(sess, NULL);
4971 if (s->ssl_ctx.reused_sess[tid].ptr && s->ssl_ctx.reused_sess[tid].allocated_size >= len) {
4972 ptr = s->ssl_ctx.reused_sess[tid].ptr;
4973 } else {
4974 free(s->ssl_ctx.reused_sess[tid].ptr);
4975 ptr = s->ssl_ctx.reused_sess[tid].ptr = malloc(len);
4976 s->ssl_ctx.reused_sess[tid].allocated_size = len;
4977 }
4978 if (s->ssl_ctx.reused_sess[tid].ptr) {
4979 s->ssl_ctx.reused_sess[tid].size = i2d_SSL_SESSION(sess,
4980 &ptr);
4981 }
4982 } else {
4983 free(s->ssl_ctx.reused_sess[tid].ptr);
4984 s->ssl_ctx.reused_sess[tid].ptr = NULL;
4985 }
4986
4987 return 0;
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004988}
4989
Olivier Houcharde6060c52017-11-16 17:42:52 +01004990
William Lallemanded0b5ad2017-10-30 19:36:36 +01004991/* SSL callback used on new session creation */
William Lallemand4f45bb92017-10-30 20:08:51 +01004992int sh_ssl_sess_new_cb(SSL *ssl, SSL_SESSION *sess)
William Lallemanded0b5ad2017-10-30 19:36:36 +01004993{
4994 unsigned char encsess[SHSESS_MAX_DATA_LEN]; /* encoded session */
4995 unsigned char encid[SSL_MAX_SSL_SESSION_ID_LENGTH]; /* encoded id */
4996 unsigned char *p;
4997 int data_len;
Emeric Bruneb469652019-10-08 18:27:37 +02004998 unsigned int sid_length;
William Lallemanded0b5ad2017-10-30 19:36:36 +01004999 const unsigned char *sid_data;
William Lallemanded0b5ad2017-10-30 19:36:36 +01005000
5001 /* Session id is already stored in to key and session id is known
5002 * so we dont store it to keep size.
Emeric Bruneb469652019-10-08 18:27:37 +02005003 * note: SSL_SESSION_set1_id is using
5004 * a memcpy so we need to use a different pointer
5005 * than sid_data or sid_ctx_data to avoid valgrind
5006 * complaining.
William Lallemanded0b5ad2017-10-30 19:36:36 +01005007 */
5008
5009 sid_data = SSL_SESSION_get_id(sess, &sid_length);
Emeric Bruneb469652019-10-08 18:27:37 +02005010
5011 /* copy value in an other buffer */
5012 memcpy(encid, sid_data, sid_length);
5013
5014 /* pad with 0 */
5015 if (sid_length < SSL_MAX_SSL_SESSION_ID_LENGTH)
5016 memset(encid + sid_length, 0, SSL_MAX_SSL_SESSION_ID_LENGTH-sid_length);
5017
5018 /* force length to zero to avoid ASN1 encoding */
5019 SSL_SESSION_set1_id(sess, encid, 0);
5020
5021 /* force length to zero to avoid ASN1 encoding */
5022 SSL_SESSION_set1_id_context(sess, (const unsigned char *)SHCTX_APPNAME, 0);
William Lallemanded0b5ad2017-10-30 19:36:36 +01005023
5024 /* check if buffer is large enough for the ASN1 encoded session */
5025 data_len = i2d_SSL_SESSION(sess, NULL);
5026 if (data_len > SHSESS_MAX_DATA_LEN)
5027 goto err;
5028
5029 p = encsess;
5030
5031 /* process ASN1 session encoding before the lock */
5032 i2d_SSL_SESSION(sess, &p);
5033
William Lallemanded0b5ad2017-10-30 19:36:36 +01005034
William Lallemanda3c77cf2017-10-30 23:44:40 +01005035 shctx_lock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01005036 /* store to cache */
William Lallemand4f45bb92017-10-30 20:08:51 +01005037 sh_ssl_sess_store(encid, encsess, data_len);
William Lallemanda3c77cf2017-10-30 23:44:40 +01005038 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01005039err:
5040 /* reset original length values */
Emeric Bruneb469652019-10-08 18:27:37 +02005041 SSL_SESSION_set1_id(sess, encid, sid_length);
5042 SSL_SESSION_set1_id_context(sess, (const unsigned char *)SHCTX_APPNAME, strlen(SHCTX_APPNAME));
William Lallemanded0b5ad2017-10-30 19:36:36 +01005043
5044 return 0; /* do not increment session reference count */
5045}
5046
5047/* SSL callback used on lookup an existing session cause none found in internal cache */
William Lallemand4f45bb92017-10-30 20:08:51 +01005048SSL_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 +01005049{
William Lallemand4f45bb92017-10-30 20:08:51 +01005050 struct sh_ssl_sess_hdr *sh_ssl_sess;
William Lallemanded0b5ad2017-10-30 19:36:36 +01005051 unsigned char data[SHSESS_MAX_DATA_LEN], *p;
5052 unsigned char tmpkey[SSL_MAX_SSL_SESSION_ID_LENGTH];
William Lallemanded0b5ad2017-10-30 19:36:36 +01005053 SSL_SESSION *sess;
William Lallemand4f45bb92017-10-30 20:08:51 +01005054 struct shared_block *first;
William Lallemanded0b5ad2017-10-30 19:36:36 +01005055
5056 global.shctx_lookups++;
5057
5058 /* allow the session to be freed automatically by openssl */
5059 *do_copy = 0;
5060
5061 /* tree key is zeros padded sessionid */
5062 if (key_len < SSL_MAX_SSL_SESSION_ID_LENGTH) {
5063 memcpy(tmpkey, key, key_len);
5064 memset(tmpkey + key_len, 0, SSL_MAX_SSL_SESSION_ID_LENGTH - key_len);
5065 key = tmpkey;
5066 }
5067
5068 /* lock cache */
William Lallemanda3c77cf2017-10-30 23:44:40 +01005069 shctx_lock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01005070
5071 /* lookup for session */
William Lallemand4f45bb92017-10-30 20:08:51 +01005072 sh_ssl_sess = sh_ssl_sess_tree_lookup(key);
5073 if (!sh_ssl_sess) {
William Lallemanded0b5ad2017-10-30 19:36:36 +01005074 /* no session found: unlock cache and exit */
William Lallemanda3c77cf2017-10-30 23:44:40 +01005075 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01005076 global.shctx_misses++;
5077 return NULL;
5078 }
5079
William Lallemand4f45bb92017-10-30 20:08:51 +01005080 /* sh_ssl_sess (shared_block->data) is at the end of shared_block */
5081 first = sh_ssl_sess_first_block(sh_ssl_sess);
William Lallemanded0b5ad2017-10-30 19:36:36 +01005082
William Lallemand4f45bb92017-10-30 20:08:51 +01005083 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 +01005084
William Lallemanda3c77cf2017-10-30 23:44:40 +01005085 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01005086
5087 /* decode ASN1 session */
5088 p = data;
William Lallemand4f45bb92017-10-30 20:08:51 +01005089 sess = d2i_SSL_SESSION(NULL, (const unsigned char **)&p, first->len-sizeof(struct sh_ssl_sess_hdr));
William Lallemanded0b5ad2017-10-30 19:36:36 +01005090 /* Reset session id and session id contenxt */
5091 if (sess) {
5092 SSL_SESSION_set1_id(sess, key, key_len);
5093 SSL_SESSION_set1_id_context(sess, (const unsigned char *)SHCTX_APPNAME, strlen(SHCTX_APPNAME));
5094 }
5095
5096 return sess;
5097}
5098
William Lallemand4f45bb92017-10-30 20:08:51 +01005099
William Lallemanded0b5ad2017-10-30 19:36:36 +01005100/* SSL callback used to signal session is no more used in internal cache */
William Lallemand4f45bb92017-10-30 20:08:51 +01005101void sh_ssl_sess_remove_cb(SSL_CTX *ctx, SSL_SESSION *sess)
William Lallemanded0b5ad2017-10-30 19:36:36 +01005102{
William Lallemand4f45bb92017-10-30 20:08:51 +01005103 struct sh_ssl_sess_hdr *sh_ssl_sess;
William Lallemanded0b5ad2017-10-30 19:36:36 +01005104 unsigned char tmpkey[SSL_MAX_SSL_SESSION_ID_LENGTH];
5105 unsigned int sid_length;
5106 const unsigned char *sid_data;
5107 (void)ctx;
5108
5109 sid_data = SSL_SESSION_get_id(sess, &sid_length);
5110 /* tree key is zeros padded sessionid */
5111 if (sid_length < SSL_MAX_SSL_SESSION_ID_LENGTH) {
5112 memcpy(tmpkey, sid_data, sid_length);
5113 memset(tmpkey+sid_length, 0, SSL_MAX_SSL_SESSION_ID_LENGTH - sid_length);
5114 sid_data = tmpkey;
5115 }
5116
William Lallemanda3c77cf2017-10-30 23:44:40 +01005117 shctx_lock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01005118
5119 /* lookup for session */
William Lallemand4f45bb92017-10-30 20:08:51 +01005120 sh_ssl_sess = sh_ssl_sess_tree_lookup(sid_data);
5121 if (sh_ssl_sess) {
William Lallemanded0b5ad2017-10-30 19:36:36 +01005122 /* free session */
William Lallemand4f45bb92017-10-30 20:08:51 +01005123 sh_ssl_sess_tree_delete(sh_ssl_sess);
William Lallemanded0b5ad2017-10-30 19:36:36 +01005124 }
5125
5126 /* unlock cache */
William Lallemanda3c77cf2017-10-30 23:44:40 +01005127 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01005128}
5129
5130/* Set session cache mode to server and disable openssl internal cache.
5131 * Set shared cache callbacks on an ssl context.
5132 * Shared context MUST be firstly initialized */
William Lallemand4f45bb92017-10-30 20:08:51 +01005133void ssl_set_shctx(SSL_CTX *ctx)
William Lallemanded0b5ad2017-10-30 19:36:36 +01005134{
5135 SSL_CTX_set_session_id_context(ctx, (const unsigned char *)SHCTX_APPNAME, strlen(SHCTX_APPNAME));
5136
5137 if (!ssl_shctx) {
5138 SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF);
5139 return;
5140 }
5141
5142 SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_SERVER |
5143 SSL_SESS_CACHE_NO_INTERNAL |
5144 SSL_SESS_CACHE_NO_AUTO_CLEAR);
5145
5146 /* Set callbacks */
William Lallemand4f45bb92017-10-30 20:08:51 +01005147 SSL_CTX_sess_set_new_cb(ctx, sh_ssl_sess_new_cb);
5148 SSL_CTX_sess_set_get_cb(ctx, sh_ssl_sess_get_cb);
5149 SSL_CTX_sess_set_remove_cb(ctx, sh_ssl_sess_remove_cb);
William Lallemanded0b5ad2017-10-30 19:36:36 +01005150}
5151
William Lallemand8b453912019-11-21 15:48:10 +01005152/*
5153 * This function applies the SSL configuration on a SSL_CTX
5154 * It returns an error code and fills the <err> buffer
5155 */
5156int 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 +01005157{
5158 struct proxy *curproxy = bind_conf->frontend;
5159 int cfgerr = 0;
5160 int verify = SSL_VERIFY_NONE;
Willy Tarreau5d4cafb2018-01-04 18:55:19 +01005161 struct ssl_bind_conf __maybe_unused *ssl_conf_cur;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005162 const char *conf_ciphers;
Emmanuel Hocdet839af572019-05-14 16:27:35 +02005163#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02005164 const char *conf_ciphersuites;
5165#endif
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01005166 const char *conf_curves = NULL;
Emeric Brunfc0421f2012-09-07 17:30:07 +02005167
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02005168 if (ssl_conf) {
5169 struct tls_version_filter *conf_ssl_methods = &ssl_conf->ssl_methods;
5170 int i, min, max;
5171 int flags = MC_SSL_O_ALL;
5172
5173 /* Real min and max should be determinate with configuration and openssl's capabilities */
Emmanuel Hocdet43664762017-08-09 18:26:20 +02005174 min = conf_ssl_methods->min ? conf_ssl_methods->min : bind_conf->ssl_conf.ssl_methods.min;
5175 max = conf_ssl_methods->max ? conf_ssl_methods->max : bind_conf->ssl_conf.ssl_methods.max;
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02005176 if (min)
5177 flags |= (methodVersions[min].flag - 1);
5178 if (max)
5179 flags |= ~((methodVersions[max].flag << 1) - 1);
5180 min = max = CONF_TLSV_NONE;
5181 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
5182 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
5183 if (min)
5184 max = i;
5185 else
5186 min = max = i;
5187 }
5188 /* save real min/max */
5189 conf_ssl_methods->min = min;
5190 conf_ssl_methods->max = max;
5191 if (!min) {
Tim Duesterhus93128532019-11-23 23:45:10 +01005192 memprintf(err, "%sProxy '%s': all SSL/TLS versions are disabled for bind '%s' at [%s:%d].\n",
5193 err && *err ? *err : "", bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
William Lallemand8b453912019-11-21 15:48:10 +01005194 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02005195 }
5196 }
5197
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005198 switch ((ssl_conf && ssl_conf->verify) ? ssl_conf->verify : bind_conf->ssl_conf.verify) {
Emeric Brun850efd52014-01-29 12:24:34 +01005199 case SSL_SOCK_VERIFY_NONE:
5200 verify = SSL_VERIFY_NONE;
5201 break;
5202 case SSL_SOCK_VERIFY_OPTIONAL:
5203 verify = SSL_VERIFY_PEER;
5204 break;
5205 case SSL_SOCK_VERIFY_REQUIRED:
5206 verify = SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
5207 break;
5208 }
5209 SSL_CTX_set_verify(ctx, verify, ssl_sock_bind_verifycbk);
5210 if (verify & SSL_VERIFY_PEER) {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005211 char *ca_file = (ssl_conf && ssl_conf->ca_file) ? ssl_conf->ca_file : bind_conf->ssl_conf.ca_file;
Emmanuel Hocdet842e94e2019-12-16 16:39:17 +01005212 char *ca_verify_file = (ssl_conf && ssl_conf->ca_verify_file) ? ssl_conf->ca_verify_file : bind_conf->ssl_conf.ca_verify_file;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005213 char *crl_file = (ssl_conf && ssl_conf->crl_file) ? ssl_conf->crl_file : bind_conf->ssl_conf.crl_file;
Emmanuel Hocdet842e94e2019-12-16 16:39:17 +01005214 if (ca_file || ca_verify_file) {
Emmanuel Hocdetd4f9a602019-10-24 11:32:47 +02005215 /* set CAfile to verify */
Emmanuel Hocdet842e94e2019-12-16 16:39:17 +01005216 if (ca_file && !ssl_set_verify_locations_file(ctx, ca_file)) {
Emmanuel Hocdetd4f9a602019-10-24 11:32:47 +02005217 memprintf(err, "%sProxy '%s': unable to set CA file '%s' for bind '%s' at [%s:%d].\n",
Tim Duesterhus93128532019-11-23 23:45:10 +01005218 err && *err ? *err : "", curproxy->id, ca_file, bind_conf->arg, bind_conf->file, bind_conf->line);
William Lallemand8b453912019-11-21 15:48:10 +01005219 cfgerr |= ERR_ALERT | ERR_FATAL;
Emeric Brund94b3fe2012-09-20 18:23:56 +02005220 }
Emmanuel Hocdet842e94e2019-12-16 16:39:17 +01005221 if (ca_verify_file && !ssl_set_verify_locations_file(ctx, ca_verify_file)) {
5222 memprintf(err, "%sProxy '%s': unable to set CA-no-names file '%s' for bind '%s' at [%s:%d].\n",
5223 err && *err ? *err : "", curproxy->id, ca_verify_file, bind_conf->arg, bind_conf->file, bind_conf->line);
5224 cfgerr |= ERR_ALERT | ERR_FATAL;
5225 }
5226 if (ca_file && !((ssl_conf && ssl_conf->no_ca_names) || bind_conf->ssl_conf.no_ca_names)) {
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02005227 /* set CA names for client cert request, function returns void */
Emmanuel Hocdet129d3282019-10-24 18:08:51 +02005228 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 +02005229 }
Emeric Brund94b3fe2012-09-20 18:23:56 +02005230 }
Emeric Brun850efd52014-01-29 12:24:34 +01005231 else {
Tim Duesterhus93128532019-11-23 23:45:10 +01005232 memprintf(err, "%sProxy '%s': verify is enabled but no CA file specified for bind '%s' at [%s:%d].\n",
5233 err && *err ? *err : "", curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
William Lallemand8b453912019-11-21 15:48:10 +01005234 cfgerr |= ERR_ALERT | ERR_FATAL;
Emeric Brun850efd52014-01-29 12:24:34 +01005235 }
Emeric Brun051cdab2012-10-02 19:25:50 +02005236#ifdef X509_V_FLAG_CRL_CHECK
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005237 if (crl_file) {
Emeric Brund94b3fe2012-09-20 18:23:56 +02005238 X509_STORE *store = SSL_CTX_get_cert_store(ctx);
5239
Emmanuel Hocdetb270e812019-11-21 19:09:31 +01005240 if (!ssl_set_cert_crl_file(store, crl_file)) {
Tim Duesterhus93128532019-11-23 23:45:10 +01005241 memprintf(err, "%sProxy '%s': unable to configure CRL file '%s' for bind '%s' at [%s:%d].\n",
5242 err && *err ? *err : "", curproxy->id, crl_file, bind_conf->arg, bind_conf->file, bind_conf->line);
William Lallemand8b453912019-11-21 15:48:10 +01005243 cfgerr |= ERR_ALERT | ERR_FATAL;
Emeric Brund94b3fe2012-09-20 18:23:56 +02005244 }
Emeric Brun561e5742012-10-02 15:20:55 +02005245 else {
5246 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
5247 }
Emeric Brund94b3fe2012-09-20 18:23:56 +02005248 }
Emeric Brun051cdab2012-10-02 19:25:50 +02005249#endif
Emeric Brun644cde02012-12-14 11:21:13 +01005250 ERR_clear_error();
Emeric Brund94b3fe2012-09-20 18:23:56 +02005251 }
Nenad Merdanovic05552d42015-02-27 19:56:49 +01005252#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
Nenad Merdanovic146defa2015-05-09 08:46:00 +02005253 if(bind_conf->keys_ref) {
Nenad Merdanovic05552d42015-02-27 19:56:49 +01005254 if (!SSL_CTX_set_tlsext_ticket_key_cb(ctx, ssl_tlsext_ticket_key_cb)) {
Tim Duesterhus93128532019-11-23 23:45:10 +01005255 memprintf(err, "%sProxy '%s': unable to set callback for TLS ticket validation for bind '%s' at [%s:%d].\n",
5256 err && *err ? *err : "", curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
William Lallemand8b453912019-11-21 15:48:10 +01005257 cfgerr |= ERR_ALERT | ERR_FATAL;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01005258 }
5259 }
5260#endif
5261
William Lallemand4f45bb92017-10-30 20:08:51 +01005262 ssl_set_shctx(ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005263 conf_ciphers = (ssl_conf && ssl_conf->ciphers) ? ssl_conf->ciphers : bind_conf->ssl_conf.ciphers;
5264 if (conf_ciphers &&
5265 !SSL_CTX_set_cipher_list(ctx, conf_ciphers)) {
Tim Duesterhus93128532019-11-23 23:45:10 +01005266 memprintf(err, "%sProxy '%s': unable to set SSL cipher list to '%s' for bind '%s' at [%s:%d].\n",
5267 err && *err ? *err : "", curproxy->id, conf_ciphers, bind_conf->arg, bind_conf->file, bind_conf->line);
William Lallemand8b453912019-11-21 15:48:10 +01005268 cfgerr |= ERR_ALERT | ERR_FATAL;
Emeric Brunfc0421f2012-09-07 17:30:07 +02005269 }
5270
Emmanuel Hocdet839af572019-05-14 16:27:35 +02005271#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02005272 conf_ciphersuites = (ssl_conf && ssl_conf->ciphersuites) ? ssl_conf->ciphersuites : bind_conf->ssl_conf.ciphersuites;
5273 if (conf_ciphersuites &&
5274 !SSL_CTX_set_ciphersuites(ctx, conf_ciphersuites)) {
Tim Duesterhus93128532019-11-23 23:45:10 +01005275 memprintf(err, "%sProxy '%s': unable to set TLS 1.3 cipher suites to '%s' for bind '%s' at [%s:%d].\n",
5276 err && *err ? *err : "", curproxy->id, conf_ciphersuites, bind_conf->arg, bind_conf->file, bind_conf->line);
William Lallemand8b453912019-11-21 15:48:10 +01005277 cfgerr |= ERR_ALERT | ERR_FATAL;
Dirkjan Bussink415150f2018-09-14 11:14:21 +02005278 }
5279#endif
5280
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01005281#ifndef OPENSSL_NO_DH
Remi Gacogne47783ef2015-05-29 15:53:22 +02005282 /* If tune.ssl.default-dh-param has not been set,
5283 neither has ssl-default-dh-file and no static DH
5284 params were in the certificate file. */
Willy Tarreauef934602016-12-22 23:12:01 +01005285 if (global_ssl.default_dh_param == 0 &&
Remi Gacogne47783ef2015-05-29 15:53:22 +02005286 global_dh == NULL &&
Remi Gacogne4f902b82015-05-28 16:23:00 +02005287 (ssl_dh_ptr_index == -1 ||
5288 SSL_CTX_get_ex_data(ctx, ssl_dh_ptr_index) == NULL)) {
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01005289 STACK_OF(SSL_CIPHER) * ciphers = NULL;
5290 const SSL_CIPHER * cipher = NULL;
5291 char cipher_description[128];
5292 /* The description of ciphers using an Ephemeral Diffie Hellman key exchange
5293 contains " Kx=DH " or " Kx=DH(". Beware of " Kx=DH/",
5294 which is not ephemeral DH. */
5295 const char dhe_description[] = " Kx=DH ";
5296 const char dhe_export_description[] = " Kx=DH(";
5297 int idx = 0;
5298 int dhe_found = 0;
5299 SSL *ssl = NULL;
Lukas Tribus90132722014-08-18 00:56:33 +02005300
Remi Gacogne23d5d372014-10-10 17:04:26 +02005301 ssl = SSL_new(ctx);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02005302
Remi Gacogne23d5d372014-10-10 17:04:26 +02005303 if (ssl) {
5304 ciphers = SSL_get_ciphers(ssl);
5305
5306 if (ciphers) {
5307 for (idx = 0; idx < sk_SSL_CIPHER_num(ciphers); idx++) {
5308 cipher = sk_SSL_CIPHER_value(ciphers, idx);
5309 if (SSL_CIPHER_description(cipher, cipher_description, sizeof (cipher_description)) == cipher_description) {
5310 if (strstr(cipher_description, dhe_description) != NULL ||
5311 strstr(cipher_description, dhe_export_description) != NULL) {
5312 dhe_found = 1;
5313 break;
5314 }
Remi Gacognec1eab8c2014-06-12 18:20:11 +02005315 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02005316 }
5317 }
Remi Gacogne23d5d372014-10-10 17:04:26 +02005318 SSL_free(ssl);
5319 ssl = NULL;
Lukas Tribus90132722014-08-18 00:56:33 +02005320 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02005321
Lukas Tribus90132722014-08-18 00:56:33 +02005322 if (dhe_found) {
Tim Duesterhus93128532019-11-23 23:45:10 +01005323 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",
5324 err && *err ? *err : "");
William Lallemand8b453912019-11-21 15:48:10 +01005325 cfgerr |= ERR_WARN;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02005326 }
5327
Willy Tarreauef934602016-12-22 23:12:01 +01005328 global_ssl.default_dh_param = 1024;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02005329 }
Remi Gacogne8de54152014-07-15 11:36:40 +02005330
Willy Tarreauef934602016-12-22 23:12:01 +01005331 if (global_ssl.default_dh_param >= 1024) {
Remi Gacogne8de54152014-07-15 11:36:40 +02005332 if (local_dh_1024 == NULL) {
5333 local_dh_1024 = ssl_get_dh_1024();
5334 }
Willy Tarreauef934602016-12-22 23:12:01 +01005335 if (global_ssl.default_dh_param >= 2048) {
Remi Gacogne8de54152014-07-15 11:36:40 +02005336 if (local_dh_2048 == NULL) {
5337 local_dh_2048 = ssl_get_dh_2048();
5338 }
Willy Tarreauef934602016-12-22 23:12:01 +01005339 if (global_ssl.default_dh_param >= 4096) {
Remi Gacogne8de54152014-07-15 11:36:40 +02005340 if (local_dh_4096 == NULL) {
5341 local_dh_4096 = ssl_get_dh_4096();
5342 }
Remi Gacogne8de54152014-07-15 11:36:40 +02005343 }
5344 }
5345 }
5346#endif /* OPENSSL_NO_DH */
Remi Gacognef46cd6e2014-06-12 14:58:40 +02005347
Emeric Brunfc0421f2012-09-07 17:30:07 +02005348 SSL_CTX_set_info_callback(ctx, ssl_sock_infocbk);
Willy Tarreau9a1ab082019-05-09 13:26:41 +02005349#if HA_OPENSSL_VERSION_NUMBER >= 0x00907000L
Emeric Brun29f037d2014-04-25 19:05:36 +02005350 SSL_CTX_set_msg_callback(ctx, ssl_sock_msgcbk);
Willy Tarreau5cbe4ef2014-05-08 22:45:11 +02005351#endif
Emeric Brun29f037d2014-04-25 19:05:36 +02005352
Bernard Spil13c53f82018-02-15 13:34:58 +01005353#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005354 ssl_conf_cur = NULL;
5355 if (ssl_conf && ssl_conf->npn_str)
5356 ssl_conf_cur = ssl_conf;
5357 else if (bind_conf->ssl_conf.npn_str)
5358 ssl_conf_cur = &bind_conf->ssl_conf;
5359 if (ssl_conf_cur)
5360 SSL_CTX_set_next_protos_advertised_cb(ctx, ssl_sock_advertise_npn_protos, ssl_conf_cur);
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02005361#endif
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01005362#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005363 ssl_conf_cur = NULL;
5364 if (ssl_conf && ssl_conf->alpn_str)
5365 ssl_conf_cur = ssl_conf;
5366 else if (bind_conf->ssl_conf.alpn_str)
5367 ssl_conf_cur = &bind_conf->ssl_conf;
5368 if (ssl_conf_cur)
5369 SSL_CTX_set_alpn_select_cb(ctx, ssl_sock_advertise_alpn_protos, ssl_conf_cur);
Willy Tarreauab861d32013-04-02 02:30:41 +02005370#endif
Lukas Tribusd14b49c2019-11-24 18:20:40 +01005371#if ((HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL) || defined(LIBRESSL_VERSION_NUMBER))
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01005372 conf_curves = (ssl_conf && ssl_conf->curves) ? ssl_conf->curves : bind_conf->ssl_conf.curves;
5373 if (conf_curves) {
5374 if (!SSL_CTX_set1_curves_list(ctx, conf_curves)) {
Tim Duesterhus93128532019-11-23 23:45:10 +01005375 memprintf(err, "%sProxy '%s': unable to set SSL curves list to '%s' for bind '%s' at [%s:%d].\n",
5376 err && *err ? *err : "", curproxy->id, conf_curves, bind_conf->arg, bind_conf->file, bind_conf->line);
William Lallemand8b453912019-11-21 15:48:10 +01005377 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01005378 }
Emmanuel Hocdeta52bb152017-03-20 11:11:49 +01005379 (void)SSL_CTX_set_ecdh_auto(ctx, 1);
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01005380 }
5381#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02005382#if defined(SSL_CTX_set_tmp_ecdh) && !defined(OPENSSL_NO_ECDH)
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01005383 if (!conf_curves) {
Emeric Brun2b58d042012-09-20 17:10:03 +02005384 int i;
5385 EC_KEY *ecdh;
Willy Tarreau9a1ab082019-05-09 13:26:41 +02005386#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005387 const char *ecdhe = (ssl_conf && ssl_conf->ecdhe) ? ssl_conf->ecdhe :
Olivier Houchardc2aae742017-09-22 18:26:28 +02005388 (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe :
5389 NULL);
5390
5391 if (ecdhe == NULL) {
Eric Salama3c8bde82019-11-20 11:33:40 +01005392 (void)SSL_CTX_set_ecdh_auto(ctx, 1);
Olivier Houchardc2aae742017-09-22 18:26:28 +02005393 return cfgerr;
5394 }
5395#else
5396 const char *ecdhe = (ssl_conf && ssl_conf->ecdhe) ? ssl_conf->ecdhe :
5397 (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe :
5398 ECDHE_DEFAULT_CURVE);
5399#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02005400
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005401 i = OBJ_sn2nid(ecdhe);
Emeric Brun2b58d042012-09-20 17:10:03 +02005402 if (!i || ((ecdh = EC_KEY_new_by_curve_name(i)) == NULL)) {
Tim Duesterhus93128532019-11-23 23:45:10 +01005403 memprintf(err, "%sProxy '%s': unable to set elliptic named curve to '%s' for bind '%s' at [%s:%d].\n",
5404 err && *err ? *err : "", curproxy->id, ecdhe, bind_conf->arg, bind_conf->file, bind_conf->line);
William Lallemand8b453912019-11-21 15:48:10 +01005405 cfgerr |= ERR_ALERT | ERR_FATAL;
Emeric Brun2b58d042012-09-20 17:10:03 +02005406 }
5407 else {
5408 SSL_CTX_set_tmp_ecdh(ctx, ecdh);
5409 EC_KEY_free(ecdh);
5410 }
5411 }
5412#endif
5413
Emeric Brunfc0421f2012-09-07 17:30:07 +02005414 return cfgerr;
5415}
5416
Evan Broderbe554312013-06-27 00:05:25 -07005417static int ssl_sock_srv_hostcheck(const char *pattern, const char *hostname)
5418{
5419 const char *pattern_wildcard, *pattern_left_label_end, *hostname_left_label_end;
5420 size_t prefixlen, suffixlen;
5421
5422 /* Trivial case */
5423 if (strcmp(pattern, hostname) == 0)
5424 return 1;
5425
Evan Broderbe554312013-06-27 00:05:25 -07005426 /* The rest of this logic is based on RFC 6125, section 6.4.3
5427 * (http://tools.ietf.org/html/rfc6125#section-6.4.3) */
5428
Emeric Bruna848dae2013-10-08 11:27:28 +02005429 pattern_wildcard = NULL;
5430 pattern_left_label_end = pattern;
5431 while (*pattern_left_label_end != '.') {
5432 switch (*pattern_left_label_end) {
5433 case 0:
5434 /* End of label not found */
5435 return 0;
5436 case '*':
5437 /* If there is more than one wildcards */
5438 if (pattern_wildcard)
5439 return 0;
5440 pattern_wildcard = pattern_left_label_end;
5441 break;
5442 }
5443 pattern_left_label_end++;
5444 }
5445
5446 /* If it's not trivial and there is no wildcard, it can't
5447 * match */
5448 if (!pattern_wildcard)
Evan Broderbe554312013-06-27 00:05:25 -07005449 return 0;
5450
5451 /* Make sure all labels match except the leftmost */
5452 hostname_left_label_end = strchr(hostname, '.');
5453 if (!hostname_left_label_end
5454 || strcmp(pattern_left_label_end, hostname_left_label_end) != 0)
5455 return 0;
5456
5457 /* Make sure the leftmost label of the hostname is long enough
5458 * that the wildcard can match */
Emeric Brun369da852013-10-08 11:39:35 +02005459 if (hostname_left_label_end - hostname < (pattern_left_label_end - pattern) - 1)
Evan Broderbe554312013-06-27 00:05:25 -07005460 return 0;
5461
5462 /* Finally compare the string on either side of the
5463 * wildcard */
5464 prefixlen = pattern_wildcard - pattern;
5465 suffixlen = pattern_left_label_end - (pattern_wildcard + 1);
Emeric Bruna848dae2013-10-08 11:27:28 +02005466 if ((prefixlen && (memcmp(pattern, hostname, prefixlen) != 0))
5467 || (suffixlen && (memcmp(pattern_wildcard + 1, hostname_left_label_end - suffixlen, suffixlen) != 0)))
Evan Broderbe554312013-06-27 00:05:25 -07005468 return 0;
5469
5470 return 1;
5471}
5472
5473static int ssl_sock_srv_verifycbk(int ok, X509_STORE_CTX *ctx)
5474{
5475 SSL *ssl;
5476 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01005477 struct ssl_sock_ctx *ssl_ctx;
Willy Tarreau2ab88672017-07-05 18:23:03 +02005478 const char *servername;
Willy Tarreau71d058c2017-07-26 20:09:56 +02005479 const char *sni;
Evan Broderbe554312013-06-27 00:05:25 -07005480
5481 int depth;
5482 X509 *cert;
5483 STACK_OF(GENERAL_NAME) *alt_names;
5484 int i;
5485 X509_NAME *cert_subject;
5486 char *str;
5487
5488 if (ok == 0)
5489 return ok;
5490
5491 ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
Thierry FOURNIER28962c92018-06-17 21:37:05 +02005492 conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Olivier Houchard66ab4982019-02-26 18:37:15 +01005493 ssl_ctx = conn->xprt_ctx;
Evan Broderbe554312013-06-27 00:05:25 -07005494
Willy Tarreauad92a9a2017-07-28 11:38:41 +02005495 /* We're checking if the provided hostnames match the desired one. The
5496 * desired hostname comes from the SNI we presented if any, or if not
5497 * provided then it may have been explicitly stated using a "verifyhost"
5498 * directive. If neither is set, we don't care about the name so the
5499 * verification is OK.
Willy Tarreau2ab88672017-07-05 18:23:03 +02005500 */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005501 servername = SSL_get_servername(ssl_ctx->ssl, TLSEXT_NAMETYPE_host_name);
Willy Tarreau71d058c2017-07-26 20:09:56 +02005502 sni = servername;
Willy Tarreau2ab88672017-07-05 18:23:03 +02005503 if (!servername) {
Willy Tarreau07d94e42018-09-20 10:57:52 +02005504 servername = __objt_server(conn->target)->ssl_ctx.verify_host;
Willy Tarreau2ab88672017-07-05 18:23:03 +02005505 if (!servername)
5506 return ok;
5507 }
Evan Broderbe554312013-06-27 00:05:25 -07005508
5509 /* We only need to verify the CN on the actual server cert,
5510 * not the indirect CAs */
5511 depth = X509_STORE_CTX_get_error_depth(ctx);
5512 if (depth != 0)
5513 return ok;
5514
5515 /* At this point, the cert is *not* OK unless we can find a
5516 * hostname match */
5517 ok = 0;
5518
5519 cert = X509_STORE_CTX_get_current_cert(ctx);
5520 /* It seems like this might happen if verify peer isn't set */
5521 if (!cert)
5522 return ok;
5523
5524 alt_names = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
5525 if (alt_names) {
5526 for (i = 0; !ok && i < sk_GENERAL_NAME_num(alt_names); i++) {
5527 GENERAL_NAME *name = sk_GENERAL_NAME_value(alt_names, i);
5528 if (name->type == GEN_DNS) {
Willy Tarreau9a1ab082019-05-09 13:26:41 +02005529#if HA_OPENSSL_VERSION_NUMBER < 0x00907000L
Emeric Bruna33410c2013-09-17 15:47:48 +02005530 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.ia5) >= 0) {
5531#else
Evan Broderbe554312013-06-27 00:05:25 -07005532 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
Emeric Bruna33410c2013-09-17 15:47:48 +02005533#endif
Evan Broderbe554312013-06-27 00:05:25 -07005534 ok = ssl_sock_srv_hostcheck(str, servername);
5535 OPENSSL_free(str);
5536 }
5537 }
5538 }
Emeric Brun4ad50a42013-09-17 15:19:54 +02005539 sk_GENERAL_NAME_pop_free(alt_names, GENERAL_NAME_free);
Evan Broderbe554312013-06-27 00:05:25 -07005540 }
5541
5542 cert_subject = X509_get_subject_name(cert);
5543 i = -1;
5544 while (!ok && (i = X509_NAME_get_index_by_NID(cert_subject, NID_commonName, i)) != -1) {
5545 X509_NAME_ENTRY *entry = X509_NAME_get_entry(cert_subject, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005546 ASN1_STRING *value;
5547 value = X509_NAME_ENTRY_get_data(entry);
5548 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
Evan Broderbe554312013-06-27 00:05:25 -07005549 ok = ssl_sock_srv_hostcheck(str, servername);
5550 OPENSSL_free(str);
5551 }
5552 }
5553
Willy Tarreau71d058c2017-07-26 20:09:56 +02005554 /* report the mismatch and indicate if SNI was used or not */
5555 if (!ok && !conn->err_code)
5556 conn->err_code = sni ? CO_ER_SSL_MISMATCH_SNI : CO_ER_SSL_MISMATCH;
Evan Broderbe554312013-06-27 00:05:25 -07005557 return ok;
5558}
5559
Emeric Brun94324a42012-10-11 14:00:19 +02005560/* prepare ssl context from servers options. Returns an error count */
Willy Tarreau03209342016-12-22 17:08:28 +01005561int ssl_sock_prepare_srv_ctx(struct server *srv)
Emeric Brun94324a42012-10-11 14:00:19 +02005562{
Willy Tarreau03209342016-12-22 17:08:28 +01005563 struct proxy *curproxy = srv->proxy;
Emeric Brun94324a42012-10-11 14:00:19 +02005564 int cfgerr = 0;
Remi Gacogneaf5c3da2014-05-19 10:29:58 +02005565 long options =
Emeric Brun94324a42012-10-11 14:00:19 +02005566 SSL_OP_ALL | /* all known workarounds for bugs */
5567 SSL_OP_NO_SSLv2 |
5568 SSL_OP_NO_COMPRESSION;
Remi Gacogneaf5c3da2014-05-19 10:29:58 +02005569 long mode =
Emeric Brun94324a42012-10-11 14:00:19 +02005570 SSL_MODE_ENABLE_PARTIAL_WRITE |
5571 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
Willy Tarreau396a1862014-11-13 14:06:52 +01005572 SSL_MODE_RELEASE_BUFFERS |
5573 SSL_MODE_SMALL_BUFFERS;
Emeric Brun850efd52014-01-29 12:24:34 +01005574 int verify = SSL_VERIFY_NONE;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01005575 SSL_CTX *ctx = NULL;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005576 struct tls_version_filter *conf_ssl_methods = &srv->ssl_ctx.methods;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005577 int i, min, max, hole;
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005578 int flags = MC_SSL_O_ALL;
Emeric Brun94324a42012-10-11 14:00:19 +02005579
Thierry Fournier383085f2013-01-24 14:15:43 +01005580 /* Make sure openssl opens /dev/urandom before the chroot */
5581 if (!ssl_initialize_random()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005582 ha_alert("OpenSSL random data generator initialization failed.\n");
Thierry Fournier383085f2013-01-24 14:15:43 +01005583 cfgerr++;
5584 }
5585
Willy Tarreaufce03112015-01-15 21:32:40 +01005586 /* Automatic memory computations need to know we use SSL there */
5587 global.ssl_used_backend = 1;
5588
5589 /* Initiate SSL context for current server */
Emeric Brun821bb9b2017-06-15 16:37:39 +02005590 if (!srv->ssl_ctx.reused_sess) {
Olivier Houcharde6060c52017-11-16 17:42:52 +01005591 if ((srv->ssl_ctx.reused_sess = calloc(1, global.nbthread*sizeof(*srv->ssl_ctx.reused_sess))) == NULL) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005592 ha_alert("Proxy '%s', server '%s' [%s:%d] out of memory.\n",
5593 curproxy->id, srv->id,
5594 srv->conf.file, srv->conf.line);
Emeric Brun821bb9b2017-06-15 16:37:39 +02005595 cfgerr++;
5596 return cfgerr;
5597 }
5598 }
Emeric Brun94324a42012-10-11 14:00:19 +02005599 if (srv->use_ssl)
5600 srv->xprt = &ssl_sock;
5601 if (srv->check.use_ssl)
Cyril Bonté9ce13112014-11-15 22:41:27 +01005602 srv->check.xprt = &ssl_sock;
Emeric Brun94324a42012-10-11 14:00:19 +02005603
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005604 ctx = SSL_CTX_new(SSLv23_client_method());
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01005605 if (!ctx) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005606 ha_alert("config : %s '%s', server '%s': unable to allocate ssl context.\n",
5607 proxy_type_str(curproxy), curproxy->id,
5608 srv->id);
Emeric Brun94324a42012-10-11 14:00:19 +02005609 cfgerr++;
5610 return cfgerr;
5611 }
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005612
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005613 if (conf_ssl_methods->flags && (conf_ssl_methods->min || conf_ssl_methods->max))
Christopher Faulet767a84b2017-11-24 16:50:31 +01005614 ha_warning("config : %s '%s': no-sslv3/no-tlsv1x are ignored for server '%s'. "
5615 "Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
5616 proxy_type_str(curproxy), curproxy->id, srv->id);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005617 else
5618 flags = conf_ssl_methods->flags;
5619
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005620 /* Real min and max should be determinate with configuration and openssl's capabilities */
5621 if (conf_ssl_methods->min)
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005622 flags |= (methodVersions[conf_ssl_methods->min].flag - 1);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005623 if (conf_ssl_methods->max)
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005624 flags |= ~((methodVersions[conf_ssl_methods->max].flag << 1) - 1);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005625
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02005626 /* find min, max and holes */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005627 min = max = CONF_TLSV_NONE;
5628 hole = 0;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005629 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005630 /* version is in openssl && version not disable in configuration */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005631 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005632 if (min) {
5633 if (hole) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005634 ha_warning("config : %s '%s': SSL/TLS versions range not contiguous for server '%s'. "
5635 "Hole find for %s. Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
5636 proxy_type_str(curproxy), curproxy->id, srv->id,
5637 methodVersions[hole].name);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005638 hole = 0;
5639 }
5640 max = i;
5641 }
5642 else {
5643 min = max = i;
5644 }
5645 }
5646 else {
5647 if (min)
5648 hole = i;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005649 }
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005650 if (!min) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005651 ha_alert("config : %s '%s': all SSL/TLS versions are disabled for server '%s'.\n",
5652 proxy_type_str(curproxy), curproxy->id, srv->id);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005653 cfgerr += 1;
5654 }
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005655
Willy Tarreau9a1ab082019-05-09 13:26:41 +02005656#if (HA_OPENSSL_VERSION_NUMBER < 0x1010000fL)
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005657 /* Keep force-xxx implementation as it is in older haproxy. It's a
Joseph Herlant017b3da2018-11-15 09:07:59 -08005658 precautionary measure to avoid any surprise with older openssl version. */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005659 if (min == max)
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02005660 methodVersions[min].ctx_set_version(ctx, SET_CLIENT);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005661 else
5662 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
5663 if (flags & methodVersions[i].flag)
5664 options |= methodVersions[i].option;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005665#else /* openssl >= 1.1.0 */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02005666 /* set the max_version is required to cap TLS version or activate new TLS (v1.3) */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02005667 methodVersions[min].ctx_set_version(ctx, SET_MIN);
5668 methodVersions[max].ctx_set_version(ctx, SET_MAX);
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02005669#endif
5670
5671 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLS_TICKETS)
5672 options |= SSL_OP_NO_TICKET;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01005673 SSL_CTX_set_options(ctx, options);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005674
Willy Tarreau5db847a2019-05-09 14:13:35 +02005675#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005676 if (global_ssl.async)
5677 mode |= SSL_MODE_ASYNC;
5678#endif
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01005679 SSL_CTX_set_mode(ctx, mode);
5680 srv->ssl_ctx.ctx = ctx;
5681
Emeric Bruna7aa3092012-10-26 12:58:00 +02005682 if (srv->ssl_ctx.client_crt) {
5683 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 +01005684 ha_alert("config : %s '%s', server '%s': unable to load SSL private key from PEM file '%s'.\n",
5685 proxy_type_str(curproxy), curproxy->id,
5686 srv->id, srv->ssl_ctx.client_crt);
Emeric Bruna7aa3092012-10-26 12:58:00 +02005687 cfgerr++;
5688 }
5689 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 +01005690 ha_alert("config : %s '%s', server '%s': unable to load ssl certificate from PEM file '%s'.\n",
5691 proxy_type_str(curproxy), curproxy->id,
5692 srv->id, srv->ssl_ctx.client_crt);
Emeric Bruna7aa3092012-10-26 12:58:00 +02005693 cfgerr++;
5694 }
5695 else if (SSL_CTX_check_private_key(srv->ssl_ctx.ctx) <= 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005696 ha_alert("config : %s '%s', server '%s': inconsistencies between private key and certificate loaded from PEM file '%s'.\n",
5697 proxy_type_str(curproxy), curproxy->id,
5698 srv->id, srv->ssl_ctx.client_crt);
Emeric Bruna7aa3092012-10-26 12:58:00 +02005699 cfgerr++;
5700 }
5701 }
Emeric Brun94324a42012-10-11 14:00:19 +02005702
Emeric Brun850efd52014-01-29 12:24:34 +01005703 if (global.ssl_server_verify == SSL_SERVER_VERIFY_REQUIRED)
5704 verify = SSL_VERIFY_PEER;
Emeric Brun850efd52014-01-29 12:24:34 +01005705 switch (srv->ssl_ctx.verify) {
5706 case SSL_SOCK_VERIFY_NONE:
5707 verify = SSL_VERIFY_NONE;
5708 break;
5709 case SSL_SOCK_VERIFY_REQUIRED:
5710 verify = SSL_VERIFY_PEER;
5711 break;
5712 }
Evan Broderbe554312013-06-27 00:05:25 -07005713 SSL_CTX_set_verify(srv->ssl_ctx.ctx,
Emeric Brun850efd52014-01-29 12:24:34 +01005714 verify,
Willy Tarreau2ab88672017-07-05 18:23:03 +02005715 (srv->ssl_ctx.verify_host || (verify & SSL_VERIFY_PEER)) ? ssl_sock_srv_verifycbk : NULL);
Emeric Brun850efd52014-01-29 12:24:34 +01005716 if (verify & SSL_VERIFY_PEER) {
Emeric Brunef42d922012-10-11 16:11:36 +02005717 if (srv->ssl_ctx.ca_file) {
Emmanuel Hocdetd4f9a602019-10-24 11:32:47 +02005718 /* set CAfile to verify */
5719 if (!ssl_set_verify_locations_file(srv->ssl_ctx.ctx, srv->ssl_ctx.ca_file)) {
5720 ha_alert("Proxy '%s', server '%s' [%s:%d] unable to set CA file '%s'.\n",
Christopher Faulet767a84b2017-11-24 16:50:31 +01005721 curproxy->id, srv->id,
5722 srv->conf.file, srv->conf.line, srv->ssl_ctx.ca_file);
Emeric Brunef42d922012-10-11 16:11:36 +02005723 cfgerr++;
5724 }
5725 }
Emeric Brun850efd52014-01-29 12:24:34 +01005726 else {
5727 if (global.ssl_server_verify == SSL_SERVER_VERIFY_REQUIRED)
Christopher Faulet767a84b2017-11-24 16:50:31 +01005728 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",
5729 curproxy->id, srv->id,
5730 srv->conf.file, srv->conf.line);
Emeric Brun850efd52014-01-29 12:24:34 +01005731 else
Christopher Faulet767a84b2017-11-24 16:50:31 +01005732 ha_alert("Proxy '%s', server '%s' [%s:%d] verify is enabled but no CA file specified.\n",
5733 curproxy->id, srv->id,
5734 srv->conf.file, srv->conf.line);
Emeric Brun850efd52014-01-29 12:24:34 +01005735 cfgerr++;
5736 }
Emeric Brunef42d922012-10-11 16:11:36 +02005737#ifdef X509_V_FLAG_CRL_CHECK
5738 if (srv->ssl_ctx.crl_file) {
5739 X509_STORE *store = SSL_CTX_get_cert_store(srv->ssl_ctx.ctx);
5740
Emmanuel Hocdetb270e812019-11-21 19:09:31 +01005741 if (!ssl_set_cert_crl_file(store, srv->ssl_ctx.crl_file)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005742 ha_alert("Proxy '%s', server '%s' [%s:%d] unable to configure CRL file '%s'.\n",
5743 curproxy->id, srv->id,
5744 srv->conf.file, srv->conf.line, srv->ssl_ctx.crl_file);
Emeric Brunef42d922012-10-11 16:11:36 +02005745 cfgerr++;
5746 }
5747 else {
5748 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
5749 }
5750 }
5751#endif
5752 }
5753
Olivier Houchardbd84ac82017-11-03 13:43:35 +01005754 SSL_CTX_set_session_cache_mode(srv->ssl_ctx.ctx, SSL_SESS_CACHE_CLIENT |
5755 SSL_SESS_CACHE_NO_INTERNAL_STORE);
5756 SSL_CTX_sess_set_new_cb(srv->ssl_ctx.ctx, ssl_sess_new_srv_cb);
Emeric Brun94324a42012-10-11 14:00:19 +02005757 if (srv->ssl_ctx.ciphers &&
5758 !SSL_CTX_set_cipher_list(srv->ssl_ctx.ctx, srv->ssl_ctx.ciphers)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005759 ha_alert("Proxy '%s', server '%s' [%s:%d] : unable to set SSL cipher list to '%s'.\n",
5760 curproxy->id, srv->id,
5761 srv->conf.file, srv->conf.line, srv->ssl_ctx.ciphers);
Emeric Brun94324a42012-10-11 14:00:19 +02005762 cfgerr++;
5763 }
Dirkjan Bussink415150f2018-09-14 11:14:21 +02005764
Emmanuel Hocdet839af572019-05-14 16:27:35 +02005765#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02005766 if (srv->ssl_ctx.ciphersuites &&
Pierre Cheynierbc34cd12019-03-21 16:15:47 +00005767 !SSL_CTX_set_ciphersuites(srv->ssl_ctx.ctx, srv->ssl_ctx.ciphersuites)) {
Dirkjan Bussink415150f2018-09-14 11:14:21 +02005768 ha_alert("Proxy '%s', server '%s' [%s:%d] : unable to set TLS 1.3 cipher suites to '%s'.\n",
5769 curproxy->id, srv->id,
5770 srv->conf.file, srv->conf.line, srv->ssl_ctx.ciphersuites);
5771 cfgerr++;
5772 }
5773#endif
Olivier Houchardc7566002018-11-20 23:33:50 +01005774#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
5775 if (srv->ssl_ctx.npn_str)
5776 SSL_CTX_set_next_proto_select_cb(ctx, ssl_sock_srv_select_protos, srv);
5777#endif
5778#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
5779 if (srv->ssl_ctx.alpn_str)
5780 SSL_CTX_set_alpn_protos(ctx, (unsigned char *)srv->ssl_ctx.alpn_str, srv->ssl_ctx.alpn_len);
5781#endif
5782
Emeric Brun94324a42012-10-11 14:00:19 +02005783
5784 return cfgerr;
5785}
5786
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005787/* Walks down the two trees in bind_conf and prepares all certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +02005788 * be NULL, in which case nothing is done. Returns the number of errors
5789 * encountered.
5790 */
Willy Tarreau03209342016-12-22 17:08:28 +01005791int ssl_sock_prepare_all_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02005792{
5793 struct ebmb_node *node;
5794 struct sni_ctx *sni;
5795 int err = 0;
William Lallemand8b453912019-11-21 15:48:10 +01005796 int errcode = 0;
5797 char *errmsg = NULL;
Emeric Brunfc0421f2012-09-07 17:30:07 +02005798
Willy Tarreaufce03112015-01-15 21:32:40 +01005799 /* Automatic memory computations need to know we use SSL there */
5800 global.ssl_used_frontend = 1;
5801
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01005802 /* Make sure openssl opens /dev/urandom before the chroot */
5803 if (!ssl_initialize_random()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005804 ha_alert("OpenSSL random data generator initialization failed.\n");
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01005805 err++;
5806 }
5807 /* Create initial_ctx used to start the ssl connection before do switchctx */
5808 if (!bind_conf->initial_ctx) {
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005809 err += ssl_sock_initial_ctx(bind_conf);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01005810 /* It should not be necessary to call this function, but it's
5811 necessary first to check and move all initialisation related
5812 to initial_ctx in ssl_sock_initial_ctx. */
William Lallemand8b453912019-11-21 15:48:10 +01005813 errcode |= ssl_sock_prepare_ctx(bind_conf, NULL, bind_conf->initial_ctx, &errmsg);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01005814 }
Emeric Brun0bed9942014-10-30 19:25:24 +01005815 if (bind_conf->default_ctx)
William Lallemand8b453912019-11-21 15:48:10 +01005816 errcode |= ssl_sock_prepare_ctx(bind_conf, bind_conf->default_ssl_conf, bind_conf->default_ctx, &errmsg);
Emeric Brun0bed9942014-10-30 19:25:24 +01005817
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005818 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02005819 while (node) {
5820 sni = ebmb_entry(node, struct sni_ctx, name);
Emeric Brun0bed9942014-10-30 19:25:24 +01005821 if (!sni->order && sni->ctx != bind_conf->default_ctx)
5822 /* only initialize the CTX on its first occurrence and
5823 if it is not the default_ctx */
William Lallemand8b453912019-11-21 15:48:10 +01005824 errcode |= ssl_sock_prepare_ctx(bind_conf, sni->conf, sni->ctx, &errmsg);
Emeric Brunfc0421f2012-09-07 17:30:07 +02005825 node = ebmb_next(node);
5826 }
5827
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005828 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02005829 while (node) {
5830 sni = ebmb_entry(node, struct sni_ctx, name);
William Lallemand8b453912019-11-21 15:48:10 +01005831 if (!sni->order && sni->ctx != bind_conf->default_ctx) {
Emeric Brun0bed9942014-10-30 19:25:24 +01005832 /* only initialize the CTX on its first occurrence and
5833 if it is not the default_ctx */
William Lallemand8b453912019-11-21 15:48:10 +01005834 errcode |= ssl_sock_prepare_ctx(bind_conf, sni->conf, sni->ctx, &errmsg);
5835 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02005836 node = ebmb_next(node);
5837 }
William Lallemand8b453912019-11-21 15:48:10 +01005838
5839 if (errcode & ERR_WARN) {
Tim Duesterhusc0e820c2019-11-23 23:52:30 +01005840 ha_warning("%s", errmsg);
William Lallemand8b453912019-11-21 15:48:10 +01005841 } else if (errcode & ERR_CODE) {
Tim Duesterhusc0e820c2019-11-23 23:52:30 +01005842 ha_alert("%s", errmsg);
William Lallemand8b453912019-11-21 15:48:10 +01005843 err++;
5844 }
5845
5846 free(errmsg);
Emeric Brunfc0421f2012-09-07 17:30:07 +02005847 return err;
5848}
5849
Willy Tarreau55d37912016-12-21 23:38:39 +01005850/* Prepares all the contexts for a bind_conf and allocates the shared SSL
5851 * context if needed. Returns < 0 on error, 0 on success. The warnings and
5852 * alerts are directly emitted since the rest of the stack does it below.
5853 */
5854int ssl_sock_prepare_bind_conf(struct bind_conf *bind_conf)
5855{
5856 struct proxy *px = bind_conf->frontend;
5857 int alloc_ctx;
5858 int err;
5859
5860 if (!bind_conf->is_ssl) {
5861 if (bind_conf->default_ctx) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005862 ha_warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
5863 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreau55d37912016-12-21 23:38:39 +01005864 }
5865 return 0;
5866 }
5867 if (!bind_conf->default_ctx) {
Emmanuel Hocdetaa0d6372017-08-09 11:24:25 +02005868 if (bind_conf->strict_sni && !bind_conf->generate_certs) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005869 ha_warning("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d], ssl connections will fail (use 'crt').\n",
5870 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetaa0d6372017-08-09 11:24:25 +02005871 }
5872 else {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005873 ha_alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
5874 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetaa0d6372017-08-09 11:24:25 +02005875 return -1;
5876 }
Willy Tarreau55d37912016-12-21 23:38:39 +01005877 }
William Lallemandc61c0b32017-12-04 18:46:39 +01005878 if (!ssl_shctx && global.tune.sslcachesize) {
William Lallemandc3cd35f2017-11-28 11:04:43 +01005879 alloc_ctx = shctx_init(&ssl_shctx, global.tune.sslcachesize,
Frédéric Lécailleb7838af2018-10-22 16:21:39 +02005880 sizeof(struct sh_ssl_sess_hdr) + SHSESS_BLOCK_MIN_SIZE, -1,
William Lallemandc3cd35f2017-11-28 11:04:43 +01005881 sizeof(*sh_ssl_sess_tree),
5882 ((global.nbthread > 1) || (!global_ssl.private_cache && (global.nbproc > 1))) ? 1 : 0);
Frédéric Lécaille4c8aa112018-10-25 20:22:46 +02005883 if (alloc_ctx <= 0) {
William Lallemandc3cd35f2017-11-28 11:04:43 +01005884 if (alloc_ctx == SHCTX_E_INIT_LOCK)
5885 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");
5886 else
5887 ha_alert("Unable to allocate SSL session cache.\n");
5888 return -1;
5889 }
5890 /* free block callback */
5891 ssl_shctx->free_block = sh_ssl_sess_free_blocks;
5892 /* init the root tree within the extra space */
5893 sh_ssl_sess_tree = (void *)ssl_shctx + sizeof(struct shared_context);
5894 *sh_ssl_sess_tree = EB_ROOT_UNIQUE;
Willy Tarreau55d37912016-12-21 23:38:39 +01005895 }
Willy Tarreau55d37912016-12-21 23:38:39 +01005896 err = 0;
5897 /* initialize all certificate contexts */
5898 err += ssl_sock_prepare_all_ctx(bind_conf);
5899
5900 /* initialize CA variables if the certificates generation is enabled */
5901 err += ssl_sock_load_ca(bind_conf);
5902
5903 return -err;
5904}
Christopher Faulet77fe80c2015-07-29 13:02:40 +02005905
5906/* release ssl context allocated for servers. */
5907void ssl_sock_free_srv_ctx(struct server *srv)
5908{
Olivier Houchardc7566002018-11-20 23:33:50 +01005909#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
5910 if (srv->ssl_ctx.alpn_str)
5911 free(srv->ssl_ctx.alpn_str);
5912#endif
Lukas Tribusda95fd92018-11-25 13:21:27 +01005913#ifdef OPENSSL_NPN_NEGOTIATED
Olivier Houchardc7566002018-11-20 23:33:50 +01005914 if (srv->ssl_ctx.npn_str)
5915 free(srv->ssl_ctx.npn_str);
Lukas Tribus7706b852018-11-26 22:57:17 +01005916#endif
Christopher Faulet77fe80c2015-07-29 13:02:40 +02005917 if (srv->ssl_ctx.ctx)
5918 SSL_CTX_free(srv->ssl_ctx.ctx);
5919}
5920
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005921/* Walks down the two trees in bind_conf and frees all the certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +02005922 * be NULL, in which case nothing is done. The default_ctx is nullified too.
5923 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005924void ssl_sock_free_all_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02005925{
5926 struct ebmb_node *node, *back;
5927 struct sni_ctx *sni;
5928
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005929 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02005930 while (node) {
5931 sni = ebmb_entry(node, struct sni_ctx, name);
5932 back = ebmb_next(node);
5933 ebmb_delete(node);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005934 if (!sni->order) { /* only free the CTX on its first occurrence */
Emeric Brunfc0421f2012-09-07 17:30:07 +02005935 SSL_CTX_free(sni->ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005936 ssl_sock_free_ssl_conf(sni->conf);
5937 free(sni->conf);
5938 sni->conf = NULL;
5939 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02005940 free(sni);
5941 node = back;
5942 }
5943
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005944 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02005945 while (node) {
5946 sni = ebmb_entry(node, struct sni_ctx, name);
5947 back = ebmb_next(node);
5948 ebmb_delete(node);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005949 if (!sni->order) { /* only free the CTX on its first occurrence */
Emeric Brunfc0421f2012-09-07 17:30:07 +02005950 SSL_CTX_free(sni->ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005951 ssl_sock_free_ssl_conf(sni->conf);
5952 free(sni->conf);
5953 sni->conf = NULL;
5954 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02005955 free(sni);
5956 node = back;
5957 }
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01005958 SSL_CTX_free(bind_conf->initial_ctx);
5959 bind_conf->initial_ctx = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005960 bind_conf->default_ctx = NULL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005961 bind_conf->default_ssl_conf = NULL;
Emeric Brune1f38db2012-09-03 20:36:47 +02005962}
5963
Willy Tarreau795cdab2016-12-22 17:30:54 +01005964/* Destroys all the contexts for a bind_conf. This is used during deinit(). */
5965void ssl_sock_destroy_bind_conf(struct bind_conf *bind_conf)
5966{
5967 ssl_sock_free_ca(bind_conf);
5968 ssl_sock_free_all_ctx(bind_conf);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005969 ssl_sock_free_ssl_conf(&bind_conf->ssl_conf);
Willy Tarreau795cdab2016-12-22 17:30:54 +01005970 free(bind_conf->ca_sign_file);
5971 free(bind_conf->ca_sign_pass);
Willy Tarreau17b4aa12018-07-17 10:05:32 +02005972 if (bind_conf->keys_ref && !--bind_conf->keys_ref->refcount) {
Willy Tarreau795cdab2016-12-22 17:30:54 +01005973 free(bind_conf->keys_ref->filename);
5974 free(bind_conf->keys_ref->tlskeys);
5975 LIST_DEL(&bind_conf->keys_ref->list);
5976 free(bind_conf->keys_ref);
5977 }
5978 bind_conf->keys_ref = NULL;
Willy Tarreau795cdab2016-12-22 17:30:54 +01005979 bind_conf->ca_sign_pass = NULL;
5980 bind_conf->ca_sign_file = NULL;
Willy Tarreau795cdab2016-12-22 17:30:54 +01005981}
5982
Christopher Faulet31af49d2015-06-09 17:29:50 +02005983/* Load CA cert file and private key used to generate certificates */
5984int
Willy Tarreau03209342016-12-22 17:08:28 +01005985ssl_sock_load_ca(struct bind_conf *bind_conf)
Christopher Faulet31af49d2015-06-09 17:29:50 +02005986{
Willy Tarreau03209342016-12-22 17:08:28 +01005987 struct proxy *px = bind_conf->frontend;
Christopher Faulet31af49d2015-06-09 17:29:50 +02005988 FILE *fp;
5989 X509 *cacert = NULL;
5990 EVP_PKEY *capkey = NULL;
5991 int err = 0;
5992
Christopher Fauletf8bb0ce2017-09-15 09:52:49 +02005993 if (!bind_conf->generate_certs)
Christopher Faulet31af49d2015-06-09 17:29:50 +02005994 return err;
5995
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005996#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Emeric Brun821bb9b2017-06-15 16:37:39 +02005997 if (global_ssl.ctx_cache) {
Willy Tarreauef934602016-12-22 23:12:01 +01005998 ssl_ctx_lru_tree = lru64_new(global_ssl.ctx_cache);
Emeric Brun821bb9b2017-06-15 16:37:39 +02005999 }
Christopher Fauletd2cab922015-07-28 16:03:47 +02006000 ssl_ctx_lru_seed = (unsigned int)time(NULL);
Emeric Brun821bb9b2017-06-15 16:37:39 +02006001 ssl_ctx_serial = now_ms;
Willy Tarreaua84c2672015-10-09 12:10:13 +02006002#endif
Christopher Fauletd2cab922015-07-28 16:03:47 +02006003
Christopher Faulet31af49d2015-06-09 17:29:50 +02006004 if (!bind_conf->ca_sign_file) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01006005 ha_alert("Proxy '%s': cannot enable certificate generation, "
6006 "no CA certificate File configured at [%s:%d].\n",
6007 px->id, bind_conf->file, bind_conf->line);
Christopher Faulet31af49d2015-06-09 17:29:50 +02006008 goto load_error;
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02006009 }
Christopher Faulet31af49d2015-06-09 17:29:50 +02006010
6011 /* read in the CA certificate */
6012 if (!(fp = fopen(bind_conf->ca_sign_file, "r"))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01006013 ha_alert("Proxy '%s': Failed to read CA certificate file '%s' at [%s:%d].\n",
6014 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Faulet31af49d2015-06-09 17:29:50 +02006015 goto load_error;
6016 }
6017 if (!(cacert = PEM_read_X509(fp, NULL, NULL, NULL))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01006018 ha_alert("Proxy '%s': Failed to read CA certificate file '%s' at [%s:%d].\n",
6019 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02006020 goto read_error;
Christopher Faulet31af49d2015-06-09 17:29:50 +02006021 }
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02006022 rewind(fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02006023 if (!(capkey = PEM_read_PrivateKey(fp, NULL, NULL, bind_conf->ca_sign_pass))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01006024 ha_alert("Proxy '%s': Failed to read CA private key file '%s' at [%s:%d].\n",
6025 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02006026 goto read_error;
Christopher Faulet31af49d2015-06-09 17:29:50 +02006027 }
Christopher Faulet31af49d2015-06-09 17:29:50 +02006028
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02006029 fclose (fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02006030 bind_conf->ca_sign_cert = cacert;
6031 bind_conf->ca_sign_pkey = capkey;
6032 return err;
6033
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02006034 read_error:
6035 fclose (fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02006036 if (capkey) EVP_PKEY_free(capkey);
6037 if (cacert) X509_free(cacert);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02006038 load_error:
6039 bind_conf->generate_certs = 0;
6040 err++;
Christopher Faulet31af49d2015-06-09 17:29:50 +02006041 return err;
6042}
6043
6044/* Release CA cert and private key used to generate certificated */
6045void
6046ssl_sock_free_ca(struct bind_conf *bind_conf)
6047{
Christopher Faulet31af49d2015-06-09 17:29:50 +02006048 if (bind_conf->ca_sign_pkey)
6049 EVP_PKEY_free(bind_conf->ca_sign_pkey);
6050 if (bind_conf->ca_sign_cert)
6051 X509_free(bind_conf->ca_sign_cert);
Willy Tarreau94ff03a2016-12-22 17:57:46 +01006052 bind_conf->ca_sign_pkey = NULL;
6053 bind_conf->ca_sign_cert = NULL;
Christopher Faulet31af49d2015-06-09 17:29:50 +02006054}
6055
Emeric Brun46591952012-05-18 15:47:34 +02006056/*
6057 * This function is called if SSL * context is not yet allocated. The function
6058 * is designed to be called before any other data-layer operation and sets the
6059 * handshake flag on the connection. It is safe to call it multiple times.
6060 * It returns 0 on success and -1 in error case.
6061 */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006062static int ssl_sock_init(struct connection *conn, void **xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02006063{
Olivier Houchard66ab4982019-02-26 18:37:15 +01006064 struct ssl_sock_ctx *ctx;
Emeric Brun46591952012-05-18 15:47:34 +02006065 /* already initialized */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006066 if (*xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02006067 return 0;
6068
Willy Tarreau3c728722014-01-23 13:50:42 +01006069 if (!conn_ctrl_ready(conn))
Willy Tarreauf79c8172013-10-21 16:30:56 +02006070 return 0;
6071
Olivier Houchard66ab4982019-02-26 18:37:15 +01006072 ctx = pool_alloc(ssl_sock_ctx_pool);
6073 if (!ctx) {
6074 conn->err_code = CO_ER_SSL_NO_MEM;
6075 return -1;
6076 }
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02006077 ctx->wait_event.tasklet = tasklet_new();
6078 if (!ctx->wait_event.tasklet) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02006079 conn->err_code = CO_ER_SSL_NO_MEM;
6080 pool_free(ssl_sock_ctx_pool, ctx);
6081 return -1;
6082 }
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02006083 ctx->wait_event.tasklet->process = ssl_sock_io_cb;
6084 ctx->wait_event.tasklet->context = ctx;
Olivier Houchardea8dd942019-05-20 14:02:16 +02006085 ctx->wait_event.events = 0;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006086 ctx->sent_early_data = 0;
Olivier Houchard54907bb2019-12-19 15:02:39 +01006087 ctx->early_buf = BUF_NULL;
Olivier Houcharda8955d52019-04-07 22:00:38 +02006088 ctx->conn = conn;
Willy Tarreau113d52b2020-01-10 09:20:26 +01006089 ctx->subs = NULL;
Emeric Brun5762a0d2019-09-06 15:36:02 +02006090 ctx->xprt_st = 0;
6091 ctx->xprt_ctx = NULL;
Olivier Houcharda8955d52019-04-07 22:00:38 +02006092
6093 /* Only work with sockets for now, this should be adapted when we'll
6094 * add QUIC support.
6095 */
6096 ctx->xprt = xprt_get(XPRT_RAW);
Olivier Houchard19afb272019-05-23 18:24:07 +02006097 if (ctx->xprt->init) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02006098 if (ctx->xprt->init(conn, &ctx->xprt_ctx) != 0)
6099 goto err;
Olivier Houchard19afb272019-05-23 18:24:07 +02006100 }
Olivier Houchard66ab4982019-02-26 18:37:15 +01006101
Willy Tarreau20879a02012-12-03 16:32:10 +01006102 if (global.maxsslconn && sslconns >= global.maxsslconn) {
6103 conn->err_code = CO_ER_SSL_TOO_MANY;
Olivier Houchardea8dd942019-05-20 14:02:16 +02006104 goto err;
Willy Tarreau20879a02012-12-03 16:32:10 +01006105 }
Willy Tarreau403edff2012-09-06 11:58:37 +02006106
Emeric Brun46591952012-05-18 15:47:34 +02006107 /* If it is in client mode initiate SSL session
6108 in connect state otherwise accept state */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01006109 if (objt_server(conn->target)) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01006110 int may_retry = 1;
6111
6112 retry_connect:
Emeric Brun46591952012-05-18 15:47:34 +02006113 /* Alloc a new SSL session ctx */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006114 ctx->ssl = SSL_new(__objt_server(conn->target)->ssl_ctx.ctx);
6115 if (!ctx->ssl) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01006116 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01006117 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01006118 goto retry_connect;
6119 }
Willy Tarreau20879a02012-12-03 16:32:10 +01006120 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006121 goto err;
Willy Tarreau20879a02012-12-03 16:32:10 +01006122 }
Olivier Houcharda8955d52019-04-07 22:00:38 +02006123 ctx->bio = BIO_new(ha_meth);
6124 if (!ctx->bio) {
Olivier Houchardefe5e8e2020-01-24 15:17:38 +01006125 SSL_free(ctx->ssl);
6126 ctx->ssl = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01006127 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01006128 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01006129 goto retry_connect;
6130 }
Emeric Brun55476152014-11-12 17:35:37 +01006131 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006132 goto err;
Emeric Brun55476152014-11-12 17:35:37 +01006133 }
Olivier Houcharda8955d52019-04-07 22:00:38 +02006134 BIO_set_data(ctx->bio, ctx);
Olivier Houcharda8955d52019-04-07 22:00:38 +02006135 SSL_set_bio(ctx->ssl, ctx->bio, ctx->bio);
Emeric Brun46591952012-05-18 15:47:34 +02006136
Evan Broderbe554312013-06-27 00:05:25 -07006137 /* set connection pointer */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006138 if (!SSL_set_ex_data(ctx->ssl, ssl_app_data_index, conn)) {
6139 SSL_free(ctx->ssl);
6140 ctx->ssl = NULL;
Emeric Brun55476152014-11-12 17:35:37 +01006141 conn->xprt_ctx = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01006142 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01006143 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01006144 goto retry_connect;
6145 }
Emeric Brun55476152014-11-12 17:35:37 +01006146 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006147 goto err;
Emeric Brun55476152014-11-12 17:35:37 +01006148 }
6149
Olivier Houchard66ab4982019-02-26 18:37:15 +01006150 SSL_set_connect_state(ctx->ssl);
Willy Tarreau07d94e42018-09-20 10:57:52 +02006151 if (__objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr) {
6152 const unsigned char *ptr = __objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr;
6153 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 +01006154 if (sess && !SSL_set_session(ctx->ssl, sess)) {
Olivier Houcharde6060c52017-11-16 17:42:52 +01006155 SSL_SESSION_free(sess);
Willy Tarreau07d94e42018-09-20 10:57:52 +02006156 free(__objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr);
6157 __objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr = NULL;
Olivier Houcharde6060c52017-11-16 17:42:52 +01006158 } else if (sess) {
6159 SSL_SESSION_free(sess);
Emeric Brun55476152014-11-12 17:35:37 +01006160 }
6161 }
Evan Broderbe554312013-06-27 00:05:25 -07006162
Emeric Brun46591952012-05-18 15:47:34 +02006163 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +02006164 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Willy Tarreau403edff2012-09-06 11:58:37 +02006165
Olivier Houchard2be5a4c2019-03-08 18:54:43 +01006166 _HA_ATOMIC_ADD(&sslconns, 1);
6167 _HA_ATOMIC_ADD(&totalsslconns, 1);
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006168 *xprt_ctx = ctx;
Olivier Houchardea8dd942019-05-20 14:02:16 +02006169 /* Start the handshake */
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02006170 tasklet_wakeup(ctx->wait_event.tasklet);
Emeric Brun46591952012-05-18 15:47:34 +02006171 return 0;
6172 }
Willy Tarreau3fdb3662012-11-12 00:42:33 +01006173 else if (objt_listener(conn->target)) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01006174 int may_retry = 1;
6175
6176 retry_accept:
Emeric Brun46591952012-05-18 15:47:34 +02006177 /* Alloc a new SSL session ctx */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006178 ctx->ssl = SSL_new(__objt_listener(conn->target)->bind_conf->initial_ctx);
6179 if (!ctx->ssl) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01006180 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01006181 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01006182 goto retry_accept;
6183 }
Willy Tarreau20879a02012-12-03 16:32:10 +01006184 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006185 goto err;
Willy Tarreau20879a02012-12-03 16:32:10 +01006186 }
Olivier Houcharda8955d52019-04-07 22:00:38 +02006187 ctx->bio = BIO_new(ha_meth);
6188 if (!ctx->bio) {
Olivier Houchardefe5e8e2020-01-24 15:17:38 +01006189 SSL_free(ctx->ssl);
6190 ctx->ssl = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01006191 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01006192 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01006193 goto retry_accept;
6194 }
Emeric Brun55476152014-11-12 17:35:37 +01006195 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006196 goto err;
Emeric Brun55476152014-11-12 17:35:37 +01006197 }
Olivier Houcharda8955d52019-04-07 22:00:38 +02006198 BIO_set_data(ctx->bio, ctx);
Olivier Houcharda8955d52019-04-07 22:00:38 +02006199 SSL_set_bio(ctx->ssl, ctx->bio, ctx->bio);
Emeric Brun46591952012-05-18 15:47:34 +02006200
Emeric Brune1f38db2012-09-03 20:36:47 +02006201 /* set connection pointer */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006202 if (!SSL_set_ex_data(ctx->ssl, ssl_app_data_index, conn)) {
6203 SSL_free(ctx->ssl);
6204 ctx->ssl = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01006205 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01006206 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01006207 goto retry_accept;
6208 }
Emeric Brun55476152014-11-12 17:35:37 +01006209 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006210 goto err;
Emeric Brun55476152014-11-12 17:35:37 +01006211 }
6212
Frédéric Lécaille3139c1b2020-01-24 14:56:18 +01006213#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
6214 if (__objt_listener(conn->target)->bind_conf->ssl_conf.early_data) {
6215 b_alloc(&ctx->early_buf);
6216 SSL_set_max_early_data(ctx->ssl,
6217 /* Only allow early data if we managed to allocate
6218 * a buffer.
6219 */
6220 (!b_is_null(&ctx->early_buf)) ?
6221 global.tune.bufsize - global.tune.maxrewrite : 0);
6222 }
6223#endif
6224
Olivier Houchard66ab4982019-02-26 18:37:15 +01006225 SSL_set_accept_state(ctx->ssl);
Emeric Brune1f38db2012-09-03 20:36:47 +02006226
Emeric Brun46591952012-05-18 15:47:34 +02006227 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +02006228 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Emmanuel Hocdetf967c312019-08-05 18:04:16 +02006229#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Olivier Houchardc2aae742017-09-22 18:26:28 +02006230 conn->flags |= CO_FL_EARLY_SSL_HS;
6231#endif
Willy Tarreau403edff2012-09-06 11:58:37 +02006232
Olivier Houchard2be5a4c2019-03-08 18:54:43 +01006233 _HA_ATOMIC_ADD(&sslconns, 1);
6234 _HA_ATOMIC_ADD(&totalsslconns, 1);
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006235 *xprt_ctx = ctx;
Olivier Houchardea8dd942019-05-20 14:02:16 +02006236 /* Start the handshake */
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02006237 tasklet_wakeup(ctx->wait_event.tasklet);
Emeric Brun46591952012-05-18 15:47:34 +02006238 return 0;
6239 }
6240 /* don't know how to handle such a target */
Willy Tarreau20879a02012-12-03 16:32:10 +01006241 conn->err_code = CO_ER_SSL_NO_TARGET;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006242err:
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02006243 if (ctx && ctx->wait_event.tasklet)
6244 tasklet_free(ctx->wait_event.tasklet);
Olivier Houchard66ab4982019-02-26 18:37:15 +01006245 pool_free(ssl_sock_ctx_pool, ctx);
Emeric Brun46591952012-05-18 15:47:34 +02006246 return -1;
6247}
6248
6249
6250/* This is the callback which is used when an SSL handshake is pending. It
6251 * updates the FD status if it wants some polling before being called again.
6252 * It returns 0 if it fails in a fatal way or needs to poll to go further,
6253 * otherwise it returns non-zero and removes itself from the connection's
6254 * flags (the bit is provided in <flag> by the caller).
6255 */
Olivier Houchard000694c2019-05-23 14:45:12 +02006256static int ssl_sock_handshake(struct connection *conn, unsigned int flag)
Emeric Brun46591952012-05-18 15:47:34 +02006257{
Olivier Houchard66ab4982019-02-26 18:37:15 +01006258 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
Emeric Brun46591952012-05-18 15:47:34 +02006259 int ret;
6260
Willy Tarreau3c728722014-01-23 13:50:42 +01006261 if (!conn_ctrl_ready(conn))
Willy Tarreauf79c8172013-10-21 16:30:56 +02006262 return 0;
6263
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02006264 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02006265 goto out_error;
6266
Willy Tarreau5db847a2019-05-09 14:13:35 +02006267#if HA_OPENSSL_VERSION_NUMBER >= 0x10101000L
Olivier Houchardc2aae742017-09-22 18:26:28 +02006268 /*
6269 * Check if we have early data. If we do, we have to read them
6270 * before SSL_do_handshake() is called, And there's no way to
6271 * detect early data, except to try to read them
6272 */
6273 if (conn->flags & CO_FL_EARLY_SSL_HS) {
Olivier Houchard54907bb2019-12-19 15:02:39 +01006274 size_t read_data = 0;
Olivier Houchardc2aae742017-09-22 18:26:28 +02006275
Olivier Houchard54907bb2019-12-19 15:02:39 +01006276 while (1) {
6277 ret = SSL_read_early_data(ctx->ssl,
6278 b_tail(&ctx->early_buf), b_room(&ctx->early_buf),
6279 &read_data);
6280 if (ret == SSL_READ_EARLY_DATA_ERROR)
6281 goto check_error;
6282 if (read_data > 0) {
6283 conn->flags |= CO_FL_EARLY_DATA;
6284 b_add(&ctx->early_buf, read_data);
6285 }
6286 if (ret == SSL_READ_EARLY_DATA_FINISH) {
6287 conn->flags &= ~CO_FL_EARLY_SSL_HS;
6288 if (!b_data(&ctx->early_buf))
6289 b_free(&ctx->early_buf);
6290 break;
6291 }
6292 }
Olivier Houchardc2aae742017-09-22 18:26:28 +02006293 }
6294#endif
Emeric Brun674b7432012-11-08 19:21:55 +01006295 /* If we use SSL_do_handshake to process a reneg initiated by
6296 * the remote peer, it sometimes returns SSL_ERROR_SSL.
6297 * Usually SSL_write and SSL_read are used and process implicitly
6298 * the reneg handshake.
6299 * Here we use SSL_peek as a workaround for reneg.
6300 */
Willy Tarreauc192b0a2020-01-23 09:11:58 +01006301 if (!(conn->flags & CO_FL_WAIT_L6_CONN) && SSL_renegotiate_pending(ctx->ssl)) {
Emeric Brun674b7432012-11-08 19:21:55 +01006302 char c;
6303
Olivier Houchard66ab4982019-02-26 18:37:15 +01006304 ret = SSL_peek(ctx->ssl, &c, 1);
Emeric Brun674b7432012-11-08 19:21:55 +01006305 if (ret <= 0) {
6306 /* handshake may have not been completed, let's find why */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006307 ret = SSL_get_error(ctx->ssl, ret);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006308
Emeric Brun674b7432012-11-08 19:21:55 +01006309 if (ret == SSL_ERROR_WANT_WRITE) {
6310 /* SSL handshake needs to write, L4 connection may not be ready */
Olivier Houchard03abf2d2019-05-28 10:12:02 +02006311 if (!(ctx->wait_event.events & SUB_RETRY_SEND))
Olivier Houchardea8dd942019-05-20 14:02:16 +02006312 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_SEND, &ctx->wait_event);
Emeric Brun674b7432012-11-08 19:21:55 +01006313 return 0;
6314 }
6315 else if (ret == SSL_ERROR_WANT_READ) {
6316 /* handshake may have been completed but we have
6317 * no more data to read.
6318 */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006319 if (!SSL_renegotiate_pending(ctx->ssl)) {
Emeric Brun674b7432012-11-08 19:21:55 +01006320 ret = 1;
6321 goto reneg_ok;
6322 }
6323 /* SSL handshake needs to read, L4 connection is ready */
Olivier Houchard03abf2d2019-05-28 10:12:02 +02006324 if (!(ctx->wait_event.events & SUB_RETRY_RECV))
Olivier Houchardea8dd942019-05-20 14:02:16 +02006325 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_RECV, &ctx->wait_event);
Emeric Brun674b7432012-11-08 19:21:55 +01006326 return 0;
6327 }
Willy Tarreau5db847a2019-05-09 14:13:35 +02006328#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006329 else if (ret == SSL_ERROR_WANT_ASYNC) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02006330 ssl_async_process_fds(ctx);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006331 return 0;
6332 }
6333#endif
Emeric Brun674b7432012-11-08 19:21:55 +01006334 else if (ret == SSL_ERROR_SYSCALL) {
6335 /* if errno is null, then connection was successfully established */
6336 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
6337 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Willy Tarreau20879a02012-12-03 16:32:10 +01006338 if (!conn->err_code) {
Lukas Tribus49799162019-07-08 14:29:15 +02006339#if defined(OPENSSL_IS_BORINGSSL) || defined(LIBRESSL_VERSION_NUMBER)
6340 /* do not handle empty handshakes in BoringSSL or LibreSSL */
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01006341 conn->err_code = CO_ER_SSL_HANDSHAKE;
6342#else
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006343 int empty_handshake;
Willy Tarreau5db847a2019-05-09 14:13:35 +02006344#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL)
Lukas Tribus49799162019-07-08 14:29:15 +02006345 /* use SSL_get_state() in OpenSSL >= 1.1.0; SSL_state() is broken */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006346 OSSL_HANDSHAKE_STATE state = SSL_get_state((SSL *)ctx->ssl);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006347 empty_handshake = state == TLS_ST_BEFORE;
6348#else
Lukas Tribus49799162019-07-08 14:29:15 +02006349 /* access packet_length directly in OpenSSL <= 1.0.2; SSL_state() is broken */
6350 empty_handshake = !ctx->ssl->packet_length;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006351#endif
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006352 if (empty_handshake) {
Emeric Brun29f037d2014-04-25 19:05:36 +02006353 if (!errno) {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006354 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emeric Brun29f037d2014-04-25 19:05:36 +02006355 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
6356 else
6357 conn->err_code = CO_ER_SSL_EMPTY;
6358 }
6359 else {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006360 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emeric Brun29f037d2014-04-25 19:05:36 +02006361 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
6362 else
6363 conn->err_code = CO_ER_SSL_ABORT;
6364 }
6365 }
6366 else {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006367 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emeric Brun29f037d2014-04-25 19:05:36 +02006368 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
Willy Tarreau20879a02012-12-03 16:32:10 +01006369 else
Emeric Brun29f037d2014-04-25 19:05:36 +02006370 conn->err_code = CO_ER_SSL_HANDSHAKE;
6371 }
Lukas Tribus49799162019-07-08 14:29:15 +02006372#endif /* BoringSSL or LibreSSL */
Willy Tarreau20879a02012-12-03 16:32:10 +01006373 }
Emeric Brun674b7432012-11-08 19:21:55 +01006374 goto out_error;
6375 }
6376 else {
6377 /* Fail on all other handshake errors */
6378 /* Note: OpenSSL may leave unread bytes in the socket's
6379 * buffer, causing an RST to be emitted upon close() on
6380 * TCP sockets. We first try to drain possibly pending
6381 * data to avoid this as much as possible.
6382 */
Willy Tarreaud85c4852015-03-13 00:40:28 +01006383 conn_sock_drain(conn);
Willy Tarreau20879a02012-12-03 16:32:10 +01006384 if (!conn->err_code)
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006385 conn->err_code = (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT) ?
Willy Tarreauf51c6982014-04-25 20:02:39 +02006386 CO_ER_SSL_KILLED_HB : CO_ER_SSL_HANDSHAKE;
Emeric Brun674b7432012-11-08 19:21:55 +01006387 goto out_error;
6388 }
6389 }
6390 /* read some data: consider handshake completed */
6391 goto reneg_ok;
6392 }
Olivier Houchard66ab4982019-02-26 18:37:15 +01006393 ret = SSL_do_handshake(ctx->ssl);
Olivier Houchardc2aae742017-09-22 18:26:28 +02006394check_error:
Emeric Brun46591952012-05-18 15:47:34 +02006395 if (ret != 1) {
6396 /* handshake did not complete, let's find why */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006397 ret = SSL_get_error(ctx->ssl, ret);
Emeric Brun46591952012-05-18 15:47:34 +02006398
6399 if (ret == SSL_ERROR_WANT_WRITE) {
6400 /* SSL handshake needs to write, L4 connection may not be ready */
Olivier Houchard03abf2d2019-05-28 10:12:02 +02006401 if (!(ctx->wait_event.events & SUB_RETRY_SEND))
Olivier Houchardea8dd942019-05-20 14:02:16 +02006402 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_SEND, &ctx->wait_event);
Emeric Brun46591952012-05-18 15:47:34 +02006403 return 0;
6404 }
6405 else if (ret == SSL_ERROR_WANT_READ) {
6406 /* SSL handshake needs to read, L4 connection is ready */
Olivier Houchardea8dd942019-05-20 14:02:16 +02006407 if (!(ctx->wait_event.events & SUB_RETRY_RECV))
Olivier Houchardea8dd942019-05-20 14:02:16 +02006408 ctx->xprt->subscribe(conn, ctx->xprt_ctx,
6409 SUB_RETRY_RECV, &ctx->wait_event);
Emeric Brun46591952012-05-18 15:47:34 +02006410 return 0;
6411 }
Willy Tarreau5db847a2019-05-09 14:13:35 +02006412#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006413 else if (ret == SSL_ERROR_WANT_ASYNC) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02006414 ssl_async_process_fds(ctx);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006415 return 0;
6416 }
6417#endif
Willy Tarreau89230192012-09-28 20:22:13 +02006418 else if (ret == SSL_ERROR_SYSCALL) {
6419 /* if errno is null, then connection was successfully established */
6420 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
6421 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01006422 if (!conn->err_code) {
Lukas Tribus49799162019-07-08 14:29:15 +02006423#if defined(OPENSSL_IS_BORINGSSL) || defined(LIBRESSL_VERSION_NUMBER)
6424 /* do not handle empty handshakes in BoringSSL or LibreSSL */
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01006425 conn->err_code = CO_ER_SSL_HANDSHAKE;
6426#else
6427 int empty_handshake;
Willy Tarreau5db847a2019-05-09 14:13:35 +02006428#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL)
Lukas Tribus49799162019-07-08 14:29:15 +02006429 /* use SSL_get_state() in OpenSSL >= 1.1.0; SSL_state() is broken */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006430 OSSL_HANDSHAKE_STATE state = SSL_get_state(ctx->ssl);
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01006431 empty_handshake = state == TLS_ST_BEFORE;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006432#else
Lukas Tribus49799162019-07-08 14:29:15 +02006433 /* access packet_length directly in OpenSSL <= 1.0.2; SSL_state() is broken */
6434 empty_handshake = !ctx->ssl->packet_length;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006435#endif
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01006436 if (empty_handshake) {
6437 if (!errno) {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006438 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01006439 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
6440 else
6441 conn->err_code = CO_ER_SSL_EMPTY;
6442 }
6443 else {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006444 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01006445 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
6446 else
6447 conn->err_code = CO_ER_SSL_ABORT;
6448 }
Emeric Brun29f037d2014-04-25 19:05:36 +02006449 }
6450 else {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006451 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emeric Brun29f037d2014-04-25 19:05:36 +02006452 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
6453 else
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01006454 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun29f037d2014-04-25 19:05:36 +02006455 }
Lukas Tribus49799162019-07-08 14:29:15 +02006456#endif /* BoringSSL or LibreSSL */
Emeric Brun29f037d2014-04-25 19:05:36 +02006457 }
Willy Tarreau89230192012-09-28 20:22:13 +02006458 goto out_error;
6459 }
Emeric Brun46591952012-05-18 15:47:34 +02006460 else {
6461 /* Fail on all other handshake errors */
Willy Tarreau566dc552012-10-19 20:52:18 +02006462 /* Note: OpenSSL may leave unread bytes in the socket's
6463 * buffer, causing an RST to be emitted upon close() on
6464 * TCP sockets. We first try to drain possibly pending
6465 * data to avoid this as much as possible.
6466 */
Willy Tarreaud85c4852015-03-13 00:40:28 +01006467 conn_sock_drain(conn);
Willy Tarreau20879a02012-12-03 16:32:10 +01006468 if (!conn->err_code)
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006469 conn->err_code = (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT) ?
Willy Tarreauf51c6982014-04-25 20:02:39 +02006470 CO_ER_SSL_KILLED_HB : CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02006471 goto out_error;
6472 }
6473 }
Willy Tarreau5db847a2019-05-09 14:13:35 +02006474#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Olivier Houchard522eea72017-11-03 16:27:47 +01006475 else {
6476 /*
6477 * If the server refused the early data, we have to send a
6478 * 425 to the client, as we no longer have the data to sent
6479 * them again.
6480 */
6481 if ((conn->flags & CO_FL_EARLY_DATA) && (objt_server(conn->target))) {
Olivier Houchard66ab4982019-02-26 18:37:15 +01006482 if (SSL_get_early_data_status(ctx->ssl) == SSL_EARLY_DATA_REJECTED) {
Olivier Houchard522eea72017-11-03 16:27:47 +01006483 conn->err_code = CO_ER_SSL_EARLY_FAILED;
6484 goto out_error;
6485 }
6486 }
6487 }
6488#endif
6489
Emeric Brun46591952012-05-18 15:47:34 +02006490
Emeric Brun674b7432012-11-08 19:21:55 +01006491reneg_ok:
Emeric Brunb5e42a82017-06-06 12:35:14 +00006492
Willy Tarreau5db847a2019-05-09 14:13:35 +02006493#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00006494 /* ASYNC engine API doesn't support moving read/write
6495 * buffers. So we disable ASYNC mode right after
6496 * the handshake to avoid buffer oveflows.
6497 */
6498 if (global_ssl.async)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006499 SSL_clear_mode(ctx->ssl, SSL_MODE_ASYNC);
Emeric Brunb5e42a82017-06-06 12:35:14 +00006500#endif
Emeric Brun46591952012-05-18 15:47:34 +02006501 /* Handshake succeeded */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006502 if (!SSL_session_reused(ctx->ssl)) {
Willy Tarreau0c9c2722014-05-28 12:28:58 +02006503 if (objt_server(conn->target)) {
6504 update_freq_ctr(&global.ssl_be_keys_per_sec, 1);
6505 if (global.ssl_be_keys_per_sec.curr_ctr > global.ssl_be_keys_max)
6506 global.ssl_be_keys_max = global.ssl_be_keys_per_sec.curr_ctr;
Emeric Brun46591952012-05-18 15:47:34 +02006507 }
Willy Tarreau0c9c2722014-05-28 12:28:58 +02006508 else {
6509 update_freq_ctr(&global.ssl_fe_keys_per_sec, 1);
6510 if (global.ssl_fe_keys_per_sec.curr_ctr > global.ssl_fe_keys_max)
6511 global.ssl_fe_keys_max = global.ssl_fe_keys_per_sec.curr_ctr;
6512 }
Emeric Brun46591952012-05-18 15:47:34 +02006513 }
6514
6515 /* The connection is now established at both layers, it's time to leave */
6516 conn->flags &= ~(flag | CO_FL_WAIT_L4_CONN | CO_FL_WAIT_L6_CONN);
6517 return 1;
6518
6519 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01006520 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02006521 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01006522 ERR_clear_error();
6523
Emeric Brun9fa89732012-10-04 17:09:56 +02006524 /* free resumed session if exists */
Willy Tarreau07d94e42018-09-20 10:57:52 +02006525 if (objt_server(conn->target) && __objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr) {
6526 free(__objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr);
6527 __objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr = NULL;
Emeric Brun9fa89732012-10-04 17:09:56 +02006528 }
6529
Emeric Brun46591952012-05-18 15:47:34 +02006530 /* Fail on all other handshake errors */
6531 conn->flags |= CO_FL_ERROR;
Willy Tarreau20879a02012-12-03 16:32:10 +01006532 if (!conn->err_code)
6533 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02006534 return 0;
6535}
6536
Willy Tarreauee1a6fc2020-01-17 07:52:13 +01006537/* Called from the upper layer, to subscribe <es> to events <event_type>. The
6538 * event subscriber <es> is not allowed to change from a previous call as long
6539 * as at least one event is still subscribed. The <event_type> must only be a
6540 * combination of SUB_RETRY_RECV and SUB_RETRY_SEND. It always returns 0,
6541 * unless the transport layer was already released.
6542 */
6543static int ssl_subscribe(struct connection *conn, void *xprt_ctx, int event_type, struct wait_event *es)
Olivier Houcharddf357842019-03-21 16:30:07 +01006544{
Olivier Houchardea8dd942019-05-20 14:02:16 +02006545 struct ssl_sock_ctx *ctx = xprt_ctx;
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006546
Olivier Houchard0ff28652019-06-24 18:57:39 +02006547 if (!ctx)
6548 return -1;
6549
Willy Tarreau113d52b2020-01-10 09:20:26 +01006550 BUG_ON(event_type & ~(SUB_RETRY_SEND|SUB_RETRY_RECV));
Willy Tarreauee1a6fc2020-01-17 07:52:13 +01006551 BUG_ON(ctx->subs && ctx->subs != es);
Olivier Houchardea8dd942019-05-20 14:02:16 +02006552
Willy Tarreauee1a6fc2020-01-17 07:52:13 +01006553 ctx->subs = es;
6554 es->events |= event_type;
Willy Tarreau113d52b2020-01-10 09:20:26 +01006555
6556 /* we may have to subscribe to lower layers for new events */
6557 event_type &= ~ctx->wait_event.events;
6558 if (event_type && !(conn->flags & CO_FL_SSL_WAIT_HS))
6559 ctx->xprt->subscribe(conn, ctx->xprt_ctx, event_type, &ctx->wait_event);
Olivier Houchardea8dd942019-05-20 14:02:16 +02006560 return 0;
Olivier Houcharddf357842019-03-21 16:30:07 +01006561}
6562
Willy Tarreauee1a6fc2020-01-17 07:52:13 +01006563/* Called from the upper layer, to unsubscribe <es> from events <event_type>.
6564 * The <es> pointer is not allowed to differ from the one passed to the
6565 * subscribe() call. It always returns zero.
6566 */
6567static int ssl_unsubscribe(struct connection *conn, void *xprt_ctx, int event_type, struct wait_event *es)
Olivier Houcharddf357842019-03-21 16:30:07 +01006568{
Olivier Houchardea8dd942019-05-20 14:02:16 +02006569 struct ssl_sock_ctx *ctx = xprt_ctx;
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006570
Willy Tarreau113d52b2020-01-10 09:20:26 +01006571 BUG_ON(event_type & ~(SUB_RETRY_SEND|SUB_RETRY_RECV));
Willy Tarreauee1a6fc2020-01-17 07:52:13 +01006572 BUG_ON(ctx->subs && ctx->subs != es);
Olivier Houchardea8dd942019-05-20 14:02:16 +02006573
Willy Tarreauee1a6fc2020-01-17 07:52:13 +01006574 es->events &= ~event_type;
6575 if (!es->events)
Willy Tarreau113d52b2020-01-10 09:20:26 +01006576 ctx->subs = NULL;
6577
6578 /* If we subscribed, and we're not doing the handshake,
6579 * then we subscribed because the upper layer asked for it,
6580 * as the upper layer is no longer interested, we can
6581 * unsubscribe too.
6582 */
6583 event_type &= ctx->wait_event.events;
6584 if (event_type && !(ctx->conn->flags & CO_FL_SSL_WAIT_HS))
6585 conn_unsubscribe(conn, ctx->xprt_ctx, event_type, &ctx->wait_event);
Olivier Houchardea8dd942019-05-20 14:02:16 +02006586
6587 return 0;
Olivier Houcharddf357842019-03-21 16:30:07 +01006588}
6589
Olivier Houchard2e055482019-05-27 19:50:12 +02006590/* Use the provided XPRT as an underlying XPRT, and provide the old one.
6591 * Returns 0 on success, and non-zero on failure.
6592 */
6593static 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)
6594{
6595 struct ssl_sock_ctx *ctx = xprt_ctx;
6596
6597 if (oldxprt_ops != NULL)
6598 *oldxprt_ops = ctx->xprt;
6599 if (oldxprt_ctx != NULL)
6600 *oldxprt_ctx = ctx->xprt_ctx;
6601 ctx->xprt = toadd_ops;
6602 ctx->xprt_ctx = toadd_ctx;
6603 return 0;
6604}
6605
Olivier Houchard5149b592019-05-23 17:47:36 +02006606/* Remove the specified xprt. If if it our underlying XPRT, remove it and
6607 * return 0, otherwise just call the remove_xprt method from the underlying
6608 * XPRT.
6609 */
6610static int ssl_remove_xprt(struct connection *conn, void *xprt_ctx, void *toremove_ctx, const struct xprt_ops *newops, void *newctx)
6611{
6612 struct ssl_sock_ctx *ctx = xprt_ctx;
6613
6614 if (ctx->xprt_ctx == toremove_ctx) {
6615 ctx->xprt_ctx = newctx;
6616 ctx->xprt = newops;
6617 return 0;
6618 }
6619 return (ctx->xprt->remove_xprt(conn, ctx->xprt_ctx, toremove_ctx, newops, newctx));
6620}
6621
Olivier Houchardea8dd942019-05-20 14:02:16 +02006622static struct task *ssl_sock_io_cb(struct task *t, void *context, unsigned short state)
6623{
6624 struct ssl_sock_ctx *ctx = context;
6625
6626 /* First if we're doing an handshake, try that */
6627 if (ctx->conn->flags & CO_FL_SSL_WAIT_HS)
6628 ssl_sock_handshake(ctx->conn, CO_FL_SSL_WAIT_HS);
6629 /* If we had an error, or the handshake is done and I/O is available,
6630 * let the upper layer know.
Olivier Houchard477902b2020-01-22 18:08:48 +01006631 * If no mux was set up yet, then call conn_create_mux()
Olivier Houchardea8dd942019-05-20 14:02:16 +02006632 * we can't be sure conn_fd_handler() will be called again.
6633 */
6634 if ((ctx->conn->flags & CO_FL_ERROR) ||
6635 !(ctx->conn->flags & CO_FL_SSL_WAIT_HS)) {
6636 int ret = 0;
6637 int woke = 0;
6638
6639 /* On error, wake any waiter */
Willy Tarreau113d52b2020-01-10 09:20:26 +01006640 if (ctx->subs) {
6641 tasklet_wakeup(ctx->subs->tasklet);
6642 ctx->subs->events = 0;
Olivier Houchardea8dd942019-05-20 14:02:16 +02006643 woke = 1;
Willy Tarreau113d52b2020-01-10 09:20:26 +01006644 ctx->subs = NULL;
Olivier Houchardea8dd942019-05-20 14:02:16 +02006645 }
Willy Tarreau113d52b2020-01-10 09:20:26 +01006646
Olivier Houchardea8dd942019-05-20 14:02:16 +02006647 /* If we're the first xprt for the connection, let the
Olivier Houchard477902b2020-01-22 18:08:48 +01006648 * upper layers know. If we have no mux, create it,
6649 * and once we have a mux, call its wake method if we didn't
6650 * woke a tasklet already.
Olivier Houchardea8dd942019-05-20 14:02:16 +02006651 */
6652 if (ctx->conn->xprt_ctx == ctx) {
Olivier Houchard477902b2020-01-22 18:08:48 +01006653 if (!ctx->conn->mux)
6654 ret = conn_create_mux(ctx->conn);
Olivier Houchardea8dd942019-05-20 14:02:16 +02006655 if (ret >= 0 && !woke && ctx->conn->mux && ctx->conn->mux->wake)
6656 ctx->conn->mux->wake(ctx->conn);
6657 return NULL;
6658 }
6659 }
Olivier Houchard54907bb2019-12-19 15:02:39 +01006660#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
6661 /* If we have early data and somebody wants to receive, let them */
Willy Tarreau113d52b2020-01-10 09:20:26 +01006662 else if (b_data(&ctx->early_buf) && ctx->subs &&
6663 ctx->subs->events & SUB_RETRY_RECV) {
6664 tasklet_wakeup(ctx->subs->tasklet);
6665 ctx->subs->events &= ~SUB_RETRY_RECV;
6666 if (!ctx->subs->events)
6667 ctx->subs = NULL;
Olivier Houchard54907bb2019-12-19 15:02:39 +01006668 }
6669#endif
Olivier Houchardea8dd942019-05-20 14:02:16 +02006670 return NULL;
6671}
6672
Emeric Brun46591952012-05-18 15:47:34 +02006673/* Receive up to <count> bytes from connection <conn>'s socket and store them
Willy Tarreauabf08d92014-01-14 11:31:27 +01006674 * into buffer <buf>. Only one call to recv() is performed, unless the
Emeric Brun46591952012-05-18 15:47:34 +02006675 * buffer wraps, in which case a second call may be performed. The connection's
6676 * flags are updated with whatever special event is detected (error, read0,
6677 * empty). The caller is responsible for taking care of those events and
6678 * avoiding the call if inappropriate. The function does not call the
6679 * connection's polling update function, so the caller is responsible for this.
6680 */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006681static 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 +02006682{
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006683 struct ssl_sock_ctx *ctx = xprt_ctx;
Willy Tarreaubfc4d772018-07-18 11:22:03 +02006684 ssize_t ret;
6685 size_t try, done = 0;
Emeric Brun46591952012-05-18 15:47:34 +02006686
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006687 if (!ctx)
Emeric Brun46591952012-05-18 15:47:34 +02006688 goto out_error;
6689
Olivier Houchard54907bb2019-12-19 15:02:39 +01006690#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
6691 if (b_data(&ctx->early_buf)) {
6692 try = b_contig_space(buf);
6693 if (try > b_data(&ctx->early_buf))
6694 try = b_data(&ctx->early_buf);
6695 memcpy(b_tail(buf), b_head(&ctx->early_buf), try);
6696 b_add(buf, try);
6697 b_del(&ctx->early_buf, try);
6698 if (b_data(&ctx->early_buf) == 0)
6699 b_free(&ctx->early_buf);
6700 return try;
6701 }
6702#endif
6703
Willy Tarreau911db9b2020-01-23 16:27:54 +01006704 if (conn->flags & (CO_FL_WAIT_XPRT | CO_FL_SSL_WAIT_HS))
Emeric Brun46591952012-05-18 15:47:34 +02006705 /* a handshake was requested */
6706 return 0;
6707
Emeric Brun46591952012-05-18 15:47:34 +02006708 /* read the largest possible block. For this, we perform only one call
6709 * to recv() unless the buffer wraps and we exactly fill the first hunk,
6710 * in which case we accept to do it once again. A new attempt is made on
6711 * EINTR too.
6712 */
Willy Tarreau00b0fb92014-01-17 11:09:40 +01006713 while (count > 0) {
Olivier Houchardc2aae742017-09-22 18:26:28 +02006714
Willy Tarreau591d4452018-06-15 17:21:00 +02006715 try = b_contig_space(buf);
6716 if (!try)
6717 break;
6718
Willy Tarreauabf08d92014-01-14 11:31:27 +01006719 if (try > count)
6720 try = count;
Willy Tarreau591d4452018-06-15 17:21:00 +02006721
Olivier Houchard66ab4982019-02-26 18:37:15 +01006722 ret = SSL_read(ctx->ssl, b_tail(buf), try);
Emmanuel Hocdetf967c312019-08-05 18:04:16 +02006723
Emeric Brune1f38db2012-09-03 20:36:47 +02006724 if (conn->flags & CO_FL_ERROR) {
6725 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01006726 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02006727 }
Emeric Brun46591952012-05-18 15:47:34 +02006728 if (ret > 0) {
Olivier Houchardacd14032018-06-28 18:17:23 +02006729 b_add(buf, ret);
Emeric Brun46591952012-05-18 15:47:34 +02006730 done += ret;
Emeric Brun46591952012-05-18 15:47:34 +02006731 count -= ret;
Emeric Brun46591952012-05-18 15:47:34 +02006732 }
Emeric Brun46591952012-05-18 15:47:34 +02006733 else {
Olivier Houchard66ab4982019-02-26 18:37:15 +01006734 ret = SSL_get_error(ctx->ssl, ret);
Emeric Brun46591952012-05-18 15:47:34 +02006735 if (ret == SSL_ERROR_WANT_WRITE) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01006736 /* handshake is running, and it needs to enable write */
Emeric Brun46591952012-05-18 15:47:34 +02006737 conn->flags |= CO_FL_SSL_WAIT_HS;
Olivier Houchardea8dd942019-05-20 14:02:16 +02006738 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_SEND, &ctx->wait_event);
Willy Tarreau5db847a2019-05-09 14:13:35 +02006739#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00006740 /* Async mode can be re-enabled, because we're leaving data state.*/
6741 if (global_ssl.async)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006742 SSL_set_mode(ctx->ssl, SSL_MODE_ASYNC);
Emeric Brunb5e42a82017-06-06 12:35:14 +00006743#endif
Emeric Brun46591952012-05-18 15:47:34 +02006744 break;
6745 }
6746 else if (ret == SSL_ERROR_WANT_READ) {
Olivier Houchard66ab4982019-02-26 18:37:15 +01006747 if (SSL_renegotiate_pending(ctx->ssl)) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02006748 ctx->xprt->subscribe(conn, ctx->xprt_ctx,
6749 SUB_RETRY_RECV,
6750 &ctx->wait_event);
Emeric Brun282a76a2012-11-08 18:02:56 +01006751 /* handshake is running, and it may need to re-enable read */
6752 conn->flags |= CO_FL_SSL_WAIT_HS;
Willy Tarreau5db847a2019-05-09 14:13:35 +02006753#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00006754 /* Async mode can be re-enabled, because we're leaving data state.*/
6755 if (global_ssl.async)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006756 SSL_set_mode(ctx->ssl, SSL_MODE_ASYNC);
Emeric Brunb5e42a82017-06-06 12:35:14 +00006757#endif
Emeric Brun282a76a2012-11-08 18:02:56 +01006758 break;
6759 }
Emeric Brun46591952012-05-18 15:47:34 +02006760 break;
Olivier Houchardc2aae742017-09-22 18:26:28 +02006761 } else if (ret == SSL_ERROR_ZERO_RETURN)
6762 goto read0;
Christopher Faulet4ac77a92018-02-19 14:25:15 +01006763 /* For SSL_ERROR_SYSCALL, make sure to clear the error
6764 * stack before shutting down the connection for
6765 * reading. */
Olivier Houchard7e2e5052018-02-13 15:17:23 +01006766 if (ret == SSL_ERROR_SYSCALL && (!errno || errno == EAGAIN))
6767 goto clear_ssl_error;
Emeric Brun46591952012-05-18 15:47:34 +02006768 /* otherwise it's a real error */
6769 goto out_error;
6770 }
6771 }
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02006772 leave:
Emeric Brun46591952012-05-18 15:47:34 +02006773 return done;
6774
Christopher Faulet4ac77a92018-02-19 14:25:15 +01006775 clear_ssl_error:
6776 /* Clear openssl global errors stack */
6777 ssl_sock_dump_errors(conn);
6778 ERR_clear_error();
Emeric Brun46591952012-05-18 15:47:34 +02006779 read0:
6780 conn_sock_read0(conn);
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02006781 goto leave;
Christopher Faulet4ac77a92018-02-19 14:25:15 +01006782
Emeric Brun46591952012-05-18 15:47:34 +02006783 out_error:
Olivier Houchard7e2e5052018-02-13 15:17:23 +01006784 conn->flags |= CO_FL_ERROR;
Emeric Brun644cde02012-12-14 11:21:13 +01006785 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02006786 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01006787 ERR_clear_error();
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02006788 goto leave;
Emeric Brun46591952012-05-18 15:47:34 +02006789}
6790
6791
Willy Tarreau787db9a2018-06-14 18:31:46 +02006792/* Send up to <count> pending bytes from buffer <buf> to connection <conn>'s
6793 * socket. <flags> may contain some CO_SFL_* flags to hint the system about
6794 * other pending data for example, but this flag is ignored at the moment.
Emeric Brun46591952012-05-18 15:47:34 +02006795 * Only one call to send() is performed, unless the buffer wraps, in which case
6796 * a second call may be performed. The connection's flags are updated with
6797 * whatever special event is detected (error, empty). The caller is responsible
6798 * for taking care of those events and avoiding the call if inappropriate. The
6799 * function does not call the connection's polling update function, so the caller
Willy Tarreau787db9a2018-06-14 18:31:46 +02006800 * is responsible for this. The buffer's output is not adjusted, it's up to the
6801 * caller to take care of this. It's up to the caller to update the buffer's
6802 * contents based on the return value.
Emeric Brun46591952012-05-18 15:47:34 +02006803 */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006804static 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 +02006805{
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006806 struct ssl_sock_ctx *ctx = xprt_ctx;
Willy Tarreau787db9a2018-06-14 18:31:46 +02006807 ssize_t ret;
6808 size_t try, done;
Emeric Brun46591952012-05-18 15:47:34 +02006809
6810 done = 0;
6811
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006812 if (!ctx)
Emeric Brun46591952012-05-18 15:47:34 +02006813 goto out_error;
6814
Willy Tarreau911db9b2020-01-23 16:27:54 +01006815 if (conn->flags & (CO_FL_WAIT_XPRT | CO_FL_SSL_WAIT_HS | CO_FL_EARLY_SSL_HS))
Emeric Brun46591952012-05-18 15:47:34 +02006816 /* a handshake was requested */
6817 return 0;
6818
6819 /* send the largest possible block. For this we perform only one call
6820 * to send() unless the buffer wraps and we exactly fill the first hunk,
6821 * in which case we accept to do it once again.
6822 */
Willy Tarreau787db9a2018-06-14 18:31:46 +02006823 while (count) {
Willy Tarreau5db847a2019-05-09 14:13:35 +02006824#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Olivier Houchardc2aae742017-09-22 18:26:28 +02006825 size_t written_data;
6826#endif
6827
Willy Tarreau787db9a2018-06-14 18:31:46 +02006828 try = b_contig_data(buf, done);
6829 if (try > count)
6830 try = count;
Willy Tarreaubfd59462013-02-21 07:46:09 +01006831
Willy Tarreau7bed9452014-02-02 02:00:24 +01006832 if (!(flags & CO_SFL_STREAMER) &&
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006833 !(ctx->xprt_st & SSL_SOCK_SEND_UNLIMITED) &&
Willy Tarreauef934602016-12-22 23:12:01 +01006834 global_ssl.max_record && try > global_ssl.max_record) {
6835 try = global_ssl.max_record;
Willy Tarreau518cedd2014-02-17 15:43:01 +01006836 }
6837 else {
6838 /* we need to keep the information about the fact that
6839 * we're not limiting the upcoming send(), because if it
6840 * fails, we'll have to retry with at least as many data.
6841 */
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006842 ctx->xprt_st |= SSL_SOCK_SEND_UNLIMITED;
Willy Tarreau518cedd2014-02-17 15:43:01 +01006843 }
Willy Tarreaubfd59462013-02-21 07:46:09 +01006844
Willy Tarreau5db847a2019-05-09 14:13:35 +02006845#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Olivier Houchard010941f2019-05-03 20:56:19 +02006846 if (!SSL_is_init_finished(ctx->ssl) && conn_is_back(conn)) {
Olivier Houchardc2aae742017-09-22 18:26:28 +02006847 unsigned int max_early;
6848
Olivier Houchard522eea72017-11-03 16:27:47 +01006849 if (objt_listener(conn->target))
Olivier Houchard66ab4982019-02-26 18:37:15 +01006850 max_early = SSL_get_max_early_data(ctx->ssl);
Olivier Houchard522eea72017-11-03 16:27:47 +01006851 else {
Olivier Houchard66ab4982019-02-26 18:37:15 +01006852 if (SSL_get0_session(ctx->ssl))
6853 max_early = SSL_SESSION_get_max_early_data(SSL_get0_session(ctx->ssl));
Olivier Houchard522eea72017-11-03 16:27:47 +01006854 else
6855 max_early = 0;
6856 }
6857
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006858 if (try + ctx->sent_early_data > max_early) {
6859 try -= (try + ctx->sent_early_data) - max_early;
Olivier Houchard522eea72017-11-03 16:27:47 +01006860 if (try <= 0) {
Olivier Houchard010941f2019-05-03 20:56:19 +02006861 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Olivier Houchard965e84e2019-06-15 20:59:30 +02006862 tasklet_wakeup(ctx->wait_event.tasklet);
Olivier Houchardc2aae742017-09-22 18:26:28 +02006863 break;
Olivier Houchard522eea72017-11-03 16:27:47 +01006864 }
Olivier Houchardc2aae742017-09-22 18:26:28 +02006865 }
Olivier Houchard66ab4982019-02-26 18:37:15 +01006866 ret = SSL_write_early_data(ctx->ssl, b_peek(buf, done), try, &written_data);
Olivier Houchardc2aae742017-09-22 18:26:28 +02006867 if (ret == 1) {
6868 ret = written_data;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006869 ctx->sent_early_data += ret;
Olivier Houchard965e84e2019-06-15 20:59:30 +02006870 if (objt_server(conn->target)) {
Olivier Houchard522eea72017-11-03 16:27:47 +01006871 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN | CO_FL_EARLY_DATA;
Olivier Houchard965e84e2019-06-15 20:59:30 +02006872 /* Initiate the handshake, now */
6873 tasklet_wakeup(ctx->wait_event.tasklet);
6874 }
Olivier Houchard522eea72017-11-03 16:27:47 +01006875
Olivier Houchardc2aae742017-09-22 18:26:28 +02006876 }
6877
6878 } else
6879#endif
Olivier Houchard66ab4982019-02-26 18:37:15 +01006880 ret = SSL_write(ctx->ssl, b_peek(buf, done), try);
Willy Tarreau518cedd2014-02-17 15:43:01 +01006881
Emeric Brune1f38db2012-09-03 20:36:47 +02006882 if (conn->flags & CO_FL_ERROR) {
6883 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01006884 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02006885 }
Emeric Brun46591952012-05-18 15:47:34 +02006886 if (ret > 0) {
Willy Tarreauc192b0a2020-01-23 09:11:58 +01006887 /* A send succeeded, so we can consider ourself connected */
6888 conn->flags &= ~CO_FL_WAIT_L4L6;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006889 ctx->xprt_st &= ~SSL_SOCK_SEND_UNLIMITED;
Willy Tarreau787db9a2018-06-14 18:31:46 +02006890 count -= ret;
Emeric Brun46591952012-05-18 15:47:34 +02006891 done += ret;
Emeric Brun46591952012-05-18 15:47:34 +02006892 }
6893 else {
Olivier Houchard66ab4982019-02-26 18:37:15 +01006894 ret = SSL_get_error(ctx->ssl, ret);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006895
Emeric Brun46591952012-05-18 15:47:34 +02006896 if (ret == SSL_ERROR_WANT_WRITE) {
Olivier Houchard66ab4982019-02-26 18:37:15 +01006897 if (SSL_renegotiate_pending(ctx->ssl)) {
Emeric Brun282a76a2012-11-08 18:02:56 +01006898 /* handshake is running, and it may need to re-enable write */
6899 conn->flags |= CO_FL_SSL_WAIT_HS;
Olivier Houchardea8dd942019-05-20 14:02:16 +02006900 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_SEND, &ctx->wait_event);
Willy Tarreau5db847a2019-05-09 14:13:35 +02006901#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00006902 /* Async mode can be re-enabled, because we're leaving data state.*/
6903 if (global_ssl.async)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006904 SSL_set_mode(ctx->ssl, SSL_MODE_ASYNC);
Emeric Brunb5e42a82017-06-06 12:35:14 +00006905#endif
Emeric Brun282a76a2012-11-08 18:02:56 +01006906 break;
6907 }
Olivier Houchardea8dd942019-05-20 14:02:16 +02006908
Emeric Brun46591952012-05-18 15:47:34 +02006909 break;
6910 }
6911 else if (ret == SSL_ERROR_WANT_READ) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01006912 /* handshake is running, and it needs to enable read */
Emeric Brun46591952012-05-18 15:47:34 +02006913 conn->flags |= CO_FL_SSL_WAIT_HS;
Olivier Houchardea8dd942019-05-20 14:02:16 +02006914 ctx->xprt->subscribe(conn, ctx->xprt_ctx,
6915 SUB_RETRY_RECV,
6916 &ctx->wait_event);
Willy Tarreau5db847a2019-05-09 14:13:35 +02006917#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00006918 /* Async mode can be re-enabled, because we're leaving data state.*/
6919 if (global_ssl.async)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006920 SSL_set_mode(ctx->ssl, SSL_MODE_ASYNC);
Emeric Brunb5e42a82017-06-06 12:35:14 +00006921#endif
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006922 break;
6923 }
Emeric Brun46591952012-05-18 15:47:34 +02006924 goto out_error;
6925 }
6926 }
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02006927 leave:
Emeric Brun46591952012-05-18 15:47:34 +02006928 return done;
6929
6930 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01006931 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02006932 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01006933 ERR_clear_error();
6934
Emeric Brun46591952012-05-18 15:47:34 +02006935 conn->flags |= CO_FL_ERROR;
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02006936 goto leave;
Emeric Brun46591952012-05-18 15:47:34 +02006937}
6938
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006939static void ssl_sock_close(struct connection *conn, void *xprt_ctx) {
Emeric Brun46591952012-05-18 15:47:34 +02006940
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006941 struct ssl_sock_ctx *ctx = xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006942
Olivier Houchardea8dd942019-05-20 14:02:16 +02006943
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006944 if (ctx) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02006945 if (ctx->wait_event.events != 0)
6946 ctx->xprt->unsubscribe(ctx->conn, ctx->xprt_ctx,
6947 ctx->wait_event.events,
6948 &ctx->wait_event);
Willy Tarreau113d52b2020-01-10 09:20:26 +01006949 if (ctx->subs) {
6950 ctx->subs->events = 0;
6951 tasklet_wakeup(ctx->subs->tasklet);
Olivier Houchardea8dd942019-05-20 14:02:16 +02006952 }
Willy Tarreau113d52b2020-01-10 09:20:26 +01006953
Olivier Houchard692c1d02019-05-23 18:41:47 +02006954 if (ctx->xprt->close)
6955 ctx->xprt->close(conn, ctx->xprt_ctx);
Willy Tarreau5db847a2019-05-09 14:13:35 +02006956#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brun3854e012017-05-17 20:42:48 +02006957 if (global_ssl.async) {
6958 OSSL_ASYNC_FD all_fd[32], afd;
6959 size_t num_all_fds = 0;
6960 int i;
6961
Olivier Houchard66ab4982019-02-26 18:37:15 +01006962 SSL_get_all_async_fds(ctx->ssl, NULL, &num_all_fds);
Emeric Brun3854e012017-05-17 20:42:48 +02006963 if (num_all_fds > 32) {
6964 send_log(NULL, LOG_EMERG, "haproxy: openssl returns too many async fds. It seems a bug. Process may crash\n");
6965 return;
6966 }
6967
Olivier Houchard66ab4982019-02-26 18:37:15 +01006968 SSL_get_all_async_fds(ctx->ssl, all_fd, &num_all_fds);
Emeric Brun3854e012017-05-17 20:42:48 +02006969
6970 /* If an async job is pending, we must try to
6971 to catch the end using polling before calling
6972 SSL_free */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006973 if (num_all_fds && SSL_waiting_for_async(ctx->ssl)) {
Emeric Brun3854e012017-05-17 20:42:48 +02006974 for (i=0 ; i < num_all_fds ; i++) {
6975 /* switch on an handler designed to
6976 * handle the SSL_free
6977 */
6978 afd = all_fd[i];
6979 fdtab[afd].iocb = ssl_async_fd_free;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006980 fdtab[afd].owner = ctx->ssl;
Emeric Brun3854e012017-05-17 20:42:48 +02006981 fd_want_recv(afd);
Emeric Brunce9e01c2017-05-31 10:02:53 +00006982 /* To ensure that the fd cache won't be used
6983 * and we'll catch a real RD event.
6984 */
6985 fd_cant_recv(afd);
Emeric Brun3854e012017-05-17 20:42:48 +02006986 }
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02006987 tasklet_free(ctx->wait_event.tasklet);
Olivier Houchard66ab4982019-02-26 18:37:15 +01006988 pool_free(ssl_sock_ctx_pool, ctx);
Olivier Houchard2be5a4c2019-03-08 18:54:43 +01006989 _HA_ATOMIC_ADD(&jobs, 1);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006990 return;
6991 }
Emeric Brun3854e012017-05-17 20:42:48 +02006992 /* Else we can remove the fds from the fdtab
6993 * and call SSL_free.
6994 * note: we do a fd_remove and not a delete
6995 * because the fd is owned by the engine.
6996 * the engine is responsible to close
6997 */
6998 for (i=0 ; i < num_all_fds ; i++)
6999 fd_remove(all_fd[i]);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00007000 }
7001#endif
Olivier Houchard66ab4982019-02-26 18:37:15 +01007002 SSL_free(ctx->ssl);
Olivier Houchard54907bb2019-12-19 15:02:39 +01007003 b_free(&ctx->early_buf);
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02007004 tasklet_free(ctx->wait_event.tasklet);
Olivier Houchard66ab4982019-02-26 18:37:15 +01007005 pool_free(ssl_sock_ctx_pool, ctx);
Olivier Houchard2be5a4c2019-03-08 18:54:43 +01007006 _HA_ATOMIC_SUB(&sslconns, 1);
Emeric Brun46591952012-05-18 15:47:34 +02007007 }
Emeric Brun46591952012-05-18 15:47:34 +02007008}
7009
7010/* This function tries to perform a clean shutdown on an SSL connection, and in
7011 * any case, flags the connection as reusable if no handshake was in progress.
7012 */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01007013static void ssl_sock_shutw(struct connection *conn, void *xprt_ctx, int clean)
Emeric Brun46591952012-05-18 15:47:34 +02007014{
Olivier Houcharde179d0e2019-03-21 18:27:17 +01007015 struct ssl_sock_ctx *ctx = xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007016
Willy Tarreau911db9b2020-01-23 16:27:54 +01007017 if (conn->flags & (CO_FL_WAIT_XPRT | CO_FL_SSL_WAIT_HS))
Emeric Brun46591952012-05-18 15:47:34 +02007018 return;
Emmanuel Hocdet405ff312017-01-08 14:07:39 +01007019 if (!clean)
7020 /* don't sent notify on SSL_shutdown */
Olivier Houchard66ab4982019-02-26 18:37:15 +01007021 SSL_set_quiet_shutdown(ctx->ssl, 1);
Emeric Brun46591952012-05-18 15:47:34 +02007022 /* no handshake was in progress, try a clean ssl shutdown */
Olivier Houchard66ab4982019-02-26 18:37:15 +01007023 if (SSL_shutdown(ctx->ssl) <= 0) {
Emeric Brun644cde02012-12-14 11:21:13 +01007024 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02007025 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01007026 ERR_clear_error();
7027 }
Emeric Brun46591952012-05-18 15:47:34 +02007028}
7029
William Lallemandd4f946c2019-12-05 10:26:40 +01007030/* fill a buffer with the algorithm and size of a public key */
7031static int cert_get_pkey_algo(X509 *crt, struct buffer *out)
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01007032{
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01007033 int bits = 0;
7034 int sig = TLSEXT_signature_anonymous;
7035 int len = -1;
Emmanuel Hocdetc3775d22019-11-04 18:19:32 +01007036 EVP_PKEY *pkey;
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01007037
Emmanuel Hocdetc3775d22019-11-04 18:19:32 +01007038 pkey = X509_get_pubkey(crt);
7039 if (pkey) {
7040 bits = EVP_PKEY_bits(pkey);
7041 switch(EVP_PKEY_base_id(pkey)) {
7042 case EVP_PKEY_RSA:
7043 sig = TLSEXT_signature_rsa;
7044 break;
7045 case EVP_PKEY_EC:
7046 sig = TLSEXT_signature_ecdsa;
7047 break;
7048 case EVP_PKEY_DSA:
7049 sig = TLSEXT_signature_dsa;
7050 break;
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01007051 }
Emmanuel Hocdetc3775d22019-11-04 18:19:32 +01007052 EVP_PKEY_free(pkey);
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01007053 }
7054
7055 switch(sig) {
7056 case TLSEXT_signature_rsa:
7057 len = chunk_printf(out, "RSA%d", bits);
7058 break;
7059 case TLSEXT_signature_ecdsa:
7060 len = chunk_printf(out, "EC%d", bits);
7061 break;
7062 case TLSEXT_signature_dsa:
7063 len = chunk_printf(out, "DSA%d", bits);
7064 break;
7065 default:
7066 return 0;
7067 }
7068 if (len < 0)
7069 return 0;
7070 return 1;
7071}
7072
William Lallemandd4f946c2019-12-05 10:26:40 +01007073/* used for ppv2 pkey alog (can be used for logging) */
7074int ssl_sock_get_pkey_algo(struct connection *conn, struct buffer *out)
7075{
7076 struct ssl_sock_ctx *ctx;
7077 X509 *crt;
7078
7079 if (!ssl_sock_is_ssl(conn))
7080 return 0;
7081
7082 ctx = conn->xprt_ctx;
7083
7084 crt = SSL_get_certificate(ctx->ssl);
7085 if (!crt)
7086 return 0;
7087
7088 return cert_get_pkey_algo(crt, out);
7089}
7090
Emmanuel Hocdet283e0042017-11-02 14:05:23 +01007091/* used for ppv2 cert signature (can be used for logging) */
7092const char *ssl_sock_get_cert_sig(struct connection *conn)
7093{
Christopher Faulet82004142019-09-10 10:12:03 +02007094 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007095
Emmanuel Hocdet283e0042017-11-02 14:05:23 +01007096 __OPENSSL_110_CONST__ ASN1_OBJECT *algorithm;
7097 X509 *crt;
7098
7099 if (!ssl_sock_is_ssl(conn))
7100 return NULL;
Christopher Faulet82004142019-09-10 10:12:03 +02007101 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007102 crt = SSL_get_certificate(ctx->ssl);
Emmanuel Hocdet283e0042017-11-02 14:05:23 +01007103 if (!crt)
7104 return NULL;
7105 X509_ALGOR_get0(&algorithm, NULL, NULL, X509_get0_tbs_sigalg(crt));
7106 return OBJ_nid2sn(OBJ_obj2nid(algorithm));
7107}
7108
Emmanuel Hocdet253c3b72018-02-01 18:29:59 +01007109/* used for ppv2 authority */
7110const char *ssl_sock_get_sni(struct connection *conn)
7111{
7112#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Christopher Faulet82004142019-09-10 10:12:03 +02007113 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007114
Emmanuel Hocdet253c3b72018-02-01 18:29:59 +01007115 if (!ssl_sock_is_ssl(conn))
7116 return NULL;
Christopher Faulet82004142019-09-10 10:12:03 +02007117 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007118 return SSL_get_servername(ctx->ssl, TLSEXT_NAMETYPE_host_name);
Emmanuel Hocdet253c3b72018-02-01 18:29:59 +01007119#else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007120 return NULL;
Emmanuel Hocdet253c3b72018-02-01 18:29:59 +01007121#endif
7122}
7123
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02007124/* used for logging/ppv2, may be changed for a sample fetch later */
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02007125const char *ssl_sock_get_cipher_name(struct connection *conn)
7126{
Christopher Faulet82004142019-09-10 10:12:03 +02007127 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007128
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02007129 if (!ssl_sock_is_ssl(conn))
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02007130 return NULL;
Christopher Faulet82004142019-09-10 10:12:03 +02007131 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007132 return SSL_get_cipher_name(ctx->ssl);
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02007133}
7134
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02007135/* used for logging/ppv2, may be changed for a sample fetch later */
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02007136const char *ssl_sock_get_proto_version(struct connection *conn)
7137{
Christopher Faulet82004142019-09-10 10:12:03 +02007138 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007139
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02007140 if (!ssl_sock_is_ssl(conn))
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02007141 return NULL;
Christopher Faulet82004142019-09-10 10:12:03 +02007142 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007143 return SSL_get_version(ctx->ssl);
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02007144}
7145
Willy Tarreau8d598402012-10-22 17:58:39 +02007146/* Extract a serial from a cert, and copy it to a chunk.
7147 * Returns 1 if serial is found and copied, 0 if no serial found and
7148 * -1 if output is not large enough.
7149 */
7150static int
Willy Tarreau83061a82018-07-13 11:56:34 +02007151ssl_sock_get_serial(X509 *crt, struct buffer *out)
Willy Tarreau8d598402012-10-22 17:58:39 +02007152{
7153 ASN1_INTEGER *serial;
7154
7155 serial = X509_get_serialNumber(crt);
7156 if (!serial)
7157 return 0;
7158
7159 if (out->size < serial->length)
7160 return -1;
7161
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007162 memcpy(out->area, serial->data, serial->length);
7163 out->data = serial->length;
Willy Tarreau8d598402012-10-22 17:58:39 +02007164 return 1;
7165}
7166
Emeric Brun43e79582014-10-29 19:03:26 +01007167/* Extract a cert to der, and copy it to a chunk.
Joseph Herlant017b3da2018-11-15 09:07:59 -08007168 * Returns 1 if the cert is found and copied, 0 on der conversion failure
7169 * and -1 if the output is not large enough.
Emeric Brun43e79582014-10-29 19:03:26 +01007170 */
7171static int
Willy Tarreau83061a82018-07-13 11:56:34 +02007172ssl_sock_crt2der(X509 *crt, struct buffer *out)
Emeric Brun43e79582014-10-29 19:03:26 +01007173{
7174 int len;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007175 unsigned char *p = (unsigned char *) out->area;;
Emeric Brun43e79582014-10-29 19:03:26 +01007176
7177 len =i2d_X509(crt, NULL);
7178 if (len <= 0)
7179 return 1;
7180
7181 if (out->size < len)
7182 return -1;
7183
7184 i2d_X509(crt,&p);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007185 out->data = len;
Emeric Brun43e79582014-10-29 19:03:26 +01007186 return 1;
7187}
7188
Emeric Brunce5ad802012-10-22 14:11:22 +02007189
Willy Tarreau83061a82018-07-13 11:56:34 +02007190/* Copy Date in ASN1_UTCTIME format in struct buffer out.
Emeric Brunce5ad802012-10-22 14:11:22 +02007191 * Returns 1 if serial is found and copied, 0 if no valid time found
7192 * and -1 if output is not large enough.
7193 */
7194static int
Willy Tarreau83061a82018-07-13 11:56:34 +02007195ssl_sock_get_time(ASN1_TIME *tm, struct buffer *out)
Emeric Brunce5ad802012-10-22 14:11:22 +02007196{
7197 if (tm->type == V_ASN1_GENERALIZEDTIME) {
7198 ASN1_GENERALIZEDTIME *gentm = (ASN1_GENERALIZEDTIME *)tm;
7199
7200 if (gentm->length < 12)
7201 return 0;
7202 if (gentm->data[0] != 0x32 || gentm->data[1] != 0x30)
7203 return 0;
7204 if (out->size < gentm->length-2)
7205 return -1;
7206
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007207 memcpy(out->area, gentm->data+2, gentm->length-2);
7208 out->data = gentm->length-2;
Emeric Brunce5ad802012-10-22 14:11:22 +02007209 return 1;
7210 }
7211 else if (tm->type == V_ASN1_UTCTIME) {
7212 ASN1_UTCTIME *utctm = (ASN1_UTCTIME *)tm;
7213
7214 if (utctm->length < 10)
7215 return 0;
7216 if (utctm->data[0] >= 0x35)
7217 return 0;
7218 if (out->size < utctm->length)
7219 return -1;
7220
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007221 memcpy(out->area, utctm->data, utctm->length);
7222 out->data = utctm->length;
Emeric Brunce5ad802012-10-22 14:11:22 +02007223 return 1;
7224 }
7225
7226 return 0;
7227}
7228
Emeric Brun87855892012-10-17 17:39:35 +02007229/* Extract an entry from a X509_NAME and copy its value to an output chunk.
7230 * Returns 1 if entry found, 0 if entry not found, or -1 if output not large enough.
7231 */
7232static int
Willy Tarreau83061a82018-07-13 11:56:34 +02007233ssl_sock_get_dn_entry(X509_NAME *a, const struct buffer *entry, int pos,
7234 struct buffer *out)
Emeric Brun87855892012-10-17 17:39:35 +02007235{
7236 X509_NAME_ENTRY *ne;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007237 ASN1_OBJECT *obj;
7238 ASN1_STRING *data;
7239 const unsigned char *data_ptr;
7240 int data_len;
Emeric Brun87855892012-10-17 17:39:35 +02007241 int i, j, n;
7242 int cur = 0;
7243 const char *s;
7244 char tmp[128];
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007245 int name_count;
7246
7247 name_count = X509_NAME_entry_count(a);
Emeric Brun87855892012-10-17 17:39:35 +02007248
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007249 out->data = 0;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007250 for (i = 0; i < name_count; i++) {
Emeric Brun87855892012-10-17 17:39:35 +02007251 if (pos < 0)
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007252 j = (name_count-1) - i;
Emeric Brun87855892012-10-17 17:39:35 +02007253 else
7254 j = i;
7255
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007256 ne = X509_NAME_get_entry(a, j);
7257 obj = X509_NAME_ENTRY_get_object(ne);
7258 data = X509_NAME_ENTRY_get_data(ne);
7259 data_ptr = ASN1_STRING_get0_data(data);
7260 data_len = ASN1_STRING_length(data);
7261 n = OBJ_obj2nid(obj);
Emeric Brun87855892012-10-17 17:39:35 +02007262 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007263 i2t_ASN1_OBJECT(tmp, sizeof(tmp), obj);
Emeric Brun87855892012-10-17 17:39:35 +02007264 s = tmp;
7265 }
7266
7267 if (chunk_strcasecmp(entry, s) != 0)
7268 continue;
7269
7270 if (pos < 0)
7271 cur--;
7272 else
7273 cur++;
7274
7275 if (cur != pos)
7276 continue;
7277
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007278 if (data_len > out->size)
Emeric Brun87855892012-10-17 17:39:35 +02007279 return -1;
7280
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007281 memcpy(out->area, data_ptr, data_len);
7282 out->data = data_len;
Emeric Brun87855892012-10-17 17:39:35 +02007283 return 1;
7284 }
7285
7286 return 0;
7287
William Lallemandd4f946c2019-12-05 10:26:40 +01007288}
7289
7290/*
7291 * Extract and format the DNS SAN extensions and copy result into a chuink
7292 * Return 0;
7293 */
7294#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
7295static int ssl_sock_get_san_oneline(X509 *cert, struct buffer *out)
7296{
7297 int i;
7298 char *str;
7299 STACK_OF(GENERAL_NAME) *names = NULL;
7300
7301 names = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
7302 if (names) {
7303 for (i = 0; i < sk_GENERAL_NAME_num(names); i++) {
7304 GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i);
7305 if (i > 0)
7306 chunk_appendf(out, ", ");
7307 if (name->type == GEN_DNS) {
7308 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
7309 chunk_appendf(out, "DNS:%s", str);
7310 OPENSSL_free(str);
7311 }
7312 }
7313 }
7314 sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
7315 }
7316 return 0;
Emeric Brun87855892012-10-17 17:39:35 +02007317}
William Lallemandd4f946c2019-12-05 10:26:40 +01007318#endif
Emeric Brun87855892012-10-17 17:39:35 +02007319
Elliot Otchet71f82972020-01-15 08:12:14 -05007320/*
7321 * Extract the DN in the specified format from the X509_NAME and copy result to a chunk.
7322 * Currently supports rfc2253 for returning LDAP V3 DNs.
7323 * Returns 1 if dn entries exist, 0 if no dn entry was found.
7324 */
7325static int
7326ssl_sock_get_dn_formatted(X509_NAME *a, const struct buffer *format, struct buffer *out)
7327{
7328 BIO *bio = NULL;
7329 int ret = 0;
7330 int data_len = 0;
7331
7332 if (chunk_strcmp(format, "rfc2253") == 0) {
7333 bio = BIO_new(BIO_s_mem());
7334 if (bio == NULL)
7335 goto out;
7336
7337 if (X509_NAME_print_ex(bio, a, 0, XN_FLAG_RFC2253) < 0)
7338 goto out;
7339
7340 if ((data_len = BIO_read(bio, out->area, out->size)) <= 0)
7341 goto out;
7342
7343 out->data = data_len;
7344
7345 ret = 1;
7346 }
7347out:
7348 if (bio)
7349 BIO_free(bio);
7350 return ret;
7351}
7352
Emeric Brun87855892012-10-17 17:39:35 +02007353/* Extract and format full DN from a X509_NAME and copy result into a chunk
7354 * Returns 1 if dn entries exits, 0 if no dn entry found or -1 if output is not large enough.
7355 */
7356static int
Willy Tarreau83061a82018-07-13 11:56:34 +02007357ssl_sock_get_dn_oneline(X509_NAME *a, struct buffer *out)
Emeric Brun87855892012-10-17 17:39:35 +02007358{
7359 X509_NAME_ENTRY *ne;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007360 ASN1_OBJECT *obj;
7361 ASN1_STRING *data;
7362 const unsigned char *data_ptr;
7363 int data_len;
Emeric Brun87855892012-10-17 17:39:35 +02007364 int i, n, ln;
7365 int l = 0;
7366 const char *s;
7367 char *p;
7368 char tmp[128];
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007369 int name_count;
7370
7371
7372 name_count = X509_NAME_entry_count(a);
Emeric Brun87855892012-10-17 17:39:35 +02007373
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007374 out->data = 0;
7375 p = out->area;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007376 for (i = 0; i < name_count; i++) {
7377 ne = X509_NAME_get_entry(a, i);
7378 obj = X509_NAME_ENTRY_get_object(ne);
7379 data = X509_NAME_ENTRY_get_data(ne);
7380 data_ptr = ASN1_STRING_get0_data(data);
7381 data_len = ASN1_STRING_length(data);
7382 n = OBJ_obj2nid(obj);
Emeric Brun87855892012-10-17 17:39:35 +02007383 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007384 i2t_ASN1_OBJECT(tmp, sizeof(tmp), obj);
Emeric Brun87855892012-10-17 17:39:35 +02007385 s = tmp;
7386 }
7387 ln = strlen(s);
7388
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007389 l += 1 + ln + 1 + data_len;
Emeric Brun87855892012-10-17 17:39:35 +02007390 if (l > out->size)
7391 return -1;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007392 out->data = l;
Emeric Brun87855892012-10-17 17:39:35 +02007393
7394 *(p++)='/';
7395 memcpy(p, s, ln);
7396 p += ln;
7397 *(p++)='=';
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007398 memcpy(p, data_ptr, data_len);
7399 p += data_len;
Emeric Brun87855892012-10-17 17:39:35 +02007400 }
7401
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007402 if (!out->data)
Emeric Brun87855892012-10-17 17:39:35 +02007403 return 0;
7404
7405 return 1;
7406}
7407
Olivier Houchardab28a322018-12-21 19:45:40 +01007408void ssl_sock_set_alpn(struct connection *conn, const unsigned char *alpn, int len)
7409{
7410#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Christopher Faulet82004142019-09-10 10:12:03 +02007411 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007412
Olivier Houcharde488ea82019-06-28 14:10:33 +02007413 if (!ssl_sock_is_ssl(conn))
7414 return;
Christopher Faulet82004142019-09-10 10:12:03 +02007415 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007416 SSL_set_alpn_protos(ctx->ssl, alpn, len);
Olivier Houchardab28a322018-12-21 19:45:40 +01007417#endif
7418}
7419
Willy Tarreau119a4082016-12-22 21:58:38 +01007420/* Sets advertised SNI for outgoing connections. Please set <hostname> to NULL
7421 * to disable SNI.
7422 */
Willy Tarreau63076412015-07-10 11:33:32 +02007423void ssl_sock_set_servername(struct connection *conn, const char *hostname)
7424{
7425#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Christopher Faulet82004142019-09-10 10:12:03 +02007426 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007427
Willy Tarreau119a4082016-12-22 21:58:38 +01007428 char *prev_name;
7429
Willy Tarreau63076412015-07-10 11:33:32 +02007430 if (!ssl_sock_is_ssl(conn))
7431 return;
Christopher Faulet82004142019-09-10 10:12:03 +02007432 ctx = conn->xprt_ctx;
Willy Tarreau63076412015-07-10 11:33:32 +02007433
Willy Tarreau119a4082016-12-22 21:58:38 +01007434 /* if the SNI changes, we must destroy the reusable context so that a
7435 * new connection will present a new SNI. As an optimization we could
7436 * later imagine having a small cache of ssl_ctx to hold a few SNI per
7437 * server.
7438 */
Olivier Houchard66ab4982019-02-26 18:37:15 +01007439 prev_name = (char *)SSL_get_servername(ctx->ssl, TLSEXT_NAMETYPE_host_name);
Willy Tarreau119a4082016-12-22 21:58:38 +01007440 if ((!prev_name && hostname) ||
7441 (prev_name && (!hostname || strcmp(hostname, prev_name) != 0)))
Olivier Houchard66ab4982019-02-26 18:37:15 +01007442 SSL_set_session(ctx->ssl, NULL);
Willy Tarreau119a4082016-12-22 21:58:38 +01007443
Olivier Houchard66ab4982019-02-26 18:37:15 +01007444 SSL_set_tlsext_host_name(ctx->ssl, hostname);
Willy Tarreau63076412015-07-10 11:33:32 +02007445#endif
7446}
7447
Emeric Brun0abf8362014-06-24 18:26:41 +02007448/* Extract peer certificate's common name into the chunk dest
7449 * Returns
7450 * the len of the extracted common name
7451 * or 0 if no CN found in DN
7452 * or -1 on error case (i.e. no peer certificate)
7453 */
Willy Tarreau83061a82018-07-13 11:56:34 +02007454int ssl_sock_get_remote_common_name(struct connection *conn,
7455 struct buffer *dest)
David Safb76832014-05-08 23:42:08 -04007456{
Christopher Faulet82004142019-09-10 10:12:03 +02007457 struct ssl_sock_ctx *ctx;
David Safb76832014-05-08 23:42:08 -04007458 X509 *crt = NULL;
7459 X509_NAME *name;
David Safb76832014-05-08 23:42:08 -04007460 const char find_cn[] = "CN";
Willy Tarreau83061a82018-07-13 11:56:34 +02007461 const struct buffer find_cn_chunk = {
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007462 .area = (char *)&find_cn,
7463 .data = sizeof(find_cn)-1
David Safb76832014-05-08 23:42:08 -04007464 };
Emeric Brun0abf8362014-06-24 18:26:41 +02007465 int result = -1;
David Safb76832014-05-08 23:42:08 -04007466
7467 if (!ssl_sock_is_ssl(conn))
Emeric Brun0abf8362014-06-24 18:26:41 +02007468 goto out;
Christopher Faulet82004142019-09-10 10:12:03 +02007469 ctx = conn->xprt_ctx;
David Safb76832014-05-08 23:42:08 -04007470
7471 /* SSL_get_peer_certificate, it increase X509 * ref count */
Olivier Houchard66ab4982019-02-26 18:37:15 +01007472 crt = SSL_get_peer_certificate(ctx->ssl);
David Safb76832014-05-08 23:42:08 -04007473 if (!crt)
7474 goto out;
7475
7476 name = X509_get_subject_name(crt);
7477 if (!name)
7478 goto out;
David Safb76832014-05-08 23:42:08 -04007479
Emeric Brun0abf8362014-06-24 18:26:41 +02007480 result = ssl_sock_get_dn_entry(name, &find_cn_chunk, 1, dest);
7481out:
David Safb76832014-05-08 23:42:08 -04007482 if (crt)
7483 X509_free(crt);
7484
7485 return result;
7486}
7487
Dave McCowan328fb582014-07-30 10:39:13 -04007488/* returns 1 if client passed a certificate for this session, 0 if not */
7489int ssl_sock_get_cert_used_sess(struct connection *conn)
7490{
Christopher Faulet82004142019-09-10 10:12:03 +02007491 struct ssl_sock_ctx *ctx;
Dave McCowan328fb582014-07-30 10:39:13 -04007492 X509 *crt = NULL;
7493
7494 if (!ssl_sock_is_ssl(conn))
7495 return 0;
Christopher Faulet82004142019-09-10 10:12:03 +02007496 ctx = conn->xprt_ctx;
Dave McCowan328fb582014-07-30 10:39:13 -04007497
7498 /* SSL_get_peer_certificate, it increase X509 * ref count */
Olivier Houchard66ab4982019-02-26 18:37:15 +01007499 crt = SSL_get_peer_certificate(ctx->ssl);
Dave McCowan328fb582014-07-30 10:39:13 -04007500 if (!crt)
7501 return 0;
7502
7503 X509_free(crt);
7504 return 1;
7505}
7506
7507/* returns 1 if client passed a certificate for this connection, 0 if not */
7508int ssl_sock_get_cert_used_conn(struct connection *conn)
David Safb76832014-05-08 23:42:08 -04007509{
Christopher Faulet82004142019-09-10 10:12:03 +02007510 struct ssl_sock_ctx *ctx;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007511
David Safb76832014-05-08 23:42:08 -04007512 if (!ssl_sock_is_ssl(conn))
7513 return 0;
Christopher Faulet82004142019-09-10 10:12:03 +02007514 ctx = conn->xprt_ctx;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007515 return SSL_SOCK_ST_FL_VERIFY_DONE & ctx->xprt_st ? 1 : 0;
David Safb76832014-05-08 23:42:08 -04007516}
7517
7518/* returns result from SSL verify */
7519unsigned int ssl_sock_get_verify_result(struct connection *conn)
7520{
Christopher Faulet82004142019-09-10 10:12:03 +02007521 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007522
David Safb76832014-05-08 23:42:08 -04007523 if (!ssl_sock_is_ssl(conn))
7524 return (unsigned int)X509_V_ERR_APPLICATION_VERIFICATION;
Christopher Faulet82004142019-09-10 10:12:03 +02007525 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007526 return (unsigned int)SSL_get_verify_result(ctx->ssl);
David Safb76832014-05-08 23:42:08 -04007527}
7528
Willy Tarreau8743f7e2016-12-04 18:44:29 +01007529/* Returns the application layer protocol name in <str> and <len> when known.
7530 * Zero is returned if the protocol name was not found, otherwise non-zero is
7531 * returned. The string is allocated in the SSL context and doesn't have to be
7532 * freed by the caller. NPN is also checked if available since older versions
7533 * of openssl (1.0.1) which are more common in field only support this one.
7534 */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01007535static int ssl_sock_get_alpn(const struct connection *conn, void *xprt_ctx, const char **str, int *len)
Willy Tarreau8743f7e2016-12-04 18:44:29 +01007536{
Olivier Houchard66ab4982019-02-26 18:37:15 +01007537#if defined(TLSEXT_TYPE_application_layer_protocol_negotiation) || \
7538 defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Olivier Houcharde179d0e2019-03-21 18:27:17 +01007539 struct ssl_sock_ctx *ctx = xprt_ctx;
7540 if (!ctx)
Willy Tarreau8743f7e2016-12-04 18:44:29 +01007541 return 0;
7542
7543 *str = NULL;
7544
7545#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Olivier Houchard66ab4982019-02-26 18:37:15 +01007546 SSL_get0_alpn_selected(ctx->ssl, (const unsigned char **)str, (unsigned *)len);
Willy Tarreau8743f7e2016-12-04 18:44:29 +01007547 if (*str)
7548 return 1;
7549#endif
Bernard Spil13c53f82018-02-15 13:34:58 +01007550#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007551 SSL_get0_next_proto_negotiated(ctx->ssl, (const unsigned char **)str, (unsigned *)len);
Willy Tarreau8743f7e2016-12-04 18:44:29 +01007552 if (*str)
7553 return 1;
7554#endif
Olivier Houcharde179d0e2019-03-21 18:27:17 +01007555#endif
Willy Tarreau8743f7e2016-12-04 18:44:29 +01007556 return 0;
7557}
7558
Willy Tarreau7875d092012-09-10 08:20:03 +02007559/***** Below are some sample fetching functions for ACL/patterns *****/
7560
Olivier Houchardccaa7de2017-10-02 11:51:03 +02007561static int
7562smp_fetch_ssl_fc_has_early(const struct arg *args, struct sample *smp, const char *kw, void *private)
7563{
7564 struct connection *conn;
7565
7566 conn = objt_conn(smp->sess->origin);
7567 if (!conn || conn->xprt != &ssl_sock)
7568 return 0;
7569
7570 smp->flags = 0;
7571 smp->data.type = SMP_T_BOOL;
Emmanuel Hocdetc9858012019-08-07 14:44:49 +02007572#ifdef OPENSSL_IS_BORINGSSL
7573 {
7574 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
7575 smp->data.u.sint = (SSL_in_early_data(ctx->ssl) &&
7576 SSL_early_data_accepted(ctx->ssl));
7577 }
7578#else
Olivier Houchard25ae45a2017-11-29 19:51:19 +01007579 smp->data.u.sint = ((conn->flags & CO_FL_EARLY_DATA) &&
Olivier Houchard220a26c2020-01-23 14:57:36 +01007580 (conn->flags & (CO_FL_EARLY_SSL_HS | CO_FL_SSL_WAIT_HS))) ? 1 : 0;
Emmanuel Hocdetc9858012019-08-07 14:44:49 +02007581#endif
Olivier Houchardccaa7de2017-10-02 11:51:03 +02007582 return 1;
7583}
7584
Emeric Brune64aef12012-09-21 13:15:06 +02007585/* boolean, returns true if client cert was present */
7586static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007587smp_fetch_ssl_fc_has_crt(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brune64aef12012-09-21 13:15:06 +02007588{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007589 struct connection *conn;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007590 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007591
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007592 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007593 if (!conn || conn->xprt != &ssl_sock)
Emeric Brune64aef12012-09-21 13:15:06 +02007594 return 0;
7595
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007596 ctx = conn->xprt_ctx;
7597
Willy Tarreau911db9b2020-01-23 16:27:54 +01007598 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Brune64aef12012-09-21 13:15:06 +02007599 smp->flags |= SMP_F_MAY_CHANGE;
7600 return 0;
7601 }
7602
7603 smp->flags = 0;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007604 smp->data.type = SMP_T_BOOL;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007605 smp->data.u.sint = SSL_SOCK_ST_FL_VERIFY_DONE & ctx->xprt_st ? 1 : 0;
Emeric Brune64aef12012-09-21 13:15:06 +02007606
7607 return 1;
7608}
7609
Emeric Brun43e79582014-10-29 19:03:26 +01007610/* binary, returns a certificate in a binary chunk (der/raw).
7611 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7612 * should be use.
7613 */
7614static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007615smp_fetch_ssl_x_der(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun43e79582014-10-29 19:03:26 +01007616{
7617 int cert_peer = (kw[4] == 'c') ? 1 : 0;
7618 X509 *crt = NULL;
7619 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02007620 struct buffer *smp_trash;
Emeric Brun43e79582014-10-29 19:03:26 +01007621 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007622 struct ssl_sock_ctx *ctx;
Emeric Brun43e79582014-10-29 19:03:26 +01007623
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007624 conn = objt_conn(smp->sess->origin);
Emeric Brun43e79582014-10-29 19:03:26 +01007625 if (!conn || conn->xprt != &ssl_sock)
7626 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007627 ctx = conn->xprt_ctx;
Emeric Brun43e79582014-10-29 19:03:26 +01007628
Willy Tarreau911db9b2020-01-23 16:27:54 +01007629 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Brun43e79582014-10-29 19:03:26 +01007630 smp->flags |= SMP_F_MAY_CHANGE;
7631 return 0;
7632 }
7633
7634 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007635 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brun43e79582014-10-29 19:03:26 +01007636 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007637 crt = SSL_get_certificate(ctx->ssl);
Emeric Brun43e79582014-10-29 19:03:26 +01007638
7639 if (!crt)
7640 goto out;
7641
7642 smp_trash = get_trash_chunk();
7643 if (ssl_sock_crt2der(crt, smp_trash) <= 0)
7644 goto out;
7645
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007646 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007647 smp->data.type = SMP_T_BIN;
Emeric Brun43e79582014-10-29 19:03:26 +01007648 ret = 1;
7649out:
7650 /* SSL_get_peer_certificate, it increase X509 * ref count */
7651 if (cert_peer && crt)
7652 X509_free(crt);
7653 return ret;
7654}
7655
Emeric Brunba841a12014-04-30 17:05:08 +02007656/* binary, returns serial of certificate in a binary chunk.
7657 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7658 * should be use.
7659 */
Willy Tarreau8d598402012-10-22 17:58:39 +02007660static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007661smp_fetch_ssl_x_serial(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau8d598402012-10-22 17:58:39 +02007662{
Emeric Brunba841a12014-04-30 17:05:08 +02007663 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Willy Tarreau8d598402012-10-22 17:58:39 +02007664 X509 *crt = NULL;
7665 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02007666 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007667 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007668 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007669
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007670 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007671 if (!conn || conn->xprt != &ssl_sock)
Willy Tarreau8d598402012-10-22 17:58:39 +02007672 return 0;
7673
Olivier Houchard66ab4982019-02-26 18:37:15 +01007674 ctx = conn->xprt_ctx;
7675
Willy Tarreau911db9b2020-01-23 16:27:54 +01007676 if (conn->flags & CO_FL_WAIT_XPRT) {
Willy Tarreau8d598402012-10-22 17:58:39 +02007677 smp->flags |= SMP_F_MAY_CHANGE;
7678 return 0;
7679 }
7680
Emeric Brunba841a12014-04-30 17:05:08 +02007681 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007682 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007683 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007684 crt = SSL_get_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007685
Willy Tarreau8d598402012-10-22 17:58:39 +02007686 if (!crt)
7687 goto out;
7688
Willy Tarreau47ca5452012-12-23 20:22:19 +01007689 smp_trash = get_trash_chunk();
Willy Tarreau8d598402012-10-22 17:58:39 +02007690 if (ssl_sock_get_serial(crt, smp_trash) <= 0)
7691 goto out;
7692
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007693 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007694 smp->data.type = SMP_T_BIN;
Willy Tarreau8d598402012-10-22 17:58:39 +02007695 ret = 1;
7696out:
Emeric Brunba841a12014-04-30 17:05:08 +02007697 /* SSL_get_peer_certificate, it increase X509 * ref count */
7698 if (cert_peer && crt)
Willy Tarreau8d598402012-10-22 17:58:39 +02007699 X509_free(crt);
7700 return ret;
7701}
Emeric Brune64aef12012-09-21 13:15:06 +02007702
Emeric Brunba841a12014-04-30 17:05:08 +02007703/* binary, returns the client certificate's SHA-1 fingerprint (SHA-1 hash of DER-encoded certificate) in a binary chunk.
7704 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7705 * should be use.
7706 */
James Votha051b4a2013-05-14 20:37:59 +02007707static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007708smp_fetch_ssl_x_sha1(const struct arg *args, struct sample *smp, const char *kw, void *private)
James Votha051b4a2013-05-14 20:37:59 +02007709{
Emeric Brunba841a12014-04-30 17:05:08 +02007710 int cert_peer = (kw[4] == 'c') ? 1 : 0;
James Votha051b4a2013-05-14 20:37:59 +02007711 X509 *crt = NULL;
7712 const EVP_MD *digest;
7713 int ret = 0;
Willy Tarreau105599c2020-02-25 08:59:23 +01007714 unsigned int len = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02007715 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007716 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007717 struct ssl_sock_ctx *ctx;
James Votha051b4a2013-05-14 20:37:59 +02007718
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007719 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007720 if (!conn || conn->xprt != &ssl_sock)
7721 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007722 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007723
Willy Tarreau911db9b2020-01-23 16:27:54 +01007724 if (conn->flags & CO_FL_WAIT_XPRT) {
James Votha051b4a2013-05-14 20:37:59 +02007725 smp->flags |= SMP_F_MAY_CHANGE;
7726 return 0;
7727 }
7728
Emeric Brunba841a12014-04-30 17:05:08 +02007729 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007730 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007731 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007732 crt = SSL_get_certificate(ctx->ssl);
James Votha051b4a2013-05-14 20:37:59 +02007733 if (!crt)
7734 goto out;
7735
7736 smp_trash = get_trash_chunk();
7737 digest = EVP_sha1();
Willy Tarreau105599c2020-02-25 08:59:23 +01007738 X509_digest(crt, digest, (unsigned char *) smp_trash->area, &len);
7739 smp_trash->data = len;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007740 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007741 smp->data.type = SMP_T_BIN;
James Votha051b4a2013-05-14 20:37:59 +02007742 ret = 1;
7743out:
Emeric Brunba841a12014-04-30 17:05:08 +02007744 /* SSL_get_peer_certificate, it increase X509 * ref count */
7745 if (cert_peer && crt)
James Votha051b4a2013-05-14 20:37:59 +02007746 X509_free(crt);
7747 return ret;
7748}
7749
Emeric Brunba841a12014-04-30 17:05:08 +02007750/* string, returns certificate's notafter date in ASN1_UTCTIME format.
7751 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7752 * should be use.
7753 */
Emeric Brunce5ad802012-10-22 14:11:22 +02007754static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007755smp_fetch_ssl_x_notafter(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunce5ad802012-10-22 14:11:22 +02007756{
Emeric Brunba841a12014-04-30 17:05:08 +02007757 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brunce5ad802012-10-22 14:11:22 +02007758 X509 *crt = NULL;
7759 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02007760 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007761 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007762 struct ssl_sock_ctx *ctx;
Emeric Brunce5ad802012-10-22 14:11:22 +02007763
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007764 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007765 if (!conn || conn->xprt != &ssl_sock)
7766 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007767 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007768
Willy Tarreau911db9b2020-01-23 16:27:54 +01007769 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Brunce5ad802012-10-22 14:11:22 +02007770 smp->flags |= SMP_F_MAY_CHANGE;
7771 return 0;
7772 }
7773
Emeric Brunba841a12014-04-30 17:05:08 +02007774 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007775 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007776 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007777 crt = SSL_get_certificate(ctx->ssl);
Emeric Brunce5ad802012-10-22 14:11:22 +02007778 if (!crt)
7779 goto out;
7780
Willy Tarreau47ca5452012-12-23 20:22:19 +01007781 smp_trash = get_trash_chunk();
Rosen Penev68185952018-12-14 08:47:02 -08007782 if (ssl_sock_get_time(X509_getm_notAfter(crt), smp_trash) <= 0)
Emeric Brunce5ad802012-10-22 14:11:22 +02007783 goto out;
7784
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007785 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007786 smp->data.type = SMP_T_STR;
Emeric Brunce5ad802012-10-22 14:11:22 +02007787 ret = 1;
7788out:
Emeric Brunba841a12014-04-30 17:05:08 +02007789 /* SSL_get_peer_certificate, it increase X509 * ref count */
7790 if (cert_peer && crt)
Emeric Brunce5ad802012-10-22 14:11:22 +02007791 X509_free(crt);
7792 return ret;
7793}
7794
Emeric Brunba841a12014-04-30 17:05:08 +02007795/* string, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. of certificate's issuer
7796 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7797 * should be use.
7798 */
Emeric Brun87855892012-10-17 17:39:35 +02007799static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007800smp_fetch_ssl_x_i_dn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun87855892012-10-17 17:39:35 +02007801{
Emeric Brunba841a12014-04-30 17:05:08 +02007802 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun87855892012-10-17 17:39:35 +02007803 X509 *crt = NULL;
7804 X509_NAME *name;
7805 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02007806 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007807 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007808 struct ssl_sock_ctx *ctx;
Emeric Brun87855892012-10-17 17:39:35 +02007809
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007810 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007811 if (!conn || conn->xprt != &ssl_sock)
7812 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007813 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007814
Willy Tarreau911db9b2020-01-23 16:27:54 +01007815 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Brun87855892012-10-17 17:39:35 +02007816 smp->flags |= SMP_F_MAY_CHANGE;
7817 return 0;
7818 }
7819
Emeric Brunba841a12014-04-30 17:05:08 +02007820 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007821 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007822 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007823 crt = SSL_get_certificate(ctx->ssl);
Emeric Brun87855892012-10-17 17:39:35 +02007824 if (!crt)
7825 goto out;
7826
7827 name = X509_get_issuer_name(crt);
7828 if (!name)
7829 goto out;
7830
Willy Tarreau47ca5452012-12-23 20:22:19 +01007831 smp_trash = get_trash_chunk();
Elliot Otchet71f82972020-01-15 08:12:14 -05007832 if (args && args[0].type == ARGT_STR && args[0].data.str.data > 0) {
Emeric Brun87855892012-10-17 17:39:35 +02007833 int pos = 1;
7834
7835 if (args[1].type == ARGT_SINT)
7836 pos = args[1].data.sint;
Emeric Brun87855892012-10-17 17:39:35 +02007837
7838 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
7839 goto out;
7840 }
Elliot Otchet71f82972020-01-15 08:12:14 -05007841 else if (args && args[2].type == ARGT_STR && args[2].data.str.data > 0) {
7842 if (ssl_sock_get_dn_formatted(name, &args[2].data.str, smp_trash) <= 0)
7843 goto out;
7844 }
Emeric Brun87855892012-10-17 17:39:35 +02007845 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
7846 goto out;
7847
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007848 smp->data.type = SMP_T_STR;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007849 smp->data.u.str = *smp_trash;
Emeric Brun87855892012-10-17 17:39:35 +02007850 ret = 1;
7851out:
Emeric Brunba841a12014-04-30 17:05:08 +02007852 /* SSL_get_peer_certificate, it increase X509 * ref count */
7853 if (cert_peer && crt)
Emeric Brun87855892012-10-17 17:39:35 +02007854 X509_free(crt);
7855 return ret;
7856}
7857
Emeric Brunba841a12014-04-30 17:05:08 +02007858/* string, returns notbefore date in ASN1_UTCTIME format.
7859 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7860 * should be use.
7861 */
Emeric Brunce5ad802012-10-22 14:11:22 +02007862static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007863smp_fetch_ssl_x_notbefore(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunce5ad802012-10-22 14:11:22 +02007864{
Emeric Brunba841a12014-04-30 17:05:08 +02007865 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brunce5ad802012-10-22 14:11:22 +02007866 X509 *crt = NULL;
7867 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02007868 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007869 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007870 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007871
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007872 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007873 if (!conn || conn->xprt != &ssl_sock)
Emeric Brunce5ad802012-10-22 14:11:22 +02007874 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007875 ctx = conn->xprt_ctx;
Emeric Brunce5ad802012-10-22 14:11:22 +02007876
Willy Tarreau911db9b2020-01-23 16:27:54 +01007877 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Brunce5ad802012-10-22 14:11:22 +02007878 smp->flags |= SMP_F_MAY_CHANGE;
7879 return 0;
7880 }
7881
Emeric Brunba841a12014-04-30 17:05:08 +02007882 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007883 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007884 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007885 crt = SSL_get_certificate(ctx->ssl);
Emeric Brunce5ad802012-10-22 14:11:22 +02007886 if (!crt)
7887 goto out;
7888
Willy Tarreau47ca5452012-12-23 20:22:19 +01007889 smp_trash = get_trash_chunk();
Rosen Penev68185952018-12-14 08:47:02 -08007890 if (ssl_sock_get_time(X509_getm_notBefore(crt), smp_trash) <= 0)
Emeric Brunce5ad802012-10-22 14:11:22 +02007891 goto out;
7892
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007893 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007894 smp->data.type = SMP_T_STR;
Emeric Brunce5ad802012-10-22 14:11:22 +02007895 ret = 1;
7896out:
Emeric Brunba841a12014-04-30 17:05:08 +02007897 /* SSL_get_peer_certificate, it increase X509 * ref count */
7898 if (cert_peer && crt)
Emeric Brunce5ad802012-10-22 14:11:22 +02007899 X509_free(crt);
7900 return ret;
7901}
7902
Emeric Brunba841a12014-04-30 17:05:08 +02007903/* string, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. of certificate's subject
7904 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7905 * should be use.
7906 */
Emeric Brun87855892012-10-17 17:39:35 +02007907static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007908smp_fetch_ssl_x_s_dn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun87855892012-10-17 17:39:35 +02007909{
Emeric Brunba841a12014-04-30 17:05:08 +02007910 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun87855892012-10-17 17:39:35 +02007911 X509 *crt = NULL;
7912 X509_NAME *name;
7913 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02007914 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007915 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007916 struct ssl_sock_ctx *ctx;
Emeric Brun87855892012-10-17 17:39:35 +02007917
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007918 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007919 if (!conn || conn->xprt != &ssl_sock)
7920 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007921 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007922
Willy Tarreau911db9b2020-01-23 16:27:54 +01007923 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Brun87855892012-10-17 17:39:35 +02007924 smp->flags |= SMP_F_MAY_CHANGE;
7925 return 0;
7926 }
7927
Emeric Brunba841a12014-04-30 17:05:08 +02007928 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007929 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007930 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007931 crt = SSL_get_certificate(ctx->ssl);
Emeric Brun87855892012-10-17 17:39:35 +02007932 if (!crt)
7933 goto out;
7934
7935 name = X509_get_subject_name(crt);
7936 if (!name)
7937 goto out;
7938
Willy Tarreau47ca5452012-12-23 20:22:19 +01007939 smp_trash = get_trash_chunk();
Elliot Otchet71f82972020-01-15 08:12:14 -05007940 if (args && args[0].type == ARGT_STR && args[0].data.str.data > 0) {
Emeric Brun87855892012-10-17 17:39:35 +02007941 int pos = 1;
7942
7943 if (args[1].type == ARGT_SINT)
7944 pos = args[1].data.sint;
Emeric Brun87855892012-10-17 17:39:35 +02007945
7946 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
7947 goto out;
7948 }
Elliot Otchet71f82972020-01-15 08:12:14 -05007949 else if (args && args[2].type == ARGT_STR && args[2].data.str.data > 0) {
7950 if (ssl_sock_get_dn_formatted(name, &args[2].data.str, smp_trash) <= 0)
7951 goto out;
7952 }
Emeric Brun87855892012-10-17 17:39:35 +02007953 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
7954 goto out;
7955
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007956 smp->data.type = SMP_T_STR;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007957 smp->data.u.str = *smp_trash;
Emeric Brun87855892012-10-17 17:39:35 +02007958 ret = 1;
7959out:
Emeric Brunba841a12014-04-30 17:05:08 +02007960 /* SSL_get_peer_certificate, it increase X509 * ref count */
7961 if (cert_peer && crt)
Emeric Brun87855892012-10-17 17:39:35 +02007962 X509_free(crt);
7963 return ret;
7964}
Emeric Brun9143d372012-12-20 15:44:16 +01007965
7966/* integer, returns true if current session use a client certificate */
7967static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007968smp_fetch_ssl_c_used(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun9143d372012-12-20 15:44:16 +01007969{
7970 X509 *crt;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007971 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007972 struct ssl_sock_ctx *ctx;
Emeric Brun9143d372012-12-20 15:44:16 +01007973
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007974 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007975 if (!conn || conn->xprt != &ssl_sock)
7976 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007977 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007978
Willy Tarreau911db9b2020-01-23 16:27:54 +01007979 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Brun9143d372012-12-20 15:44:16 +01007980 smp->flags |= SMP_F_MAY_CHANGE;
7981 return 0;
7982 }
7983
7984 /* SSL_get_peer_certificate returns a ptr on allocated X509 struct */
Olivier Houchard66ab4982019-02-26 18:37:15 +01007985 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brun9143d372012-12-20 15:44:16 +01007986 if (crt) {
7987 X509_free(crt);
7988 }
7989
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007990 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007991 smp->data.u.sint = (crt != NULL);
Emeric Brun9143d372012-12-20 15:44:16 +01007992 return 1;
7993}
7994
Emeric Brunba841a12014-04-30 17:05:08 +02007995/* integer, returns the certificate version
7996 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7997 * should be use.
7998 */
Emeric Bruna7359fd2012-10-17 15:03:11 +02007999static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008000smp_fetch_ssl_x_version(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Bruna7359fd2012-10-17 15:03:11 +02008001{
Emeric Brunba841a12014-04-30 17:05:08 +02008002 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Bruna7359fd2012-10-17 15:03:11 +02008003 X509 *crt;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008004 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008005 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008006
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02008007 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008008 if (!conn || conn->xprt != &ssl_sock)
Emeric Bruna7359fd2012-10-17 15:03:11 +02008009 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008010 ctx = conn->xprt_ctx;
Emeric Bruna7359fd2012-10-17 15:03:11 +02008011
Willy Tarreau911db9b2020-01-23 16:27:54 +01008012 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Bruna7359fd2012-10-17 15:03:11 +02008013 smp->flags |= SMP_F_MAY_CHANGE;
8014 return 0;
8015 }
8016
Emeric Brunba841a12014-04-30 17:05:08 +02008017 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01008018 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02008019 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01008020 crt = SSL_get_certificate(ctx->ssl);
Emeric Bruna7359fd2012-10-17 15:03:11 +02008021 if (!crt)
8022 return 0;
8023
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02008024 smp->data.u.sint = (unsigned int)(1 + X509_get_version(crt));
Emeric Brunba841a12014-04-30 17:05:08 +02008025 /* SSL_get_peer_certificate increase X509 * ref count */
8026 if (cert_peer)
8027 X509_free(crt);
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008028 smp->data.type = SMP_T_SINT;
Emeric Bruna7359fd2012-10-17 15:03:11 +02008029
8030 return 1;
8031}
8032
Emeric Brunba841a12014-04-30 17:05:08 +02008033/* string, returns the certificate's signature algorithm.
8034 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
8035 * should be use.
8036 */
Emeric Brun7f56e742012-10-19 18:15:40 +02008037static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008038smp_fetch_ssl_x_sig_alg(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun7f56e742012-10-19 18:15:40 +02008039{
Emeric Brunba841a12014-04-30 17:05:08 +02008040 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun7f56e742012-10-19 18:15:40 +02008041 X509 *crt;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02008042 __OPENSSL_110_CONST__ ASN1_OBJECT *algorithm;
Emeric Brun7f56e742012-10-19 18:15:40 +02008043 int nid;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008044 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008045 struct ssl_sock_ctx *ctx;
Emeric Brun7f56e742012-10-19 18:15:40 +02008046
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02008047 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008048 if (!conn || conn->xprt != &ssl_sock)
8049 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008050 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008051
Willy Tarreau911db9b2020-01-23 16:27:54 +01008052 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Brun7f56e742012-10-19 18:15:40 +02008053 smp->flags |= SMP_F_MAY_CHANGE;
8054 return 0;
8055 }
8056
Emeric Brunba841a12014-04-30 17:05:08 +02008057 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01008058 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02008059 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01008060 crt = SSL_get_certificate(ctx->ssl);
Emeric Brun7f56e742012-10-19 18:15:40 +02008061 if (!crt)
8062 return 0;
8063
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02008064 X509_ALGOR_get0(&algorithm, NULL, NULL, X509_get0_tbs_sigalg(crt));
8065 nid = OBJ_obj2nid(algorithm);
Emeric Brun7f56e742012-10-19 18:15:40 +02008066
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008067 smp->data.u.str.area = (char *)OBJ_nid2sn(nid);
8068 if (!smp->data.u.str.area) {
Emeric Brunba841a12014-04-30 17:05:08 +02008069 /* SSL_get_peer_certificate increase X509 * ref count */
8070 if (cert_peer)
8071 X509_free(crt);
Emeric Brun7f56e742012-10-19 18:15:40 +02008072 return 0;
Emeric Brun9bf3ba22013-10-07 14:31:44 +02008073 }
Emeric Brun7f56e742012-10-19 18:15:40 +02008074
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008075 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008076 smp->flags |= SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008077 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brunba841a12014-04-30 17:05:08 +02008078 /* SSL_get_peer_certificate increase X509 * ref count */
8079 if (cert_peer)
8080 X509_free(crt);
Emeric Brun7f56e742012-10-19 18:15:40 +02008081
8082 return 1;
8083}
8084
Emeric Brunba841a12014-04-30 17:05:08 +02008085/* string, returns the certificate's key algorithm.
8086 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
8087 * should be use.
8088 */
Emeric Brun521a0112012-10-22 12:22:55 +02008089static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008090smp_fetch_ssl_x_key_alg(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun521a0112012-10-22 12:22:55 +02008091{
Emeric Brunba841a12014-04-30 17:05:08 +02008092 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun521a0112012-10-22 12:22:55 +02008093 X509 *crt;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02008094 ASN1_OBJECT *algorithm;
Emeric Brun521a0112012-10-22 12:22:55 +02008095 int nid;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008096 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008097 struct ssl_sock_ctx *ctx;
Emeric Brun521a0112012-10-22 12:22:55 +02008098
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02008099 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008100 if (!conn || conn->xprt != &ssl_sock)
8101 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008102 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008103
Willy Tarreau911db9b2020-01-23 16:27:54 +01008104 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Brun521a0112012-10-22 12:22:55 +02008105 smp->flags |= SMP_F_MAY_CHANGE;
8106 return 0;
8107 }
8108
Emeric Brunba841a12014-04-30 17:05:08 +02008109 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01008110 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02008111 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01008112 crt = SSL_get_certificate(ctx->ssl);
Emeric Brun521a0112012-10-22 12:22:55 +02008113 if (!crt)
8114 return 0;
8115
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02008116 X509_PUBKEY_get0_param(&algorithm, NULL, NULL, NULL, X509_get_X509_PUBKEY(crt));
8117 nid = OBJ_obj2nid(algorithm);
Emeric Brun521a0112012-10-22 12:22:55 +02008118
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008119 smp->data.u.str.area = (char *)OBJ_nid2sn(nid);
8120 if (!smp->data.u.str.area) {
Emeric Brunba841a12014-04-30 17:05:08 +02008121 /* SSL_get_peer_certificate increase X509 * ref count */
8122 if (cert_peer)
8123 X509_free(crt);
Emeric Brun521a0112012-10-22 12:22:55 +02008124 return 0;
Emeric Brun9bf3ba22013-10-07 14:31:44 +02008125 }
Emeric Brun521a0112012-10-22 12:22:55 +02008126
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008127 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008128 smp->flags |= SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008129 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brunba841a12014-04-30 17:05:08 +02008130 if (cert_peer)
8131 X509_free(crt);
Emeric Brun521a0112012-10-22 12:22:55 +02008132
8133 return 1;
8134}
8135
Emeric Brun645ae792014-04-30 14:21:06 +02008136/* boolean, returns true if front conn. transport layer is SSL.
8137 * This function is also usable on backend conn if the fetch keyword 5th
8138 * char is 'b'.
8139 */
Willy Tarreau7875d092012-09-10 08:20:03 +02008140static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008141smp_fetch_ssl_fc(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02008142{
Emeric Bruneb8def92018-02-19 15:59:48 +01008143 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
8144 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008145
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008146 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02008147 smp->data.u.sint = (conn && conn->xprt == &ssl_sock);
Willy Tarreau7875d092012-09-10 08:20:03 +02008148 return 1;
8149}
8150
Emeric Brun2525b6b2012-10-18 15:59:43 +02008151/* boolean, returns true if client present a SNI */
Willy Tarreau7875d092012-09-10 08:20:03 +02008152static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008153smp_fetch_ssl_fc_has_sni(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02008154{
8155#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02008156 struct connection *conn = objt_conn(smp->sess->origin);
Olivier Houchard66ab4982019-02-26 18:37:15 +01008157 struct ssl_sock_ctx *ctx = conn ? conn->xprt_ctx : NULL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008158
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008159 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02008160 smp->data.u.sint = (conn && conn->xprt == &ssl_sock) &&
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008161 conn->xprt_ctx &&
Olivier Houchard66ab4982019-02-26 18:37:15 +01008162 SSL_get_servername(ctx->ssl, TLSEXT_NAMETYPE_host_name) != NULL;
Willy Tarreau7875d092012-09-10 08:20:03 +02008163 return 1;
8164#else
8165 return 0;
8166#endif
8167}
8168
Emeric Brun74f7ffa2018-02-19 16:14:12 +01008169/* boolean, returns true if client session has been resumed.
8170 * This function is also usable on backend conn if the fetch keyword 5th
8171 * char is 'b'.
8172 */
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02008173static int
8174smp_fetch_ssl_fc_is_resumed(const struct arg *args, struct sample *smp, const char *kw, void *private)
8175{
Emeric Brun74f7ffa2018-02-19 16:14:12 +01008176 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
8177 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008178 struct ssl_sock_ctx *ctx = conn ? conn->xprt_ctx : NULL;
Emeric Brun74f7ffa2018-02-19 16:14:12 +01008179
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02008180
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008181 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02008182 smp->data.u.sint = (conn && conn->xprt == &ssl_sock) &&
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02008183 conn->xprt_ctx &&
Olivier Houchard66ab4982019-02-26 18:37:15 +01008184 SSL_session_reused(ctx->ssl);
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02008185 return 1;
8186}
8187
Emeric Brun645ae792014-04-30 14:21:06 +02008188/* string, returns the used cipher if front conn. transport layer is SSL.
8189 * This function is also usable on backend conn if the fetch keyword 5th
8190 * char is 'b'.
8191 */
Emeric Brun589fcad2012-10-16 14:13:26 +02008192static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008193smp_fetch_ssl_fc_cipher(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02008194{
Emeric Bruneb8def92018-02-19 15:59:48 +01008195 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
8196 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008197 struct ssl_sock_ctx *ctx;
Emeric Brun589fcad2012-10-16 14:13:26 +02008198
Willy Tarreaube508f12016-03-10 11:47:01 +01008199 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008200 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02008201 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008202 ctx = conn->xprt_ctx;
Emeric Brun589fcad2012-10-16 14:13:26 +02008203
Olivier Houchard66ab4982019-02-26 18:37:15 +01008204 smp->data.u.str.area = (char *)SSL_get_cipher_name(ctx->ssl);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008205 if (!smp->data.u.str.area)
Emeric Brun589fcad2012-10-16 14:13:26 +02008206 return 0;
8207
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008208 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008209 smp->flags |= SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008210 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brun589fcad2012-10-16 14:13:26 +02008211
8212 return 1;
8213}
8214
Emeric Brun645ae792014-04-30 14:21:06 +02008215/* integer, returns the algoritm's keysize if front conn. transport layer
8216 * is SSL.
8217 * This function is also usable on backend conn if the fetch keyword 5th
8218 * char is 'b'.
8219 */
Emeric Brun589fcad2012-10-16 14:13:26 +02008220static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008221smp_fetch_ssl_fc_alg_keysize(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02008222{
Emeric Bruneb8def92018-02-19 15:59:48 +01008223 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
8224 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008225 struct ssl_sock_ctx *ctx;
Willy Tarreaue237fe12016-03-10 17:05:28 +01008226 int sint;
Willy Tarreaube508f12016-03-10 11:47:01 +01008227
Emeric Brun589fcad2012-10-16 14:13:26 +02008228 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008229 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02008230 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008231 ctx = conn->xprt_ctx;
Emeric Brun589fcad2012-10-16 14:13:26 +02008232
Olivier Houchard66ab4982019-02-26 18:37:15 +01008233 if (!SSL_get_cipher_bits(ctx->ssl, &sint))
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008234 return 0;
8235
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02008236 smp->data.u.sint = sint;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008237 smp->data.type = SMP_T_SINT;
Emeric Brun589fcad2012-10-16 14:13:26 +02008238
8239 return 1;
8240}
8241
Emeric Brun645ae792014-04-30 14:21:06 +02008242/* integer, returns the used keysize if front conn. transport layer is SSL.
8243 * This function is also usable on backend conn if the fetch keyword 5th
8244 * char is 'b'.
8245 */
Emeric Brun589fcad2012-10-16 14:13:26 +02008246static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008247smp_fetch_ssl_fc_use_keysize(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02008248{
Emeric Bruneb8def92018-02-19 15:59:48 +01008249 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
8250 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008251 struct ssl_sock_ctx *ctx;
Willy Tarreaube508f12016-03-10 11:47:01 +01008252
Emeric Brun589fcad2012-10-16 14:13:26 +02008253 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008254 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8255 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008256 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008257
Olivier Houchard66ab4982019-02-26 18:37:15 +01008258 smp->data.u.sint = (unsigned int)SSL_get_cipher_bits(ctx->ssl, NULL);
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02008259 if (!smp->data.u.sint)
Emeric Brun589fcad2012-10-16 14:13:26 +02008260 return 0;
8261
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008262 smp->data.type = SMP_T_SINT;
Emeric Brun589fcad2012-10-16 14:13:26 +02008263
8264 return 1;
8265}
8266
Bernard Spil13c53f82018-02-15 13:34:58 +01008267#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Willy Tarreau7875d092012-09-10 08:20:03 +02008268static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008269smp_fetch_ssl_fc_npn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreaua33c6542012-10-15 13:19:06 +02008270{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008271 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008272 struct ssl_sock_ctx *ctx;
Willy Tarreau105599c2020-02-25 08:59:23 +01008273 unsigned int len = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008274
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008275 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008276 smp->data.type = SMP_T_STR;
Willy Tarreaua33c6542012-10-15 13:19:06 +02008277
Olivier Houchard6b77f492018-11-22 18:18:29 +01008278 conn = (kw[4] != 'b' ) ? objt_conn(smp->sess->origin) :
8279 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008280 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8281 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008282 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008283
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008284 smp->data.u.str.area = NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008285 SSL_get0_next_proto_negotiated(ctx->ssl,
Willy Tarreau105599c2020-02-25 08:59:23 +01008286 (const unsigned char **)&smp->data.u.str.area,
8287 &len);
Willy Tarreaua33c6542012-10-15 13:19:06 +02008288
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008289 if (!smp->data.u.str.area)
Willy Tarreaua33c6542012-10-15 13:19:06 +02008290 return 0;
8291
Willy Tarreau105599c2020-02-25 08:59:23 +01008292 smp->data.u.str.data = len;
Willy Tarreaua33c6542012-10-15 13:19:06 +02008293 return 1;
Willy Tarreaua33c6542012-10-15 13:19:06 +02008294}
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02008295#endif
Willy Tarreaua33c6542012-10-15 13:19:06 +02008296
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01008297#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02008298static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008299smp_fetch_ssl_fc_alpn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreauab861d32013-04-02 02:30:41 +02008300{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008301 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008302 struct ssl_sock_ctx *ctx;
Willy Tarreau105599c2020-02-25 08:59:23 +01008303 unsigned int len = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008304
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008305 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008306 smp->data.type = SMP_T_STR;
Willy Tarreauab861d32013-04-02 02:30:41 +02008307
Olivier Houchard6b77f492018-11-22 18:18:29 +01008308 conn = (kw[4] != 'b' ) ? objt_conn(smp->sess->origin) :
8309 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
8310
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008311 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Willy Tarreauab861d32013-04-02 02:30:41 +02008312 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008313 ctx = conn->xprt_ctx;
Willy Tarreauab861d32013-04-02 02:30:41 +02008314
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008315 smp->data.u.str.area = NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008316 SSL_get0_alpn_selected(ctx->ssl,
Willy Tarreau105599c2020-02-25 08:59:23 +01008317 (const unsigned char **)&smp->data.u.str.area,
8318 &len);
Willy Tarreauab861d32013-04-02 02:30:41 +02008319
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008320 if (!smp->data.u.str.area)
Willy Tarreauab861d32013-04-02 02:30:41 +02008321 return 0;
8322
Willy Tarreau105599c2020-02-25 08:59:23 +01008323 smp->data.u.str.data = len;
Willy Tarreauab861d32013-04-02 02:30:41 +02008324 return 1;
8325}
8326#endif
8327
Emeric Brun645ae792014-04-30 14:21:06 +02008328/* string, returns the used protocol if front conn. transport layer is SSL.
8329 * This function is also usable on backend conn if the fetch keyword 5th
8330 * char is 'b'.
8331 */
Willy Tarreaua33c6542012-10-15 13:19:06 +02008332static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008333smp_fetch_ssl_fc_protocol(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02008334{
Emeric Bruneb8def92018-02-19 15:59:48 +01008335 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
8336 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008337 struct ssl_sock_ctx *ctx;
Willy Tarreaube508f12016-03-10 11:47:01 +01008338
Emeric Brun589fcad2012-10-16 14:13:26 +02008339 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008340 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8341 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008342 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008343
Olivier Houchard66ab4982019-02-26 18:37:15 +01008344 smp->data.u.str.area = (char *)SSL_get_version(ctx->ssl);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008345 if (!smp->data.u.str.area)
Emeric Brun589fcad2012-10-16 14:13:26 +02008346 return 0;
8347
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008348 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008349 smp->flags = SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008350 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brun589fcad2012-10-16 14:13:26 +02008351
8352 return 1;
8353}
8354
Willy Tarreau87b09662015-04-03 00:22:06 +02008355/* binary, returns the SSL stream id if front conn. transport layer is SSL.
Emeric Brun645ae792014-04-30 14:21:06 +02008356 * This function is also usable on backend conn if the fetch keyword 5th
8357 * char is 'b'.
8358 */
Willy Tarreau9a1ab082019-05-09 13:26:41 +02008359#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
Emeric Brun589fcad2012-10-16 14:13:26 +02008360static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008361smp_fetch_ssl_fc_session_id(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunfe68f682012-10-16 14:59:28 +02008362{
Emeric Bruneb8def92018-02-19 15:59:48 +01008363 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
8364 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaue237fe12016-03-10 17:05:28 +01008365 SSL_SESSION *ssl_sess;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008366 struct ssl_sock_ctx *ctx;
Willy Tarreau105599c2020-02-25 08:59:23 +01008367 unsigned int len = 0;
Willy Tarreaube508f12016-03-10 11:47:01 +01008368
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008369 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008370 smp->data.type = SMP_T_BIN;
Emeric Brunfe68f682012-10-16 14:59:28 +02008371
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008372 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8373 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008374 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008375
Olivier Houchard66ab4982019-02-26 18:37:15 +01008376 ssl_sess = SSL_get_session(ctx->ssl);
Willy Tarreau192252e2015-04-04 01:47:55 +02008377 if (!ssl_sess)
Emeric Brunfe68f682012-10-16 14:59:28 +02008378 return 0;
8379
Willy Tarreau105599c2020-02-25 08:59:23 +01008380 smp->data.u.str.area = (char *)SSL_SESSION_get_id(ssl_sess, &len);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008381 if (!smp->data.u.str.area || !smp->data.u.str.data)
Emeric Brunfe68f682012-10-16 14:59:28 +02008382 return 0;
8383
Willy Tarreau105599c2020-02-25 08:59:23 +01008384 smp->data.u.str.data = len;
Emeric Brunfe68f682012-10-16 14:59:28 +02008385 return 1;
Emeric Brunfe68f682012-10-16 14:59:28 +02008386}
Patrick Hemmer41966772018-04-28 19:15:48 -04008387#endif
8388
Emeric Brunfe68f682012-10-16 14:59:28 +02008389
Emmanuel Hocdet839af572019-05-14 16:27:35 +02008390#if HA_OPENSSL_VERSION_NUMBER >= 0x10100000L
Patrick Hemmere0275472018-04-28 19:15:51 -04008391static int
Patrick Hemmer65674662019-06-04 08:13:03 -04008392smp_fetch_ssl_fc_random(const struct arg *args, struct sample *smp, const char *kw, void *private)
8393{
8394 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
8395 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
8396 struct buffer *data;
8397 struct ssl_sock_ctx *ctx;
8398
8399 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8400 return 0;
8401 ctx = conn->xprt_ctx;
8402
8403 data = get_trash_chunk();
8404 if (kw[7] == 'c')
8405 data->data = SSL_get_client_random(ctx->ssl,
8406 (unsigned char *) data->area,
8407 data->size);
8408 else
8409 data->data = SSL_get_server_random(ctx->ssl,
8410 (unsigned char *) data->area,
8411 data->size);
8412 if (!data->data)
8413 return 0;
8414
8415 smp->flags = 0;
8416 smp->data.type = SMP_T_BIN;
8417 smp->data.u.str = *data;
8418
8419 return 1;
8420}
8421
8422static int
Patrick Hemmere0275472018-04-28 19:15:51 -04008423smp_fetch_ssl_fc_session_key(const struct arg *args, struct sample *smp, const char *kw, void *private)
8424{
8425 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
8426 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
8427 SSL_SESSION *ssl_sess;
Willy Tarreau83061a82018-07-13 11:56:34 +02008428 struct buffer *data;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008429 struct ssl_sock_ctx *ctx;
Patrick Hemmere0275472018-04-28 19:15:51 -04008430
8431 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8432 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008433 ctx = conn->xprt_ctx;
Patrick Hemmere0275472018-04-28 19:15:51 -04008434
Olivier Houchard66ab4982019-02-26 18:37:15 +01008435 ssl_sess = SSL_get_session(ctx->ssl);
Patrick Hemmere0275472018-04-28 19:15:51 -04008436 if (!ssl_sess)
8437 return 0;
8438
8439 data = get_trash_chunk();
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008440 data->data = SSL_SESSION_get_master_key(ssl_sess,
8441 (unsigned char *) data->area,
8442 data->size);
8443 if (!data->data)
Patrick Hemmere0275472018-04-28 19:15:51 -04008444 return 0;
8445
8446 smp->flags = 0;
8447 smp->data.type = SMP_T_BIN;
8448 smp->data.u.str = *data;
8449
8450 return 1;
8451}
8452#endif
8453
Patrick Hemmer41966772018-04-28 19:15:48 -04008454#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emeric Brunfe68f682012-10-16 14:59:28 +02008455static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008456smp_fetch_ssl_fc_sni(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02008457{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008458 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008459 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008460
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008461 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008462 smp->data.type = SMP_T_STR;
Willy Tarreau7875d092012-09-10 08:20:03 +02008463
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02008464 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008465 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8466 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008467 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008468
Olivier Houchard66ab4982019-02-26 18:37:15 +01008469 smp->data.u.str.area = (char *)SSL_get_servername(ctx->ssl, TLSEXT_NAMETYPE_host_name);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008470 if (!smp->data.u.str.area)
Willy Tarreau3e394c92012-09-14 23:56:58 +02008471 return 0;
8472
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008473 smp->data.u.str.data = strlen(smp->data.u.str.area);
Willy Tarreau7875d092012-09-10 08:20:03 +02008474 return 1;
Willy Tarreau7875d092012-09-10 08:20:03 +02008475}
Patrick Hemmer41966772018-04-28 19:15:48 -04008476#endif
Willy Tarreau7875d092012-09-10 08:20:03 +02008477
David Sc1ad52e2014-04-08 18:48:47 -04008478static int
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008479smp_fetch_ssl_fc_cl_bin(const struct arg *args, struct sample *smp, const char *kw, void *private)
8480{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008481 struct connection *conn;
8482 struct ssl_capture *capture;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008483 struct ssl_sock_ctx *ctx;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008484
8485 conn = objt_conn(smp->sess->origin);
8486 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8487 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008488 ctx = conn->xprt_ctx;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008489
Olivier Houchard66ab4982019-02-26 18:37:15 +01008490 capture = SSL_get_ex_data(ctx->ssl, ssl_capture_ptr_index);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008491 if (!capture)
8492 return 0;
8493
8494 smp->flags = SMP_F_CONST;
8495 smp->data.type = SMP_T_BIN;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008496 smp->data.u.str.area = capture->ciphersuite;
8497 smp->data.u.str.data = capture->ciphersuite_len;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008498 return 1;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008499}
8500
8501static int
8502smp_fetch_ssl_fc_cl_hex(const struct arg *args, struct sample *smp, const char *kw, void *private)
8503{
Willy Tarreau83061a82018-07-13 11:56:34 +02008504 struct buffer *data;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008505
8506 if (!smp_fetch_ssl_fc_cl_bin(args, smp, kw, private))
8507 return 0;
8508
8509 data = get_trash_chunk();
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008510 dump_binary(data, smp->data.u.str.area, smp->data.u.str.data);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008511 smp->data.type = SMP_T_BIN;
8512 smp->data.u.str = *data;
8513 return 1;
8514}
8515
8516static int
8517smp_fetch_ssl_fc_cl_xxh64(const struct arg *args, struct sample *smp, const char *kw, void *private)
8518{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008519 struct connection *conn;
8520 struct ssl_capture *capture;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008521 struct ssl_sock_ctx *ctx;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008522
8523 conn = objt_conn(smp->sess->origin);
8524 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8525 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008526 ctx = conn->xprt_ctx;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008527
Olivier Houchard66ab4982019-02-26 18:37:15 +01008528 capture = SSL_get_ex_data(ctx->ssl, ssl_capture_ptr_index);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008529 if (!capture)
8530 return 0;
8531
8532 smp->data.type = SMP_T_SINT;
8533 smp->data.u.sint = capture->xxh64;
8534 return 1;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008535}
8536
8537static int
8538smp_fetch_ssl_fc_cl_str(const struct arg *args, struct sample *smp, const char *kw, void *private)
8539{
Willy Tarreau5db847a2019-05-09 14:13:35 +02008540#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL)
Willy Tarreau83061a82018-07-13 11:56:34 +02008541 struct buffer *data;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008542 int i;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008543
8544 if (!smp_fetch_ssl_fc_cl_bin(args, smp, kw, private))
8545 return 0;
8546
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008547 data = get_trash_chunk();
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008548 for (i = 0; i + 1 < smp->data.u.str.data; i += 2) {
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02008549 const char *str;
8550 const SSL_CIPHER *cipher;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008551 const unsigned char *bin = (const unsigned char *) smp->data.u.str.area + i;
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02008552 uint16_t id = (bin[0] << 8) | bin[1];
8553#if defined(OPENSSL_IS_BORINGSSL)
8554 cipher = SSL_get_cipher_by_value(id);
8555#else
Willy Tarreaub7290772018-10-15 11:01:59 +02008556 struct connection *conn = __objt_conn(smp->sess->origin);
Olivier Houchard66ab4982019-02-26 18:37:15 +01008557 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
8558 cipher = SSL_CIPHER_find(ctx->ssl, bin);
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02008559#endif
8560 str = SSL_CIPHER_get_name(cipher);
8561 if (!str || strcmp(str, "(NONE)") == 0)
8562 chunk_appendf(data, "%sUNKNOWN(%04x)", i == 0 ? "" : ",", id);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008563 else
8564 chunk_appendf(data, "%s%s", i == 0 ? "" : ",", str);
8565 }
8566 smp->data.type = SMP_T_STR;
8567 smp->data.u.str = *data;
8568 return 1;
8569#else
8570 return smp_fetch_ssl_fc_cl_xxh64(args, smp, kw, private);
8571#endif
8572}
8573
Willy Tarreau9a1ab082019-05-09 13:26:41 +02008574#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008575static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008576smp_fetch_ssl_fc_unique_id(const struct arg *args, struct sample *smp, const char *kw, void *private)
David Sc1ad52e2014-04-08 18:48:47 -04008577{
Emeric Bruneb8def92018-02-19 15:59:48 +01008578 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
8579 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
David Sc1ad52e2014-04-08 18:48:47 -04008580 int finished_len;
Willy Tarreau83061a82018-07-13 11:56:34 +02008581 struct buffer *finished_trash;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008582 struct ssl_sock_ctx *ctx;
David Sc1ad52e2014-04-08 18:48:47 -04008583
8584 smp->flags = 0;
David Sc1ad52e2014-04-08 18:48:47 -04008585 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
8586 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008587 ctx = conn->xprt_ctx;
David Sc1ad52e2014-04-08 18:48:47 -04008588
Willy Tarreau911db9b2020-01-23 16:27:54 +01008589 if (conn->flags & CO_FL_WAIT_XPRT) {
David Sc1ad52e2014-04-08 18:48:47 -04008590 smp->flags |= SMP_F_MAY_CHANGE;
8591 return 0;
8592 }
8593
8594 finished_trash = get_trash_chunk();
Olivier Houchard66ab4982019-02-26 18:37:15 +01008595 if (!SSL_session_reused(ctx->ssl))
8596 finished_len = SSL_get_peer_finished(ctx->ssl,
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008597 finished_trash->area,
8598 finished_trash->size);
David Sc1ad52e2014-04-08 18:48:47 -04008599 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01008600 finished_len = SSL_get_finished(ctx->ssl,
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008601 finished_trash->area,
8602 finished_trash->size);
David Sc1ad52e2014-04-08 18:48:47 -04008603
8604 if (!finished_len)
8605 return 0;
8606
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008607 finished_trash->data = finished_len;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02008608 smp->data.u.str = *finished_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008609 smp->data.type = SMP_T_BIN;
David Sc1ad52e2014-04-08 18:48:47 -04008610
8611 return 1;
David Sc1ad52e2014-04-08 18:48:47 -04008612}
Patrick Hemmer41966772018-04-28 19:15:48 -04008613#endif
David Sc1ad52e2014-04-08 18:48:47 -04008614
Emeric Brun2525b6b2012-10-18 15:59:43 +02008615/* integer, returns the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02008616static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008617smp_fetch_ssl_c_ca_err(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunf282a812012-09-21 15:27:54 +02008618{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008619 struct connection *conn;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008620 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008621
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02008622 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008623 if (!conn || conn->xprt != &ssl_sock)
8624 return 0;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008625 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008626
Willy Tarreau911db9b2020-01-23 16:27:54 +01008627 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Brunf282a812012-09-21 15:27:54 +02008628 smp->flags = SMP_F_MAY_CHANGE;
8629 return 0;
8630 }
8631
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008632 smp->data.type = SMP_T_SINT;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008633 smp->data.u.sint = (unsigned long long int)SSL_SOCK_ST_TO_CA_ERROR(ctx->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02008634 smp->flags = 0;
8635
8636 return 1;
8637}
8638
Emeric Brun2525b6b2012-10-18 15:59:43 +02008639/* integer, returns the depth of the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02008640static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008641smp_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 +02008642{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008643 struct connection *conn;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008644 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008645
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02008646 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008647 if (!conn || conn->xprt != &ssl_sock)
Emeric Brunf282a812012-09-21 15:27:54 +02008648 return 0;
8649
Willy Tarreau911db9b2020-01-23 16:27:54 +01008650 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Brunf282a812012-09-21 15:27:54 +02008651 smp->flags = SMP_F_MAY_CHANGE;
8652 return 0;
8653 }
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008654 ctx = conn->xprt_ctx;
Emeric Brunf282a812012-09-21 15:27:54 +02008655
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008656 smp->data.type = SMP_T_SINT;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008657 smp->data.u.sint = (long long int)SSL_SOCK_ST_TO_CAEDEPTH(ctx->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02008658 smp->flags = 0;
8659
8660 return 1;
8661}
8662
Emeric Brun2525b6b2012-10-18 15:59:43 +02008663/* integer, returns the first verify error on client certificate */
Emeric Brunf282a812012-09-21 15:27:54 +02008664static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008665smp_fetch_ssl_c_err(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunf282a812012-09-21 15:27:54 +02008666{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008667 struct connection *conn;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008668 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008669
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02008670 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008671 if (!conn || conn->xprt != &ssl_sock)
8672 return 0;
8673
Willy Tarreau911db9b2020-01-23 16:27:54 +01008674 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Brunf282a812012-09-21 15:27:54 +02008675 smp->flags = SMP_F_MAY_CHANGE;
8676 return 0;
8677 }
8678
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008679 ctx = conn->xprt_ctx;
8680
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008681 smp->data.type = SMP_T_SINT;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01008682 smp->data.u.sint = (long long int)SSL_SOCK_ST_TO_CRTERROR(ctx->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02008683 smp->flags = 0;
8684
8685 return 1;
8686}
8687
Emeric Brun2525b6b2012-10-18 15:59:43 +02008688/* integer, returns the verify result on client cert */
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02008689static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02008690smp_fetch_ssl_c_verify(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02008691{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008692 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008693 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008694
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02008695 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008696 if (!conn || conn->xprt != &ssl_sock)
8697 return 0;
8698
Willy Tarreau911db9b2020-01-23 16:27:54 +01008699 if (conn->flags & CO_FL_WAIT_XPRT) {
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02008700 smp->flags = SMP_F_MAY_CHANGE;
8701 return 0;
8702 }
8703
Willy Tarreaub363a1f2013-10-01 10:45:07 +02008704 if (!conn->xprt_ctx)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02008705 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008706 ctx = conn->xprt_ctx;
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02008707
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02008708 smp->data.type = SMP_T_SINT;
Olivier Houchard66ab4982019-02-26 18:37:15 +01008709 smp->data.u.sint = (long long int)SSL_get_verify_result(ctx->ssl);
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02008710 smp->flags = 0;
8711
8712 return 1;
8713}
8714
Emmanuel Hocdet842e94e2019-12-16 16:39:17 +01008715/* for ca-file and ca-verify-file */
8716static int ssl_bind_parse_ca_file_common(char **args, int cur_arg, char **ca_file_p, char **err)
Emeric Brund94b3fe2012-09-20 18:23:56 +02008717{
8718 if (!*args[cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01008719 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
Emeric Brund94b3fe2012-09-20 18:23:56 +02008720 return ERR_ALERT | ERR_FATAL;
8721 }
8722
Willy Tarreauef934602016-12-22 23:12:01 +01008723 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
Emmanuel Hocdet842e94e2019-12-16 16:39:17 +01008724 memprintf(ca_file_p, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02008725 else
Emmanuel Hocdet842e94e2019-12-16 16:39:17 +01008726 memprintf(ca_file_p, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02008727
Emmanuel Hocdet842e94e2019-12-16 16:39:17 +01008728 if (!ssl_store_load_locations_file(*ca_file_p)) {
8729 memprintf(err, "'%s' : unable to load %s", args[cur_arg], *ca_file_p);
Emmanuel Hocdetd4f9a602019-10-24 11:32:47 +02008730 return ERR_ALERT | ERR_FATAL;
8731 }
Emeric Brund94b3fe2012-09-20 18:23:56 +02008732 return 0;
8733}
Emmanuel Hocdet842e94e2019-12-16 16:39:17 +01008734
8735/* parse the "ca-file" bind keyword */
8736static int ssl_bind_parse_ca_file(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
8737{
8738 return ssl_bind_parse_ca_file_common(args, cur_arg, &conf->ca_file, err);
8739}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008740static int bind_parse_ca_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8741{
8742 return ssl_bind_parse_ca_file(args, cur_arg, px, &conf->ssl_conf, err);
8743}
Emeric Brund94b3fe2012-09-20 18:23:56 +02008744
Emmanuel Hocdet842e94e2019-12-16 16:39:17 +01008745/* parse the "ca-verify-file" bind keyword */
8746static int ssl_bind_parse_ca_verify_file(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
8747{
8748 return ssl_bind_parse_ca_file_common(args, cur_arg, &conf->ca_verify_file, err);
8749}
8750static int bind_parse_ca_verify_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8751{
8752 return ssl_bind_parse_ca_verify_file(args, cur_arg, px, &conf->ssl_conf, err);
8753}
8754
Christopher Faulet31af49d2015-06-09 17:29:50 +02008755/* parse the "ca-sign-file" bind keyword */
8756static int bind_parse_ca_sign_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8757{
8758 if (!*args[cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01008759 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
Christopher Faulet31af49d2015-06-09 17:29:50 +02008760 return ERR_ALERT | ERR_FATAL;
8761 }
8762
Willy Tarreauef934602016-12-22 23:12:01 +01008763 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
8764 memprintf(&conf->ca_sign_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Christopher Faulet31af49d2015-06-09 17:29:50 +02008765 else
8766 memprintf(&conf->ca_sign_file, "%s", args[cur_arg + 1]);
8767
8768 return 0;
8769}
8770
Bertrand Jacquinff13c062016-11-13 16:37:11 +00008771/* parse the "ca-sign-pass" bind keyword */
Christopher Faulet31af49d2015-06-09 17:29:50 +02008772static int bind_parse_ca_sign_pass(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8773{
8774 if (!*args[cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01008775 memprintf(err, "'%s' : missing CAkey password", args[cur_arg]);
Christopher Faulet31af49d2015-06-09 17:29:50 +02008776 return ERR_ALERT | ERR_FATAL;
8777 }
8778 memprintf(&conf->ca_sign_pass, "%s", args[cur_arg + 1]);
8779 return 0;
8780}
8781
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008782/* parse the "ciphers" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008783static 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 +02008784{
8785 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02008786 memprintf(err, "'%s' : missing cipher suite", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008787 return ERR_ALERT | ERR_FATAL;
8788 }
8789
Emeric Brun76d88952012-10-05 15:47:31 +02008790 free(conf->ciphers);
Willy Tarreau4348fad2012-09-20 16:48:07 +02008791 conf->ciphers = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008792 return 0;
8793}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008794static int bind_parse_ciphers(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8795{
8796 return ssl_bind_parse_ciphers(args, cur_arg, px, &conf->ssl_conf, err);
8797}
Dirkjan Bussink415150f2018-09-14 11:14:21 +02008798
Emmanuel Hocdet839af572019-05-14 16:27:35 +02008799#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02008800/* parse the "ciphersuites" bind keyword */
8801static int ssl_bind_parse_ciphersuites(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
8802{
8803 if (!*args[cur_arg + 1]) {
8804 memprintf(err, "'%s' : missing cipher suite", args[cur_arg]);
8805 return ERR_ALERT | ERR_FATAL;
8806 }
8807
8808 free(conf->ciphersuites);
8809 conf->ciphersuites = strdup(args[cur_arg + 1]);
8810 return 0;
8811}
8812static int bind_parse_ciphersuites(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8813{
8814 return ssl_bind_parse_ciphersuites(args, cur_arg, px, &conf->ssl_conf, err);
8815}
8816#endif
8817
Willy Tarreaubbc91962019-10-16 16:42:19 +02008818/* parse the "crt" bind keyword. Returns a set of ERR_* flags possibly with an error in <err>. */
Willy Tarreau4348fad2012-09-20 16:48:07 +02008819static 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 +02008820{
Willy Tarreau38011032013-08-13 16:59:39 +02008821 char path[MAXPATHLEN];
Willy Tarreaub75d6922014-04-14 18:05:41 +02008822
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008823 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02008824 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008825 return ERR_ALERT | ERR_FATAL;
8826 }
8827
Willy Tarreauef934602016-12-22 23:12:01 +01008828 if ((*args[cur_arg + 1] != '/' ) && global_ssl.crt_base) {
8829 if ((strlen(global_ssl.crt_base) + 1 + strlen(args[cur_arg + 1]) + 1) > MAXPATHLEN) {
Emeric Brunc8e8d122012-10-02 18:42:10 +02008830 memprintf(err, "'%s' : path too long", args[cur_arg]);
8831 return ERR_ALERT | ERR_FATAL;
8832 }
Willy Tarreauef934602016-12-22 23:12:01 +01008833 snprintf(path, sizeof(path), "%s/%s", global_ssl.crt_base, args[cur_arg + 1]);
Willy Tarreaubbc91962019-10-16 16:42:19 +02008834 return ssl_sock_load_cert(path, conf, err);
Emeric Brunc8e8d122012-10-02 18:42:10 +02008835 }
8836
Willy Tarreaubbc91962019-10-16 16:42:19 +02008837 return ssl_sock_load_cert(args[cur_arg + 1], conf, err);
Emeric Brund94b3fe2012-09-20 18:23:56 +02008838}
8839
Willy Tarreaubbc91962019-10-16 16:42:19 +02008840/* 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 +01008841static int bind_parse_crt_list(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8842{
Willy Tarreaubbc91962019-10-16 16:42:19 +02008843 int err_code;
8844
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01008845 if (!*args[cur_arg + 1]) {
8846 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
8847 return ERR_ALERT | ERR_FATAL;
8848 }
8849
Willy Tarreaubbc91962019-10-16 16:42:19 +02008850 err_code = ssl_sock_load_cert_list_file(args[cur_arg + 1], conf, px, err);
8851 if (err_code)
Willy Tarreauad1731d2013-04-02 17:35:58 +02008852 memprintf(err, "'%s' : %s", args[cur_arg], *err);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01008853
Willy Tarreaubbc91962019-10-16 16:42:19 +02008854 return err_code;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01008855}
8856
Emeric Brunfb510ea2012-10-05 12:00:26 +02008857/* parse the "crl-file" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008858static 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 +02008859{
Emeric Brun051cdab2012-10-02 19:25:50 +02008860#ifndef X509_V_FLAG_CRL_CHECK
Tim Duesterhus93128532019-11-23 23:45:10 +01008861 memprintf(err, "'%s' : library does not support CRL verify", args[cur_arg]);
Emeric Brun051cdab2012-10-02 19:25:50 +02008862 return ERR_ALERT | ERR_FATAL;
8863#else
Emeric Brund94b3fe2012-09-20 18:23:56 +02008864 if (!*args[cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01008865 memprintf(err, "'%s' : missing CRLfile path", args[cur_arg]);
Emeric Brund94b3fe2012-09-20 18:23:56 +02008866 return ERR_ALERT | ERR_FATAL;
8867 }
Emeric Brun2b58d042012-09-20 17:10:03 +02008868
Willy Tarreauef934602016-12-22 23:12:01 +01008869 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
8870 memprintf(&conf->crl_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02008871 else
8872 memprintf(&conf->crl_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02008873
Emmanuel Hocdetb270e812019-11-21 19:09:31 +01008874 if (!ssl_store_load_locations_file(conf->crl_file)) {
8875 memprintf(err, "'%s' : unable to load %s", args[cur_arg], conf->crl_file);
8876 return ERR_ALERT | ERR_FATAL;
8877 }
Emeric Brun2b58d042012-09-20 17:10:03 +02008878 return 0;
Emeric Brun051cdab2012-10-02 19:25:50 +02008879#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02008880}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008881static int bind_parse_crl_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8882{
8883 return ssl_bind_parse_crl_file(args, cur_arg, px, &conf->ssl_conf, err);
8884}
Emeric Brun2b58d042012-09-20 17:10:03 +02008885
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01008886/* parse the "curves" bind keyword keyword */
8887static int ssl_bind_parse_curves(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
8888{
Lukas Tribusd14b49c2019-11-24 18:20:40 +01008889#if ((HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL) || defined(LIBRESSL_VERSION_NUMBER))
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01008890 if (!*args[cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01008891 memprintf(err, "'%s' : missing curve suite", args[cur_arg]);
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01008892 return ERR_ALERT | ERR_FATAL;
8893 }
8894 conf->curves = strdup(args[cur_arg + 1]);
8895 return 0;
8896#else
Tim Duesterhus93128532019-11-23 23:45:10 +01008897 memprintf(err, "'%s' : library does not support curve suite", args[cur_arg]);
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01008898 return ERR_ALERT | ERR_FATAL;
8899#endif
8900}
8901static int bind_parse_curves(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8902{
8903 return ssl_bind_parse_curves(args, cur_arg, px, &conf->ssl_conf, err);
8904}
8905
Bertrand Jacquinff13c062016-11-13 16:37:11 +00008906/* parse the "ecdhe" bind keyword keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008907static 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 +02008908{
Willy Tarreau9a1ab082019-05-09 13:26:41 +02008909#if HA_OPENSSL_VERSION_NUMBER < 0x0090800fL
Tim Duesterhus93128532019-11-23 23:45:10 +01008910 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (too old)", args[cur_arg]);
Emeric Brun2b58d042012-09-20 17:10:03 +02008911 return ERR_ALERT | ERR_FATAL;
8912#elif defined(OPENSSL_NO_ECDH)
Tim Duesterhus93128532019-11-23 23:45:10 +01008913 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 +02008914 return ERR_ALERT | ERR_FATAL;
8915#else
8916 if (!*args[cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01008917 memprintf(err, "'%s' : missing named curve", args[cur_arg]);
Emeric Brun2b58d042012-09-20 17:10:03 +02008918 return ERR_ALERT | ERR_FATAL;
8919 }
8920
8921 conf->ecdhe = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008922
8923 return 0;
Emeric Brun2b58d042012-09-20 17:10:03 +02008924#endif
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008925}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008926static int bind_parse_ecdhe(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8927{
8928 return ssl_bind_parse_ecdhe(args, cur_arg, px, &conf->ssl_conf, err);
8929}
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008930
Bertrand Jacquinff13c062016-11-13 16:37:11 +00008931/* parse the "crt-ignore-err" and "ca-ignore-err" bind keywords */
Emeric Brun81c00f02012-09-21 14:31:21 +02008932static int bind_parse_ignore_err(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8933{
8934 int code;
8935 char *p = args[cur_arg + 1];
8936 unsigned long long *ignerr = &conf->crt_ignerr;
8937
8938 if (!*p) {
Tim Duesterhus93128532019-11-23 23:45:10 +01008939 memprintf(err, "'%s' : missing error IDs list", args[cur_arg]);
Emeric Brun81c00f02012-09-21 14:31:21 +02008940 return ERR_ALERT | ERR_FATAL;
8941 }
8942
8943 if (strcmp(args[cur_arg], "ca-ignore-err") == 0)
8944 ignerr = &conf->ca_ignerr;
8945
8946 if (strcmp(p, "all") == 0) {
8947 *ignerr = ~0ULL;
8948 return 0;
8949 }
8950
8951 while (p) {
8952 code = atoi(p);
8953 if ((code <= 0) || (code > 63)) {
Tim Duesterhus93128532019-11-23 23:45:10 +01008954 memprintf(err, "'%s' : ID '%d' out of range (1..63) in error IDs list '%s'",
8955 args[cur_arg], code, args[cur_arg + 1]);
Emeric Brun81c00f02012-09-21 14:31:21 +02008956 return ERR_ALERT | ERR_FATAL;
8957 }
8958 *ignerr |= 1ULL << code;
8959 p = strchr(p, ',');
8960 if (p)
8961 p++;
8962 }
8963
Emeric Brun2cb7ae52012-10-05 14:14:21 +02008964 return 0;
8965}
8966
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008967/* parse tls_method_options "no-xxx" and "force-xxx" */
8968static int parse_tls_method_options(char *arg, struct tls_version_filter *methods, char **err)
Emeric Brun2cb7ae52012-10-05 14:14:21 +02008969{
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008970 uint16_t v;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008971 char *p;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008972 p = strchr(arg, '-');
8973 if (!p)
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008974 goto fail;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008975 p++;
8976 if (!strcmp(p, "sslv3"))
8977 v = CONF_SSLV3;
8978 else if (!strcmp(p, "tlsv10"))
8979 v = CONF_TLSV10;
8980 else if (!strcmp(p, "tlsv11"))
8981 v = CONF_TLSV11;
8982 else if (!strcmp(p, "tlsv12"))
8983 v = CONF_TLSV12;
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +02008984 else if (!strcmp(p, "tlsv13"))
8985 v = CONF_TLSV13;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008986 else
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008987 goto fail;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008988 if (!strncmp(arg, "no-", 3))
8989 methods->flags |= methodVersions[v].flag;
8990 else if (!strncmp(arg, "force-", 6))
8991 methods->min = methods->max = v;
8992 else
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008993 goto fail;
Emeric Brun2d0c4822012-10-02 13:45:20 +02008994 return 0;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008995 fail:
Tim Duesterhus93128532019-11-23 23:45:10 +01008996 memprintf(err, "'%s' : option not implemented", arg);
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008997 return ERR_ALERT | ERR_FATAL;
Emeric Brun2d0c4822012-10-02 13:45:20 +02008998}
8999
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02009000static 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 +02009001{
Emmanuel Hocdet43664762017-08-09 18:26:20 +02009002 return parse_tls_method_options(args[cur_arg], &conf->ssl_conf.ssl_methods, err);
Emeric Brun2cb7ae52012-10-05 14:14:21 +02009003}
9004
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02009005static 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 +02009006{
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02009007 return parse_tls_method_options(args[*cur_arg], &newsrv->ssl_ctx.methods, err);
9008}
9009
9010/* parse tls_method min/max: "ssl-min-ver" and "ssl-max-ver" */
9011static int parse_tls_method_minmax(char **args, int cur_arg, struct tls_version_filter *methods, char **err)
9012{
9013 uint16_t i, v = 0;
9014 char *argv = args[cur_arg + 1];
9015 if (!*argv) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009016 memprintf(err, "'%s' : missing the ssl/tls version", args[cur_arg]);
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02009017 return ERR_ALERT | ERR_FATAL;
9018 }
9019 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
9020 if (!strcmp(argv, methodVersions[i].name))
9021 v = i;
9022 if (!v) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009023 memprintf(err, "'%s' : unknown ssl/tls version", args[cur_arg + 1]);
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02009024 return ERR_ALERT | ERR_FATAL;
9025 }
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02009026 if (!strcmp("ssl-min-ver", args[cur_arg]))
9027 methods->min = v;
9028 else if (!strcmp("ssl-max-ver", args[cur_arg]))
9029 methods->max = v;
9030 else {
Tim Duesterhus93128532019-11-23 23:45:10 +01009031 memprintf(err, "'%s' : option not implemented", args[cur_arg]);
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02009032 return ERR_ALERT | ERR_FATAL;
9033 }
Emeric Brun2cb7ae52012-10-05 14:14:21 +02009034 return 0;
Emeric Brun2cb7ae52012-10-05 14:14:21 +02009035}
Emeric Brun2cb7ae52012-10-05 14:14:21 +02009036
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02009037static int ssl_bind_parse_tls_method_minmax(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
9038{
Willy Tarreau9a1ab082019-05-09 13:26:41 +02009039#if (HA_OPENSSL_VERSION_NUMBER < 0x10101000L) && !defined(OPENSSL_IS_BORINGSSL)
Christopher Faulet767a84b2017-11-24 16:50:31 +01009040 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 +02009041#endif
9042 return parse_tls_method_minmax(args, cur_arg, &conf->ssl_methods, err);
9043}
9044
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02009045static int bind_parse_tls_method_minmax(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
9046{
Emmanuel Hocdet43664762017-08-09 18:26:20 +02009047 return parse_tls_method_minmax(args, cur_arg, &conf->ssl_conf.ssl_methods, err);
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02009048}
9049
9050static int srv_parse_tls_method_minmax(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9051{
9052 return parse_tls_method_minmax(args, *cur_arg, &newsrv->ssl_ctx.methods, err);
9053}
9054
Emeric Brun2d0c4822012-10-02 13:45:20 +02009055/* parse the "no-tls-tickets" bind keyword */
Emmanuel Hocdet4608ed92017-01-20 13:06:27 +01009056static 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 +02009057{
Emeric Brun89675492012-10-05 13:48:26 +02009058 conf->ssl_options |= BC_SSL_O_NO_TLS_TICKETS;
Emeric Brun81c00f02012-09-21 14:31:21 +02009059 return 0;
9060}
Emeric Brun2d0c4822012-10-02 13:45:20 +02009061
Olivier Houchardc2aae742017-09-22 18:26:28 +02009062/* parse the "allow-0rtt" bind keyword */
9063static int ssl_bind_parse_allow_0rtt(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
9064{
9065 conf->early_data = 1;
9066 return 0;
9067}
9068
9069static int bind_parse_allow_0rtt(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
9070{
Olivier Houchard9679ac92017-10-27 14:58:08 +02009071 conf->ssl_conf.early_data = 1;
Olivier Houchardc2aae742017-09-22 18:26:28 +02009072 return 0;
9073}
9074
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02009075/* parse the "npn" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01009076static 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 +02009077{
Bernard Spil13c53f82018-02-15 13:34:58 +01009078#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02009079 char *p1, *p2;
9080
9081 if (!*args[cur_arg + 1]) {
9082 memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[cur_arg]);
9083 return ERR_ALERT | ERR_FATAL;
9084 }
9085
9086 free(conf->npn_str);
9087
Willy Tarreau3724da12016-02-12 17:11:12 +01009088 /* the NPN string is built as a suite of (<len> <name>)*,
9089 * so we reuse each comma to store the next <len> and need
9090 * one more for the end of the string.
9091 */
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02009092 conf->npn_len = strlen(args[cur_arg + 1]) + 1;
Willy Tarreau3724da12016-02-12 17:11:12 +01009093 conf->npn_str = calloc(1, conf->npn_len + 1);
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02009094 memcpy(conf->npn_str + 1, args[cur_arg + 1], conf->npn_len);
9095
9096 /* replace commas with the name length */
9097 p1 = conf->npn_str;
9098 p2 = p1 + 1;
9099 while (1) {
9100 p2 = memchr(p1 + 1, ',', conf->npn_str + conf->npn_len - (p1 + 1));
9101 if (!p2)
9102 p2 = p1 + 1 + strlen(p1 + 1);
9103
9104 if (p2 - (p1 + 1) > 255) {
9105 *p2 = '\0';
9106 memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
9107 return ERR_ALERT | ERR_FATAL;
9108 }
9109
9110 *p1 = p2 - (p1 + 1);
9111 p1 = p2;
9112
9113 if (!*p2)
9114 break;
9115
9116 *(p2++) = '\0';
9117 }
9118 return 0;
9119#else
Tim Duesterhus93128532019-11-23 23:45:10 +01009120 memprintf(err, "'%s' : library does not support TLS NPN extension", args[cur_arg]);
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02009121 return ERR_ALERT | ERR_FATAL;
9122#endif
9123}
9124
Emmanuel Hocdet98263292016-12-29 18:26:15 +01009125static int bind_parse_npn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
9126{
9127 return ssl_bind_parse_npn(args, cur_arg, px, &conf->ssl_conf, err);
9128}
9129
Willy Tarreauab861d32013-04-02 02:30:41 +02009130/* parse the "alpn" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01009131static 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 +02009132{
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01009133#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02009134 char *p1, *p2;
9135
9136 if (!*args[cur_arg + 1]) {
9137 memprintf(err, "'%s' : missing the comma-delimited ALPN protocol suite", args[cur_arg]);
9138 return ERR_ALERT | ERR_FATAL;
9139 }
9140
9141 free(conf->alpn_str);
9142
Marcoen Hirschbergbef60912016-02-12 17:05:24 +01009143 /* the ALPN string is built as a suite of (<len> <name>)*,
9144 * so we reuse each comma to store the next <len> and need
9145 * one more for the end of the string.
9146 */
Willy Tarreauab861d32013-04-02 02:30:41 +02009147 conf->alpn_len = strlen(args[cur_arg + 1]) + 1;
Marcoen Hirschbergbef60912016-02-12 17:05:24 +01009148 conf->alpn_str = calloc(1, conf->alpn_len + 1);
Willy Tarreauab861d32013-04-02 02:30:41 +02009149 memcpy(conf->alpn_str + 1, args[cur_arg + 1], conf->alpn_len);
9150
9151 /* replace commas with the name length */
9152 p1 = conf->alpn_str;
9153 p2 = p1 + 1;
9154 while (1) {
9155 p2 = memchr(p1 + 1, ',', conf->alpn_str + conf->alpn_len - (p1 + 1));
9156 if (!p2)
9157 p2 = p1 + 1 + strlen(p1 + 1);
9158
9159 if (p2 - (p1 + 1) > 255) {
9160 *p2 = '\0';
9161 memprintf(err, "'%s' : ALPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
9162 return ERR_ALERT | ERR_FATAL;
9163 }
9164
9165 *p1 = p2 - (p1 + 1);
9166 p1 = p2;
9167
9168 if (!*p2)
9169 break;
9170
9171 *(p2++) = '\0';
9172 }
9173 return 0;
9174#else
Tim Duesterhus93128532019-11-23 23:45:10 +01009175 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[cur_arg]);
Willy Tarreauab861d32013-04-02 02:30:41 +02009176 return ERR_ALERT | ERR_FATAL;
9177#endif
9178}
9179
Emmanuel Hocdet98263292016-12-29 18:26:15 +01009180static int bind_parse_alpn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
9181{
9182 return ssl_bind_parse_alpn(args, cur_arg, px, &conf->ssl_conf, err);
9183}
9184
Willy Tarreau79eeafa2012-09-14 07:53:05 +02009185/* parse the "ssl" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02009186static 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 +02009187{
Willy Tarreau71a8c7c2016-12-21 22:04:54 +01009188 conf->xprt = &ssl_sock;
Willy Tarreau4348fad2012-09-20 16:48:07 +02009189 conf->is_ssl = 1;
Emeric Brun76d88952012-10-05 15:47:31 +02009190
Emmanuel Hocdet98263292016-12-29 18:26:15 +01009191 if (global_ssl.listen_default_ciphers && !conf->ssl_conf.ciphers)
9192 conf->ssl_conf.ciphers = strdup(global_ssl.listen_default_ciphers);
Emmanuel Hocdet839af572019-05-14 16:27:35 +02009193#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009194 if (global_ssl.listen_default_ciphersuites && !conf->ssl_conf.ciphersuites)
9195 conf->ssl_conf.ciphersuites = strdup(global_ssl.listen_default_ciphersuites);
9196#endif
Emmanuel Hocdet4608ed92017-01-20 13:06:27 +01009197 conf->ssl_options |= global_ssl.listen_default_ssloptions;
Emmanuel Hocdet43664762017-08-09 18:26:20 +02009198 conf->ssl_conf.ssl_methods.flags |= global_ssl.listen_default_sslmethods.flags;
9199 if (!conf->ssl_conf.ssl_methods.min)
9200 conf->ssl_conf.ssl_methods.min = global_ssl.listen_default_sslmethods.min;
9201 if (!conf->ssl_conf.ssl_methods.max)
9202 conf->ssl_conf.ssl_methods.max = global_ssl.listen_default_sslmethods.max;
Emeric Brun76d88952012-10-05 15:47:31 +02009203
Willy Tarreau79eeafa2012-09-14 07:53:05 +02009204 return 0;
9205}
9206
Lukas Tribus53ae85c2017-05-04 15:45:40 +00009207/* parse the "prefer-client-ciphers" bind keyword */
9208static int bind_parse_pcc(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
9209{
9210 conf->ssl_options |= BC_SSL_O_PREF_CLIE_CIPH;
9211 return 0;
9212}
9213
Christopher Faulet31af49d2015-06-09 17:29:50 +02009214/* parse the "generate-certificates" bind keyword */
9215static int bind_parse_generate_certs(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
9216{
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01009217#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Christopher Faulet31af49d2015-06-09 17:29:50 +02009218 conf->generate_certs = 1;
9219#else
9220 memprintf(err, "%sthis version of openssl cannot generate SSL certificates.\n",
9221 err && *err ? *err : "");
9222#endif
9223 return 0;
9224}
9225
Emmanuel Hocdet65623372013-01-24 17:17:15 +01009226/* parse the "strict-sni" bind keyword */
9227static int bind_parse_strict_sni(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
9228{
9229 conf->strict_sni = 1;
9230 return 0;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009231}
9232
9233/* parse the "tls-ticket-keys" bind keyword */
9234static int bind_parse_tls_ticket_keys(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
9235{
9236#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
Christopher Faulete566f3d2019-10-21 09:55:49 +02009237 FILE *f = NULL;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009238 int i = 0;
9239 char thisline[LINESIZE];
Christopher Faulete566f3d2019-10-21 09:55:49 +02009240 struct tls_keys_ref *keys_ref = NULL;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009241
9242 if (!*args[cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009243 memprintf(err, "'%s' : missing TLS ticket keys file path", args[cur_arg]);
Christopher Faulete566f3d2019-10-21 09:55:49 +02009244 goto fail;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009245 }
9246
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02009247 keys_ref = tlskeys_ref_lookup(args[cur_arg + 1]);
Willy Tarreau17b4aa12018-07-17 10:05:32 +02009248 if (keys_ref) {
9249 keys_ref->refcount++;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02009250 conf->keys_ref = keys_ref;
9251 return 0;
9252 }
9253
Christopher Faulete566f3d2019-10-21 09:55:49 +02009254 keys_ref = calloc(1, sizeof(*keys_ref));
Emeric Brun09852f72019-01-10 10:51:13 +01009255 if (!keys_ref) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009256 memprintf(err, "'%s' : allocation error", args[cur_arg+1]);
Christopher Faulete566f3d2019-10-21 09:55:49 +02009257 goto fail;
Emeric Brun09852f72019-01-10 10:51:13 +01009258 }
9259
Emeric Brun9e754772019-01-10 17:51:55 +01009260 keys_ref->tlskeys = malloc(TLS_TICKETS_NO * sizeof(union tls_sess_key));
Emeric Brun09852f72019-01-10 10:51:13 +01009261 if (!keys_ref->tlskeys) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009262 memprintf(err, "'%s' : allocation error", args[cur_arg+1]);
Christopher Faulete566f3d2019-10-21 09:55:49 +02009263 goto fail;
Emeric Brun09852f72019-01-10 10:51:13 +01009264 }
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009265
9266 if ((f = fopen(args[cur_arg + 1], "r")) == NULL) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009267 memprintf(err, "'%s' : unable to load ssl tickets keys file", args[cur_arg+1]);
Christopher Faulete566f3d2019-10-21 09:55:49 +02009268 goto fail;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009269 }
9270
Nenad Merdanovic146defa2015-05-09 08:46:00 +02009271 keys_ref->filename = strdup(args[cur_arg + 1]);
Emeric Brun09852f72019-01-10 10:51:13 +01009272 if (!keys_ref->filename) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009273 memprintf(err, "'%s' : allocation error", args[cur_arg+1]);
Christopher Faulete566f3d2019-10-21 09:55:49 +02009274 goto fail;
Emeric Brun09852f72019-01-10 10:51:13 +01009275 }
Nenad Merdanovic146defa2015-05-09 08:46:00 +02009276
Emeric Brun9e754772019-01-10 17:51:55 +01009277 keys_ref->key_size_bits = 0;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009278 while (fgets(thisline, sizeof(thisline), f) != NULL) {
9279 int len = strlen(thisline);
Emeric Brun9e754772019-01-10 17:51:55 +01009280 int dec_size;
9281
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009282 /* Strip newline characters from the end */
9283 if(thisline[len - 1] == '\n')
9284 thisline[--len] = 0;
9285
9286 if(thisline[len - 1] == '\r')
9287 thisline[--len] = 0;
9288
Emeric Brun9e754772019-01-10 17:51:55 +01009289 dec_size = base64dec(thisline, len, (char *) (keys_ref->tlskeys + i % TLS_TICKETS_NO), sizeof(union tls_sess_key));
9290 if (dec_size < 0) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009291 memprintf(err, "'%s' : unable to decode base64 key on line %d", args[cur_arg+1], i + 1);
Christopher Faulete566f3d2019-10-21 09:55:49 +02009292 goto fail;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009293 }
Emeric Brun9e754772019-01-10 17:51:55 +01009294 else if (!keys_ref->key_size_bits && (dec_size == sizeof(struct tls_sess_key_128))) {
9295 keys_ref->key_size_bits = 128;
9296 }
9297 else if (!keys_ref->key_size_bits && (dec_size == sizeof(struct tls_sess_key_256))) {
9298 keys_ref->key_size_bits = 256;
9299 }
9300 else if (((dec_size != sizeof(struct tls_sess_key_128)) && (dec_size != sizeof(struct tls_sess_key_256)))
9301 || ((dec_size == sizeof(struct tls_sess_key_128) && (keys_ref->key_size_bits != 128)))
9302 || ((dec_size == sizeof(struct tls_sess_key_256) && (keys_ref->key_size_bits != 256)))) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009303 memprintf(err, "'%s' : wrong sized key on line %d", args[cur_arg+1], i + 1);
Christopher Faulete566f3d2019-10-21 09:55:49 +02009304 goto fail;
Emeric Brun9e754772019-01-10 17:51:55 +01009305 }
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009306 i++;
9307 }
9308
9309 if (i < TLS_TICKETS_NO) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009310 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 +02009311 goto fail;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009312 }
9313
9314 fclose(f);
9315
9316 /* Use penultimate key for encryption, handle when TLS_TICKETS_NO = 1 */
Nenad Merdanovic17891152016-03-25 22:16:57 +01009317 i -= 2;
9318 keys_ref->tls_ticket_enc_index = i < 0 ? 0 : i % TLS_TICKETS_NO;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02009319 keys_ref->unique_id = -1;
Willy Tarreau17b4aa12018-07-17 10:05:32 +02009320 keys_ref->refcount = 1;
Christopher Faulet16f45c82018-02-16 11:23:49 +01009321 HA_RWLOCK_INIT(&keys_ref->lock);
Nenad Merdanovic146defa2015-05-09 08:46:00 +02009322 conf->keys_ref = keys_ref;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009323
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02009324 LIST_ADD(&tlskeys_reference, &keys_ref->list);
9325
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009326 return 0;
Christopher Faulete566f3d2019-10-21 09:55:49 +02009327
9328 fail:
9329 if (f)
9330 fclose(f);
9331 if (keys_ref) {
9332 free(keys_ref->filename);
9333 free(keys_ref->tlskeys);
9334 free(keys_ref);
9335 }
9336 return ERR_ALERT | ERR_FATAL;
9337
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009338#else
Tim Duesterhus93128532019-11-23 23:45:10 +01009339 memprintf(err, "'%s' : TLS ticket callback extension not supported", args[cur_arg]);
Nenad Merdanovic05552d42015-02-27 19:56:49 +01009340 return ERR_ALERT | ERR_FATAL;
9341#endif /* SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB */
Emmanuel Hocdet65623372013-01-24 17:17:15 +01009342}
9343
Emeric Brund94b3fe2012-09-20 18:23:56 +02009344/* parse the "verify" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01009345static 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 +02009346{
9347 if (!*args[cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009348 memprintf(err, "'%s' : missing verify method", args[cur_arg]);
Emeric Brund94b3fe2012-09-20 18:23:56 +02009349 return ERR_ALERT | ERR_FATAL;
9350 }
9351
9352 if (strcmp(args[cur_arg + 1], "none") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01009353 conf->verify = SSL_SOCK_VERIFY_NONE;
Emeric Brund94b3fe2012-09-20 18:23:56 +02009354 else if (strcmp(args[cur_arg + 1], "optional") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01009355 conf->verify = SSL_SOCK_VERIFY_OPTIONAL;
Emeric Brund94b3fe2012-09-20 18:23:56 +02009356 else if (strcmp(args[cur_arg + 1], "required") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01009357 conf->verify = SSL_SOCK_VERIFY_REQUIRED;
Emeric Brund94b3fe2012-09-20 18:23:56 +02009358 else {
Tim Duesterhus93128532019-11-23 23:45:10 +01009359 memprintf(err, "'%s' : unknown verify method '%s', only 'none', 'optional', and 'required' are supported\n",
9360 args[cur_arg], args[cur_arg + 1]);
Emeric Brund94b3fe2012-09-20 18:23:56 +02009361 return ERR_ALERT | ERR_FATAL;
9362 }
9363
9364 return 0;
9365}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01009366static int bind_parse_verify(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
9367{
9368 return ssl_bind_parse_verify(args, cur_arg, px, &conf->ssl_conf, err);
9369}
Emeric Brund94b3fe2012-09-20 18:23:56 +02009370
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02009371/* parse the "no-ca-names" bind keyword */
9372static int ssl_bind_parse_no_ca_names(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
9373{
9374 conf->no_ca_names = 1;
9375 return 0;
9376}
9377static int bind_parse_no_ca_names(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
9378{
9379 return ssl_bind_parse_no_ca_names(args, cur_arg, px, &conf->ssl_conf, err);
9380}
9381
Willy Tarreau92faadf2012-10-10 23:04:25 +02009382/************** "server" keywords ****************/
9383
Olivier Houchardc7566002018-11-20 23:33:50 +01009384/* parse the "npn" bind keyword */
9385static int srv_parse_npn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9386{
9387#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
9388 char *p1, *p2;
9389
9390 if (!*args[*cur_arg + 1]) {
9391 memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[*cur_arg]);
9392 return ERR_ALERT | ERR_FATAL;
9393 }
9394
9395 free(newsrv->ssl_ctx.npn_str);
9396
9397 /* the NPN string is built as a suite of (<len> <name>)*,
9398 * so we reuse each comma to store the next <len> and need
9399 * one more for the end of the string.
9400 */
9401 newsrv->ssl_ctx.npn_len = strlen(args[*cur_arg + 1]) + 1;
9402 newsrv->ssl_ctx.npn_str = calloc(1, newsrv->ssl_ctx.npn_len + 1);
9403 memcpy(newsrv->ssl_ctx.npn_str + 1, args[*cur_arg + 1],
9404 newsrv->ssl_ctx.npn_len);
9405
9406 /* replace commas with the name length */
9407 p1 = newsrv->ssl_ctx.npn_str;
9408 p2 = p1 + 1;
9409 while (1) {
9410 p2 = memchr(p1 + 1, ',', newsrv->ssl_ctx.npn_str +
9411 newsrv->ssl_ctx.npn_len - (p1 + 1));
9412 if (!p2)
9413 p2 = p1 + 1 + strlen(p1 + 1);
9414
9415 if (p2 - (p1 + 1) > 255) {
9416 *p2 = '\0';
9417 memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[*cur_arg], p1 + 1);
9418 return ERR_ALERT | ERR_FATAL;
9419 }
9420
9421 *p1 = p2 - (p1 + 1);
9422 p1 = p2;
9423
9424 if (!*p2)
9425 break;
9426
9427 *(p2++) = '\0';
9428 }
9429 return 0;
9430#else
Tim Duesterhus93128532019-11-23 23:45:10 +01009431 memprintf(err, "'%s' : library does not support TLS NPN extension", args[*cur_arg]);
Olivier Houchardc7566002018-11-20 23:33:50 +01009432 return ERR_ALERT | ERR_FATAL;
9433#endif
9434}
9435
Olivier Houchard92150142018-12-21 19:47:01 +01009436/* parse the "alpn" or the "check-alpn" server keyword */
Olivier Houchardc7566002018-11-20 23:33:50 +01009437static int srv_parse_alpn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9438{
9439#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
9440 char *p1, *p2;
Olivier Houchard92150142018-12-21 19:47:01 +01009441 char **alpn_str;
9442 int *alpn_len;
Olivier Houchardc7566002018-11-20 23:33:50 +01009443
Olivier Houchard92150142018-12-21 19:47:01 +01009444 if (*args[*cur_arg] == 'c') {
9445 alpn_str = &newsrv->check.alpn_str;
9446 alpn_len = &newsrv->check.alpn_len;
9447 } else {
9448 alpn_str = &newsrv->ssl_ctx.alpn_str;
9449 alpn_len = &newsrv->ssl_ctx.alpn_len;
9450
9451 }
Olivier Houchardc7566002018-11-20 23:33:50 +01009452 if (!*args[*cur_arg + 1]) {
9453 memprintf(err, "'%s' : missing the comma-delimited ALPN protocol suite", args[*cur_arg]);
9454 return ERR_ALERT | ERR_FATAL;
9455 }
9456
Olivier Houchard92150142018-12-21 19:47:01 +01009457 free(*alpn_str);
Olivier Houchardc7566002018-11-20 23:33:50 +01009458
9459 /* the ALPN string is built as a suite of (<len> <name>)*,
9460 * so we reuse each comma to store the next <len> and need
9461 * one more for the end of the string.
9462 */
Olivier Houchard92150142018-12-21 19:47:01 +01009463 *alpn_len = strlen(args[*cur_arg + 1]) + 1;
9464 *alpn_str = calloc(1, *alpn_len + 1);
9465 memcpy(*alpn_str + 1, args[*cur_arg + 1], *alpn_len);
Olivier Houchardc7566002018-11-20 23:33:50 +01009466
9467 /* replace commas with the name length */
Olivier Houchard92150142018-12-21 19:47:01 +01009468 p1 = *alpn_str;
Olivier Houchardc7566002018-11-20 23:33:50 +01009469 p2 = p1 + 1;
9470 while (1) {
Olivier Houchard92150142018-12-21 19:47:01 +01009471 p2 = memchr(p1 + 1, ',', *alpn_str + *alpn_len - (p1 + 1));
Olivier Houchardc7566002018-11-20 23:33:50 +01009472 if (!p2)
9473 p2 = p1 + 1 + strlen(p1 + 1);
9474
9475 if (p2 - (p1 + 1) > 255) {
9476 *p2 = '\0';
9477 memprintf(err, "'%s' : ALPN protocol name too long : '%s'", args[*cur_arg], p1 + 1);
9478 return ERR_ALERT | ERR_FATAL;
9479 }
9480
9481 *p1 = p2 - (p1 + 1);
9482 p1 = p2;
9483
9484 if (!*p2)
9485 break;
9486
9487 *(p2++) = '\0';
9488 }
9489 return 0;
9490#else
Tim Duesterhus93128532019-11-23 23:45:10 +01009491 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[*cur_arg]);
Olivier Houchardc7566002018-11-20 23:33:50 +01009492 return ERR_ALERT | ERR_FATAL;
9493#endif
9494}
9495
Emeric Brunef42d922012-10-11 16:11:36 +02009496/* parse the "ca-file" server keyword */
9497static int srv_parse_ca_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9498{
9499 if (!*args[*cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009500 memprintf(err, "'%s' : missing CAfile path", args[*cur_arg]);
Emeric Brunef42d922012-10-11 16:11:36 +02009501 return ERR_ALERT | ERR_FATAL;
9502 }
9503
Willy Tarreauef934602016-12-22 23:12:01 +01009504 if ((*args[*cur_arg + 1] != '/') && global_ssl.ca_base)
9505 memprintf(&newsrv->ssl_ctx.ca_file, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02009506 else
9507 memprintf(&newsrv->ssl_ctx.ca_file, "%s", args[*cur_arg + 1]);
9508
Emmanuel Hocdetd4f9a602019-10-24 11:32:47 +02009509 if (!ssl_store_load_locations_file(newsrv->ssl_ctx.ca_file)) {
9510 memprintf(err, "'%s' : unable to load %s", args[*cur_arg], newsrv->ssl_ctx.ca_file);
9511 return ERR_ALERT | ERR_FATAL;
9512 }
Emeric Brunef42d922012-10-11 16:11:36 +02009513 return 0;
9514}
9515
Olivier Houchard9130a962017-10-17 17:33:43 +02009516/* parse the "check-sni" server keyword */
9517static int srv_parse_check_sni(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9518{
9519 if (!*args[*cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009520 memprintf(err, "'%s' : missing SNI", args[*cur_arg]);
Olivier Houchard9130a962017-10-17 17:33:43 +02009521 return ERR_ALERT | ERR_FATAL;
9522 }
9523
9524 newsrv->check.sni = strdup(args[*cur_arg + 1]);
9525 if (!newsrv->check.sni) {
9526 memprintf(err, "'%s' : failed to allocate memory", args[*cur_arg]);
9527 return ERR_ALERT | ERR_FATAL;
9528 }
9529 return 0;
9530
9531}
9532
Willy Tarreau92faadf2012-10-10 23:04:25 +02009533/* parse the "check-ssl" server keyword */
9534static int srv_parse_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9535{
9536 newsrv->check.use_ssl = 1;
Willy Tarreauef934602016-12-22 23:12:01 +01009537 if (global_ssl.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
9538 newsrv->ssl_ctx.ciphers = strdup(global_ssl.connect_default_ciphers);
Emmanuel Hocdet839af572019-05-14 16:27:35 +02009539#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009540 if (global_ssl.connect_default_ciphersuites && !newsrv->ssl_ctx.ciphersuites)
9541 newsrv->ssl_ctx.ciphersuites = strdup(global_ssl.connect_default_ciphersuites);
9542#endif
Willy Tarreauef934602016-12-22 23:12:01 +01009543 newsrv->ssl_ctx.options |= global_ssl.connect_default_ssloptions;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02009544 newsrv->ssl_ctx.methods.flags |= global_ssl.connect_default_sslmethods.flags;
9545 if (!newsrv->ssl_ctx.methods.min)
9546 newsrv->ssl_ctx.methods.min = global_ssl.connect_default_sslmethods.min;
9547 if (!newsrv->ssl_ctx.methods.max)
9548 newsrv->ssl_ctx.methods.max = global_ssl.connect_default_sslmethods.max;
9549
Willy Tarreau92faadf2012-10-10 23:04:25 +02009550 return 0;
9551}
9552
9553/* parse the "ciphers" server keyword */
9554static int srv_parse_ciphers(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9555{
9556 if (!*args[*cur_arg + 1]) {
9557 memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
9558 return ERR_ALERT | ERR_FATAL;
9559 }
9560
9561 free(newsrv->ssl_ctx.ciphers);
9562 newsrv->ssl_ctx.ciphers = strdup(args[*cur_arg + 1]);
9563 return 0;
9564}
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009565
Emmanuel Hocdet839af572019-05-14 16:27:35 +02009566#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009567/* parse the "ciphersuites" server keyword */
9568static int srv_parse_ciphersuites(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9569{
9570 if (!*args[*cur_arg + 1]) {
9571 memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
9572 return ERR_ALERT | ERR_FATAL;
9573 }
9574
9575 free(newsrv->ssl_ctx.ciphersuites);
9576 newsrv->ssl_ctx.ciphersuites = strdup(args[*cur_arg + 1]);
9577 return 0;
9578}
9579#endif
Willy Tarreau92faadf2012-10-10 23:04:25 +02009580
Emeric Brunef42d922012-10-11 16:11:36 +02009581/* parse the "crl-file" server keyword */
9582static int srv_parse_crl_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9583{
9584#ifndef X509_V_FLAG_CRL_CHECK
Tim Duesterhus93128532019-11-23 23:45:10 +01009585 memprintf(err, "'%s' : library does not support CRL verify", args[*cur_arg]);
Emeric Brunef42d922012-10-11 16:11:36 +02009586 return ERR_ALERT | ERR_FATAL;
9587#else
9588 if (!*args[*cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009589 memprintf(err, "'%s' : missing CRLfile path", args[*cur_arg]);
Emeric Brunef42d922012-10-11 16:11:36 +02009590 return ERR_ALERT | ERR_FATAL;
9591 }
9592
Willy Tarreauef934602016-12-22 23:12:01 +01009593 if ((*args[*cur_arg + 1] != '/') && global_ssl.ca_base)
9594 memprintf(&newsrv->ssl_ctx.crl_file, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02009595 else
9596 memprintf(&newsrv->ssl_ctx.crl_file, "%s", args[*cur_arg + 1]);
9597
Emmanuel Hocdetb270e812019-11-21 19:09:31 +01009598 if (!ssl_store_load_locations_file(newsrv->ssl_ctx.crl_file)) {
9599 memprintf(err, "'%s' : unable to load %s", args[*cur_arg], newsrv->ssl_ctx.crl_file);
9600 return ERR_ALERT | ERR_FATAL;
9601 }
Emeric Brunef42d922012-10-11 16:11:36 +02009602 return 0;
9603#endif
9604}
9605
Emeric Bruna7aa3092012-10-26 12:58:00 +02009606/* parse the "crt" server keyword */
9607static int srv_parse_crt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9608{
9609 if (!*args[*cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009610 memprintf(err, "'%s' : missing certificate file path", args[*cur_arg]);
Emeric Bruna7aa3092012-10-26 12:58:00 +02009611 return ERR_ALERT | ERR_FATAL;
9612 }
9613
Willy Tarreauef934602016-12-22 23:12:01 +01009614 if ((*args[*cur_arg + 1] != '/') && global_ssl.crt_base)
Christopher Fauletff3a41e2017-11-23 09:13:32 +01009615 memprintf(&newsrv->ssl_ctx.client_crt, "%s/%s", global_ssl.crt_base, args[*cur_arg + 1]);
Emeric Bruna7aa3092012-10-26 12:58:00 +02009616 else
9617 memprintf(&newsrv->ssl_ctx.client_crt, "%s", args[*cur_arg + 1]);
9618
9619 return 0;
9620}
Emeric Brunef42d922012-10-11 16:11:36 +02009621
Frédéric Lécaille340ae602017-03-13 10:38:04 +01009622/* parse the "no-check-ssl" server keyword */
9623static int srv_parse_no_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9624{
9625 newsrv->check.use_ssl = 0;
9626 free(newsrv->ssl_ctx.ciphers);
9627 newsrv->ssl_ctx.ciphers = NULL;
9628 newsrv->ssl_ctx.options &= ~global_ssl.connect_default_ssloptions;
9629 return 0;
9630}
9631
Frédéric Lécaillee892c4c2017-03-13 12:08:01 +01009632/* parse the "no-send-proxy-v2-ssl" server keyword */
9633static int srv_parse_no_send_proxy_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9634{
9635 newsrv->pp_opts &= ~SRV_PP_V2;
9636 newsrv->pp_opts &= ~SRV_PP_V2_SSL;
9637 return 0;
9638}
9639
9640/* parse the "no-send-proxy-v2-ssl-cn" server keyword */
9641static int srv_parse_no_send_proxy_cn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9642{
9643 newsrv->pp_opts &= ~SRV_PP_V2;
9644 newsrv->pp_opts &= ~SRV_PP_V2_SSL;
9645 newsrv->pp_opts &= ~SRV_PP_V2_SSL_CN;
9646 return 0;
9647}
9648
Frédéric Lécaillee381d762017-03-13 11:54:17 +01009649/* parse the "no-ssl" server keyword */
9650static int srv_parse_no_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9651{
9652 newsrv->use_ssl = 0;
9653 free(newsrv->ssl_ctx.ciphers);
9654 newsrv->ssl_ctx.ciphers = NULL;
9655 return 0;
9656}
9657
Olivier Houchard522eea72017-11-03 16:27:47 +01009658/* parse the "allow-0rtt" server keyword */
9659static int srv_parse_allow_0rtt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9660{
9661 newsrv->ssl_ctx.options |= SRV_SSL_O_EARLY_DATA;
9662 return 0;
9663}
9664
Willy Tarreau2a3fb1c2015-02-05 16:47:07 +01009665/* parse the "no-ssl-reuse" server keyword */
9666static int srv_parse_no_ssl_reuse(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9667{
9668 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_REUSE;
9669 return 0;
9670}
9671
Emeric Brunf9c5c472012-10-11 15:28:34 +02009672/* parse the "no-tls-tickets" server keyword */
9673static int srv_parse_no_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9674{
9675 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLS_TICKETS;
9676 return 0;
9677}
David Safb76832014-05-08 23:42:08 -04009678/* parse the "send-proxy-v2-ssl" server keyword */
9679static int srv_parse_send_proxy_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9680{
9681 newsrv->pp_opts |= SRV_PP_V2;
9682 newsrv->pp_opts |= SRV_PP_V2_SSL;
9683 return 0;
9684}
9685
9686/* parse the "send-proxy-v2-ssl-cn" server keyword */
9687static int srv_parse_send_proxy_cn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9688{
9689 newsrv->pp_opts |= SRV_PP_V2;
9690 newsrv->pp_opts |= SRV_PP_V2_SSL;
9691 newsrv->pp_opts |= SRV_PP_V2_SSL_CN;
9692 return 0;
9693}
Emeric Brunf9c5c472012-10-11 15:28:34 +02009694
Willy Tarreau732eac42015-07-09 11:40:25 +02009695/* parse the "sni" server keyword */
9696static int srv_parse_sni(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9697{
9698#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
9699 memprintf(err, "'%s' : the current SSL library doesn't support the SNI TLS extension", args[*cur_arg]);
9700 return ERR_ALERT | ERR_FATAL;
9701#else
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01009702 char *arg;
Willy Tarreau732eac42015-07-09 11:40:25 +02009703
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01009704 arg = args[*cur_arg + 1];
9705 if (!*arg) {
Willy Tarreau732eac42015-07-09 11:40:25 +02009706 memprintf(err, "'%s' : missing sni expression", args[*cur_arg]);
9707 return ERR_ALERT | ERR_FATAL;
9708 }
9709
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01009710 free(newsrv->sni_expr);
9711 newsrv->sni_expr = strdup(arg);
Willy Tarreau732eac42015-07-09 11:40:25 +02009712
Willy Tarreau732eac42015-07-09 11:40:25 +02009713 return 0;
9714#endif
9715}
9716
Willy Tarreau92faadf2012-10-10 23:04:25 +02009717/* parse the "ssl" server keyword */
9718static int srv_parse_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9719{
9720 newsrv->use_ssl = 1;
Willy Tarreauef934602016-12-22 23:12:01 +01009721 if (global_ssl.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
9722 newsrv->ssl_ctx.ciphers = strdup(global_ssl.connect_default_ciphers);
Emmanuel Hocdet839af572019-05-14 16:27:35 +02009723#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009724 if (global_ssl.connect_default_ciphersuites && !newsrv->ssl_ctx.ciphersuites)
9725 newsrv->ssl_ctx.ciphersuites = strdup(global_ssl.connect_default_ciphersuites);
9726#endif
Willy Tarreau92faadf2012-10-10 23:04:25 +02009727 return 0;
9728}
9729
Frédéric Lécaille2cfcdbe2017-03-13 11:32:20 +01009730/* parse the "ssl-reuse" server keyword */
9731static int srv_parse_ssl_reuse(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9732{
9733 newsrv->ssl_ctx.options &= ~SRV_SSL_O_NO_REUSE;
9734 return 0;
9735}
9736
Frédéric Lécaille2cfcdbe2017-03-13 11:32:20 +01009737/* parse the "tls-tickets" server keyword */
9738static int srv_parse_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9739{
9740 newsrv->ssl_ctx.options &= ~SRV_SSL_O_NO_TLS_TICKETS;
9741 return 0;
9742}
9743
Emeric Brunef42d922012-10-11 16:11:36 +02009744/* parse the "verify" server keyword */
9745static int srv_parse_verify(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9746{
9747 if (!*args[*cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009748 memprintf(err, "'%s' : missing verify method", args[*cur_arg]);
Emeric Brunef42d922012-10-11 16:11:36 +02009749 return ERR_ALERT | ERR_FATAL;
9750 }
9751
9752 if (strcmp(args[*cur_arg + 1], "none") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01009753 newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_NONE;
Emeric Brunef42d922012-10-11 16:11:36 +02009754 else if (strcmp(args[*cur_arg + 1], "required") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01009755 newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_REQUIRED;
Emeric Brunef42d922012-10-11 16:11:36 +02009756 else {
Tim Duesterhus93128532019-11-23 23:45:10 +01009757 memprintf(err, "'%s' : unknown verify method '%s', only 'none' and 'required' are supported\n",
9758 args[*cur_arg], args[*cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02009759 return ERR_ALERT | ERR_FATAL;
9760 }
9761
Evan Broderbe554312013-06-27 00:05:25 -07009762 return 0;
9763}
9764
9765/* parse the "verifyhost" server keyword */
9766static int srv_parse_verifyhost(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
9767{
9768 if (!*args[*cur_arg + 1]) {
Tim Duesterhus93128532019-11-23 23:45:10 +01009769 memprintf(err, "'%s' : missing hostname to verify against", args[*cur_arg]);
Evan Broderbe554312013-06-27 00:05:25 -07009770 return ERR_ALERT | ERR_FATAL;
9771 }
9772
Frédéric Lécaille273f3212017-03-13 15:52:01 +01009773 free(newsrv->ssl_ctx.verify_host);
Evan Broderbe554312013-06-27 00:05:25 -07009774 newsrv->ssl_ctx.verify_host = strdup(args[*cur_arg + 1]);
9775
Emeric Brunef42d922012-10-11 16:11:36 +02009776 return 0;
9777}
9778
Emeric Brun2c86cbf2014-10-30 15:56:50 +01009779/* parse the "ssl-default-bind-options" keyword in global section */
9780static int ssl_parse_default_bind_options(char **args, int section_type, struct proxy *curpx,
9781 struct proxy *defpx, const char *file, int line,
9782 char **err) {
9783 int i = 1;
9784
9785 if (*(args[i]) == 0) {
9786 memprintf(err, "global statement '%s' expects an option as an argument.", args[0]);
9787 return -1;
9788 }
9789 while (*(args[i])) {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02009790 if (!strcmp(args[i], "no-tls-tickets"))
Willy Tarreauef934602016-12-22 23:12:01 +01009791 global_ssl.listen_default_ssloptions |= BC_SSL_O_NO_TLS_TICKETS;
Lukas Tribus53ae85c2017-05-04 15:45:40 +00009792 else if (!strcmp(args[i], "prefer-client-ciphers"))
9793 global_ssl.listen_default_ssloptions |= BC_SSL_O_PREF_CLIE_CIPH;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02009794 else if (!strcmp(args[i], "ssl-min-ver") || !strcmp(args[i], "ssl-max-ver")) {
9795 if (!parse_tls_method_minmax(args, i, &global_ssl.listen_default_sslmethods, err))
9796 i++;
9797 else {
9798 memprintf(err, "%s on global statement '%s'.", *err, args[0]);
9799 return -1;
9800 }
9801 }
9802 else if (parse_tls_method_options(args[i], &global_ssl.listen_default_sslmethods, err)) {
Emeric Brun2c86cbf2014-10-30 15:56:50 +01009803 memprintf(err, "unknown option '%s' on global statement '%s'.", args[i], args[0]);
9804 return -1;
9805 }
9806 i++;
9807 }
9808 return 0;
9809}
9810
9811/* parse the "ssl-default-server-options" keyword in global section */
9812static int ssl_parse_default_server_options(char **args, int section_type, struct proxy *curpx,
9813 struct proxy *defpx, const char *file, int line,
9814 char **err) {
9815 int i = 1;
9816
9817 if (*(args[i]) == 0) {
9818 memprintf(err, "global statement '%s' expects an option as an argument.", args[0]);
9819 return -1;
9820 }
9821 while (*(args[i])) {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02009822 if (!strcmp(args[i], "no-tls-tickets"))
Willy Tarreauef934602016-12-22 23:12:01 +01009823 global_ssl.connect_default_ssloptions |= SRV_SSL_O_NO_TLS_TICKETS;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02009824 else if (!strcmp(args[i], "ssl-min-ver") || !strcmp(args[i], "ssl-max-ver")) {
9825 if (!parse_tls_method_minmax(args, i, &global_ssl.connect_default_sslmethods, err))
9826 i++;
9827 else {
9828 memprintf(err, "%s on global statement '%s'.", *err, args[0]);
9829 return -1;
9830 }
9831 }
9832 else if (parse_tls_method_options(args[i], &global_ssl.connect_default_sslmethods, err)) {
Emeric Brun2c86cbf2014-10-30 15:56:50 +01009833 memprintf(err, "unknown option '%s' on global statement '%s'.", args[i], args[0]);
9834 return -1;
9835 }
9836 i++;
9837 }
9838 return 0;
9839}
9840
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01009841/* parse the "ca-base" / "crt-base" keywords in global section.
9842 * Returns <0 on alert, >0 on warning, 0 on success.
9843 */
9844static int ssl_parse_global_ca_crt_base(char **args, int section_type, struct proxy *curpx,
9845 struct proxy *defpx, const char *file, int line,
9846 char **err)
9847{
9848 char **target;
9849
Willy Tarreauef934602016-12-22 23:12:01 +01009850 target = (args[0][1] == 'a') ? &global_ssl.ca_base : &global_ssl.crt_base;
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01009851
9852 if (too_many_args(1, args, err, NULL))
9853 return -1;
9854
9855 if (*target) {
9856 memprintf(err, "'%s' already specified.", args[0]);
9857 return -1;
9858 }
9859
9860 if (*(args[1]) == 0) {
9861 memprintf(err, "global statement '%s' expects a directory path as an argument.", args[0]);
9862 return -1;
9863 }
9864 *target = strdup(args[1]);
9865 return 0;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00009866}
9867
Emmanuel Hocdet70df7bf2019-01-04 11:08:20 +01009868/* "issuers-chain-path" load chain certificate in global */
9869static int ssl_load_global_issuer_from_BIO(BIO *in, char *fp, char **err)
9870{
9871 X509 *ca;
9872 X509_NAME *name = NULL;
9873 ASN1_OCTET_STRING *skid = NULL;
9874 STACK_OF(X509) *chain = NULL;
9875 struct issuer_chain *issuer;
9876 struct eb64_node *node;
9877 char *path;
9878 u64 key;
9879 int ret = 0;
9880
9881 while ((ca = PEM_read_bio_X509(in, NULL, NULL, NULL))) {
9882 if (chain == NULL) {
9883 chain = sk_X509_new_null();
9884 skid = X509_get_ext_d2i(ca, NID_subject_key_identifier, NULL, NULL);
9885 name = X509_get_subject_name(ca);
9886 }
9887 if (!sk_X509_push(chain, ca)) {
9888 X509_free(ca);
9889 goto end;
9890 }
9891 }
9892 if (!chain) {
9893 memprintf(err, "unable to load issuers-chain %s : pem certificate not found.\n", fp);
9894 goto end;
9895 }
9896 if (!skid) {
9897 memprintf(err, "unable to load issuers-chain %s : SubjectKeyIdentifier not found.\n", fp);
9898 goto end;
9899 }
9900 if (!name) {
9901 memprintf(err, "unable to load issuers-chain %s : SubjectName not found.\n", fp);
9902 goto end;
9903 }
9904 key = XXH64(ASN1_STRING_get0_data(skid), ASN1_STRING_length(skid), 0);
William Lallemande0f3fd52020-02-25 14:53:06 +01009905 for (node = eb64_lookup(&cert_issuer_tree, key); node; node = eb64_next(node)) {
Emmanuel Hocdet70df7bf2019-01-04 11:08:20 +01009906 issuer = container_of(node, typeof(*issuer), node);
9907 if (!X509_NAME_cmp(name, X509_get_subject_name(sk_X509_value(issuer->chain, 0)))) {
9908 memprintf(err, "duplicate issuers-chain %s: %s already in store\n", fp, issuer->path);
9909 goto end;
9910 }
9911 }
9912 issuer = calloc(1, sizeof *issuer);
9913 path = strdup(fp);
9914 if (!issuer || !path) {
9915 free(issuer);
9916 free(path);
9917 goto end;
9918 }
9919 issuer->node.key = key;
9920 issuer->path = path;
9921 issuer->chain = chain;
9922 chain = NULL;
William Lallemande0f3fd52020-02-25 14:53:06 +01009923 eb64_insert(&cert_issuer_tree, &issuer->node);
Emmanuel Hocdet70df7bf2019-01-04 11:08:20 +01009924 ret = 1;
9925 end:
9926 if (skid)
9927 ASN1_OCTET_STRING_free(skid);
9928 if (chain)
9929 sk_X509_pop_free(chain, X509_free);
9930 return ret;
9931}
9932
Emmanuel Hocdet75a7aa12020-02-18 15:19:24 +01009933static struct issuer_chain* ssl_get_issuer_chain(X509 *cert)
9934{
9935 AUTHORITY_KEYID *akid;
9936 struct issuer_chain *issuer = NULL;
9937
9938 akid = X509_get_ext_d2i(cert, NID_authority_key_identifier, NULL, NULL);
9939 if (akid) {
9940 struct eb64_node *node;
9941 u64 hk;
9942 hk = XXH64(ASN1_STRING_get0_data(akid->keyid), ASN1_STRING_length(akid->keyid), 0);
9943 for (node = eb64_lookup(&cert_issuer_tree, hk); node; node = eb64_next(node)) {
9944 struct issuer_chain *ti = container_of(node, typeof(*issuer), node);
9945 if (X509_check_issued(sk_X509_value(ti->chain, 0), cert) == X509_V_OK) {
9946 issuer = ti;
9947 break;
9948 }
9949 }
9950 AUTHORITY_KEYID_free(akid);
9951 }
9952 return issuer;
9953}
9954
Emmanuel Hocdet70df7bf2019-01-04 11:08:20 +01009955static void ssl_free_global_issuers(void)
9956{
9957 struct eb64_node *node, *back;
9958 struct issuer_chain *issuer;
9959
William Lallemande0f3fd52020-02-25 14:53:06 +01009960 node = eb64_first(&cert_issuer_tree);
Emmanuel Hocdet70df7bf2019-01-04 11:08:20 +01009961 while (node) {
9962 issuer = container_of(node, typeof(*issuer), node);
9963 back = eb64_next(node);
9964 eb64_delete(node);
9965 free(issuer->path);
9966 sk_X509_pop_free(issuer->chain, X509_free);
9967 free(issuer);
9968 node = back;
9969 }
9970}
9971
9972static int ssl_load_global_issuers_from_path(char **args, int section_type, struct proxy *curpx,
9973 struct proxy *defpx, const char *file, int line,
9974 char **err)
9975{
9976 char *path;
9977 struct dirent **de_list;
9978 int i, n;
9979 struct stat buf;
9980 char *end;
9981 char fp[MAXPATHLEN+1];
9982
9983 if (too_many_args(1, args, err, NULL))
9984 return -1;
9985
9986 path = args[1];
9987 if (*path == 0 || stat(path, &buf)) {
9988 memprintf(err, "%sglobal statement '%s' expects a directory path as an argument.\n",
9989 err && *err ? *err : "", args[0]);
9990 return -1;
9991 }
9992 if (S_ISDIR(buf.st_mode) == 0) {
9993 memprintf(err, "%sglobal statement '%s': %s is not a directory.\n",
9994 err && *err ? *err : "", args[0], path);
9995 return -1;
9996 }
9997
9998 /* strip trailing slashes, including first one */
9999 for (end = path + strlen(path) - 1; end >= path && *end == '/'; end--)
10000 *end = 0;
10001 /* path already parsed? */
10002 if (global_ssl.issuers_chain_path && strcmp(global_ssl.issuers_chain_path, path) == 0)
10003 return 0;
10004 /* overwrite old issuers_chain_path */
10005 free(global_ssl.issuers_chain_path);
10006 global_ssl.issuers_chain_path = strdup(path);
10007 ssl_free_global_issuers();
10008
10009 n = scandir(path, &de_list, 0, alphasort);
10010 if (n < 0) {
10011 memprintf(err, "%sglobal statement '%s': unable to scan directory '%s' : %s.\n",
10012 err && *err ? *err : "", args[0], path, strerror(errno));
10013 return -1;
10014 }
10015 for (i = 0; i < n; i++) {
10016 struct dirent *de = de_list[i];
10017 BIO *in = NULL;
10018 char *warn = NULL;
10019
10020 snprintf(fp, sizeof(fp), "%s/%s", path, de->d_name);
10021 free(de);
10022 if (stat(fp, &buf) != 0) {
10023 ha_warning("unable to stat certificate from file '%s' : %s.\n", fp, strerror(errno));
10024 goto next;
10025 }
10026 if (!S_ISREG(buf.st_mode))
10027 goto next;
10028
10029 in = BIO_new(BIO_s_file());
10030 if (in == NULL)
10031 goto next;
10032 if (BIO_read_filename(in, fp) <= 0)
10033 goto next;
10034 ssl_load_global_issuer_from_BIO(in, fp, &warn);
10035 if (warn) {
Tim Duesterhuse8aa5f22020-02-19 11:41:13 +010010036 ha_warning("%s", warn);
Emmanuel Hocdet70df7bf2019-01-04 11:08:20 +010010037 free(warn);
10038 warn = NULL;
10039 }
10040 next:
10041 if (in)
10042 BIO_free(in);
10043 }
10044 free(de_list);
10045
10046 return 0;
10047}
10048
Grant Zhangfa6c7ee2017-01-14 01:42:15 +000010049/* parse the "ssl-mode-async" keyword in global section.
10050 * Returns <0 on alert, >0 on warning, 0 on success.
10051 */
10052static int ssl_parse_global_ssl_async(char **args, int section_type, struct proxy *curpx,
10053 struct proxy *defpx, const char *file, int line,
10054 char **err)
10055{
Willy Tarreau5db847a2019-05-09 14:13:35 +020010056#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +000010057 global_ssl.async = 1;
Emeric Brunece0c332017-12-06 13:51:49 +010010058 global.ssl_used_async_engines = nb_engines;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +000010059 return 0;
10060#else
10061 memprintf(err, "'%s': openssl library does not support async mode", args[0]);
10062 return -1;
10063#endif
10064}
10065
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020010066#ifndef OPENSSL_NO_ENGINE
Grant Zhangfa6c7ee2017-01-14 01:42:15 +000010067static int ssl_check_async_engine_count(void) {
10068 int err_code = 0;
10069
Emeric Brun3854e012017-05-17 20:42:48 +020010070 if (global_ssl.async && (openssl_engines_initialized > 32)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +010010071 ha_alert("ssl-mode-async only supports a maximum of 32 engines.\n");
Grant Zhangfa6c7ee2017-01-14 01:42:15 +000010072 err_code = ERR_ABORT;
10073 }
10074 return err_code;
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +010010075}
10076
Grant Zhang872f9c22017-01-21 01:10:18 +000010077/* parse the "ssl-engine" keyword in global section.
10078 * Returns <0 on alert, >0 on warning, 0 on success.
10079 */
10080static int ssl_parse_global_ssl_engine(char **args, int section_type, struct proxy *curpx,
10081 struct proxy *defpx, const char *file, int line,
10082 char **err)
10083{
10084 char *algo;
10085 int ret = -1;
10086
10087 if (*(args[1]) == 0) {
10088 memprintf(err, "global statement '%s' expects a valid engine name as an argument.", args[0]);
10089 return ret;
10090 }
10091
10092 if (*(args[2]) == 0) {
10093 /* if no list of algorithms is given, it defaults to ALL */
10094 algo = strdup("ALL");
10095 goto add_engine;
10096 }
10097
10098 /* otherwise the expected format is ssl-engine <engine_name> algo <list of algo> */
10099 if (strcmp(args[2], "algo") != 0) {
10100 memprintf(err, "global statement '%s' expects to have algo keyword.", args[0]);
10101 return ret;
10102 }
10103
10104 if (*(args[3]) == 0) {
10105 memprintf(err, "global statement '%s' expects algorithm names as an argument.", args[0]);
10106 return ret;
10107 }
10108 algo = strdup(args[3]);
10109
10110add_engine:
10111 if (ssl_init_single_engine(args[1], algo)==0) {
10112 openssl_engines_initialized++;
10113 ret = 0;
10114 }
10115 free(algo);
10116 return ret;
10117}
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020010118#endif
Grant Zhang872f9c22017-01-21 01:10:18 +000010119
Willy Tarreauf22e9682016-12-21 23:23:19 +010010120/* parse the "ssl-default-bind-ciphers" / "ssl-default-server-ciphers" keywords
10121 * in global section. Returns <0 on alert, >0 on warning, 0 on success.
10122 */
10123static int ssl_parse_global_ciphers(char **args, int section_type, struct proxy *curpx,
10124 struct proxy *defpx, const char *file, int line,
10125 char **err)
10126{
10127 char **target;
10128
Willy Tarreauef934602016-12-22 23:12:01 +010010129 target = (args[0][12] == 'b') ? &global_ssl.listen_default_ciphers : &global_ssl.connect_default_ciphers;
Willy Tarreauf22e9682016-12-21 23:23:19 +010010130
10131 if (too_many_args(1, args, err, NULL))
10132 return -1;
10133
10134 if (*(args[1]) == 0) {
10135 memprintf(err, "global statement '%s' expects a cipher suite as an argument.", args[0]);
10136 return -1;
10137 }
10138
10139 free(*target);
10140 *target = strdup(args[1]);
10141 return 0;
10142}
Dirkjan Bussink415150f2018-09-14 11:14:21 +020010143
Emmanuel Hocdet839af572019-05-14 16:27:35 +020010144#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +020010145/* parse the "ssl-default-bind-ciphersuites" / "ssl-default-server-ciphersuites" keywords
10146 * in global section. Returns <0 on alert, >0 on warning, 0 on success.
10147 */
10148static int ssl_parse_global_ciphersuites(char **args, int section_type, struct proxy *curpx,
10149 struct proxy *defpx, const char *file, int line,
10150 char **err)
10151{
10152 char **target;
10153
10154 target = (args[0][12] == 'b') ? &global_ssl.listen_default_ciphersuites : &global_ssl.connect_default_ciphersuites;
10155
10156 if (too_many_args(1, args, err, NULL))
10157 return -1;
10158
10159 if (*(args[1]) == 0) {
10160 memprintf(err, "global statement '%s' expects a cipher suite as an argument.", args[0]);
10161 return -1;
10162 }
10163
10164 free(*target);
10165 *target = strdup(args[1]);
10166 return 0;
10167}
10168#endif
Willy Tarreauf22e9682016-12-21 23:23:19 +010010169
Willy Tarreau9ceda382016-12-21 23:13:03 +010010170/* parse various global tune.ssl settings consisting in positive integers.
10171 * Returns <0 on alert, >0 on warning, 0 on success.
10172 */
10173static int ssl_parse_global_int(char **args, int section_type, struct proxy *curpx,
10174 struct proxy *defpx, const char *file, int line,
10175 char **err)
10176{
10177 int *target;
10178
10179 if (strcmp(args[0], "tune.ssl.cachesize") == 0)
10180 target = &global.tune.sslcachesize;
10181 else if (strcmp(args[0], "tune.ssl.maxrecord") == 0)
Willy Tarreauef934602016-12-22 23:12:01 +010010182 target = (int *)&global_ssl.max_record;
Willy Tarreau9ceda382016-12-21 23:13:03 +010010183 else if (strcmp(args[0], "tune.ssl.ssl-ctx-cache-size") == 0)
Willy Tarreauef934602016-12-22 23:12:01 +010010184 target = &global_ssl.ctx_cache;
Willy Tarreau0bea58d2016-12-21 23:17:25 +010010185 else if (strcmp(args[0], "maxsslconn") == 0)
10186 target = &global.maxsslconn;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +010010187 else if (strcmp(args[0], "tune.ssl.capture-cipherlist-size") == 0)
10188 target = &global_ssl.capture_cipherlist;
Willy Tarreau9ceda382016-12-21 23:13:03 +010010189 else {
10190 memprintf(err, "'%s' keyword not unhandled (please report this bug).", args[0]);
10191 return -1;
10192 }
10193
10194 if (too_many_args(1, args, err, NULL))
10195 return -1;
10196
10197 if (*(args[1]) == 0) {
10198 memprintf(err, "'%s' expects an integer argument.", args[0]);
10199 return -1;
10200 }
10201
10202 *target = atoi(args[1]);
10203 if (*target < 0) {
10204 memprintf(err, "'%s' expects a positive numeric value.", args[0]);
10205 return -1;
10206 }
10207 return 0;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +010010208}
10209
10210static int ssl_parse_global_capture_cipherlist(char **args, int section_type, struct proxy *curpx,
10211 struct proxy *defpx, const char *file, int line,
10212 char **err)
10213{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +010010214 int ret;
10215
10216 ret = ssl_parse_global_int(args, section_type, curpx, defpx, file, line, err);
10217 if (ret != 0)
10218 return ret;
10219
Willy Tarreaubafbe012017-11-24 17:34:44 +010010220 if (pool_head_ssl_capture) {
Thierry FOURNIER5bf77322017-02-25 12:45:22 +010010221 memprintf(err, "'%s' is already configured.", args[0]);
10222 return -1;
10223 }
10224
Willy Tarreaubafbe012017-11-24 17:34:44 +010010225 pool_head_ssl_capture = create_pool("ssl-capture", sizeof(struct ssl_capture) + global_ssl.capture_cipherlist, MEM_F_SHARED);
10226 if (!pool_head_ssl_capture) {
Thierry FOURNIER5bf77322017-02-25 12:45:22 +010010227 memprintf(err, "Out of memory error.");
10228 return -1;
10229 }
10230 return 0;
Willy Tarreau9ceda382016-12-21 23:13:03 +010010231}
10232
10233/* parse "ssl.force-private-cache".
10234 * Returns <0 on alert, >0 on warning, 0 on success.
10235 */
10236static int ssl_parse_global_private_cache(char **args, int section_type, struct proxy *curpx,
10237 struct proxy *defpx, const char *file, int line,
10238 char **err)
10239{
10240 if (too_many_args(0, args, err, NULL))
10241 return -1;
10242
Willy Tarreauef934602016-12-22 23:12:01 +010010243 global_ssl.private_cache = 1;
Willy Tarreau9ceda382016-12-21 23:13:03 +010010244 return 0;
10245}
10246
10247/* parse "ssl.lifetime".
10248 * Returns <0 on alert, >0 on warning, 0 on success.
10249 */
10250static int ssl_parse_global_lifetime(char **args, int section_type, struct proxy *curpx,
10251 struct proxy *defpx, const char *file, int line,
10252 char **err)
10253{
10254 const char *res;
10255
10256 if (too_many_args(1, args, err, NULL))
10257 return -1;
10258
10259 if (*(args[1]) == 0) {
10260 memprintf(err, "'%s' expects ssl sessions <lifetime> in seconds as argument.", args[0]);
10261 return -1;
10262 }
10263
Willy Tarreauef934602016-12-22 23:12:01 +010010264 res = parse_time_err(args[1], &global_ssl.life_time, TIME_UNIT_S);
Willy Tarreau9faebe32019-06-07 19:00:37 +020010265 if (res == PARSE_TIME_OVER) {
10266 memprintf(err, "timer overflow in argument '%s' to <%s> (maximum value is 2147483647 s or ~68 years).",
10267 args[1], args[0]);
10268 return -1;
10269 }
10270 else if (res == PARSE_TIME_UNDER) {
10271 memprintf(err, "timer underflow in argument '%s' to <%s> (minimum non-null value is 1 s).",
10272 args[1], args[0]);
10273 return -1;
10274 }
10275 else if (res) {
Willy Tarreau9ceda382016-12-21 23:13:03 +010010276 memprintf(err, "unexpected character '%c' in argument to <%s>.", *res, args[0]);
10277 return -1;
10278 }
10279 return 0;
10280}
10281
10282#ifndef OPENSSL_NO_DH
Willy Tarreau14e36a12016-12-21 23:28:13 +010010283/* parse "ssl-dh-param-file".
10284 * Returns <0 on alert, >0 on warning, 0 on success.
10285 */
10286static int ssl_parse_global_dh_param_file(char **args, int section_type, struct proxy *curpx,
10287 struct proxy *defpx, const char *file, int line,
10288 char **err)
10289{
10290 if (too_many_args(1, args, err, NULL))
10291 return -1;
10292
10293 if (*(args[1]) == 0) {
10294 memprintf(err, "'%s' expects a file path as an argument.", args[0]);
10295 return -1;
10296 }
10297
10298 if (ssl_sock_load_global_dh_param_from_file(args[1])) {
10299 memprintf(err, "'%s': unable to load DH parameters from file <%s>.", args[0], args[1]);
10300 return -1;
10301 }
10302 return 0;
10303}
10304
Willy Tarreau9ceda382016-12-21 23:13:03 +010010305/* parse "ssl.default-dh-param".
10306 * Returns <0 on alert, >0 on warning, 0 on success.
10307 */
10308static int ssl_parse_global_default_dh(char **args, int section_type, struct proxy *curpx,
10309 struct proxy *defpx, const char *file, int line,
10310 char **err)
10311{
10312 if (too_many_args(1, args, err, NULL))
10313 return -1;
10314
10315 if (*(args[1]) == 0) {
10316 memprintf(err, "'%s' expects an integer argument.", args[0]);
10317 return -1;
10318 }
10319
Willy Tarreauef934602016-12-22 23:12:01 +010010320 global_ssl.default_dh_param = atoi(args[1]);
10321 if (global_ssl.default_dh_param < 1024) {
Willy Tarreau9ceda382016-12-21 23:13:03 +010010322 memprintf(err, "'%s' expects a value >= 1024.", args[0]);
10323 return -1;
10324 }
10325 return 0;
10326}
10327#endif
10328
William Lallemand3af48e72020-02-03 17:15:52 +010010329
10330/*
10331 * parse "ssl-load-extra-files".
10332 * multiple arguments are allowed: "bundle", "sctl", "ocsp", "issuer", "all", "none"
10333 */
10334static int ssl_parse_global_extra_files(char **args, int section_type, struct proxy *curpx,
10335 struct proxy *defpx, const char *file, int line,
10336 char **err)
10337{
10338 int i;
10339 int gf = SSL_GF_NONE;
10340
10341 if (*(args[1]) == 0)
10342 goto err_arg;
10343
10344 for (i = 1; *args[i]; i++) {
10345
10346 if (!strcmp("bundle", args[i])) {
10347 gf |= SSL_GF_BUNDLE;
10348
10349 } else if (!strcmp("sctl", args[i])) {
10350 gf |= SSL_GF_SCTL;
10351
10352 } else if (!strcmp("ocsp", args[i])){
10353 gf |= SSL_GF_OCSP;
10354
10355 } else if (!strcmp("issuer", args[i])){
10356 gf |= SSL_GF_OCSP_ISSUER;
10357
William Lallemand4c5adbf2020-02-24 14:23:22 +010010358 } else if (!strcmp("key", args[i])) {
10359 gf |= SSL_GF_KEY;
10360
William Lallemand3af48e72020-02-03 17:15:52 +010010361 } else if (!strcmp("none", args[i])) {
10362 if (gf != SSL_GF_NONE)
10363 goto err_alone;
10364 gf = SSL_GF_NONE;
10365 i++;
10366 break;
10367
10368 } else if (!strcmp("all", args[i])) {
10369 if (gf != SSL_GF_NONE)
10370 goto err_alone;
10371 gf = SSL_GF_ALL;
10372 i++;
10373 break;
10374 } else {
10375 goto err_arg;
10376 }
10377 }
10378 /* break from loop but there are still arguments */
10379 if (*args[i])
10380 goto err_alone;
10381
10382 global_ssl.extra_files = gf;
10383
10384 return 0;
10385
10386err_alone:
10387 memprintf(err, "'%s' 'none' and 'all' can be only used alone", args[0]);
10388 return -1;
10389
10390err_arg:
10391 memprintf(err, "'%s' expects one or multiple arguments (none, all, bundle, sctl, ocsp, issuer).", args[0]);
10392 return -1;
10393}
10394
Willy Tarreau9ceda382016-12-21 23:13:03 +010010395
William Lallemand32af2032016-10-29 18:09:35 +020010396/* This function is used with TLS ticket keys management. It permits to browse
10397 * each reference. The variable <getnext> must contain the current node,
10398 * <end> point to the root node.
10399 */
10400#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
10401static inline
10402struct tls_keys_ref *tlskeys_list_get_next(struct tls_keys_ref *getnext, struct list *end)
10403{
10404 struct tls_keys_ref *ref = getnext;
10405
10406 while (1) {
10407
10408 /* Get next list entry. */
10409 ref = LIST_NEXT(&ref->list, struct tls_keys_ref *, list);
10410
10411 /* If the entry is the last of the list, return NULL. */
10412 if (&ref->list == end)
10413 return NULL;
10414
10415 return ref;
10416 }
10417}
10418
10419static inline
10420struct tls_keys_ref *tlskeys_ref_lookup_ref(const char *reference)
10421{
10422 int id;
10423 char *error;
10424
10425 /* If the reference starts by a '#', this is numeric id. */
10426 if (reference[0] == '#') {
10427 /* Try to convert the numeric id. If the conversion fails, the lookup fails. */
10428 id = strtol(reference + 1, &error, 10);
10429 if (*error != '\0')
10430 return NULL;
10431
10432 /* Perform the unique id lookup. */
10433 return tlskeys_ref_lookupid(id);
10434 }
10435
10436 /* Perform the string lookup. */
10437 return tlskeys_ref_lookup(reference);
10438}
10439#endif
10440
10441
10442#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
10443
10444static int cli_io_handler_tlskeys_files(struct appctx *appctx);
10445
10446static inline int cli_io_handler_tlskeys_entries(struct appctx *appctx) {
10447 return cli_io_handler_tlskeys_files(appctx);
10448}
10449
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010450/* dumps all tls keys. Relies on cli.i0 (non-null = only list file names), cli.i1
10451 * (next index to be dumped), and cli.p0 (next key reference).
10452 */
William Lallemand32af2032016-10-29 18:09:35 +020010453static int cli_io_handler_tlskeys_files(struct appctx *appctx) {
10454
10455 struct stream_interface *si = appctx->owner;
10456
10457 switch (appctx->st2) {
10458 case STAT_ST_INIT:
10459 /* Display the column headers. If the message cannot be sent,
Joseph Herlant017b3da2018-11-15 09:07:59 -080010460 * quit the function with returning 0. The function is called
William Lallemand32af2032016-10-29 18:09:35 +020010461 * later and restart at the state "STAT_ST_INIT".
10462 */
10463 chunk_reset(&trash);
10464
10465 if (appctx->io_handler == cli_io_handler_tlskeys_entries)
10466 chunk_appendf(&trash, "# id secret\n");
10467 else
10468 chunk_appendf(&trash, "# id (file)\n");
10469
Willy Tarreau06d80a92017-10-19 14:32:15 +020010470 if (ci_putchk(si_ic(si), &trash) == -1) {
Willy Tarreaudb398432018-11-15 11:08:52 +010010471 si_rx_room_blk(si);
William Lallemand32af2032016-10-29 18:09:35 +020010472 return 0;
10473 }
10474
William Lallemand32af2032016-10-29 18:09:35 +020010475 /* Now, we start the browsing of the references lists.
10476 * Note that the following call to LIST_ELEM return bad pointer. The only
10477 * available field of this pointer is <list>. It is used with the function
10478 * tlskeys_list_get_next() for retruning the first available entry
10479 */
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010480 if (appctx->ctx.cli.p0 == NULL) {
10481 appctx->ctx.cli.p0 = LIST_ELEM(&tlskeys_reference, struct tls_keys_ref *, list);
10482 appctx->ctx.cli.p0 = tlskeys_list_get_next(appctx->ctx.cli.p0, &tlskeys_reference);
William Lallemand32af2032016-10-29 18:09:35 +020010483 }
10484
10485 appctx->st2 = STAT_ST_LIST;
10486 /* fall through */
10487
10488 case STAT_ST_LIST:
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010489 while (appctx->ctx.cli.p0) {
10490 struct tls_keys_ref *ref = appctx->ctx.cli.p0;
William Lallemand32af2032016-10-29 18:09:35 +020010491
10492 chunk_reset(&trash);
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010493 if (appctx->io_handler == cli_io_handler_tlskeys_entries && appctx->ctx.cli.i1 == 0)
William Lallemand32af2032016-10-29 18:09:35 +020010494 chunk_appendf(&trash, "# ");
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010495
10496 if (appctx->ctx.cli.i1 == 0)
10497 chunk_appendf(&trash, "%d (%s)\n", ref->unique_id, ref->filename);
10498
William Lallemand32af2032016-10-29 18:09:35 +020010499 if (appctx->io_handler == cli_io_handler_tlskeys_entries) {
Christopher Faulet16f45c82018-02-16 11:23:49 +010010500 int head;
10501
10502 HA_RWLOCK_RDLOCK(TLSKEYS_REF_LOCK, &ref->lock);
10503 head = ref->tls_ticket_enc_index;
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010504 while (appctx->ctx.cli.i1 < TLS_TICKETS_NO) {
Willy Tarreau83061a82018-07-13 11:56:34 +020010505 struct buffer *t2 = get_trash_chunk();
William Lallemand32af2032016-10-29 18:09:35 +020010506
10507 chunk_reset(t2);
10508 /* should never fail here because we dump only a key in the t2 buffer */
Emeric Brun9e754772019-01-10 17:51:55 +010010509 if (ref->key_size_bits == 128) {
10510 t2->data = a2base64((char *)(ref->tlskeys + (head + 2 + appctx->ctx.cli.i1) % TLS_TICKETS_NO),
10511 sizeof(struct tls_sess_key_128),
10512 t2->area, t2->size);
10513 chunk_appendf(&trash, "%d.%d %s\n", ref->unique_id, appctx->ctx.cli.i1,
10514 t2->area);
10515 }
10516 else if (ref->key_size_bits == 256) {
10517 t2->data = a2base64((char *)(ref->tlskeys + (head + 2 + appctx->ctx.cli.i1) % TLS_TICKETS_NO),
10518 sizeof(struct tls_sess_key_256),
10519 t2->area, t2->size);
10520 chunk_appendf(&trash, "%d.%d %s\n", ref->unique_id, appctx->ctx.cli.i1,
10521 t2->area);
10522 }
10523 else {
10524 /* This case should never happen */
10525 chunk_appendf(&trash, "%d.%d <unknown>\n", ref->unique_id, appctx->ctx.cli.i1);
10526 }
William Lallemand32af2032016-10-29 18:09:35 +020010527
Willy Tarreau06d80a92017-10-19 14:32:15 +020010528 if (ci_putchk(si_ic(si), &trash) == -1) {
William Lallemand32af2032016-10-29 18:09:35 +020010529 /* let's try again later from this stream. We add ourselves into
10530 * this stream's users so that it can remove us upon termination.
10531 */
Christopher Faulet16f45c82018-02-16 11:23:49 +010010532 HA_RWLOCK_RDUNLOCK(TLSKEYS_REF_LOCK, &ref->lock);
Willy Tarreaudb398432018-11-15 11:08:52 +010010533 si_rx_room_blk(si);
William Lallemand32af2032016-10-29 18:09:35 +020010534 return 0;
10535 }
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010536 appctx->ctx.cli.i1++;
William Lallemand32af2032016-10-29 18:09:35 +020010537 }
Christopher Faulet16f45c82018-02-16 11:23:49 +010010538 HA_RWLOCK_RDUNLOCK(TLSKEYS_REF_LOCK, &ref->lock);
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010539 appctx->ctx.cli.i1 = 0;
William Lallemand32af2032016-10-29 18:09:35 +020010540 }
Willy Tarreau06d80a92017-10-19 14:32:15 +020010541 if (ci_putchk(si_ic(si), &trash) == -1) {
William Lallemand32af2032016-10-29 18:09:35 +020010542 /* let's try again later from this stream. We add ourselves into
10543 * this stream's users so that it can remove us upon termination.
10544 */
Willy Tarreaudb398432018-11-15 11:08:52 +010010545 si_rx_room_blk(si);
William Lallemand32af2032016-10-29 18:09:35 +020010546 return 0;
10547 }
10548
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010549 if (appctx->ctx.cli.i0 == 0) /* don't display everything if not necessary */
William Lallemand32af2032016-10-29 18:09:35 +020010550 break;
10551
10552 /* get next list entry and check the end of the list */
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010553 appctx->ctx.cli.p0 = tlskeys_list_get_next(appctx->ctx.cli.p0, &tlskeys_reference);
William Lallemand32af2032016-10-29 18:09:35 +020010554 }
10555
10556 appctx->st2 = STAT_ST_FIN;
10557 /* fall through */
10558
10559 default:
10560 appctx->st2 = STAT_ST_FIN;
10561 return 1;
10562 }
10563 return 0;
10564}
10565
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010566/* sets cli.i0 to non-zero if only file lists should be dumped */
Aurélien Nephtaliabbf6072018-04-18 13:26:46 +020010567static int cli_parse_show_tlskeys(char **args, char *payload, struct appctx *appctx, void *private)
William Lallemand32af2032016-10-29 18:09:35 +020010568{
William Lallemand32af2032016-10-29 18:09:35 +020010569 /* no parameter, shows only file list */
10570 if (!*args[2]) {
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010571 appctx->ctx.cli.i0 = 1;
William Lallemand32af2032016-10-29 18:09:35 +020010572 appctx->io_handler = cli_io_handler_tlskeys_files;
Willy Tarreau3067bfa2016-12-05 14:50:15 +010010573 return 0;
William Lallemand32af2032016-10-29 18:09:35 +020010574 }
10575
10576 if (args[2][0] == '*') {
10577 /* list every TLS ticket keys */
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010578 appctx->ctx.cli.i0 = 1;
William Lallemand32af2032016-10-29 18:09:35 +020010579 } else {
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010580 appctx->ctx.cli.p0 = tlskeys_ref_lookup_ref(args[2]);
Willy Tarreau9d008692019-08-09 11:21:01 +020010581 if (!appctx->ctx.cli.p0)
10582 return cli_err(appctx, "'show tls-keys' unable to locate referenced filename\n");
William Lallemand32af2032016-10-29 18:09:35 +020010583 }
William Lallemand32af2032016-10-29 18:09:35 +020010584 appctx->io_handler = cli_io_handler_tlskeys_entries;
Willy Tarreau3067bfa2016-12-05 14:50:15 +010010585 return 0;
William Lallemand32af2032016-10-29 18:09:35 +020010586}
10587
Aurélien Nephtaliabbf6072018-04-18 13:26:46 +020010588static int cli_parse_set_tlskeys(char **args, char *payload, struct appctx *appctx, void *private)
William Lallemand32af2032016-10-29 18:09:35 +020010589{
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010590 struct tls_keys_ref *ref;
Willy Tarreau1c913e42018-08-22 05:26:57 +020010591 int ret;
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010592
William Lallemand32af2032016-10-29 18:09:35 +020010593 /* Expect two parameters: the filename and the new new TLS key in encoding */
Willy Tarreau9d008692019-08-09 11:21:01 +020010594 if (!*args[3] || !*args[4])
10595 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 +020010596
Willy Tarreauf5f26e82016-12-16 18:47:27 +010010597 ref = tlskeys_ref_lookup_ref(args[3]);
Willy Tarreau9d008692019-08-09 11:21:01 +020010598 if (!ref)
10599 return cli_err(appctx, "'set ssl tls-key' unable to locate referenced filename\n");
William Lallemand32af2032016-10-29 18:09:35 +020010600
Willy Tarreau1c913e42018-08-22 05:26:57 +020010601 ret = base64dec(args[4], strlen(args[4]), trash.area, trash.size);
Willy Tarreau9d008692019-08-09 11:21:01 +020010602 if (ret < 0)
10603 return cli_err(appctx, "'set ssl tls-key' received invalid base64 encoded TLS key.\n");
Emeric Brun9e754772019-01-10 17:51:55 +010010604
Willy Tarreau1c913e42018-08-22 05:26:57 +020010605 trash.data = ret;
Willy Tarreau9d008692019-08-09 11:21:01 +020010606 if (ssl_sock_update_tlskey_ref(ref, &trash) < 0)
10607 return cli_err(appctx, "'set ssl tls-key' received a key of wrong size.\n");
William Lallemand32af2032016-10-29 18:09:35 +020010608
Willy Tarreau9d008692019-08-09 11:21:01 +020010609 return cli_msg(appctx, LOG_INFO, "TLS ticket key updated!\n");
William Lallemand32af2032016-10-29 18:09:35 +020010610}
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +010010611#endif
William Lallemand32af2032016-10-29 18:09:35 +020010612
William Lallemand44b35322019-10-17 16:28:40 +020010613
10614/* Type of SSL payloads that can be updated over the CLI */
10615
10616enum {
10617 CERT_TYPE_PEM = 0,
William Lallemand4c5adbf2020-02-24 14:23:22 +010010618 CERT_TYPE_KEY,
Emmanuel Hocdetf6ac4fa2019-10-30 17:41:27 +010010619#if ((defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP) || defined OPENSSL_IS_BORINGSSL)
William Lallemand44b35322019-10-17 16:28:40 +020010620 CERT_TYPE_OCSP,
Emmanuel Hocdetf6ac4fa2019-10-30 17:41:27 +010010621#endif
William Lallemand44b35322019-10-17 16:28:40 +020010622 CERT_TYPE_ISSUER,
Emmanuel Hocdetf6ac4fa2019-10-30 17:41:27 +010010623#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
William Lallemand44b35322019-10-17 16:28:40 +020010624 CERT_TYPE_SCTL,
Emmanuel Hocdetf6ac4fa2019-10-30 17:41:27 +010010625#endif
William Lallemand44b35322019-10-17 16:28:40 +020010626 CERT_TYPE_MAX,
10627};
10628
10629struct {
10630 const char *ext;
10631 int type;
10632 int (*load)(const char *path, char *payload, struct cert_key_and_chain *ckch, char **err);
10633 /* add a parsing callback */
William Lallemandf29cdef2019-10-23 15:00:52 +020010634} cert_exts[CERT_TYPE_MAX+1] = {
William Lallemand44b35322019-10-17 16:28:40 +020010635 [CERT_TYPE_PEM] = { "", CERT_TYPE_PEM, &ssl_sock_load_pem_into_ckch }, /* default mode, no extensions */
William Lallemand4c5adbf2020-02-24 14:23:22 +010010636 [CERT_TYPE_KEY] = { "key", CERT_TYPE_KEY, &ssl_sock_load_key_into_ckch },
William Lallemand541a5342019-10-23 14:11:54 +020010637#if ((defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP) || defined OPENSSL_IS_BORINGSSL)
William Lallemand44b35322019-10-17 16:28:40 +020010638 [CERT_TYPE_OCSP] = { "ocsp", CERT_TYPE_OCSP, &ssl_sock_load_ocsp_response_from_file },
William Lallemand541a5342019-10-23 14:11:54 +020010639#endif
10640#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
William Lallemand44b35322019-10-17 16:28:40 +020010641 [CERT_TYPE_SCTL] = { "sctl", CERT_TYPE_SCTL, &ssl_sock_load_sctl_from_file },
William Lallemand541a5342019-10-23 14:11:54 +020010642#endif
William Lallemand44b35322019-10-17 16:28:40 +020010643 [CERT_TYPE_ISSUER] = { "issuer", CERT_TYPE_ISSUER, &ssl_sock_load_issuer_file_into_ckch },
William Lallemandf29cdef2019-10-23 15:00:52 +020010644 [CERT_TYPE_MAX] = { NULL, CERT_TYPE_MAX, NULL },
William Lallemand44b35322019-10-17 16:28:40 +020010645};
10646
William Lallemand430413e2019-10-28 14:30:47 +010010647/* states of the CLI IO handler for 'set ssl cert' */
10648enum {
10649 SETCERT_ST_INIT = 0,
10650 SETCERT_ST_GEN,
10651 SETCERT_ST_INSERT,
10652 SETCERT_ST_FIN,
10653};
William Lallemand8f840d72019-10-23 10:53:05 +020010654
William Lallemandd4f946c2019-12-05 10:26:40 +010010655/* release function of the `show ssl cert' command */
10656static void cli_release_show_cert(struct appctx *appctx)
10657{
10658 HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
10659}
10660
10661/* IO handler of "show ssl cert <filename>" */
10662static int cli_io_handler_show_cert(struct appctx *appctx)
10663{
10664 struct buffer *trash = alloc_trash_chunk();
10665 struct ebmb_node *node;
10666 struct stream_interface *si = appctx->owner;
10667 struct ckch_store *ckchs;
William Lallemandd4f946c2019-12-05 10:26:40 +010010668
10669 if (trash == NULL)
10670 return 1;
10671
10672 if (!appctx->ctx.ssl.old_ckchs) {
10673 if (ckchs_transaction.old_ckchs) {
10674 ckchs = ckchs_transaction.old_ckchs;
10675 chunk_appendf(trash, "# transaction\n");
10676 if (!ckchs->multi) {
10677 chunk_appendf(trash, "*%s\n", ckchs->path);
William Lallemandba22e902019-12-18 20:36:01 +010010678#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
William Lallemandd4f946c2019-12-05 10:26:40 +010010679 } else {
William Lallemanda25a19f2020-01-29 00:04:24 +010010680 int n;
10681
William Lallemandd4f946c2019-12-05 10:26:40 +010010682 chunk_appendf(trash, "*%s:", ckchs->path);
10683 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
10684 if (ckchs->ckch[n].cert)
10685 chunk_appendf(trash, " %s.%s\n", ckchs->path, SSL_SOCK_KEYTYPE_NAMES[n]);
10686 }
10687 chunk_appendf(trash, "\n");
William Lallemandba22e902019-12-18 20:36:01 +010010688#endif
William Lallemandd4f946c2019-12-05 10:26:40 +010010689 }
10690 }
10691 }
10692
10693 if (!appctx->ctx.cli.p0) {
10694 chunk_appendf(trash, "# filename\n");
10695 node = ebmb_first(&ckchs_tree);
10696 } else {
10697 node = &((struct ckch_store *)appctx->ctx.cli.p0)->node;
10698 }
10699 while (node) {
10700 ckchs = ebmb_entry(node, struct ckch_store, node);
10701 if (!ckchs->multi) {
10702 chunk_appendf(trash, "%s\n", ckchs->path);
William Lallemandba22e902019-12-18 20:36:01 +010010703#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
William Lallemandd4f946c2019-12-05 10:26:40 +010010704 } else {
William Lallemanda25a19f2020-01-29 00:04:24 +010010705 int n;
10706
William Lallemandd4f946c2019-12-05 10:26:40 +010010707 chunk_appendf(trash, "%s:", ckchs->path);
10708 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
10709 if (ckchs->ckch[n].cert)
10710 chunk_appendf(trash, " %s.%s", ckchs->path, SSL_SOCK_KEYTYPE_NAMES[n]);
10711 }
10712 chunk_appendf(trash, "\n");
William Lallemandba22e902019-12-18 20:36:01 +010010713#endif
William Lallemandd4f946c2019-12-05 10:26:40 +010010714 }
10715
10716 node = ebmb_next(node);
10717 if (ci_putchk(si_ic(si), trash) == -1) {
10718 si_rx_room_blk(si);
10719 goto yield;
10720 }
10721 }
10722
10723 appctx->ctx.cli.p0 = NULL;
10724 free_trash_chunk(trash);
10725 return 1;
10726yield:
10727
10728 free_trash_chunk(trash);
10729 appctx->ctx.cli.p0 = ckchs;
10730 return 0; /* should come back */
10731}
10732
10733/* IO handler of the details "show ssl cert <filename>" */
10734static int cli_io_handler_show_cert_detail(struct appctx *appctx)
10735{
10736 struct stream_interface *si = appctx->owner;
10737 struct ckch_store *ckchs = appctx->ctx.cli.p0;
10738 struct buffer *out = alloc_trash_chunk();
10739 struct buffer *tmp = alloc_trash_chunk();
10740 X509_NAME *name = NULL;
Emmanuel Hocdetcf8cf6c2020-02-18 16:06:14 +010010741 STACK_OF(X509) *chain;
Willy Tarreau105599c2020-02-25 08:59:23 +010010742 unsigned int len = 0;
William Lallemandd4f946c2019-12-05 10:26:40 +010010743 int write = -1;
10744 BIO *bio = NULL;
William Lallemand35f4a9d2020-02-25 11:56:32 +010010745 int i;
William Lallemandd4f946c2019-12-05 10:26:40 +010010746
10747 if (!tmp || !out)
10748 goto end;
10749
10750 if (!ckchs->multi) {
10751 chunk_appendf(out, "Filename: ");
10752 if (ckchs == ckchs_transaction.new_ckchs)
10753 chunk_appendf(out, "*");
10754 chunk_appendf(out, "%s\n", ckchs->path);
Emmanuel Hocdetcf8cf6c2020-02-18 16:06:14 +010010755
10756 chain = ckchs->ckch->chain;
10757 if (chain == NULL) {
10758 struct issuer_chain *issuer;
10759 issuer = ssl_get_issuer_chain(ckchs->ckch->cert);
10760 if (issuer) {
10761 chain = issuer->chain;
10762 chunk_appendf(out, "Chain Filename: ");
10763 chunk_appendf(out, "%s\n", issuer->path);
10764 }
10765 }
William Lallemandd4f946c2019-12-05 10:26:40 +010010766 chunk_appendf(out, "Serial: ");
10767 if (ssl_sock_get_serial(ckchs->ckch->cert, tmp) == -1)
10768 goto end;
10769 dump_binary(out, tmp->area, tmp->data);
10770 chunk_appendf(out, "\n");
10771
10772 chunk_appendf(out, "notBefore: ");
10773 chunk_reset(tmp);
10774 if ((bio = BIO_new(BIO_s_mem())) == NULL)
10775 goto end;
10776 if (ASN1_TIME_print(bio, X509_getm_notBefore(ckchs->ckch->cert)) == 0)
10777 goto end;
10778 write = BIO_read(bio, tmp->area, tmp->size-1);
10779 tmp->area[write] = '\0';
10780 BIO_free(bio);
10781 chunk_appendf(out, "%s\n", tmp->area);
10782
10783 chunk_appendf(out, "notAfter: ");
10784 chunk_reset(tmp);
10785 if ((bio = BIO_new(BIO_s_mem())) == NULL)
10786 goto end;
10787 if (ASN1_TIME_print(bio, X509_getm_notAfter(ckchs->ckch->cert)) == 0)
10788 goto end;
10789 if ((write = BIO_read(bio, tmp->area, tmp->size-1)) <= 0)
10790 goto end;
10791 tmp->area[write] = '\0';
10792 BIO_free(bio);
10793 chunk_appendf(out, "%s\n", tmp->area);
10794
William Lallemandd4f946c2019-12-05 10:26:40 +010010795#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
10796 chunk_appendf(out, "Subject Alternative Name: ");
10797 if (ssl_sock_get_san_oneline(ckchs->ckch->cert, out) == -1)
10798 goto end;
10799 *(out->area + out->data) = '\0';
10800 chunk_appendf(out, "\n");
10801#endif
10802 chunk_reset(tmp);
10803 chunk_appendf(out, "Algorithm: ");
10804 if (cert_get_pkey_algo(ckchs->ckch->cert, tmp) == 0)
10805 goto end;
10806 chunk_appendf(out, "%s\n", tmp->area);
10807
10808 chunk_reset(tmp);
10809 chunk_appendf(out, "SHA1 FingerPrint: ");
Willy Tarreau105599c2020-02-25 08:59:23 +010010810 if (X509_digest(ckchs->ckch->cert, EVP_sha1(), (unsigned char *) tmp->area, &len) == 0)
William Lallemandd4f946c2019-12-05 10:26:40 +010010811 goto end;
Willy Tarreau105599c2020-02-25 08:59:23 +010010812 tmp->data = len;
William Lallemandd4f946c2019-12-05 10:26:40 +010010813 dump_binary(out, tmp->area, tmp->data);
10814 chunk_appendf(out, "\n");
William Lallemand35f4a9d2020-02-25 11:56:32 +010010815
William Lallemanda90e5932020-02-25 14:07:58 +010010816 chunk_appendf(out, "Subject: ");
10817 if ((name = X509_get_subject_name(ckchs->ckch->cert)) == NULL)
10818 goto end;
10819 if ((ssl_sock_get_dn_oneline(name, tmp)) == -1)
10820 goto end;
10821 *(tmp->area + tmp->data) = '\0';
10822 chunk_appendf(out, "%s\n", tmp->area);
10823
10824 chunk_appendf(out, "Issuer: ");
10825 if ((name = X509_get_issuer_name(ckchs->ckch->cert)) == NULL)
10826 goto end;
10827 if ((ssl_sock_get_dn_oneline(name, tmp)) == -1)
10828 goto end;
10829 *(tmp->area + tmp->data) = '\0';
10830 chunk_appendf(out, "%s\n", tmp->area);
10831
William Lallemand35f4a9d2020-02-25 11:56:32 +010010832 /* Displays subject of each certificate in the chain */
Emmanuel Hocdetcf8cf6c2020-02-18 16:06:14 +010010833 for (i = 0; i < sk_X509_num(chain); i++) {
10834 X509 *ca = sk_X509_value(chain, i);
William Lallemand35f4a9d2020-02-25 11:56:32 +010010835
William Lallemandbb7288a2020-02-25 14:04:33 +010010836 chunk_appendf(out, "Chain Subject: ");
William Lallemand35f4a9d2020-02-25 11:56:32 +010010837 if ((name = X509_get_subject_name(ca)) == NULL)
10838 goto end;
10839 if ((ssl_sock_get_dn_oneline(name, tmp)) == -1)
10840 goto end;
10841 *(tmp->area + tmp->data) = '\0';
10842 chunk_appendf(out, "%s\n", tmp->area);
10843
William Lallemandbb7288a2020-02-25 14:04:33 +010010844 chunk_appendf(out, "Chain Issuer: ");
10845 if ((name = X509_get_issuer_name(ca)) == NULL)
10846 goto end;
10847 if ((ssl_sock_get_dn_oneline(name, tmp)) == -1)
10848 goto end;
10849 *(tmp->area + tmp->data) = '\0';
10850 chunk_appendf(out, "%s\n", tmp->area);
William Lallemand35f4a9d2020-02-25 11:56:32 +010010851 }
William Lallemandd4f946c2019-12-05 10:26:40 +010010852 }
10853
10854 if (ci_putchk(si_ic(si), out) == -1) {
10855 si_rx_room_blk(si);
10856 goto yield;
10857 }
10858
10859end:
10860 free_trash_chunk(tmp);
10861 free_trash_chunk(out);
10862 return 1;
10863yield:
10864 free_trash_chunk(tmp);
10865 free_trash_chunk(out);
10866 return 0; /* should come back */
10867}
10868
10869/* parsing function for 'show ssl cert [certfile]' */
10870static int cli_parse_show_cert(char **args, char *payload, struct appctx *appctx, void *private)
10871{
10872 struct ckch_store *ckchs;
10873
10874 if (!cli_has_level(appctx, ACCESS_LVL_OPER))
10875 return cli_err(appctx, "Can't allocate memory!\n");
10876
10877 /* The operations on the CKCH architecture are locked so we can
10878 * manipulate ckch_store and ckch_inst */
10879 if (HA_SPIN_TRYLOCK(CKCH_LOCK, &ckch_lock))
10880 return cli_err(appctx, "Can't show!\nOperations on certificates are currently locked!\n");
10881
10882 /* check if there is a certificate to lookup */
10883 if (*args[3]) {
10884 if (*args[3] == '*') {
10885 if (!ckchs_transaction.new_ckchs)
10886 goto error;
10887
10888 ckchs = ckchs_transaction.new_ckchs;
10889
10890 if (strcmp(args[3] + 1, ckchs->path))
10891 goto error;
10892
10893 } else {
10894 if ((ckchs = ckchs_lookup(args[3])) == NULL)
10895 goto error;
10896
10897 }
10898
10899 if (ckchs->multi)
10900 goto error;
10901
10902 appctx->ctx.cli.p0 = ckchs;
10903 /* use the IO handler that shows details */
10904 appctx->io_handler = cli_io_handler_show_cert_detail;
10905 }
10906
10907 return 0;
10908
10909error:
10910 HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
10911 return cli_err(appctx, "Can't display the certificate: Not found or the certificate is a bundle!\n");
10912}
10913
William Lallemand430413e2019-10-28 14:30:47 +010010914/* release function of the `set ssl cert' command, free things and unlock the spinlock */
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010915static void cli_release_commit_cert(struct appctx *appctx)
William Lallemand8f840d72019-10-23 10:53:05 +020010916{
10917 struct ckch_store *new_ckchs;
10918 struct ckch_inst *ckchi, *ckchis;
William Lallemand8f840d72019-10-23 10:53:05 +020010919
William Lallemand430413e2019-10-28 14:30:47 +010010920 HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
William Lallemand8f840d72019-10-23 10:53:05 +020010921
William Lallemand430413e2019-10-28 14:30:47 +010010922 if (appctx->st2 != SETCERT_ST_FIN) {
William Lallemand8f840d72019-10-23 10:53:05 +020010923 /* 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 +010010924 new_ckchs = appctx->ctx.ssl.new_ckchs;
William Lallemand8f840d72019-10-23 10:53:05 +020010925
William Lallemandbeea2a42019-10-30 17:45:33 +010010926 if (!new_ckchs)
10927 return;
William Lallemand8f840d72019-10-23 10:53:05 +020010928
William Lallemandbeea2a42019-10-30 17:45:33 +010010929 /* if the allocation failed, we need to free everything from the temporary list */
10930 list_for_each_entry_safe(ckchi, ckchis, &new_ckchs->ckch_inst, by_ckchs) {
10931 struct sni_ctx *sc0, *sc0s;
William Lallemand8f840d72019-10-23 10:53:05 +020010932
William Lallemandbeea2a42019-10-30 17:45:33 +010010933 list_for_each_entry_safe(sc0, sc0s, &ckchi->sni_ctx, by_ckch_inst) {
10934 if (sc0->order == 0) /* we only free if it's the first inserted */
10935 SSL_CTX_free(sc0->ctx);
10936 LIST_DEL(&sc0->by_ckch_inst);
10937 free(sc0);
William Lallemand8f840d72019-10-23 10:53:05 +020010938 }
William Lallemandbeea2a42019-10-30 17:45:33 +010010939 LIST_DEL(&ckchi->by_ckchs);
10940 free(ckchi);
William Lallemand8f840d72019-10-23 10:53:05 +020010941 }
William Lallemandbeea2a42019-10-30 17:45:33 +010010942 ckchs_free(new_ckchs);
William Lallemand8f840d72019-10-23 10:53:05 +020010943 }
10944}
10945
10946
10947/*
10948 * This function tries to create the new ckch_inst and their SNIs
10949 */
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010950static int cli_io_handler_commit_cert(struct appctx *appctx)
William Lallemand8f840d72019-10-23 10:53:05 +020010951{
10952 struct stream_interface *si = appctx->owner;
10953 int y = 0;
10954 char *err = NULL;
10955 int errcode = 0;
10956 struct ckch_store *old_ckchs, *new_ckchs = NULL;
10957 struct ckch_inst *ckchi, *ckchis;
William Lallemand8f840d72019-10-23 10:53:05 +020010958 struct buffer *trash = alloc_trash_chunk();
William Lallemand8ef0c2a2019-11-21 16:30:34 +010010959 struct sni_ctx *sc0, *sc0s;
William Lallemand8f840d72019-10-23 10:53:05 +020010960
William Lallemand33cc76f2019-10-31 11:43:45 +010010961 if (trash == NULL)
10962 goto error;
10963
William Lallemand8f840d72019-10-23 10:53:05 +020010964 if (unlikely(si_ic(si)->flags & (CF_WRITE_ERROR|CF_SHUTW)))
10965 goto error;
10966
William Lallemand430413e2019-10-28 14:30:47 +010010967 while (1) {
10968 switch (appctx->st2) {
10969 case SETCERT_ST_INIT:
10970 /* This state just print the update message */
William Lallemandbc6ca7c2019-10-29 23:48:19 +010010971 chunk_printf(trash, "Committing %s", ckchs_transaction.path);
William Lallemand430413e2019-10-28 14:30:47 +010010972 if (ci_putchk(si_ic(si), trash) == -1) {
10973 si_rx_room_blk(si);
William Lallemand8f840d72019-10-23 10:53:05 +020010974 goto yield;
William Lallemand430413e2019-10-28 14:30:47 +010010975 }
10976 appctx->st2 = SETCERT_ST_GEN;
10977 /* fallthrough */
10978 case SETCERT_ST_GEN:
10979 /*
10980 * This state generates the ckch instances with their
10981 * sni_ctxs and SSL_CTX.
10982 *
William Lallemand430413e2019-10-28 14:30:47 +010010983 * Since the SSL_CTX generation can be CPU consumer, we
10984 * yield every 10 instances.
10985 */
William Lallemand8f840d72019-10-23 10:53:05 +020010986
William Lallemandbeea2a42019-10-30 17:45:33 +010010987 old_ckchs = appctx->ctx.ssl.old_ckchs;
10988 new_ckchs = appctx->ctx.ssl.new_ckchs;
William Lallemand8f840d72019-10-23 10:53:05 +020010989
William Lallemandbeea2a42019-10-30 17:45:33 +010010990 if (!new_ckchs)
10991 continue;
William Lallemand8f840d72019-10-23 10:53:05 +020010992
William Lallemandbeea2a42019-10-30 17:45:33 +010010993 /* get the next ckchi to regenerate */
10994 ckchi = appctx->ctx.ssl.next_ckchi;
10995 /* we didn't start yet, set it to the first elem */
10996 if (ckchi == NULL)
10997 ckchi = LIST_ELEM(old_ckchs->ckch_inst.n, typeof(ckchi), by_ckchs);
William Lallemand8f840d72019-10-23 10:53:05 +020010998
William Lallemandbeea2a42019-10-30 17:45:33 +010010999 /* walk through the old ckch_inst and creates new ckch_inst using the updated ckchs */
11000 list_for_each_entry_from(ckchi, &old_ckchs->ckch_inst, by_ckchs) {
11001 struct ckch_inst *new_inst;
William Lallemand38df1c82019-12-04 15:39:35 +010011002 char **sni_filter = NULL;
11003 int fcount = 0;
William Lallemand8f840d72019-10-23 10:53:05 +020011004
William Lallemandbeea2a42019-10-30 17:45:33 +010011005 /* it takes a lot of CPU to creates SSL_CTXs, so we yield every 10 CKCH instances */
11006 if (y >= 10) {
11007 /* save the next ckchi to compute */
11008 appctx->ctx.ssl.next_ckchi = ckchi;
11009 goto yield;
11010 }
William Lallemand67630162020-03-09 16:56:39 +010011011 if (ckchi->filters) {
11012 errcode |= ckch_inst_sni_ctx_to_sni_filters(ckchi, &sni_filter, &fcount, &err);
11013 if (errcode & ERR_CODE)
11014 goto error;
11015 }
William Lallemand38df1c82019-12-04 15:39:35 +010011016
William Lallemandbeea2a42019-10-30 17:45:33 +010011017 if (new_ckchs->multi)
William Lallemand38df1c82019-12-04 15:39:35 +010011018 errcode |= ckch_inst_new_load_multi_store(new_ckchs->path, new_ckchs, ckchi->bind_conf, ckchi->ssl_conf, sni_filter, fcount, &new_inst, &err);
William Lallemandbeea2a42019-10-30 17:45:33 +010011019 else
William Lallemand38df1c82019-12-04 15:39:35 +010011020 errcode |= ckch_inst_new_load_store(new_ckchs->path, new_ckchs, ckchi->bind_conf, ckchi->ssl_conf, sni_filter, fcount, &new_inst, &err);
11021
11022 free_sni_filters(sni_filter, fcount);
11023 sni_filter = NULL;
William Lallemand8f840d72019-10-23 10:53:05 +020011024
William Lallemandbeea2a42019-10-30 17:45:33 +010011025 if (errcode & ERR_CODE)
11026 goto error;
William Lallemand8f840d72019-10-23 10:53:05 +020011027
William Lallemand21724f02019-11-04 17:56:13 +010011028 /* if the previous ckchi was used as the default */
11029 if (ckchi->is_default)
11030 new_inst->is_default = 1;
11031
William Lallemand8ef0c2a2019-11-21 16:30:34 +010011032 /* we need to initialize the SSL_CTX generated */
William Lallemand696f3172020-02-07 20:45:24 +010011033 /* this iterate on the newly generated SNIs in the new instance to prepare their SSL_CTX */
11034 list_for_each_entry_safe(sc0, sc0s, &new_inst->sni_ctx, by_ckch_inst) {
William Lallemand8ef0c2a2019-11-21 16:30:34 +010011035 if (!sc0->order) { /* we initiliazed only the first SSL_CTX because it's the same in the other sni_ctx's */
11036 errcode |= ssl_sock_prepare_ctx(ckchi->bind_conf, ckchi->ssl_conf, sc0->ctx, &err);
11037 if (errcode & ERR_CODE)
11038 goto error;
11039 }
11040 }
11041
11042
William Lallemandbeea2a42019-10-30 17:45:33 +010011043 /* display one dot per new instance */
11044 chunk_appendf(trash, ".");
11045 /* link the new ckch_inst to the duplicate */
11046 LIST_ADDQ(&new_ckchs->ckch_inst, &new_inst->by_ckchs);
11047 y++;
11048 }
William Lallemand430413e2019-10-28 14:30:47 +010011049 appctx->st2 = SETCERT_ST_INSERT;
11050 /* fallthrough */
11051 case SETCERT_ST_INSERT:
11052 /* The generation is finished, we can insert everything */
William Lallemand8f840d72019-10-23 10:53:05 +020011053
William Lallemandbeea2a42019-10-30 17:45:33 +010011054 old_ckchs = appctx->ctx.ssl.old_ckchs;
11055 new_ckchs = appctx->ctx.ssl.new_ckchs;
William Lallemand8f840d72019-10-23 10:53:05 +020011056
William Lallemandbeea2a42019-10-30 17:45:33 +010011057 if (!new_ckchs)
11058 continue;
William Lallemand430413e2019-10-28 14:30:47 +010011059
William Lallemand21724f02019-11-04 17:56:13 +010011060 /* First, we insert every new SNIs in the trees, also replace the default_ctx */
William Lallemandbeea2a42019-10-30 17:45:33 +010011061 list_for_each_entry_safe(ckchi, ckchis, &new_ckchs->ckch_inst, by_ckchs) {
11062 HA_RWLOCK_WRLOCK(SNI_LOCK, &ckchi->bind_conf->sni_lock);
11063 ssl_sock_load_cert_sni(ckchi, ckchi->bind_conf);
11064 HA_RWLOCK_WRUNLOCK(SNI_LOCK, &ckchi->bind_conf->sni_lock);
11065 }
William Lallemand8f840d72019-10-23 10:53:05 +020011066
William Lallemandbeea2a42019-10-30 17:45:33 +010011067 /* delete the old sni_ctx, the old ckch_insts and the ckch_store */
11068 list_for_each_entry_safe(ckchi, ckchis, &old_ckchs->ckch_inst, by_ckchs) {
William Lallemand430413e2019-10-28 14:30:47 +010011069
William Lallemandbeea2a42019-10-30 17:45:33 +010011070 HA_RWLOCK_WRLOCK(SNI_LOCK, &ckchi->bind_conf->sni_lock);
11071 list_for_each_entry_safe(sc0, sc0s, &ckchi->sni_ctx, by_ckch_inst) {
11072 ebmb_delete(&sc0->name);
11073 LIST_DEL(&sc0->by_ckch_inst);
11074 free(sc0);
William Lallemand430413e2019-10-28 14:30:47 +010011075 }
William Lallemandbeea2a42019-10-30 17:45:33 +010011076 HA_RWLOCK_WRUNLOCK(SNI_LOCK, &ckchi->bind_conf->sni_lock);
11077 LIST_DEL(&ckchi->by_ckchs);
11078 free(ckchi);
11079 }
William Lallemand8f840d72019-10-23 10:53:05 +020011080
William Lallemandbeea2a42019-10-30 17:45:33 +010011081 /* Replace the old ckchs by the new one */
11082 ebmb_delete(&old_ckchs->node);
11083 ckchs_free(old_ckchs);
11084 ebst_insert(&ckchs_tree, &new_ckchs->node);
William Lallemand430413e2019-10-28 14:30:47 +010011085 appctx->st2 = SETCERT_ST_FIN;
11086 /* fallthrough */
11087 case SETCERT_ST_FIN:
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011088 /* we achieved the transaction, we can set everything to NULL */
11089 free(ckchs_transaction.path);
11090 ckchs_transaction.path = NULL;
11091 ckchs_transaction.new_ckchs = NULL;
11092 ckchs_transaction.old_ckchs = NULL;
William Lallemand430413e2019-10-28 14:30:47 +010011093 goto end;
11094 }
William Lallemand8f840d72019-10-23 10:53:05 +020011095 }
William Lallemand430413e2019-10-28 14:30:47 +010011096end:
William Lallemand8f840d72019-10-23 10:53:05 +020011097
William Lallemanded442432019-11-21 16:41:07 +010011098 chunk_appendf(trash, "\n");
11099 if (errcode & ERR_WARN)
Tim Duesterhusc0e820c2019-11-23 23:52:30 +010011100 chunk_appendf(trash, "%s", err);
William Lallemanded442432019-11-21 16:41:07 +010011101 chunk_appendf(trash, "Success!\n");
William Lallemand430413e2019-10-28 14:30:47 +010011102 if (ci_putchk(si_ic(si), trash) == -1)
11103 si_rx_room_blk(si);
11104 free_trash_chunk(trash);
11105 /* success: call the release function and don't come back */
11106 return 1;
William Lallemand8f840d72019-10-23 10:53:05 +020011107yield:
11108 /* store the state */
11109 if (ci_putchk(si_ic(si), trash) == -1)
11110 si_rx_room_blk(si);
11111 free_trash_chunk(trash);
11112 si_rx_endp_more(si); /* let's come back later */
William Lallemand8f840d72019-10-23 10:53:05 +020011113 return 0; /* should come back */
11114
11115error:
11116 /* spin unlock and free are done in the release function */
William Lallemand33cc76f2019-10-31 11:43:45 +010011117 if (trash) {
11118 chunk_appendf(trash, "\n%sFailed!\n", err);
11119 if (ci_putchk(si_ic(si), trash) == -1)
11120 si_rx_room_blk(si);
11121 free_trash_chunk(trash);
11122 }
William Lallemand430413e2019-10-28 14:30:47 +010011123 /* error: call the release function and don't come back */
11124 return 1;
William Lallemand8f840d72019-10-23 10:53:05 +020011125}
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011126
11127/*
11128 * Parsing function of 'commit ssl cert'
11129 */
11130static int cli_parse_commit_cert(char **args, char *payload, struct appctx *appctx, void *private)
11131{
11132 char *err = NULL;
11133
William Lallemand230662a2019-12-03 13:32:54 +010011134 if (!cli_has_level(appctx, ACCESS_LVL_ADMIN))
11135 return 1;
11136
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011137 if (!*args[3])
11138 return cli_err(appctx, "'commit ssl cert expects a filename\n");
11139
11140 /* The operations on the CKCH architecture are locked so we can
11141 * manipulate ckch_store and ckch_inst */
11142 if (HA_SPIN_TRYLOCK(CKCH_LOCK, &ckch_lock))
11143 return cli_err(appctx, "Can't commit the certificate!\nOperations on certificates are currently locked!\n");
11144
11145 if (!ckchs_transaction.path) {
11146 memprintf(&err, "No ongoing transaction! !\n");
11147 goto error;
11148 }
11149
11150 if (strcmp(ckchs_transaction.path, args[3]) != 0) {
11151 memprintf(&err, "The ongoing transaction is about '%s' but you are trying to set '%s'\n", ckchs_transaction.path, args[3]);
11152 goto error;
11153 }
11154
William Lallemand4c5adbf2020-02-24 14:23:22 +010011155#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
11156 if (ckchs_transaction.new_ckchs->multi) {
11157 int n;
11158
11159 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
11160 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)) {
11161 memprintf(&err, "inconsistencies between private key and certificate loaded '%s'.\n", ckchs_transaction.path);
11162 goto error;
11163 }
11164 }
11165 } else
11166#endif
11167 {
11168 if (!X509_check_private_key(ckchs_transaction.new_ckchs->ckch->cert, ckchs_transaction.new_ckchs->ckch->key)) {
11169 memprintf(&err, "inconsistencies between private key and certificate loaded '%s'.\n", ckchs_transaction.path);
11170 goto error;
11171 }
11172 }
11173
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011174 /* init the appctx structure */
11175 appctx->st2 = SETCERT_ST_INIT;
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011176 appctx->ctx.ssl.next_ckchi = NULL;
11177 appctx->ctx.ssl.new_ckchs = ckchs_transaction.new_ckchs;
11178 appctx->ctx.ssl.old_ckchs = ckchs_transaction.old_ckchs;
11179
11180 /* we don't unlock there, it will be unlock after the IO handler, in the release handler */
11181 return 0;
11182
11183error:
11184
11185 HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
11186 err = memprintf(&err, "%sCan't commit %s!\n", err ? err : "", args[3]);
11187
11188 return cli_dynerr(appctx, err);
11189}
11190
William Lallemand8f840d72019-10-23 10:53:05 +020011191/*
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011192 * Parsing function of `set ssl cert`, it updates or creates a temporary ckch.
William Lallemand8f840d72019-10-23 10:53:05 +020011193 */
William Lallemand150bfa82019-09-19 17:12:49 +020011194static int cli_parse_set_cert(char **args, char *payload, struct appctx *appctx, void *private)
11195{
William Lallemand0c3b7d92019-10-18 11:27:07 +020011196 struct ckch_store *new_ckchs = NULL;
William Lallemand8f840d72019-10-23 10:53:05 +020011197 struct ckch_store *old_ckchs = NULL;
William Lallemand150bfa82019-09-19 17:12:49 +020011198 char *err = NULL;
William Lallemand963b2e72019-10-14 11:38:36 +020011199 int i;
William Lallemand849eed62019-10-17 16:23:50 +020011200 int bundle = -1; /* TRUE if >= 0 (ckch index) */
Emeric Brunf69ed1d2019-10-17 11:56:56 +020011201 int errcode = 0;
William Lallemand44b35322019-10-17 16:28:40 +020011202 char *end;
11203 int type = CERT_TYPE_PEM;
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011204 struct cert_key_and_chain *ckch;
11205 struct buffer *buf;
William Lallemand8f840d72019-10-23 10:53:05 +020011206
William Lallemand230662a2019-12-03 13:32:54 +010011207 if (!cli_has_level(appctx, ACCESS_LVL_ADMIN))
11208 return 1;
11209
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011210 if ((buf = alloc_trash_chunk()) == NULL)
11211 return cli_err(appctx, "Can't allocate memory\n");
William Lallemand150bfa82019-09-19 17:12:49 +020011212
11213 if (!*args[3] || !payload)
11214 return cli_err(appctx, "'set ssl cert expects a filename and a certificat as a payload\n");
11215
11216 /* The operations on the CKCH architecture are locked so we can
11217 * manipulate ckch_store and ckch_inst */
11218 if (HA_SPIN_TRYLOCK(CKCH_LOCK, &ckch_lock))
11219 return cli_err(appctx, "Can't update the certificate!\nOperations on certificates are currently locked!\n");
11220
William Lallemand8f840d72019-10-23 10:53:05 +020011221 if (!chunk_strcpy(buf, args[3])) {
11222 memprintf(&err, "%sCan't allocate memory\n", err ? err : "");
11223 errcode |= ERR_ALERT | ERR_FATAL;
11224 goto end;
11225 }
11226
William Lallemand44b35322019-10-17 16:28:40 +020011227 /* check which type of file we want to update */
William Lallemandf29cdef2019-10-23 15:00:52 +020011228 for (i = 0; cert_exts[i].type < CERT_TYPE_MAX; i++) {
William Lallemand8f840d72019-10-23 10:53:05 +020011229 end = strrchr(buf->area, '.');
William Lallemand44b35322019-10-17 16:28:40 +020011230 if (end && *cert_exts[i].ext && (!strcmp(end + 1, cert_exts[i].ext))) {
11231 *end = '\0';
11232 type = cert_exts[i].type;
11233 break;
11234 }
11235 }
11236
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011237 appctx->ctx.ssl.old_ckchs = NULL;
11238 appctx->ctx.ssl.new_ckchs = NULL;
William Lallemand849eed62019-10-17 16:23:50 +020011239
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011240 /* if there is an ongoing transaction */
11241 if (ckchs_transaction.path) {
11242 /* 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 +020011243#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011244 if (ckchs_transaction.new_ckchs->multi) {
Emmanuel Hocdet40f2f1e2019-10-30 17:31:28 +010011245 char *end;
William Lallemand963b2e72019-10-14 11:38:36 +020011246 int j;
William Lallemand150bfa82019-09-19 17:12:49 +020011247
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011248 /* check if it was used in a bundle by removing the
William Lallemand963b2e72019-10-14 11:38:36 +020011249 * .dsa/.rsa/.ecdsa at the end of the filename */
William Lallemand8f840d72019-10-23 10:53:05 +020011250 end = strrchr(buf->area, '.');
Emmanuel Hocdet40f2f1e2019-10-30 17:31:28 +010011251 for (j = 0; end && j < SSL_SOCK_NUM_KEYTYPES; j++) {
William Lallemand963b2e72019-10-14 11:38:36 +020011252 if (!strcmp(end + 1, SSL_SOCK_KEYTYPE_NAMES[j])) {
11253 bundle = j; /* keep the type of certificate so we insert it at the right place */
11254 *end = '\0'; /* it's a bundle let's end the string*/
11255 break;
11256 }
William Lallemand150bfa82019-09-19 17:12:49 +020011257 }
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011258 if (bundle < 0) {
11259 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);
11260 errcode |= ERR_ALERT | ERR_FATAL;
11261 goto end;
11262 }
11263 }
11264#endif
11265
11266 /* if there is an ongoing transaction, check if this is the same file */
11267 if (strcmp(ckchs_transaction.path, buf->area) != 0) {
11268 memprintf(&err, "The ongoing transaction is about '%s' but you are trying to set '%s'\n", ckchs_transaction.path, buf->area);
11269 errcode |= ERR_ALERT | ERR_FATAL;
11270 goto end;
William Lallemand150bfa82019-09-19 17:12:49 +020011271 }
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011272
11273 appctx->ctx.ssl.old_ckchs = ckchs_transaction.new_ckchs;
11274
11275 } else {
11276 struct ckch_store *find_ckchs[2] = { NULL, NULL };
11277
11278 /* lookup for the certificate in the tree:
11279 * check if this is used as a bundle AND as a unique certificate */
11280 for (i = 0; i < 2; i++) {
11281
11282 if ((find_ckchs[i] = ckchs_lookup(buf->area)) != NULL) {
11283 /* only the bundle name is in the tree and you should
11284 * never update a bundle name, only a filename */
11285 if (bundle < 0 && find_ckchs[i]->multi) {
11286 /* we tried to look for a non-bundle and we found a bundle */
11287 memprintf(&err, "%s%s is a multi-cert bundle. Try updating %s.{dsa,rsa,ecdsa}\n",
11288 err ? err : "", args[3], args[3]);
11289 errcode |= ERR_ALERT | ERR_FATAL;
11290 goto end;
11291 }
William Lallemand3246d942019-11-04 14:02:11 +010011292 /* If we want a bundle but this is not a bundle
11293 * example: When you try to update <file>.rsa, but
11294 * <file> is a regular file */
11295 if (bundle >= 0 && find_ckchs[i]->multi == 0) {
11296 find_ckchs[i] = NULL;
11297 break;
11298 }
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011299 }
11300#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
11301 {
Emmanuel Hocdet40f2f1e2019-10-30 17:31:28 +010011302 char *end;
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011303 int j;
11304
11305 /* check if it was used in a bundle by removing the
11306 * .dsa/.rsa/.ecdsa at the end of the filename */
11307 end = strrchr(buf->area, '.');
Emmanuel Hocdet40f2f1e2019-10-30 17:31:28 +010011308 for (j = 0; end && j < SSL_SOCK_NUM_KEYTYPES; j++) {
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011309 if (!strcmp(end + 1, SSL_SOCK_KEYTYPE_NAMES[j])) {
11310 bundle = j; /* keep the type of certificate so we insert it at the right place */
11311 *end = '\0'; /* it's a bundle let's end the string*/
11312 break;
11313 }
11314 }
William Lallemand37031b82019-11-04 13:38:53 +010011315 if (bundle < 0) /* we didn't find a bundle extension */
11316 break;
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011317 }
William Lallemand963b2e72019-10-14 11:38:36 +020011318#else
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011319 /* bundles are not supported here, so we don't need to lookup again */
11320 break;
William Lallemand963b2e72019-10-14 11:38:36 +020011321#endif
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011322 }
11323
11324 if (find_ckchs[0] && find_ckchs[1]) {
11325 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",
11326 err ? err : "", find_ckchs[0]->path, find_ckchs[1]->path);
11327 errcode |= ERR_ALERT | ERR_FATAL;
11328 goto end;
11329 }
11330
11331 appctx->ctx.ssl.old_ckchs = find_ckchs[0] ? find_ckchs[0] : find_ckchs[1];
William Lallemand150bfa82019-09-19 17:12:49 +020011332 }
11333
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011334 if (!appctx->ctx.ssl.old_ckchs) {
11335 memprintf(&err, "%sCan't replace a certificate which is not referenced by the configuration!\n",
William Lallemand150bfa82019-09-19 17:12:49 +020011336 err ? err : "");
Emeric Brunf69ed1d2019-10-17 11:56:56 +020011337 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemand8f840d72019-10-23 10:53:05 +020011338 goto end;
William Lallemand150bfa82019-09-19 17:12:49 +020011339 }
11340
William Lallemand8a7fdf02019-11-04 10:59:32 +010011341 if (!appctx->ctx.ssl.path) {
11342 /* this is a new transaction, set the path of the transaction */
11343 appctx->ctx.ssl.path = strdup(appctx->ctx.ssl.old_ckchs->path);
11344 if (!appctx->ctx.ssl.path) {
11345 memprintf(&err, "%sCan't allocate memory\n", err ? err : "");
11346 errcode |= ERR_ALERT | ERR_FATAL;
11347 goto end;
11348 }
11349 }
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011350
11351 old_ckchs = appctx->ctx.ssl.old_ckchs;
11352
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011353 /* duplicate the ckch store */
11354 new_ckchs = ckchs_dup(old_ckchs);
11355 if (!new_ckchs) {
11356 memprintf(&err, "%sCannot allocate memory!\n",
11357 err ? err : "");
11358 errcode |= ERR_ALERT | ERR_FATAL;
11359 goto end;
11360 }
11361
11362 if (!new_ckchs->multi)
11363 ckch = new_ckchs->ckch;
11364 else
11365 ckch = &new_ckchs->ckch[bundle];
11366
11367 /* appply the change on the duplicate */
11368 if (cert_exts[type].load(buf->area, payload, ckch, &err) != 0) {
11369 memprintf(&err, "%sCan't load the payload\n", err ? err : "");
11370 errcode |= ERR_ALERT | ERR_FATAL;
11371 goto end;
11372 }
11373
11374 appctx->ctx.ssl.new_ckchs = new_ckchs;
11375
11376 /* we succeed, we can save the ckchs in the transaction */
11377
11378 /* if there wasn't a transaction, update the old ckchs */
William Dauchyc8bb1532019-11-24 15:04:20 +010011379 if (!ckchs_transaction.old_ckchs) {
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011380 ckchs_transaction.old_ckchs = appctx->ctx.ssl.old_ckchs;
11381 ckchs_transaction.path = appctx->ctx.ssl.path;
11382 err = memprintf(&err, "Transaction created for certificate %s!\n", ckchs_transaction.path);
11383 } else {
11384 err = memprintf(&err, "Transaction updated for certificate %s!\n", ckchs_transaction.path);
11385
11386 }
11387
11388 /* free the previous ckchs if there was a transaction */
11389 ckchs_free(ckchs_transaction.new_ckchs);
11390
11391 ckchs_transaction.new_ckchs = appctx->ctx.ssl.new_ckchs;
11392
11393
William Lallemand8f840d72019-10-23 10:53:05 +020011394 /* creates the SNI ctxs later in the IO handler */
William Lallemand150bfa82019-09-19 17:12:49 +020011395
William Lallemand8f840d72019-10-23 10:53:05 +020011396end:
11397 free_trash_chunk(buf);
William Lallemand150bfa82019-09-19 17:12:49 +020011398
Emeric Brunf69ed1d2019-10-17 11:56:56 +020011399 if (errcode & ERR_CODE) {
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011400
11401 ckchs_free(appctx->ctx.ssl.new_ckchs);
11402 appctx->ctx.ssl.new_ckchs = NULL;
11403
11404 appctx->ctx.ssl.old_ckchs = NULL;
11405
11406 free(appctx->ctx.ssl.path);
11407 appctx->ctx.ssl.path = NULL;
11408
11409 HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
William Lallemand44b35322019-10-17 16:28:40 +020011410 return cli_dynerr(appctx, memprintf(&err, "%sCan't update %s!\n", err ? err : "", args[3]));
William Lallemand430413e2019-10-28 14:30:47 +010011411 } else {
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011412
11413 HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
11414 return cli_dynmsg(appctx, LOG_NOTICE, err);
William Lallemand430413e2019-10-28 14:30:47 +010011415 }
William Lallemand8f840d72019-10-23 10:53:05 +020011416 /* TODO: handle the ERR_WARN which are not handled because of the io_handler */
William Lallemand150bfa82019-09-19 17:12:49 +020011417}
11418
William Lallemand0bc9c8a2019-11-19 15:51:51 +010011419/* parsing function of 'abort ssl cert' */
11420static int cli_parse_abort_cert(char **args, char *payload, struct appctx *appctx, void *private)
11421{
11422 char *err = NULL;
11423
William Lallemand230662a2019-12-03 13:32:54 +010011424 if (!cli_has_level(appctx, ACCESS_LVL_ADMIN))
11425 return 1;
11426
William Lallemand0bc9c8a2019-11-19 15:51:51 +010011427 if (!*args[3])
11428 return cli_err(appctx, "'abort ssl cert' expects a filename\n");
11429
11430 /* The operations on the CKCH architecture are locked so we can
11431 * manipulate ckch_store and ckch_inst */
11432 if (HA_SPIN_TRYLOCK(CKCH_LOCK, &ckch_lock))
11433 return cli_err(appctx, "Can't abort!\nOperations on certificates are currently locked!\n");
11434
11435 if (!ckchs_transaction.path) {
11436 memprintf(&err, "No ongoing transaction!\n");
11437 goto error;
11438 }
11439
11440 if (strcmp(ckchs_transaction.path, args[3]) != 0) {
11441 memprintf(&err, "The ongoing transaction is about '%s' but you are trying to abort a transaction for '%s'\n", ckchs_transaction.path, args[3]);
11442 goto error;
11443 }
11444
11445 /* Only free the ckchs there, because the SNI and instances were not generated yet */
11446 ckchs_free(ckchs_transaction.new_ckchs);
11447 ckchs_transaction.new_ckchs = NULL;
11448 ckchs_free(ckchs_transaction.old_ckchs);
11449 ckchs_transaction.old_ckchs = NULL;
11450 free(ckchs_transaction.path);
11451 ckchs_transaction.path = NULL;
11452
11453 HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
11454
11455 err = memprintf(&err, "Transaction aborted for certificate '%s'!\n", args[3]);
11456 return cli_dynmsg(appctx, LOG_NOTICE, err);
11457
11458error:
11459 HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
11460
11461 return cli_dynerr(appctx, err);
11462}
11463
Aurélien Nephtaliabbf6072018-04-18 13:26:46 +020011464static int cli_parse_set_ocspresponse(char **args, char *payload, struct appctx *appctx, void *private)
William Lallemand32af2032016-10-29 18:09:35 +020011465{
11466#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
11467 char *err = NULL;
Willy Tarreau1c913e42018-08-22 05:26:57 +020011468 int i, j, ret;
Aurélien Nephtali1e0867c2018-04-18 14:04:58 +020011469
11470 if (!payload)
11471 payload = args[3];
William Lallemand32af2032016-10-29 18:09:35 +020011472
11473 /* Expect one parameter: the new response in base64 encoding */
Willy Tarreau9d008692019-08-09 11:21:01 +020011474 if (!*payload)
11475 return cli_err(appctx, "'set ssl ocsp-response' expects response in base64 encoding.\n");
Aurélien Nephtali1e0867c2018-04-18 14:04:58 +020011476
11477 /* remove \r and \n from the payload */
11478 for (i = 0, j = 0; payload[i]; i++) {
11479 if (payload[i] == '\r' || payload[i] == '\n')
11480 continue;
11481 payload[j++] = payload[i];
11482 }
11483 payload[j] = 0;
William Lallemand32af2032016-10-29 18:09:35 +020011484
Willy Tarreau1c913e42018-08-22 05:26:57 +020011485 ret = base64dec(payload, j, trash.area, trash.size);
Willy Tarreau9d008692019-08-09 11:21:01 +020011486 if (ret < 0)
11487 return cli_err(appctx, "'set ssl ocsp-response' received invalid base64 encoded response.\n");
William Lallemand32af2032016-10-29 18:09:35 +020011488
Willy Tarreau1c913e42018-08-22 05:26:57 +020011489 trash.data = ret;
William Lallemand32af2032016-10-29 18:09:35 +020011490 if (ssl_sock_update_ocsp_response(&trash, &err)) {
Willy Tarreau9d008692019-08-09 11:21:01 +020011491 if (err)
11492 return cli_dynerr(appctx, memprintf(&err, "%s.\n", err));
11493 else
11494 return cli_err(appctx, "Failed to update OCSP response.\n");
William Lallemand32af2032016-10-29 18:09:35 +020011495 }
Willy Tarreau9d008692019-08-09 11:21:01 +020011496
11497 return cli_msg(appctx, LOG_INFO, "OCSP Response updated!\n");
William Lallemand32af2032016-10-29 18:09:35 +020011498#else
Willy Tarreau9d008692019-08-09 11:21:01 +020011499 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 +020011500#endif
11501
Nenad Merdanovicc31499d2019-03-23 11:00:32 +010011502}
11503
Willy Tarreau86a394e2019-05-09 14:15:32 +020011504#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000100fL)
Nenad Merdanovicc31499d2019-03-23 11:00:32 +010011505static inline int sample_conv_var2smp_str(const struct arg *arg, struct sample *smp)
11506{
11507 switch (arg->type) {
11508 case ARGT_STR:
11509 smp->data.type = SMP_T_STR;
11510 smp->data.u.str = arg->data.str;
11511 return 1;
11512 case ARGT_VAR:
11513 if (!vars_get_by_desc(&arg->data.var, smp))
11514 return 0;
11515 if (!sample_casts[smp->data.type][SMP_T_STR])
11516 return 0;
11517 if (!sample_casts[smp->data.type][SMP_T_STR](smp))
11518 return 0;
11519 return 1;
11520 default:
11521 return 0;
11522 }
11523}
11524
11525static int check_aes_gcm(struct arg *args, struct sample_conv *conv,
11526 const char *file, int line, char **err)
11527{
11528 switch(args[0].data.sint) {
11529 case 128:
11530 case 192:
11531 case 256:
11532 break;
11533 default:
11534 memprintf(err, "key size must be 128, 192 or 256 (bits).");
11535 return 0;
11536 }
11537 /* Try to decode a variable. */
11538 vars_check_arg(&args[1], NULL);
11539 vars_check_arg(&args[2], NULL);
11540 vars_check_arg(&args[3], NULL);
11541 return 1;
11542}
11543
11544/* Arguements: AES size in bits, nonce, key, tag. The last three arguments are base64 encoded */
11545static int sample_conv_aes_gcm_dec(const struct arg *arg_p, struct sample *smp, void *private)
11546{
11547 struct sample nonce, key, aead_tag;
11548 struct buffer *smp_trash, *smp_trash_alloc;
11549 EVP_CIPHER_CTX *ctx;
11550 int dec_size, ret;
11551
11552 smp_set_owner(&nonce, smp->px, smp->sess, smp->strm, smp->opt);
11553 if (!sample_conv_var2smp_str(&arg_p[1], &nonce))
11554 return 0;
11555
11556 smp_set_owner(&key, smp->px, smp->sess, smp->strm, smp->opt);
11557 if (!sample_conv_var2smp_str(&arg_p[2], &key))
11558 return 0;
11559
11560 smp_set_owner(&aead_tag, smp->px, smp->sess, smp->strm, smp->opt);
11561 if (!sample_conv_var2smp_str(&arg_p[3], &aead_tag))
11562 return 0;
11563
11564 smp_trash = get_trash_chunk();
11565 smp_trash_alloc = alloc_trash_chunk();
11566 if (!smp_trash_alloc)
11567 return 0;
11568
11569 ctx = EVP_CIPHER_CTX_new();
11570
11571 if (!ctx)
11572 goto err;
11573
11574 dec_size = base64dec(nonce.data.u.str.area, nonce.data.u.str.data, smp_trash->area, smp_trash->size);
11575 if (dec_size < 0)
11576 goto err;
11577 smp_trash->data = dec_size;
11578
11579 /* Set cipher type and mode */
11580 switch(arg_p[0].data.sint) {
11581 case 128:
11582 EVP_DecryptInit_ex(ctx, EVP_aes_128_gcm(), NULL, NULL, NULL);
11583 break;
11584 case 192:
11585 EVP_DecryptInit_ex(ctx, EVP_aes_192_gcm(), NULL, NULL, NULL);
11586 break;
11587 case 256:
11588 EVP_DecryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL);
11589 break;
11590 }
11591
11592 EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, smp_trash->data, NULL);
11593
11594 /* Initialise IV */
11595 if(!EVP_DecryptInit_ex(ctx, NULL, NULL, NULL, (unsigned char *) smp_trash->area))
11596 goto err;
11597
11598 dec_size = base64dec(key.data.u.str.area, key.data.u.str.data, smp_trash->area, smp_trash->size);
11599 if (dec_size < 0)
11600 goto err;
11601 smp_trash->data = dec_size;
11602
11603 /* Initialise key */
11604 if (!EVP_DecryptInit_ex(ctx, NULL, NULL, (unsigned char *) smp_trash->area, NULL))
11605 goto err;
11606
11607 if (!EVP_DecryptUpdate(ctx, (unsigned char *) smp_trash->area, (int *) &smp_trash->data,
11608 (unsigned char *) smp->data.u.str.area, (int) smp->data.u.str.data))
11609 goto err;
11610
11611 dec_size = base64dec(aead_tag.data.u.str.area, aead_tag.data.u.str.data, smp_trash_alloc->area, smp_trash_alloc->size);
11612 if (dec_size < 0)
11613 goto err;
11614 smp_trash_alloc->data = dec_size;
11615 dec_size = smp_trash->data;
11616
11617 EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, smp_trash_alloc->data, (void *) smp_trash_alloc->area);
11618 ret = EVP_DecryptFinal_ex(ctx, (unsigned char *) smp_trash->area + smp_trash->data, (int *) &smp_trash->data);
11619
11620 if (ret <= 0)
11621 goto err;
11622
11623 smp->data.u.str.data = dec_size + smp_trash->data;
11624 smp->data.u.str.area = smp_trash->area;
11625 smp->data.type = SMP_T_BIN;
11626 smp->flags &= ~SMP_F_CONST;
11627 free_trash_chunk(smp_trash_alloc);
11628 return 1;
11629
11630err:
11631 free_trash_chunk(smp_trash_alloc);
11632 return 0;
William Lallemand32af2032016-10-29 18:09:35 +020011633}
Nenad Merdanovicc31499d2019-03-23 11:00:32 +010011634# endif
William Lallemand32af2032016-10-29 18:09:35 +020011635
Elliot Otchet71f82972020-01-15 08:12:14 -050011636/* Argument validation functions */
11637
11638/* This function is used to validate the arguments passed to any "x_dn" ssl
11639 * keywords. These keywords support specifying a third parameter that must be
11640 * either empty or the value "rfc2253". Returns 0 on error, non-zero if OK.
11641 */
11642int val_dnfmt(struct arg *arg, char **err_msg)
11643{
11644 if (arg && arg[2].type == ARGT_STR && arg[2].data.str.data > 0 && (strcmp(arg[2].data.str.area, "rfc2253") != 0)) {
11645 memprintf(err_msg, "only rfc2253 or a blank value are currently supported as the format argument.");
11646 return 0;
11647 }
11648 return 1;
11649}
11650
William Lallemand32af2032016-10-29 18:09:35 +020011651/* register cli keywords */
11652static struct cli_kw_list cli_kws = {{ },{
11653#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
11654 { { "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 +020011655 { { "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 +020011656#endif
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +010011657 { { "set", "ssl", "ocsp-response", NULL }, NULL, cli_parse_set_ocspresponse, NULL },
William Lallemandbc6ca7c2019-10-29 23:48:19 +010011658 { { "set", "ssl", "cert", NULL }, "set ssl cert <certfile> <payload> : replace a certificate file", cli_parse_set_cert, NULL, NULL },
11659 { { "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 +010011660 { { "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 +010011661 { { "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 +020011662 { { NULL }, NULL, NULL, NULL }
11663}};
11664
Willy Tarreau0108d902018-11-25 19:14:37 +010011665INITCALL1(STG_REGISTER, cli_register_kw, &cli_kws);
William Lallemand32af2032016-10-29 18:09:35 +020011666
Willy Tarreau7875d092012-09-10 08:20:03 +020011667/* Note: must not be declared <const> as its list will be overwritten.
11668 * Please take care of keeping this list alphabetically sorted.
11669 */
Willy Tarreaudc13c112013-06-21 23:16:39 +020011670static struct sample_fetch_kw_list sample_fetch_keywords = {ILH, {
Emeric Brun645ae792014-04-30 14:21:06 +020011671 { "ssl_bc", smp_fetch_ssl_fc, 0, NULL, SMP_T_BOOL, SMP_USE_L5SRV },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +020011672 { "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 +010011673#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Jérôme Magnine064a802018-12-03 22:21:04 +010011674 { "ssl_bc_alpn", smp_fetch_ssl_fc_alpn, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
Olivier Houchard6b77f492018-11-22 18:18:29 +010011675#endif
Emeric Brun645ae792014-04-30 14:21:06 +020011676 { "ssl_bc_cipher", smp_fetch_ssl_fc_cipher, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
Olivier Houchard6b77f492018-11-22 18:18:29 +010011677#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
11678 { "ssl_bc_npn", smp_fetch_ssl_fc_npn, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
11679#endif
Emeric Brun74f7ffa2018-02-19 16:14:12 +010011680 { "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 +020011681 { "ssl_bc_protocol", smp_fetch_ssl_fc_protocol, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
Emeric Brunb73a9b02014-04-30 18:49:19 +020011682 { "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 +020011683 { "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 +020011684#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
Emeric Brun645ae792014-04-30 14:21:06 +020011685 { "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 -040011686#endif
Emmanuel Hocdet839af572019-05-14 16:27:35 +020011687#if HA_OPENSSL_VERSION_NUMBER >= 0x10100000L
Patrick Hemmer65674662019-06-04 08:13:03 -040011688 { "ssl_bc_client_random", smp_fetch_ssl_fc_random, 0, NULL, SMP_T_BIN, SMP_USE_L5SRV },
11689 { "ssl_bc_server_random", smp_fetch_ssl_fc_random, 0, NULL, SMP_T_BIN, SMP_USE_L5SRV },
Patrick Hemmere0275472018-04-28 19:15:51 -040011690 { "ssl_bc_session_key", smp_fetch_ssl_fc_session_key, 0, NULL, SMP_T_BIN, SMP_USE_L5SRV },
11691#endif
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +020011692 { "ssl_c_ca_err", smp_fetch_ssl_c_ca_err, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
11693 { "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 +010011694 { "ssl_c_der", smp_fetch_ssl_x_der, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +020011695 { "ssl_c_err", smp_fetch_ssl_c_err, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Elliot Otchet71f82972020-01-15 08:12:14 -050011696 { "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 +020011697 { "ssl_c_key_alg", smp_fetch_ssl_x_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
11698 { "ssl_c_notafter", smp_fetch_ssl_x_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
11699 { "ssl_c_notbefore", smp_fetch_ssl_x_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
11700 { "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 -050011701 { "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 +020011702 { "ssl_c_serial", smp_fetch_ssl_x_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
11703 { "ssl_c_sha1", smp_fetch_ssl_x_sha1, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +010011704 { "ssl_c_used", smp_fetch_ssl_c_used, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +020011705 { "ssl_c_verify", smp_fetch_ssl_c_verify, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
11706 { "ssl_c_version", smp_fetch_ssl_x_version, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Emeric Brun43e79582014-10-29 19:03:26 +010011707 { "ssl_f_der", smp_fetch_ssl_x_der, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Elliot Otchet71f82972020-01-15 08:12:14 -050011708 { "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 +020011709 { "ssl_f_key_alg", smp_fetch_ssl_x_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
11710 { "ssl_f_notafter", smp_fetch_ssl_x_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
11711 { "ssl_f_notbefore", smp_fetch_ssl_x_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
11712 { "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 -050011713 { "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 +020011714 { "ssl_f_serial", smp_fetch_ssl_x_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Emeric Brun55f4fa82014-04-30 17:11:25 +020011715 { "ssl_f_sha1", smp_fetch_ssl_x_sha1, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +020011716 { "ssl_f_version", smp_fetch_ssl_x_version, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +010011717 { "ssl_fc", smp_fetch_ssl_fc, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +020011718 { "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 +010011719 { "ssl_fc_cipher", smp_fetch_ssl_fc_cipher, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +010011720 { "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 +020011721 { "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 +010011722 { "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 +020011723 { "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 +010011724#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +010011725 { "ssl_fc_npn", smp_fetch_ssl_fc_npn, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreaua33c6542012-10-15 13:19:06 +020011726#endif
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +010011727#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +010011728 { "ssl_fc_alpn", smp_fetch_ssl_fc_alpn, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreauab861d32013-04-02 02:30:41 +020011729#endif
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +010011730 { "ssl_fc_protocol", smp_fetch_ssl_fc_protocol, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreau9a1ab082019-05-09 13:26:41 +020011731#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
Emeric Brunb73a9b02014-04-30 18:49:19 +020011732 { "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 -040011733#endif
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +020011734 { "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 +020011735#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +010011736 { "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 -040011737#endif
Emmanuel Hocdet839af572019-05-14 16:27:35 +020011738#if HA_OPENSSL_VERSION_NUMBER >= 0x10100000L
Patrick Hemmer65674662019-06-04 08:13:03 -040011739 { "ssl_fc_client_random", smp_fetch_ssl_fc_random, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
11740 { "ssl_fc_server_random", smp_fetch_ssl_fc_random, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Patrick Hemmere0275472018-04-28 19:15:51 -040011741 { "ssl_fc_session_key", smp_fetch_ssl_fc_session_key, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
11742#endif
Patrick Hemmer41966772018-04-28 19:15:48 -040011743#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +010011744 { "ssl_fc_sni", smp_fetch_ssl_fc_sni, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Patrick Hemmer41966772018-04-28 19:15:48 -040011745#endif
Thierry FOURNIER5bf77322017-02-25 12:45:22 +010011746 { "ssl_fc_cipherlist_bin", smp_fetch_ssl_fc_cl_bin, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
11747 { "ssl_fc_cipherlist_hex", smp_fetch_ssl_fc_cl_hex, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
11748 { "ssl_fc_cipherlist_str", smp_fetch_ssl_fc_cl_str, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
11749 { "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 +020011750 { NULL, NULL, 0, 0, 0 },
11751}};
11752
Willy Tarreau0108d902018-11-25 19:14:37 +010011753INITCALL1(STG_REGISTER, sample_register_fetches, &sample_fetch_keywords);
11754
Willy Tarreau7875d092012-09-10 08:20:03 +020011755/* Note: must not be declared <const> as its list will be overwritten.
11756 * Please take care of keeping this list alphabetically sorted.
11757 */
Willy Tarreaudc13c112013-06-21 23:16:39 +020011758static struct acl_kw_list acl_kws = {ILH, {
Thierry FOURNIERc5a4e982014-03-05 16:07:08 +010011759 { "ssl_fc_sni_end", "ssl_fc_sni", PAT_MATCH_END },
11760 { "ssl_fc_sni_reg", "ssl_fc_sni", PAT_MATCH_REG },
Willy Tarreau8ed669b2013-01-11 15:49:37 +010011761 { /* END */ },
Willy Tarreau7875d092012-09-10 08:20:03 +020011762}};
11763
Willy Tarreau0108d902018-11-25 19:14:37 +010011764INITCALL1(STG_REGISTER, acl_register_keywords, &acl_kws);
11765
Willy Tarreau79eeafa2012-09-14 07:53:05 +020011766/* Note: must not be declared <const> as its list will be overwritten.
11767 * Please take care of keeping this list alphabetically sorted, doing so helps
11768 * all code contributors.
11769 * Optional keywords are also declared with a NULL ->parse() function so that
11770 * the config parser can report an appropriate error when a known keyword was
11771 * not enabled.
11772 */
Emmanuel Hocdet98263292016-12-29 18:26:15 +010011773static struct ssl_bind_kw ssl_bind_kws[] = {
Olivier Houchardc2aae742017-09-22 18:26:28 +020011774 { "allow-0rtt", ssl_bind_parse_allow_0rtt, 0 }, /* allow 0-RTT */
Emmanuel Hocdet98263292016-12-29 18:26:15 +010011775 { "alpn", ssl_bind_parse_alpn, 1 }, /* set ALPN supported protocols */
Emmanuel Hocdet842e94e2019-12-16 16:39:17 +010011776 { "ca-file", ssl_bind_parse_ca_file, 1 }, /* set CAfile to process ca-names and verify on client cert */
11777 { "ca-verify-file", ssl_bind_parse_ca_verify_file, 1 }, /* set CAverify file to process verify on client cert */
Emmanuel Hocdet98263292016-12-29 18:26:15 +010011778 { "ciphers", ssl_bind_parse_ciphers, 1 }, /* set SSL cipher suite */
Emmanuel Hocdet839af572019-05-14 16:27:35 +020011779#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +020011780 { "ciphersuites", ssl_bind_parse_ciphersuites, 1 }, /* set TLS 1.3 cipher suite */
11781#endif
Emmanuel Hocdet98263292016-12-29 18:26:15 +010011782 { "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 +010011783 { "curves", ssl_bind_parse_curves, 1 }, /* set SSL curve suite */
Emmanuel Hocdet98263292016-12-29 18:26:15 +010011784 { "ecdhe", ssl_bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +020011785 { "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 +010011786 { "npn", ssl_bind_parse_npn, 1 }, /* set NPN supported protocols */
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +020011787 { "ssl-min-ver", ssl_bind_parse_tls_method_minmax,1 }, /* minimum version */
11788 { "ssl-max-ver", ssl_bind_parse_tls_method_minmax,1 }, /* maximum version */
Emmanuel Hocdet98263292016-12-29 18:26:15 +010011789 { "verify", ssl_bind_parse_verify, 1 }, /* set SSL verify method */
11790 { NULL, NULL, 0 },
11791};
11792
Willy Tarreau0108d902018-11-25 19:14:37 +010011793/* no initcall for ssl_bind_kws, these ones are parsed in the parser loop */
11794
Willy Tarreau51fb7652012-09-18 18:24:39 +020011795static struct bind_kw_list bind_kws = { "SSL", { }, {
Olivier Houchardc2aae742017-09-22 18:26:28 +020011796 { "allow-0rtt", bind_parse_allow_0rtt, 0 }, /* Allow 0RTT */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +020011797 { "alpn", bind_parse_alpn, 1 }, /* set ALPN supported protocols */
Emmanuel Hocdet842e94e2019-12-16 16:39:17 +010011798 { "ca-file", bind_parse_ca_file, 1 }, /* set CAfile to process ca-names and verify on client cert */
11799 { "ca-verify-file", bind_parse_ca_verify_file, 1 }, /* set CAverify file to process verify on client cert */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +020011800 { "ca-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ignore on verify depth > 0 */
11801 { "ca-sign-file", bind_parse_ca_sign_file, 1 }, /* set CAFile used to generate and sign server certs */
11802 { "ca-sign-pass", bind_parse_ca_sign_pass, 1 }, /* set CAKey passphrase */
11803 { "ciphers", bind_parse_ciphers, 1 }, /* set SSL cipher suite */
Emmanuel Hocdet839af572019-05-14 16:27:35 +020011804#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +020011805 { "ciphersuites", bind_parse_ciphersuites, 1 }, /* set TLS 1.3 cipher suite */
11806#endif
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +020011807 { "crl-file", bind_parse_crl_file, 1 }, /* set certificat revocation list file use on client cert verify */
11808 { "crt", bind_parse_crt, 1 }, /* load SSL certificates from this location */
11809 { "crt-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ingore on verify depth == 0 */
11810 { "crt-list", bind_parse_crt_list, 1 }, /* load a list of crt from this location */
11811 { "curves", bind_parse_curves, 1 }, /* set SSL curve suite */
11812 { "ecdhe", bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
11813 { "force-sslv3", bind_parse_tls_method_options, 0 }, /* force SSLv3 */
11814 { "force-tlsv10", bind_parse_tls_method_options, 0 }, /* force TLSv10 */
11815 { "force-tlsv11", bind_parse_tls_method_options, 0 }, /* force TLSv11 */
11816 { "force-tlsv12", bind_parse_tls_method_options, 0 }, /* force TLSv12 */
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +020011817 { "force-tlsv13", bind_parse_tls_method_options, 0 }, /* force TLSv13 */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +020011818 { "generate-certificates", bind_parse_generate_certs, 0 }, /* enable the server certificates generation */
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +020011819 { "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 +020011820 { "no-sslv3", bind_parse_tls_method_options, 0 }, /* disable SSLv3 */
11821 { "no-tlsv10", bind_parse_tls_method_options, 0 }, /* disable TLSv10 */
11822 { "no-tlsv11", bind_parse_tls_method_options, 0 }, /* disable TLSv11 */
11823 { "no-tlsv12", bind_parse_tls_method_options, 0 }, /* disable TLSv12 */
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +020011824 { "no-tlsv13", bind_parse_tls_method_options, 0 }, /* disable TLSv13 */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +020011825 { "no-tls-tickets", bind_parse_no_tls_tickets, 0 }, /* disable session resumption tickets */
11826 { "ssl", bind_parse_ssl, 0 }, /* enable SSL processing */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +020011827 { "ssl-min-ver", bind_parse_tls_method_minmax, 1 }, /* minimum version */
11828 { "ssl-max-ver", bind_parse_tls_method_minmax, 1 }, /* maximum version */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +020011829 { "strict-sni", bind_parse_strict_sni, 0 }, /* refuse negotiation if sni doesn't match a certificate */
11830 { "tls-ticket-keys", bind_parse_tls_ticket_keys, 1 }, /* set file to load TLS ticket keys from */
11831 { "verify", bind_parse_verify, 1 }, /* set SSL verify method */
11832 { "npn", bind_parse_npn, 1 }, /* set NPN supported protocols */
11833 { "prefer-client-ciphers", bind_parse_pcc, 0 }, /* prefer client ciphers */
Willy Tarreau79eeafa2012-09-14 07:53:05 +020011834 { NULL, NULL, 0 },
11835}};
Emeric Brun46591952012-05-18 15:47:34 +020011836
Willy Tarreau0108d902018-11-25 19:14:37 +010011837INITCALL1(STG_REGISTER, bind_register_keywords, &bind_kws);
11838
Willy Tarreau92faadf2012-10-10 23:04:25 +020011839/* Note: must not be declared <const> as its list will be overwritten.
11840 * Please take care of keeping this list alphabetically sorted, doing so helps
11841 * all code contributors.
11842 * Optional keywords are also declared with a NULL ->parse() function so that
11843 * the config parser can report an appropriate error when a known keyword was
11844 * not enabled.
11845 */
11846static struct srv_kw_list srv_kws = { "SSL", { }, {
Olivier Houchard522eea72017-11-03 16:27:47 +010011847 { "allow-0rtt", srv_parse_allow_0rtt, 0, 1 }, /* Allow using early data on this server */
Olivier Houchardc7566002018-11-20 23:33:50 +010011848 { "alpn", srv_parse_alpn, 1, 1 }, /* Set ALPN supported protocols */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +020011849 { "ca-file", srv_parse_ca_file, 1, 1 }, /* set CAfile to process verify server cert */
Olivier Houchard92150142018-12-21 19:47:01 +010011850 { "check-alpn", srv_parse_alpn, 1, 1 }, /* Set ALPN used for checks */
Olivier Houchard9130a962017-10-17 17:33:43 +020011851 { "check-sni", srv_parse_check_sni, 1, 1 }, /* set SNI */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +020011852 { "check-ssl", srv_parse_check_ssl, 0, 1 }, /* enable SSL for health checks */
11853 { "ciphers", srv_parse_ciphers, 1, 1 }, /* select the cipher suite */
Emmanuel Hocdet839af572019-05-14 16:27:35 +020011854#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +020011855 { "ciphersuites", srv_parse_ciphersuites, 1, 1 }, /* select the cipher suite */
11856#endif
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +020011857 { "crl-file", srv_parse_crl_file, 1, 1 }, /* set certificate revocation list file use on server cert verify */
11858 { "crt", srv_parse_crt, 1, 1 }, /* set client certificate */
11859 { "force-sslv3", srv_parse_tls_method_options, 0, 1 }, /* force SSLv3 */
11860 { "force-tlsv10", srv_parse_tls_method_options, 0, 1 }, /* force TLSv10 */
11861 { "force-tlsv11", srv_parse_tls_method_options, 0, 1 }, /* force TLSv11 */
11862 { "force-tlsv12", srv_parse_tls_method_options, 0, 1 }, /* force TLSv12 */
11863 { "force-tlsv13", srv_parse_tls_method_options, 0, 1 }, /* force TLSv13 */
11864 { "no-check-ssl", srv_parse_no_check_ssl, 0, 1 }, /* disable SSL for health checks */
11865 { "no-send-proxy-v2-ssl", srv_parse_no_send_proxy_ssl, 0, 1 }, /* do not send PROXY protocol header v2 with SSL info */
11866 { "no-send-proxy-v2-ssl-cn", srv_parse_no_send_proxy_cn, 0, 1 }, /* do not send PROXY protocol header v2 with CN */
11867 { "no-ssl", srv_parse_no_ssl, 0, 1 }, /* disable SSL processing */
11868 { "no-ssl-reuse", srv_parse_no_ssl_reuse, 0, 1 }, /* disable session reuse */
11869 { "no-sslv3", srv_parse_tls_method_options, 0, 0 }, /* disable SSLv3 */
11870 { "no-tlsv10", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv10 */
11871 { "no-tlsv11", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv11 */
11872 { "no-tlsv12", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv12 */
11873 { "no-tlsv13", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv13 */
11874 { "no-tls-tickets", srv_parse_no_tls_tickets, 0, 1 }, /* disable session resumption tickets */
Olivier Houchardc7566002018-11-20 23:33:50 +010011875 { "npn", srv_parse_npn, 1, 1 }, /* Set NPN supported protocols */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +020011876 { "send-proxy-v2-ssl", srv_parse_send_proxy_ssl, 0, 1 }, /* send PROXY protocol header v2 with SSL info */
11877 { "send-proxy-v2-ssl-cn", srv_parse_send_proxy_cn, 0, 1 }, /* send PROXY protocol header v2 with CN */
11878 { "sni", srv_parse_sni, 1, 1 }, /* send SNI extension */
11879 { "ssl", srv_parse_ssl, 0, 1 }, /* enable SSL processing */
11880 { "ssl-min-ver", srv_parse_tls_method_minmax, 1, 1 }, /* minimum version */
11881 { "ssl-max-ver", srv_parse_tls_method_minmax, 1, 1 }, /* maximum version */
11882 { "ssl-reuse", srv_parse_ssl_reuse, 0, 1 }, /* enable session reuse */
11883 { "tls-tickets", srv_parse_tls_tickets, 0, 1 }, /* enable session resumption tickets */
11884 { "verify", srv_parse_verify, 1, 1 }, /* set SSL verify method */
11885 { "verifyhost", srv_parse_verifyhost, 1, 1 }, /* require that SSL cert verifies for hostname */
Willy Tarreau92faadf2012-10-10 23:04:25 +020011886 { NULL, NULL, 0, 0 },
11887}};
11888
Willy Tarreau0108d902018-11-25 19:14:37 +010011889INITCALL1(STG_REGISTER, srv_register_keywords, &srv_kws);
11890
Emeric Brun2c86cbf2014-10-30 15:56:50 +010011891static struct cfg_kw_list cfg_kws = {ILH, {
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +010011892 { CFG_GLOBAL, "ca-base", ssl_parse_global_ca_crt_base },
11893 { CFG_GLOBAL, "crt-base", ssl_parse_global_ca_crt_base },
Emmanuel Hocdet70df7bf2019-01-04 11:08:20 +010011894 { CFG_GLOBAL, "issuers-chain-path", ssl_load_global_issuers_from_path },
Willy Tarreau0bea58d2016-12-21 23:17:25 +010011895 { CFG_GLOBAL, "maxsslconn", ssl_parse_global_int },
Emeric Brun2c86cbf2014-10-30 15:56:50 +010011896 { CFG_GLOBAL, "ssl-default-bind-options", ssl_parse_default_bind_options },
11897 { CFG_GLOBAL, "ssl-default-server-options", ssl_parse_default_server_options },
Willy Tarreau14e36a12016-12-21 23:28:13 +010011898#ifndef OPENSSL_NO_DH
11899 { CFG_GLOBAL, "ssl-dh-param-file", ssl_parse_global_dh_param_file },
11900#endif
Grant Zhangfa6c7ee2017-01-14 01:42:15 +000011901 { CFG_GLOBAL, "ssl-mode-async", ssl_parse_global_ssl_async },
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020011902#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +000011903 { CFG_GLOBAL, "ssl-engine", ssl_parse_global_ssl_engine },
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020011904#endif
Willy Tarreau9ceda382016-12-21 23:13:03 +010011905 { CFG_GLOBAL, "tune.ssl.cachesize", ssl_parse_global_int },
11906#ifndef OPENSSL_NO_DH
11907 { CFG_GLOBAL, "tune.ssl.default-dh-param", ssl_parse_global_default_dh },
11908#endif
11909 { CFG_GLOBAL, "tune.ssl.force-private-cache", ssl_parse_global_private_cache },
11910 { CFG_GLOBAL, "tune.ssl.lifetime", ssl_parse_global_lifetime },
11911 { CFG_GLOBAL, "tune.ssl.maxrecord", ssl_parse_global_int },
11912 { CFG_GLOBAL, "tune.ssl.ssl-ctx-cache-size", ssl_parse_global_int },
Thierry FOURNIER5bf77322017-02-25 12:45:22 +010011913 { CFG_GLOBAL, "tune.ssl.capture-cipherlist-size", ssl_parse_global_capture_cipherlist },
Willy Tarreauf22e9682016-12-21 23:23:19 +010011914 { CFG_GLOBAL, "ssl-default-bind-ciphers", ssl_parse_global_ciphers },
11915 { CFG_GLOBAL, "ssl-default-server-ciphers", ssl_parse_global_ciphers },
Emmanuel Hocdet839af572019-05-14 16:27:35 +020011916#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +020011917 { CFG_GLOBAL, "ssl-default-bind-ciphersuites", ssl_parse_global_ciphersuites },
11918 { CFG_GLOBAL, "ssl-default-server-ciphersuites", ssl_parse_global_ciphersuites },
11919#endif
William Lallemand3af48e72020-02-03 17:15:52 +010011920 { CFG_GLOBAL, "ssl-load-extra-files", ssl_parse_global_extra_files },
Emeric Brun2c86cbf2014-10-30 15:56:50 +010011921 { 0, NULL, NULL },
11922}};
11923
Willy Tarreau0108d902018-11-25 19:14:37 +010011924INITCALL1(STG_REGISTER, cfg_register_keywords, &cfg_kws);
11925
Nenad Merdanovicc31499d2019-03-23 11:00:32 +010011926/* Note: must not be declared <const> as its list will be overwritten */
11927static struct sample_conv_kw_list conv_kws = {ILH, {
Willy Tarreau86a394e2019-05-09 14:15:32 +020011928#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000100fL)
Nenad Merdanovicc31499d2019-03-23 11:00:32 +010011929 { "aes_gcm_dec", sample_conv_aes_gcm_dec, ARG4(4,SINT,STR,STR,STR), check_aes_gcm, SMP_T_BIN, SMP_T_BIN },
11930#endif
11931 { NULL, NULL, 0, 0, 0 },
11932}};
11933
11934INITCALL1(STG_REGISTER, sample_register_convs, &conv_kws);
11935
Willy Tarreauf7bc57c2012-10-03 00:19:48 +020011936/* transport-layer operations for SSL sockets */
Willy Tarreaud9f5cca2016-12-22 21:08:52 +010011937static struct xprt_ops ssl_sock = {
Emeric Brun46591952012-05-18 15:47:34 +020011938 .snd_buf = ssl_sock_from_buf,
11939 .rcv_buf = ssl_sock_to_buf,
Olivier Houcharddf357842019-03-21 16:30:07 +010011940 .subscribe = ssl_subscribe,
11941 .unsubscribe = ssl_unsubscribe,
Olivier Houchard5149b592019-05-23 17:47:36 +020011942 .remove_xprt = ssl_remove_xprt,
Olivier Houchard2e055482019-05-27 19:50:12 +020011943 .add_xprt = ssl_add_xprt,
Emeric Brun46591952012-05-18 15:47:34 +020011944 .rcv_pipe = NULL,
11945 .snd_pipe = NULL,
11946 .shutr = NULL,
11947 .shutw = ssl_sock_shutw,
11948 .close = ssl_sock_close,
11949 .init = ssl_sock_init,
Willy Tarreau55d37912016-12-21 23:38:39 +010011950 .prepare_bind_conf = ssl_sock_prepare_bind_conf,
Willy Tarreau795cdab2016-12-22 17:30:54 +010011951 .destroy_bind_conf = ssl_sock_destroy_bind_conf,
Willy Tarreau17d45382016-12-22 21:16:08 +010011952 .prepare_srv = ssl_sock_prepare_srv_ctx,
11953 .destroy_srv = ssl_sock_free_srv_ctx,
Willy Tarreau8743f7e2016-12-04 18:44:29 +010011954 .get_alpn = ssl_sock_get_alpn,
Willy Tarreau8e0bb0a2016-11-24 16:58:12 +010011955 .name = "SSL",
Emeric Brun46591952012-05-18 15:47:34 +020011956};
11957
Olivier Houchardccaa7de2017-10-02 11:51:03 +020011958enum act_return ssl_action_wait_for_hs(struct act_rule *rule, struct proxy *px,
11959 struct session *sess, struct stream *s, int flags)
11960{
11961 struct connection *conn;
Olivier Houchard6fa63d92017-11-27 18:41:32 +010011962 struct conn_stream *cs;
Olivier Houchardccaa7de2017-10-02 11:51:03 +020011963
11964 conn = objt_conn(sess->origin);
Olivier Houchard6fa63d92017-11-27 18:41:32 +010011965 cs = objt_cs(s->si[0].end);
Olivier Houchardccaa7de2017-10-02 11:51:03 +020011966
Olivier Houchard6fa63d92017-11-27 18:41:32 +010011967 if (conn && cs) {
Olivier Houchardccaa7de2017-10-02 11:51:03 +020011968 if (conn->flags & (CO_FL_EARLY_SSL_HS | CO_FL_SSL_WAIT_HS)) {
Olivier Houchard6fa63d92017-11-27 18:41:32 +010011969 cs->flags |= CS_FL_WAIT_FOR_HS;
Olivier Houchardccaa7de2017-10-02 11:51:03 +020011970 s->req.flags |= CF_READ_NULL;
11971 return ACT_RET_YIELD;
11972 }
11973 }
11974 return (ACT_RET_CONT);
11975}
11976
11977static enum act_parse_ret ssl_parse_wait_for_hs(const char **args, int *orig_arg, struct proxy *px, struct act_rule *rule, char **err)
11978{
11979 rule->action_ptr = ssl_action_wait_for_hs;
11980
11981 return ACT_RET_PRS_OK;
11982}
11983
11984static struct action_kw_list http_req_actions = {ILH, {
11985 { "wait-for-handshake", ssl_parse_wait_for_hs },
11986 { /* END */ }
11987}};
11988
Willy Tarreau0108d902018-11-25 19:14:37 +010011989INITCALL1(STG_REGISTER, http_req_keywords_register, &http_req_actions);
11990
Willy Tarreau5db847a2019-05-09 14:13:35 +020011991#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +010011992
11993static void ssl_sock_sctl_free_func(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, long argl, void *argp)
11994{
11995 if (ptr) {
11996 chunk_destroy(ptr);
11997 free(ptr);
11998 }
11999}
12000
12001#endif
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +010012002static void ssl_sock_capture_free_func(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, long argl, void *argp)
12003{
Willy Tarreaubafbe012017-11-24 17:34:44 +010012004 pool_free(pool_head_ssl_capture, ptr);
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +010012005}
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +010012006
Emeric Brun46591952012-05-18 15:47:34 +020012007__attribute__((constructor))
Willy Tarreau92faadf2012-10-10 23:04:25 +020012008static void __ssl_sock_init(void)
12009{
Ilya Shipitsin0590f442019-05-25 19:30:50 +050012010#if (!defined(OPENSSL_NO_COMP) && !defined(SSL_OP_NO_COMPRESSION))
Emeric Brun46591952012-05-18 15:47:34 +020012011 STACK_OF(SSL_COMP)* cm;
Ilya Shipitsine242f3d2019-05-25 03:38:14 +050012012 int n;
Ilya Shipitsin0590f442019-05-25 19:30:50 +050012013#endif
Emeric Brun46591952012-05-18 15:47:34 +020012014
Willy Tarreauef934602016-12-22 23:12:01 +010012015 if (global_ssl.listen_default_ciphers)
12016 global_ssl.listen_default_ciphers = strdup(global_ssl.listen_default_ciphers);
12017 if (global_ssl.connect_default_ciphers)
12018 global_ssl.connect_default_ciphers = strdup(global_ssl.connect_default_ciphers);
Emmanuel Hocdet839af572019-05-14 16:27:35 +020012019#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +020012020 if (global_ssl.listen_default_ciphersuites)
12021 global_ssl.listen_default_ciphersuites = strdup(global_ssl.listen_default_ciphersuites);
12022 if (global_ssl.connect_default_ciphersuites)
12023 global_ssl.connect_default_ciphersuites = strdup(global_ssl.connect_default_ciphersuites);
12024#endif
Willy Tarreau610f04b2014-02-13 11:36:41 +010012025
Willy Tarreau13e14102016-12-22 20:25:26 +010012026 xprt_register(XPRT_SSL, &ssl_sock);
Willy Tarreau9a1ab082019-05-09 13:26:41 +020012027#if HA_OPENSSL_VERSION_NUMBER < 0x10100000L
Emeric Brun46591952012-05-18 15:47:34 +020012028 SSL_library_init();
Rosen Penev68185952018-12-14 08:47:02 -080012029#endif
Ilya Shipitsin0590f442019-05-25 19:30:50 +050012030#if (!defined(OPENSSL_NO_COMP) && !defined(SSL_OP_NO_COMPRESSION))
Emeric Brun46591952012-05-18 15:47:34 +020012031 cm = SSL_COMP_get_compression_methods();
Ilya Shipitsine242f3d2019-05-25 03:38:14 +050012032 n = sk_SSL_COMP_num(cm);
12033 while (n--) {
12034 (void) sk_SSL_COMP_pop(cm);
12035 }
Ilya Shipitsin0590f442019-05-25 19:30:50 +050012036#endif
Ilya Shipitsine242f3d2019-05-25 03:38:14 +050012037
Willy Tarreau5db847a2019-05-09 14:13:35 +020012038#if defined(USE_THREAD) && (HA_OPENSSL_VERSION_NUMBER < 0x10100000L)
Emeric Brun821bb9b2017-06-15 16:37:39 +020012039 ssl_locking_init();
12040#endif
Willy Tarreau5db847a2019-05-09 14:13:35 +020012041#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +010012042 sctl_ex_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, ssl_sock_sctl_free_func);
12043#endif
Thierry FOURNIER28962c92018-06-17 21:37:05 +020012044 ssl_app_data_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL);
Thierry FOURNIER16ff0502018-06-17 21:33:01 +020012045 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 +020012046#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +000012047 ENGINE_load_builtin_engines();
Grant Zhangfa6c7ee2017-01-14 01:42:15 +000012048 hap_register_post_check(ssl_check_async_engine_count);
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020012049#endif
Willy Tarreaud1c57502016-12-22 22:46:15 +010012050#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
12051 hap_register_post_check(tlskeys_finalize_config);
12052#endif
Willy Tarreau80713382018-11-26 10:19:54 +010012053
12054 global.ssl_session_max_cost = SSL_SESSION_MAX_COST;
12055 global.ssl_handshake_max_cost = SSL_HANDSHAKE_MAX_COST;
12056
Emmanuel Hocdet70df7bf2019-01-04 11:08:20 +010012057 hap_register_post_deinit(ssl_free_global_issuers);
12058
Willy Tarreau80713382018-11-26 10:19:54 +010012059#ifndef OPENSSL_NO_DH
12060 ssl_dh_ptr_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, NULL);
12061 hap_register_post_deinit(ssl_free_dh);
12062#endif
12063#ifndef OPENSSL_NO_ENGINE
12064 hap_register_post_deinit(ssl_free_engines);
12065#endif
12066 /* Load SSL string for the verbose & debug mode. */
12067 ERR_load_SSL_strings();
Olivier Houcharda8955d52019-04-07 22:00:38 +020012068 ha_meth = BIO_meth_new(0x666, "ha methods");
12069 BIO_meth_set_write(ha_meth, ha_ssl_write);
12070 BIO_meth_set_read(ha_meth, ha_ssl_read);
12071 BIO_meth_set_ctrl(ha_meth, ha_ssl_ctrl);
12072 BIO_meth_set_create(ha_meth, ha_ssl_new);
12073 BIO_meth_set_destroy(ha_meth, ha_ssl_free);
12074 BIO_meth_set_puts(ha_meth, ha_ssl_puts);
12075 BIO_meth_set_gets(ha_meth, ha_ssl_gets);
William Lallemand150bfa82019-09-19 17:12:49 +020012076
12077 HA_SPIN_INIT(&ckch_lock);
Willy Tarreau80713382018-11-26 10:19:54 +010012078}
Willy Tarreaud92aa5c2015-01-15 21:34:39 +010012079
Willy Tarreau80713382018-11-26 10:19:54 +010012080/* Compute and register the version string */
12081static void ssl_register_build_options()
12082{
12083 char *ptr = NULL;
12084 int i;
12085
Willy Tarreauc2c0b612016-12-21 19:23:20 +010012086 memprintf(&ptr, "Built with OpenSSL version : "
12087#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet50e25e12017-03-24 15:20:03 +010012088 "BoringSSL");
Willy Tarreauc2c0b612016-12-21 19:23:20 +010012089#else /* OPENSSL_IS_BORINGSSL */
12090 OPENSSL_VERSION_TEXT
12091 "\nRunning on OpenSSL version : %s%s",
Rosen Penev68185952018-12-14 08:47:02 -080012092 OpenSSL_version(OPENSSL_VERSION),
Willy Tarreau1d158ab2019-05-09 13:41:45 +020012093 ((OPENSSL_VERSION_NUMBER ^ OpenSSL_version_num()) >> 8) ? " (VERSIONS DIFFER!)" : "");
Willy Tarreauc2c0b612016-12-21 19:23:20 +010012094#endif
12095 memprintf(&ptr, "%s\nOpenSSL library supports TLS extensions : "
Willy Tarreau9a1ab082019-05-09 13:26:41 +020012096#if HA_OPENSSL_VERSION_NUMBER < 0x00907000L
Willy Tarreauc2c0b612016-12-21 19:23:20 +010012097 "no (library version too old)"
12098#elif defined(OPENSSL_NO_TLSEXT)
12099 "no (disabled via OPENSSL_NO_TLSEXT)"
12100#else
12101 "yes"
12102#endif
12103 "", ptr);
12104
12105 memprintf(&ptr, "%s\nOpenSSL library supports SNI : "
12106#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
12107 "yes"
12108#else
12109#ifdef OPENSSL_NO_TLSEXT
12110 "no (because of OPENSSL_NO_TLSEXT)"
12111#else
12112 "no (version might be too old, 0.9.8f min needed)"
12113#endif
12114#endif
12115 "", ptr);
12116
Emmanuel Hocdetf80bc242017-07-12 14:25:38 +020012117 memprintf(&ptr, "%s\nOpenSSL library supports :", ptr);
12118 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
12119 if (methodVersions[i].option)
12120 memprintf(&ptr, "%s %s", ptr, methodVersions[i].name);
Emmanuel Hocdet50e25e12017-03-24 15:20:03 +010012121
Willy Tarreauc2c0b612016-12-21 19:23:20 +010012122 hap_register_build_opts(ptr, 1);
Willy Tarreau80713382018-11-26 10:19:54 +010012123}
Willy Tarreauc2c0b612016-12-21 19:23:20 +010012124
Willy Tarreau80713382018-11-26 10:19:54 +010012125INITCALL0(STG_REGISTER, ssl_register_build_options);
Remi Gacogne4f902b82015-05-28 16:23:00 +020012126
Emeric Brun46591952012-05-18 15:47:34 +020012127
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020012128#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +000012129void ssl_free_engines(void) {
12130 struct ssl_engine_list *wl, *wlb;
12131 /* free up engine list */
12132 list_for_each_entry_safe(wl, wlb, &openssl_engines, list) {
12133 ENGINE_finish(wl->e);
12134 ENGINE_free(wl->e);
12135 LIST_DEL(&wl->list);
12136 free(wl);
12137 }
12138}
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020012139#endif
Christopher Faulet31af49d2015-06-09 17:29:50 +020012140
Remi Gacogned3a23c32015-05-28 16:39:47 +020012141#ifndef OPENSSL_NO_DH
Grant Zhang872f9c22017-01-21 01:10:18 +000012142void ssl_free_dh(void) {
12143 if (local_dh_1024) {
12144 DH_free(local_dh_1024);
12145 local_dh_1024 = NULL;
12146 }
12147 if (local_dh_2048) {
12148 DH_free(local_dh_2048);
12149 local_dh_2048 = NULL;
12150 }
12151 if (local_dh_4096) {
12152 DH_free(local_dh_4096);
12153 local_dh_4096 = NULL;
12154 }
Remi Gacogne47783ef2015-05-29 15:53:22 +020012155 if (global_dh) {
12156 DH_free(global_dh);
12157 global_dh = NULL;
12158 }
Grant Zhang872f9c22017-01-21 01:10:18 +000012159}
12160#endif
12161
12162__attribute__((destructor))
12163static void __ssl_sock_deinit(void)
12164{
12165#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Emeric Brun821bb9b2017-06-15 16:37:39 +020012166 if (ssl_ctx_lru_tree) {
12167 lru64_destroy(ssl_ctx_lru_tree);
Christopher Faulet2a944ee2017-11-07 10:42:54 +010012168 HA_RWLOCK_DESTROY(&ssl_ctx_lru_rwlock);
Emeric Brun821bb9b2017-06-15 16:37:39 +020012169 }
Remi Gacogned3a23c32015-05-28 16:39:47 +020012170#endif
12171
Willy Tarreau5db847a2019-05-09 14:13:35 +020012172#if (HA_OPENSSL_VERSION_NUMBER < 0x10100000L)
Remi Gacogned3a23c32015-05-28 16:39:47 +020012173 ERR_remove_state(0);
12174 ERR_free_strings();
12175
12176 EVP_cleanup();
Rosen Penev68185952018-12-14 08:47:02 -080012177#endif
Remi Gacogned3a23c32015-05-28 16:39:47 +020012178
Willy Tarreau5db847a2019-05-09 14:13:35 +020012179#if (HA_OPENSSL_VERSION_NUMBER >= 0x00907000L) && (HA_OPENSSL_VERSION_NUMBER < 0x10100000L)
Remi Gacogned3a23c32015-05-28 16:39:47 +020012180 CRYPTO_cleanup_all_ex_data();
12181#endif
Olivier Houcharda8955d52019-04-07 22:00:38 +020012182 BIO_meth_free(ha_meth);
Remi Gacogned3a23c32015-05-28 16:39:47 +020012183}
12184
12185
Emeric Brun46591952012-05-18 15:47:34 +020012186/*
12187 * Local variables:
12188 * c-indent-level: 8
12189 * c-basic-offset: 8
12190 * End:
12191 */